feat: add basic blob fetcher tests

pull/9168/head
Kirill Fedoseev 10 months ago
parent a22d4ca336
commit a44be8f218
  1. 2
      apps/explorer/lib/explorer/chain/beacon/reader.ex
  2. 7
      apps/explorer/test/explorer/chain/beacon/reader_test.exs
  3. 8
      apps/explorer/test/support/factory.ex
  4. 3
      apps/indexer/config/runtime/test.exs
  5. 2
      apps/indexer/lib/indexer/fetcher/beacon/client.ex
  6. 11
      apps/indexer/test/indexer/block/catchup/bound_interval_supervisor_test.exs
  7. 16
      apps/indexer/test/indexer/block/catchup/fetcher_test.exs
  8. 9
      apps/indexer/test/indexer/block/fetcher_test.exs
  9. 19
      apps/indexer/test/indexer/block/realtime/fetcher_test.exs
  10. 170
      apps/indexer/test/indexer/fetcher/beacon/blob_test.exs

@ -101,7 +101,7 @@ defmodule Explorer.Chain.Beacon.Reader do
""" """
@spec stream_missed_blob_transactions_timestamps( @spec stream_missed_blob_transactions_timestamps(
initial :: accumulator, initial :: accumulator,
reducer :: (entry :: Hash.Address.t(), accumulator -> accumulator), reducer :: (entry :: DateTime.t(), accumulator -> accumulator),
min_block :: integer() | nil, min_block :: integer() | nil,
max_block :: integer() | nil, max_block :: integer() | nil,
options :: [] options :: []

@ -0,0 +1,7 @@
defmodule Explorer.Chain.Beacon.ReaderTest do
use Explorer.DataCase
alias Explorer.Chain.Beacon.Reader
doctest Reader
end

@ -1099,16 +1099,12 @@ defmodule Explorer.Factory do
end end
def blob_transaction_factory do def blob_transaction_factory do
blob = build(:blob)
transaction = build(:transaction)
%BlobTransaction{ %BlobTransaction{
hash: transaction.hash, hash: insert(:transaction) |> with_block() |> Map.get(:hash),
transaction: transaction,
max_fee_per_blob_gas: Decimal.new(1_000_000_000), max_fee_per_blob_gas: Decimal.new(1_000_000_000),
blob_gas_price: Decimal.new(1_000_000_000), blob_gas_price: Decimal.new(1_000_000_000),
blob_gas_used: Decimal.new(131_072), blob_gas_used: Decimal.new(131_072),
blob_versioned_hashes: [blob.hash] blob_versioned_hashes: []
} }
end end

@ -2,6 +2,9 @@ import Config
alias EthereumJSONRPC.Variant alias EthereumJSONRPC.Variant
config :indexer, Indexer.Fetcher.Beacon.Blob.Supervisor, disabled?: true
config :indexer, Indexer.Fetcher.Beacon.Blob, start_block: 0
variant = Variant.get() variant = Variant.get()
Code.require_file("#{variant}.exs", "#{__DIR__}/../../../explorer/config/test") Code.require_file("#{variant}.exs", "#{__DIR__}/../../../explorer/config/test")

@ -8,7 +8,7 @@ defmodule Indexer.Fetcher.Beacon.Client do
@request_error_msg "Error while sending request to beacon rpc" @request_error_msg "Error while sending request to beacon rpc"
def http_get_request(url) do def http_get_request(url) do
case HTTPoison.get(url) do case Application.get_env(:explorer, :http_adapter).get(url) do
{:ok, %Response{body: body, status_code: 200}} -> {:ok, %Response{body: body, status_code: 200}} ->
Jason.decode(body) Jason.decode(body)

@ -11,7 +11,6 @@ defmodule Indexer.Block.Catchup.BoundIntervalSupervisorTest do
alias Indexer.BoundInterval alias Indexer.BoundInterval
alias Indexer.Block.Catchup alias Indexer.Block.Catchup
alias Indexer.Block.Catchup.MissingRangesCollector alias Indexer.Block.Catchup.MissingRangesCollector
alias Indexer.Fetcher.Beacon.Blob
alias Indexer.Fetcher.{ alias Indexer.Fetcher.{
CoinBalance, CoinBalance,
@ -33,14 +32,8 @@ defmodule Indexer.Block.Catchup.BoundIntervalSupervisorTest do
describe "start_link/1" do describe "start_link/1" do
setup do setup do
initial_block_ranges = Application.get_env(:indexer, :block_ranges) initial_env = Application.get_env(:indexer, :block_ranges)
initial_blob_disabled = Application.get_env(:indexer, Blob.Supervisor)[:disabled?] on_exit(fn -> Application.put_env(:indexer, :block_ranges, initial_env) end)
Application.put_env(:indexer, Blob.Supervisor, disabled?: true)
on_exit(fn ->
Application.put_env(:indexer, :block_ranges, initial_block_ranges)
Application.put_env(:indexer, Blob.Supervisor, disabled?: initial_blob_disabled)
end)
end end
# See https://github.com/poanetwork/blockscout/issues/597 # See https://github.com/poanetwork/blockscout/issues/597

@ -13,7 +13,6 @@ defmodule Indexer.Block.Catchup.FetcherTest do
alias Indexer.Block alias Indexer.Block
alias Indexer.Block.Catchup.Fetcher alias Indexer.Block.Catchup.Fetcher
alias Indexer.Block.Catchup.MissingRangesCollector alias Indexer.Block.Catchup.MissingRangesCollector
alias Indexer.Fetcher.Beacon.Blob
alias Indexer.Fetcher.{BlockReward, CoinBalance, InternalTransaction, Token, TokenBalance, UncleBlock} alias Indexer.Fetcher.{BlockReward, CoinBalance, InternalTransaction, Token, TokenBalance, UncleBlock}
@moduletag capture_log: true @moduletag capture_log: true
@ -38,14 +37,11 @@ defmodule Indexer.Block.Catchup.FetcherTest do
describe "import/1" do describe "import/1" do
setup do setup do
initial_last_block = Application.get_env(:indexer, :last_block) configuration = Application.get_env(:indexer, :last_block)
initial_blob_disabled = Application.get_env(:indexer, Blob.Supervisor)[:disabled?]
Application.put_env(:indexer, :last_block, 0) Application.put_env(:indexer, :last_block, 0)
Application.put_env(:indexer, Blob.Supervisor, disabled?: true)
on_exit(fn -> on_exit(fn ->
Application.put_env(:indexer, :last_block, initial_last_block) Application.put_env(:indexer, :last_block, configuration)
Application.put_env(:indexer, Blob.Supervisor, disabled?: initial_blob_disabled)
end) end)
end end
@ -143,13 +139,7 @@ defmodule Indexer.Block.Catchup.FetcherTest do
describe "task/1" do describe "task/1" do
setup do setup do
initial_env = Application.get_env(:indexer, :block_ranges) initial_env = Application.get_env(:indexer, :block_ranges)
initial_blob_disabled = Application.get_env(:indexer, Blob.Supervisor)[:disabled?] on_exit(fn -> Application.put_env(:indexer, :block_ranges, initial_env) end)
Application.put_env(:indexer, Blob.Supervisor, disabled?: true)
on_exit(fn ->
Application.put_env(:indexer, :block_ranges, initial_env)
Application.put_env(:indexer, Blob.Supervisor, disabled?: initial_blob_disabled)
end)
end end
test "ignores fetched beneficiaries with different hash for same number", %{ test "ignores fetched beneficiaries with different hash for same number", %{

@ -11,8 +11,6 @@ defmodule Indexer.Block.FetcherTest do
alias Indexer.Block.Fetcher alias Indexer.Block.Fetcher
alias Indexer.BufferedTask alias Indexer.BufferedTask
alias Indexer.Fetcher.Beacon.Blob
alias Indexer.Fetcher.{ alias Indexer.Fetcher.{
CoinBalance, CoinBalance,
ContractCode, ContractCode,
@ -62,13 +60,6 @@ defmodule Indexer.Block.FetcherTest do
block_fetcher: %Fetcher{json_rpc_named_arguments: json_rpc_named_arguments} block_fetcher: %Fetcher{json_rpc_named_arguments: json_rpc_named_arguments}
) )
initial_blob_disabled = Application.get_env(:indexer, Blob.Supervisor)[:disabled?]
Application.put_env(:indexer, Blob.Supervisor, disabled?: true)
on_exit(fn ->
Application.put_env(:indexer, Blob.Supervisor, disabled?: initial_blob_disabled)
end)
%{ %{
block_fetcher: %Fetcher{ block_fetcher: %Fetcher{
broadcast: false, broadcast: false,

@ -8,7 +8,6 @@ defmodule Indexer.Block.Realtime.FetcherTest do
alias Explorer.Chain.{Address, Transaction, Wei} alias Explorer.Chain.{Address, Transaction, Wei}
alias Indexer.Block.Catchup.Sequence alias Indexer.Block.Catchup.Sequence
alias Indexer.Block.Realtime alias Indexer.Block.Realtime
alias Indexer.Fetcher.Beacon.Blob
alias Indexer.Fetcher.{ContractCode, InternalTransaction, ReplacedTransaction, Token, TokenBalance, UncleBlock} alias Indexer.Fetcher.{ContractCode, InternalTransaction, ReplacedTransaction, Token, TokenBalance, UncleBlock}
@moduletag capture_log: true @moduletag capture_log: true
@ -42,15 +41,6 @@ defmodule Indexer.Block.Realtime.FetcherTest do
end end
describe "Indexer.Block.Fetcher.fetch_and_import_range/1" do describe "Indexer.Block.Fetcher.fetch_and_import_range/1" do
setup do
initial_blob_disabled = Application.get_env(:indexer, Blob.Supervisor)[:disabled?]
Application.put_env(:indexer, Blob.Supervisor, disabled?: true)
on_exit(fn ->
Application.put_env(:indexer, Blob.Supervisor, disabled?: initial_blob_disabled)
end)
end
@tag :no_geth @tag :no_geth
test "in range with internal transactions", %{ test "in range with internal transactions", %{
block_fetcher: %Indexer.Block.Fetcher{} = block_fetcher, block_fetcher: %Indexer.Block.Fetcher{} = block_fetcher,
@ -1067,15 +1057,6 @@ defmodule Indexer.Block.Realtime.FetcherTest do
end end
describe "start_fetch_and_import" do describe "start_fetch_and_import" do
setup do
initial_blob_disabled = Application.get_env(:indexer, Blob.Supervisor)[:disabled?]
Application.put_env(:indexer, Blob.Supervisor, disabled?: true)
on_exit(fn ->
Application.put_env(:indexer, Blob.Supervisor, disabled?: initial_blob_disabled)
end)
end
@tag :no_geth @tag :no_geth
test "reorg", %{ test "reorg", %{
block_fetcher: block_fetcher, block_fetcher: block_fetcher,

@ -0,0 +1,170 @@
defmodule Indexer.Fetcher.Beacon.BlobTest do
use Explorer.DataCase, async: false
import Mox
alias Explorer.Chain.Transaction
alias Explorer.Chain.Beacon.{Blob, Reader}
alias Indexer.Fetcher.Beacon.Blob.Supervisor, as: BlobSupervisor
setup :verify_on_exit!
setup :set_mox_global
if Application.compile_env(:explorer, :chain_type) == "ethereum" do
describe "init/1" do
setup do
initial_env = Application.get_env(:indexer, BlobSupervisor)
Application.put_env(:indexer, BlobSupervisor, initial_env |> Keyword.put(:disabled?, false))
on_exit(fn ->
Application.put_env(:indexer, BlobSupervisor, initial_env)
end)
end
test "fetches all missed blob transactions" do
{:ok, now, _} = DateTime.from_iso8601("2024-01-24 00:00:00Z")
block_a = insert(:block, timestamp: now)
block_b = insert(:block, timestamp: now |> Timex.shift(seconds: -120))
block_c = insert(:block, timestamp: now |> Timex.shift(seconds: -240))
blob_a = build(:blob)
blob_b = build(:blob)
blob_c = build(:blob)
blob_d = insert(:blob)
%Transaction{hash: transaction_a_hash} = insert(:transaction, type: 3) |> with_block(block_a)
%Transaction{hash: transaction_b_hash} = insert(:transaction, type: 3) |> with_block(block_b)
%Transaction{hash: transaction_c_hash} = insert(:transaction, type: 3) |> with_block(block_c)
insert(:blob_transaction, hash: transaction_a_hash, blob_versioned_hashes: [blob_a.hash, blob_b.hash])
insert(:blob_transaction, hash: transaction_b_hash, blob_versioned_hashes: [blob_c.hash])
insert(:blob_transaction, hash: transaction_c_hash, blob_versioned_hashes: [blob_d.hash])
assert {:error, :not_found} = Reader.blob(blob_a.hash)
assert {:error, :not_found} = Reader.blob(blob_b.hash)
assert {:error, :not_found} = Reader.blob(blob_c.hash)
assert {:ok, _} = Reader.blob(blob_d.hash)
Application.put_env(:explorer, :http_adapter, Explorer.Mox.HTTPoison)
result_ab = """
{
"data": [
{
"index": "0",
"blob": "#{to_string(blob_a.blob_data)}",
"kzg_commitment": "#{to_string(blob_a.kzg_commitment)}",
"kzg_proof": "#{to_string(blob_a.kzg_proof)}"
},
{
"index": "1",
"blob": "#{to_string(blob_b.blob_data)}",
"kzg_commitment": "#{to_string(blob_b.kzg_commitment)}",
"kzg_proof": "#{to_string(blob_b.kzg_proof)}"
}
]
}
"""
result_c = """
{
"data": [
{
"index": "0",
"blob": "#{to_string(blob_c.blob_data)}",
"kzg_commitment": "#{to_string(blob_c.kzg_commitment)}",
"kzg_proof": "#{to_string(blob_c.kzg_proof)}"
}
]
}
"""
Explorer.Mox.HTTPoison
|> expect(:get, 2, fn url ->
case url do
"http://localhost:5052/eth/v1/beacon/blob_sidecars/8269188" ->
{:ok, %HTTPoison.Response{status_code: 200, body: result_c}}
"http://localhost:5052/eth/v1/beacon/blob_sidecars/8269198" ->
{:ok, %HTTPoison.Response{status_code: 200, body: result_ab}}
end
end)
BlobSupervisor.Case.start_supervised!()
wait_for_results(fn ->
Repo.one!(from(blob in Blob, where: blob.hash == ^blob_a.hash))
end)
assert {:ok, _} = Reader.blob(blob_a.hash)
assert {:ok, _} = Reader.blob(blob_b.hash)
assert {:ok, _} = Reader.blob(blob_c.hash)
assert {:ok, _} = Reader.blob(blob_d.hash)
Application.put_env(:explorer, :http_adapter, HTTPoison)
end
end
describe "async_fetch/1" do
setup do
initial_env = Application.get_env(:indexer, BlobSupervisor)
Application.put_env(:indexer, BlobSupervisor, initial_env |> Keyword.put(:disabled?, false))
on_exit(fn ->
Application.put_env(:indexer, BlobSupervisor, initial_env)
end)
end
test "fetches blobs for block timestamp" do
Application.put_env(:explorer, :http_adapter, Explorer.Mox.HTTPoison)
{:ok, now, _} = DateTime.from_iso8601("2024-01-24 00:00:00Z")
block_a = insert(:block, timestamp: now)
%Blob{
hash: blob_hash_a,
blob_data: blob_data_a,
kzg_commitment: kzg_commitment_a,
kzg_proof: kzg_proof_a
} = build(:blob)
result_a = """
{
"data": [
{
"index": "0",
"blob": "#{to_string(blob_data_a)}",
"kzg_commitment": "#{to_string(kzg_commitment_a)}",
"kzg_proof": "#{to_string(kzg_proof_a)}"
}
]
}
"""
Explorer.Mox.HTTPoison
|> expect(:get, fn "http://localhost:5052/eth/v1/beacon/blob_sidecars/8269198" ->
{:ok, %HTTPoison.Response{status_code: 200, body: result_a}}
end)
BlobSupervisor.Case.start_supervised!()
assert :ok = Indexer.Fetcher.Beacon.Blob.async_fetch([block_a.timestamp])
wait_for_results(fn ->
Repo.one!(from(blob in Blob, where: blob.hash == ^blob_hash_a))
end)
assert {:ok, blob} = Reader.blob(blob_hash_a)
assert %{
hash: ^blob_hash_a,
blob_data: ^blob_data_a,
kzg_commitment: ^kzg_commitment_a,
kzg_proof: ^kzg_proof_a
} = blob
Application.put_env(:explorer, :http_adapter, HTTPoison)
end
end
end
end
Loading…
Cancel
Save