evm v0.1.4 Block.Header

This structure codifies the header of a block in the blockchain.

Link to this section Summary

Functions

Returns the total available gas left for all transactions in this block. This is the total gas limit minus the gas used in transactions

Deserializes a block header from an RLP encodable structure. This effectively undoes the encoding defined in L_H Eq.(32) of the Yellow Paper

Calculates the difficulty of a new block header. This implements Eq.(39), Eq.(40), Eq.(41), Eq.(42), Eq.(43) and Eq.(44) of the Yellow Paper

Returns the block that defines the start of Homestead

Returns true if a given block is at or after the Homestead block

Returns true if a given block is before the Homestead block

Function to determine if the gas limit set is valid. The miner gets to specify a gas limit, so long as it’s in range. This allows about a 0.1% change per block

Returns true if the block header is valid. This defines Eq.(50), Eq.(51), Eq.(52), Eq.(53), Eq.(54), Eq.(55), Eq.(56), Eq.(57) and Eq.(58) of the Yellow Paper, commonly referred to as V(H)

This functions encode a header into a value that can be RLP encoded. This is defined as L_H Eq.(32) in the Yellow Paper

Link to this section Types

Link to this type t()
t() :: %Block.Header{beneficiary: EVM.address | <<_::0>>, difficulty: integer | nil, extra_data: binary, gas_limit: EVM.val, gas_used: EVM.val, logs_bloom: binary, mix_hash: EVM.hash | nil, nonce: <<_::64>> | nil, number: integer | nil, ommers_hash: EVM.trie_root, parent_hash: EVM.hash | <<_::0>>, receipts_root: EVM.trie_root, state_root: EVM.trie_root, timestamp: EVM.timestamp | nil, transactions_root: EVM.trie_root}

Link to this section Functions

Link to this function available_gas(header)
available_gas(t) :: EVM.Gas.t

Returns the total available gas left for all transactions in this block. This is the total gas limit minus the gas used in transactions.

Examples

iex> Block.Header.available_gas(%Block.Header{gas_limit: 50_000, gas_used: 30_000})
20_000
Link to this function deserialize(rlp)
deserialize(ExRLP.t) :: t

Deserializes a block header from an RLP encodable structure. This effectively undoes the encoding defined in L_H Eq.(32) of the Yellow Paper.

Examples

iex> Block.Header.deserialize([<<1::256>>, <<2::256>>, <<3::160>>, <<4::256>>, <<5::256>>, <<6::256>>, <<>>, <<5>>, <<1>>, <<5>>, <<3>>, <<6>>, "Hi mom", <<7::256>>, <<8::64>>])
%Block.Header{parent_hash: <<1::256>>, ommers_hash: <<2::256>>, beneficiary: <<3::160>>, state_root: <<4::256>>, transactions_root: <<5::256>>, receipts_root: <<6::256>>, logs_bloom: <<>>, difficulty: 5, number: 1, gas_limit: 5, gas_used: 3, timestamp: 6, extra_data: "Hi mom", mix_hash: <<7::256>>, nonce: <<8::64>>}
Link to this function get_difficulty(header, parent_header)
get_difficulty(t, t | nil) :: integer

Calculates the difficulty of a new block header. This implements Eq.(39), Eq.(40), Eq.(41), Eq.(42), Eq.(43) and Eq.(44) of the Yellow Paper.

TODO: Validate these results

Examples

iex> Block.Header.get_difficulty(
...>   %Block.Header{number: 0, timestamp: 55},
...>   nil
...> )
131_072

iex> Block.Header.get_difficulty(
...>   %Block.Header{number: 1, timestamp: 1479642530},
...>   %Block.Header{number: 0, timestamp: 0, difficulty: 1_048_576}
...> )
1_048_064

iex> Block.Header.get_difficulty(
...>  %Block.Header{number: 33, timestamp: 66},
...>  %Block.Header{number: 32, timestamp: 55, difficulty: 300_000}
...> )
300_146

iex> Block.Header.get_difficulty(
...>  %Block.Header{number: 33, timestamp: 88},
...>  %Block.Header{number: 32, timestamp: 55, difficulty: 300_000}
...> )
299_854

# TODO: Is this right? These numbers are quite a jump
iex> Block.Header.get_difficulty(
...>  %Block.Header{number: 3_000_001, timestamp: 66},
...>  %Block.Header{number: 3_000_000, timestamp: 55, difficulty: 300_000}
...> )
268_735_456

iex> Block.Header.get_difficulty(
...>  %Block.Header{number: 3_000_001, timestamp: 155},
...>  %Block.Header{number: 3_000_000, timestamp: 55, difficulty: 300_000}
...> )
268_734_142
Link to this function homestead()
homestead() :: integer

Returns the block that defines the start of Homestead

Link to this function is_after_homestead?(h)
is_after_homestead?(t) :: boolean

Returns true if a given block is at or after the Homestead block.

Examples

iex> Block.Header.is_after_homestead?(%Block.Header{number: 5})
false

iex> Block.Header.is_after_homestead?(%Block.Header{number: 5_000_000})
true

iex> Block.Header.is_after_homestead?(%Block.Header{number: 1_150_000})
true
Link to this function is_before_homestead?(h)
is_before_homestead?(t) :: boolean

