├── sv ├── version ├── toolbox ├── oc ├── lookup_service ├── chain_height ├── faucet_balance ├── _toolbox.bc ├── list_docker_ips ├── inspect_container ├── newaddr ├── lookup_container ├── onchain_balance ├── _toolbox_config.sh ├── brief ├── attach_dlv ├── earn ├── ln_balance ├── pubkey ├── open_channel ├── simnet_ready ├── generate ├── req_pay ├── pay ├── get_route ├── fund ├── connect └── _toolbox_lib.sh ├── recipes ├── default.sh ├── cookbook │ ├── scaffold │ │ ├── .gitignore │ │ ├── docker │ │ │ ├── lnd │ │ │ │ ├── home │ │ │ │ │ ├── lib │ │ │ │ │ ├── run │ │ │ │ │ ├── lncli.sh │ │ │ │ │ ├── get-ready.sh │ │ │ │ │ ├── start.sh │ │ │ │ │ └── lnd.sh │ │ │ │ ├── lnd.conf │ │ │ │ └── Dockerfile │ │ │ ├── pre │ │ │ │ ├── home │ │ │ │ │ ├── lib │ │ │ │ │ ├── run │ │ │ │ │ └── start.sh │ │ │ │ └── Dockerfile │ │ │ ├── bitcoind │ │ │ │ ├── home │ │ │ │ │ ├── lib │ │ │ │ │ ├── run │ │ │ │ │ ├── setup.sh │ │ │ │ │ ├── start.sh │ │ │ │ │ ├── container-server.sh │ │ │ │ │ ├── container-service.sh │ │ │ │ │ ├── bitcoin-cli.sh │ │ │ │ │ ├── setup-chain.sh │ │ │ │ │ ├── bitcoind.sh │ │ │ │ │ └── setup-wallet.sh │ │ │ │ ├── bitcoin.conf │ │ │ │ └── Dockerfile │ │ │ ├── btcd │ │ │ │ ├── home │ │ │ │ │ ├── lib │ │ │ │ │ ├── run │ │ │ │ │ ├── setup.sh │ │ │ │ │ ├── container-service.sh │ │ │ │ │ ├── container-server.sh │ │ │ │ │ ├── start.sh │ │ │ │ │ ├── btcctl.sh │ │ │ │ │ ├── setup-wallet.sh │ │ │ │ │ ├── setup-segwit.sh │ │ │ │ │ ├── start-btcd.sh │ │ │ │ │ └── start-btcwallet.sh │ │ │ │ ├── btcd.conf │ │ │ │ ├── btcwallet.conf │ │ │ │ ├── patches │ │ │ │ │ ├── simnet-as-regtest.patch │ │ │ │ │ └── btcctl-regtest.patch │ │ │ │ └── Dockerfile │ │ │ ├── eclair │ │ │ │ ├── home │ │ │ │ │ ├── lib │ │ │ │ │ ├── run │ │ │ │ │ ├── get-ready.sh │ │ │ │ │ ├── start.sh │ │ │ │ │ ├── eclair-cli.sh │ │ │ │ │ └── eclair.sh │ │ │ │ ├── eclair.conf │ │ │ │ └── Dockerfile │ │ │ ├── lightning │ │ │ │ ├── home │ │ │ │ │ ├── lib │ │ │ │ │ ├── run │ │ │ │ │ ├── lightning-cli.sh │ │ │ │ │ ├── get-ready.sh │ │ │ │ │ ├── start.sh │ │ │ │ │ └── lightningd.sh │ │ │ │ ├── config │ │ │ │ ├── patches │ │ │ │ │ ├── docker-entrypoint.patch │ │ │ │ │ ├── unknown-version-fallback.patch │ │ │ │ │ └── disable-shadow-routing.patch │ │ │ │ └── Dockerfile │ │ │ └── _aux │ │ │ │ └── runtime │ │ │ │ └── lib │ │ │ │ ├── init.sh │ │ │ │ ├── attach_dlv.sh │ │ │ │ ├── report.sh │ │ │ │ ├── ansi.sh │ │ │ │ └── utils.sh │ │ ├── .dockerignore │ │ ├── dc │ │ ├── helpers │ │ │ ├── reset.sh │ │ │ ├── _config.sh │ │ │ └── lib │ │ │ │ └── utils.sh │ │ ├── debug │ │ └── enter │ ├── templates │ │ ├── lncli-alias.sh │ │ ├── eclair-cli-alias.sh │ │ ├── btcctl-alias.sh │ │ ├── lightning-cli-alias.sh │ │ ├── bitcoin-cli-alias.sh │ │ ├── docker │ │ │ ├── base │ │ │ │ └── Dockerfile │ │ │ ├── buildtime │ │ │ │ └── Dockerfile │ │ │ └── runtime │ │ │ │ └── Dockerfile │ │ ├── tmux │ │ ├── _alias_utils.sh │ │ ├── prelude.yml │ │ ├── bitcoind.yml │ │ ├── eclair.yml │ │ ├── lnd.yml │ │ ├── btcd.yml │ │ └── lightning.yml │ └── cookbook.sh ├── b1l2.sh ├── a1m2.sh ├── a1l2.sh ├── a1k2.sh ├── b1l3.sh ├── a1k1l2.sh ├── a1l2k1.sh ├── a1m3.sh ├── a1k2l1.sh ├── a1l1k2.sh ├── a1k3.sh ├── a1k1b1l2.sh ├── a1l1a1l2.sh ├── a1k1a1l2.sh ├── a1m1a1m2.sh ├── a1k1a1k2.sh └── readme.md ├── tests ├── suites │ ├── default.sh │ ├── tiny.sh │ ├── travis.sh │ ├── eclair.sh │ ├── lnd.sh │ ├── lightningd.sh │ ├── all.sh │ ├── pay-via-charlie.sh │ ├── pay-via-charlie-b2.sh │ ├── pay-directly.sh │ └── pay-via-charlie-hetero.sh ├── _lib │ ├── github.sh │ ├── travis.sh │ ├── prepare-test.sh │ └── helpers.sh ├── cases │ ├── 01-pay-directly │ │ └── test.sh │ └── 02-pay-via-charlie │ │ └── test.sh └── run.sh ├── .gitignore ├── .idea ├── encodings.xml ├── codeStyles │ └── codeStyleConfig.xml ├── vcs.xml ├── modules.xml ├── misc.xml ├── simverse.iml └── dictionaries │ └── darwin.xml ├── scripts ├── bisect.sh └── install-docker-compose.sh ├── .github └── workflows │ └── ci.yml ├── LICENSE ├── _defaults.sh └── readme.md /sv: -------------------------------------------------------------------------------- 1 | simverse -------------------------------------------------------------------------------- /version: -------------------------------------------------------------------------------- 1 | 0.5 -------------------------------------------------------------------------------- /toolbox/oc: -------------------------------------------------------------------------------- 1 | open_channel -------------------------------------------------------------------------------- /recipes/default.sh: -------------------------------------------------------------------------------- 1 | b1l2.sh -------------------------------------------------------------------------------- /tests/suites/default.sh: -------------------------------------------------------------------------------- 1 | travis.sh -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | _repos/ 2 | _workspace/ 3 | tests/suites/_* -------------------------------------------------------------------------------- /recipes/cookbook/scaffold/.gitignore: -------------------------------------------------------------------------------- 1 | _volumes/ 2 | .envrc -------------------------------------------------------------------------------- /recipes/cookbook/scaffold/docker/lnd/home/lib: -------------------------------------------------------------------------------- 1 | ../../_aux/runtime/lib/ -------------------------------------------------------------------------------- /recipes/cookbook/scaffold/docker/pre/home/lib: -------------------------------------------------------------------------------- 1 | ../../_aux/runtime/lib/ -------------------------------------------------------------------------------- /recipes/cookbook/scaffold/docker/bitcoind/home/lib: -------------------------------------------------------------------------------- 1 | ../../_aux/runtime/lib/ -------------------------------------------------------------------------------- /recipes/cookbook/scaffold/docker/btcd/home/lib: -------------------------------------------------------------------------------- 1 | ../../_aux/runtime/lib/ -------------------------------------------------------------------------------- /recipes/cookbook/scaffold/docker/eclair/home/lib: -------------------------------------------------------------------------------- 1 | ../../_aux/runtime/lib/ -------------------------------------------------------------------------------- /recipes/cookbook/scaffold/docker/lightning/home/lib: -------------------------------------------------------------------------------- 1 | ../../_aux/runtime/lib/ -------------------------------------------------------------------------------- /recipes/cookbook/scaffold/docker/btcd/home/run: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | exec /sbin/tini -- start.sh -------------------------------------------------------------------------------- /recipes/cookbook/scaffold/docker/lnd/home/run: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | exec /sbin/tini -- start.sh -------------------------------------------------------------------------------- /recipes/cookbook/scaffold/docker/pre/home/run: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | exec /sbin/tini -- start.sh -------------------------------------------------------------------------------- /recipes/cookbook/scaffold/docker/bitcoind/home/run: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | exec /sbin/tini -- start.sh -------------------------------------------------------------------------------- /recipes/cookbook/scaffold/docker/eclair/home/run: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | exec /sbin/tini -- start.sh -------------------------------------------------------------------------------- /recipes/cookbook/scaffold/docker/lightning/home/run: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | exec /sbin/tini -- start.sh -------------------------------------------------------------------------------- /recipes/cookbook/scaffold/docker/_aux/runtime/lib/init.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | set -e -o pipefail 4 | -------------------------------------------------------------------------------- /recipes/cookbook/scaffold/.dockerignore: -------------------------------------------------------------------------------- 1 | repos/.idea 2 | repos/*/.idea 3 | repos/*/.git 4 | repos/lightning/external/*/.git -------------------------------------------------------------------------------- /recipes/cookbook/scaffold/docker/lnd/lnd.conf: -------------------------------------------------------------------------------- 1 | # see https://github.com/lightningnetwork/lnd/blob/master/sample-lnd.conf 2 | -------------------------------------------------------------------------------- /recipes/cookbook/scaffold/docker/eclair/eclair.conf: -------------------------------------------------------------------------------- 1 | # see https://github.com/lightningnetwork/lnd/blob/master/sample-lnd.conf 2 | -------------------------------------------------------------------------------- /recipes/cookbook/scaffold/docker/btcd/btcd.conf: -------------------------------------------------------------------------------- 1 | # see https://github.com/btcsuite/btcd/blob/master/sample-btcd.conf 2 | 3 | nodnsseed=1 -------------------------------------------------------------------------------- /recipes/cookbook/scaffold/docker/btcd/btcwallet.conf: -------------------------------------------------------------------------------- 1 | # see https://github.com/btcsuite/btcwallet/blob/master/sample-btcwallet.conf 2 | -------------------------------------------------------------------------------- /tests/suites/tiny.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | cd "$(dirname "${BASH_SOURCE[0]}")" 4 | 5 | ./../cases/01-pay-directly/test.sh b1l2 6 | -------------------------------------------------------------------------------- /tests/suites/travis.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | cd "$(dirname "${BASH_SOURCE[0]}")" 4 | 5 | . ./pay-directly.sh 6 | . ./pay-via-charlie.sh -------------------------------------------------------------------------------- /recipes/cookbook/scaffold/docker/lightning/config: -------------------------------------------------------------------------------- 1 | # see https://github.com/ElementsProject/lightning/blob/master/README.md#configuration-file 2 | -------------------------------------------------------------------------------- /recipes/b1l2.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | . cookbook/cookbook.sh 4 | 5 | prelude 6 | 7 | add btcd 8 | 9 | add lnd alice 10 | add lnd bob -------------------------------------------------------------------------------- /recipes/a1m2.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | . cookbook/cookbook.sh 4 | 5 | prelude 6 | 7 | add bitcoind 8 | 9 | add eclair alice 10 | add eclair bob -------------------------------------------------------------------------------- /.idea/encodings.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /tests/suites/eclair.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | cd "$(dirname "${BASH_SOURCE[0]}")" 4 | 5 | ./../cases/01-pay-directly/test.sh a1m2 6 | ./../cases/02-pay-via-charlie/test.sh a1m3 -------------------------------------------------------------------------------- /tests/suites/lnd.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | cd "$(dirname "${BASH_SOURCE[0]}")" 4 | 5 | ./../cases/01-pay-directly/test.sh a1l2 6 | ./../cases/02-pay-via-charlie/test.sh a1l3 -------------------------------------------------------------------------------- /tests/suites/lightningd.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | cd "$(dirname "${BASH_SOURCE[0]}")" 4 | 5 | ./../cases/01-pay-directly/test.sh a1k2 6 | ./../cases/02-pay-via-charlie/test.sh a1k3 -------------------------------------------------------------------------------- /.idea/codeStyles/codeStyleConfig.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 5 | -------------------------------------------------------------------------------- /.idea/vcs.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /tests/suites/all.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | cd "$(dirname "${BASH_SOURCE[0]}")" 4 | 5 | . ./pay-directly.sh 6 | . ./pay-via-charlie.sh 7 | . ./pay-via-charlie-b2.sh 8 | . ./pay-via-charlie-hetero.sh -------------------------------------------------------------------------------- /recipes/cookbook/scaffold/docker/btcd/home/setup.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | source lib/init.sh 4 | source lib/utils.sh 5 | 6 | ./setup-wallet.sh 7 | 8 | ./setup-segwit.sh 9 | 10 | signal_service_ready -------------------------------------------------------------------------------- /toolbox/lookup_service: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | set -e -o pipefail 4 | 5 | source _toolbox_lib.sh 6 | 7 | CONTAINER=$(lookup_container "$@") 8 | 9 | inspect_container "$CONTAINER" "com.docker.compose.service" -------------------------------------------------------------------------------- /recipes/cookbook/scaffold/docker/bitcoind/home/setup.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | source lib/init.sh 4 | source lib/utils.sh 5 | 6 | ./setup-wallet.sh 7 | 8 | ./setup-chain.sh 9 | 10 | signal_service_ready -------------------------------------------------------------------------------- /recipes/a1l2.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | # in this recipe we use bitcoind instead of btcd, see b1l2.sh 4 | 5 | . cookbook/cookbook.sh 6 | 7 | prelude 8 | 9 | add bitcoind 10 | 11 | add lnd alice 12 | add lnd bob -------------------------------------------------------------------------------- /recipes/cookbook/scaffold/docker/bitcoind/home/start.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | source lib/init.sh 4 | source lib/report.sh 5 | 6 | ./setup.sh & 7 | 8 | ./container-server.sh & 9 | 10 | exec ./bitcoind.sh 11 | -------------------------------------------------------------------------------- /toolbox/chain_height: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | set -e -o pipefail 4 | 5 | source _toolbox_lib.sh 6 | 7 | if is_btcd_master; then 8 | btcctl getinfo | jq '.blocks' 9 | else 10 | bitcoin-cli -getinfo | jq '.blocks' 11 | fi -------------------------------------------------------------------------------- /recipes/a1k2.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | # in this recipe we use bitcoind instead of btcd, see b1l2.sh 4 | 5 | . cookbook/cookbook.sh 6 | 7 | prelude 8 | 9 | add bitcoind 10 | 11 | add lightning alice 12 | add lightning bob -------------------------------------------------------------------------------- /recipes/cookbook/scaffold/docker/lnd/home/lncli.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | source lib/init.sh 4 | source lib/utils.sh 5 | 6 | PARAMS="" 7 | 8 | PARAMS+=" --network=regtest" 9 | 10 | #set -x 11 | exec lncli ${PARAMS} "$@" 12 | -------------------------------------------------------------------------------- /tests/suites/pay-via-charlie.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | cd "$(dirname "${BASH_SOURCE[0]}")" 4 | 5 | ./../cases/02-pay-via-charlie/test.sh b1l3 6 | ./../cases/02-pay-via-charlie/test.sh a1k3 7 | ./../cases/02-pay-via-charlie/test.sh a1m3 8 | -------------------------------------------------------------------------------- /toolbox/faucet_balance: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | set -e -o pipefail 4 | 5 | source _toolbox_lib.sh 6 | 7 | if is_btcd_master; then 8 | btcctl --wallet getbalance imported | trim 9 | else 10 | bitcoin-cli getbalance | trim 11 | fi -------------------------------------------------------------------------------- /tests/suites/pay-via-charlie-b2.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | cd "$(dirname "${BASH_SOURCE[0]}")" 4 | 5 | ./../cases/02-pay-via-charlie/test.sh a1k1a1k2 6 | ./../cases/02-pay-via-charlie/test.sh a1l1a1l2 7 | ./../cases/02-pay-via-charlie/test.sh a1m1a1m2 8 | -------------------------------------------------------------------------------- /recipes/cookbook/scaffold/docker/btcd/home/container-service.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | IFS=$'\n' 4 | read COMMAND 5 | 6 | case "$COMMAND" in 7 | get-chain-height) ./btcctl.sh -getinfo | jq '.blocks' ;; 8 | *) echo "unknown command '$COMMAND'" ;; 9 | esac -------------------------------------------------------------------------------- /toolbox/_toolbox.bc: -------------------------------------------------------------------------------- 1 | # see https://stackoverflow.com/a/53532113/84283 2 | define floor(x) { 3 | auto s; 4 | s = scale; 5 | scale = 0; 6 | x /= 1; /* This will have the effect of truncating x to its integer value */ 7 | scale = s; 8 | return (x); 9 | } -------------------------------------------------------------------------------- /recipes/cookbook/scaffold/dc: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | . "$(dirname "${BASH_SOURCE[0]}")/helpers/_config.sh" || true || . helpers/_config.sh 4 | 5 | cd "$THIS_DIR" 6 | 7 | if [[ ! -d "$VOLUMES_DIR" ]]; then 8 | mkdir -p "$VOLUMES_DIR" 9 | fi 10 | 11 | exec docker-compose "$@" 12 | -------------------------------------------------------------------------------- /toolbox/list_docker_ips: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | set -e -o pipefail 4 | 5 | source _toolbox_lib.sh 6 | 7 | # see https://stackoverflow.com/a/55155992/84283 8 | docker ps -q | xargs -n 1 docker inspect --format '{{range .NetworkSettings.Networks}}{{.IPAddress}}{{end}} {{ .Name }}' | sed 's/ \// /' -------------------------------------------------------------------------------- /.idea/modules.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /recipes/cookbook/scaffold/helpers/reset.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | . "$(dirname "${BASH_SOURCE[0]}")/_config.sh" || true || . _config.sh 4 | 5 | cd "$THIS_DIR" 6 | 7 | if [[ -d "$VOLUMES_DIR" && -n "$VOLUMES_DIR" ]]; then 8 | rm -rf "$VOLUMES_DIR"/* 9 | fi 10 | 11 | mkdir -p "$VOLUMES_DIR/master" -------------------------------------------------------------------------------- /tests/suites/pay-directly.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | cd "$(dirname "${BASH_SOURCE[0]}")" 4 | 5 | ./../cases/01-pay-directly/test.sh a1k2 6 | ./../cases/01-pay-directly/test.sh b1l2 7 | ./../cases/01-pay-directly/test.sh a1m2 8 | ./../cases/01-pay-directly/test.sh a1l2 # https://github.com/darwin/simverse/issues/7 -------------------------------------------------------------------------------- /recipes/cookbook/scaffold/docker/btcd/home/container-server.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | source lib/init.sh 4 | 5 | # this is a simple server for other containers to talk to our node 6 | CONTAINER_SERVICE_PORT=${CONTAINER_SERVICE_PORT:?required} 7 | exec nc -nlk -p "$CONTAINER_SERVICE_PORT" -e ~/container-service.sh 8 | -------------------------------------------------------------------------------- /recipes/cookbook/scaffold/docker/bitcoind/home/container-server.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | source lib/init.sh 4 | 5 | # this is a simple server for other containers to talk to our node 6 | CONTAINER_SERVICE_PORT=${CONTAINER_SERVICE_PORT:?required} 7 | exec nc -nlk -p "$CONTAINER_SERVICE_PORT" -e ~/container-service.sh 8 | -------------------------------------------------------------------------------- /tests/_lib/github.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | # https://github.community/t5/GitHub-Actions/Has-github-action-somthing-like-travis-fold/m-p/37715 4 | 5 | github_section() { 6 | local action=$1 7 | if [[ "$action" == "start" ]]; then 8 | echo -n "::group::" 9 | else 10 | echo "::endgroup::" 11 | fi 12 | } 13 | -------------------------------------------------------------------------------- /recipes/cookbook/scaffold/docker/lnd/home/get-ready.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | source lib/init.sh 4 | source lib/utils.sh 5 | 6 | CONTAINER_NAME=${CONTAINER_NAME:?required} 7 | 8 | cmd="[[ \$(lncli.sh getinfo | jq \".synced_to_chain\") == \"true\" ]]" 9 | wait_for "$CONTAINER_NAME to sync" "$cmd" 10 | 11 | signal_service_ready -------------------------------------------------------------------------------- /recipes/cookbook/templates/lncli-alias.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | cd "$(dirname "${BASH_SOURCE[0]}")" 4 | 5 | source _alias_utils.sh 6 | 7 | cd ".." 8 | 9 | echo_command_if_needed "$@" 10 | DC_EXEC_EXTRA_ARGS=$(prepare_docker_compose_exec_args) 11 | exec ./dc exec ${DC_EXEC_EXTRA_ARGS} "$$NAME" lncli.sh "$@" | beautify_if_needed 12 | -------------------------------------------------------------------------------- /recipes/cookbook/templates/eclair-cli-alias.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | cd "$(dirname "${BASH_SOURCE[0]}")" 4 | 5 | source _alias_utils.sh 6 | 7 | cd ".." 8 | 9 | echo_command_if_needed "$@" 10 | DC_EXEC_EXTRA_ARGS=$(prepare_docker_compose_exec_args) 11 | exec ./dc exec ${DC_EXEC_EXTRA_ARGS} "$$NAME" eclair-cli.sh "$@" | beautify_if_needed 12 | -------------------------------------------------------------------------------- /recipes/cookbook/templates/btcctl-alias.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | cd "$(dirname "${BASH_SOURCE[0]}")" 4 | 5 | source _alias_utils.sh 6 | 7 | cd ".." 8 | 9 | echo_command_if_needed "$@" 10 | DC_EXEC_EXTRA_ARGS=$(prepare_docker_compose_exec_args) 11 | exec docker-compose exec ${DC_EXEC_EXTRA_ARGS} "$$NAME" btcctl.sh "$@" | beautify_if_needed 12 | -------------------------------------------------------------------------------- /recipes/cookbook/templates/lightning-cli-alias.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | cd "$(dirname "${BASH_SOURCE[0]}")" 4 | 5 | source _alias_utils.sh 6 | 7 | cd ".." 8 | 9 | echo_command_if_needed "$@" 10 | DC_EXEC_EXTRA_ARGS=$(prepare_docker_compose_exec_args) 11 | exec ./dc exec ${DC_EXEC_EXTRA_ARGS} "$$NAME" lightning-cli.sh "$@" | beautify_if_needed 12 | -------------------------------------------------------------------------------- /recipes/cookbook/templates/bitcoin-cli-alias.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | cd "$(dirname "${BASH_SOURCE[0]}")" 4 | 5 | source _alias_utils.sh 6 | 7 | cd ".." 8 | 9 | echo_command_if_needed "$@" 10 | DC_EXEC_EXTRA_ARGS=$(prepare_docker_compose_exec_args) 11 | exec docker-compose exec ${DC_EXEC_EXTRA_ARGS} "$$NAME" bitcoin-cli.sh "$@" | beautify_if_needed 12 | -------------------------------------------------------------------------------- /recipes/cookbook/scaffold/docker/btcd/home/start.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | source lib/init.sh 4 | source lib/report.sh 5 | 6 | # wait for shared certificate creation 7 | while [[ ! -f /certs/rpc.cert ]]; do sleep 1; done 8 | 9 | ./setup.sh & 10 | 11 | ./start-btcwallet.sh & 12 | 13 | # start container service in background 14 | ./container-server.sh & 15 | 16 | exec start-btcd.sh 17 | -------------------------------------------------------------------------------- /recipes/cookbook/scaffold/docker/pre/Dockerfile: -------------------------------------------------------------------------------- 1 | ARG PRE_DOCKER_BUILDTIME_IMAGE 2 | ARG PRE_DOCKER_RUNTIME_IMAGE 3 | 4 | FROM ${PRE_DOCKER_RUNTIME_IMAGE} as simverse_runtime_pre 5 | 6 | #include BASE_DOCKERFILE_SNIPPET 7 | #include RUNTIME_DOCKERFILE_SNIPPET 8 | 9 | USER simnet 10 | 11 | WORKDIR /home/simnet 12 | 13 | COPY --chown=simnet "docker/pre/home" "." 14 | 15 | RUN mkdir certs 16 | -------------------------------------------------------------------------------- /recipes/cookbook/scaffold/docker/_aux/runtime/lib/attach_dlv.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | set -e -o pipefail 4 | 5 | PROCESS=${1} 6 | PORT=${2} 7 | 8 | PID=$(pidof ${PROCESS}) 9 | 10 | if [[ -z "$PID" ]]; then 11 | echo "unable to retrieve a PID for '$PROCESS'" 12 | ps 13 | exit 1 14 | fi 15 | 16 | set -x 17 | dlv --listen=0.0.0.0:${PORT} --log --headless=true --api-version=2 attach ${PID} -------------------------------------------------------------------------------- /recipes/cookbook/templates/docker/base/Dockerfile: -------------------------------------------------------------------------------- 1 | # >>> base snippet >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> 2 | # this is a base Dockerfile snippet used in all docker containers 3 | 4 | RUN apk add --no-cache --update \ 5 | bash \ 6 | fish \ 7 | ca-certificates \ 8 | curl \ 9 | git 10 | 11 | # <<< base snippet <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< -------------------------------------------------------------------------------- /recipes/cookbook/scaffold/helpers/_config.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | # standard bash switches for our scripts 4 | set -e -o pipefail 5 | 6 | pushd "$(dirname "${BASH_SOURCE[0]}")" > /dev/null 7 | 8 | . "lib/utils.sh" 9 | 10 | cd .. 11 | 12 | THIS_DIR=$(pwd -P) 13 | 14 | HELPERS_DIR="$THIS_DIR/helpers" 15 | DOCKER_DIR="$THIS_DIR/docker" 16 | VOLUMES_DIR="$THIS_DIR/_volumes" 17 | 18 | popd 19 | -------------------------------------------------------------------------------- /.idea/misc.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /recipes/b1l3.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | . cookbook/cookbook.sh 4 | 5 | prelude 6 | 7 | add btcd 8 | 9 | add lnd alice 10 | add lnd bob 11 | add lnd charlie 12 | 13 | # generate init script to build connections 14 | cat > init < init < init < init < $*${normal}" 7 | "$@" 8 | } 9 | 10 | if [[ -n "$REPORT_ENV" ]]; then 11 | echo 12 | echo "Environment report:" 13 | report uname -a 14 | report whoami 15 | report id 16 | report env 17 | report tree -apug /home 18 | echo 19 | fi -------------------------------------------------------------------------------- /recipes/a1k2l1.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | . cookbook/cookbook.sh 4 | 5 | prelude 6 | 7 | add bitcoind 8 | 9 | add lightningd alice 10 | add lightningd bob 11 | add lnd charlie 12 | 13 | # generate init script to build connections 14 | cat > init < init < init < docker logs --tail \"${DOCKER_LOGS_TAIL_COUNT}\" \"$CONTAINER_ID\"" 15 | docker logs --tail "${DOCKER_LOGS_TAIL_COUNT}" "$CONTAINER_ID" 16 | done <<< "$SERVICES" -------------------------------------------------------------------------------- /toolbox/attach_dlv: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | set -e -o pipefail 4 | 5 | source _toolbox_lib.sh 6 | 7 | CONTAINER=${1:-alice} 8 | PROCESS=${2:-lnd} 9 | DEFAULT_PORT_VAR="DLV_PORT_$(echo "$CONTAINER" | uppercase)" 10 | PORT=${3:-${!DEFAULT_PORT_VAR}} 11 | 12 | if [[ -z "$3" && -z "$PORT" ]]; then 13 | echo_err "unable to retrieve port from env variable $DEFAULT_PORT_VAR" 14 | exit 1 15 | fi 16 | 17 | cd "../.." 18 | 19 | exec ./dc exec "${CONTAINER}" lib/attach_dlv.sh "${PROCESS}" "${PORT}" -------------------------------------------------------------------------------- /recipes/cookbook/scaffold/enter: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | cd "$(dirname "${BASH_SOURCE[0]}")" 4 | 5 | . home/_defaults.sh 6 | 7 | SIMNET_DIR_ABSOLUTE=$(pwd -P) 8 | ALIASES_DIR_ABSOLUTE="$SIMNET_DIR_ABSOLUTE/aliases" 9 | TOOLBOX_DIR_ABSOLUTE="$SIMNET_DIR_ABSOLUTE/toolbox" 10 | 11 | export PATH=${ALIASES_DIR_ABSOLUTE}:${TOOLBOX_DIR_ABSOLUTE}:$PATH 12 | 13 | . helpers/_config.sh 14 | 15 | if [[ -z "$SIMVERSE_DONT_CHECK_PREREQS" ]]; then 16 | check_prereqs 17 | fi 18 | 19 | exec "$SIMVERSE_SHELL" "$@" 20 | -------------------------------------------------------------------------------- /tests/suites/pay-via-charlie-hetero.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | cd "$(dirname "${BASH_SOURCE[0]}")" 4 | 5 | ./../cases/02-pay-via-charlie/test.sh a1k1l2 6 | ./../cases/02-pay-via-charlie/test.sh a1l1k2 7 | ./../cases/02-pay-via-charlie/test.sh a1k2l1 8 | ./../cases/02-pay-via-charlie/test.sh a1l2k1 9 | 10 | ./../cases/02-pay-via-charlie/test.sh a1k1a1l2 11 | 12 | # this one is broken with "Incoming htlc() has an expiration that is too soon" for now 13 | #./../cases/02-pay-via-charlie/test.sh a1k1b1l2 14 | -------------------------------------------------------------------------------- /recipes/cookbook/scaffold/docker/eclair/home/get-ready.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | source lib/init.sh 4 | source lib/utils.sh 5 | 6 | CONTAINER_NAME=${CONTAINER_NAME:?required} 7 | CONTAINER_SERVICE_PORT=${CONTAINER_SERVICE_PORT:?required} 8 | ECLAIR_BITCOIN_RPC_HOST=${ECLAIR_BITCOIN_RPC_HOST} 9 | 10 | cmd="[[ \$(echo get-chain-height | nc $ECLAIR_BITCOIN_RPC_HOST $CONTAINER_SERVICE_PORT) == \$(eclair-cli.sh getinfo | jq .blockHeight) ]]" 11 | wait_for "$CONTAINER_NAME to sync" "$cmd" 12 | 13 | signal_service_ready -------------------------------------------------------------------------------- /recipes/cookbook/scaffold/docker/eclair/home/start.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | source lib/init.sh 4 | source lib/report.sh 5 | source lib/utils.sh 6 | 7 | # wait for bitcoin node to open its RPC interface 8 | ECLAIR_BITCOIN_RPC_HOST=${ECLAIR_BITCOIN_RPC_HOST:?required} 9 | SERVICE_READY_PORT=${SERVICE_READY_PORT:?required} 10 | echo "Waiting for bitcoin node $ECLAIR_BITCOIN_RPC_HOST to get ready..." 11 | wait_for_socket "$SERVICE_READY_PORT" "$ECLAIR_BITCOIN_RPC_HOST" 12 | 13 | get-ready.sh & 14 | 15 | exec eclair.sh -------------------------------------------------------------------------------- /.idea/simverse.iml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /recipes/cookbook/scaffold/docker/bitcoind/home/bitcoin-cli.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | source lib/init.sh 4 | 5 | RPC_USER=${RPC_USER} 6 | RPC_PASS=${RPC_PASS} 7 | BITCOINCLI_EXTRA_PARAMS=${BITCOINCLI_EXTRA_PARAMS} 8 | BITCOIN_RPC_PORT=${BITCOIN_RPC_PORT} 9 | 10 | PARAMS="" 11 | PARAMS+=" -rpcport=${BITCOIN_RPC_PORT}" 12 | 13 | if [[ -n "$RPC_USER" ]]; then 14 | PARAMS+=" -rpcuser=$RPC_USER" 15 | PARAMS+=" -rpcpassword=$RPC_PASS" 16 | fi 17 | 18 | #set -x 19 | exec bitcoin-cli ${PARAMS} ${BITCOINCLI_EXTRA_PARAMS} "$@" 20 | -------------------------------------------------------------------------------- /recipes/cookbook/scaffold/docker/lightning/home/get-ready.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | source lib/init.sh 4 | source lib/utils.sh 5 | 6 | CONTAINER_NAME=${CONTAINER_NAME:?required} 7 | CONTAINER_SERVICE_PORT=${CONTAINER_SERVICE_PORT:?required} 8 | LIGHTNING_BITCOIN_RPC_HOST=${LIGHTNING_BITCOIN_RPC_HOST} 9 | 10 | cmd="[[ \$(echo get-chain-height | nc $LIGHTNING_BITCOIN_RPC_HOST $CONTAINER_SERVICE_PORT) == \$(lightning-cli.sh getinfo | jq .blockheight) ]]" 11 | wait_for "$CONTAINER_NAME to sync" "$cmd" 12 | 13 | signal_service_ready -------------------------------------------------------------------------------- /recipes/cookbook/scaffold/docker/lightning/patches/docker-entrypoint.patch: -------------------------------------------------------------------------------- 1 | diff --git a/tools/docker-entrypoint.sh b/tools/docker-entrypoint.sh 2 | index c5bccf4..5d91839 100755 3 | --- a/tools/docker-entrypoint.sh 4 | +++ b/tools/docker-entrypoint.sh 5 | @@ -2,7 +2,7 @@ 6 | 7 | : "${EXPOSE_TCP:=false}" 8 | 9 | -networkdatadir="${LIGHTNINGD_DATA}/${LIGHTNINGD_NETWORK}" 10 | +networkdatadir=${LIGHTNINGD_RPC_DIR_SIMVERSE:-"${LIGHTNINGD_DATA}/${LIGHTNINGD_NETWORK}"} 11 | 12 | if [ "$EXPOSE_TCP" == "true" ]; then 13 | set -m 14 | -------------------------------------------------------------------------------- /recipes/cookbook/scaffold/docker/lightning/home/start.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | source lib/init.sh 4 | source lib/report.sh 5 | source lib/utils.sh 6 | 7 | # wait for bitcoin node to open its RPC interface 8 | LIGHTNING_BITCOIN_RPC_HOST=${LIGHTNING_BITCOIN_RPC_HOST:?required} 9 | SERVICE_READY_PORT=${SERVICE_READY_PORT:?required} 10 | echo "Waiting for bitcoin node $LIGHTNING_BITCOIN_RPC_HOST to get ready..." 11 | wait_for_socket "$SERVICE_READY_PORT" "$LIGHTNING_BITCOIN_RPC_HOST" 12 | 13 | get-ready.sh & 14 | 15 | exec lightningd.sh -------------------------------------------------------------------------------- /recipes/cookbook/scaffold/docker/lightning/patches/unknown-version-fallback.patch: -------------------------------------------------------------------------------- 1 | diff --git a/Makefile b/Makefile 2 | index f6c44e3..317841e 100644 3 | --- a/Makefile 4 | +++ b/Makefile 5 | @@ -4,7 +4,7 @@ 6 | VERSION=$(shell git describe --always --dirty=-modded --abbrev=7 2>/dev/null || pwd | sed -n 's|.*/c\{0,1\}lightning-v\{0,1\}\([0-9a-f.rc\-]*\)$$|\1|gp') 7 | 8 | ifeq ($(VERSION),) 9 | -$(error "ERROR: git is required for generating version information") 10 | +VERSION="unknown" 11 | endif 12 | 13 | # --quiet / -s means quiet, dammit! 14 | -------------------------------------------------------------------------------- /scripts/bisect.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | set -e -o pipefail 4 | 5 | REPO=${1:-bitcoin} 6 | GOOD_REV=${2:?required} 7 | BAD_REV=${3:-HEAD} 8 | TEST_SUITE=${4:-_bisect} 9 | 10 | cd "$(dirname "${BASH_SOURCE[0]}")" 11 | 12 | SCRIPTS_DIR=$(pwd -P) 13 | 14 | cd .. 15 | ROOT_DIR=$(pwd -P) 16 | 17 | export SIMVERSE_TEST_REPOS=_repos 18 | export SIMVERSE_DEBUG_TEST= 19 | 20 | cd "_repos/$REPO" 21 | 22 | set -x 23 | git bisect start 24 | git bisect good "$GOOD_REV" 25 | git bisect bad "$BAD_REV" 26 | git bisect run "$ROOT_DIR/tests/run.sh" "$TEST_SUITE" -------------------------------------------------------------------------------- /toolbox/earn: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | set -e -o pipefail 4 | 5 | source _toolbox_lib.sh 6 | 7 | AMOUNT_BTC=${1:-100} # minimal amount 8 | FAUCET_ADDR=${FAUCET_ADDR:?required} 9 | 10 | BLOCK_SUBSIDY=50 # we assume a young blockchain with 50 BTC per block 11 | BLOCKS_NEEDED=$(compute "floor(${AMOUNT_BTC} / ${BLOCK_SUBSIDY}) + 1") 12 | echo "mining ${BLOCKS_NEEDED} blocks on master bitcoin node" 13 | 14 | # generate blocks on master node 15 | generate "${BLOCKS_NEEDED}" 16 | 17 | # mine blocks to mature coinbase transactions 18 | generate "${COINBASE_MATURITY}" 19 | -------------------------------------------------------------------------------- /recipes/cookbook/scaffold/docker/btcd/home/btcctl.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | source lib/init.sh 4 | 5 | BTCCTL_EXTRA_PARAMS=${BTCCTL_EXTRA_PARAMS} 6 | RPC_USER=${RPC_USER} 7 | RPC_PASS=${RPC_PASS} 8 | 9 | PARAMS="" 10 | 11 | # note: this option was added by our patch, see patches/btcctl-regtest.patch 12 | PARAMS+=" --regtest" 13 | 14 | PARAMS+=" --rpccert=/certs/rpc.cert" 15 | 16 | if [[ -n "$RPC_USER" ]]; then 17 | PARAMS+=" --rpcuser=\"$RPC_USER\"" 18 | PARAMS+=" --rpcpass=\"$RPC_PASS\"" 19 | fi 20 | 21 | #set -x 22 | exec btcctl ${PARAMS} ${BTCCTL_EXTRA_PARAMS} "$@" 23 | -------------------------------------------------------------------------------- /recipes/cookbook/scaffold/docker/lightning/patches/disable-shadow-routing.patch: -------------------------------------------------------------------------------- 1 | diff --git a/plugins/pay.c b/plugins/pay.c 2 | index 94e8402..ca4768f 100644 3 | --- a/plugins/pay.c 4 | +++ b/plugins/pay.c 5 | @@ -1087,6 +1087,9 @@ static struct command_result *shadow_route(struct command *cmd, 6 | struct out_req *req; 7 | 8 | #if DEVELOPER 9 | + // SIMVERSE HACK: until this is exposed as a cli option we disable shadow routing for stable tests 10 | + pc->use_shadow = 0; 11 | + 12 | if (!pc->use_shadow) 13 | return start_pay_attempt(cmd, pc, "Initial attempt"); 14 | #endif 15 | -------------------------------------------------------------------------------- /recipes/cookbook/scaffold/docker/lnd/home/start.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | source lib/init.sh 4 | source lib/report.sh 5 | source lib/utils.sh 6 | 7 | # wait for shared certificate creation 8 | while [[ ! -f /certs/rpc.cert ]]; do sleep 1; done 9 | 10 | # wait for bitcoin node to open its RPC interface 11 | LND_BITCOIN_RPC_HOST=${LND_BITCOIN_RPC_HOST:?required} 12 | SERVICE_READY_PORT=${SERVICE_READY_PORT:?required} 13 | echo "Waiting for bitcoin node $LND_BITCOIN_RPC_HOST to get ready..." 14 | wait_for_socket "$SERVICE_READY_PORT" "$LND_BITCOIN_RPC_HOST" 15 | 16 | get-ready.sh & 17 | 18 | exec lnd.sh -------------------------------------------------------------------------------- /recipes/cookbook/templates/tmux: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | set -e -o pipefail 4 | 5 | # inspired by tmuxinator-generated config 6 | 7 | tmux start-server 8 | 9 | TMUX= tmux new-session -d -s "$$SIMNET_NAME" -n simnet 10 | 11 | tmux set-option history-limit 90000 12 | tmux set -g mouse on 13 | 14 | tmux splitw -t $$SIMNET_NAME:0 15 | tmux send-keys -t $$SIMNET_NAME:0.0 "./dc build && ./dc up" Enter 16 | tmux select-window -t $$SIMNET_NAME:0 17 | tmux select-pane -t $$SIMNET_NAME:0.1 18 | 19 | if [[ -z "$TMUX" ]]; then 20 | tmux -u attach-session -t $$SIMNET_NAME 21 | else 22 | tmux -u switch-client -t $$SIMNET_NAME 23 | fi 24 | -------------------------------------------------------------------------------- /scripts/install-docker-compose.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | DOCKER_COMPOSE_VERSION=1.24.0 4 | 5 | install_linux() { 6 | # https://docs.docker.com/compose/install/#prerequisites 7 | sudo curl -L https://github.com/docker/compose/releases/download/${DOCKER_COMPOSE_VERSION}/docker-compose-`uname -s`-`uname -m` -o /usr/local/bin/docker-compose 8 | sudo chmod +x /usr/local/bin/docker-compose 9 | docker-compose --version 10 | } 11 | 12 | install_mac() { 13 | brew install docker-compose 14 | } 15 | 16 | case "$OSTYPE" in 17 | linux*) install_linux ;; 18 | darwin*) install_mac ;; 19 | *) echo "unsupported: $OSTYPE" ;; 20 | esac -------------------------------------------------------------------------------- /recipes/cookbook/scaffold/docker/pre/home/start.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | source lib/init.sh 4 | source lib/report.sh 5 | source lib/utils.sh 6 | 7 | SIMNET_NAME=${SIMNET_NAME:?required} 8 | 9 | CERTS_DIR=~/certs 10 | if [[ -f "$CERTS_DIR/rpc.cert" ]]; then 11 | echo "certificate present at '$CERTS_DIR/rpc.cert', nothing to do" 12 | else 13 | echo "certificate not present at '$CERTS_DIR/rpc.cert', generating a new one..." 14 | pushd "$CERTS_DIR" > /dev/null 15 | generate_cert "rpc" 16 | # openssl x509 -text -noout -in "rpc.cert" 17 | popd 18 | fi 19 | 20 | # we use this in ./sv to check if simnet is running 21 | signal_service_ready "$SIMNET_NAME" 22 | -------------------------------------------------------------------------------- /toolbox/ln_balance: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | set -e -o pipefail 4 | 5 | source _toolbox_lib.sh 6 | 7 | PERSON=${1:-alice} 8 | 9 | FLAVOR=$(get_flavor "$PERSON") 10 | case "$FLAVOR" in 11 | lnd) 12 | BALANCE=$("$PERSON" channelbalance | jq -r ".balance") 13 | if [[ -z "$BALANCE" ]]; then 14 | echo "-1" 15 | fi 16 | echo "$BALANCE" | sat2btc 17 | ;; 18 | lightning) 19 | "$PERSON" listfunds | jq '[.channels[].channel_sat] | add' | sat2btc 20 | ;; 21 | eclair) 22 | "$PERSON" usablebalances | jq '[.[].canSend] | add' | msat2btc 23 | ;; 24 | *) echo_err "unsupported flavor type '$FLAVOR' for '$PERSON'"; exit 1; ;; 25 | esac 26 | -------------------------------------------------------------------------------- /toolbox/pubkey: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | set -e -o pipefail 4 | 5 | source _toolbox_lib.sh 6 | 7 | PERSON=${1:-alice} 8 | 9 | err_report() { 10 | echo_err "error on line $(caller)" 11 | if [[ -n "$INFO" ]]; then 12 | echo_err "getinfo output:" 13 | echo_err "$INFO" 14 | fi 15 | return 1 16 | } 17 | 18 | trap err_report ERR 19 | 20 | INFO=$("$PERSON" getinfo) 21 | 22 | FLAVOR=$(get_flavor "$PERSON") 23 | case "$FLAVOR" in 24 | lnd) KEY="identity_pubkey" ;; 25 | lightning) KEY="id" ;; 26 | eclair) KEY="nodeId" ;; 27 | *) echo_err "unsupported flavor type '$FLAVOR' for '$PERSON'"; exit 1; ;; 28 | esac 29 | 30 | echo -n "$INFO" | jq -r ".${KEY}" 31 | -------------------------------------------------------------------------------- /recipes/cookbook/scaffold/docker/btcd/patches/simnet-as-regtest.patch: -------------------------------------------------------------------------------- 1 | diff --git a/netparams/params.go b/netparams/params.go 2 | index c15047e..e85e4ab 100644 3 | --- a/netparams/params.go 4 | +++ b/netparams/params.go 5 | @@ -32,8 +32,9 @@ var TestNet3Params = Params{ 6 | 7 | // SimNetParams contains parameters specific to the simulation test network 8 | // (wire.SimNet). 9 | +// !!! WARNING: this was patched for simverse !!! 10 | var SimNetParams = Params{ 11 | - Params: &chaincfg.SimNetParams, 12 | - RPCClientPort: "18556", 13 | - RPCServerPort: "18554", 14 | + Params: &chaincfg.RegressionNetParams, 15 | + RPCClientPort: "18334", 16 | + RPCServerPort: "18443", 17 | } 18 | -------------------------------------------------------------------------------- /recipes/cookbook/scaffold/docker/_aux/runtime/lib/ansi.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | # https://unix.stackexchange.com/a/10065/188074 4 | # check if stdout is a terminal... 5 | if test -t 1; then 6 | # see if it supports colors... 7 | ncolors=$(tput colors) 8 | if test -n "$ncolors" && test "$ncolors" -ge 8; then 9 | bold="$(tput bold)" 10 | underline="$(tput smul)" 11 | standout="$(tput smso)" 12 | normal="$(tput sgr0)" 13 | black="$(tput setaf 0)" 14 | red="$(tput setaf 1)" 15 | green="$(tput setaf 2)" 16 | yellow="$(tput setaf 3)" 17 | blue="$(tput setaf 4)" 18 | magenta="$(tput setaf 5)" 19 | cyan="$(tput setaf 6)" 20 | white="$(tput setaf 7)" 21 | fi 22 | fi -------------------------------------------------------------------------------- /recipes/cookbook/templates/docker/buildtime/Dockerfile: -------------------------------------------------------------------------------- 1 | # >>> buildtime snippet >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> 2 | # this is a Dockerfile snippet used in docker containers for building 3 | 4 | ARG GCFLAGS 5 | ENV GCFLAGS=$GCFLAGS 6 | 7 | # install build dependencies 8 | RUN apk add --no-cache --update \ 9 | musl-dev \ 10 | alpine-sdk \ 11 | gcc \ 12 | make \ 13 | file \ 14 | autoconf \ 15 | automake \ 16 | build-base \ 17 | libtool \ 18 | db-c++ \ 19 | db-dev \ 20 | boost-system \ 21 | boost-program_options \ 22 | boost-filesystem \ 23 | boost-dev \ 24 | libressl-dev \ 25 | libevent-dev \ 26 | zeromq-dev \ 27 | sqlite-dev 28 | 29 | # <<< buildtime snippet <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< 30 | -------------------------------------------------------------------------------- /recipes/cookbook/templates/_alias_utils.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | set -e -o pipefail 4 | 5 | SIMVERSE_VERBOSE_ALIASES=${SIMVERSE_VERBOSE_ALIASES} 6 | SIMVERSE_DONT_BEAUTIFY_ALIASES=${SIMVERSE_DONT_BEAUTIFY_ALIASES} 7 | 8 | beautify_if_needed() { 9 | local first_line 10 | set +e 11 | read -r first_line 12 | set -e 13 | if [[ -n "$SIMVERSE_DONT_BEAUTIFY_ALIASES" || "$first_line" != "{"* ]]; then 14 | echo "$first_line"; cat - 15 | else 16 | ( echo "$first_line"; cat - ) | jq 17 | fi 18 | } 19 | 20 | echo_command_if_needed() { 21 | if [[ -n "$SIMVERSE_VERBOSE_ALIASES" && -t 1 ]]; then 22 | echo ">" "$(basename "$0")" "$@" 23 | fi 24 | } 25 | 26 | prepare_docker_compose_exec_args() { 27 | if [[ ! -t 1 ]]; then 28 | echo "-T" 29 | fi 30 | } -------------------------------------------------------------------------------- /toolbox/open_channel: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | set -e -o pipefail 4 | 5 | source _toolbox_lib.sh 6 | 7 | FROM_PERSON=${1:-alice} 8 | TO_PERSON=${2:-bob} 9 | AMOUNT_BTC=${3:-0.1} 10 | 11 | TO_PERSON_PUBKEY=$(pubkey "${TO_PERSON}") 12 | AMOUNT_SAT=$(echo "$AMOUNT_BTC" | btc2sat) 13 | 14 | FLAVOR=$(get_flavor "$FROM_PERSON") 15 | case "$FLAVOR" in 16 | lnd) ${FROM_PERSON} openchannel "--node_key=${TO_PERSON_PUBKEY}" "--local_amt=${AMOUNT_SAT}" ;; 17 | lightning) ${FROM_PERSON} fundchannel "$TO_PERSON_PUBKEY" "$AMOUNT_SAT" 4000;; 18 | eclair) ${FROM_PERSON} open "--nodeId=${TO_PERSON_PUBKEY}" "--fundingSatoshis=${AMOUNT_SAT}" ;; 19 | *) echo_err "unsupported flavor type '$FLAVOR' for host '$FROM_PERSON'"; exit 1; ;; 20 | esac 21 | 22 | generate "${CHANNEL_CONF_COUNT}" 23 | -------------------------------------------------------------------------------- /recipes/cookbook/scaffold/docker/bitcoind/home/setup-chain.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | source lib/init.sh 4 | 5 | BITCOIN_COUNTER=${BITCOIN_COUNTER:?required} 6 | 7 | FAUCET_ADDR=${FAUCET_ADDR:?required} 8 | 9 | # always mine at least one block, this block might get orphaned by master node 10 | ./bitcoin-cli.sh generatetoaddress 1 ${FAUCET_ADDR} 11 | 12 | # mine for segwit activation only on first bitcoin node 13 | if [[ ! "$BITCOIN_COUNTER" -eq 1 ]]; then 14 | exit 0 15 | fi 16 | 17 | NUM_BLOCKS_REQUIRED=432 # https://gist.github.com/t4sk/0bc6b35a26998b9007d68f376a852636 18 | BLOCKS=$(./bitcoin-cli.sh getblockcount) 19 | if [[ "$BLOCKS" -lt "$NUM_BLOCKS_REQUIRED" ]]; then 20 | echo "Activating segwit..." 21 | ./bitcoin-cli.sh generatetoaddress ${NUM_BLOCKS_REQUIRED} ${FAUCET_ADDR} > /dev/null 22 | fi -------------------------------------------------------------------------------- /toolbox/simnet_ready: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | set -e -o pipefail 4 | 5 | source _toolbox_lib.sh 6 | 7 | SERVICES=$(docker-compose ps -q) 8 | COUNT=$(echo "$SERVICES" | wc -l | trim) 9 | if [[ "$COUNT" -lt 1 ]]; then 10 | echo "reporting failure, because we expected some running services" 11 | exit 2 12 | fi 13 | 14 | # shellcheck disable=SC2086 15 | STATUS_LIST=$(docker inspect --format "{{json .State.Health.Status }} {{json .Name }} {{json .ID }}" ${SERVICES}) 16 | 17 | echo "$STATUS_LIST" | tr -d "\"/" 18 | 19 | IFS=$'\n' 20 | while read -r LINE; do 21 | # shellcheck disable=SC2207 22 | ITEMS=( $(xargs -n1 <<<"$LINE") ) 23 | if [[ "${ITEMS[0]}" != "healthy" ]]; then 24 | echo "reporting failure because container '$(echo -n "${ITEMS[1]}" | tr -d "/")' is not healthy [${ITEMS[2]}]" 25 | exit 1 26 | fi 27 | done <<< "$STATUS_LIST" -------------------------------------------------------------------------------- /recipes/a1k1b1l2.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | . cookbook/cookbook.sh 4 | 5 | prelude 6 | 7 | add bitcoind 8 | add lightningd alice 9 | 10 | add btcd 11 | add lnd bob 12 | add lnd charlie 13 | 14 | # generate init script to build connections 15 | cat > init < fund_all < open_channels < init < fund_all < open_channels < /dev/null 2>&1; do 14 | sleep 1 15 | ((++PROBE_COUNTER)) 16 | if [[ ${PROBE_COUNTER} -gt ${MAX_PROBES} ]]; then 17 | echo "btcwallet didn't come online in time" 18 | exit 1 # this will stop whole container with failure and bring it to user attention 19 | fi 20 | done 21 | 22 | set -x 23 | ./btcctl.sh --wallet walletpassphrase "password" 0 24 | ./btcctl.sh --wallet importprivkey ${FAUCET_ADDR_PRIVATE_KEY} imported -------------------------------------------------------------------------------- /recipes/a1k1a1l2.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | . cookbook/cookbook.sh 4 | 5 | prelude 6 | 7 | add bitcoind 8 | add lightningd alice 9 | 10 | add bitcoind 11 | add lnd bob 12 | add lnd charlie 13 | 14 | # generate init script to build connections 15 | cat > init < fund_all < open_channels < init < fund_all < open_channels < init < fund_all < open_channels <= 0.009\"" # eclair numbers are fishy 21 | 22 | # --------------------------------------------------------------------------------------------------------------------------- 23 | 24 | announce "test case $SIMNET_NAME successfully completed" 25 | -------------------------------------------------------------------------------- /toolbox/generate: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | set -e -o pipefail 4 | 5 | source _toolbox_lib.sh 6 | 7 | NUM_BLOCKS=${1:-1} # number of blocks 8 | WHERE=${2} # (optional) bitcoin node which should mine it, defaults to master bitcoin node 9 | FAUCET_ADDR=${FAUCET_ADDR:?required} 10 | 11 | if [[ -z "$WHERE" ]]; then 12 | WHERE=$(lookup_service 1 role bitcoin) 13 | fi 14 | 15 | BLOCKS="blocks" 16 | if [[ "$NUM_BLOCKS" = 1 ]]; then 17 | BLOCKS="block" 18 | fi 19 | 20 | echo "generating $NUM_BLOCKS $BLOCKS via $WHERE ..." 21 | FLAVOR=$(get_flavor "$WHERE") 22 | case "$FLAVOR" in 23 | bitcoind) 24 | "$WHERE" generatetoaddress "${NUM_BLOCKS}" "${FAUCET_ADDR}" > /dev/null 25 | ;; 26 | btcd) 27 | # note: faucet addr was passed to btcd daemon as config 28 | "$WHERE" generate "${NUM_BLOCKS}" > /dev/null 29 | ;; 30 | *) echo_err "unsupported flavor type '$FLAVOR' for '$WHERE'"; exit 1; ;; 31 | esac -------------------------------------------------------------------------------- /toolbox/req_pay: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | set -e -o pipefail 4 | 5 | source _toolbox_lib.sh 6 | 7 | PERSON=${1:-alice} 8 | AMOUNT_BTC=${2:-0.01} 9 | LABEL=${3:-$PERSON invoicing $AMOUNT_BTC BTC [#$RANDOM]} 10 | DESCRIPTION=${4:-without description} 11 | 12 | FLAVOR=$(get_flavor "$PERSON") 13 | case "$FLAVOR" in 14 | lnd) 15 | AMOUNT_SAT=$(echo "$AMOUNT_BTC" | btc2sat) 16 | "$PERSON" addinvoice "--amt=${AMOUNT_SAT}" --memo="$LABEL" | jq -r ".payment_request" 17 | ;; 18 | lightning) 19 | AMOUNT_MSAT=$(echo "$AMOUNT_BTC" | btc2msat) 20 | "$PERSON" invoice "${AMOUNT_MSAT}" "$LABEL" "$DESCRIPTION" | jq -r ".bolt11" 21 | ;; 22 | eclair) 23 | AMOUNT_MSAT=$(echo "$AMOUNT_BTC" | btc2msat) 24 | "$PERSON" createinvoice "--description=$DESCRIPTION" "--amountMsat=${AMOUNT_MSAT}" | jq -r ".serialized" 25 | ;; 26 | *) echo_err "unsupported flavor type '$FLAVOR' for '$PERSON'"; exit 1; ;; 27 | esac 28 | -------------------------------------------------------------------------------- /.github/workflows/ci.yml: -------------------------------------------------------------------------------- 1 | name: CI 2 | 3 | on: 4 | push: 5 | branches: 6 | - master 7 | 8 | schedule: 9 | - cron: '0 8 * * *' 10 | 11 | env: 12 | DOCKER_COMPOSE_VERSION: 1.24.0 13 | SIMVERSE_REPORT_ENV: 1 14 | 15 | jobs: 16 | test_job: 17 | 18 | runs-on: ubuntu-latest 19 | 20 | steps: 21 | - uses: actions/checkout@v1 22 | - name: Install dependencies 23 | run: | 24 | curl -L https://github.com/docker/compose/releases/download/${DOCKER_COMPOSE_VERSION}/docker-compose-`uname -s`-`uname -m` > docker-compose 25 | chmod +x docker-compose 26 | sudo mv docker-compose /usr/local/bin 27 | # we rely on jq 1.6, apt-get currently installs version 1.5 28 | # - sudo apt-get install -y jq 29 | curl -L https://github.com/stedolan/jq/releases/download/jq-1.6/jq-linux64 > jq 30 | chmod +x jq 31 | sudo mv jq /usr/local/bin 32 | - name: Run tests 33 | run: ./tests/run.sh 34 | -------------------------------------------------------------------------------- /toolbox/pay: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | set -e -o pipefail 4 | 5 | source _toolbox_lib.sh 6 | 7 | FROM_PERSON=${1:-alice} 8 | TO_PERSON=${2:-bob} 9 | AMOUNT_BTC=${3:-0.01} 10 | 11 | PAY_REQUEST=$(req_pay "$TO_PERSON" ${AMOUNT_BTC}) 12 | 13 | FLAVOR=$(get_flavor "$FROM_PERSON") 14 | case "$FLAVOR" in 15 | lnd) "$FROM_PERSON" sendpayment --force --pay_req="${PAY_REQUEST}" ;; 16 | lightning) "$FROM_PERSON" pay "${PAY_REQUEST}" ;; 17 | eclair) 18 | PAY_ATTEMPT_ID=$("$FROM_PERSON" payinvoice --maxAttempts=100 --invoice="${PAY_REQUEST}") 19 | # see https://acinq.github.io/eclair/#getsentinfo 20 | cmd="jq -e '.[] | select(.parentId == \"${PAY_ATTEMPT_ID}\").status.paymentPreimage' <<<\$(alice getsentinfo --id=${PAY_ATTEMPT_ID})" 21 | cmd2="alice getsentinfo --id=${PAY_ATTEMPT_ID}" 22 | wait_for "payment success between $FROM_PERSON and $TO_PERSON" "$cmd" "$cmd2" 23 | ;; 24 | *) echo_err "unsupported flavor type '$FLAVOR' for '$FROM_PERSON'"; exit 1; ;; 25 | esac 26 | -------------------------------------------------------------------------------- /recipes/cookbook/scaffold/docker/btcd/home/setup-segwit.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | source lib/init.sh 4 | 5 | BITCOIN_COUNTER=${BITCOIN_COUNTER:?required} 6 | 7 | # always mine at least one block, this block might get orphaned by master node 8 | ./btcctl.sh generate 1 9 | 10 | # mine for segwit activation only on first bitcoin node 11 | if [[ ! "$BITCOIN_COUNTER" -eq 1 ]]; then 12 | exit 0 13 | fi 14 | 15 | # Prevent: "has witness data, but segwit isn't active yet" 16 | # "This means that the block height of the simnet blockchain is not high enough. 17 | # The threshold for segwit activation is 300 blocks on simnet." 18 | # source: https://degreesofzero.com/article/shared-private-lightning-network.html 19 | NUM_BLOCKS_REQUIRED=432 # https://gist.github.com/t4sk/0bc6b35a26998b9007d68f376a852636 20 | BLOCKS=$(./btcctl.sh getblockcount) 21 | if [[ "$BLOCKS" -lt "$NUM_BLOCKS_REQUIRED" ]]; then 22 | echo "Activating segwit..." 23 | ./btcctl.sh generate ${NUM_BLOCKS_REQUIRED} > /dev/null 24 | fi -------------------------------------------------------------------------------- /recipes/cookbook/scaffold/docker/eclair/home/eclair-cli.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | source lib/init.sh 4 | source lib/utils.sh 5 | 6 | CONTAINER_NAME=${CONTAINER_NAME:?required} 7 | CONTAINER_SERVICE_PORT=${CONTAINER_SERVICE_PORT:?required} 8 | ECLAIR_BITCOIN_RPC_HOST=${ECLAIR_BITCOIN_RPC_HOST} 9 | 10 | # shim for some wallet commands 11 | case "$1" in 12 | # eclair uses bitcoind's wallet, we ask it to generate a new address for us 13 | newaddr) 14 | echo get-new-address | nc "$ECLAIR_BITCOIN_RPC_HOST" "$CONTAINER_SERVICE_PORT" | trim 15 | exit 0 16 | ;; 17 | walletbalance) 18 | echo get-wallet-balance | nc "$ECLAIR_BITCOIN_RPC_HOST" "$CONTAINER_SERVICE_PORT" | trim 19 | exit 0 20 | ;; 21 | esac 22 | 23 | ECLAIR_RPC_PORT=${ECLAIR_RPC_PORT} # 8080 24 | RPC_PASS=${RPC_PASS} 25 | 26 | PARAMS="" 27 | 28 | if [[ -n "$ECLAIR_RPC_PORT" ]]; then 29 | PARAMS+=" -a http://localhost:${ECLAIR_RPC_PORT}" 30 | fi 31 | 32 | if [[ -n "$RPC_PASS" ]]; then 33 | PARAMS+=" -p \"${RPC_PASS}\"" 34 | fi 35 | 36 | #set -x 37 | exec eclair-cli ${PARAMS} "$@" 38 | -------------------------------------------------------------------------------- /toolbox/get_route: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | set -e -o pipefail 4 | 5 | source _toolbox_lib.sh 6 | 7 | FROM_PERSON=${1:-alice} 8 | TO_PERSON=${2:-bob} 9 | AMOUNT_BTC=${3:-$(sat2btc 1)} # 1 sat by default 10 | RISK_FACTOR=${4:-10} 11 | 12 | TO_PERSON_ID=$(pubkey "$TO_PERSON") 13 | 14 | FLAVOR=$(get_flavor "$FROM_PERSON") 15 | case "$FLAVOR" in 16 | lnd) 17 | AMOUNT_SAT=$(btc2sat "$AMOUNT_BTC") 18 | exec "$FROM_PERSON" queryroutes "$TO_PERSON_ID" "$AMOUNT_SAT" 19 | ;; 20 | lightning) 21 | AMOUNT_MSAT=$(btc2msat "$AMOUNT_BTC") 22 | exec "$FROM_PERSON" getroute "$TO_PERSON_ID" "$AMOUNT_MSAT" "$RISK_FACTOR" 23 | ;; 24 | eclair) 25 | AMOUNT_MSAT=$(btc2msat "$AMOUNT_BTC") 26 | ROUTE=$("$FROM_PERSON" findroutetonode --nodeId="$TO_PERSON_ID" --amountMsat="$AMOUNT_MSAT") 27 | echo "$ROUTE" 28 | # see https://github.com/ACINQ/eclair/issues/998 29 | if [[ "$ROUTE" == "route not found"* ]]; then 30 | exit 1 31 | else 32 | exit 0 33 | fi 34 | ;; 35 | *) echo_err "unsupported flavor type '$FLAVOR' for '$FROM_PERSON'"; exit 1; ;; 36 | esac 37 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2019 Antonin Hildebrand 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. -------------------------------------------------------------------------------- /tests/cases/02-pay-via-charlie/test.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | RECIPE=${1:?required} 4 | SIMNET_NAME="t02_$RECIPE" 5 | 6 | cd "$(dirname "${BASH_SOURCE[0]}")" 7 | 8 | source ../../_lib/prepare-test.sh 9 | 10 | # --------------------------------------------------------------------------------------------------------------------------- 11 | 12 | announce "running $SIMNET_NAME tests..." 13 | 14 | # LN state: alice <-0.1--0.0-> charlie <-0.1--0.0-> bob 15 | # 16 | # Payment alice -> bob of 0.01 17 | # 18 | # resulting LN state: alice <-0.09--0.01-> charlie <-0.09--0.01-> bob 19 | 20 | # init connections 21 | check "./init" 22 | 23 | # funding 24 | check "fund alice 10" 25 | check "fund charlie 5" 26 | 27 | # open channels 28 | check "open_channel alice charlie 0.1" 29 | check "open_channel charlie bob 0.1" 30 | 31 | # perform payment 32 | check "wait_for_route alice bob" 33 | check "is \"\$(ln_balance bob) == 0\"" 34 | check "pay alice bob 0.01" 35 | check_retry "is \"\$(ln_balance bob) >= 0.009\"" # eclair numbers are fishy 36 | check_retry "is \"\$(ln_balance charlie) >= 0.09\"" # losing on fees? 37 | 38 | # --------------------------------------------------------------------------------------------------------------------------- 39 | 40 | announce "test case $SIMNET_NAME successfully completed" 41 | -------------------------------------------------------------------------------- /recipes/cookbook/scaffold/docker/lnd/Dockerfile: -------------------------------------------------------------------------------- 1 | ARG LND_DOCKER_BUILDTIME_IMAGE 2 | ARG LND_DOCKER_RUNTIME_IMAGE 3 | 4 | FROM ${LND_DOCKER_BUILDTIME_IMAGE} as simverse_buildtime_lnd 5 | 6 | #include BASE_DOCKERFILE_SNIPPET 7 | #include BUILDTIME_DOCKERFILE_SNIPPET 8 | 9 | ARG LND_REPO_PATH 10 | 11 | WORKDIR $GOPATH/src/github.com/lightningnetwork/lnd 12 | COPY "$LND_REPO_PATH" . 13 | 14 | # force Go to use the cgo based DNS resolver. This is required to ensure DNS 15 | # queries required to connect to linked containers succeed. 16 | ENV GODEBUG netdns=cgo 17 | 18 | # install dependencies and install/build lnd. 19 | RUN make && make install 20 | 21 | # --------------------------------------------------------------------------------------------------------------------------- 22 | 23 | FROM ${LND_DOCKER_RUNTIME_IMAGE} as simverse_runtime_lnd 24 | 25 | #include BASE_DOCKERFILE_SNIPPET 26 | #include RUNTIME_DOCKERFILE_SNIPPET 27 | 28 | ARG LND_CONF_PATH 29 | 30 | # copy the binaries and entrypoint from the builder image. 31 | COPY --from=simverse_buildtime_lnd /go/bin/lncli /bin/ 32 | COPY --from=simverse_buildtime_lnd /go/bin/lnd /bin/ 33 | 34 | USER simnet 35 | 36 | WORKDIR /home/simnet 37 | 38 | COPY --chown=simnet "docker/lnd/home" "." 39 | COPY --chown=simnet "$LND_CONF_PATH" "seed-lnd.conf" 40 | 41 | RUN mkdir .lnd 42 | -------------------------------------------------------------------------------- /recipes/cookbook/scaffold/docker/btcd/home/start-btcd.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | source lib/init.sh 4 | 5 | cp "seed-btcd.conf" ".btcd/btcd.conf" 6 | 7 | PARAMS="" 8 | 9 | # optional parameters 10 | DEBUG=${DEBUG} 11 | RPC_USER=${RPC_USER} 12 | RPC_PASS=${RPC_PASS} 13 | FAUCET_ADDR=${FAUCET_ADDR} 14 | BITCOIN_P2P_BIND=${BITCOIN_P2P_BIND} 15 | BITCOIN_P2P_PORT=${BITCOIN_P2P_PORT} 16 | BITCOIN_RPC_BIND=${BITCOIN_RPC_BIND} 17 | BITCOIN_RPC_PORT=${BITCOIN_RPC_PORT} 18 | BTCD_EXTRA_PARAMS=${BTCD_EXTRA_PARAMS} 19 | 20 | PARAMS+=" --regtest" 21 | 22 | if [[ -n "$DEBUG" ]]; then 23 | PARAMS+=" --debuglevel=$DEBUG" 24 | fi 25 | 26 | if [[ -n "$BITCOIN_P2P_BIND" ]]; then 27 | PARAMS+=" --listen=$BITCOIN_P2P_BIND:$BITCOIN_P2P_PORT" 28 | fi 29 | 30 | if [[ -n "$BITCOIN_RPC_BIND" ]]; then 31 | PARAMS+=" --rpclisten=$BITCOIN_RPC_BIND:$BITCOIN_RPC_PORT" 32 | fi 33 | 34 | if [[ -n "$RPC_USER" ]]; then 35 | PARAMS+=" --rpcuser=$RPC_USER" 36 | PARAMS+=" --rpcpass=$RPC_PASS" 37 | fi 38 | 39 | if [[ -n "$FAUCET_ADDR" ]]; then 40 | PARAMS+=" --miningaddr=$FAUCET_ADDR" 41 | fi 42 | 43 | if [[ ! "$@" = *"--droptxindex"* ]]; then 44 | PARAMS+=" --txindex" 45 | fi 46 | 47 | # we keep one shared rpc cert for all btcd nodes 48 | PARAMS+=" --rpccert=/certs/rpc.cert" 49 | PARAMS+=" --rpckey=/certs/rpc.key" 50 | 51 | set -x 52 | exec btcd ${PARAMS} ${BTCD_EXTRA_PARAMS} "$@" 53 | -------------------------------------------------------------------------------- /toolbox/fund: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | set -e -o pipefail 4 | 5 | source _toolbox_lib.sh 6 | 7 | PERSON=${1:-alice} 8 | AMOUNT_BTC=${2:-100} 9 | 10 | ADDRESS=$(newaddr "$PERSON") 11 | 12 | ORIGINAL_BALANCE_BTC=$(onchain_balance "$PERSON") 13 | echo "generated new address $ADDRESS for $PERSON (original balance ${ORIGINAL_BALANCE_BTC} BTC)" 14 | 15 | AVAILABLE_BALANCE_BTC=$(faucet_balance) 16 | 17 | if is "${AVAILABLE_BALANCE_BTC} < ${AMOUNT_BTC}"; then 18 | echo "insufficient balance $AVAILABLE_BALANCE_BTC BTC, earning more..." 19 | earn "${AMOUNT_BTC}" 20 | fi 21 | 22 | echo "sending $AMOUNT_BTC BTC to $PERSON" 23 | 24 | if is_btcd_master; then 25 | # a simple direct command would be: 26 | # btcctl --wallet sendfrom imported ${ADDRESS} ${AMOUNT_BTC} 27 | 28 | # btcctl can be flaky and report "-32603: insufficient funds available to construct transaction" 29 | # see https://travis-ci.org/darwin/simverse/builds/531193450#L3941 30 | # let's try it in a loop and hope it succeeds at some point, also mine some blocks between trials 31 | SEND_CMD="btcctl --wallet sendfrom imported ${ADDRESS} ${AMOUNT_BTC}" 32 | wait_for "sending funds to $PERSON" "$SEND_CMD" "generate 1" 33 | else 34 | bitcoin-cli sendtoaddress "${ADDRESS}" "${AMOUNT_BTC}" 35 | fi 36 | 37 | generate "${TX_CONF_COUNT}" 38 | 39 | # c-lightning is pretty lazy in updating its state 40 | # we have to resort to polling... 41 | EXPECTED_BALANCE=$(compute "${ORIGINAL_BALANCE_BTC} + ${AMOUNT_BTC}") 42 | wait_for_onchain_balance "$PERSON" "$EXPECTED_BALANCE" 43 | 44 | NEW_BALANCE_BTC=$(onchain_balance "$PERSON") 45 | echo "$PERSON now has ${NEW_BALANCE_BTC} BTC" -------------------------------------------------------------------------------- /recipes/cookbook/scaffold/docker/bitcoind/Dockerfile: -------------------------------------------------------------------------------- 1 | ARG BITCOIND_DOCKER_BUILDTIME_IMAGE 2 | ARG BITCOIND_DOCKER_RUNTIME_IMAGE 3 | 4 | FROM ${BITCOIND_DOCKER_BUILDTIME_IMAGE} as simverse_buildtime_bitcoind 5 | 6 | #include BASE_DOCKERFILE_SNIPPET 7 | #include BUILDTIME_DOCKERFILE_SNIPPET 8 | 9 | ARG BITCOIND_REPO_PATH 10 | 11 | WORKDIR /root/build 12 | 13 | COPY "$BITCOIND_REPO_PATH" . 14 | # lower optimizations for faster builds 15 | ARG CFLAGS="" 16 | ARG CXXFLAGS="$CFLAGS" 17 | ARG MAKEFLAGS="-j4" 18 | 19 | ENV CFLAGS="$CFLAGS" 20 | ENV CXXFLAGS="$CXXFLAGS" 21 | ENV MAKEFLAGS="$MAKEFLAGS" 22 | 23 | RUN ./autogen.sh 24 | 25 | ARG BITCOIND_CONFIGURE_FLAGS="--without-gui --disable-tests --disable-bench --with-incompatible-bdb" 26 | RUN ./configure $BITCOIND_CONFIGURE_FLAGS 27 | 28 | RUN make 29 | 30 | RUN make install 31 | 32 | # --------------------------------------------------------------------------------------------------------------------------- 33 | 34 | FROM ${BITCOIND_DOCKER_RUNTIME_IMAGE} as simverse_runtime_bitcoind 35 | 36 | #include BASE_DOCKERFILE_SNIPPET 37 | #include RUNTIME_DOCKERFILE_SNIPPET 38 | 39 | ARG BITCOIND_CONF_PATH 40 | 41 | # copy the compiled binaries from the builder image 42 | COPY --from=simverse_buildtime_bitcoind /usr/local/bin/bitcoin* /usr/local/bin/ 43 | 44 | # we also need to copy some relevant libraries over 45 | COPY --from=simverse_buildtime_bitcoind /usr/lib/libboost* /usr/lib/ 46 | COPY --from=simverse_buildtime_bitcoind /usr/local/lib/libbitcoin* /usr/local/lib/ 47 | 48 | USER simnet 49 | 50 | WORKDIR /home/simnet 51 | 52 | COPY --chown=simnet "docker/bitcoind/home" "." 53 | COPY --chown=simnet "$BITCOIND_CONF_PATH" "seed-bitcoin.conf" 54 | 55 | RUN mkdir .bitcoin 56 | -------------------------------------------------------------------------------- /tests/_lib/travis.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | # this was generated by https://github.com/travis-ci/travis-build 4 | 5 | TRAVIS_ANSI_CLEAR="\033[0K" 6 | 7 | case $(uname | tr '[:upper:]' '[:lower:]') in 8 | linux*) 9 | TRAVIS_OS_NAME=linux 10 | ;; 11 | darwin*) 12 | TRAVIS_OS_NAME=osx 13 | ;; 14 | msys*) 15 | TRAVIS_OS_NAME=windows 16 | ;; 17 | *) 18 | TRAVIS_OS_NAME=notset 19 | ;; 20 | esac 21 | 22 | travis_time_start() { 23 | TRAVIS_TIMER_ID="$(printf %08x $((RANDOM * RANDOM)))" 24 | TRAVIS_TIMER_START_TIME="$(travis_nanoseconds)" 25 | export TRAVIS_TIMER_ID TRAVIS_TIMER_START_TIME 26 | echo -en "travis_time:start:$TRAVIS_TIMER_ID\r${TRAVIS_ANSI_CLEAR}" 27 | } 28 | 29 | travis_time_finish() { 30 | local travis_timer_end_time 31 | travis_timer_end_time="$(travis_nanoseconds)" 32 | local duration 33 | duration="$((travis_timer_end_time - TRAVIS_TIMER_START_TIME))" 34 | echo -en "travis_time:end:${TRAVIS_TIMER_ID}:start=${TRAVIS_TIMER_START_TIME},finish=${travis_timer_end_time},duration=${duration}\r${TRAVIS_ANSI_CLEAR}" 35 | } 36 | 37 | travis_nanoseconds() { 38 | local cmd='date' 39 | local format='+%s%N' 40 | 41 | if hash gdate >/dev/null 2>&1; then 42 | cmd='gdate' 43 | elif [[ "${TRAVIS_OS_NAME}" == osx ]]; then 44 | format='+%s000000000' 45 | fi 46 | 47 | "${cmd}" -u "${format}" 48 | } 49 | 50 | travis_fold() { 51 | local action=$1 52 | local name=$2 53 | echo -en "travis_fold:${action}:${name}\r${TRAVIS_ANSI_CLEAR}" 54 | } 55 | 56 | travis_section() { 57 | local action=$1 58 | if [[ "$action" == "start" ]]; then 59 | travis_fold "$@" 60 | travis_time_start 61 | else 62 | travis_time_finish 63 | travis_fold "$@" 64 | fi 65 | } 66 | -------------------------------------------------------------------------------- /recipes/cookbook/scaffold/docker/bitcoind/home/bitcoind.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | #!/usr/bin/env bash 4 | 5 | source lib/init.sh 6 | 7 | cp "seed-bitcoin.conf" ".bitcoin/bitcoin.conf" 8 | 9 | RPC_USER=${RPC_USER} 10 | RPC_PASS=${RPC_PASS} 11 | BITCOIN_P2P_BIND=${BITCOIN_P2P_BIND} 12 | BITCOIN_P2P_PORT=${BITCOIN_P2P_PORT} 13 | BITCOIN_RPC_BIND=${BITCOIN_RPC_BIND} 14 | BITCOIN_RPC_PORT=${BITCOIN_RPC_PORT} 15 | BITCOIND_EXTRA_PARAMS=${BITCOIND_EXTRA_PARAMS} 16 | ZMQ_PUBRAWBLOCK_PORT=${ZMQ_PUBRAWBLOCK_PORT} # 28332 17 | ZMQ_PUBRAWTX_PORT=${ZMQ_PUBRAWTX_PORT} # 28333 18 | ZMQ_BIND=${ZMQ_BIND} # 0.0.0.0 19 | ZMQ_PUBRAWBLOCK="tcp://$ZMQ_BIND:$ZMQ_PUBRAWBLOCK_PORT" 20 | ZMQ_PUBRAWTX="tcp://$ZMQ_BIND:$ZMQ_PUBRAWTX_PORT" 21 | 22 | PARAMS="" 23 | PARAMS+=" -regtest" 24 | PARAMS+=" -server=1" 25 | PARAMS+=" -rest=1" 26 | PARAMS+=" -txindex=1" 27 | PARAMS+=" -port=${BITCOIN_P2P_PORT}" 28 | PARAMS+=" -rpcbind=${BITCOIN_RPC_BIND}" 29 | PARAMS+=" -rpcport=${BITCOIN_RPC_PORT}" 30 | PARAMS+=" -rpcallowip=0.0.0.0/0" 31 | 32 | if [[ -n "$RPC_USER" ]]; then 33 | PARAMS+=" -rpcuser=$RPC_USER" 34 | PARAMS+=" -rpcpassword=$RPC_PASS" 35 | fi 36 | 37 | PARAMS+=" -zmqpubrawblock=$ZMQ_PUBRAWBLOCK" 38 | PARAMS+=" -zmqpubrawtx=$ZMQ_PUBRAWTX" 39 | PARAMS+=" -printtoconsole" 40 | 41 | # this instructs bitcoind to activate segwit with mainnet rules since block 0 42 | # without this segwit would be activated by default and that would break consensus with btcd peers 43 | # https://github.com/bitcoin/bitcoin/pull/11389 44 | # this is no longer needed since https://github.com/bitcoin/bitcoin/commit/1bf2ff2bf8e8bef3ba21e635aabb1b0964062743 45 | # PARAMS+=" -vbparams=segwit:0:999999999999" 46 | 47 | set -x 48 | exec bitcoind ${PARAMS} ${BITCOIND_EXTRA_PARAMS} "$@" 49 | -------------------------------------------------------------------------------- /recipes/cookbook/scaffold/docker/bitcoind/home/setup-wallet.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | source lib/init.sh 4 | 5 | FAUCET_ADDR_PRIVATE_KEY=${FAUCET_ADDR_PRIVATE_KEY:?required} 6 | 7 | echo "Initializing wallet..." 8 | 9 | # we need to wait for bitcoin-cli start responding 10 | PROBE_CMD="./bitcoin-cli.sh -getinfo" 11 | PROBE_COUNTER=1 12 | MAX_PROBES=100 13 | while ! ${PROBE_CMD} > /dev/null 2>&1; do 14 | sleep 1 15 | ((++PROBE_COUNTER)) 16 | if [[ ${PROBE_COUNTER} -gt ${MAX_PROBES} ]]; then 17 | echo "bitcoin-cli didn't come online in time" 18 | exit 1 # this will stop whole container with failure and bring it to user attention 19 | fi 20 | done 21 | 22 | set -x 23 | 24 | # must be "" (empty name), this name is hard-coded in eclair: 25 | # https://github.com/ACINQ/eclair/blob/662e0c4bcc1dec24f9aad2bd526866a8a056153f/eclair-core/src/main/scala/fr/acinq/eclair/blockchain/bitcoind/rpc/BasicBitcoinJsonRPCClient.scala#L40 26 | # https://gitter.im/ACINQ/eclair?at=5e48f793c8da1343d4540a44 27 | # with a different name we would get "bitcoind must have wallet support enabled" from: 28 | # https://github.com/ACINQ/eclair/blob/daddfc007fe569c89bb854ef5d672614d397e91e/eclair-core/src/main/scala/fr/acinq/eclair/Setup.scala#L150 29 | # that error message is quite misleading in this particular situation, it should not swallow original error 30 | # and should communicate both, something like "unable to get balance, error: Requested wallet does not exist or is not loaded (code: -18)" 31 | WALLET_NAME="" 32 | WALLET_DIR="$HOME/.bitcoin/regtest/wallets/$WALLET_NAME" 33 | if [[ -e "$WALLET_DIR" ]]; then 34 | rm -rf "$WALLET_DIR" 35 | fi 36 | ./bitcoin-cli.sh createwallet "$WALLET_NAME" 37 | ./bitcoin-cli.sh importprivkey "${FAUCET_ADDR_PRIVATE_KEY}" imported 38 | -------------------------------------------------------------------------------- /recipes/cookbook/scaffold/docker/btcd/home/start-btcwallet.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | source lib/init.sh 4 | 5 | cp "seed-btcwallet.conf" ".btcwallet/btcwallet.conf" 6 | 7 | PARAMS="" 8 | 9 | # note we patch btcwallet's simnet mode to effectively run in regtest mode 10 | # see patches/simnet-as-regtest.patch 11 | # see https://github.com/btcsuite/btcwallet/issues/506 12 | PARAMS+=" --simnet" 13 | 14 | PARAMS+=" --appdata=$(pwd -P)/.btcwallet" 15 | 16 | # we keep one shared rpc cert for all btcd nodes 17 | PARAMS+=" --cafile=/certs/rpc.cert" 18 | PARAMS+=" --rpccert=/certs/rpc.cert" 19 | PARAMS+=" --rpckey=/certs/rpc.key" 20 | 21 | # optional parameters 22 | BTCWALLET_EXTRA_PARAMS=${BTCWALLET_EXTRA_PARAMS} 23 | BTCWALLET_RPC_BIND=${BTCWALLET_RPC_BIND} 24 | BTCWALLET_RPC_PORT=${BTCWALLET_RPC_PORT} 25 | RPC_USER=${RPC_USER} 26 | RPC_PASS=${RPC_PASS} 27 | BTCWALLET_USER=${BTCWALLET_USER} 28 | BTCWALLET_PASS=${BTCWALLET_PASS} 29 | DEBUG=${DEBUG} 30 | 31 | if [[ -n "$DEBUG" ]]; then 32 | PARAMS+=" --debuglevel=$DEBUG" 33 | fi 34 | 35 | if [[ -n "$BTCWALLET_RPC_BIND" ]]; then 36 | PARAMS+=" --rpclisten=$BTCWALLET_RPC_BIND:$BTCWALLET_RPC_PORT" 37 | fi 38 | 39 | if [[ -n "$RPC_USER" ]]; then 40 | PARAMS+=" --btcdusername=$RPC_USER" 41 | if [[ -z "$BTCWALLET_USER" ]]; then 42 | BTCWALLET_USER="$RPC_USER" 43 | fi 44 | fi 45 | 46 | if [[ -n "$RPC_PASS" ]]; then 47 | PARAMS+=" --btcdpassword=$RPC_PASS" 48 | if [[ -z "$BTCWALLET_PASS" ]]; then 49 | BTCWALLET_PASS="$RPC_PASS" 50 | fi 51 | fi 52 | 53 | if [[ -n "$BTCWALLET_USER" ]]; then 54 | PARAMS+=" --username=$BTCWALLET_USER" 55 | PARAMS+=" --password=$BTCWALLET_PASS" 56 | fi 57 | 58 | PARAMS+=" --createtemp" 59 | 60 | set -x 61 | exec btcwallet ${PARAMS} ${BTCWALLET_EXTRA_PARAMS} "$@" 62 | -------------------------------------------------------------------------------- /toolbox/connect: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | set -e -o pipefail 4 | 5 | source _toolbox_lib.sh 6 | 7 | FROM_PERSON=${1:-alice} 8 | TO_PERSON=${2:-bob} 9 | 10 | connect_bitcoin_nodes() { 11 | local role 12 | role=$(get_role "$TO_PERSON") 13 | if [[ "$role" != "bitcoin" ]]; then 14 | echo_err "both nodes to have the same role, '$TO_PERSON' has role '$role' but 'bitcoin' was expected" 15 | exit 2 16 | fi 17 | 18 | # note: we don't have to check for flavor here, both bitcoind and btcd have compatible 'addnode' cli interface 19 | "$FROM_PERSON" addnode "$TO_PERSON" onetry 20 | # note we need to generate one block to trigger potential block sync 21 | # not sure what is the issue, but this might be related https://bitcoin.stackexchange.com/q/27055/875 22 | generate 1 "$FROM_PERSON" 23 | } 24 | 25 | connect_ln_nodes() { 26 | local role 27 | role=$(get_role "$TO_PERSON") 28 | if [[ "$role" != "ln" ]]; then 29 | echo_err "both nodes to have the same role, '$TO_PERSON' has role '$role' but 'ln' was expected" 30 | exit 2 31 | fi 32 | 33 | TO_PERSON_CONNECTION=$(ln_connect_string "$TO_PERSON") 34 | if [[ -z "$TO_PERSON_CONNECTION" ]]; then 35 | echo_err "failed to format connection string for '$TO_PERSON'" 36 | exit 1 37 | fi 38 | 39 | local flavor 40 | flavor=$(get_flavor "$FROM_PERSON") 41 | case "$flavor" in 42 | lnd|lightning) "$FROM_PERSON" connect "$TO_PERSON_CONNECTION" ;; 43 | eclair) "$FROM_PERSON" connect --uri="$TO_PERSON_CONNECTION" ;; 44 | *) echo_err "unsupported flavor type '$flavor' for '$FROM_PERSON'"; exit 1; ;; 45 | esac 46 | } 47 | 48 | ROLE=$(get_role "$FROM_PERSON") 49 | case "$ROLE" in 50 | bitcoin) connect_bitcoin_nodes ;; 51 | ln) connect_ln_nodes ;; 52 | *) echo_err "unsupported role type '$ROLE' for '$FROM_PERSON'"; exit 1; ;; 53 | esac 54 | -------------------------------------------------------------------------------- /recipes/cookbook/templates/docker/runtime/Dockerfile: -------------------------------------------------------------------------------- 1 | # >>> runtime snippet >>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> 2 | # this is a Dockerfile snippet used in docker containers for runtime 3 | 4 | ARG SIMVERSE_HOST_UID 5 | ARG SIMVERSE_HOST_GID 6 | 7 | RUN apk add --no-cache --update \ 8 | libzmq \ 9 | libevent \ 10 | db \ 11 | db-c++ \ 12 | libressl \ 13 | jq \ 14 | tini \ 15 | tree \ 16 | sqlite-libs 17 | 18 | # TODO: move this into a special snippet to provide go debugging support 19 | # RUN go get -u github.com/go-delve/delve/cmd/dlv 20 | # RUN dlv version 21 | 22 | # we want to prepare simnet user and run services under it 23 | # our main reason is to have docker _volumes written with host-friendly permissions 24 | # see https://dille.name/blog/2018/07/16/handling-file-permissions-when-writing-to-volumes-from-docker-containers/ 25 | 26 | # if the GID is already taken, create group without forcing external SIMVERSE_HOST_GID 27 | RUN if getent group $SIMVERSE_HOST_GID > /dev/null 2>&1; \ 28 | then addgroup simnet; \ 29 | else addgroup -g $SIMVERSE_HOST_GID simnet; \ 30 | fi 31 | 32 | # if the GID is already taken, create group without forcing external SIMVERSE_HOST_GID 33 | RUN if id -u $SIMVERSE_HOST_UID > /dev/null 2>&1; \ 34 | then adduser -D -h /home/simnet -G simnet simnet; \ 35 | else adduser -D -h /home/simnet -G simnet -u $SIMVERSE_HOST_UID simnet; \ 36 | fi 37 | 38 | WORKDIR /home/simnet 39 | 40 | ENV PATH $PATH:/home/simnet 41 | 42 | # we don't want to force entrypoint to not confuse ad-hoc commands via `docker exec` 43 | # see our `run` scripts in individual containers which might decide to use tiny as a wrapper 44 | # ENTRYPOINT ["/sbin/tini", "--"] 45 | # see https://github.com/krallin/tini 46 | 47 | # <<< runtime snippet <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< 48 | -------------------------------------------------------------------------------- /recipes/cookbook/scaffold/docker/lightning/home/lightningd.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | source lib/init.sh 4 | 5 | mkdir -p "$LIGHTNINGD_DATA/regtest" 6 | cp "seed-config" "$LIGHTNINGD_DATA/regtest/config" 7 | 8 | # optional parameters 9 | RPC_USER=${RPC_USER} 10 | RPC_PASS=${RPC_PASS} 11 | DEBUG=${DEBUG} 12 | LIGHTNING_ALIAS=${LIGHTNING_ALIAS} # 13 | LIGHTNING_BACKEND=${LIGHTNING_BACKEND} 14 | LIGHTNING_P2P_BIND=${LIGHTNING_P2P_BIND} # 0.0.0.0 15 | LIGHTNING_P2P_PORT=${LIGHTNING_P2P_PORT} # 9735 16 | LIGHTNING_RPC_BIND=${LIGHTNING_RPC_BIND} # 0.0.0.0 17 | LIGHTNING_RPC_PORT=${LIGHTNING_RPC_PORT} # 10009 18 | LIGHTNING_BITCOIN_RPC_HOST=${LIGHTNING_BITCOIN_RPC_HOST} 19 | BITCOIN_RPC_PORT=${BITCOIN_RPC_PORT} 20 | LIGHTNINGD_EXTRA_PARAMS=${LIGHTNINGD_EXTRA_PARAMS} 21 | 22 | if [[ "$LIGHTNING_BACKEND" != "bitcoind" ]]; then 23 | echo "c-lightning nodes support only bitcoind backend, you passed '$LIGHTNING_BACKEND'" 24 | exit 1 25 | fi 26 | 27 | PARAMS="" 28 | 29 | PARAMS=" --network regtest" 30 | 31 | if [[ -n "$LIGHTNING_BITCOIN_RPC_HOST" ]]; then 32 | PARAMS+=" --bitcoin-rpcconnect $LIGHTNING_BITCOIN_RPC_HOST" 33 | fi 34 | 35 | if [[ -n "$BITCOIN_RPC_PORT" ]]; then 36 | PARAMS+=" --bitcoin-rpcport $BITCOIN_RPC_PORT" 37 | fi 38 | 39 | if [[ -n "$RPC_USER" ]]; then 40 | PARAMS+=" --bitcoin-rpcuser $RPC_USER" 41 | PARAMS+=" --bitcoin-rpcpassword $RPC_PASS" 42 | fi 43 | 44 | if [[ -n "$LIGHTNING_ALIAS" ]]; then 45 | PARAMS+=" --alias=$LIGHTNING_ALIAS" 46 | fi 47 | 48 | if [[ -n "$LIGHTNING_P2P_BIND" ]]; then 49 | PARAMS+=" --bind-addr $LIGHTNING_P2P_BIND:$LIGHTNING_P2P_PORT" 50 | fi 51 | 52 | if [[ -n "$DEBUG" ]]; then 53 | PARAMS+=" --log-level=$DEBUG" 54 | fi 55 | 56 | PARAMS+=" --disable-dns" 57 | PARAMS+=" --rpc-file=${LIGHTNINGD_RPC_DIR_SIMVERSE}/lightning-rpc" 58 | 59 | set -x 60 | exec lightning-docker-entrypoint.sh ${PARAMS} ${LIGHTNINGD_EXTRA_PARAMS} "$@" 61 | -------------------------------------------------------------------------------- /recipes/cookbook/templates/prelude.yml: -------------------------------------------------------------------------------- 1 | version: '3.7' 2 | 3 | # https://docs.docker.com/compose/compose-file/#extension-fields 4 | x-shared: &shared 5 | networks: 6 | - ${SIMVERSE_DOCKER_NETWORK_PREFIX}${SIMNET_NAME}_network 7 | healthcheck: 8 | test: "nc -z localhost ${SERVICE_READY_PORT}" 9 | interval: 5s 10 | timeout: 10s 11 | retries: 3 12 | start_period: 2m 13 | privileged: true # needed for dlv attach 14 | stop_grace_period: 1m 15 | security_opt: 16 | - seccomp:unconfined # https://github.com/arrisray/secql/commit/19b8e85c270b888cecc3a0364b7956ba9e0f5334 17 | 18 | networks: 19 | ${SIMVERSE_DOCKER_NETWORK_PREFIX}${SIMNET_NAME}_network: 20 | driver: bridge 21 | name: ${SIMVERSE_DOCKER_NETWORK_PREFIX}${SIMNET_NAME}_network 22 | 23 | services: 24 | 25 | pre: 26 | <<: *shared 27 | image: ${SIMVERSE_DOCKER_IMAGE_PREFIX}${SIMNET_NAME}_pre 28 | container_name: ${SIMVERSE_DOCKER_CONTAINER_PREFIX}${SIMNET_NAME}_pre 29 | command: ["run"] 30 | build: 31 | context: . 32 | dockerfile: docker/pre/Dockerfile 33 | args: 34 | - SIMVERSE_HOST_UID=$SIMVERSE_HOST_UID 35 | - SIMVERSE_HOST_GID=$SIMVERSE_HOST_GID 36 | - PRE_DOCKER_BUILDTIME_IMAGE=$PRE_DOCKER_BUILDTIME_IMAGE 37 | - PRE_DOCKER_RUNTIME_IMAGE=$PRE_DOCKER_RUNTIME_IMAGE 38 | ports: 39 | - $SIMVERSE_HOST_BIND$SERVICE_READY_PORT_ON_HOST:$SERVICE_READY_PORT # readiness signal port 40 | volumes: 41 | # !DANGER! when touching this, review cookbook.sh > prepare_pre_volumes 42 | - ./_volumes/certs:/home/simnet/certs # shared certificates 43 | environment: 44 | - CONTAINER_NAME=pre 45 | - REPORT_ENV=${SIMVERSE_REPORT_ENV} 46 | - SERVICE_READY_PORT=${SERVICE_READY_PORT} 47 | - CONTAINER_SERVICE_PORT=${CONTAINER_SERVICE_PORT} 48 | - SIMNET_NAME=${SIMNET_NAME} 49 | $SIMVERSE_EXTRA_SERVICE_CONFIG 50 | -------------------------------------------------------------------------------- /recipes/readme.md: -------------------------------------------------------------------------------- 1 | # Simnet recipes 2 | 3 | Simnet recipe describes how a simnet should look like. You can pick one of existing recipes in this folder or create your own. 4 | 5 | Please run `./simverse help recipes` to learn more: 6 | 7 | ``` 8 | About recipes 9 | 10 | Simnets can have different sizes and shapes. They can be heavily parametrized. 11 | Recipe is a script describing how to build a given simnet. 12 | 13 | An example of a simple recipe: 14 | 15 | . cookbook/cookbook.sh 16 | 17 | prelude 18 | 19 | add btcd btcd 20 | 21 | add lnd alice 22 | add lnd bob 23 | 24 | Recipes are located under `recipes` folder. 25 | Say, we stored the above recipe as `recipes/example.sh`. 26 | 27 | By running `./sv create example mysn`, we create a new simnet named `mysn` 28 | which has one btcd node and two lnd nodes, all with default settings. 29 | 30 | Recipes are bash scripts executed as the last step in simnet creation. 31 | That means you can do anything bash can do to tweak given simnet. 32 | To make your life easier, we provide a simple library "cookbook" for building 33 | simnet on step-by-step basis with sane defaults. 34 | 35 | We are not going to document the cookbook here. Please refer to its sources. 36 | 37 | Please look around in `recipes` folder and see how existing recipes are done. 38 | ``` 39 | 40 | ## Naming conventions: 41 | 42 | I adopted a simple naming convention: strings of letter-number to hint on network shape 43 | 44 | * `a` - [bitcoind](https://github.com/bitcoin/bitcoin) 45 | * `b` - [btcd](https://github.com/btcsuite/btcd) 46 | * `k` - [lightningd](https://github.com/ElementsProject/lightning) 47 | * `l` - [lnd](https://github.com/lightningnetwork/lnd) 48 | * `m` - [eclair](https://github.com/ACINQ/eclair) 49 | 50 | So for example `b1l2` reads as "one master btcd node and two lnd nodes". 51 | You might want to specify arbitrary postfix if you want to distinguish more nuanced setups, e.g. `a1k1b1l2-routing-test`. -------------------------------------------------------------------------------- /tests/_lib/prepare-test.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | RECIPE=${RECIPE:?require} 4 | TRAVIS=${TRAVIS} 5 | 6 | SIMNET_NAME=${SIMNET_NAME:?required} 7 | SIMVERSE_HOME=${SIMVERSE_HOME:?required} 8 | SIMVERSE_WORKSPACE=${SIMVERSE_WORKSPACE:?required} 9 | SIMVERSE_NOANSI=${SIMVERSE_NOANSI} 10 | SIMVERSE_DEBUG_TEST=${SIMVERSE_DEBUG_TEST} 11 | SIMVERSE_SHELL=${SIMVERSE_SHELL:-$SHELL} 12 | 13 | if [[ -n "$TRAVIS" ]]; then 14 | SIMVERSE_NOANSI=1 15 | fi 16 | 17 | DOCKER_COMPOSE_OPTS= 18 | if [[ -n "$SIMVERSE_NOANSI" ]]; then 19 | DOCKER_COMPOSE_OPTS="--no-ansi" 20 | fi 21 | 22 | cd "$(dirname "${BASH_SOURCE[0]}")" 23 | 24 | source ../../toolbox/_toolbox_lib.sh 25 | source helpers.sh 26 | 27 | # --------------------------------------------------------------------------------------------------------------------------- 28 | 29 | cd "${SIMVERSE_HOME}" 30 | 31 | log_section start "prepare_simnet" 32 | announce "creating simnet '$SIMNET_NAME'..." 33 | ./sv create ${RECIPE} ${SIMNET_NAME} --yes 34 | enter_simnet ${SIMNET_NAME} 35 | log_section end "prepare_simnet" 36 | 37 | log_section start "build_docker_containers" 38 | announce "building docker containers..." 39 | ./dc ${DOCKER_COMPOSE_OPTS} build 40 | log_section end "build_docker_containers" 41 | 42 | log_section start "start_docker_containers" 43 | announce "starting docker containers..." 44 | ./dc ${DOCKER_COMPOSE_OPTS} up -d 45 | log_section end "start_docker_containers" 46 | 47 | tear_down() { 48 | if [[ $? -ne 0 ]]; then 49 | brief 50 | if [[ -n "$SIMVERSE_DEBUG_TEST" ]]; then 51 | echo "entering shell for debugging because SIMVERSE_DEBUG_TEST is set:" 52 | "$SIMVERSE_SHELL" 53 | fi 54 | fi 55 | 56 | log_section start "stop_docker_containers" 57 | announce "stopping docker containers..." 58 | ./dc ${DOCKER_COMPOSE_OPTS} down 59 | log_section end "stop_docker_containers" 60 | } 61 | 62 | trap tear_down EXIT 63 | 64 | if ! wait_simnet_ready; then 65 | exit 2 66 | fi 67 | -------------------------------------------------------------------------------- /recipes/cookbook/scaffold/helpers/lib/utils.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | pushd() { 4 | command pushd "$@" > /dev/null 5 | } 6 | 7 | popd() { 8 | command popd "$@" > /dev/null 9 | } 10 | 11 | echo_err() { 12 | printf "\e[31m%s\e[0m\n" "$*" >&2; 13 | } 14 | 15 | docker_image_exists() { 16 | test "$(docker images -q "$1" 2> /dev/null)" != "" 17 | } 18 | 19 | docker_image_rev() { 20 | local image_name=${1:?required} 21 | local rev="$(docker inspect --format "{{index .Config.Labels \"simverse.rev\" }}" "${image_name}")" 22 | if [[ -z "$rev" ]]; then 23 | echo -n "0"; 24 | else 25 | echo -n "$rev" 26 | fi 27 | } 28 | 29 | # https://stackoverflow.com/a/24067243/84283 30 | version_gt() { 31 | test "$(printf '%s\n' "$@" | sort --version-sort -r | head -n 1)" == "$1" 32 | } 33 | 34 | check_prereq() { 35 | local tool=${1:?required} 36 | local min_version=$2 37 | local version_cmd=${3:-$tool --version} 38 | 39 | if ! command -v "$tool" > /dev/null; then 40 | echo "Required prerequisite '$tool' is missing on your system. We didn't detect it on your \$PATH. Please install it." 41 | echo "Simverse requires version '$min_version' or higher." 42 | echo "For additional info see https://github.com/darwin/simverse#prerequisites." 43 | return 1 44 | fi 45 | 46 | if [[ -n "$min_version" ]]; then 47 | local actual_version 48 | actual_version=$(bash -c "$version_cmd") 49 | if ! version_gt "$actual_version" "$min_version"; then 50 | echo "Required prerequisite '$tool' is outdated on your system (we detected version '$actual_version'). Please update it." 51 | echo "Simverse requires version '$min_version' or higher." 52 | echo "For additional info see https://github.com/darwin/simverse#prerequisites." 53 | return 2 54 | fi 55 | fi 56 | } 57 | 58 | check_prereqs() { 59 | check_prereq bash 4.0 "echo '$BASH_VERSION'" 60 | check_prereq jq jq-1.6 61 | check_prereq git 2.0 "git --version | head -n 1 | cut -d ' ' -f 3" 62 | check_prereq docker 18.06 "docker --version | head -n 1 | tr , ' ' | cut -d ' ' -f 3" 63 | check_prereq docker-compose 1.24 "docker-compose --version | head -n 1 | tr , ' ' | cut -d ' ' -f 3" 64 | } -------------------------------------------------------------------------------- /recipes/cookbook/scaffold/docker/lnd/home/lnd.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | source lib/init.sh 4 | 5 | cp "seed-lnd.conf" ".lnd/lnd.conf" 6 | 7 | # optional parameters 8 | RPC_USER=${RPC_USER} 9 | RPC_PASS=${RPC_PASS} 10 | DEBUG=${DEBUG} 11 | LND_CHAIN=${LND_CHAIN} # bitcoin 12 | LND_BACKEND=${LND_BACKEND} 13 | LND_P2P_BIND=${LND_P2P_BIND} # 0.0.0.0 14 | LND_P2P_PORT=${LND_P2P_PORT} # 9735 15 | LND_RPC_BIND=${LND_RPC_BIND} # 0.0.0.0 16 | LND_RPC_PORT=${LND_RPC_PORT} # 10009 17 | LND_REST_BIND=${LND_REST_BIND} # 0.0.0.0 18 | LND_REST_PORT=${LND_REST_PORT} # 8080 19 | LND_BITCOIN_RPC_HOST=${LND_BITCOIN_RPC_HOST} 20 | BITCOIN_RPC_PORT=${BITCOIN_RPC_PORT} 21 | LND_EXTRA_PARAMS=${LND_EXTRA_PARAMS} 22 | ZMQ_PUBRAWBLOCK_PORT=${ZMQ_PUBRAWBLOCK_PORT} # 28332 23 | ZMQ_PUBRAWTX_PORT=${ZMQ_PUBRAWTX_PORT} # 28333 24 | ZMQ_PUBRAWBLOCK="tcp://$LND_BITCOIN_RPC_HOST:$ZMQ_PUBRAWBLOCK_PORT" 25 | ZMQ_PUBRAWTX="tcp://$LND_BITCOIN_RPC_HOST:$ZMQ_PUBRAWTX_PORT" 26 | 27 | PARAMS="" 28 | 29 | if [[ -n "$LND_CHAIN" ]]; then 30 | PARAMS+=" --$LND_CHAIN.active" 31 | PARAMS+=" --$LND_CHAIN.regtest" 32 | PARAMS+=" --$LND_CHAIN.node=$LND_BACKEND" 33 | fi 34 | 35 | if [[ -n "$LND_BACKEND" && -n "$LND_BITCOIN_RPC_HOST" ]]; then 36 | PARAMS+=" --$LND_BACKEND.rpchost=$LND_BITCOIN_RPC_HOST:$BITCOIN_RPC_PORT" 37 | fi 38 | 39 | if [[ -n "$LND_BACKEND" && -n "$RPC_USER" ]]; then 40 | PARAMS+=" --$LND_BACKEND.rpcuser=$RPC_USER" 41 | PARAMS+=" --$LND_BACKEND.rpcpass=$RPC_PASS" 42 | fi 43 | 44 | if [[ "$LND_BACKEND" == "btcd" ]]; then 45 | PARAMS+=" --btcd.rpccert=/certs/rpc.cert" 46 | fi 47 | 48 | if [[ "$LND_BACKEND" == "bitcoind" ]]; then 49 | PARAMS+=" --bitcoind.zmqpubrawblock=$ZMQ_PUBRAWBLOCK" 50 | PARAMS+=" --bitcoind.zmqpubrawtx=$ZMQ_PUBRAWTX" 51 | fi 52 | 53 | if [[ -n "$LND_P2P_BIND" ]]; then 54 | PARAMS+=" --listen=$LND_P2P_BIND:$LND_P2P_PORT" 55 | fi 56 | 57 | if [[ -n "$LND_RPC_BIND" ]]; then 58 | PARAMS+=" --rpclisten=$LND_RPC_BIND:$LND_RPC_PORT" 59 | fi 60 | 61 | if [[ -n "$LND_REST_BIND" ]]; then 62 | PARAMS+=" --restlisten=$LND_REST_BIND:$LND_REST_PORT" 63 | fi 64 | 65 | if [[ -n "$DEBUG" ]]; then 66 | PARAMS+=" --debuglevel=$DEBUG" 67 | fi 68 | 69 | PARAMS+=" --noseedbackup" 70 | 71 | set -x 72 | exec lnd ${PARAMS} ${LND_EXTRA_PARAMS} "$@" 73 | -------------------------------------------------------------------------------- /tests/run.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | set -e -o pipefail 4 | 5 | TEST_SUITE=${1:-default} 6 | 7 | LAUNCH_DIR=$(pwd -P) 8 | 9 | SIMVERSE_DEBUG_TEST=${SIMVERSE_DEBUG_TEST} 10 | SIMVERSE_TEST_REPOS=${SIMVERSE_TEST_REPOS} 11 | 12 | cd "$(dirname "${BASH_SOURCE[0]}")" 13 | 14 | TESTS_DIR="$(pwd -P)" 15 | 16 | source ../toolbox/_toolbox_lib.sh 17 | source _lib/helpers.sh 18 | 19 | cd .. 20 | 21 | export SIMVERSE_HOME="$(pwd -P)" 22 | 23 | # instead of generating TMP_DIR using mktemp, default SIMVERSE_TEST_TMP to /tmp to prevent error: 24 | # "lightningd: Binding rpc socket to 'lightning-rpc': Filename too long" 25 | # this has something to do with docker bug under macOS: https://github.com/moby/moby/issues/23545 26 | # having long TMP_DIR will cause failures inside docker container, when process tries work with files 27 | # in that mapped volume folder (bind call in case of c-lightning) 28 | SIMVERSE_TEST_TMP=${SIMVERSE_TEST_TMP:-/tmp} 29 | if [[ -n "$SIMVERSE_TEST_TMP" ]]; then 30 | TMP_DIR="$SIMVERSE_TEST_TMP/simverse-tests" 31 | rm -rf "$TMP_DIR" 32 | mkdir -p "$TMP_DIR" 33 | else 34 | TMP_DIR=$(mktemp -d -t simverse_tests.XXXXXXXX) 35 | fi 36 | 37 | if [[ ! "$TMP_DIR" || ! -d "$TMP_DIR" ]]; then 38 | echo_err "failed to create temp directory" 39 | exit 1 40 | fi 41 | 42 | cleanup() { 43 | rm -rf "$TMP_DIR" 44 | } 45 | 46 | trap "exit 20" HUP INT PIPE QUIT TERM 47 | trap cleanup EXIT 48 | 49 | export SIMVERSE_WORKSPACE=${SIMVERSE_WORKSPACE:-$TMP_DIR/_workspace} 50 | if [[ -n "$SIMVERSE_TEST_REPOS" ]]; then 51 | export SIMVERSE_REPOS="$SIMVERSE_TEST_REPOS" 52 | export SIMVERSE_GIT_REFERENCE_PREFIX= 53 | else 54 | export SIMVERSE_REPOS=${SIMVERSE_REPOS:-$TMP_DIR/_repos} 55 | export SIMVERSE_GIT_REFERENCE_PREFIX=${SIMVERSE_GIT_REFERENCE_PREFIX:-$SIMVERSE_HOME/_repos} # use git references to limit network I/O 56 | fi 57 | 58 | cd "${SIMVERSE_HOME}" 59 | 60 | log_section start "repos_init" 61 | announce "init repos" 62 | ./sv repos init 63 | log_section end "repos_init" 64 | 65 | log_section start "repos_report" 66 | announce "report repos" 67 | ./sv repos report 68 | log_section end "repos_report" 69 | 70 | cd "$TESTS_DIR" 71 | 72 | announce "running [$TEST_SUITE] tests from '$(pwd -P)'" 73 | 74 | # echo alias commands during tests 75 | export SIMVERSE_VERBOSE_ALIASES=1 76 | 77 | . "suites/$TEST_SUITE.sh" 78 | 79 | announce "all tests went OK" 80 | -------------------------------------------------------------------------------- /recipes/cookbook/scaffold/docker/btcd/patches/btcctl-regtest.patch: -------------------------------------------------------------------------------- 1 | diff --git a/cmd/btcctl/config.go b/cmd/btcctl/config.go 2 | index cd232a9e..03a17d73 100644 3 | --- a/cmd/btcctl/config.go 4 | +++ b/cmd/btcctl/config.go 5 | @@ -105,13 +105,14 @@ type config struct { 6 | ProxyPass string `long:"proxypass" default-mask:"-" description:"Password for proxy server"` 7 | TestNet3 bool `long:"testnet" description:"Connect to testnet"` 8 | SimNet bool `long:"simnet" description:"Connect to the simulation test network"` 9 | + RegTest bool `long:"regtest" description:"Connect to the regtest test network"` 10 | TLSSkipVerify bool `long:"skipverify" description:"Do not verify tls certificates (not recommended!)"` 11 | Wallet bool `long:"wallet" description:"Connect to wallet"` 12 | } 13 | 14 | // normalizeAddress returns addr with the passed default port appended if 15 | // there is not already a port specified. 16 | -func normalizeAddress(addr string, useTestNet3, useSimNet, useWallet bool) string { 17 | +func normalizeAddress(addr string, useTestNet3, useSimNet, useWallet, useRegTest bool) string { 18 | _, _, err := net.SplitHostPort(addr) 19 | if err != nil { 20 | var defaultPort string 21 | @@ -128,6 +129,12 @@ func normalizeAddress(addr string, useTestNet3, useSimNet, useWallet bool) strin 22 | } else { 23 | defaultPort = "18556" 24 | } 25 | + case useRegTest: 26 | + if useWallet { 27 | + defaultPort = "18443" 28 | + } else { 29 | + defaultPort = "18334" 30 | + } 31 | default: 32 | if useWallet { 33 | defaultPort = "8332" 34 | @@ -254,8 +261,11 @@ func loadConfig() (*config, []string, error) { 35 | if cfg.SimNet { 36 | numNets++ 37 | } 38 | + if cfg.RegTest { 39 | + numNets++ 40 | + } 41 | if numNets > 1 { 42 | - str := "%s: The testnet and simnet params can't be used " + 43 | + str := "%s: The testnet, simnet, regtest params can't be used " + 44 | "together -- choose one of the two" 45 | err := fmt.Errorf(str, "loadConfig") 46 | fmt.Fprintln(os.Stderr, err) 47 | @@ -274,7 +284,7 @@ func loadConfig() (*config, []string, error) { 48 | // Add default port to RPC server based on --testnet and --wallet flags 49 | // if needed. 50 | cfg.RPCServer = normalizeAddress(cfg.RPCServer, cfg.TestNet3, 51 | - cfg.SimNet, cfg.Wallet) 52 | + cfg.SimNet, cfg.Wallet, cfg.RegTest) 53 | 54 | return &cfg, remainingArgs, nil 55 | } 56 | -------------------------------------------------------------------------------- /recipes/cookbook/templates/bitcoind.yml: -------------------------------------------------------------------------------- 1 | ${NAME}: 2 | <<: *shared 3 | image: ${SIMVERSE_DOCKER_IMAGE_PREFIX}${SIMNET_NAME}_bitcoind 4 | container_name: ${SIMVERSE_DOCKER_CONTAINER_PREFIX}${SIMNET_NAME}_${NAME} 5 | command: ["run"] 6 | build: 7 | context: . 8 | dockerfile: docker/bitcoind/Dockerfile 9 | args: 10 | - GCFLAGS=$GCFLAGS 11 | - SIMVERSE_HOST_UID=$SIMVERSE_HOST_UID 12 | - SIMVERSE_HOST_GID=$SIMVERSE_HOST_GID 13 | - BITCOIND_DOCKER_BUILDTIME_IMAGE=$BITCOIND_DOCKER_BUILDTIME_IMAGE 14 | - BITCOIND_DOCKER_RUNTIME_IMAGE=$BITCOIND_DOCKER_RUNTIME_IMAGE 15 | - BITCOIND_REPO_PATH=$BITCOIND_REPO_PATH 16 | - BITCOIND_CONF_PATH=$BITCOIND_CONF_PATH 17 | ports: 18 | - $SIMVERSE_HOST_BIND$(($SERVICE_READY_PORT_ON_HOST+$SERVICE_COUNTER)):$SERVICE_READY_PORT # readiness signal port 19 | - $SIMVERSE_HOST_BIND$BITCOIND_SERVER_PORT_ON_HOST:${BITCOIN_P2P_PORT} # bitcoind p2p port 20 | - $SIMVERSE_HOST_BIND$BITCOIND_RPC_PORT_ON_HOST:${BITCOIN_RPC_PORT} # bitcoind rpc port 21 | volumes: 22 | # !DANGER! when touching this, review cookbook.sh > prepare_bitcoind_volumes 23 | - ./_volumes/bitcoind-data-${NAME}:/home/simnet/.bitcoin # bitcoind data dir 24 | labels: 25 | - "simverse.role=bitcoin" 26 | - "simverse.flavor=bitcoind" 27 | - "simverse.service_counter=${SERVICE_COUNTER}" 28 | - "simverse.role_counter=${BITCOIN_COUNTER}" 29 | - "simverse.flavor_counter=${BITCOIND_COUNTER}" 30 | environment: 31 | - CONTAINER_NAME=${NAME} 32 | - REPORT_ENV=${SIMVERSE_REPORT_ENV} 33 | - SERVICE_READY_PORT=${SERVICE_READY_PORT} 34 | - CONTAINER_SERVICE_PORT=${CONTAINER_SERVICE_PORT} 35 | - SERVICE_COUNTER=${SERVICE_COUNTER} 36 | - BITCOIN_COUNTER=${BITCOIN_COUNTER} 37 | - BITCOIND_COUNTER=${BITCOIND_COUNTER} 38 | - FAUCET_ADDR=${FAUCET_ADDR} 39 | - FAUCET_ADDR_PRIVATE_KEY=${FAUCET_ADDR_PRIVATE_KEY} 40 | - RPC_USER=${RPC_USER} 41 | - RPC_PASS=${RPC_PASS} 42 | - BITCOIN_P2P_BIND=${BITCOIN_P2P_BIND} 43 | - BITCOIN_P2P_PORT=${BITCOIN_P2P_PORT} 44 | - BITCOIN_RPC_BIND=${BITCOIN_RPC_BIND} 45 | - BITCOIN_RPC_PORT=${BITCOIN_RPC_PORT} 46 | - BITCOIND_EXTRA_PARAMS=${BITCOIND_EXTRA_PARAMS} 47 | - BITCOINCLI_EXTRA_PARAMS=${BITCOINCLI_EXTRA_PARAMS} 48 | - ZMQ_BIND=${ZMQ_BIND} 49 | - ZMQ_PUBRAWBLOCK_PORT=${ZMQ_PUBRAWBLOCK_PORT} 50 | - ZMQ_PUBRAWTX_PORT=${ZMQ_PUBRAWTX_PORT} 51 | $SIMVERSE_EXTRA_SERVICE_CONFIG -------------------------------------------------------------------------------- /recipes/cookbook/scaffold/docker/btcd/Dockerfile: -------------------------------------------------------------------------------- 1 | ARG BTCD_DOCKER_BUILDTIME_IMAGE 2 | ARG BTCD_DOCKER_RUNTIME_IMAGE 3 | 4 | FROM ${BTCD_DOCKER_BUILDTIME_IMAGE} as simverse_buildtime_btcwallet 5 | 6 | #include BASE_DOCKERFILE_SNIPPET 7 | #include BUILDTIME_DOCKERFILE_SNIPPET 8 | 9 | ARG BTCWALLET_REPO_PATH 10 | 11 | # https://github.com/btcsuite/btcwallet#installation-and-updating 12 | WORKDIR $GOPATH/src/github.com/btcsuite/btcwallet 13 | 14 | COPY "$BTCWALLET_REPO_PATH" . 15 | COPY "docker/btcd/patches/simnet-as-regtest.patch" . 16 | RUN git apply simnet-as-regtest.patch 17 | RUN GO111MODULE=on go install -v . ./cmd/... 18 | 19 | # --------------------------------------------------------------------------------------------------------------------------- 20 | 21 | FROM ${BTCD_DOCKER_BUILDTIME_IMAGE} as simverse_buildtime_btcd 22 | 23 | #include BASE_DOCKERFILE_SNIPPET 24 | #include BUILDTIME_DOCKERFILE_SNIPPET 25 | 26 | ARG BTCD_REPO_PATH 27 | 28 | WORKDIR /root/build 29 | 30 | # we want to populate the module cache based on the go.{mod,sum} files. 31 | COPY "$BTCD_REPO_PATH/go.mod" . 32 | COPY "$BTCD_REPO_PATH/go.sum" . 33 | 34 | # pre-cache deps 35 | # see https://container-solutions.com/faster-builds-in-docker-with-go-1-11/ 36 | RUN go mod download 37 | 38 | WORKDIR $GOPATH/src/github.com/btcsuite/btcd 39 | 40 | # https://github.com/btcsuite/btcd#installation 41 | COPY "$BTCD_REPO_PATH" . 42 | COPY "docker/btcd/patches/btcctl-regtest.patch" . 43 | RUN git apply btcctl-regtest.patch 44 | RUN GO111MODULE=on go install -v . ./cmd/... 45 | 46 | # --------------------------------------------------------------------------------------------------------------------------- 47 | 48 | FROM ${BTCD_DOCKER_RUNTIME_IMAGE} as simverse_runtime_btcd 49 | 50 | #include BASE_DOCKERFILE_SNIPPET 51 | #include RUNTIME_DOCKERFILE_SNIPPET 52 | 53 | ARG BTCD_CONF_PATH 54 | ARG BTCWALLET_CONF_PATH 55 | 56 | # copy the compiled binaries from the builder image. 57 | COPY --from=simverse_buildtime_btcd /go/bin/addblock /bin/ 58 | COPY --from=simverse_buildtime_btcd /go/bin/btcctl /bin/ 59 | COPY --from=simverse_buildtime_btcd /go/bin/btcd /bin/ 60 | COPY --from=simverse_buildtime_btcd /go/bin/findcheckpoint /bin/ 61 | COPY --from=simverse_buildtime_btcd /go/bin/gencerts /bin/ 62 | 63 | COPY --from=simverse_buildtime_btcwallet /go/bin/btcwallet /bin/ 64 | 65 | USER simnet 66 | 67 | WORKDIR /home/simnet 68 | 69 | COPY --chown=simnet "docker/btcd/home" "." 70 | COPY --chown=simnet "$BTCD_CONF_PATH" "seed-btcd.conf" 71 | COPY --chown=simnet "$BTCWALLET_CONF_PATH" "seed-btcwallet.conf" 72 | 73 | RUN mkdir .btcd 74 | RUN mkdir .btcwallet 75 | -------------------------------------------------------------------------------- /recipes/cookbook/templates/eclair.yml: -------------------------------------------------------------------------------- 1 | ${NAME}: 2 | <<: *shared 3 | image: ${SIMVERSE_DOCKER_IMAGE_PREFIX}${SIMNET_NAME}_eclair 4 | container_name: ${SIMVERSE_DOCKER_CONTAINER_PREFIX}${SIMNET_NAME}_${NAME} 5 | command: ["run"] 6 | build: 7 | context: . 8 | dockerfile: docker/eclair/Dockerfile 9 | args: 10 | - GCFLAGS=$GCFLAGS 11 | - SIMVERSE_HOST_UID=$SIMVERSE_HOST_UID 12 | - SIMVERSE_HOST_GID=$SIMVERSE_HOST_GID 13 | - ECLAIR_DOCKER_BUILDTIME_IMAGE=$ECLAIR_DOCKER_BUILDTIME_IMAGE 14 | - ECLAIR_DOCKER_RUNTIME_IMAGE=$ECLAIR_DOCKER_RUNTIME_IMAGE 15 | - ECLAIR_REPO_PATH=$ECLAIR_REPO_PATH 16 | - ECLAIR_CONF_PATH=$ECLAIR_CONF_PATH 17 | ports: 18 | - $SIMVERSE_HOST_BIND$(($SERVICE_READY_PORT_ON_HOST+$SERVICE_COUNTER)):$SERVICE_READY_PORT # readiness signal port 19 | - $SIMVERSE_HOST_BIND$ECLAIR_SERVER_PORT_ON_HOST:${ECLAIR_P2P_PORT} # eclair p2p port 20 | - $SIMVERSE_HOST_BIND$ECLAIR_RPC_PORT_ON_HOST:${ECLAIR_RPC_PORT} # eclair rpc port 21 | volumes: 22 | # !DANGER! when touching this, review cookbook.sh > prepare_eclair_volumes 23 | - ./_volumes/eclair-data-${NAME}:/home/simnet/.eclair # eclair data dir 24 | labels: 25 | - "simverse.role=ln" 26 | - "simverse.flavor=eclair" 27 | - "simverse.service_counter=${SERVICE_COUNTER}" 28 | - "simverse.role_counter=${LN_COUNTER}" 29 | - "simverse.flavor_counter=${ECLAIR_COUNTER}" 30 | environment: 31 | - CONTAINER_NAME=${NAME} 32 | - REPORT_ENV=${SIMVERSE_REPORT_ENV} 33 | - SERVICE_READY_PORT=${SERVICE_READY_PORT} 34 | - CONTAINER_SERVICE_PORT=${CONTAINER_SERVICE_PORT} 35 | - SERVICE_COUNTER=${SERVICE_COUNTER} 36 | - LN_COUNTER=${LN_COUNTER} 37 | - ECLAIR_COUNTER=${ECLAIR_COUNTER} 38 | - DEBUG=${DEBUG} 39 | - RPC_USER=${RPC_USER} 40 | - RPC_PASS=${RPC_PASS} 41 | - ECLAIR_ALIAS=${NAME} 42 | - ECLAIR_EXTRA_PARAMS=${ECLAIR_EXTRA_PARAMS} 43 | - ECLAIR_CHAIN=${ECLAIR_CHAIN} 44 | - ECLAIR_BACKEND=${ECLAIR_BACKEND} 45 | - ECLAIR_P2P_BIND=${ECLAIR_P2P_BIND} 46 | - ECLAIR_P2P_PORT=${ECLAIR_P2P_PORT} 47 | - ECLAIR_RPC_BIND=${ECLAIR_RPC_BIND} 48 | - ECLAIR_RPC_PORT=${ECLAIR_RPC_PORT} 49 | - ECLAIR_BITCOIN_RPC_HOST=${ECLAIR_BITCOIN_RPC_HOST} 50 | - BITCOIN_RPC_PORT=${BITCOIN_RPC_PORT} 51 | - FAUCET_ADDR=${FAUCET_ADDR} 52 | - FAUCET_ADDR_PRIVATE_KEY=${FAUCET_ADDR_PRIVATE_KEY} 53 | - ZMQ_PUBRAWBLOCK_PORT=${ZMQ_PUBRAWBLOCK_PORT} 54 | - ZMQ_PUBRAWTX_PORT=${ZMQ_PUBRAWTX_PORT} 55 | $SIMVERSE_EXTRA_SERVICE_CONFIG 56 | -------------------------------------------------------------------------------- /recipes/cookbook/templates/lnd.yml: -------------------------------------------------------------------------------- 1 | ${NAME}: 2 | <<: *shared 3 | image: ${SIMVERSE_DOCKER_IMAGE_PREFIX}${SIMNET_NAME}_lnd 4 | container_name: ${SIMVERSE_DOCKER_CONTAINER_PREFIX}${SIMNET_NAME}_${NAME} 5 | command: ["run"] 6 | build: 7 | context: . 8 | dockerfile: docker/lnd/Dockerfile 9 | args: 10 | - GCFLAGS=$GCFLAGS 11 | - SIMVERSE_HOST_UID=$SIMVERSE_HOST_UID 12 | - SIMVERSE_HOST_GID=$SIMVERSE_HOST_GID 13 | - LND_DOCKER_BUILDTIME_IMAGE=$LND_DOCKER_BUILDTIME_IMAGE 14 | - LND_DOCKER_RUNTIME_IMAGE=$LND_DOCKER_RUNTIME_IMAGE 15 | - LND_REPO_PATH=$LND_REPO_PATH 16 | - LND_CONF_PATH=$LND_CONF_PATH 17 | ports: 18 | - $SIMVERSE_HOST_BIND$(($SERVICE_READY_PORT_ON_HOST+$SERVICE_COUNTER)):$SERVICE_READY_PORT # readiness signal port 19 | - $SIMVERSE_HOST_BIND$LND_SERVER_PORT_ON_HOST:${LND_P2P_PORT} # lnd p2p port 20 | - $SIMVERSE_HOST_BIND$LND_RPC_PORT_ON_HOST:${LND_RPC_PORT} # lnd rpc port 21 | - $SIMVERSE_HOST_BIND$LND_REST_PORT_ON_HOST:${LND_REST_PORT} # lnd rest port 22 | - $SIMVERSE_HOST_BIND$DLV_PORT_ON_HOST:$DLV_PORT # go-delve port 23 | volumes: 24 | # !DANGER! when touching this, review cookbook.sh > prepare_lnd_volumes 25 | - ./_volumes/certs:/certs:ro # shared certificates 26 | - ./_volumes/lnd-data-${NAME}:/home/simnet/.lnd # lnd data dir 27 | labels: 28 | - "simverse.role=ln" 29 | - "simverse.flavor=lnd" 30 | - "simverse.service_counter=${SERVICE_COUNTER}" 31 | - "simverse.role_counter=${LN_COUNTER}" 32 | - "simverse.flavor_counter=${LND_COUNTER}" 33 | environment: 34 | - CONTAINER_NAME=${NAME} 35 | - REPORT_ENV=${SIMVERSE_REPORT_ENV} 36 | - SERVICE_READY_PORT=${SERVICE_READY_PORT} 37 | - CONTAINER_SERVICE_PORT=${CONTAINER_SERVICE_PORT} 38 | - SERVICE_COUNTER=${SERVICE_COUNTER} 39 | - LN_COUNTER=${LN_COUNTER} 40 | - LND_COUNTER=${LND_COUNTER} 41 | - DEBUG=${DEBUG} 42 | - RPC_USER=${RPC_USER} 43 | - RPC_PASS=${RPC_PASS} 44 | - LND_EXTRA_PARAMS=${LND_EXTRA_PARAMS} 45 | - LND_CHAIN=${LND_CHAIN} 46 | - LND_BACKEND=${LND_BACKEND} 47 | - LND_P2P_BIND=${LND_P2P_BIND} 48 | - LND_P2P_PORT=${LND_P2P_PORT} 49 | - LND_RPC_BIND=${LND_RPC_BIND} 50 | - LND_RPC_PORT=${LND_RPC_PORT} 51 | - LND_REST_BIND=${LND_REST_BIND} 52 | - LND_REST_PORT=${LND_REST_PORT} 53 | - LND_BITCOIN_RPC_HOST=${LND_BITCOIN_RPC_HOST} 54 | - BITCOIN_RPC_PORT=${BITCOIN_RPC_PORT} 55 | - FAUCET_ADDR=${FAUCET_ADDR} 56 | - FAUCET_ADDR_PRIVATE_KEY=${FAUCET_ADDR_PRIVATE_KEY} 57 | - ZMQ_PUBRAWBLOCK_PORT=${ZMQ_PUBRAWBLOCK_PORT} 58 | - ZMQ_PUBRAWTX_PORT=${ZMQ_PUBRAWTX_PORT} 59 | $SIMVERSE_EXTRA_SERVICE_CONFIG 60 | -------------------------------------------------------------------------------- /recipes/cookbook/scaffold/docker/eclair/home/eclair.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | source lib/init.sh 4 | 5 | cp "seed-eclair.conf" ".eclair/eclair.conf" 6 | 7 | # optional parameters 8 | RPC_USER=${RPC_USER} 9 | RPC_PASS=${RPC_PASS} 10 | DEBUG=${DEBUG} 11 | ECLAIR_ALIAS=${ECLAIR_ALIAS} # 12 | ECLAIR_BACKEND=${ECLAIR_BACKEND} 13 | ECLAIR_P2P_BIND=${ECLAIR_P2P_BIND} # 0.0.0.0 14 | ECLAIR_P2P_PORT=${ECLAIR_P2P_PORT} # 9735 15 | ECLAIR_RPC_BIND=${ECLAIR_RPC_BIND} # 0.0.0.0 16 | ECLAIR_RPC_PORT=${ECLAIR_RPC_PORT} # 8080 17 | ECLAIR_BITCOIN_RPC_HOST=${ECLAIR_BITCOIN_RPC_HOST} 18 | BITCOIN_RPC_PORT=${BITCOIN_RPC_PORT} 19 | ECLAIR_EXTRA_PARAMS=${ECLAIR_EXTRA_PARAMS} 20 | ZMQ_PUBRAWBLOCK_PORT=${ZMQ_PUBRAWBLOCK_PORT} # 28332 21 | ZMQ_PUBRAWTX_PORT=${ZMQ_PUBRAWTX_PORT} # 28333 22 | ZMQ_PUBRAWBLOCK="tcp://$ECLAIR_BITCOIN_RPC_HOST:$ZMQ_PUBRAWBLOCK_PORT" 23 | ZMQ_PUBRAWTX="tcp://$ECLAIR_BITCOIN_RPC_HOST:$ZMQ_PUBRAWTX_PORT" 24 | 25 | 26 | if [[ "$ECLAIR_BACKEND" != "bitcoind" ]]; then 27 | echo "eclair nodes support only bitcoind backend, you passed '$ECLAIR_BACKEND'" 28 | # note: in future eclair.watcher-type could support other bitcoin node implementations 29 | exit 1 30 | fi 31 | 32 | PARAMS="" 33 | 34 | PARAMS+=" -Declair.chain=regtest" 35 | 36 | if [[ -n "$ECLAIR_P2P_BIND" ]]; then 37 | PARAMS+=" -Declair.server.binding-ip=$ECLAIR_P2P_BIND" 38 | fi 39 | 40 | if [[ -n "$ECLAIR_P2P_PORT" ]]; then 41 | PARAMS+=" -Declair.server.port=$ECLAIR_P2P_PORT" 42 | fi 43 | 44 | if [[ -n "$ECLAIR_RPC_PORT" ]]; then 45 | PARAMS+=" -Declair.api.enabled=true" 46 | PARAMS+=" -Declair.api.port=$ECLAIR_RPC_PORT" 47 | PARAMS+=" -Declair.api.password=$RPC_PASS" 48 | fi 49 | 50 | if [[ -n "$ECLAIR_RPC_BIND" ]]; then 51 | PARAMS+=" -Declair.api.binding-ip=$ECLAIR_RPC_BIND" 52 | fi 53 | 54 | if [[ -n "$ECLAIR_BITCOIN_RPC_HOST" ]]; then 55 | PARAMS+=" -Declair.bitcoind.host=$ECLAIR_BITCOIN_RPC_HOST" 56 | fi 57 | 58 | if [[ -n "$BITCOIN_RPC_PORT" ]]; then 59 | PARAMS+=" -Declair.bitcoind.rpcport=$BITCOIN_RPC_PORT" 60 | fi 61 | 62 | if [[ -n "$RPC_USER" ]]; then 63 | PARAMS+=" -Declair.bitcoind.rpcuser=$RPC_USER" 64 | PARAMS+=" -Declair.bitcoind.rpcpassword=$RPC_PASS" 65 | fi 66 | 67 | if [[ -n "$ECLAIR_ALIAS" ]]; then 68 | PARAMS+=" -Declair.node-alias=$ECLAIR_ALIAS" 69 | fi 70 | 71 | if [[ -n "$ZMQ_PUBRAWBLOCK_PORT" ]]; then 72 | PARAMS+=" -Declair.bitcoind.zmqblock=$ZMQ_PUBRAWBLOCK" 73 | fi 74 | 75 | if [[ -n "$ZMQ_PUBRAWTX_PORT" ]]; then 76 | PARAMS+=" -Declair.bitcoind.zmqtx=$ZMQ_PUBRAWTX" 77 | fi 78 | 79 | #if [[ -n "$DEBUG" ]]; then 80 | # PARAMS+=" --log-level=$DEBUG" 81 | #fi 82 | 83 | PARAMS+=" -Declair.printToConsole=true" 84 | 85 | # https://github.com/ACINQ/eclair/wiki/Logging 86 | PARAMS+=" -Dakka.loglevel=DEBUG" 87 | 88 | set -x 89 | exec $JAVA_OPTS eclair-node/bin/eclair-node.sh ${PARAMS} ${ECLAIR_EXTRA_PARAMS} "$@" 90 | -------------------------------------------------------------------------------- /recipes/cookbook/templates/btcd.yml: -------------------------------------------------------------------------------- 1 | ${NAME}: 2 | <<: *shared 3 | image: ${SIMVERSE_DOCKER_IMAGE_PREFIX}${SIMNET_NAME}_btcd 4 | container_name: ${SIMVERSE_DOCKER_CONTAINER_PREFIX}${SIMNET_NAME}_${NAME} 5 | command: ["run"] 6 | build: 7 | context: . 8 | dockerfile: docker/btcd/Dockerfile 9 | args: 10 | - GCFLAGS=$GCFLAGS 11 | - SIMVERSE_HOST_UID=$SIMVERSE_HOST_UID 12 | - SIMVERSE_HOST_GID=$SIMVERSE_HOST_GID 13 | - BTCD_DOCKER_BUILDTIME_IMAGE=$BTCD_DOCKER_BUILDTIME_IMAGE 14 | - BTCD_DOCKER_RUNTIME_IMAGE=$BTCD_DOCKER_RUNTIME_IMAGE 15 | - BTCD_REPO_PATH=$BTCD_REPO_PATH 16 | - BTCD_CONF_PATH=$BTCD_CONF_PATH 17 | - BTCWALLET_REPO_PATH=$BTCWALLET_REPO_PATH 18 | - BTCWALLET_CONF_PATH=$BTCWALLET_CONF_PATH 19 | ports: 20 | - $SIMVERSE_HOST_BIND$(($SERVICE_READY_PORT_ON_HOST+$SERVICE_COUNTER)):$SERVICE_READY_PORT # readiness signal port 21 | - $SIMVERSE_HOST_BIND$BTCD_SERVER_PORT_ON_HOST:${BITCOIN_P2P_PORT} # btcd p2p port 22 | - $SIMVERSE_HOST_BIND$BTCD_RPC_PORT_ON_HOST:${BITCOIN_RPC_PORT} # btcd rpc port 23 | - $SIMVERSE_HOST_BIND$BTCWALLET_RPC_PORT_ON_HOST:${BTCWALLET_RPC_PORT} # btcwallet rpc port 24 | - $SIMVERSE_HOST_BIND$DLV_PORT_ON_HOST:$DLV_PORT # go-delve port 25 | volumes: 26 | # !DANGER! when touching this, review cookbook.sh > prepare_btcd_volumes 27 | - ./_volumes/certs:/certs:ro # shared certificates 28 | - ./_volumes/btcd-data-${NAME}:/home/simnet/.btcd # btcd data dir 29 | - ./_volumes/btcwallet-data-${NAME}:/home/simnet/.btcwallet # btcwallet data dir 30 | labels: 31 | - "simverse.role=bitcoin" 32 | - "simverse.flavor=btcd" 33 | - "simverse.service_counter=${SERVICE_COUNTER}" 34 | - "simverse.role_counter=${BITCOIN_COUNTER}" 35 | - "simverse.flavor_counter=${BTCD_COUNTER}" 36 | environment: 37 | - CONTAINER_NAME=${NAME} 38 | - REPORT_ENV=${SIMVERSE_REPORT_ENV} 39 | - SERVICE_READY_PORT=${SERVICE_READY_PORT} 40 | - CONTAINER_SERVICE_PORT=${CONTAINER_SERVICE_PORT} 41 | - SERVICE_COUNTER=${SERVICE_COUNTER} 42 | - BITCOIN_COUNTER=${BITCOIN_COUNTER} 43 | - BTCD_COUNTER=${BTCD_COUNTER} 44 | - DEBUG=${DEBUG} 45 | - RPC_USER=${RPC_USER} 46 | - RPC_PASS=${RPC_PASS} 47 | - FAUCET_ADDR=${FAUCET_ADDR} 48 | - FAUCET_ADDR_PRIVATE_KEY=${FAUCET_ADDR_PRIVATE_KEY} 49 | - BITCOIN_P2P_BIND=${BITCOIN_P2P_BIND} 50 | - BITCOIN_P2P_PORT=${BITCOIN_P2P_PORT} 51 | - BITCOIN_RPC_BIND=${BITCOIN_RPC_BIND} 52 | - BITCOIN_RPC_PORT=${BITCOIN_RPC_PORT} 53 | - BTCWALLET_RPC_BIND=${BTCWALLET_RPC_BIND} 54 | - BTCWALLET_RPC_PORT=${BTCWALLET_RPC_PORT} 55 | - BTCD_EXTRA_PARAMS=${BTCD_EXTRA_PARAMS} 56 | - BTCWALLET_EXTRA_PARAMS=${BTCWALLET_EXTRA_PARAMS} 57 | - BTCCTL_EXTRA_PARAMS=${BTCCTL_EXTRA_PARAMS} 58 | - BTCWALLET_USER=${BTCWALLET_USER} 59 | - BTCWALLET_PASS=${BTCWALLET_PASS} 60 | $SIMVERSE_EXTRA_SERVICE_CONFIG -------------------------------------------------------------------------------- /recipes/cookbook/scaffold/docker/_aux/runtime/lib/utils.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | echo_err() { 4 | printf "\e[31m%s\e[0m\n" "$*" >&2; 5 | } 6 | 7 | trim() { 8 | local str 9 | str=$(cat) 10 | if [[ "$str" =~ [^[:space:]](.*[^[:space:]])? ]]; then 11 | printf "%s" "$BASH_REMATCH" 12 | else 13 | echo -n "$str" 14 | fi 15 | } 16 | 17 | wait_for_socket() { 18 | local port=${1:?required} 19 | local host=${2:-localhost} 20 | local max=${3:-100} 21 | local delay=${4:-1} 22 | 23 | local counter=1 24 | while ! nc -z "$host" "$port" > /dev/null 2>&1; do 25 | sleep ${delay} 26 | ((++counter)) 27 | if [[ ${counter} -gt ${max} ]]; then 28 | echo_err "socket '$host:$port' didn't come online in time" 29 | return 1 30 | fi 31 | done 32 | } 33 | 34 | generate_cert() { 35 | local name=${1:-ssl} 36 | local cert_file="$name.cert" 37 | local key_file="$name.key" 38 | local csr_file="$name.csr" 39 | local cnf_file=openssl.cnf 40 | 41 | cat /etc/ssl/openssl.cnf > "$cnf_file" 42 | cat >> "$cnf_file" < /dev/null 2>&1; 95 | status=$? 96 | eval "${saved_opts}" 97 | if [[ "$status" -eq 0 ]]; then 98 | if [[ "$counter" -ne 1 ]]; then 99 | echo 100 | fi 101 | return 0 102 | fi 103 | sleep 1 104 | if [[ -n "$cmd2" ]]; then 105 | if ! (( "$counter" % "$interval" )); then 106 | echo 107 | saved_opts="set -$-" 108 | set +e 109 | eval "${cmd2}" 110 | eval "${saved_opts}" 111 | fi 112 | fi 113 | ((++counter)) 114 | if [[ ${counter} -gt ${max} ]]; then 115 | echo 116 | echo_err "wait_for stuck waiting for '$msg' (tried $max times)" 117 | return 1 118 | fi 119 | done 120 | } 121 | 122 | strip_ansi_colors() { 123 | # https://superuser.com/a/380778/8244 124 | sed 's/\x1b\[[0-9;]*m//g' 125 | } -------------------------------------------------------------------------------- /recipes/cookbook/templates/lightning.yml: -------------------------------------------------------------------------------- 1 | ${NAME}: 2 | <<: *shared 3 | image: ${SIMVERSE_DOCKER_IMAGE_PREFIX}${SIMNET_NAME}_lightning 4 | container_name: ${SIMVERSE_DOCKER_CONTAINER_PREFIX}${SIMNET_NAME}_${NAME} 5 | command: ["run"] 6 | build: 7 | context: . 8 | dockerfile: docker/lightning/Dockerfile 9 | args: 10 | - GCFLAGS=$GCFLAGS 11 | - SIMVERSE_HOST_UID=$SIMVERSE_HOST_UID 12 | - SIMVERSE_HOST_GID=$SIMVERSE_HOST_GID 13 | - LIGHTNING_DOCKER_BUILDTIME_IMAGE=$LIGHTNING_DOCKER_BUILDTIME_IMAGE 14 | - LIGHTNING_DOCKER_RUNTIME_IMAGE=$LIGHTNING_DOCKER_RUNTIME_IMAGE 15 | - LIGHTNING_REPO_PATH=$LIGHTNING_REPO_PATH 16 | - LIGHTNING_CONF_PATH=$LIGHTNING_CONF_PATH 17 | - RELEVANT_BITCOIND_IMAGE=${SIMVERSE_DOCKER_IMAGE_PREFIX}${SIMNET_NAME}_bitcoind 18 | - LIGHTNING_DEVELOPER_FLAG=$LIGHTNING_DEVELOPER_FLAG 19 | - LIGHTNING_VALGRIND_FLAG=$LIGHTNING_VALGRIND_FLAG 20 | - LIGHTNING_CONFIGURE_OPTS=$LIGHTNING_CONFIGURE_OPTS 21 | ports: 22 | - $SIMVERSE_HOST_BIND$(($SERVICE_READY_PORT_ON_HOST+$SERVICE_COUNTER)):$SERVICE_READY_PORT # readiness signal port 23 | - $SIMVERSE_HOST_BIND$LIGHTNING_SERVER_PORT_ON_HOST:${LIGHTNING_P2P_PORT} # lightning p2p port 24 | - $SIMVERSE_HOST_BIND$LIGHTNING_RPC_PORT_ON_HOST:${LIGHTNING_RPC_PORT} # lightning rpc port 25 | volumes: 26 | # !DANGER! when touching this, review cookbook.sh > prepare_lightning_volumes 27 | - ./_volumes/lightning-data-${NAME}:/home/simnet/.lightning # lightning data dir 28 | labels: 29 | - "simverse.role=ln" 30 | - "simverse.flavor=lightning" 31 | - "simverse.service_counter=${SERVICE_COUNTER}" 32 | - "simverse.role_counter=${LN_COUNTER}" 33 | - "simverse.flavor_counter=${LIGHTNING_COUNTER}" 34 | environment: 35 | - CONTAINER_NAME=${NAME} 36 | - REPORT_ENV=${SIMVERSE_REPORT_ENV} 37 | - SERVICE_READY_PORT=${SERVICE_READY_PORT} 38 | - CONTAINER_SERVICE_PORT=${CONTAINER_SERVICE_PORT} 39 | - SERVICE_COUNTER=${SERVICE_COUNTER} 40 | - EXPOSE_TCP=${LIGHTNING_EXPOSE_TCP} 41 | - LIGHTNINGD_RPC_PORT=${LIGHTNING_RPC_PORT} 42 | - LN_COUNTER=${LN_COUNTER} 43 | - LIGHTNING_COUNTER=${LIGHTNING_COUNTER} 44 | - DEBUG=${DEBUG} 45 | - RPC_USER=${RPC_USER} 46 | - RPC_PASS=${RPC_PASS} 47 | - LIGHTNING_ALIAS=${NAME} 48 | - LIGHTNINGD_EXTRA_PARAMS=${LIGHTNINGD_EXTRA_PARAMS} 49 | - LIGHTNING_CLI_EXTRA_PARAMS=${LIGHTNING_CLI_EXTRA_PARAMS} 50 | - LIGHTNING_CHAIN=${LIGHTNING_CHAIN} 51 | - LIGHTNING_BACKEND=${LIGHTNING_BACKEND} 52 | - LIGHTNING_P2P_BIND=${LIGHTNING_P2P_BIND} 53 | - LIGHTNING_P2P_PORT=${LIGHTNING_P2P_PORT} 54 | - LIGHTNING_RPC_BIND=${LIGHTNING_RPC_BIND} 55 | - LIGHTNING_RPC_PORT=${LIGHTNING_RPC_PORT} 56 | - LIGHTNING_BITCOIN_RPC_HOST=${LIGHTNING_BITCOIN_RPC_HOST} 57 | - BITCOIN_RPC_PORT=${BITCOIN_RPC_PORT} 58 | - FAUCET_ADDR=${FAUCET_ADDR} 59 | - FAUCET_ADDR_PRIVATE_KEY=${FAUCET_ADDR_PRIVATE_KEY} 60 | - ZMQ_PUBRAWBLOCK_PORT=${ZMQ_PUBRAWBLOCK_PORT} 61 | - ZMQ_PUBRAWTX_PORT=${ZMQ_PUBRAWTX_PORT} 62 | $SIMVERSE_EXTRA_SERVICE_CONFIG 63 | -------------------------------------------------------------------------------- /.idea/dictionaries/darwin.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | "force" 5 | addnode 6 | alphanum 7 | apfs 8 | appdata 9 | backends 10 | binaryage 11 | bitcoin 12 | bitcoincli 13 | bitcoind 14 | blockchain 15 | blockheight 16 | btcctl 17 | btcd 18 | btcddatadir 19 | btcdlisten 20 | btcdlogdir 21 | btcdminingaddr 22 | btcdpassword 23 | btcdusername 24 | btcsuite 25 | btcwallet 26 | btcwalletd 27 | buildtime 28 | cafile 29 | clonefile 30 | coinbase 31 | configfile 32 | createtemp 33 | datadir 34 | debuggo 35 | debuglevel 36 | declair 37 | dedolarize 38 | direnv 39 | dnsseed 40 | dockerfiles 41 | dolarize 42 | droptxindex 43 | envrc 44 | externalip 45 | fromjson 46 | gcflags 47 | gencerts 48 | genreadme 49 | getbalance 50 | getinfo 51 | grpc 52 | launchd 53 | lightningd 54 | lightningnetwork 55 | litecoin 56 | lncli 57 | lnd 58 | lndlisten 59 | logdir 60 | ltcd 61 | macos 62 | mainnet 63 | maxdepth 64 | miningaddr 65 | mktemp 66 | msat 67 | mysn 68 | newaddr 69 | noansi 70 | noclienttls 71 | noout 72 | noseedbackup 73 | noservertls 74 | notls 75 | onchain 76 | pipefail 77 | plists 78 | popd 79 | printtoconsole 80 | pubkey 81 | pubrawblock 82 | pubrawtx 83 | pushd 84 | regtest 85 | reposdir 86 | restlisten 87 | roadmap 88 | rpcallowip 89 | rpcbind 90 | rpccert 91 | rpccertdir 92 | rpcconnect 93 | rpchost 94 | rpckey 95 | rpclisten 96 | rpcpass 97 | rpcpassword 98 | rpcport 99 | rpcserver 100 | rpcuser 101 | sats 102 | segwit 103 | sendfrom 104 | simnet 105 | simnets 106 | simverse 107 | subcommand 108 | testnet 109 | tlsextraip 110 | tmux 111 | tmuxinator 112 | txindex 113 | unshallow 114 | upnp 115 | vbparams 116 | workdir 117 | zmqblock 118 | zmqpubrawblock 119 | zmqpubrawtx 120 | zmqtx 121 | 122 | 123 | -------------------------------------------------------------------------------- /recipes/cookbook/scaffold/docker/lightning/Dockerfile: -------------------------------------------------------------------------------- 1 | # see https://medium.com/@tonistiigi/advanced-multi-stage-build-patterns-6f741b852fae 2 | ARG LIGHTNING_DOCKER_BUILDTIME_IMAGE 3 | ARG LIGHTNING_DOCKER_RUNTIME_IMAGE 4 | ARG RELEVANT_BITCOIND_IMAGE 5 | 6 | # modelled after https://github.com/ElementsProject/lightning/blob/master/Dockerfile 7 | FROM ${LIGHTNING_DOCKER_BUILDTIME_IMAGE} as simverse_buildtime_lightning 8 | 9 | #include BASE_DOCKERFILE_SNIPPET 10 | #include BUILDTIME_DOCKERFILE_SNIPPET 11 | 12 | RUN apk add --no-cache --update \ 13 | ca-certificates \ 14 | autoconf \ 15 | automake \ 16 | build-base \ 17 | libressl \ 18 | libtool \ 19 | gmp-dev \ 20 | python \ 21 | python-dev \ 22 | python3 \ 23 | py3-mako \ 24 | sqlite-dev \ 25 | wget \ 26 | git \ 27 | file \ 28 | gnupg \ 29 | swig \ 30 | zlib-dev \ 31 | gettext 32 | 33 | ARG LIGHTNING_REPO_PATH 34 | 35 | WORKDIR /root/build 36 | 37 | COPY "$LIGHTNING_REPO_PATH" . 38 | 39 | # lower optimizations for faster builds 40 | #ARG CFLAGS="" 41 | #ARG CXXFLAGS="$CFLAGS" 42 | ARG MAKEFLAGS="-j4" 43 | 44 | #ENV CFLAGS="$CFLAGS" 45 | #ENV CXXFLAGS="$CXXFLAGS" 46 | ENV MAKEFLAGS="$MAKEFLAGS" 47 | 48 | COPY "docker/lightning/patches/unknown-version-fallback.patch" . 49 | RUN git apply unknown-version-fallback.patch 50 | 51 | COPY "docker/lightning/patches/disable-shadow-routing.patch" . 52 | RUN git apply disable-shadow-routing.patch 53 | 54 | COPY "docker/lightning/patches/docker-entrypoint.patch" . 55 | RUN git apply docker-entrypoint.patch 56 | 57 | ARG LIGHTNING_DEVELOPER_FLAG=0 58 | ARG LIGHTNING_VALGRIND_FLAG=0 59 | ARG LIGHTNING_CONFIGURE_OPTS="" 60 | RUN ./configure --prefix=/tmp/lightning_install ${LIGHTNING_CONFIGURE_OPTS} 61 | 62 | RUN make DEVELOPER=${LIGHTNING_DEVELOPER_FLAG} VALGRIND=${LIGHTNING_VALGRIND_FLAG} 63 | 64 | RUN make install 65 | 66 | # --------------------------------------------------------------------------------------------------------------------------- 67 | 68 | FROM ${RELEVANT_BITCOIND_IMAGE} as simverse_runtime_bitcoind 69 | 70 | # --------------------------------------------------------------------------------------------------------------------------- 71 | 72 | FROM ${LIGHTNING_DOCKER_RUNTIME_IMAGE} as simverse_runtime_lightning 73 | 74 | #include BASE_DOCKERFILE_SNIPPET 75 | #include RUNTIME_DOCKERFILE_SNIPPET 76 | 77 | RUN apk add --no-cache --update \ 78 | gmp-dev \ 79 | sqlite-dev \ 80 | inotify-tools \ 81 | socat \ 82 | bash \ 83 | zlib-dev \ 84 | tini 85 | 86 | ARG LIGHTNING_CONF_PATH 87 | 88 | # copy the binaries and entrypoint from the builder image. 89 | COPY --from=simverse_buildtime_lightning /tmp/lightning_install/ /usr/local/ 90 | 91 | # copy some binaries from the bitcoind image 92 | COPY --from=simverse_runtime_bitcoind /usr/local/bin/bitcoin-cli /usr/local/bin/ 93 | # we also need to copy some relevant libraries over 94 | COPY --from=simverse_runtime_bitcoind /usr/lib/libboost* /usr/lib/ 95 | 96 | USER simnet 97 | 98 | WORKDIR /home/simnet 99 | 100 | ENV LIGHTNINGD_DATA=/home/simnet/.lightning 101 | ENV LIGHTNINGD_NETWORK=regtest 102 | # we need to place lightning-rpc outside volumes because of socket path limits (in docker) 103 | # see https://github.com/moby/moby/issues/23545 104 | ENV LIGHTNINGD_RPC_DIR_SIMVERSE=/tmp/lightningd-rpc 105 | RUN mkdir -p "$LIGHTNINGD_RPC_DIR_SIMVERSE" 106 | 107 | COPY --chown=simnet "docker/lightning/home" "." 108 | COPY --chown=simnet --from=simverse_buildtime_lightning /root/build/tools/docker-entrypoint.sh lightning-docker-entrypoint.sh 109 | COPY --chown=simnet "$LIGHTNING_CONF_PATH" "seed-config" 110 | -------------------------------------------------------------------------------- /recipes/cookbook/scaffold/docker/eclair/Dockerfile: -------------------------------------------------------------------------------- 1 | # this file is modelled after https://github.com/ACINQ/eclair/blob/master/Dockerfile 2 | 3 | ARG ECLAIR_DOCKER_BUILDTIME_IMAGE 4 | ARG ECLAIR_DOCKER_RUNTIME_IMAGE 5 | 6 | FROM ${ECLAIR_DOCKER_BUILDTIME_IMAGE} as simverse_buildtime_eclair 7 | 8 | #include BASE_DOCKERFILE_SNIPPET 9 | #include BUILDTIME_DOCKERFILE_SNIPPET 10 | 11 | ARG ECLAIR_REPO_PATH 12 | 13 | # Setup maven, we don't use https://hub.docker.com/_/maven/ as it declare .m2 as volume, we loose all mvn cache 14 | # We can alternatively do as proposed by https://github.com/carlossg/docker-maven#packaging-a-local-repository-with-the-image 15 | # this was meant to make the image smaller, but we use multi-stage build so we don't care 16 | 17 | RUN apk add --no-cache curl tar bash 18 | 19 | ARG MAVEN_VERSION=3.6.3 20 | ARG USER_HOME_DIR="/root" 21 | ARG SHA=c35a1803a6e70a126e80b2b3ae33eed961f83ed74d18fcd16909b2d44d7dada3203f1ffe726c17ef8dcca2dcaa9fca676987befeadc9b9f759967a8cb77181c0 22 | ARG BASE_URL=https://apache.osuosl.org/maven/maven-3/${MAVEN_VERSION}/binaries 23 | 24 | RUN mkdir -p /usr/share/maven /usr/share/maven/ref \ 25 | && curl -fsSL -o /tmp/apache-maven.tar.gz ${BASE_URL}/apache-maven-${MAVEN_VERSION}-bin.tar.gz \ 26 | && echo "${SHA} /tmp/apache-maven.tar.gz" | sha512sum -c - \ 27 | && tar -xzf /tmp/apache-maven.tar.gz -C /usr/share/maven --strip-components=1 \ 28 | && rm -f /tmp/apache-maven.tar.gz \ 29 | && ln -s /usr/share/maven/bin/mvn /usr/bin/mvn 30 | 31 | ENV MAVEN_HOME /usr/share/maven 32 | ENV MAVEN_CONFIG "$USER_HOME_DIR/.m2" 33 | 34 | # Let's fetch eclair dependencies, so that Docker can cache them 35 | # This way we won't have to fetch dependencies again if only the source code changes 36 | # The easiest way to reliably get dependencies is to build the project with no sources 37 | WORKDIR /root/build 38 | COPY "$ECLAIR_REPO_PATH/pom.xml" pom.xml 39 | COPY "$ECLAIR_REPO_PATH/eclair-core/pom.xml" eclair-core/pom.xml 40 | COPY "$ECLAIR_REPO_PATH/eclair-front/pom.xml" eclair-front/pom.xml 41 | COPY "$ECLAIR_REPO_PATH/eclair-node/pom.xml" eclair-node/pom.xml 42 | COPY "$ECLAIR_REPO_PATH/eclair-node-gui/pom.xml" eclair-node-gui/pom.xml 43 | COPY "$ECLAIR_REPO_PATH/eclair-node/modules/assembly.xml" eclair-node/modules/assembly.xml 44 | COPY "$ECLAIR_REPO_PATH/eclair-node-gui/modules/assembly.xml" eclair-node-gui/modules/assembly.xml 45 | RUN mkdir -p eclair-core/src/main/scala && touch eclair-core/src/main/scala/empty.scala 46 | # Blank build. We only care about eclair-node, and we use install because eclair-node depends on eclair-core 47 | RUN mvn install -pl eclair-node -am 48 | RUN mvn clean 49 | 50 | # Only then do we copy the sources 51 | COPY "$ECLAIR_REPO_PATH" . 52 | 53 | # And this time we can build in offline mode, specifying 'notag' instead of git commit 54 | RUN mvn package -pl eclair-node -am -DskipTests -Dgit.commit.id=notag -Dgit.commit.id.abbrev=notag -o 55 | # It might be good idea to run the tests here, so that the docker build fail if the code is bugged 56 | 57 | # --------------------------------------------------------------------------------------------------------------------------- 58 | 59 | FROM ${ECLAIR_DOCKER_RUNTIME_IMAGE} as simverse_runtime_eclair 60 | 61 | #include BASE_DOCKERFILE_SNIPPET 62 | #include RUNTIME_DOCKERFILE_SNIPPET 63 | 64 | RUN apk add --no-cache --update \ 65 | unzip \ 66 | gmp-dev \ 67 | openjdk11-jre 68 | 69 | ARG ECLAIR_CONF_PATH 70 | 71 | # copy build artefacts... 72 | COPY --from=simverse_buildtime_eclair /root/build/eclair-node/target/eclair-node-*.zip ./eclair-node.zip 73 | RUN unzip eclair-node.zip && mv eclair-node-* eclair-node 74 | COPY --from=simverse_buildtime_eclair /root/build/eclair-core/eclair-cli . 75 | RUN chmod +x eclair-cli 76 | 77 | USER simnet 78 | 79 | WORKDIR /home/simnet 80 | 81 | COPY --chown=simnet "docker/eclair/home" "." 82 | COPY --chown=simnet "$ECLAIR_CONF_PATH" "seed-eclair.conf" 83 | 84 | RUN mkdir .eclair 85 | -------------------------------------------------------------------------------- /tests/_lib/helpers.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | pushd "$(dirname "${BASH_SOURCE[0]}")" > /dev/null || exit 1 4 | source github.sh 5 | source travis.sh 6 | popd > /dev/null || exit 1 7 | 8 | log_section() { 9 | if [[ -n "$TRAVIS" ]]; then 10 | travis_section "$@" 11 | fi 12 | 13 | if [[ -n "$GITHUB_WORKFLOW" ]]; then 14 | github_section "$@" 15 | fi 16 | } 17 | 18 | echo_err() { 19 | printf "\e[31m%s\e[0m\n" "$*" >&2; 20 | } 21 | 22 | unquote() { 23 | tr -d '"' 24 | } 25 | 26 | CHECK_COUNTER=1 27 | 28 | check() { 29 | local command=${1:?required} 30 | local silent=${2} 31 | local status 32 | 33 | if [[ -z "$silent" ]]; then 34 | log_section start "test.$CHECK_COUNTER" 35 | printf "\$ \e[33m%s\e[0m\n" "$command" 36 | fi 37 | local saved_opts="set -$-" 38 | set +e 39 | # partially evaluate our command arguments 40 | eval set -- ${command} 41 | status1=$? 42 | evaluated_arguments="$@" # this is for potential error message below 43 | if [[ "$status1" -eq 0 ]]; then 44 | # evaluate actual command with pre-evaluated arguments 45 | "$@" 46 | status2=$? 47 | fi 48 | eval "${saved_opts}" 49 | if [[ -z "$silent" ]]; then 50 | log_section end "test.$CHECK_COUNTER" 51 | ((++CHECK_COUNTER)) 52 | fi 53 | 54 | # print evaluated args on failure 55 | if [[ "$status1" -ne 0 ]]; then 56 | if [[ -z "$silent" ]]; then 57 | printf "!! \e[31m%s\e[0m\n" "$evaluated_arguments" 58 | fi 59 | return ${status1} 60 | fi 61 | if [[ "$status2" -ne 0 ]]; then 62 | if [[ -z "$silent" ]]; then 63 | printf "! \e[31m%s\e[0m\n" "$evaluated_arguments" 64 | fi 65 | return ${status2} 66 | fi 67 | } 68 | 69 | check_retry() { 70 | local command=${1:?required} 71 | local max=${2:-60} 72 | local interval=${3:-1} 73 | 74 | log_section start "test.$CHECK_COUNTER" 75 | printf "\$ \e[33m%s\e[0m\n" "$command" 76 | 77 | local counter=1 78 | local status 79 | local saved_opts 80 | while true; do 81 | saved_opts="set -$-" 82 | set +e 83 | check "$command" 1 # > /dev/null 2>&1; 84 | status=$? 85 | eval "${saved_opts}" 86 | if [[ "$status" -eq 0 ]]; then 87 | if [[ "$counter" -ne 1 ]]; then 88 | echo 89 | fi 90 | 91 | log_section end "test.$CHECK_COUNTER" 92 | ((++CHECK_COUNTER)) 93 | 94 | return 0 95 | fi 96 | if [[ "$counter" -eq 1 ]]; then 97 | echo -n "Waiting for satisfaction of condition '$command'. Zzz.." 98 | fi 99 | sleep ${interval} 100 | echo -n "." 101 | ((++counter)) 102 | if [[ ${counter} -gt ${max} ]]; then 103 | echo 104 | echo_err "FATAL: check_retry didn't satisfy '$command' (tried $max times with interval of $interval sec)" 105 | log_section end "test.$CHECK_COUNTER" 106 | ((++CHECK_COUNTER)) 107 | exit 1 108 | fi 109 | done 110 | 111 | } 112 | 113 | announce1() { 114 | printf "\e[35m%s\e[0m" "$1" 115 | } 116 | 117 | announce() { 118 | announce1 "$@" 119 | echo 120 | } 121 | 122 | # this is a replacement for ./sv enter ${SIMNET_NAME} 123 | enter_simnet() { 124 | local SIMNET_NAME=$1 125 | 126 | SIMVERSE_HOME=${SIMVERSE_HOME:?required} 127 | SIMVERSE_WORKSPACE=${SIMVERSE_WORKSPACE:?required} 128 | 129 | . "$SIMVERSE_HOME/_defaults.sh" 130 | 131 | cd "$SIMVERSE_WORKSPACE" 132 | cd "$SIMNET_NAME" 133 | SIMNET_DIR=$(pwd -P) 134 | export PATH=$PATH:"$SIMNET_DIR/toolbox":"$SIMNET_DIR/aliases" 135 | } 136 | 137 | wait_for_bitcoin_ready() { 138 | local num_blocks=432 139 | announce1 "waiting for master bitcoin node to mine $num_blocks blocks " 140 | local saved_opts="set -$-" 141 | set +e 142 | local probe_counter=1 143 | local delay=1 144 | local max_probes=$(expr 3*60) # approx 3min 145 | while ! [[ $(chain_height) -ge ${num_blocks} ]] > /dev/null 2>&1; do 146 | # echo "$PROBE_COUNTER $(btcctl getinfo | jq '.blocks')" 147 | sleep ${delay} 148 | echo -n "." 149 | ((++probe_counter)) 150 | if [[ ${probe_counter} -gt ${max_probes} ]]; then 151 | echo 152 | echo_err "master bitcoin node didn't reach expected $num_blocks blocks in time" 153 | eval "${saved_opts}" 154 | return 1 155 | fi 156 | done 157 | eval "${saved_opts}" 158 | echo 159 | } 160 | -------------------------------------------------------------------------------- /toolbox/_toolbox_lib.sh: -------------------------------------------------------------------------------- 1 | # shellcheck shell=bash 2 | 3 | # this is a shell library, it should be sourced by scripts in toolbox 4 | 5 | set -e -o pipefail 6 | 7 | export REAL_TOOLBOX_DIR 8 | REAL_TOOLBOX_DIR="$(realpath "$(dirname "${BASH_SOURCE[0]}")")" 9 | 10 | pushd "$REAL_TOOLBOX_DIR" > /dev/null 11 | source _toolbox_config.sh 12 | popd > /dev/null 13 | 14 | echo_err() { 15 | printf "\e[31m%s\e[0m\n" "$*" >&2; 16 | } 17 | 18 | # https://gist.github.com/ahendrix/7030300 19 | report_error() { 20 | local err=$? 21 | set +o xtrace 22 | local code="${1:-1}" 23 | echo_err "Error in ${BASH_SOURCE[1]}:${BASH_LINENO[0]}. '${BASH_COMMAND}' exited with status $err" 24 | # Print out the stack trace described by $function_stack 25 | if [[ ${#FUNCNAME[@]} -gt 2 ]] 26 | then 27 | echo_err "Call tree:" 28 | for ((i=1;i<${#FUNCNAME[@]}-1;i++)) 29 | do 30 | echo_err " $i: ${BASH_SOURCE[$i+1]}:${BASH_LINENO[$i]} ${FUNCNAME[$i]}(...)" 31 | done 32 | fi 33 | echo_err "Exiting with status ${code}" 34 | exit "${code}" 35 | } 36 | 37 | trap report_error ERR 38 | 39 | realpath() { 40 | [[ $1 = /* ]] && echo "$1" || echo "$PWD/${1#./}" 41 | } 42 | 43 | BC_ARGS=(-l "$REAL_TOOLBOX_DIR/_toolbox.bc") 44 | 45 | trim() { 46 | local str 47 | str=$(cat) 48 | if [[ "$str" =~ [^[:space:]](.*[^[:space:]])? ]]; then 49 | printf "%s" "${BASH_REMATCH[0]}" 50 | else 51 | echo -n "$str" 52 | fi 53 | } 54 | 55 | sat2btc() { 56 | local number=${1} 57 | if [[ -z "$number" ]]; then 58 | read -r number 59 | fi 60 | echo "${number} / 100000000" | bc "${BC_ARGS[@]}" | xargs printf "%.*f\n" 8 61 | } 62 | 63 | btc2sat() { 64 | local number=${1} 65 | if [[ -z "$number" ]]; then 66 | read -r number 67 | fi 68 | echo "${number} * 100000000" | bc "${BC_ARGS[@]}" | xargs printf "%.*f\n" 0 69 | } 70 | 71 | btc2msat() { 72 | local number=${1} 73 | if [[ -z "$number" ]]; then 74 | read -r number 75 | fi 76 | echo "${number} * 100000000000" | bc "${BC_ARGS[@]}" | xargs printf "%.*f\n" 0 77 | } 78 | 79 | msat2btc() { 80 | local number=${1} 81 | if [[ -z "$number" ]]; then 82 | read -r number 83 | fi 84 | echo "${number} / 100000000000" | bc "${BC_ARGS[@]}" | xargs printf "%.*f\n" 8 85 | } 86 | 87 | unquote() { 88 | tr -d '"' 89 | } 90 | 91 | is() { 92 | test "$(echo "$1" | bc "${BC_ARGS[@]}")" -eq 1 93 | } 94 | 95 | compute() { 96 | echo "$1" | bc "${BC_ARGS[@]}" 97 | } 98 | 99 | uppercase() { 100 | tr '[:lower:]' '[:upper:]' 101 | } 102 | 103 | ln_connect_string() { 104 | local person=${1:-alice} 105 | local pubkey 106 | if ! pubkey=$(pubkey "$person"); then 107 | return 1 108 | fi 109 | echo "$pubkey@$person" 110 | } 111 | 112 | # checks whether btcd is our master bitcoin node 113 | # we branch some code based on this info 114 | is_btcd_master() { 115 | local container 116 | container=$(lookup_container 1 role bitcoin) 117 | if [[ -z "$container" ]]; then 118 | echo_err "unable to lookup first container with role bitcoin" 119 | exit 1 120 | fi 121 | 122 | local flavor 123 | flavor=$(inspect_container "${container}" flavor) 124 | if [[ -z "$flavor" ]]; then 125 | echo_err "unable to determine flavor of service in container '$container'" 126 | exit 1 127 | fi 128 | 129 | test "$flavor" == "btcd" 130 | } 131 | 132 | get_flavor() { 133 | local person=${1:?required} 134 | local container 135 | container=$(docker-compose ps -q "$person") 136 | if [[ -z "$container" ]]; then 137 | echo_err "unable to lookup container for for '$person'" 138 | exit 1 139 | fi 140 | 141 | local flavor 142 | flavor=$(inspect_container "${container}" flavor) 143 | if [[ -z "$flavor" ]]; then 144 | echo_err "unable to determine flavor of service for '$person'" 145 | exit 1 146 | fi 147 | 148 | echo -n "$flavor" 149 | } 150 | 151 | get_role() { 152 | local person=${1:?required} 153 | local container 154 | container=$(docker-compose ps -q "$person") 155 | if [[ -z "$container" ]]; then 156 | echo_err "unable to lookup container for for '$person'" 157 | exit 1 158 | fi 159 | 160 | local role 161 | role=$(inspect_container "${container}" role) 162 | if [[ -z "$role" ]]; then 163 | echo_err "unable to determine role of service for '$person'" 164 | exit 1 165 | fi 166 | 167 | echo -n "$role" 168 | } 169 | 170 | wait_for() { 171 | local msg=${1:?required} 172 | local cmd=${2:?required} 173 | local cmd2=${3} 174 | local max=${4:-100} 175 | local cmd2_interval=${5:-5} 176 | local interval=${6:-1} 177 | 178 | local counter=1 179 | local status 180 | local saved_opts 181 | while true; do 182 | saved_opts="set -$-" 183 | set +e 184 | eval "${cmd}" > /dev/null 2>&1; 185 | status=$? 186 | eval "${saved_opts}" 187 | if [[ "$status" -eq 0 ]]; then 188 | if [[ "$counter" -ne 1 ]]; then 189 | echo 190 | fi 191 | return 0 192 | fi 193 | if [[ "$counter" -eq 1 ]]; then 194 | echo -n "Waiting for $msg. Zzz.." 195 | fi 196 | sleep "${interval}" 197 | echo -n "." 198 | if [[ -n "$cmd2" ]]; then 199 | if ! (( "$counter" % "$cmd2_interval" )); then 200 | echo 201 | saved_opts="set -$-" 202 | set +e 203 | eval "${cmd2}" 204 | eval "${saved_opts}" 205 | echo -n "Waiting for $msg. Zzz.." 206 | fi 207 | fi 208 | ((++counter)) 209 | if [[ ${counter} -gt ${max} ]]; then 210 | echo 211 | echo_err "FATAL: wait_for stuck waiting for '$msg' (tried $max times with interval of $interval sec)" 212 | exit 1 213 | fi 214 | done 215 | } 216 | 217 | wait_for_onchain_balance() { 218 | local person=${1:?required} 219 | local expected_amount=${2:?required} 220 | 221 | local cmd="is \"\$(onchain_balance \"$person\") >= $expected_amount\"" 222 | wait_for "$person to receive onchain balance of $expected_amount BTC" "$cmd" 223 | } 224 | 225 | wait_for_route() { 226 | local from_person=${1:?required} 227 | local to_person=${2:?required} 228 | local amt_btc=${3} 229 | 230 | local cmd="get_route \"$from_person\" \"$to_person\" ${amt_btc}" 231 | local cmd2="generate 1" 232 | wait_for "route between $from_person and $to_person" "$cmd" "$cmd2" 233 | } 234 | 235 | wait_sync_one() { 236 | local person=${1:?required} 237 | 238 | local cmd="\"$person\" getinfo" 239 | wait_for "$person to become available" "$cmd" 240 | 241 | local flavor 242 | flavor=$(get_flavor "$person") 243 | local cmd 244 | case "$flavor" in 245 | lnd) 246 | cmd="[[ \$(\"$person\" getinfo | jq \".synced_to_chain\") == \"true\" ]]" 247 | wait_for "$person to sync" "$cmd" 248 | ;; 249 | lightning) 250 | cmd="[[ \$(chain_height) == \$(\"$person\" getinfo | jq .blockheight) ]]" 251 | wait_for "$person to sync" "$cmd" 252 | ;; 253 | *) 254 | echo_err "unsupported flavor type '$flavor' for '$person'" 255 | return 1 256 | ;; 257 | esac 258 | } 259 | 260 | wait_sync() { 261 | for person in "$@"; do 262 | wait_sync_one "$person" 263 | done 264 | } 265 | 266 | wait_simnet_ready() { 267 | wait_for "simnet to get ready" "simnet_ready" 268 | } 269 | 270 | wait_is() { 271 | local condition=${1:?required} 272 | wait_for "condition '${condition}' to be met" "is \"$condition\"" 273 | } -------------------------------------------------------------------------------- /_defaults.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | # simverse workspace can be located outside this repo checkout 4 | export SIMVERSE_WORKSPACE=${SIMVERSE_WORKSPACE:-_workspace} 5 | 6 | # simverse repos can be located outside this repo checkout 7 | export SIMVERSE_REPOS=${SIMVERSE_REPOS:-_repos} 8 | 9 | export SIMVERSE_SHELL=${SIMVERSE_SHELL:-$SHELL} 10 | export SIMVERSE_VERBOSE=${SIMVERSE_VERBOSE} 11 | export SIMVERSE_VERBOSE_ALIASES=${SIMVERSE_VERBOSE_ALIASES} 12 | export SIMVERSE_DONT_BEAUTIFY_ALIASES=${SIMVERSE_DONT_BEAUTIFY_ALIASES} 13 | export SIMVERSE_DONT_CHECK_PREREQS=${SIMVERSE_DONT_CHECK_PREREQS} 14 | 15 | ############################################################################################################################# 16 | # simnet create-time defaults, effective during ./sv create (or other ./sv commands) 17 | 18 | export SIMVERSE_DOCKER_IMAGE_PREFIX=${SIMVERSE_DOCKER_IMAGE_PREFIX:-sv_} 19 | export SIMVERSE_DOCKER_NETWORK_PREFIX=${SIMVERSE_DOCKER_NETWORK_PREFIX:-$SIMVERSE_DOCKER_IMAGE_PREFIX} 20 | export SIMVERSE_DOCKER_CONTAINER_PREFIX=${SIMVERSE_DOCKER_CONTAINER_PREFIX} 21 | export SIMVERSE_HOST_UID=${SIMVERSE_HOST_UID:-$(id -u)} 22 | export SIMVERSE_HOST_GID=${SIMVERSE_HOST_GID:-$(id -g)} 23 | 24 | export DEFAULT_SIMNET_NAME=${DEFAULT_SIMNET_NAME:-default} 25 | export DEFAULT_RECIPE_NAME=${DEFAULT_RECIPE_NAME:-default} 26 | export DEFAULT_STATE_NAME=${DEFAULT_STATE_NAME:-master} 27 | 28 | export SIMVERSE_BTCD_REPO_URL=${SIMVERSE_BTCD_REPO_URL:-https://github.com/btcsuite/btcd.git} 29 | export SIMVERSE_BTCWALLET_REPO_URL=${SIMVERSE_BTCWALLET_REPO_URL:-https://github.com/btcsuite/btcwallet.git} 30 | export SIMVERSE_LND_REPO_URL=${SIMVERSE_LND_REPO_URL:-https://github.com/lightningnetwork/lnd.git} 31 | export SIMVERSE_BITCOIND_REPO_URL=${SIMVERSE_BITCOIND_REPO_URL:-https://github.com/bitcoin/bitcoin.git} 32 | export SIMVERSE_LIGHTNING_REPO_URL=${SIMVERSE_LIGHTNING_REPO_URL:-https://github.com/ElementsProject/lightning.git} 33 | export SIMVERSE_ECLAIR_REPO_URL=${SIMVERSE_ECLAIR_REPO_URL:-https://github.com/ACINQ/eclair.git} 34 | 35 | export SIMVERSE_GIT_CLONE_OPTS=${SIMVERSE_GIT_CLONE_OPTS:-"--depth=1 --recursive"} 36 | export SIMVERSE_GIT_REFERENCE_PREFIX=${SIMVERSE_GIT_REFERENCE_PREFIX} # used in tests 37 | export SIMVERSE_GIT_FETCH_OPTS=${SIMVERSE_GIT_FETCH_OPTS:-"--ff-only"} 38 | export SIMVERSE_GIT_PULL_OPTS=${SIMVERSE_GIT_PULL_OPTS:-"--ff-only"} 39 | 40 | export FIRST_DLV_PORT_ON_HOST=${FIRST_DLV_PORT_ON_HOST:-41000} 41 | export FIRST_DLV_PORT=${FIRST_DLV_PORT:-41000} 42 | 43 | export SERVICE_READY_PORT=${SERVICE_READY_PORT:-31337} 44 | export SERVICE_READY_PORT_ON_HOST=${SERVICE_READY_PORT_ON_HOST:-$SERVICE_READY_PORT} 45 | 46 | export CONTAINER_SERVICE_PORT=${CONTAINER_SERVICE_PORT:-32337} 47 | 48 | export FIRST_LND_SERVER_PORT_ON_HOST=${FIRST_LND_SERVER_PORT_ON_HOST:-10000} 49 | export FIRST_LND_RPC_PORT_ON_HOST=${FIRST_LND_RPC_PORT_ON_HOST:-10300} 50 | export FIRST_LND_REST_PORT_ON_HOST=${FIRST_LND_REST_PORT_ON_HOST:-10600} 51 | export FIRST_BTCWALLET_RPC_PORT_ON_HOST=${FIRST_BTCWALLET_RPC_PORT_ON_HOST:-12000} 52 | export FIRST_BTCD_SERVER_PORT_ON_HOST=${FIRST_BTCD_SERVER_PORT_ON_HOST:-12300} 53 | export FIRST_BTCD_RPC_PORT_ON_HOST=${FIRST_BTCD_RPC_PORT_ON_HOST:-12600} 54 | export FIRST_BITCOIND_SERVER_PORT_ON_HOST=${FIRST_BITCOIND_SERVER_PORT_ON_HOST:-13000} 55 | export FIRST_BITCOIND_RPC_PORT_ON_HOST=${FIRST_BITCOIND_RPC_PORT_ON_HOST:-13300} 56 | export FIRST_LIGHTNING_SERVER_PORT_ON_HOST=${FIRST_LIGHTNING_SERVER_PORT_ON_HOST:-14000} 57 | export FIRST_LIGHTNING_RPC_PORT_ON_HOST=${FIRST_LIGHTNING_RPC_PORT_ON_HOST:-14300} 58 | export FIRST_LIGHTNING_REST_PORT_ON_HOST=${FIRST_LIGHTNING_REST_PORT_ON_HOST:-14600} 59 | export FIRST_ECLAIR_SERVER_PORT_ON_HOST=${FIRST_ECLAIR_SERVER_PORT_ON_HOST:-15000} 60 | export FIRST_ECLAIR_RPC_PORT_ON_HOST=${FIRST_ECLAIR_RPC_PORT_ON_HOST:-15300} 61 | 62 | export LND_AUTO_NAME_PREFIX=${LND_AUTO_NAME_PREFIX:-lnd} 63 | export BTCD_AUTO_NAME_PREFIX=${BTCD_AUTO_NAME_PREFIX:-btcd} 64 | export BITCOIND_AUTO_NAME_PREFIX=${BITCOIND_AUTO_NAME_PREFIX:-bitcoind} 65 | export LIGHTNING_AUTO_NAME_PREFIX=${LIGHTNING_AUTO_NAME_PREFIX:-lightning} 66 | export ECLAIR_AUTO_NAME_PREFIX=${ECLAIR_AUTO_NAME_PREFIX:-eclair} 67 | 68 | # --------------------------------------------------------------------------------------------------------------------------- 69 | # you can tweak these on per-node basis in your recipes 70 | 71 | # here we define base docker images for individual containers, they should be based on alpine 72 | export DEFAULT_DOCKER_IMAGE=${DEFAULT_DOCKER_IMAGE:-alpine:3.10} 73 | export DEFAULT_DOCKER_BUILDTIME_GO_IMAGE=${DEFAULT_DOCKER_BUILDTIME_GO_IMAGE:-golang:1.13-alpine3.10} 74 | export DEFAULT_DOCKER_BUILDTIME_JAVA_IMAGE=${DEFAULT_DOCKER_BUILDTIME_JAVA_IMAGE:-adoptopenjdk/openjdk11:jdk-11.0.3_7-alpine} # see https://github.com/ACINQ/eclair/blob/master/Dockerfile#L1 75 | export DEFAULT_DOCKER_BUILDTIME_IMAGE=${DEFAULT_DOCKER_BUILDTIME_IMAGE:-$DEFAULT_DOCKER_IMAGE} 76 | export DEFAULT_DOCKER_RUNTIME_IMAGE=${DEFAULT_DOCKER_RUNTIME_IMAGE:-$DEFAULT_DOCKER_IMAGE} 77 | export BITCOIND_DOCKER_BUILDTIME_IMAGE=${BITCOIND_DOCKER_BUILDTIME_IMAGE:-$DEFAULT_DOCKER_BUILDTIME_IMAGE} 78 | export BITCOIND_DOCKER_RUNTIME_IMAGE=${BITCOIND_DOCKER_BUILDTIME_IMAGE:-$DEFAULT_DOCKER_RUNTIME_IMAGE} 79 | export BTCD_DOCKER_BUILDTIME_IMAGE=${BTCD_DOCKER_BUILDTIME_IMAGE:-$DEFAULT_DOCKER_BUILDTIME_GO_IMAGE} 80 | export BTCD_DOCKER_RUNTIME_IMAGE=${BTCD_DOCKER_BUILDTIME_IMAGE:-$DEFAULT_DOCKER_RUNTIME_IMAGE} 81 | export ECLAIR_DOCKER_BUILDTIME_IMAGE=${ECLAIR_DOCKER_BUILDTIME_IMAGE:-$DEFAULT_DOCKER_BUILDTIME_JAVA_IMAGE} 82 | export ECLAIR_DOCKER_RUNTIME_IMAGE=${ECLAIR_DOCKER_BUILDTIME_IMAGE:-$DEFAULT_DOCKER_RUNTIME_IMAGE} 83 | export LIGHTNING_DOCKER_BUILDTIME_IMAGE=${LIGHTNING_DOCKER_BUILDTIME_IMAGE:-$DEFAULT_DOCKER_BUILDTIME_IMAGE} 84 | export LIGHTNING_DOCKER_RUNTIME_IMAGE=${LIGHTNING_DOCKER_BUILDTIME_IMAGE:-$DEFAULT_DOCKER_RUNTIME_IMAGE} 85 | export LND_DOCKER_BUILDTIME_IMAGE=${LND_DOCKER_BUILDTIME_IMAGE:-$DEFAULT_DOCKER_BUILDTIME_GO_IMAGE} 86 | export LND_DOCKER_RUNTIME_IMAGE=${LND_DOCKER_BUILDTIME_IMAGE:-$DEFAULT_DOCKER_RUNTIME_IMAGE} 87 | export PRE_DOCKER_BUILDTIME_IMAGE=${PRE_DOCKER_BUILDTIME_IMAGE:-$DEFAULT_DOCKER_BUILDTIME_IMAGE} 88 | export PRE_DOCKER_RUNTIME_IMAGE=${PRE_DOCKER_BUILDTIME_IMAGE:-$DEFAULT_DOCKER_RUNTIME_IMAGE} 89 | 90 | # note: these are relative to docker build context 91 | export DEFAULT_BTCD_REPO_PATH=${DEFAULT_BTCD_REPO_PATH:-repos/btcd} 92 | export DEFAULT_BTCWALLET_REPO_PATH=${DEFAULT_BTCWALLET_REPO_PATH:-repos/btcwallet} 93 | export DEFAULT_LND_REPO_PATH=${DEFAULT_LND_REPO_PATH:-repos/lnd} 94 | export DEFAULT_LIGHTNING_REPO_PATH=${DEFAULT_LIGHTNING_REPO_PATH:-repos/lightning} 95 | export DEFAULT_BITCOIND_REPO_PATH=${DEFAULT_BITCOIND_REPO_PATH:-repos/bitcoin} 96 | export DEFAULT_BTCD_CONF_PATH=${DEFAULT_BTCD_CONF_PATH:-docker/btcd/btcd.conf} 97 | export DEFAULT_BTCWALLET_CONF_PATH=${DEFAULT_BTCWALLET_CONF_PATH:-docker/btcd/btcwallet.conf} 98 | export DEFAULT_LND_CONF_PATH=${DEFAULT_LND_CONF_PATH:-docker/lnd/lnd.conf} 99 | export DEFAULT_LIGHTNING_CONF_PATH=${DEFAULT_LIGHTNING_CONF_PATH:-docker/lightning/config} 100 | export DEFAULT_BITCOIND_CONF_PATH=${DEFAULT_BITCOIND_CONF_PATH:-docker/bitcoind/bitcoin.conf} 101 | export DEFAULT_ECLAIR_REPO_PATH=${DEFAULT_ECLAIR_REPO_PATH:-repos/eclair} 102 | export DEFAULT_ECLAIR_CONF_PATH=${DEFAULT_ECLAIR_CONF_PATH:-docker/eclair/eclair.conf} 103 | 104 | export SIMVERSE_HOST_BIND=${SIMVERSE_HOST_BIND:-127.0.0.1:} # note the trailing colon, see https://docs.docker.com/compose/compose-file/#ports 105 | export SIMVERSE_EXTRA_SERVICE_CONFIG=${SIMVERSE_EXTRA_SERVICE_CONFIG} 106 | 107 | export SIMVERSE_REPORT_ENV=${SIMVERSE_REPORT_ENV} 108 | 109 | export DEBUG=${DEBUG:-info} 110 | export FAUCET_ADDR=${FAUCET_ADDR:-mp76nrashrCCYLy3a8cAc5HufEas11yHbh} # note this is a regtest address 111 | export FAUCET_ADDR_PRIVATE_KEY=${FAUCET_ADDR_PRIVATE_KEY:-cP2SDKHK9PwQyBwRcnCTar4R5iv8HMPNZs6aCNRJ5o736cWcYGsZ} # note this is a regtest key 112 | export RPC_USER=${RPC_USER:-devuser} 113 | export RPC_PASS=${RPC_PASS:-devpass} 114 | export BTCWALLET_USER=${BTCWALLET_USER} # optional, RPC_USER will be used if not given 115 | export BTCWALLET_PASS=${BTCWALLET_PASS} # optional, RPC_PASS will be used if not given 116 | 117 | export BITCOIN_P2P_BIND=${BITCOIN_P2P_BIND:-0.0.0.0} 118 | export BITCOIN_P2P_PORT=${BITCOIN_P2P_PORT:-18444} # note: touching this is not flexible, some ports are hardcoded or left default 119 | export BITCOIN_RPC_BIND=${BITCOIN_RPC_BIND:-0.0.0.0} 120 | export BITCOIN_RPC_PORT=${BITCOIN_RPC_PORT:-18334} # note: touching this is not flexible, some ports are hardcoded or left default 121 | export BTCWALLET_RPC_BIND=${BTCWALLET_RPC_BIND:-0.0.0.0} 122 | export BTCWALLET_RPC_PORT=${BTCWALLET_RPC_PORT:-18443} # note: touching this is not flexible, some ports are hardcoded or left default 123 | 124 | export LND_CHAIN=${LND_CHAIN:-bitcoin} 125 | export LND_BACKEND=${LND_BACKEND} 126 | export LND_P2P_BIND=${LND_P2P_BIND:-0.0.0.0} 127 | export LND_P2P_PORT=${LND_P2P_PORT:-9735} 128 | export LND_RPC_BIND=${LND_RPC_BIND:-0.0.0.0} 129 | export LND_RPC_PORT=${LND_RPC_PORT:-10009} 130 | export LND_REST_BIND=${LND_REST_BIND:-0.0.0.0} 131 | export LND_REST_PORT=${LND_REST_PORT:-8080} 132 | export LND_BITCOIN_RPC_HOST=${LND_BITCOIN_RPC_HOST} 133 | 134 | export ZMQ_BIND=${ZMQ_BIND:-0.0.0.0} 135 | export ZMQ_PUBRAWBLOCK_PORT=${ZMQ_PUBRAWBLOCK_PORT:-28332} 136 | export ZMQ_PUBRAWTX_PORT=${ZMQ_PUBRAWTX_PORT:-28333} 137 | 138 | export LIGHTNING_BACKEND=${LIGHTNING_BACKEND} 139 | export LIGHTNING_BITCOIN_RPC_HOST=${LIGHTNING_BITCOIN_RPC_HOST} 140 | export LIGHTNING_P2P_BIND=${LIGHTNING_P2P_BIND:-0.0.0.0} 141 | export LIGHTNING_P2P_PORT=${LIGHTNING_P2P_PORT:-9735} 142 | export LIGHTNING_RPC_BIND=${LIGHTNING_RPC_BIND:-0.0.0.0} 143 | export LIGHTNING_RPC_PORT=${LIGHTNING_RPC_PORT:-9835} 144 | export LIGHTNING_EXPOSE_TCP=${LIGHTNING_EXPOSE_TCP:-true} 145 | export LIGHTNING_VALGRIND_FLAG=${LIGHTNING_VALGRIND_FLAG:-0} 146 | export LIGHTNING_DEVELOPER_FLAG=${LIGHTNING_DEVELOPER_FLAG:-1} 147 | export LIGHTNING_CONFIGURE_OPTS=${LIGHTNING_CONFIGURE_OPTS:-"--enable-developer"} 148 | 149 | export ECLAIR_BACKEND=${ECLAIR_BACKEND} 150 | export ECLAIR_BITCOIN_RPC_HOST=${ECLAIR_BITCOIN_RPC_HOST} 151 | export ECLAIR_P2P_BIND=${ECLAIR_P2P_BIND:-0.0.0.0} 152 | export ECLAIR_P2P_PORT=${ECLAIR_P2P_PORT:-9735} 153 | export ECLAIR_RPC_BIND=${ECLAIR_RPC_BIND:-0.0.0.0} 154 | export ECLAIR_RPC_PORT=${ECLAIR_RPC_PORT:-8080} 155 | 156 | export BTCD_EXTRA_PARAMS=${BTCD_EXTRA_PARAMS} 157 | export BTCWALLET_EXTRA_PARAMS=${BTCWALLET_EXTRA_PARAMS} 158 | export BTCCTL_EXTRA_PARAMS=${BTCCTL_EXTRA_PARAMS} 159 | export LND_EXTRA_PARAMS=${LND_EXTRA_PARAMS} 160 | export LIGHTNINGD_EXTRA_PARAMS=${LIGHTNINGD_EXTRA_PARAMS} 161 | export LIGHTNING_CLI_EXTRA_PARAMS=${LIGHTNING_CLI_EXTRA_PARAMS} 162 | export BITCOINCLI_EXTRA_PARAMS=${BITCOINCLI_EXTRA_PARAMS} 163 | export BITCOIND_EXTRA_PARAMS=${BITCOIND_EXTRA_PARAMS} 164 | 165 | # GO specific 166 | export GCFLAGS=${GCFLAGS:-"all=-N -l"} # compile with no optimizations, for go-delve debugger 167 | -------------------------------------------------------------------------------- /readme.md: -------------------------------------------------------------------------------- 1 | # Simverse 2 | 3 | This is a tool for lightning network developers. It can generate local simnet clusters of requested size and shape. It uses docker-compose 4 | to manage the cluster and provides a set of helper scripts for your convenience. 5 | 6 | ## Features 7 | 8 | * supports [btcd](https://github.com/btcsuite/btcd) and [bitcoind](https://github.com/bitcoin/bitcoin) as backend nodes 9 | * supports [lnd](https://github.com/lightningnetwork/lnd), [lightningd](https://github.com/ElementsProject/lightning) and [eclair](https://github.com/ACINQ/eclair) as lightning nodes 10 | 11 | ## Workflow 12 | 13 | You use a simple DSL script (bash) as a recipe to describe your cluster. Given a [recipe](recipes), Simverse will generate 14 | a bunch of dockerfiles, docker-compose config and other supporting scripts for you. Before generating the files you can tweak your 15 | configuration using [env variables](_defaults.sh). 16 | 17 | ## Prerequisites: 18 | 19 | On host machine you should have recent versions of: 20 | 21 | * bash 4+, git 2+, jq 1.6+ 22 | * docker 18+, docker-compose 1.24+ 23 | 24 | Tested on macOS and Ubuntu 18.10. 25 | 26 | ## Quick start 27 | 28 | In a terminal session: 29 | ```bash 30 | > git clone --recursive https://github.com/darwin/simverse.git 31 | > cd simverse 32 | > ./sv create # first time, it will ask to clone repos, answer yes 33 | ... 34 | > ./sv enter 35 | ... 36 | _workspace/default > ./dc build 37 | ... 38 | _workspace/default > ./dc up # this gives you a nice log for whole cluster 39 | ... 40 | ``` 41 | 42 | In a second terminal session: 43 | 44 | ```bash 45 | > cd simverse 46 | > ./sv enter 47 | _workspace/default > btcd1 getinfo 48 | ... 49 | _workspace/default > alice getinfo 50 | ... 51 | _workspace/default > connect alice bob # connect Alice's lnd node to Bob's 52 | ... 53 | _workspace/default > fund alice 10 # fund Alice with 10 BTC 54 | ... 55 | _workspace/default > open_channel alice bob 0.1 # open a LN channel 56 | ... 57 | _workspace/default > pay alice bob 0.01 # pay via LN 58 | ``` 59 | 60 | Here is the default recipe which was used for simnet generation (see [`recipes/default.sh`](recipes/default.sh)): 61 | 62 | ```bash 63 | . cookbook/cookbook.sh 64 | 65 | prelude 66 | 67 | add btcd 68 | 69 | add lnd alice 70 | add lnd bob 71 | ``` 72 | 73 | If you want different configuration, see [`recipes/readme.md`](recipes/readme.md) to understand 74 | the naming convention of recipes. Then you can create the simverse by adding a parameter to the 75 | create script: 76 | 77 | ```bash 78 | ./sv create a1k2 79 | ``` 80 | 81 | This will create a bitcoind and two lightningd configuration simverse. 82 | 83 | If you don't want to risk putting your machine on fire, here is a recording: 84 | 85 | * note that we used pre-generated `./tmux` script to launch everything in one terminal window 86 | 87 | [![asciicast](https://asciinema.org/a/246214.svg)](https://asciinema.org/a/246214) 88 | 89 | ## Generated simnet folder 90 | 91 | A simnet folder contains generated files for your simnet based on a selected recipe. 92 | 93 | Typical workflow is to create simnet and then enter it via `./sv enter [simnet_name]`, then you can 94 | 95 | * use `./dc` command to manage simnet cluster via docker compose (see generated `docker-compose.yml`). 96 | * use tools from [`toolbox`](toolbox) and (generated) `aliases` folders (they should be on $PATH). 97 | 98 | ## An example simnet session 99 | 100 | ___See 'quick start' section above.___ 101 | 102 | Go to simverse root directory. Please open two terminal windows: 103 | 104 | - The first one will be for logs 105 | - The second one will be for interaction with running cluster 106 | 107 | ### In the first terminal session 108 | 109 | 1. Enter simnet via `./sv enter default` 110 | 2. Build simnet via `./dc build` 111 | 3. Launch simnet via `./dc up` 112 | 113 | When you hit CTRL+C, docker will shutdown your simnet and you can rinse, repeat. See tips below in FAQ to learn more. 114 | 115 | ### In the second terminal session 116 | 117 | 1. (assuming running simnet) 118 | 2. Enter simnet via `./sv enter default` 119 | 3. you can control individual services via their names e.g. `alice getinfo` or 120 | `btcd1 getnetworkinfo` (see `aliases` dir). Also note that first lnd node has alias `lncli` and first btcd node 121 | has alias `btcctl`. 122 | 4. you can also use convenience commands from [`toolbox`](toolbox), for example: 123 | 124 | ```bash 125 | # assuming you have at least one btcd node and lnd nodes alice, bob and charlie (see the recipe 'b1l3.sh') 126 | # 127 | # let's follow the tutorial https://dev.lightning.community/tutorial/01-lncli 128 | 129 | fund alice 10 130 | fund bob 10 131 | fund charlie 10 132 | 133 | connect alice charlie 134 | connect bob charlie 135 | 136 | open_channel alice charlie 0.1 137 | open_channel charlie bob 0.05 138 | 139 | # wait for channel discovery to kick in (circa 20s) 140 | 141 | pay alice bob 0.01 142 | ``` 143 | 144 | Alternatively you can use our pre-generated `./tmux` script. 145 | 146 | ### Gotchas 147 | 148 | * If in troubles, please make sure you have the latest versions tools above, especially docker and docker-compose. 149 | * Simverse [tries to enforce](https://github.com/darwin/simverse/blob/master/recipes/cookbook/templates/docker/runtime/Dockerfile) 150 | host's UID and GID as permissions for simnet user running the services like `lnd` or `btcd`. 151 | This is quite important for [comfortable access](https://dille.name/blog/2018/07/16/handling-file-permissions-when-writing-to-volumes-from-docker-containers/) 152 | to simnet state folders from host machine under some systems. This can fail in case when your current UID(GID) on host is 153 | already taken inside Alpine Linux container. In such cases the effective user in the container is disconnected from host 154 | user and permissions on state folder might be different. You might need root permission to remove them on host. 155 | 156 | ### macOS notes 157 | 158 | * (recommended)keep workspace on APFS-formatted filesystem to benefit from clonefile 159 | 160 | ## FAQ 161 | 162 | #### Is this secure? 163 | 164 | > No. This is a developer setup and should be never used on a machine connected to open internet. 165 | > It is expected to be used developer machine on a local network behind NAT/firewall and should never contain sensitive info. 166 | > Anyways whatever you do, you use it at your own risk. 167 | 168 | #### How do I customize build/runtime parameters for individual docker containers? 169 | 170 | > By customizing your recipe before adding a node or globally via env variables. See [`_defaults.sh`](_defaults.sh). 171 | > For example you can set different `DEFAULT_LND_REPO_PATH` before each `add lnd ...` command. This would tweak effective 172 | config for following lnd nodes. Read the [`cookbook.sh`](recipes/cookbook/cookbook.sh) bash script for better understanding. 173 | 174 | #### How do I rebuild everything from scratch? 175 | 176 | > `./dc --no-cache build` 177 | 178 | #### How do I determine ports mapping to my host machine? 179 | 180 | > `./dc ps` (assuming a running simnet) 181 | 182 | #### I'd like to know IP addresses of individual machines in the simnet cluster. How? 183 | 184 | > [`list_docker_ips`](toolbox/list_docker_ips) please note that you should not use hard-coded IPs, instead use service names docker assigned to 185 | individual machines 186 | 187 | #### Is it possible to launch multiple simnets in parallel? 188 | 189 | > It is possible to create multiple simnets. But under normal circumstances you are expected to run only one simnet at a time. 190 | By default, all simnets use the same port mappings to the host machine, so you would not be able to launch them in parallel. 191 | But you can write a simple wrapper scripts which could modify all *_PORT_ON_HOST in _defaults.sh. You can allocate them so 192 | that they don't overlap for simnets you need to run in parallel. 193 | 194 | #### I noticed the nodes run in regtest mode, not simnet. Why? 195 | 196 | > Simnet mode is supported only in btcd and lnd. Bitcoind and c-lightning have regtest which happens to be available in btcd/lnd as well. 197 | To allow hybrid simverse clusters we had to use regtest mode everywhere (which works like simnet for our purposes). 198 | Only we had to [patch btcd](recipes/cookbook/scaffold/docker/btcd/patches) to fix some minor issue, because not many people use 199 | it this way I guess. 200 | 201 | #### How can I inspect a running container in shell? 202 | 203 | > `./dc exec bash` or `./dc exec fish` or `./dc exec sh` 204 | > 205 | > or `./dc exec ` 206 | > 207 | > Pro Tip: you might want to add `--user root` before container name to run the command with unrestricted permissions 208 | 209 | #### Is it possible to keep simverse workspace on my own path? 210 | 211 | > Yes. Look for [`SIMVERSE_WORKSPACE`](_defaults.sh) env var. 212 | 213 | #### Is it possible to keep projects' repos on my own path? 214 | 215 | > Yes. Look for [`SIMVERSE_REPOS`](_defaults.sh) env var. 216 | 217 | #### What is a master bitcoin node? 218 | 219 | > In a cluster of bitcoin nodes we need one which will be special. It will do some privileged tasks like mining or holding 220 | mined coins in its associated wallet. By convention, master bitcoin node is always first bitcoin node created. You can get its hostname 221 | by running `lookup_host 1 role bitcoin`. Simverse supports multiple bitcoin node implementations and master node might be either 222 | btcd or bitcoind "flavor". Raw cli interface might be slightly different, so we try to hide this in our commands like [`onchain_balance`](toolbox/onchain_balance), 223 | [`chain_height`](toolbox/chain_height) or [`earn`](toolbox/earn). If you looked at their implementation you would spot code branches for different bitcoin node flavors. 224 | 225 | #### Where is a faucet? 226 | 227 | > This is not a testnet with faucet so we have to mine coins ourselves. Look for [`FAUCET_ADDR`](_defaults.sh) env var which contains 228 | > pre-generated bitcoin address which will receive all mined coins. During bitcoin node initialization we import this address into 229 | > a wallet (see [`setup-wallet.sh`](recipes/cookbook/scaffold/docker/btcd/home/setup-wallet.sh)). 230 | > This way `btcctl --wallet sendfrom imported ...` can be used to send funds to others in need. We use similar approach when your 231 | > master bitcoin node is bitcoind. 232 | > 233 | > Please look at [`toolbox/fund`](toolbox/fund) script which can be used for convenient funding of lnd wallets. For example run `fund alice 10` 234 | > to send 10 BTC to Alice's lnd node wallet. The script might decide to call [`toolbox/earn`](toolbox/earn) to mine enough coins and wait 235 | > for their maturity. 236 | 237 | #### What is the difference between heterogeneous and hybrid simnets? 238 | 239 | > A homogeneous simnet contains only `btcd` + `lnd` nodes or only `bitcoind` + `c-lightning` nodes. 240 | Generally, it contains only one flavor of bitcoin and one flavor of lightning nodes. Heterogeneous simnet can mix them. 241 | > A hybrid simnet is a simnet with cooperating nodes running in docker and also on the host machine. This is more advanced 242 | developer setup where you want to develop/debug one specific node and have rest of the simnet running "in the background" in docker. 243 | 244 | #### Cool work! How can I send some sats your way? 245 | 246 |

