Build Your Own Blockchain ETH2.0 Beaconchain (Part1)

This article is for educational purposes only. A beacon chain is a future Ethereum 2.0 relay connecting shard chains. There's literally no value in running a beacon chain currently as there are no shards yet and there's no other functionality on the beacon chain available. But it's new technology, and who's not excited about playing around with it?

To bootstrap a new, custom beacon chain, we would need to cover the following topics:

The deposit contract ceremony The beacon chain transition specification The genesis event Bootstrapping the actual network Before we start, we need to understand that the beacon chain, which we will also call eth2 chain for now, cannot live without a legacy Ethereum chain which we will call eth1 chain. There will be a transition from eth1 to eth2 defined by an interface, the so called deposit contract.

The deposit contract ceremony

The deposit contract is a tool that allows gathering Ether deposits on the eth1 chain to enable validators proposing blocks on the eth2 chain later. How this will work in detail, will be covered later. For now, we need to understand that we need the deposit contract before doing anything else.

An example of the deposit contract is available as validator_registration.vy in the eth2.0-specs repository written in the Vyper contract language. The main function of interest of that fairly simple contract is -- surprise -- deposit(). But we'll cover that later.

We need three things now:
The compiled bytecode of the contract The ABI of the contract And an eth1 testnet to deploy it to To compile the contract, we need to install Vyper locally or use an Vyper Online Compiler. The online-compiler comes in pretty handy in some cases, but for such an important piece of infrastructure, we'll use the native compiler locally. It's simple as that:

❯ vyper validator_registration.vy 

Output Codes

