Setting up a private network or joining a public network requires an Ethereum node to create a new blockchain. Whether it is a private or public network, each node/validator will have a full copy of the blockchain. In order to build this copy, the node/validator has to have instructions on how to build the first block and the subsequent blocks in the chain. In this article, we are going to walk through the components of a genesis file, within the context of using Hyperledger Besu as the client for our network. These concepts are applicable to all Ethereum clients.
The first block in a blockchain is called the genesis block. Ethereum mainnet’s genesis block - block 0 - was mined on July 30, 2015. In order to join or create any network, the data for the genesis block must be included. Therefore, the genesis file defines the data that is in the first block of a blockchain, as well as rules for the blockchain itself. If a new node or validator attempts to join the blockchain, it will use the genesis file as the starting point in recreating the history of the chain in order to synchronize with the existing network.
The genesis file for Ethereum mainnet, along with the supported testnets, is included in the download of Besu. When creating a private network, a custom genesis file must be provided. The genesis file is a JSON formatted file. It looks like the below:
{
"config": {
"chainId": 2018,
"muirglacierblock": 0,
"ibft2": {
"blockperiodseconds": 2,
"epochlength": 30000,
"requesttimeoutseconds": 4
}
},
"nonce": "0x0",
"timestamp": "0x58ee40ba",
"extraData": "0xf83ea00000000000000000000000000000000000000000000000000000000000000000d5949811ebc35d7b06b3fa8dc5809a1f9c52751e1deb808400000000c0",
"gasLimit": "0x1fffffffffffff",
"difficulty": "0x1",
"mixHash": "0x63746963616c2062797a616e74696e65206661756c7420746f6c6572616e6365",
"coinbase": "0x0000000000000000000000000000000000000000",
"alloc": {
"9811ebc35d7b06b3fa8dc5809a1f9c52751e1deb": {
"balance": "0xad78ebc5ac6200000"
}
}
}
In this specific example, the genesis file is for an IBFT 2.0 private network.
{
"config": {
"chainId": 2018,
"muirglacierblock": 0,
"ibft2": {
"blockperiodseconds": 2,
"epochlength": 30000,
"requesttimeoutseconds": 4
}
The config key section contains the following information about the blockchain
“chainId”: 2018
The chainId controls the transaction signature process, providing a unique identifier to allow for the hashing of signed transactions to only work on the network associated with the corresponding chainId. Ethereum Improvement Proposal 155 (EIP-155) provides more information on the relationale behind the chainID. Most chainIDs match the networkID of the network. In this case, 2018 refers to the chainID associated with a development chain. For a list of the network and chain IDs, please see the Documentation.
"muirglacierblock": 0,
This field is called a “milestone block”. Muir glacier refers to a specific network upgrade that occurred at block 9,200,000 on Ethereum mainnet. For private networks, like the one that is being created in this example, the name of the latest milestone block can be listed, and set to be the genesis block. Here you can see a continuously updated list of network upgrades and the associated blocks for Ethereum.
“ibft2”:
This specifies that the consensus protocol for the blockchain is IBFT 2.0. The options available for specifying the consensus mechanism are available in the documentation, with an overview of the proof-of-authority (PoA) consensus protocols available here. Within the specification, the following three fields are provided:
"blockperiodseconds": 2,
The minimum block time, in seconds. In this case, after two seconds, a new block will be proposed by the network with transactions stored in the memory pool packaged and distributed to the network.
"epochlength": 30000,
The number of blocks at which to reset all votes. The votes refer to validators voting to add or remove validators to the network. In this case, after 30,000 blocks are created, this IBFT 2.0 network will discard all pending votes collected from received blocks. Existing proposals remain in effect and validators re-add their vote the next time they create a block.
"requesttimeoutseconds": 4
The time by which a new block must be proposed or else a new validator will be assigned by the network. If a validator goes down, the request time out ensures that the proposal of a new block passes on to another validator. The request time out seconds should be set to be double the minimum block time (blockperiodseconds), hence why it is 4.
The second section, starting with "nonce": "0x0", contains information about the genesis block
"nonce": "0x0",
"timestamp": "0x58ee40ba",
"extraData": "0xf83ea00000000000000000000000000000000000000000000000000000000000000000d5949811ebc35d7b06b3fa8dc5809a1f9c52751e1deb808400000000c0",
"gasLimit": "0x1fffffffffffff",
"difficulty": "0x1",
"mixHash": "0x63746963616c2062797a616e74696e65206661756c7420746f6c6572616e6365",
"coinbase": "0x0000000000000000000000000000000000000000",
"alloc": {
"9811ebc35d7b06b3fa8dc5809a1f9c52751e1deb": {
"balance": "0xad78ebc5ac6200000"
}
}
}
"nonce": "0x0",
The number used once aka nonce, that is a part of the blockheader for the first block. Set to 0x0.
"timestamp": "0x58ee40ba",
The creation date and time of the block. Often it can be set to 0x0, but as long as it is any value in the past, it will work. In this case 0x58ee40ba is a hexadecimal which converts to 1492009146 and represents Wed Apr 12 2017 14:59:06 GMT+0000
"extraData": "0xf83ea00000000000000000000000000000000000000000000000000000000000000000d5949811ebc35d7b06b3fa8dc5809a1f9c52751e1deb808400000000c0",
Extra data is a recursive length prefix (RLP) encoded string (which is space efficient) containing the validator addresses of the IBFT 2.0 private network. The validator addresses are unique to the validators, so if there are four validators are the start of the network, this field should contain a list of their addresses. Instructions on how to create an RLP using Besu can be found here.
"gasLimit": "0x1fffffffffffff",
The block gas limit, which is the total gas limit for all transactions included in a block. It defines how large the block size can be for the block, and is represented by an hexadecimal string. For this network, the gas limit is the maximum size, and is therefore a “free gas network”
"difficulty": "0x1",
The difficulty of creating a new block. Represented as a hexadecimal string, the difficulty is set to 1, effectively the lowest difficulty.
"mixHash": "0x63746963616c2062797a616e74696e65206661756c7420746f6c6572616e6365",
The mixHash is the unique identifier for the block, which for this genesis file is 0x63746963616c2062797a616e74696e65206661756c7420746f6c6572616e6365
"coinbase": "0x0000000000000000000000000000000000000000",
The network coinbase account, which is where all block rewards for this network will be paid. In this case it is to 0x0000000000000000000000000000000000000000, which is sometimes called address(0) or the zero address.
"alloc": {
"9811ebc35d7b06b3fa8dc5809a1f9c52751e1deb": {
"balance": "0xad78ebc5ac6200000"
The alloc field creates an address on our network, which is sometimes also referred to as an externally owned account, as it is an account not associated with a smart contract (referred to as a contract account). The number starting with “98” is the public key of the address. The balance can be passed in as a decimal OR a hexadecimal (like it has in this case and corresponds to 200 ETH, or 2*10^20 Wei). The balance is always in Wei, or 10^-18 Ether.
A Second Genesis File
Below we provide another genesis file with a different consensus mechanism, Clique PoA, and different information. Take a look below and see what values stick out. This is the genesis file for the chain that you can build in the Consensys Quorum quickstart:
{
"config":{
"chainId":1337,
"muirglacierblock": 0,
"clique":{
"blockperiodseconds":15,
"epochlength":30000
}
},
"coinbase":"0x0000000000000000000000000000000000000000",
"difficulty":"0x1",
"extraData":"0x00000000000000000000000000000000000000000000000000000000000000004592c8e45706cc08b8f44b11e43cba0cfc5892cb0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
"gasLimit":"0xa00000", "mixHash":"0x0000000000000000000000000000000000000000000000000000000000000000",
"nonce":"0x0",
"timestamp":"0x5c51a607",
"alloc": {
"fe3b557e8fb62b89f4916b721be55ceb828dbd73": {
"privateKey": "8f2a55949038a9610f50fb23b5883af3b4ecb3c3bb792cbcefbd1542c692be63",
"comment": "private key and this comment are ignored. In a real chain, the private key should NOT be stored",
"balance": "0xad78ebc5ac6200000"
},
"627306090abaB3A6e1400e9345bC60c78a8BEf57": {
"privateKey": "c87509a1c067bbde78beb793e6fa76530b6382a4c0241e5e4a9ec0a0f44dc0d3",
"comment": "private key and this comment are ignored. In a real chain, the private key should NOT be stored",
"balance": "90000000000000000000000"
},
"f17f52151EbEF6C7334FAD080c5704D77216b732": {
"privateKey": "ae6ae8e5ccbfb04590405997ee2d52d2b330726137b875053c36d94e974d162f",
"comment": "private key and this comment are ignored. In a real chain, the private key should NOT be stored",
"balance": "90000000000000000000000"
}
},
"number":"0x0",
"gasUsed":"0x0",
"parentHash":"0x0000000000000000000000000000000000000000000000000000000000000000"
}
Once again, we will look at the fields and explain them.
{
"config":{
"chainId":1337,
"constantinoplefixblock": 0,
"clique":{
"blockperiodseconds":15,
"epochlength":30000
}
}
The config key section contains the following information about the blockchain
“chainId”: 1337
In this case. 1337 refers to a local chainID. MetaMask, a self-custodial wallet, and Ganache, which is Truffle’s Private Blockchain App, both use this as the local chain ID, and so to follow convention, in this genesis file we are doing the same. For a list of the network and chain IDs, please see the Documentation.
"muirglacierblock": 0,
Once again, we have set the milestone block to Muir Glacier. Something to note - The “milestone block” could be for this configuration file, which is something you may see in some tutorials. For example, if we saw constantinopleBlock": 0, this refers to a specific network upgrade that occurred at block 7,280,000 on Ethereum mainnet. For private networks, like the one that is being created in this example, the name of the latest milestone block can be listed, and set to be the genesis block. Here you can see a continuously updated list of network upgrades and the associated blocks for Ethereum.
“clique”:
This specifies that the consensus protocol for the blockchain is Clique. The options available for specifying the consensus mechanism are available in the documentation, with an overview of the proof-of-authority (PoA) consensus protocols available here. Within the specification, the following two fields are provided:
"blockperiodseconds": 15,
The minimum block time, in seconds. In this case, after 15 seconds, a new block will be proposed by the network. Given this genesis file is modeled after the testnet, it is made to approximate the minimum blocktime of mainnet, which is 15 seconds.
"epochlength": 30000,
The number of blocks at which to reset all votes. The votes refer to validators voting to add or remove validators to the network. In this case, after 30,000 blocks are created, this Clique network will discard all pending votes collected from received blocks. Existing proposals remain in effect and validators re-add their vote the next time they create a block.
Starting at the coinbase we now have the information available in the genesis block
"coinbase":"0x0000000000000000000000000000000000000000",
"difficulty":"0x1",
"extraData":"0x00000000000000000000000000000000000000000000000000000000000000004592c8e45706cc08b8f44b11e43cba0cfc5892cb0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
"gasLimit":"0xa00000",
"mixHash":"0x0000000000000000000000000000000000000000000000000000000000000000",
"nonce":"0x0",
"timestamp":"0x5c51a607",
"alloc": {
"fe3b557e8fb62b89f4916b721be55ceb828dbd73": {
"privateKey": "8f2a55949038a9610f50fb23b5883af3b4ecb3c3bb792cbcefbd1542c692be63",
"comment": "private key and this comment are ignored. In a real chain, the private key should NOT be stored",
"balance": "0xad78ebc5ac6200000"
},
"627306090abaB3A6e1400e9345bC60c78a8BEf57": {
"privateKey": "c87509a1c067bbde78beb793e6fa76530b6382a4c0241e5e4a9ec0a0f44dc0d3",
"comment": "private key and this comment are ignored. In a real chain, the private key should NOT be stored",
"balance": "90000000000000000000000"
},
"f17f52151EbEF6C7334FAD080c5704D77216b732": {
"privateKey": "ae6ae8e5ccbfb04590405997ee2d52d2b330726137b875053c36d94e974d162f",
"comment": "private key and this comment are ignored. In a real chain, the private key should NOT be stored",
"balance": "90000000000000000000000"
}
}
"coinbase": "0x0000000000000000000000000000000000000000",
The coinbase account, which is where all block rewards for this network will be paid. In this case it is to 0x0000000000000000000000000000000000000000, which is sometimes called address(0) or the zero address.
"difficulty": "0x1",
The difficulty of creating a new block. Represented as a hexadecimal string, the difficulty is set to 1, effectively the lowest difficulty.
"extraData":"0x00000000000000000000000000000000000000000000000000000000000000004592c8e45706cc08b8f44b11e43cba0cfc5892cb0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
Extra data is a recursive length prefix (RLP) encoded string (which is space efficient) containing the validator address of the Clique private network, which in this case is 4592c8e45706cc08b8f44b11e43cba0cfc5892cb. Instructions on how to create an RLP using Besu can be found here and how to add additional addresses for a Clique network with additional signers can be found here.
"gasLimit": "0xa00000",
The block gas limit, which is the total gas limit for all transactions included in a block. It defines how large the block size can be for the block, and is represented by an hexadecimal string. For this network, the gas limit is
"mixHash":"0x0000000000000000000000000000000000000000000000000000000000000000",
The mixHash is the unique identifier for the block, which for this genesis file is 0x0000000000000000000000000000000000000000000000000000000000000000
"nonce": "0x0",
"timestamp": "0x5c51a607",
In this case 0x5c51a607 is a hexadecimal which converts to 1548854791 and represents Wed Jan 30 2019 13:26:31 GMT+0000.
"alloc": {
"fe3b557e8fb62b89f4916b721be55ceb828dbd73": {
"privateKey": "8f2a55949038a9610f50fb23b5883af3b4ecb3c3bb792cbcefbd1542c692be63",
"comment": "private key and this comment are ignored. In a real chain, the private key should NOT be stored",
"balance": "0xad78ebc5ac6200000"
},
"627306090abaB3A6e1400e9345bC60c78a8BEf57": {
"privateKey": "c87509a1c067bbde78beb793e6fa76530b6382a4c0241e5e4a9ec0a0f44dc0d3",
"comment": "private key and this comment are ignored. In a real chain, the private key should NOT be stored",
"balance": "90000000000000000000000"
},
"f17f52151EbEF6C7334FAD080c5704D77216b732": {
"privateKey": "ae6ae8e5ccbfb04590405997ee2d52d2b330726137b875053c36d94e974d162f",
"comment": "private key and this comment are ignored. In a real chain, the private key should NOT be stored",
"balance": "90000000000000000000000"
}
The alloc field creates three addresses on our network, The balance can be passed in as a decimal (like the second and third account, which are both 900 ETH, or 2*10^20 Wei) OR a hexadecimal (like the first account, which is 200 ETH, or 2*10^20 Wei). The balance is always in Wei, or 10^-18 Ether.
Deploying Your Genesis File
Once you have created your genesis file, you will save it within the directory where your blockchain networks files will be kept. Do not save it within any of the Node or data folders, but rather at the top level. When it is time to start your network, you will use the flag
--genesis-file=../genesis.json
To start up your network using the genesis file use the following command:besu--genesis-file=../genesis.json
For more information, please see the Documentation.
In the next article in this series, we will explore two advanced features for using a genesis file as part of a private network - how to deploy a smart contract within a genesis file and how to ensure the genesis file is appropriately tuned for the desired performance.