#!/bin/bash set -exu set -o pipefail # Check if jq is installed if ! command -v jq &> /dev/null; then echo "Error: jq is not installed. Please install jq first." exit 1 fi # Check if curl is installed if ! command -v curl &> /dev/null; then echo "Error: curl is not installed. Please install curl first." exit 1 fi # NETWORK_DIR is where all files for the testnet will be stored, # including logs and storage NETWORK_DIR=./network # Change this number for your desired number of nodes NUM_NODES=2 # Port information. All ports will be incremented upon # with more validators to prevent port conflicts on a single machine GETH_HTTP_PORT=8000 GETH_WS_PORT=8100 GETH_AUTH_RPC_PORT=8200 GETH_METRICS_PORT=8300 GETH_NETWORK_PORT=8400 trap 'echo "Error on line $LINENO"; exit 1' ERR # Function to handle the cleanup cleanup() { echo "Caught Ctrl+C. Killing active background processes and exiting." kill $(jobs -p) # Kills all background processes started in this script exit } # Trap the SIGINT signal and call the cleanup function when it's caught trap 'cleanup' SIGINT # Set Paths for your binaries. Configure as you wish, particularly # if you're developing on a local fork of geth/prysm GETH_BINARY=./dependencies/go-ethereum/build/bin/geth PRYSM_CTL_BINARY=./dependencies/prysm/out/prysmctl # Get the ENODE from the first line of the logs for the bootnode bootnode_enode=$(head -n 1 $NETWORK_DIR/bootnode/bootnode.log) # Generate the genesis. This will generate validators based # on https://github.com/ethereum/eth2.0-pm/blob/a085c9870f3956d6228ed2a40cd37f0c6580ecd7/interop/mocked_start/README.md $PRYSM_CTL_BINARY testnet generate-genesis \ --fork=deneb \ --num-validators=$NUM_NODES \ --chain-config-file=./config.yml \ --geth-genesis-json-in=./genesis.json \ --output-ssz=$NETWORK_DIR/genesis.ssz \ --geth-genesis-json-out=$NETWORK_DIR/genesis.json # Create the validators in a loop # for (( i=0; i<$NUM_NODES; i++ )); do i=1 NODE_DIR=$NETWORK_DIR/node-$i mkdir -p $NODE_DIR/consensus mkdir -p $NODE_DIR/logs # We use an empty password. Do not do this in production geth_pw_file="$NODE_DIR/geth_password.txt" # Copy the same genesis and inital config the node's directories # All nodes must have the same genesis otherwise they will reject eachother cp ./config.yml $NODE_DIR/consensus/config.yml cp $NETWORK_DIR/genesis.ssz $NODE_DIR/consensus/genesis.ssz cp $NETWORK_DIR/genesis.json $NODE_DIR/execution/genesis.json # Initialize geth for this node. Geth uses the genesis.json to write some initial state $GETH_BINARY init \ --datadir=$NODE_DIR/execution \ $NODE_DIR/execution/genesis.json # Start geth execution client for this node $GETH_BINARY \ --networkid=${CHAIN_ID:-210597} \ --http \ --http.api=eth,net,web3 \ --http.addr=0.0.0.0 \ --http.corsdomain="*" \ --http.port=$((GETH_HTTP_PORT + i)) \ --port=$((GETH_NETWORK_PORT + i)) \ --metrics.port=$((GETH_METRICS_PORT + i)) \ --ws \ --ws.api=eth,net,web3 \ --ws.addr=0.0.0.0 \ --ws.origins="*" \ --ws.port=$((GETH_WS_PORT + i)) \ --authrpc.vhosts="*" \ --authrpc.addr=0.0.0.0 \ --authrpc.jwtsecret=$NODE_DIR/execution/jwtsecret \ --authrpc.port=$((GETH_AUTH_RPC_PORT + i)) \ --datadir=$NODE_DIR/execution \ --password=$geth_pw_file \ --bootnodes=$bootnode_enode \ --identity=node-$i \ --maxpendpeers=$NUM_NODES \ --verbosity=3 \ --syncmode=full > "$NETWORK_DIR/node-0/logs/geth.log"