ethereum.genesis

Genesis Configuration ^^^^^^^^^^^^^^^^^^^^^

.. contents:: Table of Contents :backlinks: none :local:

Introduction

Functionalities and entities to obtain the genesis configurations for different chains.

  1"""
  2Genesis Configuration
  3^^^^^^^^^^^^^^^^^^^^^
  4
  5.. contents:: Table of Contents
  6    :backlinks: none
  7    :local:
  8
  9Introduction
 10------------
 11
 12Functionalities and entities to obtain the genesis configurations for
 13different chains.
 14"""
 15import json
 16import pkgutil
 17from dataclasses import dataclass
 18from typing import Any, Dict, cast
 19
 20from ethereum import rlp
 21from ethereum.base_types import (
 22    U64,
 23    U256,
 24    Bytes,
 25    Bytes8,
 26    Bytes20,
 27    Uint,
 28    slotted_freezable,
 29)
 30from ethereum.utils.hexadecimal import (
 31    hex_to_bytes,
 32    hex_to_bytes8,
 33    hex_to_bytes32,
 34    hex_to_u256,
 35    hex_to_uint,
 36)
 37
 38Address = Bytes20
 39
 40
 41@slotted_freezable
 42@dataclass
 43class GenesisConfiguration:
 44    """
 45    Configuration for the first block of an Ethereum chain.
 46
 47    Specifies the allocation of ether set out in the pre-sale, and some of
 48    the fields of the genesis block.
 49    """
 50
 51    chain_id: U64
 52    difficulty: Uint
 53    extra_data: Bytes
 54    gas_limit: Uint
 55    nonce: Bytes8
 56    timestamp: U256
 57    initial_accounts: Dict[str, Dict]
 58
 59
 60def get_genesis_configuration(genesis_file: str) -> GenesisConfiguration:
 61    """
 62    Obtain the genesis configuration from the given genesis json file.
 63
 64    The genesis file should be present in the `assets` directory.
 65
 66    Parameters
 67    ----------
 68    genesis_file :
 69        The json file which contains the parameters for the genesis block
 70        and the pre-sale allocation data.
 71
 72    Returns
 73    -------
 74    configuration : `GenesisConfiguration`
 75        The genesis configuration obtained from the json genesis file.
 76    """
 77    genesis_str_data = cast(
 78        bytes, pkgutil.get_data("ethereum", f"assets/{genesis_file}")
 79    ).decode()
 80    genesis_data = json.loads(genesis_str_data)
 81
 82    return GenesisConfiguration(
 83        chain_id=U64(genesis_data["config"]["chainId"]),
 84        difficulty=hex_to_uint(genesis_data["difficulty"]),
 85        extra_data=hex_to_bytes(genesis_data["extraData"]),
 86        gas_limit=hex_to_uint(genesis_data["gasLimit"]),
 87        nonce=hex_to_bytes8(genesis_data["nonce"]),
 88        timestamp=hex_or_base_10_str_to_u256(genesis_data["timestamp"]),
 89        initial_accounts=genesis_data["alloc"],
 90    )
 91
 92
 93def hex_or_base_10_str_to_u256(balance: str) -> U256:
 94    """
 95    The genesis format can have balances and timestamps as either base 10
 96    numbers or 0x prefixed hex. This function supports both.
 97    """
 98    if balance.startswith("0x"):
 99        return hex_to_u256(balance)
