# `EEVM.Block.Processor`
[🔗](https://github.com/mw2000/eevm/blob/v0.1.0/lib/eevm/block/processor.ex#L1)

Lower-level block engine with an injectable transaction executor: system
calls, then transactions in order, then beacon-chain withdrawals, then
EIP-7685 requests, then the commitments a consensus-level verifier will
check.

Most callers want `EEVM.Block.execute/4`, which validates the block, runs
each transaction through `EEVM.Handler`, and checks the commitments against
the header. Use this module directly to plug in a custom executor.

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, %EEVM.BlockEnv{}, %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`, plus an optional `:tx_type` (default
  `:legacy`) that selects the EIP-2718 receipt encoding, an optional
  `:state_root` that the receipt carries in place of its status (before
  Byzantium, EIP-658), an optional `:contract_address` that the receipt
  carries for a contract creation, and an optional `:trace` (an
  `EEVM.Tracer`); when any transaction returns one, `result.trace` lists
  them in order.
- `:system_calls` — list of hooks, each `(%Database{}, %EEVM.BlockEnv{})
  -> %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.
- `:rewards` — list of `{address, wei}` balance credits for the block's
  proof-of-work miner and ommer rewards, applied after the transactions.
  Defaults to `[]`.
- `: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 `[]`.
- `:block_context` — the `EEVM.BlockEnv` handed to system calls and
  the executor. Defaults to one derived from the header's fields.
- `:requests` — `(%Database{}, %EEVM.BlockEnv{}, [%Receipt{}]) ->
  {:ok, requests, %Database{}} | {:error, reason}`, run after the
  withdrawals to collect the block's EIP-7685 requests (see
  `EEVM.Block.Requests.collect/5`). Its database is the one the
  `state_root` is computed from. Without it, `result.requests` is `nil`.

# `process_error`

```elixir
@type process_error() :: {:tx_failed, non_neg_integer(), term()} | atom()
```

# `process_opts`

```elixir
@type process_opts() :: [
  tx_executor: tx_executor(),
  system_calls: [system_call()],
  tx_encoder: tx_encoder(),
  rewards: [{non_neg_integer(), non_neg_integer()}],
  withdrawals: [EEVM.Block.Withdrawal.t()],
  block_context: EEVM.BlockEnv.t(),
  requests: requests_hook()
]
```

# `requests_hook`

```elixir
@type requests_hook() :: (EEVM.Database.t(),
                    EEVM.BlockEnv.t(),
                    [EEVM.Block.Receipt.t()] -&gt;
                      {:ok, [binary()], EEVM.Database.t()} | {:error, atom()})
```

# `system_call`

```elixir
@type system_call() :: (EEVM.Database.t(), EEVM.BlockEnv.t() -&gt; EEVM.Database.t())
```

# `tx_encoder`

```elixir
@type tx_encoder() :: (term() -&gt; binary())
```

# `tx_executor`

```elixir
@type tx_executor() :: (term(), EEVM.BlockEnv.t(), EEVM.Database.t() -&gt;
                    {:ok, tx_result()} | {:error, term()})
```

# `tx_result`

```elixir
@type tx_result() :: %{
  :status =&gt; 0 | 1,
  :gas_used =&gt; non_neg_integer(),
  :logs =&gt; [EEVM.Block.Bloom.log_entry()],
  :db =&gt; EEVM.Database.t(),
  optional(:tx_type) =&gt; EEVM.Block.Receipt.tx_type(),
  optional(:state_root) =&gt; binary(),
  optional(:contract_address) =&gt; non_neg_integer() | nil,
  optional(:trace) =&gt; EEVM.Tracer.t() | nil
}
```

# `process_block`

```elixir
@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, {:tx_failed, index, :gas_allowance_exceeded}}` when a
  transaction's `gas_limit` exceeds the gas left in the block
  (`header.gas_limit` minus the gas used so far).
- `{:error, {:tx_failed, index, reason}}` when the injected executor
  rejects a transaction. `index` is 0-based in `transactions` order.
- `{:error, reason}` when the `:requests` hook fails.

---

*Consult [api-reference.md](api-reference.md) for complete listing*
