Add Explorer.Chain.Zkevm.Reader module

pull/7584/head
POA 1 year ago
parent a82c8bd2a3
commit 54fb9a3f20
  1. 3
      apps/block_scout_web/lib/block_scout_web/controllers/api/v2/transaction_controller.ex
  2. 9
      apps/block_scout_web/lib/block_scout_web/controllers/api/v2/zkevm_controller.ex
  3. 30
      apps/explorer/lib/explorer/chain.ex
  4. 122
      apps/explorer/lib/explorer/chain/zkevm/reader.ex
  5. 54
      apps/indexer/lib/indexer/fetcher/zkevm/transaction_batch.ex

@ -19,6 +19,7 @@ defmodule BlockScoutWeb.API.V2.TransactionController do
alias BlockScoutWeb.AccessHelper alias BlockScoutWeb.AccessHelper
alias BlockScoutWeb.Models.TransactionStateHelper alias BlockScoutWeb.Models.TransactionStateHelper
alias Explorer.Chain alias Explorer.Chain
alias Explorer.Chain.Zkevm.Reader
alias Indexer.Fetcher.FirstTraceOnDemand alias Indexer.Fetcher.FirstTraceOnDemand
action_fallback(BlockScoutWeb.API.V2.FallbackController) action_fallback(BlockScoutWeb.API.V2.FallbackController)
@ -114,7 +115,7 @@ defmodule BlockScoutWeb.API.V2.TransactionController do
def zkevm_batch(conn, %{"batch_number" => batch_number} = _params) do def zkevm_batch(conn, %{"batch_number" => batch_number} = _params) do
transactions = transactions =
batch_number batch_number
|> Chain.zkevm_batch_transactions(api?: true) |> Reader.batch_transactions(api?: true)
|> Enum.map(fn tx -> tx.hash end) |> Enum.map(fn tx -> tx.hash end)
|> Chain.hashes_to_transactions(api?: true, necessity_by_association: @transaction_necessity_by_association) |> Chain.hashes_to_transactions(api?: true, necessity_by_association: @transaction_necessity_by_association)

@ -9,6 +9,7 @@ defmodule BlockScoutWeb.API.V2.ZkevmController do
] ]
alias Explorer.Chain alias Explorer.Chain
alias Explorer.Chain.Zkevm.Reader
action_fallback(BlockScoutWeb.API.V2.FallbackController) action_fallback(BlockScoutWeb.API.V2.FallbackController)
@ -24,7 +25,7 @@ defmodule BlockScoutWeb.API.V2.ZkevmController do
def batch(conn, %{"batch_number" => batch_number} = _params) do def batch(conn, %{"batch_number" => batch_number} = _params) do
{:ok, batch} = {:ok, batch} =
Chain.zkevm_batch( Reader.batch(
batch_number, batch_number,
necessity_by_association: @batch_necessity_by_association, necessity_by_association: @batch_necessity_by_association,
api?: true api?: true
@ -47,7 +48,7 @@ defmodule BlockScoutWeb.API.V2.ZkevmController do
|> paging_options() |> paging_options()
|> Keyword.put(:necessity_by_association, @batches_necessity_by_association) |> Keyword.put(:necessity_by_association, @batches_necessity_by_association)
|> Keyword.put(:api?, true) |> Keyword.put(:api?, true)
|> Chain.zkevm_batches() |> Reader.batches()
|> split_list_by_page() |> split_list_by_page()
next_page_params = next_page_params(next_page, batches, params) next_page_params = next_page_params(next_page, batches, params)
@ -72,7 +73,7 @@ defmodule BlockScoutWeb.API.V2.ZkevmController do
|> Keyword.put(:necessity_by_association, @batches_necessity_by_association) |> Keyword.put(:necessity_by_association, @batches_necessity_by_association)
|> Keyword.put(:api?, true) |> Keyword.put(:api?, true)
|> Keyword.put(:confirmed?, true) |> Keyword.put(:confirmed?, true)
|> Chain.zkevm_batches() |> Reader.batches()
conn conn
|> put_status(200) |> put_status(200)
@ -80,7 +81,7 @@ defmodule BlockScoutWeb.API.V2.ZkevmController do
end end
defp batch_latest_number do defp batch_latest_number do
case Chain.zkevm_batch(:latest, api?: true) do case Reader.batch(:latest, api?: true) do
{:ok, batch} -> batch.number {:ok, batch} -> batch.number
{:error, :not_found} -> 0 {:error, :not_found} -> 0
end end

@ -67,8 +67,6 @@ defmodule Explorer.Chain do
Withdrawal Withdrawal
} }
alias Explorer.Chain.Zkevm.{BatchTransaction, TransactionBatch}
alias Explorer.Chain.Block.{EmissionReward, Reward} alias Explorer.Chain.Block.{EmissionReward, Reward}
alias Explorer.Chain.Cache.{ alias Explorer.Chain.Cache.{
@ -4118,7 +4116,7 @@ defmodule Explorer.Chain do
end end
end end
defp join_associations(query, necessity_by_association) when is_map(necessity_by_association) do def join_associations(query, necessity_by_association) when is_map(necessity_by_association) do
Enum.reduce(necessity_by_association, query, fn {association, join}, acc_query -> Enum.reduce(necessity_by_association, query, fn {association, join}, acc_query ->
join_association(acc_query, association, join) join_association(acc_query, association, join)
end) end)
@ -6393,32 +6391,6 @@ defmodule Explorer.Chain do
) )
end end
def zkevm_batch(number, options \\ [])
def zkevm_batch(:latest, options) when is_list(options) do
TransactionBatch
|> order_by(desc: :number)
|> limit(1)
|> select_repo(options).one()
|> case do
nil -> {:error, :not_found}
batch -> {:ok, batch}
end
end
def zkevm_batch(number, options) when is_list(options) do
necessity_by_association = Keyword.get(options, :necessity_by_association, %{})
TransactionBatch
|> where(number: ^number)
|> join_associations(necessity_by_association)
|> select_repo(options).one()
|> case do
nil -> {:error, :not_found}
batch -> {:ok, batch}
end
end
@spec verified_contracts_top(non_neg_integer()) :: [Hash.Address.t()] @spec verified_contracts_top(non_neg_integer()) :: [Hash.Address.t()]
def verified_contracts_top(limit) do def verified_contracts_top(limit) do
query = query =

