EEVM.Block.HeaderValidator (eevm v0.1.0)

Copy Markdown View Source

Validates a child EEVM.Block.Header against its parent.

Covers the consensus rules that don't require running the EVM:

  • parent_hash matches the parent header's hash.
  • number is one greater than the parent's number.
  • timestamp is strictly greater than the parent's timestamp.
  • extra_data is at most 32 bytes.
  • gas_limit is at least 5,000, fits in a signed 64-bit integer, and differs from the parent's gas limit by less than parent_gas_limit / 1024.
  • Each fork-dependent field is present exactly when its fork is active: base_fee_per_gas (London), withdrawals_root (Shanghai), blob_gas_used, excess_blob_gas, and parent_beacon_block_root (Cancun), requests_hash (Prague).
  • From London, base_fee_per_gas equals the value derived from the parent's base fee, gas used, and gas target (EIP-1559).
  • From Paris, difficulty is 0, nonce is eight zero bytes, and ommers_hash is EEVM.Block.Header.empty_ommers_hash/0 (EIP-3675).
  • From Cancun, blob_gas_used is a multiple of the per-blob gas and at most EEVM.Gas.Blob.max_blob_gas_per_block/1. excess_blob_gas equals EEVM.Gas.Blob.calc_excess_blob_gas/2 of the parent (EIP-4844, EIP-7691 from Prague, EIP-7918 from Osaka).

Checks run in that order and the first failure wins. The parent is judged under the same fork as the child, so a fork's first block (such as London's, whose expected base fee is the initial 1 gwei) isn't modelled.

Checks against the block body and the execution result (transactions_root, withdrawals_root, gas_used, receipts_root, state_root, ...) live in EEVM.Block.validate/3 and EEVM.Block.execute/4.

Summary

Types

Reason returned when a header fails validation; see EEVM.Error.

Functions

Returns :ok when child is a valid successor of parent, otherwise {:error, reason} for the first rule it breaks. hardfork selects the fork-dependent rules and defaults to EEVM.HardforkConfig.default/0.

Types

error()

Reason returned when a header fails validation; see EEVM.Error.

Functions

validate(child, parent, hardfork \\ HardforkConfig.default())

@spec validate(EEVM.Block.Header.t(), EEVM.Block.Header.t(), EEVM.HardforkConfig.t()) ::
  :ok | {:error, error()}

Returns :ok when child is a valid successor of parent, otherwise {:error, reason} for the first rule it breaks. hardfork selects the fork-dependent rules and defaults to EEVM.HardforkConfig.default/0.

Example

iex> alias EEVM.Block.{Header, HeaderValidator}
iex> shanghai = EEVM.HardforkConfig.new(:shanghai)
iex> parent = Header.new(number: 1, timestamp: 10, gas_limit: 30_000_000, hash: <<1::256>>)
iex> fields = [base_fee_per_gas: 0, withdrawals_root: <<0::256>>]
iex> parent = struct!(parent, fields)
iex> child = Header.new([number: 2, timestamp: 22, gas_limit: 30_000_000, parent_hash: <<1::256>>] ++ fields)
iex> HeaderValidator.validate(child, parent, shanghai)
:ok
iex> HeaderValidator.validate(%{child | timestamp: 10}, parent, shanghai)
{:error, :invalid_timestamp}