0x740100000000000000000000000000000000000000006020526f7fffffffffffffffffffffffffffffff6040527fffffffffffffffffffffffffffffffff8000000000000000000000000000000060605274012a05f1fffffffffffffffffffffffffdabf41c006080527ffffffffffffffffffffffffed5fa0e000000000000000000000000000000000060a052341561009857600080fd5b6101406000601f818352015b600061014051602081106100b757600080fd5b600260c052602060c020015460208261016001015260208101905061014051602081106100e357600080fd5b600260c052602060c020015460208261016001015260208101905080610160526101609050602060c0825160208401600060025af161012157600080fd5b60c05190506101405160016060518183018060405190131561014257600080fd5b809190121561015057600080fd5b905090506020811061016157600080fd5b600260c052602060c02001555b81516001018083528114156100a4575b50506110a256600436101561000d57610f17565b600035601c52740100000000000000000000000000000000000000006020526f7fffffffffffffffffffffffffffffff6040527fffffffffffffffffffffffffffffffff8000000000000000000000000000000060605274012a05f1fffffffffffffffffffffffffdabf41c006080527ffffffffffffffffffffffffed5fa0e000000000000000000000000000000000060a05260001561020e575b6101605261014052600061018052610140516101a0526101c060006008818352015b61018051600881811b90509050610180526101805160ff6101a051168181830110156100f657600080fd5b80820190509050610180526101a0517ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff88160081c905090506101a0525b81516001018083528114156100cb575b505060186008602082066101e0016020828401111561016157600080fd5b60208061020082610180600060045af15050818152809050905090508051602001806102a08284600060045af161019757600080fd5b50506102a051806102c001818260206001820306601f820103905003368237505060206102805260406102a0510160206001820306601f8201039050610260525b6000610260511115156101ea57610206565b60206102605103610280015160206102605103610260526101d8565b610160515650005b63c5f2892f60005114156104a257341561022757600080fd5b6000610140526101405161016052600154610180526101a060006020818352015b60016001610180511614156102c95760006101a0516020811061026a57600080fd5b600060c052602060c02001546020826102400101526020810190506101605160208261024001015260208101905080610240526102409050602060c0825160208401600060025af16102bb57600080fd5b60c051905061016052610337565b6000610160516020826101c00101526020810190506101a051602081106102ef57600080fd5b600260c052602060c02001546020826101c0010152602081019050806101c0526101c09050602060c0825160208401600060025af161032d57600080fd5b60c0519050610160525b61018080516002808061034957600080fd5b8204905090508152505b8151600101808352811415610248575b505060006101605160208261046001015260208101905061014051610160516101805163806732896102e0526001546103005261030051600658016100a9565b506103605260006103c0525b6103605160206001820306601f82010390506103c0511015156103d1576103ea565b6103c05161038001526103c0516020016103c0526103af565b61018052610160526101405261036060088060208461046001018260208501600060045af150508051820191505060006018602082066103e0016020828401111561043457600080fd5b60208061040082610140600060045af150508181528090509050905060188060208461046001018260208501600060045af150508051820191505080610460526104609050602060c0825160208401600060025af161049257600080fd5b60c051905060005260206000f350005b63621fd130600051141561057f5734156104bb57600080fd5b6380673289610140526001546101605261016051600658016100a9565b506101c0526000610220525b6101c05160206001820306601f8201039050610220511015156105065761051f565b610220516101e0015261022051602001610220526104e4565b6101c08051602001806102808284600060045af161053c57600080fd5b505061028051806102a001818260206001820306601f82010390500336823750506020610260526040610280510160206001820306601f8201039050610260f350005b63228951186000511415610f165760506004356004016101403760306004356004013511156105ad57600080fd5b60406024356004016101c03760206024356004013511156105cd57600080fd5b60806044356004016102203760606044356004013511156105ed57600080fd5b63ffffffff600154106105ff57600080fd5b34633b9aca00808061061057600080fd5b8204905090506102c052633b9aca006102c051101561062e57600080fd5b6030610140511461063e57600080fd5b60206101c0511461064e57600080fd5b6060610220511461065e57600080fd5b610140610340525b6103405151602061034051016103405261034061034051101561068857610666565b6380673289610360526102c0516103805261038051600658016100a9565b506103e0526000610440525b6103e05160206001820306601f8201039050610440511015156106d4576106ed565b61044051610400015261044051602001610440526106b2565b610320610340525b6103405152602061034051036103405261014061034051101515610718576106f5565b6103e08051602001806102e08284600060045af161073557600080fd5b5050610140610460525b610460515160206104605101610460526104606104605110156107615761073f565b6380673289610480526001546104a0526104a051600658016100a9565b50610500526000610560525b6105005160206001820306601f8201039050610560511015156107ac576107c5565b610560516105200152610560516020016105605261078a565b610440610460525b61046051526020610460510361046052610140610460511015156107f0576107cd565b6105008051602001806105808284600060045af161080d57600080fd5b505060a06105e0526105e051610620526101408051602001806105e051610620018284600060045af161083f57600080fd5b50506105e05161062001518060206105e051610620010101818260206001820306601f820103905003368237505060206105e051610620015160206001820306601f82010390506105e05101016105e0526105e051610640526101c08051602001806105e051610620018284600060045af16108ba57600080fd5b50506105e05161062001518060206105e051610620010101818260206001820306601f820103905003368237505060206105e051610620015160206001820306601f82010390506105e05101016105e0526105e051610660526102e08051602001806105e051610620018284600060045af161093557600080fd5b50506105e05161062001518060206105e051610620010101818260206001820306601f820103905003368237505060206105e051610620015160206001820306601f82010390506105e05101016105e0526105e051610680526102208051602001806105e051610620018284600060045af16109b057600080fd5b50506105e05161062001518060206105e051610620010101818260206001820306601f820103905003368237505060206105e051610620015160206001820306601f82010390506105e05101016105e0526105e0516106a0526105808051602001806105e051610620018284600060045af1610a2b57600080fd5b50506105e05161062001518060206105e051610620010101818260206001820306601f820103905003368237505060206105e051610620015160206001820306601f82010390506105e05101016105e0527f649bbc62d0e31342afea4e5cd82d4049e7e1ee912fc0889aa790803be39038c56105e051610620a160006106c052600061014060308060208461078001018260208501600060045af150508051820191505060006010602082066107000160208284011115610aeb57600080fd5b602080610720826106c0600060045af150508181528090509050905060108060208461078001018260208501600060045af150508051820191505080610780526107809050602060c0825160208401600060025af1610b4957600080fd5b60c05190506106e0526000600060406020820661082001610220518284011115610b7257600080fd5b6060806108408260206020880688030161022001600060045af1505081815280905090509050602060c0825160208401600060025af1610bb157600080fd5b60c0519050602082610a20010152602081019050600060406020602082066108e001610220518284011115610be557600080fd5b6060806109008260206020880688030161022001600060045af15050818152809050905090506020806020846109a001018260208501600060045af15050805182019150506106c0516020826109a0010152602081019050806109a0526109a09050602060c0825160208401600060025af1610c6057600080fd5b60c0519050602082610a2001015260208101905080610a2052610a209050602060c0825160208401600060025af1610c9757600080fd5b60c051905061080052600060006106e051602082610ac00101526020810190506101c0602080602084610ac001018260208501600060045af150508051820191505080610ac052610ac09050602060c0825160208401600060025af1610cfc57600080fd5b60c0519050602082610c4001015260208101905060006102e0600880602084610bc001018260208501600060045af15050805182019150506000601860208206610b400160208284011115610d5057600080fd5b602080610b60826106c0600060045af1505081815280905090509050601880602084610bc001018260208501600060045af150508051820191505061080051602082610bc001015260208101905080610bc052610bc09050602060c0825160208401600060025af1610dc157600080fd5b60c0519050602082610c4001015260208101905080610c4052610c409050602060c0825160208401600060025af1610df857600080fd5b60c0519050610aa052606435610aa05114610e1257600080fd5b600180546001818183011015610e2757600080fd5b80820190509050815550600154610cc052610ce060006020818352015b60016001610cc051161415610e7957610aa051610ce05160208110610e6857600080fd5b600060c052602060c0200155610f12565b6000610ce05160208110610e8c57600080fd5b600060c052602060c0200154602082610d00010152602081019050610aa051602082610d0001015260208101905080610d0052610d009050602060c0825160208401600060025af1610edd57600080fd5b60c0519050610aa052610cc0805160028080610ef857600080fd5b8204905090508152505b8151600101808352811415610e44575b5050005b5b60006000fd5b6101856110a2036101856000396101856110a2036000f3

