-
Notifications
You must be signed in to change notification settings - Fork 26
/
testnet.sh
executable file
·227 lines (193 loc) · 8.32 KB
/
testnet.sh
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
#!/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_BOOTNODE_PORT=30301
GETH_HTTP_PORT=8000
GETH_WS_PORT=8100
GETH_AUTH_RPC_PORT=8200
GETH_METRICS_PORT=8300
GETH_NETWORK_PORT=8400
PRYSM_BEACON_RPC_PORT=4000
PRYSM_BEACON_GRPC_GATEWAY_PORT=4100
PRYSM_BEACON_P2P_TCP_PORT=4200
PRYSM_BEACON_P2P_UDP_PORT=4300
PRYSM_BEACON_MONITORING_PORT=4400
PRYSM_VALIDATOR_RPC_PORT=7000
PRYSM_VALIDATOR_GRPC_GATEWAY_PORT=7100
PRYSM_VALIDATOR_MONITORING_PORT=7200
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
# Reset the data from any previous runs and kill any hanging runtimes
rm -rf "$NETWORK_DIR" || echo "no network directory"
mkdir -p $NETWORK_DIR
pkill geth || echo "No existing geth processes"
pkill beacon-chain || echo "No existing beacon-chain processes"
pkill validator || echo "No existing validator processes"
pkill bootnode || echo "No existing bootnode processes"
# 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
GETH_BOOTNODE_BINARY=./dependencies/go-ethereum/build/bin/bootnode
PRYSM_CTL_BINARY=./dependencies/prysm/bazel-bin/cmd/prysmctl/prysmctl_/prysmctl
PRYSM_BEACON_BINARY=./dependencies/prysm/bazel-bin/cmd/beacon-chain/beacon-chain_/beacon-chain
PRYSM_VALIDATOR_BINARY=./dependencies/prysm/bazel-bin/cmd/validator/validator_/validator
# Create the bootnode for execution client peer discovery.
# Not a production grade bootnode. Does not do peer discovery for consensus client
mkdir -p $NETWORK_DIR/bootnode
$GETH_BOOTNODE_BINARY -genkey $NETWORK_DIR/bootnode/nodekey
$GETH_BOOTNODE_BINARY \
-nodekey $NETWORK_DIR/bootnode/nodekey \
-addr=:$GETH_BOOTNODE_PORT \
-verbosity=5 > "$NETWORK_DIR/bootnode/bootnode.log" 2>&1 &
sleep 2
# Get the ENODE from the first line of the logs for the bootnode
bootnode_enode=$(head -n 1 $NETWORK_DIR/bootnode/bootnode.log)
# Check if the line begins with "enode"
if [[ "$bootnode_enode" == enode* ]]; then
echo "bootnode enode is: $bootnode_enode"
else
echo "The bootnode enode was not found. Exiting."
exit 1
fi
# 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
# The prysm bootstrap node is set after the first loop, as the first
# node is the bootstrap node. This is used for consensus client discovery
PRYSM_BOOTSTRAP_NODE=
# Calculate how many nodes to wait for to be in sync with. Not a hard rule
MIN_SYNC_PEERS=$((NUM_NODES/2))
echo $MIN_SYNC_PEERS is minimum number of synced peers required
# Create the validators in a loop
for (( i=0; i<$NUM_NODES; i++ )); do
NODE_DIR=$NETWORK_DIR/node-$i
mkdir -p $NODE_DIR/execution
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"
echo "" > "$geth_pw_file"
# 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
# Create the secret keys for this node and other account details
$GETH_BINARY account new --datadir "$NODE_DIR/execution" --password "$geth_pw_file"
# 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:-32382} \
--http \
--http.api=eth,net,web3 \
--http.addr=127.0.0.1 \
--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=127.0.0.1 \
--ws.origins="*" \
--ws.port=$((GETH_WS_PORT + i)) \
--authrpc.vhosts="*" \
--authrpc.addr=127.0.0.1 \
--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 > "$NODE_DIR/logs/geth.log" 2>&1 &
sleep 5
# Start prysm consensus client for this node
$PRYSM_BEACON_BINARY \
--datadir=$NODE_DIR/consensus/beacondata \
--min-sync-peers=$MIN_SYNC_PEERS \
--genesis-state=$NODE_DIR/consensus/genesis.ssz \
--bootstrap-node=$PRYSM_BOOTSTRAP_NODE \
--interop-eth1data-votes \
--chain-config-file=$NODE_DIR/consensus/config.yml \
--contract-deployment-block=0 \
--chain-id=${CHAIN_ID:-32382} \
--rpc-host=127.0.0.1 \
--rpc-port=$((PRYSM_BEACON_RPC_PORT + i)) \
--grpc-gateway-host=127.0.0.1 \
--grpc-gateway-port=$((PRYSM_BEACON_GRPC_GATEWAY_PORT + i)) \
--execution-endpoint=http://localhost:$((GETH_AUTH_RPC_PORT + i)) \
--accept-terms-of-use \
--jwt-secret=$NODE_DIR/execution/jwtsecret \
--suggested-fee-recipient=0x123463a4b065722e99115d6c222f267d9cabb524 \
--minimum-peers-per-subnet=0 \
--p2p-tcp-port=$((PRYSM_BEACON_P2P_TCP_PORT + i)) \
--p2p-udp-port=$((PRYSM_BEACON_P2P_UDP_PORT + i)) \
--monitoring-port=$((PRYSM_BEACON_MONITORING_PORT + i)) \
--verbosity=info \
--slasher \
--enable-debug-rpc-endpoints > "$NODE_DIR/logs/beacon.log" 2>&1 &
# Start prysm validator for this node. Each validator node will
# manage 1 validator
$PRYSM_VALIDATOR_BINARY \
--beacon-rpc-provider=localhost:$((PRYSM_BEACON_RPC_PORT + i)) \
--datadir=$NODE_DIR/consensus/validatordata \
--accept-terms-of-use \
--interop-num-validators=1 \
--interop-start-index=$i \
--rpc-port=$((PRYSM_VALIDATOR_RPC_PORT + i)) \
--grpc-gateway-port=$((PRYSM_VALIDATOR_GRPC_GATEWAY_PORT + i)) \
--monitoring-port=$((PRYSM_VALIDATOR_MONITORING_PORT + i)) \
--graffiti="node-$i" \
--chain-config-file=$NODE_DIR/consensus/config.yml > "$NODE_DIR/logs/validator.log" 2>&1 &
# Check if the PRYSM_BOOTSTRAP_NODE variable is already set
if [[ -z "${PRYSM_BOOTSTRAP_NODE}" ]]; then
sleep 5 # sleep to let the prysm node set up
# If PRYSM_BOOTSTRAP_NODE is not set, execute the command and capture the result into the variable
# This allows subsequent nodes to discover the first node, treating it as the bootnode
PRYSM_BOOTSTRAP_NODE=$(curl -s localhost:4100/eth/v1/node/identity | jq -r '.data.enr')
# Check if the result starts with enr
if [[ $PRYSM_BOOTSTRAP_NODE == enr* ]]; then
echo "PRYSM_BOOTSTRAP_NODE is valid: $PRYSM_BOOTSTRAP_NODE"
else
echo "PRYSM_BOOTSTRAP_NODE does NOT start with enr"
exit 1
fi
fi
done
# You might want to change this if you want to tail logs for other nodes
# Logs for all nodes can be found in `./network/node-*/logs`
tail -f "$NETWORK_DIR/node-0/logs/geth.log"