Genesis Configuration

Introduction

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

Module Contents

Classes

GenesisConfiguration

Configuration for the first block of an Ethereum chain.

Functions

get_genesis_configuration

Obtain the genesis configuration from the given genesis json file.

hex_or_base_10_str_to_u256

The genesis format can have balances and timestamps as either base 10

add_genesis_block

Adds the genesis block to an empty blockchain.

Attributes

Address

Module Details

Address

Address
Address = Bytes20

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.

class GenesisConfiguration
chain_id :ethereum.base_types.U64
difficulty :ethereum.base_types.Uint
extra_data :ethereum.base_types.Bytes
gas_limit :ethereum.base_types.Uint
nonce :ethereum.base_types.Bytes8
timestamp :ethereum.base_types.U256
initial_accounts :Dict[str, Dict]

get_genesis_configuration

get_genesis_configuration(genesis_file: str)GenesisConfiguration

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 – The genesis configuration obtained from the json genesis file.

Return type

GenesisConfiguration

def get_genesis_configuration(genesis_file: str) -> GenesisConfiguration:
    genesis_str_data = cast(
        bytes, pkgutil.get_data("ethereum", f"assets/{genesis_file}")
    ).decode()
    genesis_data = json.loads(genesis_str_data)

    return GenesisConfiguration(
        chain_id=U64(genesis_data["config"]["chainId"]),
        difficulty=hex_to_uint(genesis_data["difficulty"]),
        extra_data=hex_to_bytes(genesis_data["extraData"]),
        gas_limit=hex_to_uint(genesis_data["gasLimit"]),
        nonce=hex_to_bytes8(genesis_data["nonce"]),
        timestamp=hex_or_base_10_str_to_u256(genesis_data["timestamp"]),
        initial_accounts=genesis_data["alloc"],
    )

hex_or_base_10_str_to_u256

hex_or_base_10_str_to_u256(balance: str)ethereum.base_types.U256

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

def hex_or_base_10_str_to_u256(balance: str) -> U256:
    if balance.startswith("0x"):
        return hex_to_u256(balance)
    else:
        return U256(int(balance))

add_genesis_block

add_genesis_block(hardfork: Any, chain: Any, genesis: GenesisConfiguration)None

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.

def add_genesis_block(
    hardfork: Any, chain: Any, genesis: GenesisConfiguration
) -> None:
    for address, account in genesis.initial_accounts.items():
        address = hardfork.utils.hexadecimal.hex_to_address(address)
        hardfork.state.set_account(
            chain.state,
            address,
            hardfork.fork_types.Account(
                Uint(int(account.get("nonce", "0"))),
                hex_or_base_10_str_to_u256(account.get("balance", 0)),
                hex_to_bytes(account.get("code", "0x")),
            ),
        )
        for key, value in account.get("storage", {}).items():
            hardfork.state.set_storage(
                chain.state, address, hex_to_bytes32(key), hex_to_uint(value)
            )

    fields = {
        "parent_hash": hardfork.fork_types.Hash32(b"\0" * 32),
        "ommers_hash": rlp.rlp_hash(()),
        "coinbase": Address(b"\0" * 20),
        "state_root": hardfork.state.state_root(chain.state),
        "transactions_root": hardfork.trie.root(
            hardfork.trie.Trie(False, None)
        ),
        "receipt_root": hardfork.trie.root(hardfork.trie.Trie(False, None)),
        "bloom": hardfork.fork_types.Bloom(b"\0" * 256),
        "difficulty": genesis.difficulty,
        "number": Uint(0),
        "gas_limit": genesis.gas_limit,
        "gas_used": Uint(0),
        "timestamp": genesis.timestamp,
        "extra_data": genesis.extra_data,
        "nonce": genesis.nonce,
    }

    if hasattr(hardfork.fork_types.Header, "mix_digest"):
        fields["mix_digest"] = hardfork.fork_types.Hash32(b"\0" * 32)
    else:
        fields["prev_randao"] = hardfork.fork_types.Hash32(b"\0" * 32)

    if hasattr(hardfork.fork_types.Header, "base_fee_per_gas"):
        fields["base_fee_per_gas"] = Uint(10**9)

    genesis_header = hardfork.fork_types.Header(**fields)

    genesis_block = hardfork.fork_types.Block(
        header=genesis_header,
        transactions=(),
        ommers=(),
    )

    chain.blocks.append(genesis_block)
    chain.chain_id = genesis.chain_id