From 034f82524c8e9e2377cd2b74f5b04bfb0ec0a114 Mon Sep 17 00:00:00 2001 From: lesterli Date: Sun, 20 Oct 2024 21:50:59 +0800 Subject: [PATCH] refactor to fix some issues --- .env.bitcoin.example | 10 ++--- .github/workflows/publish-bitcoin.yml | 9 +--- Makefile | 2 +- docker/docker-compose-bitcoin.yml | 3 +- scripts/bitcoin/entrypoint.sh | 62 ++------------------------ scripts/bitcoin/setup-wallet.sh | 43 ++++++++++++++++++ scripts/bitcoin/start.sh | 35 +++++++++++++++ scripts/bitcoin/verify-sync-balance.sh | 10 ++--- 8 files changed, 94 insertions(+), 80 deletions(-) create mode 100755 scripts/bitcoin/setup-wallet.sh create mode 100755 scripts/bitcoin/start.sh diff --git a/.env.bitcoin.example b/.env.bitcoin.example index ec8c3a9..9980620 100644 --- a/.env.bitcoin.example +++ b/.env.bitcoin.example @@ -1,15 +1,13 @@ NETWORK=regtest # regtest | signet RPC_PORT=18443 # 18443 (regtest) | 38332 (signet) -WALLET_PASS=walletpass -# btcstaker private key in WIF format -BTCSTAKER_PRIVKEY= RPC_USER=rpcuser RPC_PASS=rpcpass -WALLET_PASS=walletpass -WALLET_NAME=default BTCSTAKER_WALLET_NAME=btcstaker +BTCSTAKER_WALLET_PASS=walletpass +# btcstaker private key in WIF format +BTCSTAKER_PRIVKEY= ZMQ_SEQUENCE_PORT=29000 ZMQ_RAWBLOCK_PORT=29001 ZMQ_RAWTR_PORT=29002 # only used if BITCOIN_NETWORK=regtest -GENERATE_INTERVAL_SECS=10 \ No newline at end of file +GENERATE_INTERVAL_SECS=600 # 10 minutes \ No newline at end of file diff --git a/.github/workflows/publish-bitcoin.yml b/.github/workflows/publish-bitcoin.yml index 9a862b6..2a5d22d 100644 --- a/.github/workflows/publish-bitcoin.yml +++ b/.github/workflows/publish-bitcoin.yml @@ -7,9 +7,6 @@ name: publish-bitcoin on: push: - tags: - - 'v*' - pull_request: paths: - 'scripts/bitcoin/**' @@ -56,11 +53,7 @@ jobs: - name: Set Docker image tag id: set-tag run: | - if [[ $GITHUB_REF == refs/pull/* ]]; then - echo "TAG=$(git rev-parse --short HEAD)" >> $GITHUB_OUTPUT - elif [[ $GITHUB_REF == refs/tags/* ]]; then - echo "TAG=${GITHUB_REF#refs/tags/}" >> $GITHUB_OUTPUT - fi + echo "TAG=$(git rev-parse --short HEAD)" >> $GITHUB_OUTPUT # Build and push Docker image with Buildx (don't push on PR) # https://github.com/docker/build-push-action diff --git a/Makefile b/Makefile index 822225b..28178a2 100644 --- a/Makefile +++ b/Makefile @@ -4,7 +4,7 @@ start-babylon: .PHONY: start-babylon start-bitcoin: - @docker compose -f docker/docker-compose-bitcoin.yml up -d + @./scripts/bitcoin/start.sh .PHONY: start-bitcoin stop-bitcoin: diff --git a/docker/docker-compose-bitcoin.yml b/docker/docker-compose-bitcoin.yml index 423eb4d..427e93c 100644 --- a/docker/docker-compose-bitcoin.yml +++ b/docker/docker-compose-bitcoin.yml @@ -1,6 +1,6 @@ services: bitcoind: - image: snapchain/bitcoind:2a54e8e + image: snapchain/bitcoind:latest container_name: bitcoind env_file: - "${PWD}/.env.bitcoin" @@ -12,6 +12,7 @@ services: volumes: - "bitcoin_data:/bitcoind/.bitcoin" - "${PWD}/scripts/bitcoin/entrypoint.sh:/entrypoint.sh" + - "${PWD}/scripts/bitcoin/setup-wallet.sh:/setup-wallet.sh" entrypoint: - "/bin/bash" - "/entrypoint.sh" diff --git a/scripts/bitcoin/entrypoint.sh b/scripts/bitcoin/entrypoint.sh index 0d92d55..2c391c2 100755 --- a/scripts/bitcoin/entrypoint.sh +++ b/scripts/bitcoin/entrypoint.sh @@ -2,19 +2,14 @@ set -euo pipefail echo "NETWORK: $NETWORK" -echo "RPC PORT: $RPC_PORT" +echo "RPC_PORT: $RPC_PORT" if [[ "$NETWORK" != "regtest" && "$NETWORK" != "signet" ]]; then echo "Unsupported network: $NETWORK" exit 1 fi -if [[ "$NETWORK" == "regtest" && -z "$GENERATE_INTERVAL_SECS" ]]; then - GENERATE_INTERVAL_SECS=10 - echo "GENERATE_INTERVAL_SECS not set, using default: $GENERATE_INTERVAL_SECS" -fi - -DATA_DIR="/bitcoind/.bitcoin" +DATA_DIR=/bitcoind/.bitcoin CONF=/bitcoind/bitcoin.conf echo "Generating bitcoin.conf file at $CONF" @@ -52,55 +47,4 @@ rpcport=$RPC_PORT EOF echo "Starting bitcoind..." -bitcoind -${NETWORK} -datadir="$DATA_DIR" -conf="$CONF" -rpcport="$RPC_PORT" -daemon - -# Allow some time for bitcoind to start -sleep 5 - -if [[ "$NETWORK" == "regtest" ]]; then - if [[ ! -d "${DATA_DIR}/${NETWORK}/wallets/${WALLET_NAME}" ]]; then - echo "Creating a wallet..." - bitcoin-cli -${NETWORK} -rpcuser="$RPC_USER" -rpcpassword="$RPC_PASS" createwallet "$WALLET_NAME" false false "$WALLET_PASS" false false - fi - - echo "Opening ${WALLET_NAME} wallet..." - bitcoin-cli -${NETWORK} -rpcuser="$RPC_USER" -rpcpassword="$RPC_PASS" -rpcwallet="$WALLET_NAME" walletpassphrase "$WALLET_PASS" 10 - - echo "Generating 110 blocks for the first coinbases to mature..." - bitcoin-cli -${NETWORK} -rpcuser="$RPC_USER" -rpcpassword="$RPC_PASS" -rpcwallet="$WALLET_NAME" -generate 110 -fi - -if [[ ! -d "${DATA_DIR}/${NETWORK}/wallets/${BTCSTAKER_WALLET_NAME}" ]]; then - echo "Creating a wallet for btcstaker..." - bitcoin-cli -${NETWORK} -rpcuser="$RPC_USER" -rpcpassword="$RPC_PASS" createwallet "$BTCSTAKER_WALLET_NAME" false false "$WALLET_PASS" false false -fi - -echo "Opening ${BTCSTAKER_WALLET_NAME} wallet..." -bitcoin-cli -${NETWORK} -rpcuser="$RPC_USER" -rpcpassword="$RPC_PASS" -rpcwallet="$BTCSTAKER_WALLET_NAME" walletpassphrase "$WALLET_PASS" 10 -echo "Importing the private key to the wallet ${BTCSTAKER_WALLET_NAME} with the label ${BTCSTAKER_WALLET_NAME} without rescan..." -bitcoin-cli -${NETWORK} -rpcuser="$RPC_USER" -rpcpassword="$RPC_PASS" -rpcwallet="$BTCSTAKER_WALLET_NAME" importprivkey "$BTCSTAKER_PRIVKEY" "${BTCSTAKER_WALLET_NAME}" false - -# Allow some time for the wallet to catch up. -sleep 5 - -if [[ "$NETWORK" == "regtest" ]]; then - echo "Checking balance..." - bitcoin-cli -${NETWORK} -rpcuser="$RPC_USER" -rpcpassword="$RPC_PASS" -rpcwallet="$WALLET_NAME" getbalance - - echo "Getting the imported BTC address for wallet ${BTCSTAKER_WALLET_NAME}..." - BTCSTAKER_ADDR=$(bitcoin-cli -${NETWORK} -rpcuser="$RPC_USER" -rpcpassword="$RPC_PASS" -rpcwallet="$BTCSTAKER_WALLET_NAME" getaddressesbylabel "${BTCSTAKER_WALLET_NAME}" | jq -r 'keys[0]') - echo "Imported BTC address: ${BTCSTAKER_ADDR}" - - echo "Generating a block every ${GENERATE_INTERVAL_SECS} seconds..." - while true; do - bitcoin-cli -${NETWORK} -rpcuser="$RPC_USER" -rpcpassword="$RPC_PASS" -rpcwallet="$WALLET_NAME" -generate 1 - echo "Periodically send funds to the address ${BTCSTAKER_ADDR} for wallet ${BTCSTAKER_WALLET_NAME}..." - bitcoin-cli -${NETWORK} -rpcuser="$RPC_USER" -rpcpassword="$RPC_PASS" -rpcwallet="$WALLET_NAME" walletpassphrase "$WALLET_PASS" 10 - bitcoin-cli -${NETWORK} -rpcuser="$RPC_USER" -rpcpassword="$RPC_PASS" -rpcwallet="$WALLET_NAME" sendtoaddress "$BTCSTAKER_ADDR" 10 - sleep "${GENERATE_INTERVAL_SECS}" - done -elif [[ "$NETWORK" == "signet" ]]; then - # Keep the container running - echo "Bitcoind is running..." - tail -f /dev/null -fi +bitcoind -${NETWORK} -datadir="$DATA_DIR" -conf="$CONF" -rpcport="$RPC_PORT" \ No newline at end of file diff --git a/scripts/bitcoin/setup-wallet.sh b/scripts/bitcoin/setup-wallet.sh new file mode 100755 index 0000000..5ffea71 --- /dev/null +++ b/scripts/bitcoin/setup-wallet.sh @@ -0,0 +1,43 @@ +#!/bin/bash +set -euo pipefail + +echo "NETWORK: $NETWORK" +echo "BTCSTAKER_WALLET_NAME: $BTCSTAKER_WALLET_NAME" + +DATA_DIR=/bitcoind/.bitcoin + +if [[ ! -d "${DATA_DIR}/${NETWORK}/wallets/${BTCSTAKER_WALLET_NAME}" ]]; then + echo "Creating a wallet for btcstaker..." + bitcoin-cli -${NETWORK} -rpcuser="$RPC_USER" -rpcpassword="$RPC_PASS" createwallet "$BTCSTAKER_WALLET_NAME" false false "$BTCSTAKER_WALLET_PASS" false false +fi + +echo "Opening ${BTCSTAKER_WALLET_NAME} wallet..." +bitcoin-cli -${NETWORK} -rpcuser="$RPC_USER" -rpcpassword="$RPC_PASS" -rpcwallet="$BTCSTAKER_WALLET_NAME" walletpassphrase "$BTCSTAKER_WALLET_PASS" 10 +echo "Importing the private key to the wallet ${BTCSTAKER_WALLET_NAME} with the label ${BTCSTAKER_WALLET_NAME} without rescan..." +bitcoin-cli -${NETWORK} -rpcuser="$RPC_USER" -rpcpassword="$RPC_PASS" -rpcwallet="$BTCSTAKER_WALLET_NAME" importprivkey "$BTCSTAKER_PRIVKEY" "${BTCSTAKER_WALLET_NAME}" false + +if [[ "$NETWORK" == "regtest" ]]; then + echo "Generating 110 blocks for the first coinbases to mature..." + bitcoin-cli -${NETWORK} -rpcuser="$RPC_USER" -rpcpassword="$RPC_PASS" -rpcwallet="$BTCSTAKER_WALLET_NAME" -generate 110 + + # Waiting for the wallet to catch up. + sleep 5 + echo "Checking balance..." + bitcoin-cli -${NETWORK} -rpcuser="$RPC_USER" -rpcpassword="$RPC_PASS" -rpcwallet="$BTCSTAKER_WALLET_NAME" getbalance + + echo "Getting the imported BTC address for wallet ${BTCSTAKER_WALLET_NAME}..." + BTCSTAKER_ADDR=$(bitcoin-cli -${NETWORK} -rpcuser="$RPC_USER" -rpcpassword="$RPC_PASS" -rpcwallet="$BTCSTAKER_WALLET_NAME" getaddressesbylabel "${BTCSTAKER_WALLET_NAME}" | jq -r 'keys[0]') + echo "Imported BTC address: ${BTCSTAKER_ADDR}" + + if [[ -z "$GENERATE_INTERVAL_SECS" ]]; then + GENERATE_INTERVAL_SECS=600 # 10 minutes + fi + + echo "Starting block generation every $GENERATE_INTERVAL_SECS seconds in the background..." + ( + while true; do + bitcoin-cli -${NETWORK} -rpcuser="$RPC_USER" -rpcpassword="$RPC_PASS" -rpcwallet="$BTCSTAKER_WALLET_NAME" -generate 1 + sleep "$GENERATE_INTERVAL_SECS" + done + ) & +fi \ No newline at end of file diff --git a/scripts/bitcoin/start.sh b/scripts/bitcoin/start.sh new file mode 100755 index 0000000..d2e3084 --- /dev/null +++ b/scripts/bitcoin/start.sh @@ -0,0 +1,35 @@ +#!/bin/bash +set -euo pipefail + +# Load environment variables from .env.bitcoin file +set -a +source "$(pwd)/.env.bitcoin" +set +a + +# Start the bitcoin container +echo "Starting the bitcoin container..." +docker compose -f "$(pwd)/docker/docker-compose-bitcoin.yml" up -d + +# Wait for the bitcoin node to be ready +echo "Waiting for the bitcoin node to be ready..." +sleep 5 + +max_attempts=10 +attempt=0 +while ! docker exec bitcoind bitcoin-cli -${NETWORK} -rpcuser="$RPC_USER" -rpcpassword="$RPC_PASS" getblockchaininfo &>/dev/null; do + sleep 2 + ((attempt++)) + if [ $attempt -ge $max_attempts ]; then + echo "Timeout waiting for bitcoin node to be ready." + exit 1 + fi +done + +echo "Bitcoin node is ready!" +echo + +# Setup the wallet +echo "Setting up the wallet..." +docker exec -it bitcoind /setup-wallet.sh +echo "Wallet setup done!" +echo \ No newline at end of file diff --git a/scripts/bitcoin/verify-sync-balance.sh b/scripts/bitcoin/verify-sync-balance.sh index 0f7963e..3504f73 100755 --- a/scripts/bitcoin/verify-sync-balance.sh +++ b/scripts/bitcoin/verify-sync-balance.sh @@ -6,13 +6,13 @@ set -a source $(pwd)/.env.bitcoin set +a -if [ -z "$(echo ${WALLET_PASS})" ] || [ -z "$(echo ${BTCSTAKER_PRIVKEY})" ]; then - echo "Error: WALLET_PASS or BTCSTAKER_PRIVKEY environment variable is not set" +if [ -z "$(echo ${BTCSTAKER_WALLET_PASS})" ] || [ -z "$(echo ${BTCSTAKER_PRIVKEY})" ]; then + echo "Error: BTCSTAKER_WALLET_PASS or BTCSTAKER_PRIVKEY environment variable is not set" exit 1 fi echo "Environment variables loaded successfully" echo "NETWORK: $NETWORK" -echo "RPC PORT: $RPC_PORT" +echo "RPC_PORT: $RPC_PORT" echo echo "Checking if Bitcoin node is synced..." @@ -26,7 +26,7 @@ if (( $(awk -v synced="$SYNCED" 'BEGIN {print (synced < 0.999)}') )); then echo "Error: Bitcoin node is not fully synced. Expected at least 99.9%, got ${SYNCED}" exit 1 fi -echo "Bitcoin node is synced: ${SYNCED}" +echo "Bitcoin node is synced" echo # Check btcstaker address @@ -37,7 +37,7 @@ BTCSTAKER_ADDRESS=$(docker exec bitcoind /bin/sh -c " -rpcpassword=${RPC_PASS} \ -rpcwallet=${BTCSTAKER_WALLET_NAME} \ getaddressesbylabel \"${BTCSTAKER_WALLET_NAME}\"" \ - | jq -r 'keys[] | select(startswith("tb1"))') + | jq -r 'keys[0]') echo "BTCStaker address: ${BTCSTAKER_ADDRESS}" # Check if btcstaker has any unspent transactions