100    else:
101        return U256(int(balance))
102
103
104def add_genesis_block(
105    hardfork: Any, chain: Any, genesis: GenesisConfiguration
106) -> None:
107    """
108    Adds the genesis block to an empty blockchain.
109
110    The genesis block is an entirely sui generis block (unique) that is not
111    governed by the general rules applying to all other Ethereum blocks.
112    Instead, the only consensus requirement is that it must be identical to
113    the block added by this function.
114
115    The mainnet genesis configuration was originally created using the
116    `mk_genesis_block.py` script. It is long since defunct, but is still
117    available at https://github.com/ethereum/genesis_block_generator.
118
119    The initial state is populated with balances based on the Ethereum presale
120    that happened on the Bitcoin blockchain. Additional Ether worth 1.98% of
121    the presale was given to the foundation.
122
123    The `state_root` is set to the root of the initial state. The `gas_limit`
124    and `difficulty` are set to suitable starting values. In particular the
125    low gas limit made sending transactions impossible in the early stages of
126    Frontier.
127
128    The `nonce` field is `0x42` referencing Douglas Adams' "HitchHiker's Guide
129    to the Galaxy".
130
131    The `extra_data` field contains the hash of block `1028201` on
132    the pre-launch Olympus testnet. The creation of block `1028201` on Olympus
133    marked the "starting gun" for Ethereum block creation. Including its hash
134    in the genesis block ensured a fair launch of the Ethereum mining process.
135
136    The remaining fields are set to appropriate default values.
137
138    On testnets the genesis configuration usually allocates 1 wei to addresses
139    `0x00` to `0xFF` to avoid edgecases around precompiles being created or
140    cleared (by EIP 161).
141
142    Parameters
143    ----------
144    hardfork:
145        The module containing the initial hardfork
146    chain :
147        An empty `Blockchain` object.
148    genesis :
149        The genesis configuration to use.
150    """
151    for address, account in genesis.initial_accounts.items():
152        address = hardfork.utils.hexadecimal.hex_to_address(address)
153        hardfork.state.set_account(
154            chain.state,
155            address,
156            hardfork.fork_types.Account(
157                Uint(int(account.get("nonce", "0"))),
158                hex_or_base_10_str_to_u256(account.get("balance", 0)),
159                hex_to_bytes(account.get("code", "0x")),
160            ),
161        )
162        for key, value in account.get("storage", {}).items():
163            hardfork.state.set_storage(
164                chain.state, address, hex_to_bytes32(key), hex_to_uint(value)
165            )
166
167    fields = {
168        "parent_hash": hardfork.fork_types.Hash32(b"\0" * 32),
169        "ommers_hash": rlp.rlp_hash(()),
170        "coinbase": Address(b"\0" * 20),
171        "state_root": hardfork.state.state_root(chain.state),
172        "transactions_root": hardfork.trie.root(
173            hardfork.trie.Trie(False, None)
174        ),
175        "receipt_root": hardfork.trie.root(hardfork.trie.Trie(False, None)),
176        "bloom": hardfork.fork_types.Bloom(b"\0" * 256),
177        "difficulty": genesis.difficulty,
178        "number": Uint(0),
179        "gas_limit": genesis.gas_limit,
180        "gas_used": Uint(0),
181        "timestamp": genesis.timestamp,
182        "extra_data": genesis.extra_data,
183        "nonce": genesis.nonce,
184    }
185
186    if hasattr(hardfork.fork_types.Header, "mix_digest"):
187        fields["mix_digest"] = hardfork.fork_types.Hash32(b"\0" * 32)
188    else:
189        fields["prev_randao"] = hardfork.fork_types.Hash32(b"\0" * 32)
190
191    if hasattr(hardfork.fork_types.Header, "base_fee_per_gas"):
192        fields["base_fee_per_gas"] = Uint(10**9)
193
194    genesis_header = hardfork.fork_types.Header(**fields)
195
196    genesis_block = hardfork.fork_types.Block(
197        header=genesis_header,
198        transactions=(),
199        ommers=(),
200    )
201
202    chain.blocks.append(genesis_block)
203    chain.chain_id = genesis.chain_id
@slotted_freezable
@dataclass
class GenesisConfiguration:
42@slotted_freezable
43@dataclass
44class GenesisConfiguration:
45    """
46    Configuration for the first block of an Ethereum chain.
47
48    Specifies the allocation of ether set out in the pre-sale, and some of
49    the fields of the genesis block.
50    """
51
52    chain_id: U64
53    difficulty: Uint
54    extra_data: Bytes
55    gas_limit: Uint
56    nonce: Bytes8
57    timestamp: U256
58    initial_accounts: Dict[str, Dict]