247 | 248 | Tip darwin on TipHub 249 |
250 | My pubkey starts with 03e24db0 251 |
252 |

253 | 254 | --- 255 | 256 | ## simverse utility reference 257 | 258 | Note that [`sv`](sv) is a convenience symlink to [`simverse`](simverse). 259 | 260 | ##### `> ./sv help` 261 | ``` 262 | Simverse v0.5. 263 | 264 | A generator of simnet clusters for lnd and friends. 265 | 266 | Usage: ./sv [command] [args...] 267 | 268 | Commands: 269 | 270 | create create a new simnet based on a recipe 271 | destroy destroy existing named simnet 272 | list list existing simnets 273 | enter enter a named simnet 274 | state perform state operations on a simnet 275 | repos perform operations on code repositories 276 | help this help page 277 | version display version 278 | 279 | Run `./sv help ` for specific usage. 280 | Run `./sv help ` to learn about general concepts. 281 | 282 | Topics: simnet, recipes, workspace, toolbox, aliases. 283 | 284 | Please visit 'https://github.com/darwin/simverse' for further info. 285 | ``` 286 | 287 | ##### `> ./sv help simnet` 288 | ``` 289 | About simnets 290 | 291 | Simnet is a cluster of bitcoin and lightning nodes talking to each other. 292 | Simnets are used during development to test different scenarios/workflow 293 | where multiple nodes are required. 294 | 295 | Simnets can have different sizes and shapes. They can be heavily parametrized. 296 | 297 | This tool aims to help with simnet creation and maintenance. 298 | 299 | The goal is to: 300 | 301 | * easily generate a simnet based on given parameters 302 | * easily manage state of a simnet (e.g. for future replays) 303 | * somewhat isolate simnet from host machine (via docker) 304 | * provide cross-platform solution (macos, linux) 305 | 306 | Typical simnet folder structure is: 307 | 308 | _workspace/[simnet_name]/ 309 | _states/ 310 | master/ 311 | certs/ 312 | lnd-data-alice/ 313 | btcd-data-btcd1/ 314 | ... 315 | ... 316 | _volumes -> _states/master 317 | aliases/ 318 | docker/ 319 | helpers/ 320 | repos/ 321 | toolbox/ 322 | dc 323 | docker-compose.yml 324 | tmux 325 | 326 | Feel free to look around. Below we discuss state management. 327 | 328 | Simnet state 329 | 330 | All docker containers have their state mapped to host machine into _volumes folder. 331 | It contains btcd's data directories, lnd's data directories and similar. 332 | When you stop docker containers and later run them again, the state will persist. 333 | 334 | When you look at _volumes you realize that it is just a symlink somewhere into _states directory. 335 | Typically pointing to 'master', which is the default state. 336 | 337 | You can manage states via `./sv state ...`. 338 | Those are just convenience commands to copy/switch _volumes symlink between states. 339 | 340 | This is an advanced feature for people who want to snapshot a state for further rollbacks. 341 | It can be also used for replays during automated testing. 342 | 343 | 344 | A note on hybrid simnets 345 | 346 | By default, simnet is generated in a way that all nodes live inside docker containers 347 | managed by docker-compose. For convenience we map all relevant ports to host machine. 348 | This allows running another node directly on host machine and interact with nodes in 349 | the cluster inside the docker. 350 | 351 | This is expected workflow for someone who wants to develop particular feature and 352 | needs supporting simnet "in the background". 353 | 354 | ``` 355 | 356 | ##### `> ./sv help workspace` 357 | ``` 358 | About workspace 359 | 360 | Workspace is a working folder where your generated simnets get stored. 361 | By default it is under `_workspace` but you can control it 362 | via SIMVERSE_WORKSPACE environmental variable. 363 | 364 | Each simnet has a name given to it during `./sv create [recipe] [name]` call. 365 | Workspace contains a folder for each simnet named after it. 366 | 367 | You can enter your simnet via `./sv enter [name]`. 368 | ``` 369 | 370 | ##### `> ./sv help create` 371 | ``` 372 | Usage: ./sv create [-f] [recipe] [name] 373 | 374 | Creates a new simnet with `name` (default) based on `recipe` (default). 375 | On success, prints a path to generated simnet working folder in your workspace. 376 | 377 | Flags: 378 | -f,--force force creation by destroying previous simnet 379 | 380 | Recipe should be name of a script in `recipes` folder. It specifies requested simnet 381 | parameters and drives the generator. 382 | 383 | Read more about recipes via `./sv help recipes` 384 | ``` 385 | 386 | ##### `> ./sv help recipe` 387 | ``` 388 | About recipes 389 | 390 | Simnets can have different sizes and shapes. They can be heavily parametrized. 391 | Recipe is a script describing how to build a given simnet. 392 | 393 | An example of a simple recipe: 394 | 395 | . cookbook/cookbook.sh 396 | 397 | prelude 398 | 399 | add btcd btcd 400 | 401 | add lnd alice 402 | add lnd bob 403 | 404 | Recipes are located under `recipes` folder. 405 | Say, we stored the above recipe as `recipes/example.sh`. 406 | 407 | By running `./sv create example mysn`, we create a new simnet named `mysn` 408 | which has one btcd node and two lnd nodes, all with default settings. 409 | 410 | Recipes are bash scripts executed as the last step in simnet creation. 411 | That means you can do anything bash can do to tweak given simnet. 412 | To make your life easier, we provide a simple library "cookbook" for building 413 | simnet on step-by-step basis with sane defaults. 414 | 415 | We are not going to document the cookbook here. Please refer to its sources. 416 | 417 | Please look around in `recipes` folder and see how existing recipes are done. 418 | ``` 419 | 420 | ##### `> ./sv help toolbox` 421 | ``` 422 | About toolbox 423 | 424 | Toolbox is a set of convenience scripts for typical interaction with simnet. 425 | 426 | When you enter a simnet via `./sv enter [name]`, toolbox folder is added to your PATH. 427 | 428 | Explore `toolbox` folder for the details: 429 | 430 | attach_dlv 431 | brief 432 | chain_height 433 | connect 434 | earn 435 | faucet_balance 436 | fund 437 | generate 438 | get_route 439 | inspect_container 440 | list_docker_ips 441 | ln_balance 442 | lookup_container 443 | lookup_service 444 | newaddr 445 | onchain_balance 446 | open_channel 447 | pay 448 | pubkey 449 | req_pay 450 | simnet_ready 451 | 452 | ``` 453 | 454 | ##### `> ./sv help aliases` 455 | ``` 456 | About aliases 457 | 458 | Aliases are scripts generated depending on shape/parameters of your simnet. 459 | 460 | When you enter a simnet via `./sv enter [name]`. Aliases folder is added to your PATH. 461 | 462 | For example default simnet will generate following aliases for you: 463 | 464 | alice 465 | bob 466 | btcd1 467 | btcctl -> btcd1 468 | lncli -> alice 469 | 470 | Aliases are convenience shortcuts to control tools for individual nodes (named by simnet recipe). 471 | 472 | Additionally there will be generated `btcctl` symlink pointing to first btcd node. And `lncli` 473 | symlink pointing to the first lnd node. This comes handy for asking general questions about networks 474 | not specific to exact node. 475 | ``` 476 | 477 | ##### `> ./sv help destroy` 478 | ``` 479 | Usage: ./sv destroy [name] 480 | 481 | Deletes a simnet with `name` (default). 482 | ``` 483 | 484 | ##### `> ./sv help enter` 485 | ``` 486 | Usage: ./sv enter [name] 487 | 488 | Enters into a sub-shell with environment prepared for simnet with `name` (default). 489 | 490 | You typically use this command to start working with a given simnet. In the sub-shell we: 491 | 492 | * switch working directory into simnet's folder 493 | * set PATH to additionally contain toolbox and aliases 494 | ``` 495 | 496 | ##### `> ./sv help list` 497 | ``` 498 | Usage: ./sv list [filter] 499 | 500 | Lists all available simnets by name. Optionally you can filter the list using a case-insensitive substring. 501 | 502 | Run `./sv help simnet` to learn what is a simnet. 503 | ``` 504 | 505 | ##### `> ./sv help state` 506 | ``` 507 | Usage: ./sv state [sub-command] ... 508 | 509 | Manipulates simnet state. 510 | 511 | Sub-commands: 512 | 513 | show show currently selected state in a given simnet 514 | clone clone existing state in a given simnet 515 | switch switch selection to a named state in a given simnet 516 | list list states for a given simnet 517 | rm remove a named state in a given simnet 518 | 519 | ./sv state show [simnet_name] 520 | ./sv state clone [--force] [--switch] [simnet_name] [old_state_name] 521 | ./sv state switch [simnet_name] [state_name] 522 | ./sv state list [simnet_name] [filter] 523 | ./sv state rm [simnet_name] 524 | 525 | Run `./sv help simnet` to learn about simnet states. 526 | ``` 527 | 528 | ##### `> ./sv help repos` 529 | ``` 530 | Usage: ./sv repos [sub-command] ... 531 | 532 | Manipulates code repositories. 533 | 534 | Sub-commands: 535 | 536 | init init default repos (git clone) 537 | update update default repos (git pull) 538 | clone clone existing repo under a new name 539 | list list repos 540 | rm remove repo(s) 541 | report report current tips 542 | unshallow unshallow repos 543 | 544 | ./sv repos init [repo_name] [...] 545 | ./sv repos update [repo_name] [...] 546 | ./sv repos clone [--force] 547 | ./sv repos list [filter] 548 | ./sv repos rm [repo_name] [...] 549 | ./sv repos report [filter] 550 | ./sv repos unshallow [filter] 551 | ``` 552 | -------------------------------------------------------------------------------- /recipes/cookbook/cookbook.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | set -e -o pipefail 4 | 5 | # this script defines a simple DSL for incrementally building docker-compose config and related files 6 | 7 | # recipes must be invoked from $SIMVERSE_HOME/recipes dir, with 8 | # 9 | # also note that SIMVERSE_HOME, SIMVERSE_WORKSPACE and SIMVERSE_REPOS must be set 10 | 11 | SIMNET_NAME=${1:?please specify a simnet name as first argument} 12 | 13 | # example usage: 14 | # 15 | # . cookbook/cookbook.sh 16 | # 17 | # prelude 18 | # add btcd prague 19 | # add lnd alice 20 | # add lnd bob 21 | 22 | REQUIRED="variable not set or empty, (hint: source _defaults.sh)" 23 | 24 | SIMVERSE_HOME=${SIMVERSE_HOME:?$REQUIRED} 25 | SIMVERSE_REPOS=${SIMVERSE_REPOS:?$REQUIRED} 26 | SIMVERSE_WORKSPACE=${SIMVERSE_WORKSPACE:?$REQUIRED} 27 | COOKBOOK_DIR="$SIMVERSE_HOME/recipes/cookbook" 28 | TEMPLATES_DIR="$COOKBOOK_DIR/templates" 29 | SCAFFOLD_DIR="$COOKBOOK_DIR/scaffold" 30 | TOOLBOX_DIR="$SIMVERSE_HOME/toolbox" 31 | 32 | COMPOSE_FILE="docker-compose.yml" 33 | ALIASES_DIR_NAME="aliases" 34 | 35 | # configured externally via env (see _defaults.sh) 36 | 37 | FIRST_DLV_PORT_ON_HOST=${FIRST_DLV_PORT_ON_HOST:?$REQUIRED} 38 | FIRST_DLV_PORT=${FIRST_DLV_PORT:?$REQUIRED} 39 | 40 | FIRST_LND_SERVER_PORT_ON_HOST=${FIRST_LND_SERVER_PORT_ON_HOST:?$REQUIRED} 41 | FIRST_LND_RPC_PORT_ON_HOST=${FIRST_LND_RPC_PORT_ON_HOST:?$REQUIRED} 42 | FIRST_LND_REST_PORT_ON_HOST=${FIRST_LND_REST_PORT_ON_HOST:?$REQUIRED} 43 | FIRST_BTCD_SERVER_PORT_ON_HOST=${FIRST_BTCD_SERVER_PORT_ON_HOST:?$REQUIRED} 44 | FIRST_BTCD_RPC_PORT_ON_HOST=${FIRST_BTCD_RPC_PORT_ON_HOST:?$REQUIRED} 45 | FIRST_BTCWALLET_RPC_PORT_ON_HOST=${FIRST_BTCWALLET_RPC_PORT_ON_HOST:?$REQUIRED} 46 | FIRST_BITCOIND_SERVER_PORT_ON_HOST=${FIRST_BITCOIND_SERVER_PORT_ON_HOST:?$REQUIRED} 47 | FIRST_BITCOIND_RPC_PORT_ON_HOST=${FIRST_BITCOIND_RPC_PORT_ON_HOST:?$REQUIRED} 48 | FIRST_LIGHTNING_SERVER_PORT_ON_HOST=${FIRST_LIGHTNING_SERVER_PORT_ON_HOST:?$REQUIRED} 49 | FIRST_LIGHTNING_RPC_PORT_ON_HOST=${FIRST_LIGHTNING_RPC_PORT_ON_HOST:?$REQUIRED} 50 | FIRST_ECLAIR_SERVER_PORT_ON_HOST=${FIRST_ECLAIR_SERVER_PORT_ON_HOST:?$REQUIRED} 51 | FIRST_ECLAIR_RPC_PORT_ON_HOST=${FIRST_ECLAIR_RPC_PORT_ON_HOST:?$REQUIRED} 52 | 53 | LND_AUTO_NAME_PREFIX=${LND_AUTO_NAME_PREFIX:?$REQUIRED} 54 | BTCD_AUTO_NAME_PREFIX=${BTCD_AUTO_NAME_PREFIX:?$REQUIRED} 55 | BITCOIND_AUTO_NAME_PREFIX=${BITCOIND_AUTO_NAME_PREFIX:?$REQUIRED} 56 | LIGHTNING_AUTO_NAME_PREFIX=${LIGHTNING_AUTO_NAME_PREFIX:?$REQUIRED} 57 | ECLAIR_AUTO_NAME_PREFIX=${ECLAIR_AUTO_NAME_PREFIX:?$REQUIRED} 58 | 59 | DEFAULT_BTCD_REPO_PATH=${DEFAULT_BTCD_REPO_PATH:?$REQUIRED} 60 | DEFAULT_BTCWALLET_REPO_PATH=${DEFAULT_BTCWALLET_REPO_PATH:?$REQUIRED} 61 | DEFAULT_LND_REPO_PATH=${DEFAULT_LND_REPO_PATH:?$REQUIRED} 62 | DEFAULT_BITCOIND_REPO_PATH=${DEFAULT_BITCOIND_REPO_PATH:?$REQUIRED} 63 | DEFAULT_LIGHTNING_REPO_PATH=${DEFAULT_LIGHTNING_REPO_PATH:?$REQUIRED} 64 | DEFAULT_ECLAIR_REPO_PATH=${DEFAULT_ECLAIR_REPO_PATH:?$REQUIRED} 65 | 66 | DEFAULT_BTCD_CONF_PATH=${DEFAULT_BTCD_CONF_PATH:?$REQUIRED} 67 | DEFAULT_BTCWALLET_CONF_PATH=${DEFAULT_BTCWALLET_CONF_PATH:?$REQUIRED} 68 | DEFAULT_LND_CONF_PATH=${DEFAULT_LND_CONF_PATH:?$REQUIRED} 69 | DEFAULT_BITCOIND_CONF_PATH=${DEFAULT_BITCOIND_CONF_PATH:?$REQUIRED} 70 | DEFAULT_LIGHTNING_CONF_PATH=${DEFAULT_LIGHTNING_CONF_PATH:?$REQUIRED} 71 | DEFAULT_ECLAIR_CONF_PATH=${DEFAULT_ECLAIR_CONF_PATH:?$REQUIRED} 72 | 73 | LND_BITCOIN_RPC_HOST=${LND_BITCOIN_RPC_HOST} 74 | LND_BACKEND=${LND_BACKEND} 75 | 76 | LIGHTNING_BITCOIN_RPC_HOST=${LIGHTNING_BITCOIN_RPC_HOST} 77 | LIGHTNING_BACKEND=${LIGHTNING_BACKEND} 78 | 79 | ECLAIR_BITCOIN_RPC_HOST=${ECLAIR_BITCOIN_RPC_HOST} 80 | ECLAIR_BACKEND=${ECLAIR_BACKEND} 81 | 82 | # error codes 83 | ERR_NOT_IMPLEMENTED=10 84 | ERR_MUST_CALL_PRELUDE_FIRST=11 85 | ERR_NEED_BTCD_OR_BITCOIND=12 86 | ERR_REQUIRE_BITCOIND=13 87 | 88 | # -- helpers ---------------------------------------------------------------------------------------------------------------- 89 | 90 | echo_err() { 91 | printf "\e[31m%s\e[0m\n" "$*" >&2; 92 | } 93 | 94 | print_stack_trace() { 95 | local i=0 96 | while caller ${i}; do 97 | ((++i)) 98 | done 99 | } 100 | 101 | echo_err_with_stack_trace() { 102 | echo_err "$@" 103 | print_stack_trace | tail -n "+2" 104 | } 105 | 106 | # -- utils ------------------------------------------------------------------------------------------------------------------ 107 | 108 | init_common_defaults() { 109 | local 110 | } 111 | 112 | # shellcheck disable=SC2034 113 | init_btcd_defaults() { 114 | BTCD_REPO_PATH=${DEFAULT_BTCD_REPO_PATH} 115 | BTCWALLET_REPO_PATH=${DEFAULT_BTCWALLET_REPO_PATH} 116 | BTCD_CONF_PATH=${DEFAULT_BTCD_CONF_PATH} 117 | BTCWALLET_CONF_PATH=${DEFAULT_BTCWALLET_CONF_PATH} 118 | } 119 | 120 | # shellcheck disable=SC2034 121 | init_lnd_defaults() { 122 | LND_REPO_PATH=${DEFAULT_LND_REPO_PATH} 123 | LND_CONF_PATH=${DEFAULT_LND_CONF_PATH} 124 | } 125 | 126 | # shellcheck disable=SC2034 127 | init_bitcoind_defaults() { 128 | BITCOIND_REPO_PATH=${DEFAULT_BITCOIND_REPO_PATH} 129 | BITCOIND_CONF_PATH=${DEFAULT_BITCOIND_CONF_PATH} 130 | } 131 | 132 | # shellcheck disable=SC2034 133 | init_lightning_defaults() { 134 | LIGHTNING_REPO_PATH=${DEFAULT_LIGHTNING_REPO_PATH} 135 | LIGHTNING_CONF_PATH=${DEFAULT_LIGHTNING_CONF_PATH} 136 | } 137 | 138 | # shellcheck disable=SC2034 139 | init_eclair_defaults() { 140 | ECLAIR_REPO_PATH=${DEFAULT_ECLAIR_REPO_PATH} 141 | ECLAIR_CONF_PATH=${DEFAULT_ECLAIR_CONF_PATH} 142 | } 143 | 144 | init_defaults() { 145 | init_common_defaults 146 | init_bitcoind_defaults 147 | init_btcd_defaults 148 | init_lightning_defaults 149 | init_lnd_defaults 150 | init_eclair_defaults 151 | } 152 | 153 | reset_common_counters() { 154 | SERVICE_COUNTER=1 155 | BITCOIN_COUNTER=1 156 | LN_COUNTER=1 157 | DLV_PORT=${FIRST_DLV_PORT} 158 | DLV_PORT_ON_HOST=${FIRST_DLV_PORT_ON_HOST} 159 | LAST_BITCOIN_SERVICE= 160 | } 161 | 162 | reset_btcd_counters() { 163 | LAST_BTCD_SERVICE= 164 | BTCD_COUNTER=1 165 | BTCD_AUTO_NAME_COUNTER=0 166 | BTCD_SERVER_PORT_ON_HOST=${FIRST_BTCD_SERVER_PORT_ON_HOST} 167 | BTCD_RPC_PORT_ON_HOST=${FIRST_BTCD_RPC_PORT_ON_HOST} 168 | BTCWALLET_RPC_PORT_ON_HOST=${FIRST_BTCWALLET_RPC_PORT_ON_HOST} 169 | } 170 | 171 | reset_lnd_counters() { 172 | LND_COUNTER=1 173 | LND_AUTO_NAME_COUNTER=0 174 | LND_SERVER_PORT_ON_HOST=${FIRST_LND_SERVER_PORT_ON_HOST} 175 | LND_RPC_PORT_ON_HOST=${FIRST_LND_RPC_PORT_ON_HOST} 176 | LND_REST_PORT_ON_HOST=${FIRST_LND_REST_PORT_ON_HOST} 177 | } 178 | 179 | reset_bitcoind_counters() { 180 | LAST_BITCOIND_SERVICE= 181 | BITCOIND_COUNTER=1 182 | BITCOIND_AUTO_NAME_COUNTER=0 183 | BITCOIND_SERVER_PORT_ON_HOST=${FIRST_BITCOIND_SERVER_PORT_ON_HOST} 184 | BITCOIND_RPC_PORT_ON_HOST=${FIRST_BITCOIND_RPC_PORT_ON_HOST} 185 | } 186 | 187 | reset_lightning_counters() { 188 | LIGHTNING_COUNTER=1 189 | LIGHTNING_AUTO_NAME_COUNTER=0 190 | LIGHTNING_SERVER_PORT_ON_HOST=${FIRST_LIGHTNING_SERVER_PORT_ON_HOST} 191 | LIGHTNING_RPC_PORT_ON_HOST=${FIRST_LIGHTNING_RPC_PORT_ON_HOST} 192 | } 193 | 194 | reset_eclair_counters() { 195 | ECLAIR_COUNTER=1 196 | ECLAIR_AUTO_NAME_COUNTER=0 197 | ECLAIR_SERVER_PORT_ON_HOST=${FIRST_ECLAIR_SERVER_PORT_ON_HOST} 198 | ECLAIR_RPC_PORT_ON_HOST=${FIRST_ECLAIR_RPC_PORT_ON_HOST} 199 | } 200 | 201 | reset_counters() { 202 | reset_common_counters 203 | reset_lnd_counters 204 | reset_btcd_counters 205 | reset_bitcoind_counters 206 | reset_lightning_counters 207 | reset_eclair_counters 208 | } 209 | 210 | advance_common_counters() { 211 | ((++SERVICE_COUNTER)) 212 | ((++DLV_PORT)) 213 | ((++DLV_PORT_ON_HOST)) 214 | } 215 | 216 | advance_btcd_counters() { 217 | ((++BTCD_COUNTER)) 218 | ((++BTCD_SERVER_PORT_ON_HOST)) 219 | ((++BTCD_RPC_PORT_ON_HOST)) 220 | ((++BTCWALLET_RPC_PORT_ON_HOST)) 221 | 222 | ((++BITCOIN_COUNTER)) 223 | } 224 | 225 | advance_lnd_counters() { 226 | ((++LND_COUNTER)) 227 | ((++LND_SERVER_PORT_ON_HOST)) 228 | ((++LND_RPC_PORT_ON_HOST)) 229 | ((++LND_REST_PORT_ON_HOST)) 230 | 231 | ((++LN_COUNTER)) 232 | } 233 | 234 | advance_bitcoind_counters() { 235 | ((++BITCOIND_COUNTER)) 236 | ((++BITCOIND_SERVER_PORT_ON_HOST)) 237 | ((++BITCOIND_RPC_PORT_ON_HOST)) 238 | 239 | ((++BITCOIN_COUNTER)) 240 | } 241 | 242 | advance_lightning_counters() { 243 | ((++LIGHTNING_COUNTER)) 244 | ((++LIGHTNING_SERVER_PORT_ON_HOST)) 245 | ((++LIGHTNING_RPC_PORT_ON_HOST)) 246 | 247 | ((++LN_COUNTER)) 248 | } 249 | 250 | advance_eclair_counters() { 251 | ((++ECLAIR_COUNTER)) 252 | ((++ECLAIR_SERVER_PORT_ON_HOST)) 253 | ((++ECLAIR_RPC_PORT_ON_HOST)) 254 | 255 | ((++LN_COUNTER)) 256 | } 257 | 258 | gen_lnd_auto_name() { 259 | echo "${LND_AUTO_NAME_PREFIX}${LND_AUTO_NAME_COUNTER}" 260 | } 261 | 262 | advance_lnd_auto_name_counter() { 263 | ((++LND_AUTO_NAME_COUNTER)) 264 | } 265 | 266 | gen_btcd_auto_name() { 267 | echo "${BTCD_AUTO_NAME_PREFIX}${BTCD_AUTO_NAME_COUNTER}" 268 | } 269 | 270 | advance_btcd_auto_name_counter() { 271 | ((++BTCD_AUTO_NAME_COUNTER)) 272 | } 273 | 274 | gen_bitcoind_auto_name() { 275 | echo "${BITCOIND_AUTO_NAME_PREFIX}${BITCOIND_AUTO_NAME_COUNTER}" 276 | } 277 | 278 | advance_bitcoind_auto_name_counter() { 279 | ((++BITCOIND_AUTO_NAME_COUNTER)) 280 | } 281 | 282 | gen_lightning_auto_name() { 283 | echo "${LIGHTNING_AUTO_NAME_PREFIX}${LIGHTNING_AUTO_NAME_COUNTER}" 284 | } 285 | 286 | advance_lightning_auto_name_counter() { 287 | ((++LIGHTNING_AUTO_NAME_COUNTER)) 288 | } 289 | 290 | gen_eclair_auto_name() { 291 | echo "${ECLAIR_AUTO_NAME_PREFIX}${ECLAIR_AUTO_NAME_COUNTER}" 292 | } 293 | 294 | advance_eclair_auto_name_counter() { 295 | ((++ECLAIR_AUTO_NAME_COUNTER)) 296 | } 297 | 298 | eval_template() { 299 | local template_file=$1 300 | eval "cat < /dev/null 304 | } 305 | 306 | dolarize() { 307 | # in template scripts we use double dollar convention for template parameters 308 | sed 's/\$/>##<>###### /dev/null 322 | } 323 | 324 | into_dockerfile_snippet() { 325 | # in dockerfile template scripts we use '#include ' convention for template parameters 326 | sed 's/\$/>###BACKSLASH###BACKSLASH /dev/null 340 | } 341 | 342 | create_aliases_dir() { 343 | mkdir "$ALIASES_DIR_NAME" 344 | cp "$TEMPLATES_DIR/_alias_utils.sh" "$ALIASES_DIR_NAME" 345 | } 346 | 347 | prepare_repos() { 348 | # the problem is that our docker build context is somewhere $SIMVERSE_HOME/_workspace/[simnetname] (we can have multiple) 349 | # but we need to access files from $SIMVERSE_HOME/_repos 350 | # due to security reasons docker does not allow to access files outside that build context 351 | # here we attempt a fast way how to mount _repos as repos inside the docker context 352 | case "$OSTYPE" in 353 | darwin*) 354 | # -c assumes fast APFS clone 355 | cp -c -r "$SIMVERSE_REPOS" repos 356 | ;; 357 | linux*) 358 | # TODO: see https://superuser.com/a/842690 359 | # mkdir -p repos 360 | # sudo mount --bind "$SIMVERSE_REPOS" repos 361 | 362 | # use slower cp for now... 363 | cp -r "$SIMVERSE_REPOS" repos 364 | ;; 365 | *) 366 | echo "NOT IMPLEMENTED: add support for mirroring repos inside docker context for $OSTYPE" 367 | exit ${ERR_NOT_IMPLEMENTED} 368 | ;; 369 | esac 370 | } 371 | 372 | interpolate_dockerfile() { 373 | local path=$1 374 | eval_dockerfile_template "$SCAFFOLD_DIR/docker/$path" > "docker/$path" 375 | } 376 | 377 | # shellcheck disable=SC2034 378 | generate_dockerfiles() { 379 | BASE_DOCKERFILE_SNIPPET=$(eval_dockerfile_template "$TEMPLATES_DIR/docker/base/Dockerfile") 380 | BUILDTIME_DOCKERFILE_SNIPPET=$(eval_dockerfile_template "$TEMPLATES_DIR/docker/buildtime/Dockerfile") 381 | RUNTIME_DOCKERFILE_SNIPPET=$(eval_dockerfile_template "$TEMPLATES_DIR/docker/runtime/Dockerfile") 382 | 383 | interpolate_dockerfile "bitcoind/Dockerfile" 384 | interpolate_dockerfile "btcd/Dockerfile" 385 | interpolate_dockerfile "eclair/Dockerfile" 386 | interpolate_dockerfile "lightning/Dockerfile" 387 | interpolate_dockerfile "lnd/Dockerfile" 388 | interpolate_dockerfile "pre/Dockerfile" 389 | } 390 | 391 | scaffold_simnet() { 392 | # copy including dot files 393 | shopt -s dotglob 394 | cp -aL "$SCAFFOLD_DIR"/* . 395 | shopt -u dotglob 396 | generate_dockerfiles 397 | } 398 | 399 | add_toolbox() { 400 | ln -s "$TOOLBOX_DIR" toolbox 401 | 402 | } 403 | 404 | init_states() { 405 | mkdir "_states" 406 | mkdir "_states/master" 407 | ln -s "_states/master" _volumes 408 | } 409 | 410 | prepare_tmux_script() { 411 | eval_script_template "$TEMPLATES_DIR/tmux" > "tmux" 412 | chmod +x "tmux" 413 | } 414 | 415 | prepare_home_link() { 416 | ln -s "$SIMVERSE_HOME" home 417 | } 418 | 419 | echo_service_separator() { 420 | local kind=$1 421 | local name=$2 422 | local counter=$3 423 | echo -e "\n # -- ${counter}. $kind service -----------------------------------------------------------" >> ${COMPOSE_FILE} 424 | } 425 | 426 | # we have to create stub folders for volumes on host 427 | # if we let docker container create them instead under some systems we could end up with root permissions on them 428 | 429 | prepare_pre_volumes() { 430 | mkdir _volumes/certs 431 | } 432 | 433 | prepare_btcd_volumes() { 434 | local name=${1:?required} 435 | mkdir "_volumes/btcd-data-${name}" 436 | mkdir "_volumes/btcwallet-data-${name}" 437 | } 438 | 439 | prepare_lnd_volumes() { 440 | local name=${1:?required} 441 | mkdir "_volumes/lnd-data-${name}" 442 | } 443 | 444 | prepare_bitcoind_volumes() { 445 | local name=${1:?required} 446 | mkdir "_volumes/bitcoind-data-${name}" 447 | } 448 | 449 | prepare_lightning_volumes() { 450 | local name=${1:?required} 451 | mkdir "_volumes/lightning-data-${name}" 452 | } 453 | 454 | prepare_eclair_volumes() { 455 | local name=${1:?required} 456 | mkdir "_volumes/eclair-data-${name}" 457 | } 458 | 459 | ensure_bitcoin_service() { 460 | if [[ -z "$LAST_BITCOIN_SERVICE" ]]; then 461 | echo_err_with_stack_trace "'add lnd' called but no prior btcd or bitcoind was added, call 'add btcd' or 'add bitcoind' prior adding lnd nodes or set LND_BITCOIN_RPC_HOST explicitly" 462 | exit ${ERR_NEED_BTCD_OR_BITCOIND} 463 | fi 464 | } 465 | 466 | get_last_bitcoin_service() { 467 | ensure_bitcoin_service 468 | echo "$LAST_BITCOIN_SERVICE" 469 | } 470 | 471 | get_last_bitcoin_backend() { 472 | ensure_bitcoin_service 473 | if [[ "$LAST_BITCOIN_SERVICE" == "$LAST_BITCOIND_SERVICE" ]]; then 474 | echo "bitcoind" 475 | return 476 | fi 477 | echo "btcd" 478 | } 479 | 480 | add_lnd() { 481 | NAME=$1 482 | 483 | # generate default name if not given 484 | if [[ -z "$NAME" ]]; then 485 | advance_lnd_auto_name_counter 486 | NAME=$(gen_lnd_auto_name) 487 | fi 488 | 489 | # auto-provide LND_BITCOIN_RPC_HOST if not given 490 | local prev_lnd_bitcoin_rpc_host="$LND_BITCOIN_RPC_HOST" 491 | if [[ -z "$LND_BITCOIN_RPC_HOST" ]]; then 492 | LND_BITCOIN_RPC_HOST="$(get_last_bitcoin_service)" 493 | fi 494 | local prev_lnd_backend="$LND_BACKEND" 495 | if [[ -z "$LND_BACKEND" ]]; then 496 | LND_BACKEND="$(get_last_bitcoin_backend)" 497 | fi 498 | 499 | echo_service_separator lnd "${NAME}" ${LND_COUNTER} 500 | eval_template "$TEMPLATES_DIR/lnd.yml" >> ${COMPOSE_FILE} 501 | 502 | local alias_file="$ALIASES_DIR_NAME/$NAME" 503 | eval_script_template "$TEMPLATES_DIR/lncli-alias.sh" >> "$alias_file" 504 | chmod +x "$alias_file" 505 | 506 | # point generic lncli to first lnd node 507 | local default_alias_file="$ALIASES_DIR_NAME/lncli" 508 | if [[ ! -f "$default_alias_file" ]]; then 509 | ln -s "$NAME" ${default_alias_file} 510 | fi 511 | 512 | prepare_lnd_volumes "$NAME" 513 | 514 | advance_common_counters 515 | advance_lnd_counters 516 | 517 | LND_BITCOIN_RPC_HOST="$prev_lnd_bitcoin_rpc_host" 518 | LND_BACKEND="$prev_lnd_backend" 519 | } 520 | 521 | add_btcd() { 522 | NAME=$1 523 | 524 | # generate default name if not given 525 | if [[ -z "$NAME" ]]; then 526 | advance_btcd_auto_name_counter 527 | NAME=$(gen_btcd_auto_name) 528 | fi 529 | 530 | echo_service_separator btcd "${NAME}" ${BTCD_COUNTER} 531 | eval_template "$TEMPLATES_DIR/btcd.yml" >> ${COMPOSE_FILE} 532 | 533 | local alias_file="$ALIASES_DIR_NAME/$NAME" 534 | eval_script_template "$TEMPLATES_DIR/btcctl-alias.sh" >> "$alias_file" 535 | chmod +x "$alias_file" 536 | 537 | # point generic btcctl to first btcd node 538 | local default_alias_file="$ALIASES_DIR_NAME/btcctl" 539 | if [[ ! -f "$default_alias_file" ]]; then 540 | ln -s "$NAME" ${default_alias_file} 541 | fi 542 | 543 | prepare_btcd_volumes "$NAME" 544 | 545 | advance_common_counters 546 | advance_btcd_counters 547 | 548 | LAST_BTCD_SERVICE=${NAME} 549 | LAST_BITCOIN_SERVICE=${LAST_BTCD_SERVICE} 550 | } 551 | 552 | add_bitcoind() { 553 | NAME=$1 554 | 555 | # generate default name if not given 556 | if [[ -z "$NAME" ]]; then 557 | advance_bitcoind_auto_name_counter 558 | NAME=$(gen_bitcoind_auto_name) 559 | fi 560 | 561 | echo_service_separator bitcoind "${NAME}" ${BITCOIND_COUNTER} 562 | eval_template "$TEMPLATES_DIR/bitcoind.yml" >> ${COMPOSE_FILE} 563 | 564 | local alias_file="$ALIASES_DIR_NAME/$NAME" 565 | eval_script_template "$TEMPLATES_DIR/bitcoin-cli-alias.sh" >> "$alias_file" 566 | chmod +x "$alias_file" 567 | 568 | # point generic bitcoin-cli to first bitcoind node 569 | local default_alias_file="$ALIASES_DIR_NAME/bitcoin-cli" 570 | if [[ ! -f "$default_alias_file" ]]; then 571 | ln -s "$NAME" ${default_alias_file} 572 | fi 573 | 574 | prepare_bitcoind_volumes "$NAME" 575 | 576 | advance_common_counters 577 | advance_bitcoind_counters 578 | 579 | LAST_BITCOIND_SERVICE=${NAME} 580 | LAST_BITCOIN_SERVICE=${LAST_BITCOIND_SERVICE} 581 | } 582 | 583 | add_lightning() { 584 | NAME=$1 585 | 586 | # generate default name if not given 587 | if [[ -z "$NAME" ]]; then 588 | advance_lightning_auto_name_counter 589 | NAME=$(gen_lightning_auto_name) 590 | fi 591 | 592 | # auto-provide LIGHTNING_BITCOIN_RPC_HOST if not given 593 | local prev_lightning_bitcoin_rpc_host="$LIGHTNING_BITCOIN_RPC_HOST" 594 | if [[ -z "$LIGHTNING_BITCOIN_RPC_HOST" ]]; then 595 | LIGHTNING_BITCOIN_RPC_HOST="$(get_last_bitcoin_service)" 596 | fi 597 | local prev_lightning_backend="$LIGHTNING_BACKEND" 598 | if [[ -z "$LIGHTNING_BACKEND" ]]; then 599 | LIGHTNING_BACKEND="$(get_last_bitcoin_backend)" 600 | if [[ "$LIGHTNING_BACKEND" != "bitcoind" ]]; then 601 | echo_err "lightning node '$NAME' needs bitcoind backend, add at least one bitcoind before adding lightning nodes" 602 | exit ${ERR_REQUIRE_BITCOIND} 603 | fi 604 | fi 605 | 606 | echo_service_separator lightning "${NAME}" ${LIGHTNING_COUNTER} 607 | eval_template "$TEMPLATES_DIR/lightning.yml" >> ${COMPOSE_FILE} 608 | 609 | local alias_file="$ALIASES_DIR_NAME/$NAME" 610 | eval_script_template "$TEMPLATES_DIR/lightning-cli-alias.sh" >> "$alias_file" 611 | chmod +x "$alias_file" 612 | 613 | # point generic lightning-cli to the first lightning node 614 | local default_alias_file="$ALIASES_DIR_NAME/lightning-cli" 615 | if [[ ! -f "$default_alias_file" ]]; then 616 | ln -s "$NAME" ${default_alias_file} 617 | fi 618 | 619 | prepare_lightning_volumes "$NAME" 620 | 621 | advance_common_counters 622 | advance_lightning_counters 623 | 624 | LIGHTNING_BITCOIN_RPC_HOST="$prev_lightning_bitcoin_rpc_host" 625 | LIGHTNING_BACKEND="$prev_lightning_backend" 626 | } 627 | 628 | add_eclair() { 629 | NAME=$1 630 | 631 | # generate default name if not given 632 | if [[ -z "$NAME" ]]; then 633 | advance_eclair_auto_name_counter 634 | NAME=$(gen_eclair_auto_name) 635 | fi 636 | 637 | # auto-provide ECLAIR_BITCOIN_RPC_HOST if not given 638 | local prev_eclair_bitcoin_rpc_host="$ECLAIR_BITCOIN_RPC_HOST" 639 | if [[ -z "$ECLAIR_BITCOIN_RPC_HOST" ]]; then 640 | ECLAIR_BITCOIN_RPC_HOST="$(get_last_bitcoin_service)" 641 | fi 642 | local prev_eclair_backend="$ECLAIR_BACKEND" 643 | if [[ -z "$ECLAIR_BACKEND" ]]; then 644 | ECLAIR_BACKEND="$(get_last_bitcoin_backend)" 645 | if [[ "$ECLAIR_BACKEND" != "bitcoind" ]]; then 646 | echo_err "lightning node '$NAME' needs bitcoind backend, add at least one bitcoind before adding eclair nodes" 647 | exit ${ERR_REQUIRE_BITCOIND} 648 | fi 649 | fi 650 | 651 | echo_service_separator eclair "${NAME}" ${ECLAIR_COUNTER} 652 | eval_template "$TEMPLATES_DIR/eclair.yml" >> ${COMPOSE_FILE} 653 | 654 | local alias_file="$ALIASES_DIR_NAME/$NAME" 655 | eval_script_template "$TEMPLATES_DIR/eclair-cli-alias.sh" >> "$alias_file" 656 | chmod +x "$alias_file" 657 | 658 | # point generic lncli to first eclair node 659 | local default_alias_file="$ALIASES_DIR_NAME/eclair-cli" 660 | if [[ ! -f "$default_alias_file" ]]; then 661 | ln -s "$NAME" ${default_alias_file} 662 | fi 663 | 664 | prepare_eclair_volumes "$NAME" 665 | 666 | advance_common_counters 667 | advance_eclair_counters 668 | 669 | ECLAIR_BITCOIN_RPC_HOST="$prev_eclair_bitcoin_rpc_host" 670 | ECLAIR_BACKEND="$prev_eclair_backend" 671 | } 672 | 673 | # -- public API ------------------------------------------------------------------------------------------------------------- 674 | 675 | prelude() { 676 | scaffold_simnet 677 | add_toolbox 678 | create_aliases_dir 679 | prepare_repos 680 | init_states 681 | prepare_pre_volumes 682 | prepare_tmux_script 683 | prepare_home_link 684 | eval_template "$TEMPLATES_DIR/prelude.yml" > ${COMPOSE_FILE} 685 | touch docker-compose.yml 686 | PRELUDE_DONE=1 687 | } 688 | 689 | # add [flavor] [name] ... 690 | add() { 691 | local kind=$1 692 | shift 693 | 694 | # add commands must be called AFTER prelude 695 | if [[ -z "${PRELUDE_DONE}" ]]; then 696 | echo_err_with_stack_trace "prelude not called prior calling first add" 697 | exit ${ERR_MUST_CALL_PRELUDE_FIRST} 698 | fi 699 | 700 | case "$kind" in 701 | "btcd") add_btcd "$@" ;; 702 | "lnd") add_lnd "$@" ;; 703 | "bitcoind") add_bitcoind "$@" ;; 704 | "lightningd"|"lightning"|"c-lightning") add_lightning "$@" ;; 705 | "eclair") add_eclair "$@" ;; 706 | *) echo "unsupported service '$kind', currently allowed are 'btcd' or 'lnd'" ;; 707 | esac 708 | } 709 | 710 | # -- initialization --------------------------------------------------------------------------------------------------------- 711 | 712 | init_defaults 713 | reset_counters 714 | 715 | cd "$SIMVERSE_WORKSPACE" 716 | if [[ ! -d "$SIMNET_NAME" ]]; then 717 | mkdir "$SIMNET_NAME" 718 | fi 719 | cd "$SIMNET_NAME" --------------------------------------------------------------------------------