A validator node on the post-merge Ethereum consists of execution and consensus clients communicating over EngineAPI. If you need to disable the execution client, for example, to prune Geth and free some space up, you will have to use an external execution layer.
This guide explains how to temporarily connect a consensus client to an external execution client and prune the primary database without losing attestations and rewards. We will do this using Geth and Prysm as examples.
What Is Pruning?
A snap-sync’d Geth node takes up about 650 GB on the hard disk. Over time, the blockchain grows, the disk fills with data, and the node refuses to work.
The developers of Geth have provided a way to clean the database up and return it to its original size: pruning. Geth regularly snapshots the database, and pruning removes old data and brings the database back to its original 650 GB.
Pruning takes about four hours. During this time, Geth finds target trie nodes, removes stale trie nodes, and forms a new database.
To prune an ETH 2.0 validator, follow this algorithm:
- Prepare an external node.
- Install and synchronize the execution and consensus clients on the external node.
- Stop the execution and consensus clients on the local node.
- Connect the consensus client on the local node to the execution client on the external node.
- To prune the execution client on the local node, wait for completion.
- Stop the consensus client, and reconnect it to the execution client on the local node.
- Run the execution and consensus clients on the local node.
Sounds like a heart transplant surgery, doesn’t it?
A Guide on Pruning Geth With the Prysm Consensus Client
Everstake uses two Linux machines: a local node (ov6) (with both the Geth execution client and the Prysm consensus client) and an external node (ov7) with the same clients.
Configure the firewall of the external node to be able to connect to it on port 8551:
sudo iptables -A INPUT -i $(ip route get 8.8.8.8 | awk '{ print $5 }' | head -n 1) -p tcp --dport 8551 -s IP ov6 -j ACCEPT -m comment --comment "EL for ov6”
Check if the IP rule has been added:
sudo iptables -vnL
Configure the geth.service systemd script on external node ov7. Add --authrpc.addr
0.0.0.0 to the ExecStart line:
ExecStart=geth --syncmode snap --cache 4096 --http --http.addr 0.0.0.0 --http.api "engine,eth,net,rpc,web3,debug,txpool,admin" --ws --ws.addr="0.0.0.0" --ws.origins "*" --authrpc.vhosts="localhost" --authrpc.jwtsecret=/mnt/operational/lido/jwt/jwt.hex --http.vhosts=* --metrics.addr 0.0.0.0 --metrics.port 7070 --metrics --txpool.accountslots 64 --txpool.globalslots 8192 --txpool.accountqueue 128 --vmodule "rpc=5" --datadir "/mnt/operational/lido/geth”
↓↓↓
ExecStart=geth --syncmode snap --cache 4096 --http --http.addr 0.0.0.0 --authrpc.addr 0.0.0.0 --http.api "engine,eth,net,rpc,web3,debug,txpool,admin" --ws --ws.addr="0.0.0.0" --ws.origins "*" --authrpc.vhosts="localhost" --authrpc.jwtsecret=/mnt/operational/lido/jwt/jwt.hex --http.vhosts=* --metrics.addr 0.0.0.0 --metrics.port 7070 --metrics --txpool.accountslots 64 --txpool.globalslots 8192 --txpool.accountqueue 128 --vmodule "rpc=5" --datadir "/mnt/operational/lido/geth"
Refresh the systemctl daemon:
sudo systemctl daemon-reload
Stop Prysm on the external node:
sudo systemctl stop ethereum2-node.service
Make sure Prysm has stopped and Geth is listening to 0.0.0.0:8511:
sudo netstat -tlpn
Launch the Geth systemd script on the external node:
sudo systemctl restart geth.service
Go to the local node. Once there, stop both Prysm and Geth:
sudo systemctl stop ethereum2-node.service
sudo systemctl stop geth.service
Configure Prysm to connect to the external node. In the Prysm systemd script, change --execution-endpoint
to the IP address of the external node (ov7 in our case):
ExecStart=/mnt/operational/lido/prysm/prysm.sh beacon-chain --datadir /mnt/operational/lido/prysm/data --p2p-host-ip ${HOST} --execution-endpoint=http://localhost:8551 --http-mev-relay=http://localhost:18550 --jwt-secret=/mnt/operational/lido/jwt/jwt.hex --min-sync-peers 7 --p2p-max-peers 100 --suggested-fee-recipient=0x7f396Ef9F10C7beB11D01f2EA4a99a5787993474 --monitoring-host 0.0.0.0 --accept-terms-of-use
↓↓↓
ExecStart=/mnt/operational/lido/prysm/prysm.sh beacon-chain --datadir /mnt/operational/lido/prysm/data --p2p-host-ip ${HOST} --execution-endpoint=http://IP-OV7:8551 --http-mev-relay=http://localhost:18550 --jwt-secret=/mnt/operational/lido/jwt/jwt.hex --min-sync-peers 7 --p2p-max-peers 100 --suggested-fee-recipient=0x7f396Ef9F10C7beB11D01f2EA4a99a5787993474 --monitoring-host 0.0.0.0 --accept-terms-of-use
Refresh the systemctl daemon:
sudo systemctl daemon-reload
On the local node, back up the JWT token, e.g., in jwt.hex.bak
:
cp /mnt/operational/lido/jwt/jwt.hex /mnt/operational/lido/jwt/jwt.hex.bak
Copy the JWT token from the external node, paste it into jwt.hex
on the local node, and save the changes:
cat /mnt/operational/lido/jwt/jwt.hex
nano /mnt/operational/lido/jwt/jwt.hex
Launch Prysm on the local node:
sudo systemctl start ethereum2-node.service
Check the logs for the connection to the external node:
eternal el-geth cat /mnt/operational/lido/prysm/stderr.txt |grep 8551
Check that Geth on the external node and Prysm on the local node catch up with the headblock.
Then prune Geth on the local node (Double-check that Geth is not running!):
tmux new -s PRUNE
geth snapshot prune-state --datadir "/mnt/operational/lido/geth”
Pruning will complete after two or three hours. Then revert the changes and launch the local validator:
- Stop both Prysm and Geth.
- Return the JWT from
jwt.hex.bak
tojwt.hex
on the local node. - Return
--execution-endpoint=http://localhost:8551
to the Prysm systemd. - Run Geth and then Prysm on the local node.
- Remove
--authrpc.addr 0.0.0.0
- Close the 8551 IP port on the external node.
Conclusion
Pruning enables Ethereum validators with the Geth client to keep a 1 TB hard disk node running stably.
Pruning was easy in the Ethereum PoW days, but with the move to PoS, one has to switch the consensus client to an external execution client for pruning. This is relatively easy, and one can get used to changing clients if they do it regularly.
Our instructions describe pruning with the Geth and Prysm consensus clients, but you can do the same with Teku, Lighthouse, and other consensus clients for Ethereum. Just study the configuration files, figure out what IP to change, and disable and enable the clients in the correct order.