This is our compiled bytecode which can be deployed later. Now we need the ABI:

❯ vyper -f abi validator_registration.vy 

Output Code

[
    {
        "name": "DepositEvent",
        "inputs": [
            {
                "type": "bytes",
                "name": "pubkey",
                "indexed": false
            },
            {
                "type": "bytes",
                "name": "withdrawal_credentials",
                "indexed": false
            },
            {
                "type": "bytes",
                "name": "amount",
                "indexed": false
            },
            {
                "type": "bytes",
                "name": "signature",
                "indexed": false
            },
            {
                "type": "bytes",
                "name": "index",
                "indexed": false
            }
        ],
        "anonymous": false,
        "type": "event"
    },
    {
        "outputs": [],
        "inputs": [],
        "constant": false,
        "payable": false,
        "type": "constructor"
    },
    {
        "name": "get_deposit_root",
        "outputs": [
            {
                "type": "bytes32",
                "name": ""
            }
        ],
        "inputs": [],
        "constant": true,
        "payable": false,
        "type": "function",
        "gas": 112305
    },
    {
        "name": "get_deposit_count",
        "outputs": [
            {
                "type": "bytes",
                "name": ""
            }
        ],
        "inputs": [],
        "constant": true,
        "payable": false,
        "type": "function",
        "gas": 14558
    },
    {
        "name": "deposit",
        "outputs": [],
        "inputs": [
            {
                "type": "bytes",
                "name": "pubkey"
            },
            {
                "type": "bytes",
                "name": "withdrawal_credentials"
            },
            {
                "type": "bytes",
                "name": "signature"
            },
            {
                "type": "bytes32",
                "name": "deposit_data_root"
            }
        ],
        "constant": false,
        "payable": true,
        "type": "function",
        "gas": 1331065
    }
]