@ -0,0 +1,122 @@
defmodule Explorer.Chain.Zkevm.Reader do
@moduledoc "Contains read functions for zkevm modules."
import Ecto.Query,
only: [
from: 2,
limit: 2,
order_by: 2,
where: 2,
where: 3
]
import Explorer.Chain, only: [select_repo: 1]
alias Explorer.Chain.Zkevm.{BatchTransaction, LifecycleTransaction, TransactionBatch}
alias Explorer.{Chain, PagingOptions, Repo}
def batch(number, options \\ [])
def batch(:latest, options) when is_list(options) do
TransactionBatch
|> order_by(desc: :number)
|> limit(1)
|> select_repo(options).one()
|> case do
nil -> {:error, :not_found}
batch -> {:ok, batch}
end
end
def batch(number, options) when is_list(options) do
necessity_by_association = Keyword.get(options, :necessity_by_association, %{})
TransactionBatch
|> where(number: ^number)
|> Chain.join_associations(necessity_by_association)
|> select_repo(options).one()
|> case do
nil -> {:error, :not_found}
batch -> {:ok, batch}
end
end
def batches(options \\ []) do
necessity_by_association = Keyword.get(options, :necessity_by_association, %{})
base_query =
from(tb in TransactionBatch,
order_by: [desc: tb.number]
)
query =
if Keyword.get(options, :confirmed?, false) do
base_query
|> Chain.join_associations(necessity_by_association)
|> where([tb], not is_nil(tb.sequence_id) and tb.sequence_id > 0)
|> limit(10)
else
paging_options = Keyword.get(options, :paging_options, Chain.default_paging_options())
base_query
|> Chain.join_associations(necessity_by_association)
|> page_batches(paging_options)
|> limit(^paging_options.page_size)
end
select_repo(options).all(query)
end
def batch_transactions(batch_number, options \\ []) do
query = from(bts in BatchTransaction, where: bts.batch_number == ^batch_number)
select_repo(options).all(query)
end
def last_verified_batch_number do
query =
from(tb in TransactionBatch,
select: tb.number,
where: not is_nil(tb.verify_id),
order_by: [desc: tb.number],
limit: 1
)
query
|> Repo.one()
|> Kernel.||(0)
end
def lifecycle_transactions(l1_tx_hashes) do
query =
from(
lt in LifecycleTransaction,
select: {lt.hash, lt.id},
where: lt.hash in ^l1_tx_hashes
)
Repo.all(query, timeout: :infinity)
end
def next_id do
query =
from(lt in LifecycleTransaction,
select: lt.id,
order_by: [desc: lt.id],
limit: 1
)
last_id =
query
|> Repo.one()
|> Kernel.||(0)
last_id + 1
end
defp page_batches(query, %PagingOptions{key: nil}), do: query
defp page_batches(query, %PagingOptions{key: {number}}) do
from(tb in query, where: tb.number < ^number)
end
end

