TODO before publishing
This guide is meant to be a starting point and provides a mid-level summary of the required steps. It is not intended to be a beginner’s guide, so copying and running commands from here may not work without some tweaking.
The testnet is meant to mimic a chain that is post-merge. Therefore, the genesis state will be in a merged state. The chain will have to go through a fork on both EL and CL at the same time. This fork is called Shanghai on the EL side and Capella on the CL side. These two events will be triggered simultaneously.
This is achieved by EL forking at a specific time rather than at a block number, and CL forking at a specific epoch.
The Zhejiang testnet aims to test the following features:
A future testnet will be launched in Jan '23 that impliments all the final Shanghai EIPs.
More details about these other changes can be found here
The JSON-RPC endpoint, faucet, and other tooling URLs can be found on https://zhejiang.ethpandaops.io/
The partial withdrawals feature will be automatically triggered on all addresses that already have 0x01
withdrawal credentials set. For those that use 0x00
(legacy BLS credentials), they will need to first change their credentials from 0x00
to 0x01
before this feature can be tested.
Changing 0x00
to 0x01
credential is currently only supported by a single tool ethdo. Hopefully, over time there will be multiple different tools that offer this functionality. A detailed description of how to convert your address and trigger a full exit is described in another guide (all instructions done with docker!) that can be found here.
Client Name | Git Branch | Docker image |
---|---|---|
Lighthouse | capella | sigp/lighthouse:capella |
Teku | master | consensys/teku:develop |
Lodestar | unstable | chainsafe/lodestar:next |
Prysm | capella | gcr.io/prysmaticlabs/prysm/beacon-chain:capella-6b2721 gcr.io/prysmaticlabs/prysm/validator:HEAD-29dfca |
Nimbus | unstable | ethpandaops/nimbus:merge-aff0505 |
Client Name | Git Branch | Docker image |
---|---|---|
Geth | lightclient/withdrawals-timestamp | ethpandaops/geth:withdrawal-devnet-1-9c4a92b |
Nethermind | master | nethermindeth/nethermind:withdrawals |
Besu | siladu/shanghaitime-forkid-withdrawals-evm | siladu/besu:22.10.3-SNAPSHOT-openjdk-11-debug-withdrawals-evm-0455b22 |
EthereumJS | master | g11tech/ethereumjs:latest |
Erigon | devel | thorax/erigon:devel |
Download the configs from https://github.com/ethpandaops/withdrawals-testnet/tree/master/withdrawal-devnet-1/custom_config_data.
git clone https://github.com/ethpandaops/withdrawals-testnet.git
cd withdrawals-testnet/withdrawal-devnet-0/custom_config_data
Generate the JWT secret with openssl
openssl rand -hex 32 | tr -d "\n" > "/tmp/jwtsecret"
This file needs to be passed to both the Execution Client and the Consensus Client. If you do not specify a JWT secret, then the execution and/or consensus layer client will automatically generate one for you. You will then have to specify this secret in the Consensus Layer client.
Pre-requisites: git, make, go, gcc
.
Clone and build the withdrawals-timestamp
branch of Geth (lightclient’s repo)
git clone -b withdrawals-timestamp https://github.com/lightclient/go-ethereum.git
cd go-ethereum
make geth
cd ..
From the custom_config_data
folder start the client
./go-ethereum/build/bin/geth --datadir "geth-datadir" init genesis.json
./go-ethereum/build/bin/geth \
--datadir "geth-datadir" \
--http --http.api="engine,eth,web3,net,debug" \
--ws --ws.api="engine,eth,web3,net,debug" \
--http.corsdomain "*" \
--networkid=1337805 \
--syncmode=full \
--authrpc.jwtsecret=/tmp/jwtsecret \
--bootnodes "enode://b896e651b9d100ece367bf6a360b22b7e3032f542c1bffcc102f94e79a44d74b227bbcf67218e25d375ddd50beaf229135d3e42a260717c3d82eb897ce8b9069@167.71.60.16:30303"
Pre-requisites: git, dotnet
Please ensure you have Node 12.x+ installed.
Clone and build the feature/shanghai-eip-4895-withdrawals
branch of Nethermind
git clone --recursive -b feature/shanghai-eip-4895-withdrawals https://github.com/NethermindEth/nethermind.git
cd nethermind/src/Nethermind
dotnet build Nethermind.sln -c Release
From the custom_config_data/nethermind/src/Nethermind/
folder start the client
cd Nethermind.Runner
dotnet run -c Release -- \
--config withdrawals_devnet \
--datadir="../../../../nethermind-datadir" \
--JsonRpc.Host=0.0.0.0 \
--JsonRpc.JwtSecretFile=/tmp/jwtsecret \
--Init.ChainSpecPath="../../../../chainspec.json" \
--Network.StaticPeers="enode://b896e651b9d100ece367bf6a360b22b7e3032f542c1bffcc102f94e79a44d74b227bbcf67218e25d375ddd50beaf229135d3e42a260717c3d82eb897ce8b9069@167.71.60.16:30303"
Pre-requisites: git, jvm
Clone and build the shanghaitime-forkid-withdrawals-evm
branch of Besu
git clone --recursive -b shanghaitime-forkid-withdrawals https://github.com/siladu/besu.git
cd besu
./gradlew installDist
cd ..
From the custom_config_data
folder start the client
besu/build/install/besu/bin/besu \
--network=1337805 \
--data-path="besu-datadir" \
--genesis-file="besu.json" \
--rpc-http-enabled=true \
--rpc-http-host="0.0.0.0" \
--rpc-http-cors-origins="*"\
--rpc-ws-enabled=true \
--rpc-ws-host="0.0.0.0" \
--host-allowlist="*" \
--engine-host-allowlist="*"\
--engine-jwt-enabled=true \
--engine-jwt-secret=/tmp/jwtsecret \
--bootnodes="enode://b896e651b9d100ece367bf6a360b22b7e3032f542c1bffcc102f94e79a44d74b227bbcf67218e25d375ddd50beaf229135d3e42a260717c3d82eb897ce8b9069@167.71.60.16:30303"
Pre-requisites: git, node, npm
Please ensure you have Node 18.x+ installed.
Clone and build from source
git clone --depth 1 --branch master https://github.com/ethereumjs/ethereumjs-monorepo.git
cd ethereumjs-monorepo
npm i
From the custom_config_data
folder start the client
cd packages/client
npm run client:start -- \
--datadir ../../../ethereumjs-datadir \
--gethGenesis ../../../genesis.json \
--saveReceipts \
--rpc --rpcport=8545 \
--ws \
--jwt-secret=/tmp/jwtsecret \
--rpcEngine --rpcEnginePort=8551 \
--bootnodes="enode://b896e651b9d100ece367bf6a360b22b7e3032f542c1bffcc102f94e79a44d74b227bbcf67218e25d375ddd50beaf229135d3e42a260717c3d82eb897ce8b9069@167.71.60.16:30303"
This will create a secret in ethereumjs-datadir/jwtsecret, you will need to provide this secret to the CL client.
Pre-requisites: git, go
Clone and build from source
git clone --branch=devel https://github.com/ledgerwatch/erigon
cd erigon
make erigon rpcdaemon
cd ..
From the custom_config_data
folder start the client
### Initialize database
./erigon/build/bin/erigon init \
--datadir=erigon-datadir genesis.json
### run Erigon
./erigon/build/bin/erigon \
--datadir erigon-datadir \
--externalcl \
--networkid=1337805 \
--authrpc.jwtsecret=/tmp/jwtsecret \
--http --http.api=engine,net,eth \
--bootnodes="enode://b896e651b9d100ece367bf6a360b22b7e3032f542c1bffcc102f94e79a44d74b227bbcf67218e25d375ddd50beaf229135d3e42a260717c3d82eb897ce8b9069@167.71.60.16:30303"
After starting the client, you will be able to interact with the client using the following ports:
Pre-requisites: git, rust
Please ensure you have RustC 1.59.x+ installed.
Clone and build from source
git clone -b capella https://github.com/sigp/lighthouse.git
cd lighthouse
make
cd ..
From the custom_config_data
folder start the client
lighthouse \
--testnet-dir="." \
bn \
--datadir lighthouse-dir \
--eth1 \
--http \
--http-allow-sync-stalled \
--execution-endpoints http://127.0.0.1:8551 \
--enr-udp-port=9000 \
--enr-tcp-port=9000 \
--discovery-port=9000 \
--jwt-secrets="/tmp/jwtsecret" \
--boot-nodes="enr:-Iq4QJk4WqRkjsX5c2CXtOra6HnxN-BMXnWhmhEQO9Bn9iABTJGdjUOurM7Btj1ouKaFkvTRoju5vz2GPmVON2dffQKGAX53x8JigmlkgnY0gmlwhLKAlv6Jc2VjcDI1NmsxoQK6S-Cii_KmfFdUJL2TANL3ksaKUnNXvTCv1tLwXs0QgIN1ZHCCIyk" \
--suggested-fee-recipient=<enter-eth-address-here>
Pre-requisites: git, nodejs, yarn
More info about how to install dependencies can be found here
Clone and build the client
git clone -b unstable https://github.com/chainsafe/lodestar.git
cd lodestar
yarn install --ignore-optional
yarn run build
From the custom_config_data/lodestar
folder start the client
./lodestar beacon \
--dataDir="../lodestar-beacondata" \
--paramsFile="../config.yaml" \
--genesisStateFile="../genesis.ssz" \
--execution.urls="http://127.0.0.1:8551" \
--jwt-secret="/tmp/jwtsecret" \
--bootnodes="enr:-Iq4QJk4WqRkjsX5c2CXtOra6HnxN-BMXnWhmhEQO9Bn9iABTJGdjUOurM7Btj1ouKaFkvTRoju5vz2GPmVON2dffQKGAX53x8JigmlkgnY0gmlwhLKAlv6Jc2VjcDI1NmsxoQK6S-Cii_KmfFdUJL2TANL3ksaKUnNXvTCv1tLwXs0QgIN1ZHCCIyk" \
--suggestedFeeRecipient=<enter-eth-address-here>
Pre-requisites: git, java
Ensure Java 11 or above is installed (Ubuntu: sudo apt install default-jre).
git clone -b asdf https://github.com/ConsenSys/teku.git
cd teku
./gradlew installDist
cd ..
The teku executable is now available in ./teku/build/install/teku/bin/teku. You can also use the pre-built distribution or the consensys/teku:develop docker image.
From the custom_config_data
folder start the client
./teku/build/install/teku/bin/teku \
--data-path="teku-datadir" \
--network="config.yaml" \
--initial-state="genesis.ssz" \
--ee-endpoint="http://localhost:8551" \
--Xee-version=kilnv2 \
--ee-jwt-secret-file="/tmp/jwtsecret" \
--p2p-discovery-bootnodes="enr:-Iq4QJk4WqRkjsX5c2CXtOra6HnxN-BMXnWhmhEQO9Bn9iABTJGdjUOurM7Btj1ouKaFkvTRoju5vz2GPmVON2dffQKGAX53x8JigmlkgnY0gmlwhLKAlv6Jc2VjcDI1NmsxoQK6S-Cii_KmfFdUJL2TANL3ksaKUnNXvTCv1tLwXs0QgIN1ZHCCIyk" \
--validators-proposer-default-fee-recipient=<Enter-eth-address-here>
Pre-requisites: git, bazel
Ensure bazel 5.3.+ is installed.
mkdir -p prysm-dir
export genesis=$PWD/genesis.ssz
export prysmdir=$PWD/prysm-dir
export config=$PWD/config.yaml
git clone -b capella https://github.com/prysmaticlabs/prysm.git
cd prysm
bazel build //cmd/beacon-chain:beacon-chain
From the custom_config_data/prysm
folder start the client
bazel run //cmd/beacon-chain -- \
--accept-terms-of-use=true \
--genesis-state=$genesis \
--datadir=$prysmdir \
--chain-config-file=$config \
--execution-endpoint=http://localhost:8551 \
--jwt-secret=/tmp/jwtsecret \
--bootstrap-node=enr:-Iq4QJk4WqRkjsX5c2CXtOra6HnxN-BMXnWhmhEQO9Bn9iABTJGdjUOurM7Btj1ouKaFkvTRoju5vz2GPmVON2dffQKGAX53x8JigmlkgnY0gmlwhLKAlv6Jc2VjcDI1NmsxoQK6S-Cii_KmfFdUJL2TANL3ksaKUnNXvTCv1tLwXs0QgIN1ZHCCIyk \
--suggested-fee-recipient=<Enter-eth-address-here>
Pre-requisites: git, make, gcc
Ensure that the websocket related flags (–ws) are present on your EL (e.g: Geth). Nethermind enables websockets by default. Nimbus can use either http or ws.
Clone and build from source (use branch unstable)
git clone --branch=unstable https://github.com/status-im/nimbus-eth2.git
cd nimbus-eth2
make update
make -j4 nimbus_beacon_node
cd ..
Start the client
nimbus-eth2/build/nimbus_beacon_node \
--data-dir=./nimbus-datadir\
--jwt-secret=/tmp/jwtsecret \
--web3-url=http://127.0.0.1:8551 \
--rest \
--network=./ \
--bootstrap-node=enr:-Iq4QJk4WqRkjsX5c2CXtOra6HnxN-BMXnWhmhEQO9Bn9iABTJGdjUOurM7Btj1ouKaFkvTRoju5vz2GPmVON2dffQKGAX53x8JigmlkgnY0gmlwhLKAlv6Jc2VjcDI1NmsxoQK6S-Cii_KmfFdUJL2TANL3ksaKUnNXvTCv1tLwXs0QgIN1ZHCCIyk \
--suggested-fee-recipient=<Enter-eth-address-here>
Loading embed note