ethereum.genesis

Types and functions for beginning a new chain.

Genesis is the term for the beginning of a new chain, and so a genesis block is a block with no parent (its parent_hash is all zeros.)

The genesis configuration for a chain is specified with a GenesisConfiguration, and genesis blocks are created with add_genesis_block.

GenesisConfiguration

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.

36
@slotted_freezable
37
@dataclass
class GenesisConfiguration:

chain_id

46
    chain_id: U64

difficulty

51
    difficulty: Uint

extra_data

58
    extra_data: Bytes

gas_limit

65
    gas_limit: Uint

nonce

72
    nonce: Bytes8

timestamp

79
    timestamp: U256

initial_accounts

86
    initial_accounts: Dict[str, Dict]

get_genesis_configuration

Read a genesis configuration from the given JSON file path.

The genesis file should be present in the assets directory.

def get_genesis_configuration(genesis_file: str) -> GenesisConfiguration:
93
    """
94
    Read a genesis configuration from the given JSON file path.
95
96
    The genesis file should be present in the `assets` directory.
97
    """
98
    genesis_path = f"assets/{genesis_file}"
99
    genesis_bytes = pkgutil.get_data("ethereum", genesis_path)
100
    if genesis_bytes is None:
101
        raise Exception(f"Unable to read genesis from `{genesis_path}`")
102
103
    genesis_data = json.loads(genesis_bytes.decode())
104
105
    return GenesisConfiguration(
106
        chain_id=U64(genesis_data["config"]["chainId"]),
107
        difficulty=hex_to_uint(genesis_data["difficulty"]),
108
        extra_data=hex_to_bytes(genesis_data["extraData"]),
109
        gas_limit=hex_to_uint(genesis_data["gasLimit"]),
110
        nonce=hex_to_bytes8(genesis_data["nonce"]),
111
        timestamp=hex_or_base_10_str_to_u256(genesis_data["timestamp"]),
112
        initial_accounts=genesis_data["alloc"],
113
    )

hex_or_base_10_str_to_u256

Convert a string in either hexadecimal or base-10 to a U256.

def hex_or_base_10_str_to_u256(balance: str) -> U256:
117
    """
118
    Convert a string in either hexadecimal or base-10 to a `U256`.
119
    """
120
    if balance.startswith("0x"):
121
        return hex_to_u256(balance)
122
    else:
123
        return U256(int(balance))

AddressT

126
AddressT = TypeVar("AddressT", bound=FixedBytes)

AccountT

127
AccountT = TypeVar("AccountT")

StateT

128
StateT = TypeVar("StateT")

TrieT

129
TrieT = TypeVar("TrieT")

BloomT

130
BloomT = TypeVar("BloomT")

HeaderT

131
HeaderT = TypeVar("HeaderT")

BlockT

132
BlockT = TypeVar("BlockT")

GenesisFork

Pointers to the various types and functions required to build a genesis block.

135
@slotted_freezable
136
@dataclass
class GenesisFork:

Address

145
    Address: Type[FixedBytes]

Account

146
    Account: Callable[[Uint, U256, bytes], AccountT]

Trie

147
    Trie: Callable[[bool, object], TrieT]

Bloom

148
    Bloom: Type[FixedBytes]

Header

149
    Header: Type[HeaderT]

Block

150
    Block: Type[BlockT]

hex_to_address

151
    hex_to_address: Callable[[str], AddressT]

set_account

152
    set_account: Callable[[StateT, AddressT, AccountT], object]

set_storage

153
    set_storage: Callable[[StateT, AddressT, Bytes32, U256], object]

state_root

154
    state_root: Callable[[StateT], Hash32]

root

155
    root: Callable[[TrieT], object]

add_genesis_block

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 edge cases around precompiles being created or cleared (by EIP-161).