@ -8,12 +8,10 @@ defmodule Indexer.Fetcher.Zkevm.TransactionBatch do
require Logger require Logger
import Ecto.Query
import EthereumJSONRPC, only: [integer_to_quantity: 1, json_rpc: 2, quantity_to_integer: 1] import EthereumJSONRPC, only: [integer_to_quantity: 1, json_rpc: 2, quantity_to_integer: 1]
alias Explorer.{Chain, Repo} alias Explorer.Chain
alias Explorer.Chain.Zkevm.{LifecycleTransaction, TransactionBatch} alias Explorer.Chain.Zkevm.Reader
@zero_hash "0000000000000000000000000000000000000000000000000000000000000000" @zero_hash "0000000000000000000000000000000000000000000000000000000000000000"
@ -71,7 +69,7 @@ defmodule Indexer.Fetcher.Zkevm.TransactionBatch do
{new_state, handle_duration} = {new_state, handle_duration} =
if latest_batch_number > prev_latest_batch_number or virtual_batch_number > prev_virtual_batch_number or if latest_batch_number > prev_latest_batch_number or virtual_batch_number > prev_virtual_batch_number or
verified_batch_number > prev_verified_batch_number do verified_batch_number > prev_verified_batch_number do
start_batch_number = get_last_verified_batch_number() + 1 start_batch_number = Reader.last_verified_batch_number() + 1
end_batch_number = latest_batch_number end_batch_number = latest_batch_number
log_message = log_message =
@ -111,36 +109,6 @@ defmodule Indexer.Fetcher.Zkevm.TransactionBatch do
{:noreply, state} {:noreply, state}
end end
defp get_last_verified_batch_number do
query =
from(tb in TransactionBatch,
select: tb.number,
where: not is_nil(tb.verify_id),
order_by: [desc: tb.number],
limit: 1
)
query
|> Repo.one()
|> Kernel.||(0)
end
defp get_next_id do
query =
from(lt in LifecycleTransaction,
select: lt.id,
order_by: [desc: lt.id],
limit: 1
)
last_id =
query
|> Repo.one()
|> Kernel.||(0)
last_id + 1
end
defp handle_batch_range(start_batch_number, end_batch_number, json_rpc_named_arguments, chunk_size) do defp handle_batch_range(start_batch_number, end_batch_number, json_rpc_named_arguments, chunk_size) do
start_batch_number..end_batch_number start_batch_number..end_batch_number
|> Enum.chunk_every(chunk_size) |> Enum.chunk_every(chunk_size)
@ -226,24 +194,18 @@ defmodule Indexer.Fetcher.Zkevm.TransactionBatch do
l1_tx_hashes = Enum.uniq(sequence_hashes ++ verify_hashes) l1_tx_hashes = Enum.uniq(sequence_hashes ++ verify_hashes)
query =
from(
lt in LifecycleTransaction,
select: {lt.hash, lt.id},
where: lt.hash in ^l1_tx_hashes
)
hash_to_id = hash_to_id =
query l1_tx_hashes
|> Repo.all(timeout: :infinity) |> Reader.lifecycle_transactions()
|> Enum.reduce(%{}, fn {hash, id}, acc -> |> Enum.reduce(%{}, fn {hash, id}, acc ->
Map.put(acc, hash.bytes, id) Map.put(acc, hash.bytes, id)
end) end)
{batches_to_import, l2_txs_to_import, l1_txs_to_import, _, _} = {batches_to_import, l2_txs_to_import, l1_txs_to_import, _, _} =
responses responses
|> Enum.reduce({[], [], [], get_next_id(), hash_to_id}, fn res, |> Enum.reduce({[], [], [], Reader.next_id(), hash_to_id}, fn res,
{batches, l2_txs, l1_txs, next_id, hash_to_id} = _acc -> {batches, l2_txs, l1_txs, next_id, hash_to_id} =
_acc ->
number = quantity_to_integer(Map.get(res.result, "number")) number = quantity_to_integer(Map.get(res.result, "number"))
{:ok, timestamp} = DateTime.from_unix(quantity_to_integer(Map.get(res.result, "timestamp"))) {:ok, timestamp} = DateTime.from_unix(quantity_to_integer(Map.get(res.result, "timestamp")))
l2_transaction_hashes = Map.get(res.result, "transactions") l2_transaction_hashes = Map.get(res.result, "transactions")

Loading…
Cancel
Save