From 2b7f29f44cb12bded413a83d7850c97af2c5a644 Mon Sep 17 00:00:00 2001 From: David Boreham Date: Thu, 25 Apr 2024 06:23:30 -0600 Subject: [PATCH] Migrate from SO repo --- compose/docker-compose-fixturenet-eth.yml | 132 +++++++++++++++ compose/docker-compose-foundry.yml | 9 + config/fixturenet-eth/fixturenet-eth.env | 28 ++++ .../cerc-fixturenet-eth-genesis/Dockerfile | 25 +++ .../cerc-fixturenet-eth-genesis/build.sh | 8 + .../genesis/Makefile | 13 ++ .../genesis/accounts/import_keys.sh | 17 ++ .../genesis/accounts/mnemonic_to_csv.py | 16 ++ .../genesis/el/build_el.sh | 16 ++ .../genesis/el/el-config.yaml | 17 ++ .../cerc-fixturenet-eth-geth/Dockerfile | 21 +++ .../cerc-fixturenet-eth-geth/build.sh | 8 + .../cerc-fixturenet-eth-geth/run-el.sh | 154 ++++++++++++++++++ .../cerc-fixturenet-eth-lighthouse/Dockerfile | 30 ++++ .../cerc-fixturenet-eth-lighthouse/build.sh | 8 + .../genesis/Makefile | 13 ++ .../genesis/cl/beacon_node.sh | 41 +++++ .../genesis/cl/bootnode.sh | 39 +++++ .../genesis/cl/build_cl.sh | 56 +++++++ .../genesis/cl/ready.sh | 10 ++ .../genesis/cl/reset_genesis_time.sh | 20 +++ .../genesis/cl/validator_client.sh | 31 ++++ .../genesis/cl/vars.env | 58 +++++++ .../cerc-fixturenet-eth-lighthouse/run-cl.sh | 80 +++++++++ .../scripts/export-ethdb.sh | 50 ++++++ .../scripts/status-internal.sh | 10 ++ .../scripts/status.sh | 97 +++++++++++ container-build/cerc-go-ethereum/build.sh | 4 + container-build/cerc-lighthouse-cli/build.sh | 7 + container-build/cerc-lighthouse/Dockerfile | 10 ++ container-build/cerc-lighthouse/build.sh | 9 + .../cerc-lighthouse/start-lighthouse.sh | 9 + stacks/fixturenet-eth/README.md | 124 ++++++++++++++ stacks/fixturenet-eth/stack.yml | 18 ++ 34 files changed, 1188 insertions(+) create mode 100644 compose/docker-compose-fixturenet-eth.yml create mode 100644 compose/docker-compose-foundry.yml create mode 100644 config/fixturenet-eth/fixturenet-eth.env create mode 100644 container-build/cerc-fixturenet-eth-genesis/Dockerfile create mode 100755 container-build/cerc-fixturenet-eth-genesis/build.sh create mode 100644 container-build/cerc-fixturenet-eth-genesis/genesis/Makefile create mode 100755 container-build/cerc-fixturenet-eth-genesis/genesis/accounts/import_keys.sh create mode 100644 container-build/cerc-fixturenet-eth-genesis/genesis/accounts/mnemonic_to_csv.py create mode 100755 container-build/cerc-fixturenet-eth-genesis/genesis/el/build_el.sh create mode 100644 container-build/cerc-fixturenet-eth-genesis/genesis/el/el-config.yaml create mode 100644 container-build/cerc-fixturenet-eth-geth/Dockerfile create mode 100755 container-build/cerc-fixturenet-eth-geth/build.sh create mode 100755 container-build/cerc-fixturenet-eth-geth/run-el.sh create mode 100644 container-build/cerc-fixturenet-eth-lighthouse/Dockerfile create mode 100755 container-build/cerc-fixturenet-eth-lighthouse/build.sh create mode 100644 container-build/cerc-fixturenet-eth-lighthouse/genesis/Makefile create mode 100755 container-build/cerc-fixturenet-eth-lighthouse/genesis/cl/beacon_node.sh create mode 100755 container-build/cerc-fixturenet-eth-lighthouse/genesis/cl/bootnode.sh create mode 100755 container-build/cerc-fixturenet-eth-lighthouse/genesis/cl/build_cl.sh create mode 100755 container-build/cerc-fixturenet-eth-lighthouse/genesis/cl/ready.sh create mode 100755 container-build/cerc-fixturenet-eth-lighthouse/genesis/cl/reset_genesis_time.sh create mode 100755 container-build/cerc-fixturenet-eth-lighthouse/genesis/cl/validator_client.sh create mode 100644 container-build/cerc-fixturenet-eth-lighthouse/genesis/cl/vars.env create mode 100755 container-build/cerc-fixturenet-eth-lighthouse/run-cl.sh create mode 100755 container-build/cerc-fixturenet-eth-lighthouse/scripts/export-ethdb.sh create mode 100755 container-build/cerc-fixturenet-eth-lighthouse/scripts/status-internal.sh create mode 100755 container-build/cerc-fixturenet-eth-lighthouse/scripts/status.sh create mode 100755 container-build/cerc-go-ethereum/build.sh create mode 100755 container-build/cerc-lighthouse-cli/build.sh create mode 100644 container-build/cerc-lighthouse/Dockerfile create mode 100755 container-build/cerc-lighthouse/build.sh create mode 100755 container-build/cerc-lighthouse/start-lighthouse.sh create mode 100644 stacks/fixturenet-eth/README.md create mode 100644 stacks/fixturenet-eth/stack.yml diff --git a/compose/docker-compose-fixturenet-eth.yml b/compose/docker-compose-fixturenet-eth.yml new file mode 100644 index 0000000..4608a2a --- /dev/null +++ b/compose/docker-compose-fixturenet-eth.yml @@ -0,0 +1,132 @@ +version: '3.7' + +services: + fixturenet-eth-bootnode-geth: + restart: always + hostname: fixturenet-eth-bootnode-geth + env_file: + - ../config/fixturenet-eth/fixturenet-eth.env + environment: + RUN_BOOTNODE: "true" + image: cerc/fixturenet-eth-geth:local + volumes: + - fixturenet_eth_bootnode_geth_data:/root/ethdata + ports: + - "9898" + - "30303" + + fixturenet-eth-geth-1: + restart: always + hostname: fixturenet-eth-geth-1 + cap_add: + - SYS_PTRACE + environment: + CERC_REMOTE_DEBUG: ${CERC_REMOTE_DEBUG:-true} + CERC_RUN_STATEDIFF: ${CERC_RUN_STATEDIFF:-detect} + CERC_STATEDIFF_DB_NODE_ID: 1 + CERC_SCRIPT_DEBUG: ${CERC_SCRIPT_DEBUG} + env_file: + - ../config/fixturenet-eth/fixturenet-eth.env + image: cerc/fixturenet-eth-geth:local + volumes: + - fixturenet_eth_geth_1_data:/root/ethdata + healthcheck: + test: ["CMD", "nc", "-v", "localhost", "8545"] + interval: 30s + timeout: 10s + retries: 10 + start_period: 3s + depends_on: + - fixturenet-eth-bootnode-geth + ports: + - "8545" + - "8546" + - "40000" + - "6060" + + fixturenet-eth-geth-2: + restart: always + hostname: fixturenet-eth-geth-2 + healthcheck: + test: ["CMD", "nc", "-v", "localhost", "8545"] + interval: 30s + timeout: 10s + retries: 10 + start_period: 3s + environment: + CERC_KEEP_RUNNING_AFTER_GETH_EXIT: "true" + env_file: + - ../config/fixturenet-eth/fixturenet-eth.env + image: cerc/fixturenet-eth-geth:local + depends_on: + - fixturenet-eth-bootnode-geth + volumes: + - fixturenet_eth_geth_2_data:/root/ethdata + ports: + - "8545" + - "8546" + + fixturenet-eth-bootnode-lighthouse: + restart: always + hostname: fixturenet-eth-bootnode-lighthouse + environment: + RUN_BOOTNODE: "true" + image: cerc/fixturenet-eth-lighthouse:local + + fixturenet-eth-lighthouse-1: + restart: always + hostname: fixturenet-eth-lighthouse-1 + healthcheck: + test: ["CMD", "wget", "--tries=1", "--connect-timeout=1", "--quiet", "-O", "-", "http://localhost:8001/eth/v2/beacon/blocks/head"] + interval: 30s + timeout: 10s + retries: 10 + start_period: 30s + env_file: + - ../config/fixturenet-eth/fixturenet-eth.env + environment: + NODE_NUMBER: "1" + ETH1_ENDPOINT: "http://fixturenet-eth-geth-1:8545" + EXECUTION_ENDPOINT: "http://fixturenet-eth-geth-1:8551" + image: cerc/fixturenet-eth-lighthouse:local + volumes: + - fixturenet_eth_lighthouse_1_data:/opt/testnet/build/cl + depends_on: + fixturenet-eth-bootnode-lighthouse: + condition: service_started + fixturenet-eth-geth-1: + condition: service_healthy + ports: + - "8001" + + fixturenet-eth-lighthouse-2: + restart: always + hostname: fixturenet-eth-lighthouse-2 + healthcheck: + test: ["CMD", "wget", "--tries=1", "--connect-timeout=1", "--quiet", "-O", "-", "http://localhost:8001/eth/v2/beacon/blocks/head"] + interval: 30s + timeout: 10s + retries: 10 + start_period: 30s + env_file: + - ../config/fixturenet-eth/fixturenet-eth.env + environment: + NODE_NUMBER: "2" + ETH1_ENDPOINT: "http://fixturenet-eth-geth-2:8545" + EXECUTION_ENDPOINT: "http://fixturenet-eth-geth-2:8551" + LIGHTHOUSE_GENESIS_STATE_URL: "http://fixturenet-eth-lighthouse-1:8001/eth/v2/debug/beacon/states/0" + image: cerc/fixturenet-eth-lighthouse:local + volumes: + - fixturenet_eth_lighthouse_2_data:/opt/testnet/build/cl + depends_on: + fixturenet-eth-bootnode-lighthouse: + condition: service_started + fixturenet-eth-geth-2: + condition: service_healthy + +volumes: + fixturenet_eth_bootnode_geth_data: + fixturenet_eth_geth_1_data: + fixturenet_eth_geth_2_data: + fixturenet_eth_lighthouse_1_data: + fixturenet_eth_lighthouse_2_data: diff --git a/compose/docker-compose-foundry.yml b/compose/docker-compose-foundry.yml new file mode 100644 index 0000000..e5987b5 --- /dev/null +++ b/compose/docker-compose-foundry.yml @@ -0,0 +1,9 @@ +# Add-on pod to include foundry tooling within a fixturenet +services: + foundry: + restart: always + image: cerc/foundry:local + command: ["while :; do sleep 600; done"] + volumes: + - ../config/foundry/foundry.toml:/foundry.toml + - ./foundry/workspace:/workspace diff --git a/config/fixturenet-eth/fixturenet-eth.env b/config/fixturenet-eth/fixturenet-eth.env new file mode 100644 index 0000000..695c8fa --- /dev/null +++ b/config/fixturenet-eth/fixturenet-eth.env @@ -0,0 +1,28 @@ +# The password used to access test accounts (eg, via personal_unlockAccount). The password is the same for all accounts. +ACCOUNT_PASSWORD=secret1212 + +# ENODE of the geth bootnode. +BOOTNODE_KEY="b0ac22adcad37213c7c565810a50f1772291e7b0ce53fb73e7ec2a3c75bc13b5" +ENODE="enode://af22c29c316ad069cf48a09a4ad5cf04a251b411e45098888d114c6dd7f489a13786620d5953738762afa13711d4ffb3b19aa5de772d8af72f851f7e9c5b164a@fixturenet-eth-bootnode-geth:30303" + +# JWT shared by geth and lighthouse for authentication. +JWT="0x6cdcac3501046a08e186730dd8bd136cfaf0fdc1fc955f6e15ad3068c0ff2af0" + +# URL to download the ENR of the lighthouse bootnode (generated at first start). +ENR_URL="http://fixturenet-eth-bootnode-lighthouse:3000/bootnode/enr.dat" + +# DB connection settings for statediffing (see docker-compose-db.yml) +CERC_STATEDIFF_DB_HOST="ipld-eth-db" +CERC_STATEDIFF_DB_PORT=5432 +CERC_STATEDIFF_DB_NAME="cerc_testing" +CERC_STATEDIFF_DB_USER="vdbm" +CERC_STATEDIFF_DB_PASSWORD="password" +CERC_STATEDIFF_DB_GOOSE_MIN_VER=${CERC_STATEDIFF_DB_GOOSE_MIN_VER:-18} +CERC_STATEDIFF_DB_LOG_STATEMENTS="${CERC_STATEDIFF_DB_LOG_STATEMENTS:-false}" +CERC_STATEDIFF_WORKERS=2 + +CERC_GETH_VMODULE="statediff/*=5,rpc/*=5" +CERC_GETH_VERBOSITY=${CERC_GETH_VERBOSITY:-3} + +# Used by Lighthouse +SECONDS_PER_ETH1_BLOCK=${SECONDS_PER_ETH1_BLOCK:-3} diff --git a/container-build/cerc-fixturenet-eth-genesis/Dockerfile b/container-build/cerc-fixturenet-eth-genesis/Dockerfile new file mode 100644 index 0000000..870e8c9 --- /dev/null +++ b/container-build/cerc-fixturenet-eth-genesis/Dockerfile @@ -0,0 +1,25 @@ +FROM ethpandaops/ethereum-genesis-generator:3.0.0 AS ethgen + +FROM golang:1.20-alpine as builder + +RUN apk add --no-cache python3 py3-pip make bash envsubst jq + +# Install ethereum-genesis-generator tools +COPY --from=ethgen /apps /apps +RUN cd /apps/el-gen && pip3 install --break-system-packages -r requirements.txt +RUN pip3 install --break-system-packages --upgrade "web3==v6.15.1" +RUN pip3 install --break-system-packages --upgrade "typing-extensions" + +# Install tool to generate initial block +RUN go install github.com/cerc-io/eth-dump-genblock@b29516740fc01cf1d1d623acbfd0e9a2b6440a96 + +# Build genesis config +COPY genesis /opt/genesis +RUN cd /opt/genesis && make genesis-el + +# Snag the genesis block info. +RUN eth-dump-genblock /opt/genesis/build/el/geth.json > /opt/genesis/build/el/genesis_block.json + +FROM alpine:latest + +COPY --from=builder /opt/genesis /opt/genesis diff --git a/container-build/cerc-fixturenet-eth-genesis/build.sh b/container-build/cerc-fixturenet-eth-genesis/build.sh new file mode 100755 index 0000000..e2fd112 --- /dev/null +++ b/container-build/cerc-fixturenet-eth-genesis/build.sh @@ -0,0 +1,8 @@ +#!/usr/bin/env bash +# Build cerc/fixturenet-eth-genesis + +source ${CERC_CONTAINER_BASE_DIR}/build-base.sh + +SCRIPT_DIR=$( cd -- "$( dirname -- "${BASH_SOURCE[0]}" )" &> /dev/null && pwd ) + +docker build -t cerc/fixturenet-eth-genesis:local -f ${SCRIPT_DIR}/Dockerfile ${build_command_args} $SCRIPT_DIR diff --git a/container-build/cerc-fixturenet-eth-genesis/genesis/Makefile b/container-build/cerc-fixturenet-eth-genesis/genesis/Makefile new file mode 100644 index 0000000..a1eef57 --- /dev/null +++ b/container-build/cerc-fixturenet-eth-genesis/genesis/Makefile @@ -0,0 +1,13 @@ +.PHONY: build +build: genesis + +.PHONY: genesis +genesis: genesis-el + +.PHONY: genesis-el +genesis-el: + cd el; ./build_el.sh + +.PHONY: clean +clean: + rm -rf build diff --git a/container-build/cerc-fixturenet-eth-genesis/genesis/accounts/import_keys.sh b/container-build/cerc-fixturenet-eth-genesis/genesis/accounts/import_keys.sh new file mode 100755 index 0000000..e8dce0e --- /dev/null +++ b/container-build/cerc-fixturenet-eth-genesis/genesis/accounts/import_keys.sh @@ -0,0 +1,17 @@ +#!/bin/sh + +ACCOUNT_PASSWORD=${ACCOUNT_PASSWORD:-secret1212} + +for line in `cat ../build/el/accounts.csv`; do + BIP44_PATH="`echo "$line" | cut -d',' -f1`" + ADDRESS="`echo "$line" | cut -d',' -f2`" + PRIVATE_KEY="`echo "$line" | cut -d',' -f3`" + + echo "$ACCOUNT_PASSWORD" > .pw.$$ + echo "$PRIVATE_KEY" | sed 's/0x//' > .key.$$ + + echo "" + echo "$ADDRESS" + geth account import --datadir=~/ethdata --password .pw.$$ .key.$$ + rm -f .pw.$$ .key.$$ +done diff --git a/container-build/cerc-fixturenet-eth-genesis/genesis/accounts/mnemonic_to_csv.py b/container-build/cerc-fixturenet-eth-genesis/genesis/accounts/mnemonic_to_csv.py new file mode 100644 index 0000000..1e6d10f --- /dev/null +++ b/container-build/cerc-fixturenet-eth-genesis/genesis/accounts/mnemonic_to_csv.py @@ -0,0 +1,16 @@ +from web3.auto import w3 +import ruamel.yaml as yaml +import sys + +w3.eth.account.enable_unaudited_hdwallet_features() + +testnet_config_path = "genesis-config.yaml" +if len(sys.argv) > 1: + testnet_config_path = sys.argv[1] + +with open(testnet_config_path) as stream: + data = yaml.safe_load(stream) + +for key, value in data['el_premine'].items(): + acct = w3.eth.account.from_mnemonic(data['mnemonic'], account_path=key, passphrase='') + print("%s,%s,%s" % (key, acct.address, acct.key.hex())) diff --git a/container-build/cerc-fixturenet-eth-genesis/genesis/el/build_el.sh b/container-build/cerc-fixturenet-eth-genesis/genesis/el/build_el.sh new file mode 100755 index 0000000..d7a0ae1 --- /dev/null +++ b/container-build/cerc-fixturenet-eth-genesis/genesis/el/build_el.sh @@ -0,0 +1,16 @@ +#!/usr/bin/env bash +set -e + +# See: https://github.com/skylenet/ethereum-genesis-generator/blob/master/entrypoint.sh + +rm -rf ../build/el +mkdir -p ../build/el + +tmp_dir=$(mktemp -d -t ci-XXXXXXXXXX) +envsubst < el-config.yaml > $tmp_dir/genesis-config.yaml + +python3 /apps/el-gen/genesis_geth.py $tmp_dir/genesis-config.yaml | \ + jq 'del(.config.pragueTime)' \ + > ../build/el/geth.json + +python3 ../accounts/mnemonic_to_csv.py $tmp_dir/genesis-config.yaml > ../build/el/accounts.csv diff --git a/container-build/cerc-fixturenet-eth-genesis/genesis/el/el-config.yaml b/container-build/cerc-fixturenet-eth-genesis/genesis/el/el-config.yaml new file mode 100644 index 0000000..a3bfb11 --- /dev/null +++ b/container-build/cerc-fixturenet-eth-genesis/genesis/el/el-config.yaml @@ -0,0 +1,17 @@ +mnemonic: "viable ketchup woman library opinion copy rhythm attend rose knock penalty practice photo bundle budget dentist enter round bind holiday useful arch danger lobster" +el_premine: + "m/44'/60'/0'/0/0": 10000000ETH + "m/44'/60'/0'/0/1": 10000000ETH + "m/44'/60'/0'/0/2": 10000000ETH + "m/44'/60'/0'/0/3": 10000000ETH + "m/44'/60'/0'/0/4": 10000000ETH + "m/44'/60'/0'/0/5": 10000000ETH +el_premine_addrs: {} +chain_id: 1212 +deposit_contract_address: "0x1212121212121212121212121212121212121212" +genesis_timestamp: 0 +genesis_delay: 0 +deneb_fork_epoch: 0 +# note: only needed as workaround https://github.com/ethpandaops/ethereum-genesis-generator/pull/105 +electra_fork_epoch: 0 +slot_duration_in_seconds: 3 diff --git a/container-build/cerc-fixturenet-eth-geth/Dockerfile b/container-build/cerc-fixturenet-eth-geth/Dockerfile new file mode 100644 index 0000000..946dd95 --- /dev/null +++ b/container-build/cerc-fixturenet-eth-geth/Dockerfile @@ -0,0 +1,21 @@ +FROM cerc/fixturenet-eth-genesis:local as fnetgen +FROM cerc/go-ethereum:local as geth + +# Using the same golang image as used to build geth: https://github.com/cerc-io/go-ethereum/blob/HEAD/Dockerfile +FROM golang:1.20-alpine as delve +RUN go install github.com/go-delve/delve/cmd/dlv@latest + +FROM alpine:3.17 + +RUN apk add --no-cache bash wget python3 bind-tools postgresql-client + +COPY run-el.sh /opt/testnet/run.sh + +COPY --from=delve /go/bin/dlv /usr/local/bin/ +COPY --from=geth /usr/local/bin/geth /usr/local/bin/ +COPY --from=fnetgen /opt/genesis /opt/testnet + +# Initialize the geth db with our config +RUN geth --datadir ~/ethdata init /opt/testnet/build/el/geth.json && rm -f ~/ethdata/geth/nodekey + +ENTRYPOINT ["/opt/testnet/run.sh"] diff --git a/container-build/cerc-fixturenet-eth-geth/build.sh b/container-build/cerc-fixturenet-eth-geth/build.sh new file mode 100755 index 0000000..a00a3f1 --- /dev/null +++ b/container-build/cerc-fixturenet-eth-geth/build.sh @@ -0,0 +1,8 @@ +#!/usr/bin/env bash +# Build cerc/fixturenet-eth-geth + +source ${CERC_CONTAINER_BASE_DIR}/build-base.sh + +SCRIPT_DIR=$( cd -- "$( dirname -- "${BASH_SOURCE[0]}" )" &> /dev/null && pwd ) + +docker build -t cerc/fixturenet-eth-geth:local -f ${SCRIPT_DIR}/Dockerfile ${build_command_args} $SCRIPT_DIR diff --git a/container-build/cerc-fixturenet-eth-geth/run-el.sh b/container-build/cerc-fixturenet-eth-geth/run-el.sh new file mode 100755 index 0000000..f84befd --- /dev/null +++ b/container-build/cerc-fixturenet-eth-geth/run-el.sh @@ -0,0 +1,154 @@ +#!/bin/bash + +if [ -n "$CERC_SCRIPT_DEBUG" ]; then + set -x +fi + +ETHERBASE=`cat /opt/testnet/build/el/accounts.csv | head -1 | cut -d',' -f2` +NETWORK_ID=`cat /opt/testnet/el/el-config.yaml | grep 'chain_id' | awk '{ print $2 }'` +NETRESTRICT=`ip addr | grep -w inet | grep -v '127.0' | awk '{print $2}'` +CERC_ETH_DATADIR="${CERC_ETH_DATADIR:-$HOME/ethdata}" +CERC_PLUGINS_DIR="${CERC_PLUGINS_DIR:-/usr/local/lib/plugeth}" + +cd /opt/testnet/build/el +python3 -m http.server 9898 & +cd $HOME + +START_CMD="geth" +if [ "true" == "$CERC_REMOTE_DEBUG" ] && [ -x "/usr/local/bin/dlv" ]; then + START_CMD="/usr/local/bin/dlv --listen=:40000 --headless=true --api-version=2 --accept-multiclient exec /usr/local/bin/geth --continue --" +fi + +# See https://linuxconfig.org/how-to-propagate-a-signal-to-child-processes-from-a-bash-script +cleanup() { + echo "Signal received, cleaning up..." + + # Kill the child process first (CERC_REMOTE_DEBUG=true uses dlv which starts geth as a child process) + pkill -P ${geth_pid} + sleep 2 + kill $(jobs -p) + + wait + echo "Done" +} +trap 'cleanup' SIGINT SIGTERM + +if [ "true" == "$RUN_BOOTNODE" ]; then + $START_CMD \ + --datadir="${CERC_ETH_DATADIR}" \ + --nodekeyhex="${BOOTNODE_KEY}" \ + --nodiscover \ + --ipcdisable \ + --networkid=${NETWORK_ID} \ + --netrestrict="${NETRESTRICT}" \ + & + + geth_pid=$! +else + cd /opt/testnet/accounts + ./import_keys.sh + + echo -n "$JWT" > /opt/testnet/build/el/jwtsecret + + if [ "$CERC_RUN_STATEDIFF" == "detect" ] && [ -n "$CERC_STATEDIFF_DB_HOST" ]; then + dig_result=$(dig $CERC_STATEDIFF_DB_HOST +short) + dig_status_code=$? + if [[ $dig_status_code = 0 && -n $dig_result ]]; then + echo "Statediff DB at $CERC_STATEDIFF_DB_HOST" + CERC_RUN_STATEDIFF="true" + else + echo "No statediff DB available." + CERC_RUN_STATEDIFF="false" + fi + fi + + STATEDIFF_OPTS="" + if [ "$CERC_RUN_STATEDIFF" == "true" ]; then + ready=0 + echo "Waiting for statediff DB..." + while [ $ready -eq 0 ]; do + sleep 1 + export PGPASSWORD="$CERC_STATEDIFF_DB_PASSWORD" + result=$(psql -h "$CERC_STATEDIFF_DB_HOST" \ + -p "$CERC_STATEDIFF_DB_PORT" \ + -U "$CERC_STATEDIFF_DB_USER" \ + -d "$CERC_STATEDIFF_DB_NAME" \ + -t -c 'select max(version_id) from goose_db_version;' 2>/dev/null | awk '{ print $1 }') + if [ -n "$result" ]; then + echo "DB ready..." + if [ $result -ge $CERC_STATEDIFF_DB_GOOSE_MIN_VER ]; then + ready=1 + else + echo "DB not at required version (want $CERC_STATEDIFF_DB_GOOSE_MIN_VER, have $result)" + fi + fi + done + STATEDIFF_OPTS="--statediff \ + --statediff.db.host=$CERC_STATEDIFF_DB_HOST \ + --statediff.db.name=$CERC_STATEDIFF_DB_NAME \ + --statediff.db.nodeid=$CERC_STATEDIFF_DB_NODE_ID \ + --statediff.db.password=$CERC_STATEDIFF_DB_PASSWORD \ + --statediff.db.port=$CERC_STATEDIFF_DB_PORT \ + --statediff.db.user=$CERC_STATEDIFF_DB_USER \ + --statediff.db.logstatements=${CERC_STATEDIFF_DB_LOG_STATEMENTS:-false} \ + --statediff.db.copyfrom=${CERC_STATEDIFF_DB_COPY_FROM:-true} \ + --statediff.waitforsync=true \ + --statediff.workers=${CERC_STATEDIFF_WORKERS:-1} \ + --statediff.writing=true" + + if [ -d "${CERC_PLUGINS_DIR}" ]; then + # With plugeth, we separate the statediff options by prefixing with ' -- ' + STATEDIFF_OPTS="--pluginsdir "${CERC_PLUGINS_DIR}" -- ${STATEDIFF_OPTS}" + fi + fi + + OTHER_OPTS="" + # miner options were removed in v1.12 + GETH_VERSION=$(geth --version | grep -io '[0-9][0-9a-z.-]*') + if echo -e "$GETH_VERSION\n1.12" | sort -Vc; then + OTHER_OPTS="--miner.threads=1" + fi + + $START_CMD \ + --datadir="${CERC_ETH_DATADIR}" \ + --bootnodes="${ENODE}" \ + --allow-insecure-unlock \ + --http \ + --http.addr="0.0.0.0" \ + --http.vhosts="*" \ + --http.api="${CERC_GETH_HTTP_APIS:-eth,web3,net,admin,personal,debug,statediff}" \ + --http.corsdomain="*" \ + --authrpc.addr="0.0.0.0" \ + --authrpc.vhosts="*" \ + --authrpc.jwtsecret="/opt/testnet/build/el/jwtsecret" \ + --ws \ + --ws.addr="0.0.0.0" \ + --ws.origins="*" \ + --ws.api="${CERC_GETH_WS_APIS:-eth,web3,net,admin,personal,debug,statediff}" \ + --http.corsdomain="*" \ + --networkid="${NETWORK_ID}" \ + --netrestrict="${NETRESTRICT}" \ + --gcmode archive \ + --txlookuplimit=0 \ + --cache.preimages \ + --syncmode=full \ + --mine \ + --metrics \ + --metrics.addr="0.0.0.0" \ + --verbosity=${CERC_GETH_VERBOSITY:-3} \ + --log.vmodule="${CERC_GETH_VMODULE:-statediff/*=5}" \ + --miner.etherbase="${ETHERBASE}" \ + ${OTHER_OPTS} \ + ${STATEDIFF_OPTS} \ + & + + geth_pid=$! +fi + +wait $geth_pid + +if [ "true" == "$CERC_KEEP_RUNNING_AFTER_GETH_EXIT" ]; then + while [ 1 -eq 1 ]; do + sleep 60 + done +fi diff --git a/container-build/cerc-fixturenet-eth-lighthouse/Dockerfile b/container-build/cerc-fixturenet-eth-lighthouse/Dockerfile new file mode 100644 index 0000000..21712bc --- /dev/null +++ b/container-build/cerc-fixturenet-eth-lighthouse/Dockerfile @@ -0,0 +1,30 @@ +FROM cerc/lighthouse-cli:local AS lcli +FROM cerc/fixturenet-eth-genesis:local AS fnetgen + +FROM cerc/lighthouse:local + +# cerc/lighthouse is based on Ubuntu +RUN apt-get update && apt-get -y upgrade && apt-get install -y --no-install-recommends \ + libssl-dev ca-certificates \ + curl socat iproute2 telnet wget jq \ + build-essential python3 python3-dev python3-pip gettext-base \ + && apt-get clean \ + && rm -rf /var/lib/apt/lists/* + +COPY --from=lcli /usr/local/bin/lcli /usr/local/bin/lcli +COPY --from=fnetgen /opt/genesis/el /opt/testnet/el +COPY --from=fnetgen /opt/genesis/build/el /opt/testnet/build/el + +COPY genesis /opt/testnet +COPY run-cl.sh /opt/testnet/run.sh + +RUN cd /opt/testnet && make genesis-cl + +# Work around some bugs in lcli where the default path is always used. +RUN mkdir -p /root/.lighthouse && cd /root/.lighthouse && ln -s /opt/testnet/build/cl/testnet + +RUN mkdir -p /scripts +COPY scripts/status-internal.sh /scripts +COPY scripts/status.sh /scripts + +ENTRYPOINT ["/opt/testnet/run.sh"] diff --git a/container-build/cerc-fixturenet-eth-lighthouse/build.sh b/container-build/cerc-fixturenet-eth-lighthouse/build.sh new file mode 100755 index 0000000..e7e0603 --- /dev/null +++ b/container-build/cerc-fixturenet-eth-lighthouse/build.sh @@ -0,0 +1,8 @@ +#!/usr/bin/env bash +# Build cerc/fixturenet-eth-lighthouse + +source ${CERC_CONTAINER_BASE_DIR}/build-base.sh + +SCRIPT_DIR=$( cd -- "$( dirname -- "${BASH_SOURCE[0]}" )" &> /dev/null && pwd ) + +docker build -t cerc/fixturenet-eth-lighthouse:local -f ${SCRIPT_DIR}/Dockerfile ${build_command_args} $SCRIPT_DIR diff --git a/container-build/cerc-fixturenet-eth-lighthouse/genesis/Makefile b/container-build/cerc-fixturenet-eth-lighthouse/genesis/Makefile new file mode 100644 index 0000000..5a91fbb --- /dev/null +++ b/container-build/cerc-fixturenet-eth-lighthouse/genesis/Makefile @@ -0,0 +1,13 @@ +.PHONY: build +build: genesis + +.PHONY: genesis +genesis: genesis-cl + +.PHONY: genesis-cl +genesis-cl: + cd cl; ./build_cl.sh + +.PHONY: clean +clean: + rm -rf build diff --git a/container-build/cerc-fixturenet-eth-lighthouse/genesis/cl/beacon_node.sh b/container-build/cerc-fixturenet-eth-lighthouse/genesis/cl/beacon_node.sh new file mode 100755 index 0000000..7e92f49 --- /dev/null +++ b/container-build/cerc-fixturenet-eth-lighthouse/genesis/cl/beacon_node.sh @@ -0,0 +1,41 @@ +#!/usr/bin/env bash + +# See: https://github.com/sigp/lighthouse/blob/stable/scripts/local_testnet/beacon_node.sh +# +# Starts a beacon node based upon a genesis state created by `./setup.sh`. +# + +set -Eeuo pipefail + +source ./vars.env + +SUBSCRIBE_ALL_SUBNETS= + +# Get positional arguments +data_dir=$DATADIR/node_${NODE_NUMBER} +network_port=9001 +http_port=8001 +authrpc_port=8551 + +exec lighthouse \ + bn \ + $SUBSCRIBE_ALL_SUBNETS \ + --debug-level $DEBUG_LEVEL \ + --boot-nodes "$ENR" \ + --datadir $data_dir \ + --testnet-dir $TESTNET_DIR \ + --enable-private-discovery \ + --staking \ + --enr-address $ENR_IP \ + --enr-udp-port $network_port \ + --enr-tcp-port $network_port \ + --port $network_port \ + --http-address 0.0.0.0 \ + --http-port $http_port \ + --disable-packet-filter \ + --execution-endpoint $EXECUTION_ENDPOINT \ + --execution-jwt $JWTSECRET \ + --terminal-total-difficulty-override $ETH1_TTD \ + --suggested-fee-recipient $SUGGESTED_FEE_RECIPIENT \ + --target-peers $((BN_COUNT - 1)) \ + --http-allow-sync-stalled \ diff --git a/container-build/cerc-fixturenet-eth-lighthouse/genesis/cl/bootnode.sh b/container-build/cerc-fixturenet-eth-lighthouse/genesis/cl/bootnode.sh new file mode 100755 index 0000000..15aee6e --- /dev/null +++ b/container-build/cerc-fixturenet-eth-lighthouse/genesis/cl/bootnode.sh @@ -0,0 +1,39 @@ +#!/usr/bin/env bash + +# See: https://github.com/sigp/lighthouse/blob/stable/scripts/local_testnet/bootnode.sh +# +# Starts a bootnode from the generated enr. +# + +set -Eeuo pipefail + +source ./vars.env + +echo "Starting bootnode" + +# Clean up existing ENR dir to avoid node connectivity issues on a restart +if [ -d "$DATADIR/bootnode" ]; then + echo "Removing existing bootnode enr directory" + rm -r "$DATADIR/bootnode" +fi + +echo "Generating bootnode enr" +lcli \ + generate-bootnode-enr \ + --ip $ENR_IP \ + --udp-port $BOOTNODE_PORT \ + --tcp-port $BOOTNODE_PORT \ + --genesis-fork-version $GENESIS_FORK_VERSION \ + --output-dir $DATADIR/bootnode + +bootnode_enr=`cat $DATADIR/bootnode/enr.dat` +echo "- $bootnode_enr" > $TESTNET_DIR/boot_enr.yaml + +echo "Generated bootnode enr and written to $TESTNET_DIR/boot_enr.yaml" + +exec lighthouse boot_node \ + --testnet-dir $TESTNET_DIR \ + --port $BOOTNODE_PORT \ + --listen-address 0.0.0.0 \ + --disable-packet-filter \ + --network-dir $DATADIR/bootnode \ diff --git a/container-build/cerc-fixturenet-eth-lighthouse/genesis/cl/build_cl.sh b/container-build/cerc-fixturenet-eth-lighthouse/genesis/cl/build_cl.sh new file mode 100755 index 0000000..5157b38 --- /dev/null +++ b/container-build/cerc-fixturenet-eth-lighthouse/genesis/cl/build_cl.sh @@ -0,0 +1,56 @@ +#!/usr/bin/env bash + +# See https://github.com/sigp/lighthouse/scripts/local_testnet/setup.sh +# +# Deploys the deposit contract and makes deposits for $VALIDATOR_COUNT insecure deterministic validators. +# Produces a testnet specification and a genesis state where the genesis time +# is now + $GENESIS_DELAY. +# +# Generates datadirs for multiple validator keys according to the +# $VALIDATOR_COUNT and $BN_COUNT variables. +# + +set -o nounset -o errexit -o pipefail + +source ./vars.env + +rm -rf $DATADIR +mkdir -p $DATADIR + +NOW=`date +%s` +GENESIS_TIME=`expr $NOW + $GENESIS_DELAY` + +echo "Creating testnet ..." +echo "(Note: errors of the form 'WARN: Scrypt parameters are too weak...' below can be safely ignored)" +lcli \ + new-testnet \ + --spec $SPEC_PRESET \ + --testnet-dir $TESTNET_DIR \ + --deposit-contract-address $ETH1_DEPOSIT_CONTRACT_ADDRESS \ + --min-genesis-active-validator-count $GENESIS_VALIDATOR_COUNT \ + --validator-count $VALIDATOR_COUNT \ + --min-genesis-time $GENESIS_TIME \ + --genesis-delay $GENESIS_DELAY \ + --genesis-fork-version $GENESIS_FORK_VERSION \ + --altair-fork-epoch $ALTAIR_FORK_EPOCH \ + --bellatrix-fork-epoch $BELLATRIX_FORK_EPOCH \ + --capella-fork-epoch $CAPELLA_FORK_EPOCH \ + --deneb-fork-epoch $DENEB_FORK_EPOCH \ + --eth1-id $ETH1_CHAIN_ID \ + --eth1-block-hash $ETH1_BLOCK_HASH \ + --eth1-follow-distance 1 \ + --seconds-per-slot $SECONDS_PER_SLOT \ + --seconds-per-eth1-block $SECONDS_PER_ETH1_BLOCK \ + --interop-genesis-state \ + --force + +echo Specification and genesis.ssz generated at $TESTNET_DIR. +echo "Generating $VALIDATOR_COUNT validators concurrently... (this may take a while)" + +lcli \ + insecure-validators \ + --count $VALIDATOR_COUNT \ + --base-dir $DATADIR \ + --node-count $BN_COUNT + +echo Validators generated with keystore passwords at $DATADIR. diff --git a/container-build/cerc-fixturenet-eth-lighthouse/genesis/cl/ready.sh b/container-build/cerc-fixturenet-eth-lighthouse/genesis/cl/ready.sh new file mode 100755 index 0000000..ef0a184 --- /dev/null +++ b/container-build/cerc-fixturenet-eth-lighthouse/genesis/cl/ready.sh @@ -0,0 +1,10 @@ +#!/bin/bash + +LIGHTHOUSE_BASE_URL=http://localhost:8001 + +result=`wget --no-check-certificate --quiet -O - "$LIGHTHOUSE_BASE_URL/eth/v2/beacon/blocks/head" | jq -r '.data.message.body.execution_payload.block_number'` +if [ ! -z "$result" ] && [ $result -gt 0 ]; then + exit 0 +fi + +exit 1 diff --git a/container-build/cerc-fixturenet-eth-lighthouse/genesis/cl/reset_genesis_time.sh b/container-build/cerc-fixturenet-eth-lighthouse/genesis/cl/reset_genesis_time.sh new file mode 100755 index 0000000..5917307 --- /dev/null +++ b/container-build/cerc-fixturenet-eth-lighthouse/genesis/cl/reset_genesis_time.sh @@ -0,0 +1,20 @@ +#!/bin/bash + +# See: https://github.com/sigp/lighthouse/blob/stable/scripts/local_testnet/reset_genesis_time.sh +# +# Resets the beacon state genesis time to now. +# + +set -Eeuo pipefail + +source ./vars.env + +NOW=${1:-`date +%s`} + +lcli \ + change-genesis-time \ + --testnet-dir $TESTNET_DIR \ + $TESTNET_DIR/genesis.ssz \ + $NOW + +echo "Reset genesis time to ($NOW)" diff --git a/container-build/cerc-fixturenet-eth-lighthouse/genesis/cl/validator_client.sh b/container-build/cerc-fixturenet-eth-lighthouse/genesis/cl/validator_client.sh new file mode 100755 index 0000000..2c65e74 --- /dev/null +++ b/container-build/cerc-fixturenet-eth-lighthouse/genesis/cl/validator_client.sh @@ -0,0 +1,31 @@ +#!/usr/bin/env bash + +# See: https://github.com/sigp/lighthouse/blob/stable/scripts/local_testnet/validator_client.sh +# +# Usage: ./validator_client.sh + +set -Eeuo pipefail + +source ./vars.env + +BUILDER_PROPOSALS= + +# Get options +while getopts "pd:" flag; do + case "${flag}" in + p) BUILDER_PROPOSALS="--builder-proposals";; + d) DEBUG_LEVEL=${OPTARG};; + esac +done + +exec lighthouse \ + vc \ + $BUILDER_PROPOSALS \ + --debug-level $DEBUG_LEVEL \ + --validators-dir $DATADIR/node_$NODE_NUMBER/validators \ + --secrets-dir $DATADIR/node_$NODE_NUMBER/secrets \ + --testnet-dir $TESTNET_DIR \ + --init-slashing-protection \ + --beacon-nodes http://localhost:8001 \ + --suggested-fee-recipient $SUGGESTED_FEE_RECIPIENT \ + $VC_ARGS diff --git a/container-build/cerc-fixturenet-eth-lighthouse/genesis/cl/vars.env b/container-build/cerc-fixturenet-eth-lighthouse/genesis/cl/vars.env new file mode 100644 index 0000000..83780b2 --- /dev/null +++ b/container-build/cerc-fixturenet-eth-lighthouse/genesis/cl/vars.env @@ -0,0 +1,58 @@ +# Base directories for the validator keys and secrets +DATADIR=${DATADIR:-../build/cl} + +# Directory for the eth2 config +TESTNET_DIR=${TESTNET_DIR:-$DATADIR/testnet} +JWTSECRET=${JWTSECRET:-$DATADIR/jwtsecret} +ENR=${ENR:="SET_AT_RUNTIME"} +ENR_IP=`ip addr | grep inet | grep -v '127.0.0.1' | sort | head -1 | awk '{print $2}' | cut -d '/' -f1` + +GENESIS_FORK_VERSION=${GENESIS_FORK_VERSION:-0x12121212} + +VALIDATOR_COUNT=${VALIDATOR_COUNT:-80} +GENESIS_VALIDATOR_COUNT=${GENESIS_VALIDATOR_COUNT:-80} + +# Number of beacon_node instances that you intend to run +BN_COUNT=${BN_COUNT:-2} + +# Number of seconds to delay to start genesis block. +# If started by a script this can be 0, if starting by hand +# use something like 180. +GENESIS_DELAY=${GENESIS_DELAY:-0} + +# Port for P2P communication with bootnode +BOOTNODE_PORT=${BOOTNODE_PORT:-4242} + +# Hard fork configuration +ALTAIR_FORK_EPOCH=${ALTAIR_FORK_EPOCH:-0} +BELLATRIX_FORK_EPOCH=${BELLATRIX_FORK_EPOCH:-0} +CAPELLA_FORK_EPOCH=${CAPELLA_FORK_EPOCH:-0} +DENEB_FORK_EPOCH=${DENEB_FORK_EPOCH:-0} + +# Spec version (mainnet or minimal) +SPEC_PRESET=${SPEC_PRESET:-mainnet} + +# Seconds per Eth2 slot +SECONDS_PER_SLOT=${SECONDS_PER_SLOT:-3} + +# Seconds per Eth1 block +SECONDS_PER_ETH1_BLOCK=${SECONDS_PER_ETH1_BLOCK:-1} + +# Command line arguments for validator client +VC_ARGS=${VC_ARGS:-""} + +EXECUTION_ENDPOINT=${EXECUTION_ENDPOINT:-http://localhost:8551} + +ETH1_GENESIS_JSON=${ETH1_GENESIS_JSON:-"../build/el/geth.json"} +ETH1_GENESIS_BLOCK_JSON=${ETH1_GENESIS_BLOCK_JSON:-"../build/el/genesis_block.json"} +ETH1_CONFIG_YAML=${ETH1_CONFIG_YAML:-"../el/el-config.yaml"} +ETH1_BLOCK_HASH=${ETH1_BLOCK_HASH:-`cat $ETH1_GENESIS_BLOCK_JSON | jq -r '.hash' | cut -d'x' -f2`} + +ETH1_CHAIN_ID=${ETH1_CHAIN_ID:-`cat $ETH1_GENESIS_JSON | jq -r '.config.chainId'`} +ETH1_TTD=${ETH1_TTD:-`cat $ETH1_GENESIS_JSON | jq -r '.config.terminalTotalDifficulty'`} +ETH1_DEPOSIT_CONTRACT_ADDRESS=${ETH1_DEPOSIT_CONTRACT_ADDRESS:-`cat $ETH1_CONFIG_YAML | grep 'deposit_contract_address' | awk '{ print $2 }' | sed 's/"//g'`} +ETH1_DEPOSIT_CONTRACT_BLOCK=${ETH1_DEPOSIT_CONTRACT_BLOCK:-0x0} +SUGGESTED_FEE_RECIPIENT=`cat ../build/el/accounts.csv | head -1 | cut -d',' -f2` + +# --debug-level +DEBUG_LEVEL=${LIGHTHOUSE_DEBUG_LEVEL:-debug} diff --git a/container-build/cerc-fixturenet-eth-lighthouse/run-cl.sh b/container-build/cerc-fixturenet-eth-lighthouse/run-cl.sh new file mode 100755 index 0000000..ec0e9ae --- /dev/null +++ b/container-build/cerc-fixturenet-eth-lighthouse/run-cl.sh @@ -0,0 +1,80 @@ +#!/bin/bash + +# See https://linuxconfig.org/how-to-propagate-a-signal-to-child-processes-from-a-bash-script +cleanup() { + echo "Signal received, cleaning up..." + kill $(jobs -p) + + wait + echo "Done" +} +trap 'cleanup' SIGINT SIGTERM + +if [ "true" == "$RUN_BOOTNODE" ]; then + cd /opt/testnet/build/cl + python3 -m http.server 3000 & + + + cd /opt/testnet/cl + ./bootnode.sh 2>&1 | tee /var/log/lighthouse_bootnode.log & + bootnode_pid=$! + + wait $bootnode_pid +else + while [ 1 -eq 1 ]; do + echo "Waiting on geth ..." + sleep 5 + result=`wget --no-check-certificate --quiet \ + -O - \ + --method POST \ + --timeout=0 \ + --header 'Content-Type: application/json' \ + --body-data '{ "jsonrpc": "2.0", "id": 1, "method": "eth_blockNumber", "params": [] }' "${ETH1_ENDPOINT:-localhost:8545}" | jq -r '.result'` + if [ ! -z "$result" ] && [ "null" != "$result" ]; then + break + fi + done + + cd /opt/testnet/cl + + if [ -z "$LIGHTHOUSE_GENESIS_STATE_URL" ]; then + # Check if beacon node data exists to avoid resetting genesis time on a restart + if [ -d /opt/testnet/build/cl/node_"$NODE_NUMBER"/beacon ]; then + echo "Skipping genesis time reset" + else + ./reset_genesis_time.sh + fi + else + while [ 1 -eq 1 ]; do + echo "Waiting on Genesis time ..." + sleep 5 + result=`wget --no-check-certificate --quiet -O - --timeout=0 $LIGHTHOUSE_GENESIS_STATE_URL | jq -r '.data.genesis_time'` + if [ ! -z "$result" ]; then + ./reset_genesis_time.sh $result + break; + fi + done + fi + + if [ ! -z "$ENR_URL" ]; then + while [ 1 -eq 1 ]; do + echo "Waiting on ENR for boot node..." + sleep 5 + result=`wget --no-check-certificate --quiet -O - --timeout=0 $ENR_URL` + if [ ! -z "$result" ]; then + export ENR="$result" + break; + fi + done + fi + + export JWTSECRET="/opt/testnet/build/cl/jwtsecret" + echo -n "$JWT" > $JWTSECRET + + ./beacon_node.sh 2>&1 | tee /var/log/lighthouse_bn.log & + beacon_pid=$! + ./validator_client.sh 2>&1 | tee /var/log/lighthouse_vc.log & + validator_pid=$! + + wait $beacon_pid $validator_pid +fi diff --git a/container-build/cerc-fixturenet-eth-lighthouse/scripts/export-ethdb.sh b/container-build/cerc-fixturenet-eth-lighthouse/scripts/export-ethdb.sh new file mode 100755 index 0000000..151cb7c --- /dev/null +++ b/container-build/cerc-fixturenet-eth-lighthouse/scripts/export-ethdb.sh @@ -0,0 +1,50 @@ +#!/bin/bash + +# Exports the complete fixturenet-eth ethdb data to a tarball (default, ./ethdb.tgz), waiting for a minimum +# block height (default 1000) to be reached before exporting. + +# Usage: export-ethdb.sh [min_block_number=1000] [output_file=./ethdb.tgz] + +if [[ -n "$CERC_SCRIPT_DEBUG" ]]; then + set -x +fi + +SCRIPT_DIR=$( cd -- "$( dirname -- "${BASH_SOURCE[0]}" )" &> /dev/null && pwd ) + +GETH_EXPORT_MIN_BLOCK=${1:-${GETH_EXPORT_MIN_BLOCK:-1000}} + +# Wait for block. +${SCRIPT_DIR}/status.sh $GETH_EXPORT_MIN_BLOCK +if [[ $? -ne 0 ]]; then + echo "Unable to export ethdb." 1>&2 + exit 1 +fi + +GETH_CONTAINER=`docker ps -q -f "name=${CERC_SO_COMPOSE_PROJECT}-fixturenet-eth-geth-2-1"` +if [[ -z "$GETH_CONTAINER" ]]; then + echo "not found" + exit 1 +fi + +# Make sure we have the necessary tools +docker exec $GETH_CONTAINER sh -c 'apk add --no-cache jq curl' + +# Gather metadata. +docker exec $GETH_CONTAINER sh -c 'rm -rf /root/tmp && mkdir -p /root/tmp/export' +docker exec $GETH_CONTAINER sh -c 'ln -s /opt/testnet/build/el/geth.json /root/tmp/export/genesis.json && ln -s /root/ethdata /root/tmp/export/' +docker exec $GETH_CONTAINER sh -c 'cat /root/tmp/export/genesis.json | jq ".config" > /root/tmp/export/genesis.config.json' +docker exec $GETH_CONTAINER sh -c 'curl -s --location "localhost:8545" --header "Content-Type: application/json" --data "{\"jsonrpc\": \"2.0\", \"id\": 1, \"method\": \"eth_getBlockByNumber\", \"params\": [\"0x0\", false]}" > /root/tmp/export/eth_getBlockByNumber_0x0.json' +docker exec $GETH_CONTAINER sh -c 'curl -s --location "localhost:8545" --header "Content-Type: application/json" --data "{\"jsonrpc\": \"2.0\", \"id\": 1, \"method\": \"eth_blockNumber\", \"params\": []}" > /root/tmp/export/eth_blockNumber.json' + +# Stop geth and zip up ethdb. +echo -n "Exporting ethdb.... " +docker exec $GETH_CONTAINER sh -c "killall geth && sleep 2 && tar chzf /root/tmp/ethdb.tgz -C /root/tmp/export ." + +# Copy ethdb to host. +GETH_EXPORT_FILE=${2:-${GETH_EXPORT_FILE:-./ethdb.tgz}} +docker cp $GETH_CONTAINER:/root/tmp/ethdb.tgz $GETH_EXPORT_FILE +echo "$GETH_EXPORT_FILE" +docker exec $GETH_CONTAINER sh -c "rm -rf /root/tmp" + +# Restart the container to get geth back up and running. +docker restart $GETH_CONTAINER >/dev/null diff --git a/container-build/cerc-fixturenet-eth-lighthouse/scripts/status-internal.sh b/container-build/cerc-fixturenet-eth-lighthouse/scripts/status-internal.sh new file mode 100755 index 0000000..628d7d4 --- /dev/null +++ b/container-build/cerc-fixturenet-eth-lighthouse/scripts/status-internal.sh @@ -0,0 +1,10 @@ +#!/usr/bin/env bash +# Wrapper to facilitate using status.sh inside the container +if [ -n "$CERC_SCRIPT_DEBUG" ]; then + set -x +fi +export LIGHTHOUSE_BASE_URL="http://fixturenet-eth-lighthouse-1:8001" +export GETH_BASE_URL="http://fixturenet-eth-geth-1:8545" +# See: https://stackoverflow.com/a/246128/1701505 +SCRIPT_DIR=$( cd -- "$( dirname -- "${BASH_SOURCE[0]}" )" &> /dev/null && pwd ) +$SCRIPT_DIR/status.sh diff --git a/container-build/cerc-fixturenet-eth-lighthouse/scripts/status.sh b/container-build/cerc-fixturenet-eth-lighthouse/scripts/status.sh new file mode 100755 index 0000000..d9f33d1 --- /dev/null +++ b/container-build/cerc-fixturenet-eth-lighthouse/scripts/status.sh @@ -0,0 +1,97 @@ +#!/usr/bin/env bash +if [ -n "$CERC_SCRIPT_DEBUG" ]; then + set -x +fi + +MIN_BLOCK_NUM=${1:-${MIN_BLOCK_NUM:-3}} +STATUSES=( + "geth to generate DAG" + "beacon phase0" + "beacon altair" + "beacon bellatrix pre-merge" + "beacon bellatrix merge" + "block number $MIN_BLOCK_NUM" +) +STATUS=0 + +LIGHTHOUSE_BASE_URL=${LIGHTHOUSE_BASE_URL} +GETH_BASE_URL=${GETH_BASE_URL} + +# TODO: Docker commands below should be replaced by some interface into stack orchestrator +# or some execution environment-neutral mechanism. +if [ -z "$LIGHTHOUSE_BASE_URL" ]; then + LIGHTHOUSE_CONTAINER=`docker ps -q -f "name=fixturenet-eth-lighthouse-1-1"` + if [ -z "$LIGHTHOUSE_CONTAINER" ]; then + echo "Lighthouse container not found." 1>&2 + exit 1 + fi + LIGHTHOUSE_PORT=`docker port $LIGHTHOUSE_CONTAINER 8001 | cut -d':' -f2` + LIGHTHOUSE_BASE_URL="http://localhost:${LIGHTHOUSE_PORT}" +fi + +if [ -z "$GETH_BASE_URL" ]; then + GETH_CONTAINER=`docker ps -q -f "name=fixturenet-eth-geth-1-1"` + if [ -z "$GETH_CONTAINER" ]; then + echo "Lighthouse container not found." 1>&2 + exit 1 + fi + GETH_PORT=`docker port $GETH_CONTAINER 8545 | cut -d':' -f2` + GETH_BASE_URL="http://localhost:${GETH_PORT}" +fi + +MARKER="." + +function inc_status() { + echo " done" + STATUS=$((STATUS + 1)) + if [ $STATUS -lt ${#STATUSES[@]} ]; then + echo -n "Waiting for ${STATUSES[$STATUS]}..." + fi +} + +echo -n "Waiting for ${STATUSES[$STATUS]}..." +while [ $STATUS -lt ${#STATUSES[@]} ]; do + sleep 1 + echo -n "$MARKER" + case $STATUS in + 0) + result=`wget --no-check-certificate --quiet -O - --method POST --header 'Content-Type: application/json' \ + --body-data '{ "jsonrpc": "2.0", "id": 1, "method": "eth_getBlockByNumber", "params": ["0x3", false] }' $GETH_BASE_URL | jq -r '.result'` + if [ ! -z "$result" ] && [ "null" != "$result" ]; then + inc_status + fi + ;; + 1) + result=`wget --no-check-certificate --quiet -O - "$LIGHTHOUSE_BASE_URL/eth/v2/beacon/blocks/head" | jq -r '.data.message.slot'` + if [ ! -z "$result" ] && [ $result -gt 0 ]; then + inc_status + fi + ;; + 2) + result=`wget --no-check-certificate --quiet -O - "$LIGHTHOUSE_BASE_URL/eth/v2/beacon/blocks/head" | jq -r '.version'` + if [ ! -z "$result" ] && ([ "$result" == "altair" ] || [ "$result" == "bellatrix" ]); then + inc_status + fi + ;; + 3) + result=`wget --no-check-certificate --quiet -O - "$LIGHTHOUSE_BASE_URL/eth/v2/beacon/blocks/head" | jq -r '.version'` + if [ ! -z "$result" ] && [ "$result" == "bellatrix" ]; then + inc_status + fi + ;; + 4) + result=`wget --no-check-certificate --quiet -O - "$LIGHTHOUSE_BASE_URL/eth/v2/beacon/blocks/head" | jq -r '.data.message.body.execution_payload.block_number'` + if [ ! -z "$result" ] && [ $result -gt 0 ]; then + inc_status + fi + ;; + 5) + result=`wget --no-check-certificate --quiet -O - "$LIGHTHOUSE_BASE_URL/eth/v2/beacon/blocks/head" | jq -r '.data.message.body.execution_payload.block_number'` + if [ ! -z "$result" ] && [ $result -gt $MIN_BLOCK_NUM ]; then + inc_status + else + MARKER="$result " + fi + ;; + esac +done diff --git a/container-build/cerc-go-ethereum/build.sh b/container-build/cerc-go-ethereum/build.sh new file mode 100755 index 0000000..171d007 --- /dev/null +++ b/container-build/cerc-go-ethereum/build.sh @@ -0,0 +1,4 @@ +#!/usr/bin/env bash +# Build cerc/go-ethereum +source ${CERC_CONTAINER_BASE_DIR}/build-base.sh +docker build -t cerc/go-ethereum:local ${build_command_args} ${CERC_REPO_BASE_DIR}/go-ethereum diff --git a/container-build/cerc-lighthouse-cli/build.sh b/container-build/cerc-lighthouse-cli/build.sh new file mode 100755 index 0000000..75719ef --- /dev/null +++ b/container-build/cerc-lighthouse-cli/build.sh @@ -0,0 +1,7 @@ +#!/usr/bin/env bash +# Build cerc/lighthouse-cli + +source ${CERC_CONTAINER_BASE_DIR}/build-base.sh + +project_dir=${CERC_REPO_BASE_DIR}/lighthouse +docker build -t cerc/lighthouse-cli:local --build-arg PORTABLE=true -f ${project_dir}/lcli/Dockerfile ${build_command_args} ${project_dir} diff --git a/container-build/cerc-lighthouse/Dockerfile b/container-build/cerc-lighthouse/Dockerfile new file mode 100644 index 0000000..de32150 --- /dev/null +++ b/container-build/cerc-lighthouse/Dockerfile @@ -0,0 +1,10 @@ +FROM sigp/lighthouse:v5.1.2 + +RUN apt-get update && apt-get -y upgrade \ + && apt-get -y install bash netcat curl less jq wget \ + && apt-get clean && rm -rf /var/lib/apt/lists/* + +WORKDIR /root +ADD start-lighthouse.sh . + +ENTRYPOINT [ "./start-lighthouse.sh" ] diff --git a/container-build/cerc-lighthouse/build.sh b/container-build/cerc-lighthouse/build.sh new file mode 100755 index 0000000..2e9cfe3 --- /dev/null +++ b/container-build/cerc-lighthouse/build.sh @@ -0,0 +1,9 @@ +#!/usr/bin/env bash +# Build cerc/lighthouse + +source ${CERC_CONTAINER_BASE_DIR}/build-base.sh + +# See: https://stackoverflow.com/a/246128/1701505 +SCRIPT_DIR=$( cd -- "$( dirname -- "${BASH_SOURCE[0]}" )" &> /dev/null && pwd ) + +docker build -t cerc/lighthouse:local ${build_command_args} ${SCRIPT_DIR} diff --git a/container-build/cerc-lighthouse/start-lighthouse.sh b/container-build/cerc-lighthouse/start-lighthouse.sh new file mode 100755 index 0000000..f254ada --- /dev/null +++ b/container-build/cerc-lighthouse/start-lighthouse.sh @@ -0,0 +1,9 @@ +#!/bin/bash + +# This bash script will be used to start the lighthouse client +# The 0.0.0.0 is not safe. + +lighthouse bn \ + --http --http-address 0.0.0.0 --metrics --private --network $NETWORK & + +tail -f /dev/null diff --git a/stacks/fixturenet-eth/README.md b/stacks/fixturenet-eth/README.md new file mode 100644 index 0000000..6f1ec8e --- /dev/null +++ b/stacks/fixturenet-eth/README.md @@ -0,0 +1,124 @@ +# fixturenet-eth + +Instructions for deploying a local a geth + lighthouse blockchain "fixturenet" for development and testing purposes using laconic-stack-orchestrator (the installation of which is covered [here](https://git.vdb.to/cerc-io/stack-orchestrator)): + +## Clone required repositories + +``` +$ laconic-so --stack fixturenet-eth setup-repositories +``` + +## Build the fixturenet-eth containers + +``` +$ laconic-so --stack fixturenet-eth build-containers +``` + +This should create several container images in the local image registry: + +* cerc/go-ethereum +* cerc/lighthouse +* cerc/fixturenet-eth-geth +* cerc/fixturenet-eth-lighthouse + +## Deploy the stack + +``` +$ laconic-so --stack fixturenet-eth deploy up +``` + +## Check status + +``` +$ laconic-so --stack fixturenet-eth deploy exec fixturenet-eth-bootnode-lighthouse /scripts/status-internal.sh +Waiting for geth to generate DAG.... done +Waiting for beacon phase0.... done +Waiting for beacon altair.... done +Waiting for beacon bellatrix pre-merge.... done +Waiting for beacon bellatrix merge.... done + +$ laconic-so --stack fixturenet-eth deploy ps +Running containers: +id: c6538b60c0328dadfa2c5585c4d09674a6a13e6d712ff1cd82a26849e4e5679b, name: laconic-b12fa16e999821562937781f8ab0b1e8-fixturenet-eth-bootnode-geth-1, ports: 0.0.0.0:58909->30303/tcp, 0.0.0.0:58910->9898/tcp +id: 5b70597a8211bc7e78d33e50486cb565a7f4a9ce581ce150b3bb450e342bdeda, name: laconic-b12fa16e999821562937781f8ab0b1e8-fixturenet-eth-bootnode-lighthouse-1, ports: +id: 19ed78867b6c534d893835cdeb1e89a9ea553b8e8c02ab02468e4bd1563a340f, name: laconic-b12fa16e999821562937781f8ab0b1e8-fixturenet-eth-geth-1-1, ports: 0.0.0.0:58911->40000/tcp, 0.0.0.0:58912->6060/tcp, 0.0.0.0:58913->8545/tcp +id: 8da0e30a1ce33122d8fd2225e4d26c7f30eb4bfbfa743f2af04d9db5d0bf7fa6, name: laconic-b12fa16e999821562937781f8ab0b1e8-fixturenet-eth-geth-2-1, ports: +id: 387a42a14971034588ba9aeb9b9e2ca7fc0cc61b96f8fe8c2ab770c9d6fb1e0f, name: laconic-b12fa16e999821562937781f8ab0b1e8-fixturenet-eth-lighthouse-1-1, ports: 0.0.0.0:58917->8001/tcp +id: de5115bf89087bae03b291664a73ffe3554fe23e79e4b8345e088b040d5580ac, name: laconic-b12fa16e999821562937781f8ab0b1e8-fixturenet-eth-lighthouse-2-1, ports: +id: 2a7e5a0fb2be7fc9261a7b725a40818facbbe6d0cb2497d82c0e02de0a8e959b, name: laconic-b12fa16e999821562937781f8ab0b1e8-foundry-1, ports: + +$ laconic-so --stack fixturenet-eth deploy exec foundry "cast block-number" +3 +``` + +## Additional pieces + +Several other containers can used with the basic `fixturenet-eth`: + +* `ipld-eth-db` (enables statediffing) +* `ipld-eth-server` (GQL and Ethereum API server, requires `ipld-eth-db`) +* `ipld-eth-beacon-db` and `ipld-eth-beacon-indexer` (for indexing Beacon chain blocks) +* `eth-probe` (captures eth1 tx gossip) +* `keycloak` (nginx proxy with keycloak auth for API authentication) +* `tx-spammer` (generates and sends automated transactions to the fixturenet) + +It is not necessary to use them all at once, but a complete example follows: + +``` +# Setup +$ laconic-so setup-repositories --include git.vdb.to/cerc-io/go-ethereum,git.vdb.to/cerc-io/ipld-eth-db,git.vdb.to/cerc-io/ipld-eth-server,github.com/cerc-io/ipld-eth-beacon-db,github.com/cerc-io/ipld-eth-beacon-indexer,github.com/cerc-io/eth-probe,git.vdb.to/cerc-io/tx-spammer + +# Build +$ laconic-so build-containers --include cerc/go-ethereum,cerc/lighthouse,cerc/fixturenet-eth-geth,cerc/fixturenet-eth-lighthouse,cerc/ipld-eth-db,cerc/ipld-eth-server,cerc/ipld-eth-beacon-db,cerc/ipld-eth-beacon-indexer,cerc/eth-probe,cerc/keycloak,cerc/tx-spammer + +# Deploy +$ laconic-so deploy-system --include db,fixturenet-eth,ipld-eth-server,ipld-eth-beacon-db,ipld-eth-beacon-indexer,eth-probe,keycloak,tx-spammer up + +# Status + +$ container-build/cerc-fixturenet-eth-lighthouse/scripts/status.sh +Waiting for geth to generate DAG.... done +Waiting for beacon phase0.... done +Waiting for beacon altair.... done +Waiting for beacon bellatrix pre-merge.... done +Waiting for beacon bellatrix merge.... done + +$ docker ps -f 'name=laconic' --format 'table {{.Names}}\t{{.Ports}}' | cut -d'-' -f3- | sort +NAMES PORTS +eth-probe-db-1 0.0.0.0:55849->5432/tcp +eth-probe-mq-1 +eth-probe-probe-1 +fixturenet-eth-bootnode-geth-1 8545-8546/tcp, 30303/udp, 0.0.0.0:55847->9898/tcp, 0.0.0.0:55848->30303/tcp +fixturenet-eth-bootnode-lighthouse-1 +fixturenet-eth-geth-1-1 8546/tcp, 30303/tcp, 30303/udp, 0.0.0.0:55851->8545/tcp +fixturenet-eth-geth-2-1 8545-8546/tcp, 30303/tcp, 30303/udp +fixturenet-eth-lighthouse-1-1 0.0.0.0:55858->8001/tcp +fixturenet-eth-lighthouse-2-1 +ipld-eth-beacon-db-1 127.0.0.1:8076->5432/tcp +ipld-eth-beacon-indexer-1 +ipld-eth-db-1 127.0.0.1:8077->5432/tcp +ipld-eth-server-1 127.0.0.1:8081-8082->8081-8082/tcp +keycloak-1 8443/tcp, 0.0.0.0:55857->8080/tcp +keycloak-db-1 0.0.0.0:55850->5432/tcp +keycloak-nginx-1 0.0.0.0:55859->80/tcp +migrations-1 +tx-spammer-1 +``` + +## Clean up + +Stop all services running in the background: + +```bash +$ laconic-so --stack fixturenet-eth deploy down +``` + +Clear volumes created by this stack: + +```bash +# List all relevant volumes +$ docker volume ls -q --filter "name=.*fixturenet_eth_bootnode_geth_data|.*fixturenet_eth_geth_1_data|.*fixturenet_eth_geth_2_data|.*fixturenet_eth_lighthouse_1_data|.*fixturenet_eth_lighthouse_2_data" + +# Remove all the listed volumes +$ docker volume rm $(docker volume ls -q --filter "name=.*fixturenet_eth_bootnode_geth_data|.*fixturenet_eth_geth_1_data|.*fixturenet_eth_geth_2_data|.*fixturenet_eth_lighthouse_1_data|.*fixturenet_eth_lighthouse_2_data") +``` diff --git a/stacks/fixturenet-eth/stack.yml b/stacks/fixturenet-eth/stack.yml new file mode 100644 index 0000000..ce57df4 --- /dev/null +++ b/stacks/fixturenet-eth/stack.yml @@ -0,0 +1,18 @@ +version: "1.1" +name: fixturenet-eth +description: "Ethereum Fixturenet" +repos: + - git.vdb.to/cerc-io/go-ethereum@v1.11.6-statediff-v5 + - git.vdb.to/cerc-io/lighthouse + - github.com/dboreham/foundry +containers: + - cerc/go-ethereum + - cerc/lighthouse + - cerc/lighthouse-cli + - cerc/fixturenet-eth-genesis + - cerc/fixturenet-eth-geth + - cerc/fixturenet-eth-lighthouse + - cerc/foundry +pods: + - fixturenet-eth + - foundry