Configuration for the first block of an Ethereum chain.

Specifies the allocation of ether set out in the pre-sale, and some of the fields of the genesis block.

def get_genesis_configuration(genesis_file: str) -> GenesisConfiguration:
61def get_genesis_configuration(genesis_file: str) -> GenesisConfiguration:
62    """
63    Obtain the genesis configuration from the given genesis json file.
64
65    The genesis file should be present in the `assets` directory.
66
67    Parameters
68    ----------
69    genesis_file :
70        The json file which contains the parameters for the genesis block
71        and the pre-sale allocation data.
72
73    Returns
74    -------
75    configuration : `GenesisConfiguration`
76        The genesis configuration obtained from the json genesis file.
77    """
78    genesis_str_data = cast(
79        bytes, pkgutil.get_data("ethereum", f"assets/{genesis_file}")
80    ).decode()
81    genesis_data = json.loads(genesis_str_data)
82
83    return GenesisConfiguration(
84        chain_id=U64(genesis_data["config"]["chainId"]),
85        difficulty=hex_to_uint(genesis_data["difficulty"]),
86        extra_data=hex_to_bytes(genesis_data["extraData"]),
87        gas_limit=hex_to_uint(genesis_data["gasLimit"]),
88        nonce=hex_to_bytes8(genesis_data["nonce"]),
89        timestamp=hex_or_base_10_str_to_u256(genesis_data["timestamp"]),
90        initial_accounts=genesis_data["alloc"],
91    )

Obtain the genesis configuration from the given genesis json file.

The genesis file should be present in the assets directory.

Parameters

genesis_file : The json file which contains the parameters for the genesis block and the pre-sale allocation data.

Returns

configuration : GenesisConfiguration The genesis configuration obtained from the json genesis file.

def hex_or_base_10_str_to_u256(balance: str) -> ethereum.base_types.U256:
 94def hex_or_base_10_str_to_u256(balance: str) -> U256:
 95    """
 96    The genesis format can have balances and timestamps as either base 10
 97    numbers or 0x prefixed hex. This function supports both.
 98    """
 99    if balance.startswith("0x"):
100        return hex_to_u256(balance)
101    else:
102        return U256(int(balance))

The genesis format can have balances and timestamps as either base 10 numbers or 0x prefixed hex. This function supports both.

