EEVM.Block.Processor (eevm v0.1.0)

Copy Markdown View Source

Execute a block end-to-end: system calls, then transactions in order, then beacon-chain withdrawals, then the commitments a consensus-level verifier will check.

If any transaction fails (the injected executor returns an {:error, _}) the processor halts and reports the failing index. The post-state database is left at whatever the last successful transaction produced — this processor does not attempt optimistic rollback.

Options

Callers inject the executor and any per-block hooks:

  • :tx_executor — (tx, %Context.Block{}, %Database{}) -> {:ok, tx_result} | {:error, reason}. Each call receives the current database after all prior transactions and system calls have been applied. The returned tx_result is a map with keys :status, :gas_used, :logs, and :db.
  • :system_calls — list of hooks, each (%Database{}, %Context.Block{}) -> %Database{}. Executed in order, strictly before any transaction. The default is [].
  • :tx_encoder — (tx) -> binary used to compute the transactions_root. Defaults to EEVM.Transaction.Envelope.encode/1, which handles every typed envelope this codebase knows about. Tests using plain maps supply their own.
  • :withdrawals — list of EEVM.Block.Withdrawal structs (EIP-4895). Applied as flat balance credits after the transaction fold and before the state root is computed, so the returned state_root already reflects them. Defaults to [].
  • :hardfork — optional atom, purely informational today; the real executor will consume it once wired in.

Summary

Functions

Execute every phase of the block and produce a %EEVM.Block.Result{}.

Types

process_error()

@type process_error() ::
  :block_gas_limit_exceeded | {:tx_failed, non_neg_integer(), term()}

process_opts()

@type process_opts() :: [
  tx_executor: tx_executor(),
  system_calls: [system_call()],
  tx_encoder: tx_encoder(),
  withdrawals: [EEVM.Block.Withdrawal.t()],
  hardfork: atom() | nil
]

system_call()

@type system_call() :: (EEVM.Database.t(), EEVM.Context.Block.t() ->
                    EEVM.Database.t())

tx_encoder()

@type tx_encoder() :: (term() -> binary())

tx_executor()

@type tx_executor() :: (term(), EEVM.Context.Block.t(), EEVM.Database.t() ->
                    {:ok, tx_result()} | {:error, term()})

tx_result()

@type tx_result() :: %{
  status: 0 | 1,
  gas_used: non_neg_integer(),
  logs: [EEVM.Block.Bloom.log_entry()],
  db: EEVM.Database.t()
}

Functions

process_block(header, transactions, pre_state_db, opts)

@spec process_block(
  EEVM.Block.Header.t(),
  [term()],
  EEVM.Database.t(),
  process_opts()
) ::
  {:ok, EEVM.Block.Result.t()} | {:error, process_error()}

Execute every phase of the block and produce a %EEVM.Block.Result{}.

The caller owns pre_state_db and must pass an injected :tx_executor. See the module doc for the full option list.

Returns:

  • {:ok, %Result{}} on success.
  • {:error, :block_gas_limit_exceeded} when sum(tx.gas_limit) exceeds header.gas_limit.
  • {:error, {:tx_failed, index, reason}} when the injected executor rejects a transaction. index is 0-based in transactions order.