Migrate a validator
This process should only be used if you want to split an existing validator private key into multiple private key shares for use in a Distributed Validator Cluster. If your existing validator is not properly shut down before the Distributed Validator starts, your validator may be slashed.
If you are starting a new validator, you should follow a quickstart guide instead.
Split an existing Ethereum validator key into multiple key shares for use in an Obol Distributed Validator Cluster.
Pre-requisites
- Ensure you have the existing validator keystores (the ones to split) and passwords.
- Ensure you have docker installed.
- Make sure
docker
is running before executing the commands below. - If you use MEV-Boost, you must either:
- Turn off your MEV-Boost client before you split your keys, or;
- Temporarily use a relay you won't be using when running the Distributed Validator; to prevent registering for MEV with a timestamp more recent than the one Charon prepares at the moment of key splitting.
Step 1. Prepare the existing keystore files
Create a folder to hold the encrypted keystores, along with the passwords to decrypt them.
# Create a folder
mkdir split_keys
Copy the existing validator keystore.json
files into this new folder. Alongside them, with a matching filename but ending with .txt
should be the password to the keystore (e.g.: keystore-0.json
, keystore-0.txt
). The files must start with keystore*
.
At the end of this process, you should have a tree like this:
├── split_keys
│ ├── keystore-0.json
│ ├── keystore-0.txt
│ ├── keystore-1.json
│ ├── keystore-1.txt
│ ...
│ ├── keystore-N.json
│ ├── keystore-N.txt
Step 2. Split the keys using the charon docker command
Run the following docker command to split the keys (for mainnet):
CHARON_VERSION= # E.g. v1.1.1
CLUSTER_NAME= # The name of the cluster you want to create.
WITHDRAWAL_ADDRESS= # The address you want to use for withdrawals (this is just for accuracy in your lock file, you can't change a withdrawal address for a validator that has already been deposited)
FEE_RECIPIENT_ADDRESS= # The address you want to use for block reward and MEV payments.
NODES= # The number of nodes in the cluster.
docker run --rm -v $(pwd):/opt/charon obolnetwork/charon:${CHARON_VERSION} create cluster \
--name="${CLUSTER_NAME}" \
--withdrawal-addresses="${WITHDRAWAL_ADDRESS}" \
--fee-recipient-addresses="${FEE_RECIPIENT_ADDRESS}" \
--split-existing-keys \
--split-keys-dir=/opt/charon/split_keys \
--nodes ${NODES} \
--network mainnet
The above command will create validator_keys
along with cluster-lock.json
in ./cluster
for each node.
Command output:
***************** WARNING: Splitting keys **********************
Please make sure any existing validator has been shut down for
at least 2 finalised epochs before starting the Charon cluster,
otherwise slashing could occur.
****************************************************************
Created Charon cluster:
--split-existing-keys=true
./cluster/
├─ node[0-*]/ # Directory for each node
│ ├─ charon-enr-private-key # Charon networking private key for node authentication
│ ├─ cluster-lock.json # Cluster lock defines the cluster lock file which is signed by all nodes
│ ├─ validator_keys # Validator keystores and password
│ │ ├─ keystore-*.json # Validator private share key for duty signing
│ │ ├─ keystore-*.txt # Keystore password files for keystore-*.json
These split keys can now be used to start a Charon cluster.
Step 3. (Optional) Encrypt artifacts for distribution
Within each folder are the encrypted private key shares, along with the decryption passwords. To transmit these folders to the operators/machines where they will run, it might be prudent to encrypt the folder as a .zip
to transport them.
# For each folder in ./cluster/ encrypt it with a different password
zip -er node1.zip ./cluster/node1/
# Repeat for node2,...,nodeN.