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.

37
@final
38
@slotted_freezable
39
@dataclass
class GenesisConfiguration:

chain_id

Discriminant between diverged blockchains; 1 for Ethereum's main network.

48
    chain_id: U64

difficulty

See difficulty (and subsequent forks.)

53
    difficulty: Uint

extra_data

See extra_data (and subsequent forks.)

60
    extra_data: Bytes

gas_limit

See gas_limit (and subsequent forks.)

67
    gas_limit: Uint

nonce

See nonce (and subsequent forks.)

74
    nonce: Bytes8

timestamp

See timestamp (and subsequent forks.)

81
    timestamp: U256

initial_accounts

State of the blockchain at genesis.

88
    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:
95
    <snip>
100
    genesis_path = f"assets/{genesis_file}"
101
    genesis_bytes = pkgutil.get_data("ethereum", genesis_path)
102
    if genesis_bytes is None:
103
        raise Exception(f"Unable to read genesis from `{genesis_path}`")
104
105
    genesis_data = json.loads(genesis_bytes.decode())
106
107
    return GenesisConfiguration(
108
        chain_id=U64(genesis_data["config"]["chainId"]),
109
        difficulty=hex_to_uint(genesis_data["difficulty"]),
110
        extra_data=hex_to_bytes(genesis_data["extraData"]),
111
        gas_limit=hex_to_uint(genesis_data["gasLimit"]),
112
        nonce=hex_to_bytes8(genesis_data["nonce"]),
113
        timestamp=hex_or_base_10_str_to_u256(genesis_data["timestamp"]),
114
        initial_accounts=genesis_data["alloc"],
115
    )

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:
119
    <snip>
122
    if balance.startswith("0x"):
123
        return hex_to_u256(balance)
124
    else:
125
        return U256(int(balance))

AddressT

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

AccountT

129
AccountT = TypeVar("AccountT")

StateT

130
StateT = TypeVar("StateT")

TrieT

131
TrieT = TypeVar("TrieT")

BloomT

132
BloomT = TypeVar("BloomT")

HeaderT

133
HeaderT = TypeVar("HeaderT")

BlockT

134
BlockT = TypeVar("BlockT")

GenesisFork

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

137
@final
138
@slotted_freezable
139
@dataclass
class GenesisFork:

Address

148
    Address: Type[FixedBytes]

Account

149
    Account: Callable[[Uint, U256, Hash32], AccountT]

Trie

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

Bloom

151
    Bloom: Type[FixedBytes]

Header

152
    Header: Type[HeaderT]

Block

153
    Block: Type[BlockT]

hex_to_address

154
    hex_to_address: Callable[[str], AddressT]

set_account

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

set_storage

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

state_root

157
    state_root: Callable[[StateT], Hash32]

root

158
    root: Callable[[TrieT], object]

store_code

159
    store_code: Callable[[StateT, Bytes], Hash32]

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:
169
    <snip>
206
    Address: Type[FixedBytes] = hardfork.Address  # noqa N806
207
    assert issubclass(Address, FixedBytes)
208
209
    for hex_address, account in genesis.initial_accounts.items():
210
        address = hardfork.hex_to_address(hex_address)
211
        code = hex_to_bytes(account.get("code", "0x"))
212
        code_hash = hardfork.store_code(chain.state, code)
213
        hardfork.set_account(
214
            chain.state,
215
            address,
216
            hardfork.Account(
217
                Uint(int(account.get("nonce", "0"))),
218
                hex_or_base_10_str_to_u256(account.get("balance", 0)),
219
                code_hash,
220
            ),
221
        )
222
        for key, value in account.get("storage", {}).items():
223
            hardfork.set_storage(
224
                chain.state, address, hex_to_bytes32(key), hex_to_u256(value)
225
            )
226
227
    fields = {
228
        "parent_hash": Hash32(b"\0" * 32),
229
        "ommers_hash": keccak256(rlp.encode(())),
230
        "coinbase": Address(b"\0" * Address.LENGTH),
231
        "state_root": hardfork.state_root(chain.state),
232
        "transactions_root": hardfork.root(hardfork.Trie(False, None)),
233
        "receipt_root": hardfork.root(hardfork.Trie(False, None)),
234
        "bloom": hardfork.Bloom(b"\0" * 256),
235
        "difficulty": genesis.difficulty,
236
        "number": Uint(0),
237
        "gas_limit": genesis.gas_limit,
238
        "gas_used": Uint(0),
239
        "timestamp": genesis.timestamp,
240
        "extra_data": genesis.extra_data,
241
        "nonce": genesis.nonce,
242
    }
243
244
    if has_field(hardfork.Header, "mix_digest"):
245
        fields["mix_digest"] = Hash32(b"\0" * 32)
246
    else:
247
        fields["prev_randao"] = Hash32(b"\0" * 32)
248
249
    if has_field(hardfork.Header, "base_fee_per_gas"):
250
        fields["base_fee_per_gas"] = Uint(10**9)
251
252
    if has_field(hardfork.Header, "withdrawals_root"):
253
        fields["withdrawals_root"] = hardfork.root(hardfork.Trie(False, None))
254
255
    if has_field(hardfork.Header, "blob_gas_used"):
256
        fields["blob_gas_used"] = U64(0)
257
258
    if has_field(hardfork.Header, "excess_blob_gas"):
259
        fields["excess_blob_gas"] = U64(0)
260
261
    if has_field(hardfork.Header, "parent_beacon_block_root"):
262
        fields["parent_beacon_block_root"] = Hash32(b"\0" * 32)
263
264
    if has_field(hardfork.Header, "requests_hash"):
265
        fields["requests_hash"] = Hash32(b"\0" * 32)
266
267
    if has_field(hardfork.Header, "block_access_list_hash"):
268
        fields["block_access_list_hash"] = keccak256(rlp.encode([]))
269
270
    if has_field(hardfork.Header, "slot_number"):
271
        fields["slot_number"] = U64(0)
272
273
    genesis_header = hardfork.Header(**fields)
274
275
    block_fields = {
276
        "header": genesis_header,
277
        "transactions": (),
278
        "ommers": (),
279
    }
280
281
    if has_field(hardfork.Block, "withdrawals"):
282
        block_fields["withdrawals"] = ()
283
284
    if has_field(hardfork.Block, "requests"):
285
        block_fields["requests"] = ()
286
287
    genesis_block = hardfork.Block(**block_fields)
288
289
    chain.blocks.append(genesis_block)
290
    chain.chain_id = genesis.chain_id