def add_genesis_block(hardfork: GenesisFork[AddressT, AccountT, StateT, TrieT, BloomT, HeaderT, BlockT], ​​chain: Any, ​​genesis: GenesisConfiguration) -> None:
165
    """
166
    Adds the genesis block to an empty blockchain.
167
168
    The genesis block is an entirely sui generis block (unique) that is not
169
    governed by the general rules applying to all other Ethereum blocks.
170
    Instead, the only consensus requirement is that it must be identical to
171
    the block added by this function.
172
173
    The mainnet genesis configuration was originally created using the
174
    `mk_genesis_block.py` script. It is long since defunct, but is still
175
    available at <https://github.com/ethereum/genesis_block_generator>.
176
177
    The initial state is populated with balances based on the Ethereum presale
178
    that happened on the Bitcoin blockchain. Additional ether worth 1.98% of
179
    the presale was given to the foundation.
180
181
    The `state_root` is set to the root of the initial state. The `gas_limit`
182
    and `difficulty` are set to suitable starting values. In particular the
183
    low gas limit made sending transactions impossible in the early stages of
184
    Frontier.
185
186
    The `nonce` field is `0x42` referencing Douglas Adams' "HitchHiker's Guide
187
    to the Galaxy".
188
189
    The `extra_data` field contains the hash of block `1028201` on
190
    the pre-launch Olympus testnet. The creation of block `1028201` on Olympus
191
    marked the "starting gun" for Ethereum block creation. Including its hash
192
    in the genesis block ensured a fair launch of the Ethereum mining process.
193
194
    The remaining fields are set to appropriate default values.
195
196
    On testnets the genesis configuration usually allocates 1 wei to addresses
197
    `0x00` to `0xFF` to avoid edge cases around precompiles being created or
198
    cleared (by [EIP-161]).
199
200
    [EIP-161]: https://eips.ethereum.org/EIPS/eip-161
201
    """
202
    Address: Type[FixedBytes] = hardfork.Address
203
    assert issubclass(Address, FixedBytes)
204
205
    for hex_address, account in genesis.initial_accounts.items():
206
        address = hardfork.hex_to_address(hex_address)
207
        hardfork.set_account(
208
            chain.state,
209
            address,
210
            hardfork.Account(
211
                Uint(int(account.get("nonce", "0"))),
212
                hex_or_base_10_str_to_u256(account.get("balance", 0)),
213
                hex_to_bytes(account.get("code", "0x")),
214
            ),
215
        )
216
        for key, value in account.get("storage", {}).items():
217
            hardfork.set_storage(
218
                chain.state, address, hex_to_bytes32(key), hex_to_u256(value)
219
            )
220
221
    fields = {
222
        "parent_hash": Hash32(b"\0" * 32),
223
        "ommers_hash": rlp.rlp_hash(()),
224
        "coinbase": Address(b"\0" * Address.LENGTH),
225
        "state_root": hardfork.state_root(chain.state),
226
        "transactions_root": hardfork.root(hardfork.Trie(False, None)),
227
        "receipt_root": hardfork.root(hardfork.Trie(False, None)),
228
        "bloom": hardfork.Bloom(b"\0" * 256),
229
        "difficulty": genesis.difficulty,
230
        "number": Uint(0),
231
        "gas_limit": genesis.gas_limit,
232
        "gas_used": Uint(0),
233
        "timestamp": genesis.timestamp,
234
        "extra_data": genesis.extra_data,
235
        "nonce": genesis.nonce,
236
    }
237
238
    if has_field(hardfork.Header, "mix_digest"):
239
        fields["mix_digest"] = Hash32(b"\0" * 32)
240
    else:
241
        fields["prev_randao"] = Hash32(b"\0" * 32)
242
243
    if has_field(hardfork.Header, "base_fee_per_gas"):
244
        fields["base_fee_per_gas"] = Uint(10**9)
245
246
    if has_field(hardfork.Header, "withdrawals_root"):
247
        fields["withdrawals_root"] = hardfork.root(hardfork.Trie(False, None))
248
249
    if has_field(hardfork.Header, "blob_gas_used"):
250
        fields["blob_gas_used"] = U64(0)
251
252
    if has_field(hardfork.Header, "excess_blob_gas"):
253
        fields["excess_blob_gas"] = U64(0)
254
255
    if has_field(hardfork.Header, "parent_beacon_block_root"):
256
        fields["parent_beacon_block_root"] = Hash32(b"\0" * 32)
257
258
    genesis_header = hardfork.Header(**fields)
259
260
    block_fields = {
261
        "header": genesis_header,
262
        "transactions": (),
263
        "ommers": (),
264
    }
265
266
    if has_field(hardfork.Block, "withdrawals"):
267
        block_fields["withdrawals"] = ()
268
269
    genesis_block = hardfork.Block(**block_fields)
270
271
    chain.blocks.append(genesis_block)
272
    chain.chain_id = genesis.chain_id