def add_genesis_block( hardfork: Any, chain: Any, genesis: GenesisConfiguration) -> None:
105def add_genesis_block(
106    hardfork: Any, chain: Any, genesis: GenesisConfiguration
107) -> None:
108    """
109    Adds the genesis block to an empty blockchain.
110
111    The genesis block is an entirely sui generis block (unique) that is not
112    governed by the general rules applying to all other Ethereum blocks.
113    Instead, the only consensus requirement is that it must be identical to
114    the block added by this function.
115
116    The mainnet genesis configuration was originally created using the
117    `mk_genesis_block.py` script. It is long since defunct, but is still
118    available at https://github.com/ethereum/genesis_block_generator.
119
120    The initial state is populated with balances based on the Ethereum presale
121    that happened on the Bitcoin blockchain. Additional Ether worth 1.98% of
122    the presale was given to the foundation.
123
124    The `state_root` is set to the root of the initial state. The `gas_limit`
125    and `difficulty` are set to suitable starting values. In particular the
126    low gas limit made sending transactions impossible in the early stages of
127    Frontier.
128
129    The `nonce` field is `0x42` referencing Douglas Adams' "HitchHiker's Guide
130    to the Galaxy".
131
132    The `extra_data` field contains the hash of block `1028201` on
133    the pre-launch Olympus testnet. The creation of block `1028201` on Olympus
134    marked the "starting gun" for Ethereum block creation. Including its hash
135    in the genesis block ensured a fair launch of the Ethereum mining process.
136
137    The remaining fields are set to appropriate default values.
138
139    On testnets the genesis configuration usually allocates 1 wei to addresses
140    `0x00` to `0xFF` to avoid edgecases around precompiles being created or
141    cleared (by EIP 161).
142
143    Parameters
144    ----------
145    hardfork:
146        The module containing the initial hardfork
147    chain :
148        An empty `Blockchain` object.
149    genesis :
150        The genesis configuration to use.
151    """
152    for address, account in genesis.initial_accounts.items():
153        address = hardfork.utils.hexadecimal.hex_to_address(address)
154        hardfork.state.set_account(
155            chain.state,
156            address,
157            hardfork.fork_types.Account(
158                Uint(int(account.get("nonce", "0"))),
159                hex_or_base_10_str_to_u256(account.get("balance", 0)),
160                hex_to_bytes(account.get("code", "0x")),
161            ),
162        )
163        for key, value in account.get("storage", {}).items():
164            hardfork.state.set_storage(
165                chain.state, address, hex_to_bytes32(key), hex_to_uint(value)
166            )
167
168    fields = {
169        "parent_hash": hardfork.fork_types.Hash32(b"\0" * 32),
170        "ommers_hash": rlp.rlp_hash(()),
171        "coinbase": Address(b"\0" * 20),
172        "state_root": hardfork.state.state_root(chain.state),
173        "transactions_root": hardfork.trie.root(
174            hardfork.trie.Trie(False, None)
175        ),
176        "receipt_root": hardfork.trie.root(hardfork.trie.Trie(False, None)),
177        "bloom": hardfork.fork_types.Bloom(b"\0" * 256),
178        "difficulty": genesis.difficulty,
179        "number": Uint(0),
180        "gas_limit": genesis.gas_limit,
181        "gas_used": Uint(0),
182        "timestamp": genesis.timestamp,
183        "extra_data": genesis.extra_data,
184        "nonce": genesis.nonce,
185    }
186
187    if hasattr(hardfork.fork_types.Header, "mix_digest"):
188        fields["mix_digest"] = hardfork.fork_types.Hash32(b"\0" * 32)
189    else:
190        fields["prev_randao"] = hardfork.fork_types.Hash32(b"\0" * 32)
191
192    if hasattr(hardfork.fork_types.Header, "base_fee_per_gas"):
193        fields["base_fee_per_gas"] = Uint(10**9)
194
195    genesis_header = hardfork.fork_types.Header(**fields)
196
197    genesis_block = hardfork.fork_types.Block(
198        header=genesis_header,
199        transactions=(),
200        ommers=(),
201    )
202
203    chain.blocks.append(genesis_block)
204    chain.chain_id = genesis.chain_id

Adds the genesis block to an empty blockchain.

The genesis block is an entirely sui generis block (unique) that is not governed by the general rules applying to all other Ethereum blocks. Instead, the only consensus requirement is that it must be identical to the block added by this function.

The mainnet genesis configuration was originally created using the mk_genesis_block.py script. It is long since defunct, but is still available at https://github.com/ethereum/genesis_block_generator.

The initial state is populated with balances based on the Ethereum presale that happened on the Bitcoin blockchain. Additional Ether worth 1.98% of the presale was given to the foundation.

The state_root is set to the root of the initial state. The gas_limit and difficulty are set to suitable starting values. In particular the low gas limit made sending transactions impossible in the early stages of Frontier.

The nonce field is 0x42 referencing Douglas Adams' "HitchHiker's Guide to the Galaxy".

The extra_data field contains the hash of block 1028201 on the pre-launch Olympus testnet. The creation of block 1028201 on Olympus marked the "starting gun" for Ethereum block creation. Including its hash in the genesis block ensured a fair launch of the Ethereum mining process.

The remaining fields are set to appropriate default values.

On testnets the genesis configuration usually allocates 1 wei to addresses 0x00 to 0xFF to avoid edgecases around precompiles being created or cleared (by EIP 161).

Parameters

hardfork: The module containing the initial hardfork chain : An empty Blockchain object. genesis : The genesis configuration to use.