Returns true if a given block is before the Homestead block.

Examples

iex> Block.Header.is_before_homestead?(%Block.Header{number: 5})
true

iex> Block.Header.is_before_homestead?(%Block.Header{number: 5_000_000})
false

iex> Block.Header.is_before_homestead?(%Block.Header{number: 1_150_000})
false
Link to this function is_gas_limit_valid?(gas_limit, parent_gas_limit)
is_gas_limit_valid?(EVM.Gas.t, EVM.Gas.t | nil) :: boolean

Function to determine if the gas limit set is valid. The miner gets to specify a gas limit, so long as it’s in range. This allows about a 0.1% change per block.

This function directly implements Eq.(45), Eq.(46) and Eq.(47).

Examples

iex> Block.Header.is_gas_limit_valid?(1_000_000, nil)
true

iex> Block.Header.is_gas_limit_valid?(1_000, nil)
false

iex> Block.Header.is_gas_limit_valid?(1_000_000, 1_000_000)
true

iex> Block.Header.is_gas_limit_valid?(1_000_000, 2_000_000)
false

iex> Block.Header.is_gas_limit_valid?(1_000_000, 500_000)
false

iex> Block.Header.is_gas_limit_valid?(1_000_000, 999_500)
true

iex> Block.Header.is_gas_limit_valid?(1_000_000, 999_000)
false
Link to this function is_valid?(header, parent_header, enforce_difficulty \\ false)
is_valid?(t, t | nil, boolean) :: :valid | {:invalid, [atom]}

Returns true if the block header is valid. This defines Eq.(50), Eq.(51), Eq.(52), Eq.(53), Eq.(54), Eq.(55), Eq.(56), Eq.(57) and Eq.(58) of the Yellow Paper, commonly referred to as V(H).

TODO: Implement and add examples

TODO: Add proof of work check

Examples

iex> Block.Header.is_valid?(%Block.Header{number: 0, difficulty: 131_072, gas_limit: 200_000}, nil)
:valid

iex> Block.Header.is_valid?(%Block.Header{number: 0, difficulty: 5, gas_limit: 5}, nil, true)
{:invalid, [:invalid_difficulty, :invalid_gas_limit]}

iex> Block.Header.is_valid?(%Block.Header{number: 1, difficulty: 131_136, gas_limit: 200_000, timestamp: 65}, %Block.Header{number: 0, difficulty: 131_072, gas_limit: 200_000, timestamp: 55})
:valid

iex> Block.Header.is_valid?(%Block.Header{number: 1, difficulty: 131_000, gas_limit: 200_000, timestamp: 65}, %Block.Header{number: 0, difficulty: 131_072, gas_limit: 200_000, timestamp: 55})
:valid

iex> Block.Header.is_valid?(%Block.Header{number: 1, difficulty: 131_000, gas_limit: 200_000, timestamp: 65}, %Block.Header{number: 0, difficulty: 131_072, gas_limit: 200_000, timestamp: 55}, true)
{:invalid, [:invalid_difficulty]}

iex> Block.Header.is_valid?(%Block.Header{number: 1, difficulty: 131_136, gas_limit: 200_000, timestamp: 45}, %Block.Header{number: 0, difficulty: 131_072, gas_limit: 200_000, timestamp: 55})
{:invalid, [:child_timestamp_invalid]}

iex> Block.Header.is_valid?(%Block.Header{number: 1, difficulty: 131_136, gas_limit: 300_000, timestamp: 65}, %Block.Header{number: 0, difficulty: 131_072, gas_limit: 200_000, timestamp: 55})
{:invalid, [:invalid_gas_limit]}

iex> Block.Header.is_valid?(%Block.Header{number: 2, difficulty: 131_136, gas_limit: 200_000, timestamp: 65}, %Block.Header{number: 0, difficulty: 131_072, gas_limit: 200_000, timestamp: 55})
{:invalid, [:child_number_invalid]}

iex> Block.Header.is_valid?(%Block.Header{number: 1, difficulty: 131_136, gas_limit: 200_000, timestamp: 65, extra_data: "0123456789012345678901234567890123456789"}, %Block.Header{number: 0, difficulty: 131_072, gas_limit: 200_000, timestamp: 55})
{:invalid, [:extra_data_too_large]}
Link to this function serialize(h)
serialize(t) :: ExRLP.t

This functions encode a header into a value that can be RLP encoded. This is defined as L_H Eq.(32) in the Yellow Paper.

Examples

iex> Block.Header.serialize(%Block.Header{parent_hash: <<1::256>>, ommers_hash: <<2::256>>, beneficiary: <<3::160>>, state_root: <<4::256>>, transactions_root: <<5::256>>, receipts_root: <<6::256>>, logs_bloom: <<>>, difficulty: 5, number: 1, gas_limit: 5, gas_used: 3, timestamp: 6, extra_data: "Hi mom", mix_hash: <<7::256>>, nonce: <<8::64>>})
[<<1::256>>, <<2::256>>, <<3::160>>, <<4::256>>, <<5::256>>, <<6::256>>, <<>>, 5, 1, 5, 3, 6, "Hi mom", <<7::256>>, <<8::64>>]