diff --git a/README.md b/README.md index 6561249..64b63f5 100644 --- a/README.md +++ b/README.md @@ -1 +1,5 @@ -# bsc-stack \ No newline at end of file +# bsc-stack + +Stack definitions for BSC node deployment. + +[stack documentation](stack-orchestrator/stacks/bsc-node/README.md) diff --git a/stack-orchestrator/compose/docker-compose-bsc-node.yml b/stack-orchestrator/compose/docker-compose-bsc-node.yml new file mode 100644 index 0000000..9789a63 --- /dev/null +++ b/stack-orchestrator/compose/docker-compose-bsc-node.yml @@ -0,0 +1,32 @@ +services: + bsc: + image: cerc/bsc-geth:local + restart: unless-stopped + environment: + CERC_BSC_NETWORK: ${CERC_BSC_NETWORK:-mainnet} + CERC_USE_SNAPSHOT: ${CERC_USE_SNAPSHOT:-false} + CERC_FAST_NODE: ${CERC_FAST_NODE:-false} + CERC_GETH_GCMODE: ${CERC_GETH_GCMODE:-full} + CERC_GETH_VERBOSITY: ${CERC_GETH_VERBOSITY:-3} + volumes: + - ../config/bsc-node/docker-entrypoint.sh:/bsc/docker-entrypoint.sh + - data:/data + - bsc:/bsc + - snapshot:/var/tmp/snapshot + ports: + - "30303" + - "30311" + - "6060" + - "8545" + - "8546" + healthcheck: + test: ["CMD", "nc", "-vz", "localhost", "8545"] + interval: 5s + retries: 5 + start_period: 10s + timeout: 3s + +volumes: + data: + bsc: + snapshot: diff --git a/stack-orchestrator/config/bsc-node/docker-entrypoint.sh b/stack-orchestrator/config/bsc-node/docker-entrypoint.sh new file mode 100755 index 0000000..056a1d0 --- /dev/null +++ b/stack-orchestrator/config/bsc-node/docker-entrypoint.sh @@ -0,0 +1,96 @@ +#!/bin/bash + +set -e + +echo "Setting up BSC $CERC_BSC_NETWORK" +echo DATA_DIR: ${DATA_DIR} +echo BSC_HOME: ${BSC_HOME} + +BSC_CONFIG=${BSC_HOME}/config/config.toml +BSC_GENESIS=${BSC_HOME}/config/genesis.json + +# Setup config +if [ -f "$BSC_CONFIG" ]; then + echo "Config file found at $BSC_CONFIG" +else + echo "Config file not found at $BSC_CONFIG, downloading config for $CERC_BSC_NETWORK..." + + # Download and unzip the config files (https://github.com/bnb-chain/bsc/releases/tag/v1.4.8) + wget -O config.zip $(curl -s https://api.github.com/repos/bnb-chain/bsc/releases/156666248 | grep browser_ | grep $CERC_BSC_NETWORK | cut -d\" -f4) + unzip config.zip -d config +fi + +# Use snapshot if provided +# Take first file from the snapshot dir +snapshot_file=$((ls /var/tmp/snapshot/*) 2>/dev/null | head -1) +geth_dir=${DATA_DIR}/geth +ADDITIONAL_FLAGS="" +if [ ! -d "$geth_dir" ] && [ "${CERC_USE_SNAPSHOT}" = "true" ] && [ -n "$snapshot_file" ]; then + echo "Using snapshot $snapshot_file" + + case $snapshot_file in + *.lz4) + # Determine where geth dir is located + archive_geth_path=$(lz4 -c -d $snapshot_file | tar -tf - | grep -m1 -E 'geth/?$') + + # Determine strip-components count from the path + to_strip=$(($(echo "$archive_geth_path" | grep -o '/' | wc -l) - 1)) + + lz4 -c -d $snapshot_file | tar -C ${DATA_DIR}/ -xvf - --strip-components=$to_strip $archive_geth_path + ;; + *.zst) + archive_geth_path=$(zstd -c -d $snapshot_file | tar -tf - | grep -m1 -E 'geth/?$') + to_strip=$(($(echo "$archive_geth_path" | grep -o '/' | wc -l) - 1)) + + zstd -c -d $snapshot_file | tar -C ${DATA_DIR}/ -xvf - --strip-components=$to_strip $archive_geth_path + ;; + *) + echo "Unsupported archive format for the snapshot file: $snapshot_file" + exit 1 + ;; + esac + + if [ "${CERC_FAST_NODE}" = "true" ]; then + echo "Pruning trie data and turning snapshot verification off" + + # Prune all trie data from the snapshot + geth snapshot insecure-prune-all --datadir ${DATA_DIR} ${BSC_GENESIS} + + # Turn off snapshot verification + ADDITIONAL_FLAGS="--tries-verify-mode none" + fi +fi + +# Init genesis state if geth sub dir does not exist +if [ ! -d "$geth_dir" ]; then + STATE_SCHEME_OPTS="" + if [ "$CERC_GETH_GCMODE" = "archive" ]; then + # Archive mode only works with state.scheme set to hash + STATE_SCHEME_OPTS="--state.scheme=hash" + fi + + echo "Initializing geth..." + geth --datadir ${DATA_DIR} ${STATE_SCHEME_OPTS} init ${BSC_GENESIS} + echo "Initialization done" +fi + +exec "geth" \ + --config="${BSC_CONFIG}" \ + --datadir="${DATA_DIR}" \ + --rpc.allow-unprotected-txs \ + --history.transactions 0 \ + --http \ + --http.addr="0.0.0.0" \ + --http.port 8545 \ + --http.vhosts="*" \ + --http.corsdomain="*" \ + --ws \ + --ws.addr="0.0.0.0" \ + --ws.port 8546 \ + --ws.origins="*" \ + --gcmode=${CERC_GETH_GCMODE} \ + --verbosity=${CERC_GETH_VERBOSITY} \ + --metrics \ + --metrics.addr="0.0.0.0" \ + ${ADDITIONAL_FLAGS} \ + "$@" diff --git a/stack-orchestrator/container-build/cerc-bsc-geth/Dockerfile b/stack-orchestrator/container-build/cerc-bsc-geth/Dockerfile new file mode 100644 index 0000000..f159a76 --- /dev/null +++ b/stack-orchestrator/container-build/cerc-bsc-geth/Dockerfile @@ -0,0 +1,8 @@ +FROM ghcr.io/bnb-chain/bsc:1.4.8 + +USER root + +# Add lz4, zstd and tar for extracting snapshot files +RUN apk add lz4 zstd tar + +USER bsc diff --git a/stack-orchestrator/container-build/cerc-bsc-geth/build.sh b/stack-orchestrator/container-build/cerc-bsc-geth/build.sh new file mode 100755 index 0000000..3c398ac --- /dev/null +++ b/stack-orchestrator/container-build/cerc-bsc-geth/build.sh @@ -0,0 +1,7 @@ +#!/usr/bin/env bash + +source ${CERC_CONTAINER_BASE_DIR}/build-base.sh +SCRIPT_DIR=$( cd -- "$( dirname -- "${BASH_SOURCE[0]}" )" &> /dev/null && pwd ) + +# Build cerc/bsc-geth +docker build -t cerc/bsc-geth:local ${build_command_args} ${SCRIPT_DIR} diff --git a/stack-orchestrator/stacks/bsc-node/README.md b/stack-orchestrator/stacks/bsc-node/README.md new file mode 100644 index 0000000..9853f6f --- /dev/null +++ b/stack-orchestrator/stacks/bsc-node/README.md @@ -0,0 +1,137 @@ +# bsc-node + +Instructions for running a BSC node + +## Setup + +* (Optional) Download the snapshot for BSC network (mainnet | testnet) by following instructions from + + ```bash + # Example (mainnet) + wget -O geth.tar.lz4 https://pub-c0627345c16f47ab858c9469133073a8.r2.dev/geth-pbss-pebble-20240514.tar.lz4 + + # Example (testnet) + wget -O geth.testnet.tar.lz4 https://pub-c0627345c16f47ab858c9469133073a8.r2.dev/testnet-geth-pbss-20240307.tar.lz4 + ``` + +* Clone the stack repo: + + ```bash + laconic-so fetch-stack git.vdb.to/cerc-io/bsc-stack + ``` + +* Build the container images: + + ```bash + laconic-so --stack ~/cerc/bsc-stack/stack-orchestrator/stacks/bsc-node build-containers + ``` + +## Create a deployment + +* Create a spec file for the deployment: + + ```bash + laconic-so --stack ~/cerc/bsc-stack/stack-orchestrator/stacks/bsc-node deploy init --map-ports-to-host any-same --output bsc-node-spec.yml + ``` + +* Edit `network` in the spec file to map container ports to host ports as required + +* Create a deployment directory from the spec file: + + ```bash + laconic-so --stack ~/cerc/bsc-stack/stack-orchestrator/stacks/bsc-node deploy create --spec-file bsc-node-spec.yml --deployment-dir bsc-node-deployment + ``` + +* (Optional) Copy over the snapshot file (`*.tar.lz4` or `*.tar.zst`) in snapshot data directory in the deployment (`bsc-node-deployment/data/snapshot`): + + ```bash + # Example + cp geth.tar.lz4 bsc-node-deployment/data/snapshot/ + ``` + +## Configuration + +* Environment variables for BSC node can be configured by setting them in `config.env` inside the deployment directory: + + ```bash + # All optional + # Runs a full node syncing from genesis if none are set + + # BSC network to run (mainnet | testnet) (default: mainnet) + CERC_BSC_NETWORK= + + # Whether to sync from a snapshot (true | false) (default: false) + # Requires snapshot file with extension .tar.lz4 or .tar.zst to be placed in the snapshot directory + CERC_USE_SNAPSHOT= + + # Whether to run as a fast node (true | false) (default: false) + # Fast node does not generate trie data when syncing + CERC_FAST_NODE= + + # Garbage collection mode (full | archive) (default: full) + # Set to archive for archive node + CERC_GETH_GCMODE= + + # Logging verbosity (default: 3) + # 0=silent, 1=error, 2=warn, 3=info, 4=debug, 5=detail + CERC_GETH_VERBOSITY= + ``` + +## Start the deployment + +```bash +laconic-so deployment --dir bsc-node-deployment up +``` + +## Check status + +* To list down and monitor the running containers: + + ```bash + # With status + docker ps -a + + # Check logs for a container + docker logs -f + ``` + +* Check Synchronization: + + ```bash + # Start geth console + laconic-so deployment --dir bsc-node-deployment exec bsc "geth attach ipc:/data/geth.ipc" + + >eth.syncing + ``` + +* Check geth logs: + + ```bash + laconic-so deployment --dir bsc-node-deployment exec bsc "tail -f /data/bsc.log" + ``` + +## Clean up + +* Stop all services running in the background: + + ```bash + # Stop the docker containers + laconic-so deployment --dir bsc-node-deployment down + ``` + +* To stop all services and also delete data: + + ```bash + # Stop the docker containers + laconic-so deployment --dir bsc-node-deployment down --delete-volumes + + # Remove deployment directory (deployment will have to be recreated for a re-run) + rm -r bsc-node-deployment + ``` + +## Upgrading + +To upgrade the BSC release being used: + +* Upgrade the base Docker image used in [Dockerfile](`stack-orchestrator/container-build/cerc-bsc-geth/Dockerfile`) +* Update the release assets URL used for fetching config files in [docker-entrypoint.sh](stack-orchestrator/config/bsc-node/docker-entrypoint.sh) diff --git a/stack-orchestrator/stacks/bsc-node/stack.yml b/stack-orchestrator/stacks/bsc-node/stack.yml new file mode 100644 index 0000000..a017c2e --- /dev/null +++ b/stack-orchestrator/stacks/bsc-node/stack.yml @@ -0,0 +1,8 @@ +version: "1.0" +name: bsc-node +description: "BSC node stack" +repos: +containers: + - cerc/bsc-geth +pods: + - bsc-node