Chain ID | Latest Version Tag | Sidecar version | Custom Port |
---|---|---|---|
gardia-4 | v5.16.10 | v5.16.9 | 182 |
Setup validator name
Replace YOUR_MONIKER_GOES_HERE with your validator name
MONIKER="YOUR_MONIKER_GOES_HERE"
Install dependencies
Update system and install build tools
sudo apt -q update
sudo apt -qy install curl git jq lz4 build-essential
sudo apt -qy upgrade
Install Go
sudo rm -rf /usr/local/go
curl -Ls https://go.dev/dl/go1.23.5.linux-amd64.tar.gz | sudo tar -xzf - -C /usr/local
eval $(echo 'export PATH=$PATH:/usr/local/go/bin' | sudo tee /etc/profile.d/golang.sh)
eval $(echo 'export PATH=$PATH:$HOME/go/bin' | tee -a $HOME/.profile)
Download and build binaries
# Clone project repository
cd $HOME
rm -rf zrchain
git clone https://github.com/zenrocklabs/zrchain.git
cd zrchain
git checkout v5.16.10
# Build binaries
make build
# Prepare binaries for Cosmovisor
mkdir -p $HOME/.zrchain/cosmovisor/genesis/bin
mv build/zenrockd $HOME/.zrchain/cosmovisor/genesis/bin/
rm -rf build
# Create application symlinks
ln -s $HOME/.zrchain/cosmovisor/genesis $HOME/.zrchain/cosmovisor/current -f
sudo ln -s $HOME/.zrchain/cosmovisor/current/bin/zenrockd /usr/local/bin/zenrockd -f
Install Cosmovisor and create a service
# Download and install Cosmovisor
go install cosmossdk.io/tools/cosmovisor/cmd/cosmovisor@v1.6.0
# Create service
sudo tee /etc/systemd/system/zenrock-testnet.service > /dev/null << EOF
[Unit]
Description=zenrock node service
After=network-online.target
[Service]
User=$USER
ExecStart=$(which cosmovisor) run start
Restart=on-failure
RestartSec=10
LimitNOFILE=65535
Environment="DAEMON_HOME=$HOME/.zrchain"
Environment="DAEMON_NAME=zenrockd"
Environment="UNSAFE_SKIP_BACKUP=true"
Environment="PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games:/snap/bin:$HOME/.zrchain/cosmovisor/current/bin"
[Install]
WantedBy=multi-user.target
EOF
sudo systemctl daemon-reload
sudo systemctl enable zenrock-testnet.service
Set node configuration
# Set node configuration
zenrockd config set client chain-id gardia-4
zenrockd config set client keyring-backend test
zenrockd config set client node tcp://localhost:18257
Initialize the node
# Initialize the node
zenrockd init $MONIKER --chain-id gardia-4
# Download genesis and addrbook
curl -Ls https://snapshots.kjnodes.com/zenrock-testnet/genesis.json > $HOME/.zrchain/config/genesis.json
curl -Ls https://snapshots.kjnodes.com/zenrock-testnet/addrbook.json > $HOME/.zrchain/config/addrbook.json
# Add seeds
sed -i -e "s|^seeds *=.*|seeds = \"3f472746f46493309650e5a033076689996c8881@zenrock-testnet.rpc.kjnodes.com:18259\"|" $HOME/.zrchain/config/config.toml
# Set minimum gas price
sed -i -e "s|^minimum-gas-prices *=.*|minimum-gas-prices = \"2.5urock\"|" $HOME/.zrchain/config/app.toml
# Set pruning
sed -i \
-e 's|^pruning *=.*|pruning = "custom"|' \
-e 's|^pruning-keep-recent *=.*|pruning-keep-recent = "100"|' \
-e 's|^pruning-keep-every *=.*|pruning-keep-every = "0"|' \
-e 's|^pruning-interval *=.*|pruning-interval = "19"|' \
$HOME/.zrchain/config/app.toml
# Set custom ports
sed -i -e "s%^proxy_app = \"tcp://127.0.0.1:26658\"%proxy_app = \"tcp://127.0.0.1:18258\"%; s%^laddr = \"tcp://127.0.0.1:26657\"%laddr = \"tcp://127.0.0.1:18257\"%; s%^pprof_laddr = \"localhost:6060\"%pprof_laddr = \"localhost:18260\"%; s%^laddr = \"tcp://0.0.0.0:26656\"%laddr = \"tcp://0.0.0.0:18256\"%; s%^prometheus_listen_addr = \":26660\"%prometheus_listen_addr = \":18266\"%" $HOME/.zrchain/config/config.toml
sed -i -e "s%^address = \"tcp://0.0.0.0:1317\"%address = \"tcp://0.0.0.0:18217\"%; s%^address = \":8080\"%address = \":18280\"%; s%^address = \"0.0.0.0:9090\"%address = \"0.0.0.0:18290\"%; s%^address = \"0.0.0.0:9091\"%address = \"0.0.0.0:18291\"%; s%:8545%:18245%; s%:8546%:18246%; s%:6065%:18265%" $HOME/.zrchain/config/app.toml
Download latest chain snapshot
curl -L https://snapshots.kjnodes.com/zenrock-testnet/snapshot_latest.tar.lz4 | tar -Ilz4 -xf - -C $HOME/.zrchain
[[ -f $HOME/.zrchain/data/upgrade-info.json ]] && cp $HOME/.zrchain/data/upgrade-info.json $HOME/.zrchain/cosmovisor/genesis/upgrade-info.json
Start service and check the logs
sudo systemctl start zenrock-testnet.service && sudo journalctl -u zenrock-testnet.service -f --no-hostname -o cat
Validator setup
To set up a validator, follow the steps below. Official validator setup instructions can be found at https://github.com/zenrocklabs/zenrock-validators.
Step 1: Create a wallet
First of all we will need to create wallet for our validator. You have two options for that.
Option 1 - Create new wallet
zenrockd keys add wallet
Option 2 - Recover existing wallet
zenrockd keys add wallet --recover
Save the mnemonic
output as this is the only way to recover your validator wallet in case you lose it!
To list your wallets use command below
zenrockd keys list
Step 2: Fund a wallet
To create validator you have to top up previously created wallet with tokens.
To check wallet balance use command below
zenrockd q bank balances $(zenrockd keys show wallet -a)
Step 3: Create validator
Ensure that you have updated the validator details to match your own.
zenrockd tx validation create-validator <(cat <<EOF
{
"pubkey": $(zenrockd comet show-validator),
"amount": "1000000urock",
"moniker": "YOUR_MONIKER_NAME",
"identity": "YOUR_KEYBASE_ID",
"website": "YOUR_WEBSITE_URL",
"security": "YOUR_SECURITY_EMAIL",
"details": "YOUR_DETAILS",
"commission-rate": "0.05",
"commission-max-rate": "0.20",
"commission-max-change-rate": "0.05",
"min-self-delegation": "1"
}
EOF
) \
--chain-id gardia-4 \
--from wallet \
--gas-adjustment 1.4 \
--gas auto \
--gas-prices 2.5urock \
-y
Save the $HOME/.zrchain/config/priv_validator_key.json
file as this is the only way to recover your validator signing key in case you lose it!
Sidecar setup
The validator sidecar service allows validators to vote on oracle data during the consensus process in CometBFT, ensuring that oracle values are secured by the same economic security as the blockchain through a super-majority consensus mechanism.
Learn more about Validation Module.
Step 1: Clone zenrock-validators repository
cd $HOME
rm -rf zenrock-validators
git clone https://github.com/zenrocklabs/zenrock-validators
Step 2: Generate keys
# Set key password
read -p "Enter password for the keys: " key_pass
# Create sidecar directories
mkdir -p $HOME/.zrchain/sidecar/bin
mkdir -p $HOME/.zrchain/sidecar/keys
# Build ecdsa binary
cd $HOME/zenrock-validators/utils/keygen/ecdsa && go build
# Build bls binary
cd $HOME/zenrock-validators/utils/keygen/bls && go build
# Generate ecdsa key
ecdsa_output_file=$HOME/.zrchain/sidecar/keys/ecdsa.key.json
ecdsa_creation=$($HOME/zenrock-validators/utils/keygen/ecdsa/ecdsa --password $key_pass -output-file $ecdsa_output_file)
ecdsa_address=$(echo "$ecdsa_creation" | grep "Public address" | cut -d: -f2)
# Generate bls key
bls_output_file=$HOME/.zrchain/sidecar/keys/bls.key.json
$HOME/zenrock-validators/utils/keygen/bls/bls --password $key_pass -output-file $bls_output_file
# Output
echo "ecdsa address: $ecdsa_address"
Step 3: Top up your wallet address
Please fund your wallet addresses with Holesky $ETH before proceeding further.
Step 4: Set operator configuration
Ensure that you have configured TESTNET_HOLESKY_ENDPOINT, MAINNET_ENDPOINT, ETH_RPC_URL, ETH_WS_URL with your specific values. You can use Quicknode.com to get api keys.
Declare variables
EIGEN_OPERATOR_CONFIG="$HOME/.zrchain/sidecar/eigen_operator_config.yaml"
TESTNET_HOLESKY_ENDPOINT="YOUR_TESTNET_HOLESKY_ENDPOINT"
MAINNET_ENDPOINT="YOUR_ETH_MAINNET_ENDPOINT"
OPERATOR_VALIDATOR_ADDRESS=$(zenrockd keys show wallet --bech val -a)
OPERATOR_ADDRESS=$ecdsa_address
ETH_RPC_URL="YOUR_TESTNET_HOLESKY_RPC"
ETH_WS_URL="YOUR_TESTNET_HOLESKY_WS"
ECDSA_KEY_PATH=$ecdsa_output_file
BLS_KEY_PATH=$bls_output_file
Generate eigen_operator_config.yaml configuration file
tee $HOME/.zrchain/sidecar/eigen_operator_config.yaml > /dev/null <<EOF
register_operator_on_startup: true
# this sets the logger level (true = info, false = debug)
production: true
operator_address: OPERATOR_ADDRESS
operator_validator_address: OPERATOR_VALIDATOR_ADDRESS
# EigenLayer Slasher contract address
# This is the address of the contracts which are deployed in the anvil saved state
# The saved eigenlayer state is located in tests/anvil/credible_squaring_avs_deployment_output.json
avs_registry_coordinator_address: 0xdc3A1b2a44D18c6B98a1d6c8C042247d2F5AC722
operator_state_retriever_address: 0xdB55356826a16DfFBD86ba334b84fC4E37113d97
# ETH RPC URL
eth_rpc_url: ETH_RPC_URL
eth_ws_url: ETH_WS_URL
# ECDSA key
ecdsa_private_key_store_path: ECDSA_KEY_PATH
# We are using bn254 curve for bls keys
bls_private_key_store_path: BLS_KEY_PATH
# address which the aggregator listens on for operator signed messages
aggregator_server_ip_port_address: avs-aggregator.gardia.zenrocklabs.io:8090
# avs node spec compliance https://eigen.nethermind.io/docs/spec/intro
eigen_metrics_ip_port_address: 0.0.0.0:9292
enable_metrics: true
node_api_ip_port_address: 0.0.0.0:9191
enable_node_api: true
# address of token to deposit tokens into when registering on startup
token_strategy_addr: 0x80528D6e9A2BAbFc766965E0E26d5aB08D9CFaF9
EOF
Generate config.yaml configuration file
tee $HOME/.zrchain/sidecar/config.yaml > /dev/null <<EOF
enabled: true
grpc_port: 9191
zrchain_rpc: "localhost:18290"
state_file: "cache.json"
operator_config: "$HOME/.zrchain/sidecar/eigen_operator_config.yaml"
network: "testnet"
eth_oracle:
rpc:
local: "http://127.0.0.1:8545"
testnet: TESTNET_HOLESKY_ENDPOINT # Replace this endpoint with a valid one
mainnet: MAINNET_ENDPOINT # Replace this endpoint with a valid one
contract_addrs:
service_manager: "0xa559CDb9e029fc4078170122eBf7A3e622a764E4"
price_feeds:
btc: "0xF4030086522a5bEEa4988F8cA5B36dbC97BeE88c"
eth: "0x5f4eC3Df9cbd43714FE2740f5E3616155c5b8419"
zenbtc:
controller:
testnet: "0xaCE3634AAd9bCC48ef6A194f360F7ACe51F7d9f1"
token:
ethereum:
testnet: "0xfA32a2D7546f8C7c229F94E693422A786DaE5E18"
network_name:
mainnet: "Ethereum Mainnet"
testnet: "Holesky Ethereum Testnet"
solana_rpc:
testnet: "https://api.testnet.solana.com"
mainnet: ""
proxy_rpc:
url: #To be provided by the Zenrock team
user: #To be provided by the Zenrock team
password: #To be provided by the Zenrock team
neutrino:
path: "$HOME/.zrchain/neutrino"
EOF
Replace variables in config.yaml
sed -i "s|TESTNET_HOLESKY_ENDPOINT|$TESTNET_HOLESKY_ENDPOINT|g" "$HOME/.zrchain/sidecar/config.yaml"
sed -i "s|MAINNET_ENDPOINT|$MAINNET_ENDPOINT|g" "$HOME/.zrchain/sidecar/config.yaml"
Replace variables in eigen_operator_config.yaml
sed -i "s|OPERATOR_VALIDATOR_ADDRESS|$OPERATOR_VALIDATOR_ADDRESS|g" "$HOME/.zrchain/sidecar/eigen_operator_config.yaml"
sed -i "s|OPERATOR_ADDRESS|$OPERATOR_ADDRESS|g" "$HOME/.zrchain/sidecar/eigen_operator_config.yaml"
sed -i "s|ETH_RPC_URL|$ETH_RPC_URL|g" "$HOME/.zrchain/sidecar/eigen_operator_config.yaml"
sed -i "s|ETH_WS_URL|$ETH_WS_URL|g" "$HOME/.zrchain/sidecar/eigen_operator_config.yaml"
sed -i "s|ECDSA_KEY_PATH|$ECDSA_KEY_PATH|g" "$HOME/.zrchain/sidecar/eigen_operator_config.yaml"
sed -i "s|BLS_KEY_PATH|$BLS_KEY_PATH|g" "$HOME/.zrchain/sidecar/eigen_operator_config.yaml"
Step 5: Download sidecar binary
wget -O $HOME/.zrchain/sidecar/bin/validator_sidecar https://github.com/zenrocklabs/zrchain/releases/download/v5.16.9/validator_sidecar
chmod +x $HOME/.zrchain/sidecar/bin/validator_sidecar
Step 6: Create and run sidecar service
Create service
sudo tee /etc/systemd/system/zenrock-testnet-sidecar.service > /dev/null <<EOF
[Unit]
Description=Validator Sidecar
After=network-online.target
[Service]
User=$USER
ExecStart=$HOME/.zrchain/sidecar/bin/validator_sidecar
WorkingDirectory=$HOME/.zrchain/sidecar
Restart=on-failure
RestartSec=30
LimitNOFILE=65535
Environment="OPERATOR_BLS_KEY_PASSWORD=$key_pass"
Environment="OPERATOR_ECDSA_KEY_PASSWORD=$key_pass"
Environment="SIDECAR_CONFIG_FILE=$HOME/.zrchain/sidecar/config.yaml"
[Install]
WantedBy=multi-user.target
EOF
Enable and start service
sudo systemctl daemon-reload
sudo systemctl enable zenrock-testnet-sidecar.service
sudo systemctl start zenrock-testnet-sidecar.service
Step 7: Check the service logs
To check service logs use command below:
journalctl -fu zenrock-testnet-sidecar.service -o cat
Successfull Log examples:
{"level":"info","ts":1727294139.4385705,"caller":"operator/operator.go:250","msg":"Operator info","operatorId":[144,89,34,19,95,158,123,120,47,228,59,114,85,73,150,39,84,119,143,77,154,173,85,210,132,206,213,195,7,190,250,142],"operatorAddr":"0x68e305548619Ce71D562b851ff1adfb7e5369DB3","operatorG1Pubkey":"E([20150260775620749168755223143919346367674724303860875751315024817211815113340,5713528518001336848987890055463332760351549074437348780451495739349376234320])","operatorG2Pubkey":"E([9400781597017099172228313635710883835447541071342639102400258381712924127278+17588199816725806065286885136698384247231626887315665039610705603333445204237*u,21507870890336379219932542686750816691453493327464905543429790078496913285917+3341052853010856303076683482759015503204225193006075252832111461015148222443*u])"}
2024/09/25 19:55:39 initialized operator
2024/09/25 19:55:39 starting operator
{"level":"info","ts":1727294139.4387212,"caller":"operator/operator.go:262","msg":"Starting operator."}
{"level":"info","ts":1727294139.438742,"caller":"nodeapi/nodeapi.go:104","msg":"Starting node api server at address 0.0.0.0:9191"}
{"level":"info","ts":1727294139.4388723,"caller":"metrics/eigenmetrics.go:81","msg":"Starting metrics server at port 0.0.0.0:9292"}
{"level":"info","ts":1727294139.4389389,"caller":"nodeapi/nodeapi.go:238","msg":"node api server running","addr":"0.0.0.0:9191"}
{"level":"info","ts":1727294139.5475569,"caller":"chainio/avs_subscriber.go:63","msg":"Subscribed to new TaskManager tasks"}
2024/09/25 19:55:45 Received AVS contract state for block 2407883
2024/09/25 19:55:45 Received prices: ETH/USD 2583.166191, ROCK/USD 0.000000
2024/09/25 19:56:00 Received prices: ETH/USD 2583.166191, ROCK/USD 0.000000
2024/09/25 19:56:00 Received AVS contract state for block 2407884
2024/09/25 19:56:15 Received prices: ETH/USD 2583.166191, ROCK/USD 0.000000
2024/09/25 19:56:15 Received AVS contract state for block 2407885
Step 8: Backup operator config and keys
To back up your sidecar configuration and keys, ensure you have a copy of the $HOME/.zrchain/sidecar
directory.