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
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.
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.
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.
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.