The merge is arguably the most significant milestone of the Ethereum research and development roadmap. By attaching a proof-of-stake consensus beacon chain to an already established proof-of-work execution chain, it is possible to swap out the consensus engine on a hot network. However, this is a very tedious task. Wouldn't it be nice to be able to launch an Ethereum network right from the proof-of-stake stage? Here's how!
The following sections outline how to configure an execution-layer client and a consensus-layer client so that they have everything in place to execute the entire merge already in the genesis block. Here, we'll use Geth and Lodestar.
Execution-Layer Configuration
Creating a new genesis for Geth is as simple as running geth dumpgenesis
and subsequently modifying fields as needed for the testnet, i.e., for a new devnet or local testnet, we'll run:
geth --sepolia dumpgenesis
This uses the latest Sepolia testnet genesis.
Now, we have to adjust the genesis configuration:
- Set a new
chainID
for replay protection. - Set all protocol upgrades to block
0
, includingmergeForkBlock
andmergeNetsplitBlock
. -
Set merge total terminal difficulty (TTD) to
0
and the TTD-passed flag totrue
(terminalTotalDifficulty
,terminalTotalDifficultyPassed
).
"config":{ "chainId":39677693, "homesteadBlock":0, "eip150Block":0, "eip155Block":0, "eip158Block":0, "byzantiumBlock":0, "constantinopleBlock":0, "petersburgBlock":0, "istanbulBlock":0, "muirGlacierBlock":0, "berlinBlock":0, "londonBlock":0, "mergeForkBlock":0, "mergeNetsplitBlock":0, "terminalTotalDifficulty":0, "terminalTotalDifficultyPassed":true },
Remove the
ethash
parameters altogether. We don't need any additional pre-merge consensus engine.Remove the existing
alloc
and create a custom allocation per our needs.-
Adjust the genesis parameters as desired, mainly
timestamp
,extraData
, andnonce
, to ensure they do not match an existing genesis. Note that all fields need to be hexadecimal for the Geth genesis file.
"nonce":"0x44144", "timestamp":"0x63A1E047", "extraData":"0x887b30d1e617484474521f31a37376760299fa7f15eb4214fce4157744b896c2", "gasLimit":"0x1c9c380", "difficulty":"0x20000", "mixHash":"0x0000000000000000000000000000000000000000000000000000000000000000", "coinbase":"0x0000000000000000000000000000000000000000", "number":"0x0", "gasUsed":"0x0", "parentHash":"0x0000000000000000000000000000000000000000000000000000000000000000",
That's it. Now all that is left is the deposit contract. Since we merge from genesis, this has to be part of the genesis state.
For that, we have to take the vanilla deposit contract from the consensus specs: deposit_contract.sol
, get the Solidity compiler version 0.6.11
, compile the binary of the runtime part and create an empty deposit tree.
Fortunately, the contract's runtime code and initial state remain always the same (see protolambda's notes), so we can copy and paste this into our genesis file.
"alloc":{
"0x0420420420420420420420420420420420420420":{
"balance":"0x0",
"code": "0x60806040526004361061003f5760003560e01c806301ffc9a71461004457806322895118146100a4578063621fd130146101ba578063c5f2892f14610244575b600080fd5b34801561005057600080fd5b506100906004803603602081101561006757600080fd5b50357fffffffff000000000000000000000000000000000000000000000000000000001661026b565b604080519115158252519081900360200190f35b6101b8600480360360808110156100ba57600080fd5b8101906020810181356401000000008111156100d557600080fd5b8201836020820111156100e757600080fd5b8035906020019184600183028401116401000000008311171561010957600080fd5b91939092909160208101903564010000000081111561012757600080fd5b82018360208201111561013957600080fd5b8035906020019184600183028401116401000000008311171561015b57600080fd5b91939092909160208101903564010000000081111561017957600080fd5b82018360208201111561018b57600080fd5b803590602001918460018302840111640100000000831117156101ad57600080fd5b919350915035610304565b005b3480156101c657600080fd5b506101cf6110b5565b6040805160208082528351818301528351919283929083019185019080838360005b838110156102095781810151838201526020016101f1565b50505050905090810190601f1680156102365780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b34801561025057600080fd5b506102596110c7565b60408051918252519081900360200190f35b60007fffffffff0000000000000000000000000000000000000000000000000000000082167f01ffc9a70000000000000000000000000000000000000000000000000000000014806102fe57507fffffffff0000000000000000000000000000000000000000000000000000000082167f8564090700000000000000000000000000000000000000000000000000000000145b92915050565b6030861461035d576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260268152602001806118056026913960400191505060405180910390fd5b602084146103b6576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252603681526020018061179c6036913960400191505060405180910390fd5b6060821461040f576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260298152602001806118786029913960400191505060405180910390fd5b670de0b6b3a7640000341015610470576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260268152602001806118526026913960400191505060405180910390fd5b633b9aca003406156104cd576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260338152602001806117d26033913960400191505060405180910390fd5b633b9aca00340467ffffffffffffffff811115610535576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602781526020018061182b6027913960400191505060405180910390fd5b6060610540826114ba565b90507f649bbc62d0e31342afea4e5cd82d4049e7e1ee912fc0889aa790803be39038c589898989858a8a6105756020546114ba565b6040805160a0808252810189905290819060208201908201606083016080840160c085018e8e80828437600083820152601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe01690910187810386528c815260200190508c8c808284376000838201819052601f9091017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe01690920188810386528c5181528c51602091820193918e019250908190849084905b83811015610648578181015183820152602001610630565b50505050905090810190601f1680156106755780820380516001836020036101000a031916815260200191505b5086810383528881526020018989808284376000838201819052601f9091017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169092018881038452895181528951602091820193918b019250908190849084905b838110156106ef5781810151838201526020016106d7565b50505050905090810190601f16801561071c5780820380516001836020036101000a031916815260200191505b509d505050505050505050505050505060405180910390a1600060028a8a600060801b604051602001808484808284377fffffffffffffffffffffffffffffffff0000000000000000000000000000000090941691909301908152604080517ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0818403018152601090920190819052815191955093508392506020850191508083835b602083106107fc57805182527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe090920191602091820191016107bf565b51815160209384036101000a7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff01801990921691161790526040519190930194509192505080830381855afa158015610859573d6000803e3d6000fd5b5050506040513d602081101561086e57600080fd5b5051905060006002806108846040848a8c6116fe565b6040516020018083838082843780830192505050925050506040516020818303038152906040526040518082805190602001908083835b602083106108f857805182527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe090920191602091820191016108bb565b51815160209384036101000a7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff01801990921691161790526040519190930194509192505080830381855afa158015610955573d6000803e3d6000fd5b5050506040513d602081101561096a57600080fd5b5051600261097b896040818d6116fe565b60405160009060200180848480828437919091019283525050604080518083038152602092830191829052805190945090925082918401908083835b602083106109f457805182527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe090920191602091820191016109b7565b51815160209384036101000a7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff01801990921691161790526040519190930194509192505080830381855afa158015610a51573d6000803e3d6000fd5b5050506040513d6020811015610a6657600080fd5b5051604080516020818101949094528082019290925280518083038201815260609092019081905281519192909182918401908083835b60208310610ada57805182527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe09092019160209182019101610a9d565b51815160209384036101000a7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff01801990921691161790526040519190930194509192505080830381855afa158015610b37573d6000803e3d6000fd5b5050506040513d6020811015610b4c57600080fd5b50516040805160208101858152929350600092600292839287928f928f92018383808284378083019250505093505050506040516020818303038152906040526040518082805190602001908083835b60208310610bd957805182527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe09092019160209182019101610b9c565b51815160209384036101000a7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff01801990921691161790526040519190930194509192505080830381855afa158015610c36573d6000803e3d6000fd5b5050506040513d6020811015610c4b57600080fd5b50516040518651600291889160009188916020918201918291908601908083835b60208310610ca957805182527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe09092019160209182019101610c6c565b6001836020036101000a0380198251168184511680821785525050505050509050018367ffffffffffffffff191667ffffffffffffffff1916815260180182815260200193505050506040516020818303038152906040526040518082805190602001908083835b60208310610d4e57805182527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe09092019160209182019101610d11565b51815160209384036101000a7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff01801990921691161790526040519190930194509192505080830381855afa158015610dab573d6000803e3d6000fd5b5050506040513d6020811015610dc057600080fd5b5051604080516020818101949094528082019290925280518083038201815260609092019081905281519192909182918401908083835b60208310610e3457805182527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe09092019160209182019101610df7565b51815160209384036101000a7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff01801990921691161790526040519190930194509192505080830381855afa158015610e91573d6000803e3d6000fd5b5050506040513d6020811015610ea657600080fd5b50519050858114610f02576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260548152602001806117486054913960600191505060405180910390fd5b60205463ffffffff11610f60576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260218152602001806117276021913960400191505060405180910390fd5b602080546001019081905560005b60208110156110a9578160011660011415610fa0578260008260208110610f9157fe5b0155506110ac95505050505050565b600260008260208110610faf57fe5b01548460405160200180838152602001828152602001925050506040516020818303038152906040526040518082805190602001908083835b6020831061102557805182527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe09092019160209182019101610fe8565b51815160209384036101000a7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff01801990921691161790526040519190930194509192505080830381855afa158015611082573d6000803e3d6000fd5b5050506040513d602081101561109757600080fd5b50519250600282049150600101610f6e565b50fe5b50505050505050565b60606110c26020546114ba565b905090565b6020546000908190815b60208110156112f05781600116600114156111e6576002600082602081106110f557fe5b01548460405160200180838152602001828152602001925050506040516020818303038152906040526040518082805190602001908083835b6020831061116b57805182527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0909201916020918201910161112e565b51815160209384036101000a7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff01801990921691161790526040519190930194509192505080830381855afa1580156111c8573d6000803e3d6000fd5b5050506040513d60208110156111dd57600080fd5b505192506112e2565b600283602183602081106111f657fe5b015460405160200180838152602001828152602001925050506040516020818303038152906040526040518082805190602001908083835b6020831061126b57805182527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0909201916020918201910161122e565b51815160209384036101000a7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff01801990921691161790526040519190930194509192505080830381855afa1580156112c8573d6000803e3d6000fd5b5050506040513d60208110156112dd57600080fd5b505192505b6002820491506001016110d1565b506002826112ff6020546114ba565b600060401b6040516020018084815260200183805190602001908083835b6020831061135a57805182527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0909201916020918201910161131d565b51815160209384036101000a7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff01801990921691161790527fffffffffffffffffffffffffffffffffffffffffffffffff000000000000000095909516920191825250604080518083037ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8018152601890920190819052815191955093508392850191508083835b6020831061143f57805182527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe09092019160209182019101611402565b51815160209384036101000a7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff01801990921691161790526040519190930194509192505080830381855afa15801561149c573d6000803e3d6000fd5b5050506040513d60208110156114b157600080fd5b50519250505090565b60408051600880825281830190925260609160208201818036833701905050905060c082901b8060071a60f81b826000815181106114f457fe5b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a9053508060061a60f81b8260018151811061153757fe5b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a9053508060051a60f81b8260028151811061157a57fe5b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a9053508060041a60f81b826003815181106115bd57fe5b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a9053508060031a60f81b8260048151811061160057fe5b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a9053508060021a60f81b8260058151811061164357fe5b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a9053508060011a60f81b8260068151811061168657fe5b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a9053508060001a60f81b826007815181106116c957fe5b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a90535050919050565b6000808585111561170d578182fd5b83861115611719578182fd5b505082019391909203915056fe4465706f736974436f6e74726163743a206d65726b6c6520747265652066756c6c4465706f736974436f6e74726163743a207265636f6e7374727563746564204465706f7369744461746120646f6573206e6f74206d6174636820737570706c696564206465706f7369745f646174615f726f6f744465706f736974436f6e74726163743a20696e76616c6964207769746864726177616c5f63726564656e7469616c73206c656e6774684465706f736974436f6e74726163743a206465706f7369742076616c7565206e6f74206d756c7469706c65206f6620677765694465706f736974436f6e74726163743a20696e76616c6964207075626b6579206c656e6774684465706f736974436f6e74726163743a206465706f7369742076616c756520746f6f20686967684465706f736974436f6e74726163743a206465706f7369742076616c756520746f6f206c6f774465706f736974436f6e74726163743a20696e76616c6964207369676e6174757265206c656e677468a26469706673582212201dd26f37a621703009abf16e77e69c93dc50c79db7f6cc37543e3e0e3decdc9764736f6c634300060b0033",
"storage": {
"0x0000000000000000000000000000000000000000000000000000000000000022": "0xf5a5fd42d16a20302798ef6ed309979b43003d2320d9f0e8ea9831a92759fb4b",
"0x0000000000000000000000000000000000000000000000000000000000000023": "0xdb56114e00fdd4c1f85c892bf35ac9a89289aaecb1ebd0a96cde606a748b5d71",
"0x0000000000000000000000000000000000000000000000000000000000000024": "0xc78009fdf07fc56a11f122370658a353aaa542ed63e44c4bc15ff4cd105ab33c",
"0x0000000000000000000000000000000000000000000000000000000000000025": "0x536d98837f2dd165a55d5eeae91485954472d56f246df256bf3cae19352a123c",
"0x0000000000000000000000000000000000000000000000000000000000000026": "0x9efde052aa15429fae05bad4d0b1d7c64da64d03d7a1854a588c2cb8430c0d30",
"0x0000000000000000000000000000000000000000000000000000000000000027": "0xd88ddfeed400a8755596b21942c1497e114c302e6118290f91e6772976041fa1",
"0x0000000000000000000000000000000000000000000000000000000000000028": "0x87eb0ddba57e35f6d286673802a4af5975e22506c7cf4c64bb6be5ee11527f2c",
"0x0000000000000000000000000000000000000000000000000000000000000029": "0x26846476fd5fc54a5d43385167c95144f2643f533cc85bb9d16b782f8d7db193",
"0x000000000000000000000000000000000000000000000000000000000000002a": "0x506d86582d252405b840018792cad2bf1259f1ef5aa5f887e13cb2f0094f51e1",
"0x000000000000000000000000000000000000000000000000000000000000002b": "0xffff0ad7e659772f9534c195c815efc4014ef1e1daed4404c06385d11192e92b",
"0x000000000000000000000000000000000000000000000000000000000000002c": "0x6cf04127db05441cd833107a52be852868890e4317e6a02ab47683aa75964220",
"0x000000000000000000000000000000000000000000000000000000000000002d": "0xb7d05f875f140027ef5118a2247bbb84ce8f2f0f1123623085daf7960c329f5f",
"0x000000000000000000000000000000000000000000000000000000000000002e": "0xdf6af5f5bbdb6be9ef8aa618e4bf8073960867171e29676f8b284dea6a08a85e",
"0x000000000000000000000000000000000000000000000000000000000000002f": "0xb58d900f5e182e3c50ef74969ea16c7726c549757cc23523c369587da7293784",
"0x0000000000000000000000000000000000000000000000000000000000000030": "0xd49a7502ffcfb0340b1d7885688500ca308161a7f96b62df9d083b71fcc8f2bb",
"0x0000000000000000000000000000000000000000000000000000000000000031": "0x8fe6b1689256c0d385f42f5bbe2027a22c1996e110ba97c171d3e5948de92beb",
"0x0000000000000000000000000000000000000000000000000000000000000032": "0x8d0d63c39ebade8509e0ae3c9c3876fb5fa112be18f905ecacfecb92057603ab",
"0x0000000000000000000000000000000000000000000000000000000000000033": "0x95eec8b2e541cad4e91de38385f2e046619f54496c2382cb6cacd5b98c26f5a4",
"0x0000000000000000000000000000000000000000000000000000000000000034": "0xf893e908917775b62bff23294dbbe3a1cd8e6cc1c35b4801887b646a6f81f17f",
"0x0000000000000000000000000000000000000000000000000000000000000035": "0xcddba7b592e3133393c16194fac7431abf2f5485ed711db282183c819e08ebaa",
"0x0000000000000000000000000000000000000000000000000000000000000036": "0x8a8d7fe3af8caa085a7639a832001457dfb9128a8061142ad0335629ff23ff9c",
"0x0000000000000000000000000000000000000000000000000000000000000037": "0xfeb3c337d7a51a6fbf00b9e34c52e1c9195c969bd4e7a0bfd51d5c5bed9c1167",
"0x0000000000000000000000000000000000000000000000000000000000000038": "0xe71f0aa83cc32edfbefa9f4d3e0174ca85182eec9f3a09f6a6c0df6377a510d7",
"0x0000000000000000000000000000000000000000000000000000000000000039": "0x31206fa80a50bb6abe29085058f16212212a60eec8f049fecb92d8c8e0a84bc0",
"0x000000000000000000000000000000000000000000000000000000000000003a": "0x21352bfecbeddde993839f614c3dac0a3ee37543f9b412b16199dc158e23b544",
"0x000000000000000000000000000000000000000000000000000000000000003b": "0x619e312724bb6d7c3153ed9de791d764a366b389af13c58bf8a8d90481a46765",
"0x000000000000000000000000000000000000000000000000000000000000003c": "0x7cdd2986268250628d0c10e385c58c6191e6fbe05191bcc04f133f2cea72c1c4",
"0x000000000000000000000000000000000000000000000000000000000000003d": "0x848930bd7ba8cac54661072113fb278869e07bb8587f91392933374d017bcbe1",
"0x000000000000000000000000000000000000000000000000000000000000003e": "0x8869ff2c22b28cc10510d9853292803328be4fb0e80495e8bb8d271f5b889636",
"0x000000000000000000000000000000000000000000000000000000000000003f": "0xb5fe28e79f1b850f8658246ce9b6a1e7b49fc06db7143e8fe0b4f2b0c5523a5c",
"0x0000000000000000000000000000000000000000000000000000000000000040": "0x985e929f70af28d0bdd1a90a808f977f597c7c778c489e98d3bd8910d31ac0f7"
}
}
}
So, we add the binary and storage tuples to the allocation of the genesis file.
Once set, we initialize as many execution clients as desired, using geth init
. Let's start with two:
geth init \
--datadir "./data/execution/0" \
./execution/genesis.json
geth init \
--datadir "./data/execution/1" \
./execution/genesis.json
Lastly, we get the genesis hash to be used as a reference for the consensus client setup later. For that, we run an execution node and get the genesis from it, e.g., attach to it and query eth.getBlockByNumber(0)
.
geth \
--networkid 39677693 \
--datadir "./data/execution/0" \
console
Note down the genesis hash for the consensus-layer configuration later and also get the node's enode
address to connect other execution-layer clients. Let's connect another one right away.
geth \
--networkid 39677693 \
--datadir "./data/execution/1" \
--authrpc.port 8651 \
--port 31303 \
--bootnodes "enode://39dc4161c55076d1245c7c8383996606e1d1d4a9006e58454bd8e2c139970269fa682560bfed2087bf1d1f5d5fc0d40f143b46398a8eaee343b43136f373f091@127.0.0.1:30303"
Persist the bootnodes in a text file for later use, e.g., bootnodes.txt
.
That's our execution-layer configuration. It currently runs two nodes locally that do nothing except wait for a consensus client to provide blocks.
Consensus-Layer Configuration
To create a new consensus-layer configuration, get the latest mainnet.yaml config from the consensus specs.
- Come up with a unique
CONFIG_NAME
, i.e., the name of our testnet, here:mergednet
. - Set the TTD to
0
and the terminal hash to the genesis hash we previously extracted from the execution-layer client. - Set the minimum genesis time to the genesis time of the execution layer or any desired time greater than that. Also, create a sensible genesis delay, e.g., two hours. We don't want to wait seven days!
- Set the fork versions to something custom to not conflict with mainnet, e.g.,
0x00677693
for genesis,0x01677693
for Altair, etc. Also, consider setting all upgrades to activate on genesis epoch0
. - Set the deposit chain and network ID to the previously created execution-layer network and match the deposit contract address to the one in the genesis, here:
39677693
,0x0420420420420420420420420420420420420420
.
In addition to the config.yaml
for the consensus layer, we also create auxiliary files for the deposit contract:
-
deploy_block.txt
containing the block number0
-
deposit_contract_block.txt
containing the execution genesis hash -
deposit_contract.txt
containing the deposit-contract address from the genesis allocation, here:0x0420420420420420420420420420420420420420
Lastly, before generating the genesis, we need to create validators that kick off the chain right from the start.
- We'll generate BIP-39 mnemonics for everyone who is going to run genesis validators and store them in a
mnemonics.yaml
file. Take a look at protolambda's notes for mnemonic-yaml formatting: protolambda/eth2-testnet-genesis#mnemonics. - Update the
MIN_GENESIS_ACTIVE_VALIDATOR_COUNT
to something sensible; we don't need 16k validators for our network yet. If you plan to run eight validators, set it to8
. - Lastly, use the eth2 testnet genesis tool to generate the
genesis.ssz
state for amerge
configuration:
eth2-testnet-genesis merge \
--config "./consensus/config.yaml" \
--eth1-config "./execution/genesis.json" \
--mnemonics "./consensus/mnemonic.yaml" \
--state-output "./consensus/genesis.ssz" \
--tranches-dir "./consensus/tranches"
The genesis state will contain the initial genesis validators, and there is no need to conduct actual deposits. To add more validators later, use the deposit contract at any time.
That's all for the configuration. We can run beacon nodes now and allow them to network and discover peers before genesis. Note that the network needs at least two peered beacon nodes; otherwise, the nodes will act as if they are offline and refuse to author blocks!
lodestar beacon \
--suggestedFeeRecipient "0xCaA29806044A08E533963b2e573C1230A2cd9a2d" \
--execution.urls "http://127.0.0.1:8551" \
--jwt-secret "./data/execution/0/geth/jwtsecret" \
--dataDir "./data/consensus/0" \
--paramsFile "./consensus/config.yaml" \
--genesisStateFile "./consensus/genesis.ssz" \
--enr.ip 127.0.0.1
Note we are setting the ENR IP to whatever we need (here: localhost) so that we can use the ENR as the initial bootnode record. Get it from the identity endpoint:
curl http://localhost:9596/eth/v1/node/identity
All ENRs can be persisted in a file such as bootnodes.txt
that we can pass to the beacon-chain clients later to bootstrap the networking.
lodestar beacon \
--suggestedFeeRecipient "0xCaA29806044A08E533963b2e573C1230A2cd9a2d" \
--execution.urls "http://127.0.0.1:8651" \
--jwt-secret "./data/execution/1/geth/jwtsecret" \
--dataDir "./data/consensus/1" \
--paramsFile "./consensus/config.yaml" \
--genesisStateFile "./consensus/genesis.ssz" \
--enr.ip 127.0.0.1 \
--rest.port 9696 \
--port 9100 \
--network.connectToDiscv5Bootnodes true \
--bootnodes "enr:-Ku4QFqWLadqfhKv7669IBdUwAilxPt9khrHqXVTqZjYdYtyNGTs4qeZslPf5Jx61QrKnMZ6-AcSgvu4zEcmSnnUrIIFh2F0dG5ldHOIAAAAAAAAAACEZXRoMpDYGrlYAmd2k___________gmlkgnY0gmlwhH8AAAGJc2VjcDI1NmsxoQIK5OOTyDgyoNl6TIqkWyap7VTqnIzlq40kE4N-250mV4N0Y3CCIyg"
We do this for as many beacon nodes as we want. Note that we need to enable discv5
bootnodes for our local network; otherwise, our clients will not peer.
That's it for our consensus-layer configuration. We have two Geth execution nodes running with two Lodestar beacon nodes connected with each other. Now, we have to launch the network.
Launch the Network
We have both execution-layer and consensus-layer clients running already. We can easily make sure they are running correctly by reading the logs. If they fail to authenticate or connect, there will be errors.
However, to kick off the network, we must ensure the validators are loaded and connected before genesis. If we fail to generate a chain within the first 32 slots, the clients will remain forever in a syncing state, potentially preventing long-range attacks. Therefore, if your beacon node is already past the 32nd slot, bump the genesis delay and redo the consensus-layer configuration.
We can use the deposit CLI to generate validator keypairs. Run ./deposit existing-mnemonic
and follow the instructions.
This generates deposit data and the actual keypairs. The deposit data can be discarded as we don't need to conduct any deposits. The keys can be imported to our validator client. Make sure also to provide a password.
lodestar validator \
--dataDir "./data/consensus/0" \
--suggestedFeeRecipient "0xCaA29806044A08E533963b2e573C1230A2cd9a2d" \
--graffiti "YOLO MERGEDNET GETH LODESTAR" \
--paramsFile "./consensus/config.yaml" \
--importKeystores "./consensus/validator_keys" \
--importKeystoresPassword "./consensus/validator_keys/password.txt"
Once the keys and passwords are imported, the validator client will wait to take on its duties. Once the minimum genesis time and genesis delay is passed, it will propose blocks and attestations.
That's it. That's our new Ethereum network, merged right from genesis.
Additional Resources
Credit goes to Gajinder, Parithosh, and Protolamda for the valuable pointers, tools, and documentation. Thank you so much for your contributions!
- github/protolambda/merge-genesis-tools: Testnet tooling to create a merge state at genesis.
- github/ethereum/consensus-specs: Ethereum proof-of-stake consensus specifications, including mainnet templates and deposit contract.
- notes/protolambda/merge-devnet-setup-guide: Multi-client post-merge Ethereum devnet setup by protolambda.
- github/ethereumjs/consensus-deployment-ansible: Ansible playbooks by Parithosh that allow us to do everything we did in this tutorial with one click ;)
- github/protolambda/eth2-testnet-genesis: Tool to create a genesis state for an beacon-chain testnet.
- github/ethereum/staking-deposit-cli: Secure key generation for beacon-chain deposits.
- github/ethereum/go-ethereum: Official Go implementation of the Ethereum protocol (execution).
- github/ChainSafe/lodestar: TypeScript implementation of an Ethereum consensus layer.
- github/eth-clients/holesovice: Preview: the first public merged-from-genesis Ethereum testnet.
Now that you scrolled to the end of this article, I will reward you with the entire configuration used in this tutorial: github.com/q9f/mergednet - I pedantically created one commit for each step.
Thanks for reading!
Top comments (12)
Thanks @q9 for this elaborate article with the github commits. It would help us a lot.
It was very easy to follow up and understand things along the way.
I got an error in the beacon and the validator when it publishes its first block at slot 0:
Error on submitPoolSyncCommitteeSignatures [0] slot=1, validatorIndex=0 PublishError.InsufficientPeers
but it looks like a normal error in lodestar that is waiting for a fix and not affecting the process.
I had another issue where the nodes stopped syncing after reproducing a couple of blocks, and it was fixed by your suggestion to put
--syncmode full
I got the same issue. How can I fix this?
Hi Afri,
First of all, thanks for this awesome tutorial and repository. It helped me understand a lot of things about the merge configurations.
I was trying to follow along with the article and I'm stuck at the point where the network won't kick off - I'm using Geth/Prysm (running two geth nodes connected to two beacon nodes, with the 8 validators connected to the first beacon node)
I'm using pretty much the same execution/beacon configurations in the article.
The only change I made was the
GENESIS_DELAY: 3600
Here's a screenshot of the beacon logs:
ibb.co/DCrQTNX
All the commands, and configs that I'm using are in this repo:
github.com/oone-world/merge-from-g...
Could you please help me with this?
Turns out the issue was that the
timestamp (in genesis.json) + GENESIS_DELAY (in config.yaml)
is in the past!This just torpedoes the whole thing!
For the
timestamp
ingenesis.json
have you usedMIN_GENESIS_TIME
or sum ofMIN_GENESIS_TIME+GENESIS_DELAY
?The
timestamp
ingenesis.json
is not important, you could also set it to January 1st, 1970. Important isMIN_GENESIS_TIME
andGENESIS_DELAY
.how to setup genesis delay and timestap in your genesis? im trying to change genesis delay 3200 and timestap the day now but its not synced.
eth. getBlockByNumber(0)
i took from the hash: "0x56c9b4417bafc42766888bae53959de8f0e5ac898eec6b30880c340f45d6ede9", and put this hash in deposit_contract_block.txt
then I tried to execute everything and run as you provide but I get a notification like this:
Node is syncing - Service Unavailable: Node is syncing - waiting for peers - Failed to obtain attester duty.
in the beacon node they get peer :
info: Searching peers - peers: 1 - slot: 3264964 (skipped 3264964) - head: 0 0 0x9e15…5549 - execution: valid(0x56c9…ede9) - finalized: 0x0000…0000:0
in geth I get something like this:
Beacon client online, but never received consensus updates. Please ensure your beacon client is operational to follow the chain!
slot: 3264964 (skipped 3264964)
indicates that something is wrong with your genesis timestamp. it should be less than 32 ideally.sorry, sir, what do you mean, can I just change my timestamp to number 32?
Genesis time should not be more than 32 slots behind current time. For example if your
SECONDS_PER_SLOT
value is 12, then genesis time must not be more than 384 seconds in the past when starting the network.There is a known issue (github.com/ChainSafe/lodestar/issu...) were Lodestar won't be able to sync due to a genesis time to far in the past and no peers to range sync historical data from.
sir, can you also tell how to make rollups for blockchains ?