diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index cb25f1a874..1d755b671a 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -528,7 +528,23 @@ jobs: - name: release notes check run: scripts/check-release-notes.sh - + + ######################## + # Backwards Compatibility Test + ######################## + backwards-compatability-test: + name: backwards compatability test + runs-on: ubuntu-latest + steps: + - name: git checkout + uses: actions/checkout@v4 + + - name: ๐Ÿณ Set up Docker Buildx + uses: docker/setup-buildx-action@v3 + + - name: ๐Ÿ›ก๏ธ backwards compatibility test + run: make backwards-compat-test + # Notify about the completion of all coverage collecting jobs. finish: if: ${{ always() }} diff --git a/Makefile b/Makefile index fc7a041182..511344d83f 100644 --- a/Makefile +++ b/Makefile @@ -364,6 +364,11 @@ help: Makefile @$(call print, "Listing commands:") @sed -n 's/^#?//p' $< | column -t -s ':' | sort | sed -e 's/^/ /' +#? backwards-compat-test: Run basic backwards compatibility test +backwards-compat-test: + @$(call print, "Running backwards compatability test") + ./scripts/bw-compatibility-test/test.sh + #? sqlc: Generate sql models and queries in Go sqlc: @$(call print, "Generating sql models and queries in Go") diff --git a/docs/release-notes/release-notes-0.19.0.md b/docs/release-notes/release-notes-0.19.0.md index 1e3da2f326..118c1fde5d 100644 --- a/docs/release-notes/release-notes-0.19.0.md +++ b/docs/release-notes/release-notes-0.19.0.md @@ -319,6 +319,9 @@ The underlying functionality between those two options remain the same. * [Fixed](https://github.com/lightningnetwork/lnd/pull/9549) a long standing unit test flake found in the `chainntnfs/bitcoindnotify` package. + +* Add a new CI-step to do some basic [backwards compatibility + testing](https://github.com/lightningnetwork/lnd/pull/9540) for each PR. ## Database diff --git a/scripts/bw-compatibility-test/.env b/scripts/bw-compatibility-test/.env new file mode 100644 index 0000000000..7fbd8d106e --- /dev/null +++ b/scripts/bw-compatibility-test/.env @@ -0,0 +1,3 @@ +BITCOIND_VERSION=26 +LND_LATEST_VERSION=v0.18.5-beta +TIMEOUT=15 diff --git a/scripts/bw-compatibility-test/README.md b/scripts/bw-compatibility-test/README.md new file mode 100644 index 0000000000..0db91ad83f --- /dev/null +++ b/scripts/bw-compatibility-test/README.md @@ -0,0 +1,125 @@ +# Basic Backwards Compatibility Test + +This directory houses some docker compose files and various bash helpers all +used by the main `test.sh` file which runs the test. The idea is to be able to +test that a node can be upgraded from a stable release to a checked out branch +of LND and still function as expected with nodes running the stable release. + +## Test Flow + +The test sets up the following network: + +``` +Alice <---> Bob <---> Charlie <---> Dave +``` + +Initially, all the nodes are running a tagged LND release. This is all +configured via the main `docker-compose.yaml` file. + +1. The Bob node is the node we will focus on. While Bob is still on a stable + version of LND, we ensure that he can: send and receive multi-hop payments as + well as route payments. + +2. Bob is then shutdown. + +3. The `docker-compose.override.yaml` file is then loaded and used to spin up + Bob again but this time using the checked out branch of LND. This is done by + using the `dev.Dockerfile` in the LND repo. + +4. The test now waits for this new version of Bob (which uses the same data + directory as the previous version) to sync up with the network, reactivate + its channels. + +5. Finally, basic send, receive and routing tests are run to ensure that Bob + is still functional after the upgrade. + +## How to use this directory + +1. If you would just like to run the full test from start to finish, then all + you need to do is run: + + ```bash + ./test.sh + ``` + +2. If you would like to run the test in parts, then you can use the `execute.sh` + script to call the various functions in the directory. Here is an example: + ```bash + # Spin up the docker containers. + ./execute.sh compose_up + + # Wait for the nodes to start. + ./execute.sh wait_for_nodes alice bob charlie dave + + # Query various nodes. + ./execute.sh alice getinfo + + # Set-up a basic channel network. + ./execute.sh setup-network + + # Wait for bob to see all the channels in the network. + ./execute.sh wait_graph_sync bob 3 + + # Open a channel between Bob and Charlie. + ./execute.sh open_channel bob charlie + + # Send a payment from Alice to Dave. + ./execute.sh send_payment alice dave + + # Take down a single node. + ./execute.sh compose_stop dave + + # Start a single node. + ./execute.sh compose_start dave + + ``` + +## File Descriptions: + +##### `test.sh` + +This script runs the full backwards compatibility test. + + ```bash + ./test.sh + ``` + +##### `execute.sh` + +A helper script that allows you to call the various functions in the directory. + +This is useful if you are debugging something and want to step through the test +steps manually while keeping the main network running. + +For example: +```bash + # Spin up the docker containers. + ./execute.sh compose_up + + # Query various nodes. + ./execute.sh alice getinfo +``` + +#### `compose.sh` + +This script contains all the docker-compose variables and helper functions that +are used in the test. + +#### `network.sh` + +This script contains all the various helper functions that can be used to +interact with the Lightning nodes in the network. + +### `vars.sh` + +Any global variables used across the other scripts are defined here. + +#### `docker-compose.yaml` + +This docker compose file contains the network configuration for all the nodes +running a stable LND tag. + +#### `docker-compose.override.yaml` + +This compose file adds defines the `bob-pr` service which will pull and build +the LND branch that is currently checked out. diff --git a/scripts/bw-compatibility-test/compose.sh b/scripts/bw-compatibility-test/compose.sh new file mode 100755 index 0000000000..6c06cbc67b --- /dev/null +++ b/scripts/bw-compatibility-test/compose.sh @@ -0,0 +1,61 @@ +#!/bin/bash + +# DIR is set to the directory of this script. +DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" + +# The way we call docker-compose depends on the installation. +if which docker-compose > /dev/null; then + COMPOSE_CMD="docker-compose" +else + COMPOSE_CMD="docker compose" +fi + +# Common arguments that we want to pass to docker-compose. +# By default, this only includes the main docker-compose file +# and not the override file. Use the `compose_upgrade` method +# to load both docker compose files. +COMPOSE_ARGS="-f $DIR/docker-compose.yaml -p regtest" +COMPOSE="$COMPOSE_CMD $COMPOSE_ARGS" + +# compose_upgrade sets COMPOSE_ARGS and COMPOSE such that +# both the main docker-compose file and the override file +# are loaded. +function compose_upgrade() { + export COMPOSE_ARGS="-p regtest" + export COMPOSE="$COMPOSE_CMD $COMPOSE_ARGS" +} + +# compose_up starts the docker-compose cluster. +function compose_up() { + echo "๐Ÿณ Starting the cluster" + $COMPOSE up -d --quiet-pull +} + +# compose_down tears down the docker-compose cluster +# and removes all volumes and orphans. +function compose_down() { + echo "๐Ÿณ Tearing down the cluster" + $COMPOSE down --volumes --remove-orphans +} + +# compose_stop stops a specific service in the cluster. +function compose_stop() { + local service="$1" + echo "๐Ÿณ Stopping $service" + $COMPOSE stop "$service" +} + +# compose_start starts a specific service in the cluster. +function compose_start() { + local service="$1" + echo "๐Ÿณ Starting $service" + $COMPOSE up -d $service +} + +# compose_rebuild forces the rebuild of the image for a +# specific service in the cluster. +function compose_rebuild() { + local service="$1" + echo "๐Ÿณ Rebuilding $service" + $COMPOSE build --no-cache $service +} diff --git a/scripts/bw-compatibility-test/docker-compose.override.yaml b/scripts/bw-compatibility-test/docker-compose.override.yaml new file mode 100644 index 0000000000..52e53d72b1 --- /dev/null +++ b/scripts/bw-compatibility-test/docker-compose.override.yaml @@ -0,0 +1,43 @@ +services: + bob-pr: + build: + context: ../../ + dockerfile: dev.Dockerfile + container_name: bob-pr + restart: unless-stopped + ports: + - 10012:10009 + - 9742:9735 + - 8092:8080 + networks: + regtest: + aliases: + - bob + volumes: + - "bob:/root/.lnd" + depends_on: + - bitcoind + command: > + lnd + --logdir=/root/.lnd + --alias=bob + --rpclisten=0.0.0.0:10009 + --restlisten=0.0.0.0:8080 + --color=#cccccc + --noseedbackup + --bitcoin.active + --bitcoin.regtest + --bitcoin.node=bitcoind + --bitcoind.rpchost=bitcoind + --bitcoind.rpcuser=lightning + --bitcoind.rpcpass=lightning + --bitcoind.zmqpubrawblock=tcp://bitcoind:28332 + --bitcoind.zmqpubrawtx=tcp://bitcoind:28333 + --debuglevel=debug + --externalip=bob + --tlsextradomain=bob + --accept-keysend + --protocol.option-scid-alias + --protocol.zero-conf + --protocol.simple-taproot-chans + --trickledelay=50 \ No newline at end of file diff --git a/scripts/bw-compatibility-test/docker-compose.yaml b/scripts/bw-compatibility-test/docker-compose.yaml new file mode 100644 index 0000000000..8e39447c22 --- /dev/null +++ b/scripts/bw-compatibility-test/docker-compose.yaml @@ -0,0 +1,197 @@ +services: + bitcoind: + image: lightninglabs/bitcoin-core:${BITCOIND_VERSION} + container_name: bitcoind + restart: unless-stopped + ports: + - 18443:18443 + - 18444:18444 + - 28332:28332 + - 28333:28333 + networks: + regtest: + aliases: + - bitcoind + command: + - "-txindex" + - "-regtest" + - "-rest" + - "-printtoconsole" + - "-zmqpubrawblock=tcp://0.0.0.0:28332" + - "-zmqpubrawtx=tcp://0.0.0.0:28333" + - "-rpcport=18443" + - "-rpcbind=0.0.0.0" + - "-rpcauth=lightning:8492220e715bbfdf5f165102bfd7ed4$$88090545821ed5e9db614588c0afbad575ccc14681fb77f3cae6899bc419af67" + - "-rpcallowip=0.0.0.0/0" + - "-fallbackfee=0.0002" + - "-peerblockfilters=1" + - "-blockfilterindex=1" + - "-wallet=/home/bitcoin/.bitcoin/regtest/wallets/miner" + environment: + - HOME=/home/bitcoin + volumes: + - bitcoind:/home/bitcoin/.bitcoin + + alice: + image: lightninglabs/lnd:${LND_LATEST_VERSION} + container_name: alice + restart: unless-stopped + ports: + - 10011:10009 + - 9741:9735 + - 8091:8080 + networks: + regtest: + aliases: + - alice + volumes: + - "alice:/root/.lnd" + depends_on: + - bitcoind + command: + - "--logdir=/root/.lnd" + - "--alias=alice" + - "--rpclisten=0.0.0.0:10009" + - "--restlisten=0.0.0.0:8080" + - "--color=#cccccc" + - "--noseedbackup" + - "--bitcoin.active" + - "--bitcoin.regtest" + - "--bitcoin.node=bitcoind" + - "--bitcoind.rpchost=bitcoind" + - "--bitcoind.rpcuser=lightning" + - "--bitcoind.rpcpass=lightning" + - "--bitcoind.zmqpubrawblock=tcp://bitcoind:28332" + - "--bitcoind.zmqpubrawtx=tcp://bitcoind:28333" + - "--debuglevel=debug" + - "--externalip=alice" + - "--tlsextradomain=alice" + - "--accept-keysend" + - "--protocol.option-scid-alias" + - "--protocol.zero-conf" + - "--protocol.simple-taproot-chans" + - "--trickledelay=50" + + bob: + image: lightninglabs/lnd:${LND_LATEST_VERSION} + container_name: bob + restart: unless-stopped + ports: + - 10012:10009 + - 9742:9735 + - 8092:8080 + networks: + regtest: + aliases: + - bob + volumes: + - "bob:/root/.lnd" + depends_on: + - bitcoind + command: + - "--logdir=/root/.lnd" + - "--alias=bob" + - "--rpclisten=0.0.0.0:10009" + - "--restlisten=0.0.0.0:8080" + - "--color=#cccccc" + - "--noseedbackup" + - "--bitcoin.active" + - "--bitcoin.regtest" + - "--bitcoin.node=bitcoind" + - "--bitcoind.rpchost=bitcoind" + - "--bitcoind.rpcuser=lightning" + - "--bitcoind.rpcpass=lightning" + - "--bitcoind.zmqpubrawblock=tcp://bitcoind:28332" + - "--bitcoind.zmqpubrawtx=tcp://bitcoind:28333" + - "--debuglevel=debug" + - "--externalip=bob" + - "--tlsextradomain=bob" + - "--accept-keysend" + - "--protocol.option-scid-alias" + - "--protocol.zero-conf" + - "--protocol.simple-taproot-chans" + - "--trickledelay=50" + + charlie: + image: lightninglabs/lnd:${LND_LATEST_VERSION} + container_name: charlie + restart: unless-stopped + ports: + - 10013:10009 + - 9743:9735 + - 8093:8080 + networks: + regtest: + aliases: + - charlie + volumes: + - "charlie:/root/.lnd" + depends_on: + - bitcoind + command: + - "--logdir=/root/.lnd" + - "--alias=charlie" + - "--rpclisten=0.0.0.0:10009" + - "--restlisten=0.0.0.0:8080" + - "--color=#cccccc" + - "--noseedbackup" + - "--bitcoin.active" + - "--bitcoin.regtest" + - "--bitcoin.node=bitcoind" + - "--bitcoind.rpchost=bitcoind" + - "--bitcoind.rpcuser=lightning" + - "--bitcoind.rpcpass=lightning" + - "--bitcoind.zmqpubrawblock=tcp://bitcoind:28332" + - "--bitcoind.zmqpubrawtx=tcp://bitcoind:28333" + - "--debuglevel=debug" + - "--externalip=charlie" + - "--tlsextradomain=charlie" + - "--accept-keysend" + - "--trickledelay=50" + + dave: + image: lightninglabs/lnd:${LND_LATEST_VERSION} + container_name: dave + restart: unless-stopped + ports: + - 10014:10009 + - 9744:9735 + - 8094:8080 + networks: + regtest: + aliases: + - dave + volumes: + - "dave:/root/.lnd" + depends_on: + - bitcoind + command: + - "--logdir=/root/.lnd" + - "--alias=dave" + - "--rpclisten=0.0.0.0:10009" + - "--restlisten=0.0.0.0:8080" + - "--color=#cccccc" + - "--noseedbackup" + - "--bitcoin.active" + - "--bitcoin.regtest" + - "--bitcoin.node=bitcoind" + - "--bitcoind.rpchost=bitcoind" + - "--bitcoind.rpcuser=lightning" + - "--bitcoind.rpcpass=lightning" + - "--bitcoind.zmqpubrawblock=tcp://bitcoind:28332" + - "--bitcoind.zmqpubrawtx=tcp://bitcoind:28333" + - "--debuglevel=debug" + - "--externalip=dave" + - "--tlsextradomain=dave" + - "--accept-keysend" + - "--trickledelay=50" + +networks: + regtest: + +volumes: + bitcoind: + alice: + bob: + charlie: + dave: diff --git a/scripts/bw-compatibility-test/execute.sh b/scripts/bw-compatibility-test/execute.sh new file mode 100755 index 0000000000..d88c0f4fb2 --- /dev/null +++ b/scripts/bw-compatibility-test/execute.sh @@ -0,0 +1,16 @@ +#!/bin/bash + +# The execute.sh file can be used to call any helper functions directly +# from the command line. For example: +# $ ./execute.sh compose-up + +# DIR is set to the directory of this script. +DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" + +source "$DIR/.env" +source "$DIR/compose.sh" +source "$DIR/network.sh" + +CMD=$1 +shift +$CMD "$@" \ No newline at end of file diff --git a/scripts/bw-compatibility-test/network.sh b/scripts/bw-compatibility-test/network.sh new file mode 100644 index 0000000000..77a558e8ee --- /dev/null +++ b/scripts/bw-compatibility-test/network.sh @@ -0,0 +1,337 @@ +#!/bin/bash + +# DIR is set to the directory of this script. +DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" + +source "$DIR/.env" + +# Global variable to keep track of which Bob container to use. +# Once Bob is upgraded to the PR version, this variable must +# be updated to 'bob-pr'. +BOB=bob + +# upgrade_bob shuts down the stable Bob container, upgrades the +# compose variables to use the PR version of Bob, rebuilds the +# Bob container, and starts the PR version of Bob. +function upgrade_bob() { + # Shutdown Bob. + compose_stop bob + + # Upgrade the compose variables so that the Bob configuration + # is swapped out for the PR version. + compose_upgrade + export BOB=bob-pr + + # Force the rebuild of the Bob container. + compose_rebuild bob-pr + + # This should now start with the new version of Bob. + compose_start bob-pr +} + +# wait_for_nodes waits for all the nodes in the argument list to +# start. +function wait_for_nodes() { + local nodes=("$@") + + for node in "${nodes[@]}"; do + wait_for_node $node + done + echo "๐ŸŽ๏ธ All nodes have started!" +} + +# wait_for_node waits for the given node in the cluster to start, with a timeout. +wait_for_node() { + if [[ $# -ne 1 ]]; then + echo "โŒ Error: wait_for_node requires exactly 1 argument (node)" + echo "Usage: wait_for_node " + return 1 + fi + + local node="$1" + local start_time=$(date +%s) + + echo -n "โŒ› Waiting for $node to start (timeout: ${TIMEOUT}s)" + + while ! $node getinfo 2>/dev/null | grep -q identity_pubkey; do + echo -n "." + sleep 0.5 + + # Check if timeout has been reached + local elapsed_time=$(( $(date +%s) - start_time )) + if [[ $elapsed_time -ge $TIMEOUT ]]; then + echo + echo "โŒ Error: Timeout after $TIMEOUT seconds waiting for $node to start" + return 1 + fi + done + + echo + echo "โœ… $node has started" +} + +# do_for is a generic function to execute a command for a set of nodes. +do_for() { + if [[ $# -lt 2 ]]; then + echo "โŒ Error: do_for requires at least 2 arguments (function and nodes)" + echo "Usage: do_for [node1] [node2] [node3]..." + return 1 + fi + + local func="$1" + shift + local nodes=("$@") + + for node in "${nodes[@]}"; do + "$func" "$node" + done +} + +# setup_network sets up the basic A <> B <> C <> D network. +function setup_network() { + wait_for_nodes alice bob charlie dave + + setup_bitcoin + + do_for fund_node alice bob charlie dave + mine 6 + + connect_nodes alice bob + connect_nodes bob charlie + connect_nodes charlie dave + + open_channel alice bob + open_channel bob charlie + open_channel charlie dave + + echo "Set up network: Alice <-> Bob <-> Charlie <-> Dave" + + mine 7 + + wait_graph_sync alice 3 + wait_graph_sync bob 3 + wait_graph_sync charlie 3 + wait_graph_sync dave 3 +} + +# fund_node funds the specified node with 5 BTC. +function fund_node() { + local node="$1" + + ADDR=$( $node newaddress p2wkh | jq .address -r) + + bitcoin sendtoaddress "$ADDR" 5 > /dev/null + + echo "๐Ÿ’ฐ Funded $node with 5 BTC" +} + +# connect_nodes connects two specified nodes. +function connect_nodes() { + if [[ $# -ne 2 ]]; then + echo "โŒ Error: connect_nodes requires exactly 2 arguments (node1 and node2)" + echo "Usage: connect_nodes " + return 1 + fi + + local node1="$1" + local node2="$2" + + echo -ne "๐Ÿ“ž Connecting $node1 to $node2...\r" + + KEY_2=$( $node2 getinfo | jq .identity_pubkey -r) + + $node1 connect "$KEY_2"@$node2:9735 > /dev/null + + echo -ne " \r" + echo "๐Ÿ“ž Connected $node1 to $node2" +} + +# open_channel opens a channel between two specified nodes. +function open_channel() { + if [[ $# -ne 2 ]]; then + echo "โŒ Error: open_channel requires exactly 2 arguments (node1 and node2)" + echo "Usage: open_channel " + return 1 + fi + + local node1="$1" + local node2="$2" + + KEY_2=$( $node2 getinfo | jq .identity_pubkey -r) + + $node1 openchannel --node_key "$KEY_2" --local_amt 15000000 --push_amt 7000000 > /dev/null + + echo "๐Ÿ”— Opened channel between $node1 and $node2" +} + +# Function to check if a node's graph has the expected number of channels +wait_graph_sync() { + if [[ $# -ne 2 ]]; then + echo "โŒ Error: graph_synced requires exactly 2 arguments (node and num_chans)" + echo "Usage: graph_synced " + return 1 + fi + + local node="$1" + local num_chans="$2" + + while :; do + num_channels=$($node getnetworkinfo | jq -r '.num_channels') + + # Ensure num_channels is a valid number before proceeding + if [[ "$num_channels" =~ ^[0-9]+$ ]]; then + echo -ne "โŒ› $node sees $num_channels channels...\r" + + if [[ "$num_channels" -eq num_chans ]]; then + echo "๐Ÿ‘€ $node sees all the channels!" + break # Exit loop when num_channels reaches num_chans + fi + fi + + sleep 1 + done +} + +# send_payment attempts to send a payment between two specified nodes. +send_payment() { + if [[ $# -ne 2 ]]; then + echo "โŒ Error: send_payment requires exactly 2 arguments (from_node and to_node)" + echo "Usage: send_payment " + return 1 + fi + + local from_node="$1" + local to_node="$2" + + # Generate invoice and capture error output + local invoice_output + if ! invoice_output=$($to_node addinvoice 10000 2>&1); then + echo "โŒ Error: Failed to generate invoice from $to_node" + echo "๐Ÿ“œ Details: $invoice_output" + return 1 + fi + + # Extract payment request + local PAY_REQ + PAY_REQ=$(echo "$invoice_output" | jq -r '.payment_request') + + # Ensure invoice creation was successful + if [[ -z "$PAY_REQ" || "$PAY_REQ" == "null" ]]; then + echo "โŒ Error: Invoice response did not contain a valid payment request." + echo "๐Ÿ“œ Raw Response: $invoice_output" + return 1 + fi + + # Send payment and capture error output + local payment_output + if ! payment_output=$($from_node payinvoice --force "$PAY_REQ" 2>&1); then + echo "โŒ Error: Payment failed from $from_node to $to_node" + echo "๐Ÿ“œ Details: $payment_output" + return 1 + fi + + echo "๐Ÿ’ธ Payment sent from $from_node to $to_node" +} + +# print_version prints the commit hash that the given node is running. +print_version() { + if [[ $# -ne 1 ]]; then + echo "โŒ Error: print_version requires exactly 1 argument (node)" + echo "Usage: print_version " + return 1 + fi + + local node="$1" + + # Get the commit hash + local commit_hash + commit_hash=$($node version 2>/dev/null | jq -r '.lnd.commit_hash' | sed 's/^[ \t]*//') + + # Ensure commit hash is retrieved + if [[ -z "$commit_hash" || "$commit_hash" == "null" ]]; then + echo "โŒ Error: Could not retrieve commit hash for $node" + return 1 + fi + + echo "โ„น๏ธ $node is running on commit $commit_hash" +} + +# wait_for_active_chans waits for a node to have the expected number of active channels. +wait_for_active_chans() { + if [[ $# -ne 2 ]]; then + echo "โŒ Error: wait_for_active_chans requires exactly 2 arguments (node and expected_active_channels)" + echo "Usage: wait_for_active_chans " + return 1 + fi + + local node="$1" + local expected_channels="$2" + + echo "๐ŸŸ  Waiting for $node to have exactly $expected_channels active channels..." + + while :; do + # Get the active channel count + local active_count + active_count=$($node --network=regtest listchannels 2>/dev/null | jq '[.channels[] | select(.active == true)] | length') + + # Ensure active_count is a valid number + if [[ "$active_count" =~ ^[0-9]+$ ]]; then + echo -ne "โŒ› $node sees $active_count active channels...\r" + + # Exit loop only if the expected number of channels is active + if [[ "$active_count" -eq "$expected_channels" ]]; then + break + fi + fi + + sleep 1 + done + + echo + echo "๐ŸŸข $node now has exactly $expected_channels active channels!" +} + +# mine mines a number of blocks on the regtest network. If no +# argument is provided, it defaults to 6 blocks. +function mine() { + NUMBLOCKS="${1-6}" + bitcoin generatetoaddress "$NUMBLOCKS" "$(bitcoin getnewaddress "" legacy)" > /dev/null +} + +# setup_bitcoin performs various operations on the regtest bitcoind node +# so that it is ready to be used by the Lightning nodes and so that it can +# be used to fund the nodes. +function setup_bitcoin() { + echo "๐Ÿ”— Setting up Bitcoin node" + bitcoin createwallet miner > /dev/null + + ADDR_BTC=$(bitcoin getnewaddress "" legacy) + bitcoin generatetoaddress 106 "$ADDR_BTC" > /dev/null + bitcoin getbalance > /dev/null + + echo "๐Ÿ”— Bitcoin node is set up" +} + +function bitcoin() { + docker exec -i -u bitcoin bitcoind bitcoin-cli -regtest -rpcuser=lightning -rpcpassword=lightning "$@" +} + +function alice() { + docker exec -i alice lncli --network regtest "$@" +} + +function bob() { + docker exec -i "$BOB" lncli --network regtest "$@" +} + +function bob-pr() { + docker exec -i bob-pr lncli --network regtest "$@" +} + +function charlie() { + docker exec -i charlie lncli --network regtest "$@" +} + +function dave() { + docker exec -i dave lncli --network regtest "$@" +} diff --git a/scripts/bw-compatibility-test/test.sh b/scripts/bw-compatibility-test/test.sh new file mode 100755 index 0000000000..af22e5d1b6 --- /dev/null +++ b/scripts/bw-compatibility-test/test.sh @@ -0,0 +1,53 @@ +#!/bin/bash + +# Stop the script if an error is returned by any step. +set -e + +# DIR is set to the directory of this script. +DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" + +source "$DIR/compose.sh" +source "$DIR/network.sh" +source "$DIR/.env" + +cd $DIR + +# Spin up the network in detached mode. +compose_up + +# Ensure that the cluster is shut down when the script exits +# regardless of success +trap compose_down EXIT + +# Set up the network. +setup_network + +# Print the initial version of each node. +do_for print_version alice bob charlie dave + +# Test that Bob can send a multi-hop payment. +send_payment bob dave + +# Test that Bob can receive a multi-hop payment. +send_payment dave bob + +# Test that Bob can route a payment. +send_payment alice dave + +# Upgrade the compose variables so that the Bob configuration +# is swapped out for the PR version. +upgrade_bob + +# Wait for Bob to start. +wait_for_node bob +wait_for_active_chans bob 2 + +# Show that Bob is now running the current branch. +do_for print_version bob + +# Repeat the basic tests. +send_payment bob dave +send_payment dave bob +send_payment alice dave + +echo "๐Ÿ›ก๏ธโš”๏ธ๐Ÿซก Backwards compatibility test passed! ๐Ÿซกโš”๏ธ๐Ÿ›ก๏ธ"