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.

42
@slotted_freezable
43
@dataclass
class GenesisConfiguration:

chain_id

52
    chain_id: U64

difficulty

57
    difficulty: Uint

extra_data

64
    extra_data: Bytes

gas_limit

71
    gas_limit: Uint

nonce

78
    nonce: Bytes8

timestamp

85
    timestamp: U256

initial_accounts

92
    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:
99
    """
100
    Read a genesis configuration from the given JSON file path.
101
102
    The genesis file should be present in the `assets` directory.
103
    """
104
    genesis_path = f"assets/{genesis_file}"
105
    genesis_bytes = pkgutil.get_data("ethereum", genesis_path)
106
    if genesis_bytes is None:
107
        raise Exception(f"Unable to read genesis from `{genesis_path}`")
108
109
    genesis_data = json.loads(genesis_bytes.decode())
110
111
    return GenesisConfiguration(
112
        chain_id=U64(genesis_data["config"]["chainId"]),
113
        difficulty=hex_to_uint(genesis_data["difficulty"]),
114
        extra_data=hex_to_bytes(genesis_data["extraData"]),
115
        gas_limit=hex_to_uint(genesis_data["gasLimit"]),
116
        nonce=hex_to_bytes8(genesis_data["nonce"]),
117
        timestamp=hex_or_base_10_str_to_u256(genesis_data["timestamp"]),
118
        initial_accounts=genesis_data["alloc"],
119
    )

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:
123
    """
124
    Convert a string in either hexadecimal or base-10 to a [`U256`].
125
126
    [`U256`]: ref:ethereum.base_types.U256
127
    """
128
    if balance.startswith("0x"):
129
        return hex_to_u256(balance)
130
    else:
131
        return U256(int(balance))

AddressT

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

AccountT

135
AccountT = TypeVar("AccountT")

StateT

136
StateT = TypeVar("StateT")

TrieT

137
TrieT = TypeVar("TrieT")

BloomT

138
BloomT = TypeVar("BloomT")

HeaderT

139
HeaderT = TypeVar("HeaderT")

BlockT

140
BlockT = TypeVar("BlockT")

GenesisFork

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

143
@slotted_freezable
144
@dataclass
class GenesisFork:

Address

153
    Address: Type[FixedBytes]

Account

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

Trie

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

Bloom

156
    Bloom: Type[FixedBytes]

Header

157
    Header: Type[HeaderT]

Block

158
    Block: Type[BlockT]

hex_to_address

159
    hex_to_address: Callable[[str], AddressT]

set_account

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

set_storage

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

state_root

162
    state_root: Callable[[StateT], Hash32]

root

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