Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
126 changes: 111 additions & 15 deletions scripts/setup-devnet.sh
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
# This script initializes a complete devnet environment including:
# - Validator keys and configuration
# - Genesis file with funded validator accounts
# - Docker Compose configuration
# - Docker Compose configuration (only when --ips is not specified)
#
# Usage:
# ./scripts/setup-devnet.sh [options]
Expand All @@ -17,13 +17,18 @@
# --network-id <ID> Network identifier (default: cipherbft-devnet-1)
# --output <DIR> Output directory (default: ./devnet)
# --extra-alloc <ADDR:ETH> Extra account allocation (can be repeated)
# --ips <IP1,IP2,...> Comma-separated list of validator IPs (one per validator).
# When provided, peer addresses in node configs will use these
# IPs instead of 127.0.0.1. Docker Compose is not generated.
# The number of IPs must match --validators.
# --force Overwrite existing devnet directory
# --help Show this help message
#
# Examples:
# ./scripts/setup-devnet.sh # Default 4 validators, 100 ETH each
# ./scripts/setup-devnet.sh -n 7 --balance 1000 # 7 validators, 1000 ETH each
# ./scripts/setup-devnet.sh --extra-alloc 0x123...abc:5000 # Add extra funded account
# ./scripts/setup-devnet.sh --ips 10.0.0.1,10.0.0.2,10.0.0.3,10.0.0.4 # Multi-machine devnet

set -e

Expand All @@ -39,6 +44,7 @@ NETWORK_ID="cipherbft-devnet-1"
OUTPUT_DIR="$PROJECT_ROOT/devnet"
EXTRA_ALLOC=()
FORCE=false
VALIDATOR_IPS="" # Comma-separated IPs; empty means use localhost

# Parse arguments
while [[ $# -gt 0 ]]; do
Expand Down Expand Up @@ -71,6 +77,10 @@ while [[ $# -gt 0 ]]; do
EXTRA_ALLOC+=("--extra-alloc" "$2")
shift 2
;;
--ips)
VALIDATOR_IPS="$2"
shift 2
;;
--force)
FORCE=true
shift
Expand Down Expand Up @@ -103,6 +113,18 @@ if [ -d "$OUTPUT_DIR" ]; then
fi
fi

# Validate --ips if provided
if [ -n "$VALIDATOR_IPS" ]; then
IFS=',' read -ra IP_ARRAY <<< "$VALIDATOR_IPS"
IP_COUNT=${#IP_ARRAY[@]}
if [ "$IP_COUNT" -ne "$NUM_VALIDATORS" ]; then
echo "Error: --ips requires exactly $NUM_VALIDATORS IP addresses (got $IP_COUNT)"
echo " Provided: $VALIDATOR_IPS"
echo " Use -n/--validators to change the validator count"
exit 1
fi
fi

echo "Setting up devnet with $NUM_VALIDATORS validators..."
echo ""
echo "Configuration:"
Expand All @@ -112,6 +134,9 @@ echo " Initial Balance: $INITIAL_BALANCE_ETH ETH per validator"
echo " Chain ID: $CHAIN_ID"
echo " Network ID: $NETWORK_ID"
echo " Output: $OUTPUT_DIR"
if [ -n "$VALIDATOR_IPS" ]; then
echo " Validator IPs: $VALIDATOR_IPS"
fi
if [ ${#EXTRA_ALLOC[@]} -gt 0 ]; then
echo " Extra Allocs: ${EXTRA_ALLOC[*]}"
fi
Expand Down Expand Up @@ -146,24 +171,95 @@ echo "Generating devnet configuration..."

echo ""

# Generate docker-compose configuration
echo "Generating Docker Compose configuration..."
"$SCRIPT_DIR/generate-compose.sh" "$OUTPUT_DIR" "$PROJECT_ROOT/docker"
# If custom IPs are provided, rewrite peer addresses in all node configs
if [ -n "$VALIDATOR_IPS" ]; then
echo "Updating peer addresses in node configs with provided IPs..."
IFS=',' read -ra IP_ARRAY <<< "$VALIDATOR_IPS"

for ((i=0; i<NUM_VALIDATORS; i++)); do
CONFIG="${OUTPUT_DIR}/node${i}/config/node.json"
if [ ! -f "$CONFIG" ]; then
echo "Warning: Config not found: $CONFIG"
continue
fi

python3 << PYEOF
import json, re

with open("$CONFIG") as f:
config = json.load(f)

ips = "$VALIDATOR_IPS".split(",")

for peer in config.get("peers", []):
for key in ["primary_addr", "consensus_addr"]:
if key in peer:
addr = peer[key]
match = re.match(r"127\.0\.0\.1:(\d+)", addr)
if match:
port = int(match.group(1))
peer_node_num = (port - 9000) // 10
if 0 <= peer_node_num < len(ips):
peer[key] = f"{ips[peer_node_num].strip()}:{port}"

if "worker_addrs" in peer:
new_addrs = []
for addr in peer["worker_addrs"]:
match = re.match(r"127\.0\.0\.1:(\d+)", addr)
if match:
port = int(match.group(1))
peer_node_num = (port - 9000) // 10
if 0 <= peer_node_num < len(ips):
new_addrs.append(f"{ips[peer_node_num].strip()}:{port}")
else:
new_addrs.append(addr)
else:
new_addrs.append(addr)
peer["worker_addrs"] = new_addrs

with open("$CONFIG", "w") as f:
json.dump(config, f, indent=2)
PYEOF

echo " Updated: node${i}/config/node.json"
done
echo ""
fi

# Generate docker-compose configuration (only for localhost mode)
if [ -z "$VALIDATOR_IPS" ]; then
echo "Generating Docker Compose configuration..."
"$SCRIPT_DIR/generate-compose.sh" "$OUTPUT_DIR" "$PROJECT_ROOT/docker"
echo ""
fi

echo ""
echo "Devnet setup complete!"
echo ""
echo "Validator accounts funded with:"
echo " - $INITIAL_STAKE_ETH ETH staked in deposit contract"
echo " - $INITIAL_BALANCE_ETH ETH available balance (for gas)"
echo ""
echo "Next steps:"
echo " Start devnet: ./scripts/start-devnet.sh"
echo " Reset state: ./scripts/reset-devnet.sh"
echo " Stop devnet: ./scripts/stop-devnet.sh"
echo ""
echo "RPC endpoints (after start):"
for ((i=0; i<NUM_VALIDATORS; i++)); do
PORT=$((8545 + i * 10))
echo " node$i: http://localhost:$PORT"
done

if [ -z "$VALIDATOR_IPS" ]; then
echo "Next steps:"
echo " Start devnet: ./scripts/start-devnet.sh"
echo " Reset state: ./scripts/reset-devnet.sh"
echo " Stop devnet: ./scripts/stop-devnet.sh"
echo ""
echo "RPC endpoints (after start):"
for ((i=0; i<NUM_VALIDATORS; i++)); do
PORT=$((8545 + i * 10))
echo " node$i: http://localhost:$PORT"
done
else
IFS=',' read -ra IP_ARRAY <<< "$VALIDATOR_IPS"
echo "Node configs are ready. Distribute each node directory to its machine:"
for ((i=0; i<NUM_VALIDATORS; i++)); do
PORT=$((8545 + i * 10))
IP="${IP_ARRAY[$i]}"
echo " node$i -> ${IP} (RPC: http://${IP}:${PORT})"
done
echo ""
echo "On each machine, copy the corresponding node directory and run:"
echo " cipherd start --config ./nodeN/config/node.json"
fi