evm v0.1.14 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

Computes hash of a block header, which is simply the hash of the serialized block header

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, 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, 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, initial_difficulty \\ 131072, minimum_difficulty \\ 131072, difficulty_bound_divisor \\ 2048, homestead_block \\ 1150000)

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.

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

Test actual Ropsten genesis block
iex> Block.Header.get_difficulty(
...>   %Block.Header{number: 0, timestamp: 0},
...>   nil,
...>   0x100000,
...>   0x020000,
...>   0x0800,
...>   0
...> )
1_048_576

# Test actual Ropsten first block
iex> Block.Header.get_difficulty(
...>   %Block.Header{number: 1, timestamp: 1_479_642_530},
...>   %Block.Header{number: 0, timestamp: 0, difficulty: 1_048_576},
...>   0x100000,
...>   0x020000,
...>   0x0800,
...>   0
...> )
997_888
Link to this function hash(header)
hash(t) :: EVM.hash

Computes hash of a block header, which is simply the hash of the serialized block header.

This is defined in Eq.(37) of the Yellow Paper.

Examples

iex> %Block.Header{number: 5, parent_hash: <<1, 2, 3>>, beneficiary: <<2, 3, 4>>, difficulty: 100, timestamp: 11, mix_hash: <<1>>, nonce: <<2>>}
...> |> Block.Header.hash()
<<78, 28, 127, 10, 192, 253, 127, 239, 254, 179, 39, 34, 245, 44, 152, 98, 128, 71, 238, 155, 100, 161, 199, 71, 243, 223, 172, 191, 74, 99, 128, 63>>

iex> %Block.Header{number: 0, parent_hash: <<1, 2, 3>>, beneficiary: <<2, 3, 4>>, difficulty: 100, timestamp: 11, mix_hash: <<1>>, nonce: <<2>>}
...> |> Block.Header.hash()
<<218, 225, 46, 241, 196, 160, 136, 96, 109, 216, 73, 167, 92, 174, 91, 228, 85, 112, 234, 129, 99, 200, 158, 61, 223, 166, 165, 132, 187, 24, 142, 193>>
Link to this function homestead(homestead_block \\ 1150000)
homestead(integer) :: integer

Returns the block that defines the start of Homestead.

This should be a constant, but it’s configurable on different chains, and as such, as allow you to pass that configuration variable (which ends up making this the identity function, if so).

Link to this function is_after_homestead?(h, homestead_block \\ 1150000)
is_after_homestead?(t, integer) :: 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

iex> Block.Header.is_after_homestead?(%Block.Header{number: 5}, 6)
false
Link to this function is_before_homestead?(h, homestead_block \\ 1150000)
is_before_homestead?(t, integer) :: 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

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

iex> Block.Header.is_before_homestead?(%Block.Header{number: 5}, 4)
false
Link to this function is_gas_limit_valid?(gas_limit, parent_gas_limit, gas_limit_bound_divisor \\ 1024, min_gas_limit \\ 125000)

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

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

iex> Block.Header.is_gas_limit_valid?(1_000, nil, 1024, 500)
true
Link to this function is_valid?(header, parent_header, homestead_block \\ 1150000, initial_difficulty \\ 131072, minimum_difficulty \\ 131072, difficulty_bound_divisor \\ 2048, gas_limit_bound_divisor \\ 1024, min_gas_limit \\ 125000)
is_valid?(t, t | nil, integer, integer, integer, integer, integer, integer) ::
  :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: 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}, 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]}

# TODO: Add tests for setting homestead_block
# TODO: Add tests for setting initial_difficulty
# TODO: Add tests for setting minimum_difficulty
# TODO: Add tests for setting difficulty_bound_divisor
# TODO: Add tests for setting gas_limit_bound_divisor
# TODO: Add tests for setting min_gas_limit
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>>]