The ABI will allow us later to interact with the deposit contract once it is deployed. As testnet, we will use the Görli Testnet. We will go on straight deploying the bytecode from above and have a contract address: 0xaA888248144Bc5d584a7f400839d0D912F21C39A.

That's it, for a testnet at least. For a mainnet, this process will involve an actual ceremony to determine social consensus on the contract code and the official instance to use. For the sake of easing eth2 clients with eth1 synchronization, we also note down two values:

The deposit contract deploy block: 2355031 The deposit contract deploy date: 1584316800 (March/16, 2020)

The beacon chain transition specification

Now that we have an instance of the deposit contract deployed to a public eth1 network, we'll start configuring our eth2 network transitions. For that, we can template our future network on the existing specification for the official Ethereum 2.0 mainnet, namely mainnet.yaml.

We'll take that specification and modify it slightly to ease running a testnet with just a couple of validators:

DEPOSIT_CONTRACT_ADDRESS: 0xaA888248144Bc5d584a7f400839d0D912F21C39A
- We deployed this contract in the previous step.

GENESIS_FORK_VERSION: 0x00000539
- We just change this to something that's not 0x0 to distinguish our network from mainnet.

BLS_WITHDRAWAL_PREFIX: 0x05
- We change this to something that's not 0x0 to not conflict with mainnet.

MIN_GENESIS_ACTIVE_VALIDATOR_COUNT: 16
- We want to be able to bootstrap the network with as little as 16 validators.

MIN_GENESIS_TIME: 1584316800
- This is our day we deployed the deposit contract, the genesis cannot happen before (Mar/16, 2020).

MIN_DEPOSIT_AMOUNT: 100000000
- We reduce the minimum deposit amount to 0.1 GöETH.

MAX_EFFECTIVE_BALANCE: 3200000000
- We reduce the maximum effective balance to 3.2 GöETH.

EJECTION_BALANCE: 1600000000
- We reduce the ejection balance to 1.6 GöETH.

EFFECTIVE_BALANCE_INCREMENT: 100000000
- We reduce the effective balance increment to 0.1 GöETH.

ETH1_FOLLOW_DISTANCE: 16
- We change the eth1 follow distance to 16.

MIN_GENESIS_DELAY: 3600
- We reduce the minimum genesis delay to one hour.

The Genesis Event

After fully configuring the network, we still don't have a network, yet. What's missing is the genesis state. The genesis is determined by a certain starting condition which is defined in the clients and by our previous network specification. It mainly breaks down to the following criteria:

The minimum number of active validator deposits: We configured 16 and the genesis event will not happen before the deposit contract registered 16 valid deposits. The minimum genesis time: We configured March/16 2020 and the genesis event will not be happening before that date. The minimum genesis delay: We configured to delay the genesis state by at least one hour. The genesis will not happen before we don't have 16 validator deposits and one hour passed. Once these conditions are met, an eth2 client will be able to extract the genesis state from the eth1 chain and validators can start proposing blocks.

The Lighthouse client not only comes with beacon chain and a validator client, but also with a command line tool lcli that assists us in generating keypairs for validators and sending the required validator deposit directly to the deposit contract on the eth1 chain.

First, we instruct our lighthouse node how to configure the new testnet:

lcli --spec mainnet new-testnet \ # template new testnet on mainnet
--deposit-contract-address 0xaA888248144Bc5d584a7f400839d0D912F21C39A \
--deposit-contract-deploy-block 2355031 \
--effective-balance-increment 100000000 \
--ejection-balance 1600000000 \
--eth1-follow-distance 16 \
--genesis-fork-version 0x00000539 \
--max-effective-balance 3200000000 \
--min-deposit-amount 100000000 \
--min-genesis-active-validator-count 16 \
--min-genesis-delay 3600 \
--min-genesis-time 1584316800 \
--testnet-dir ~/.lighthouse/schlesi

These are the values we defined in the previous step and have now been written to our testnet directory ~/.lighthouse/schlesi for further use by the Lighthouse client. To run a beacon node, simply point it to the config:

lighthouse bn \ # lighthouse beacon node
--testnet-dir ~/.lighthouse/schlesi \
--spec mainnet \
--eth1-endpoint http://127.0.0.1:8545 \
--http

Now, our beacon node monitors our local Görli node on localhost port :8545 and waits that something happens on the deposit contract.

We can use lighthouse now to make validator deposits:

lighthouse account validator new \
--testnet-dir ~/.lighthouse/schlesi \
--spec mainnet \
--send-deposits \
--eth1-endpoint http://127.0.0.1:8545 \
--password ./password.txt \
--deposit-value 3200000000 random 

This will do the following things:

  1. It reads our testnet spec in ~/.lighthouse/schlesi mainly to know about the deposit contract.

  2. It generates a keypair for a validator in ~/.lighthouse/validators.

  3. It generates a transaction and broadcasts it to the eth1 network using your local node. Important to note here, is that you have enough testnet Ether on the first account of your local Görli node (eth.accounts[0]) and that you provide a valid password to unlock that account.

This does not work with Parity Ethereum, so we used Geth instead. Also, to have both, HTTP-RPC APIs exposed and being able to unlock the accounts, one would have to pass the --allow-insecure-unlock flag to the Görli node. Please, use this with caution!

Once this was done, the node will give positive feedback:

Mar 18 13:53:48.174 INFO Validator deposit successful            

validator_voting_pubkey: 0x82ad6def329bf94f06dae46b3222a3cb9baf2a68e1bf6e1dadaac5bb47dfe6690e2c3222b6256e17a4ec1bdbec6dbd65, 

eth1_tx_hash: 0x13cb9c913d946b222cb595f4bb42bd3e7d11e985d1d4dc3c50faacdc8e42e053

This is how a deposit transaction to our contract looks like. Repeat this step 16 times to meet the minimum genesis deposit threshold. The beacon chain closely monitoring the deposit contract notices the met threshold:

Mar 18 13:55:42.991 INFO Minimum genesis deposit count met       block_number: 2366961, deposit_count: 16, service: beacon

Mar 18 13:55:57.647 INFO Deposit contract genesis complete       validator_count: 16, eth1_block_height: 2366961, service: beacon

Mar 18 13:55:57.680 INFO Beacon chain initialized head_slot: 0, 
head_block: 0xd0ad…1b0d, head_state: 0xdadf…c6bc, service: beacon

The genesis state can be extracted from the eth1 contract using lcli:

lcli eth1-genesis \
--testnet-dir ~/.lighthouse/schlesi \
--eth1-endpoint http://127.0.0.1:8545

Bootstrapping the actual network

Now that the genesis event happened, we need two last things to bootstrap the actual network:

  1. Validators proposing new blocks

  2. Bootnode records allowing for other nodes to connect

Fortunately, both is available in Lighthouse. To run your 16 validators configured locally, simply run:

lighthouse vc --allow-unsynced

The --allow-unsynced option is required as we do not have any other peers yet and simply allow the validator to start proposing blocks right away.

Mar 18 13:57:20.871 WARN Ethereum 2.0 is pre-release. This software is experimental.

Mar 18 13:57:20.876 INFO Starting validator client datadir: "/home/user/.lighthouse/validators", beacon_node: http://localhost:5052/

Mar 18 13:57:20.893 INFO Connected to beacon node version: Lighthouse/v0.1.0-unstable/x86_64-linux

Mar 18 13:57:20.900 INFO Starting node prior to genesis          seconds_to_wait: 3759

The validator node now waits at least one hour before proposing blocks as defined in our MIN_GENESIS_DELAY.

Meanwhile, we can launch more beacon nodes and start wiring them. To connect them, we take the Ethereum Node Record (ENR) from each of the nodes and add them to our testnet configuration. The ENR looks as follows:

Mar 18 13:55:57.692 INFO ENR Initialised seq: 1, enr: enr:-Iu4QN6QRhX7abcUZ6E5eV9iSNwG0FGWWifEevi98EDGhoPVt3e82j9KC2H7DiLtDGnj03MMrs707fEBgmlkgnY0gmlwhH8AAAGJc2VjcDI1NmsxoQL4Lu3nwG5diXILEh3LiAauCrNgtoTJxGZQER33BTDMKoN0Y3CCIyiDdWRwgiMo, service: network

Our testnet configuration in ~/.lighthouse/schlesi contains a boot_enr.yaml file which we use to collect ENR of known peers to ease discovery. We simply add all known ENR of our beacon-bootnodes to that file which allows the network to have a first point of entry when adding new beacon nodes. The file could look like that:

- "enr:-Iu4QGCUN3RjOLZCab4LLqlOqnnOB9BspIE30Nj5gQGoY00ZXCIW2PCXuGqDLHEPZJK9NO8SFZlKzFF-5rSbTyPqksoBgmlkgnY0gmlwhH8AAAGJc2VjcDI1NmsxoQJmy_5ZkaIFozyMd3gPygG1lVLQONuTL4C1j_smkZ9WmoN0Y3CCIyiDdWRwgiMo"

- "enr:-Iu4QCKxIZVqkBMGHOxfeDvY8Yp0V0uq2MQ8wFS2tQGMfQ1YVuER_WeyVmqKawz6H4JE1OVeN52_kJUdZmkuvpyETjMBgmlkgnY0gmlwhH8AAAGJc2VjcDI1NmsxoQNsaKrbnhjMgAcpHREHrZiCA7sXyEOokOck_1oc3zZMG4N0Y3CCJRyDdWRwgiUc"

- "enr:-Iu4QN6QRhX7abcUZ6E5eV9-AIUSXpNBSytiSNwG0FGWWifEevi98EDGhoPVt3e82j9KC2H7DiLtDGnj03MMrs707fEBgmlkgnY0gmlwhH8AAAGJc2VjcDI1NmsxoQL4Lu3nwG5diXILEh3LiAauCrNgtoTJxGZQER33BTDMKoN0Y3CCIyiDdWRwgiMo"

That's it. We have our own, custom beacon chain now running on Lighthouse.

Mar 21 16:38:26.000 INFO Synced slot: 425, epoch: 13, finalized_epoch: 11, finalized_root: 0x41fc…1ac0, peers: 3, service: slot_notifier

Mar 21 16:38:32.226 INFO Block from local validator              block_slot: 426, block_root: 0xa2ef…e552, service: http

Mar 21 16:38:38.000 INFO Synced slot: 426, epoch: 13, finalized_epoch: 11, finalized_root: 0x41fc…1ac0, peers: 3, service: slot_notifier

Mar 21 16:38:44.218 INFO Block from local validator              block_slot: 427, block_root: 0x563c…b946, service: http

Mar 21 16:38:48.018 INFO Attestation from local validator slot: 427, index: 
0, source: 12, target: 12, service: http

Mar 21 16:38:50.000 INFO Synced slot: 427, epoch: 13, finalized_epoch: 11, finalized_root: 0x41fc…1ac0, peers: 3, service: slot_notifier

Mar 21 16:38:56.249 INFO Block from local validator              block_slot: 428, block_root: 0x8229…eb17, service: http

Mar 21 16:39:02.000 INFO Synced slot: 428, epoch: 13, finalized_epoch: 11, finalized_root: 0x41fc…1ac0, peers: 3, service: slot_notifier


It's important to note, that this network is permissionless. Everyone with 3.2 Görli ETH can generate a validator keypair and make a deposit to the Schlesi validator registration contract. Everyone can be part running validator nodes or beacon chain nodes by simply connecting to the provided ENR. Why don't you give it a try?

Soon, hopefully, we will be able to add other clients to our network, such as PrysmNimbusTeku, or Trinity. The multi-client testnet phase is soon to be upon us.

Full Credit : Afri q9f - Head Of Protocol ChainSafe

Subscribe to Avenlabs
Receive the latest updates directly to your inbox.
Mint this entry as an NFT to add it to your collection.
Verification
This entry has been permanently stored onchain and signed by its creator.