diff --git a/README.md b/README.md index ab0c3ea..87119ef 100644 --- a/README.md +++ b/README.md @@ -1,14 +1,45 @@ -# legend-regtest-enviroment -Useful and easy docker LNbits regtest enviroment. +# setup +clone it into your lnbits-legend repository +```console +mkdir ~/repos/lnbits-legend/docker +git clone git@github.com:lnbits/legend-regtest-enviroment.git ~/repos/lnbits-legend/docker -Will spin up regtest: +``` +# usage +```console +cd ~/repos/lnbits-legend/docker +source docker-scripts.sh -* lnbits -* bitcoin-core -* lnd -* clightning -* electrs -* mempool -* boltz +# start docker-compose with logs +lnbits-regtest-start-log +# start docker-compose in background +lnbits-regtest-start -Just place the docker folder in your lnbits-legend install. To run use these instructions +# errors on startup are normal! wait at least 60 seconds +# for all services to come up before you start initializing +sleep 60 + +# initialize blockchain, +# fund lightning wallets +# connect peers +# create channels +# balance channels +lnbits-regtest-init + +# use bitcoin core, mine a block +bitcoin-cli-sim -generate 1 + +# use c-lightning nodes +lightning-cli-sim 1 newaddr # use node 1 +lightning-cli-sim 2 getinfo # use node 2 +lightning-cli-sim 3 getinfo | jq -r '.bech32' # use node 3 + +# use lnd nodes +lncli-sim 1 newaddr p2wsh +lncli-sim 2 listpeers +``` + +# lnbits debug log +```console +docker logs lnbits-legend-lnbits-1 -f +``` diff --git a/data/boltz/boltz.conf b/data/boltz/boltz.conf new file mode 100644 index 0000000..c9e9d6d --- /dev/null +++ b/data/boltz/boltz.conf @@ -0,0 +1,34 @@ +[api] +host = "boltz" +port = 9_001 + +[[pairs]] +base = "BTC" +quote = "BTC" +rate = 1 +fee = 0.5 +timeoutDelta = 1_440 + +[[currencies]] +symbol = "BTC" +network = "bitcoinRegtest" +minWalletBalance = 10_000_000 +minChannelBalance = 10_000_000 +maxSwapAmount = 4_294_967 +minSwapAmount = 10_000 +maxZeroConfAmount = 10_000_000 + +[currencies.chain] +mempoolSpace = "http://mempool-web:8080/api" +host = "bitcoind" +zmqpubrawtx = "tcp://bitcoind:29000" +zmqpubrawblock = "tcp://bitcoind:29001" +port = 18_443 +user = "lnbits" +password = "lnbits" + +[currencies.lnd] +host = "lnd-1" +port = 10_009 +certpath = "/data/lnd/tls.cert" +macaroonpath = "/data/lnd/data/chain/bitcoin/regtest/admin.macaroon" diff --git a/data/electrs/config.toml b/data/electrs/config.toml new file mode 100644 index 0000000..962fdae --- /dev/null +++ b/data/electrs/config.toml @@ -0,0 +1,3 @@ +network="regtest" +auth="lnbits:lnbits" +wait_duration="45s" diff --git a/docker-compose.yml b/docker-compose.yml new file mode 100644 index 0000000..65a0c8b --- /dev/null +++ b/docker-compose.yml @@ -0,0 +1,153 @@ +version: "3.7" +services: + lnbits: + hostname: lnbits + image: lnbitsdocker/lnbits-legend + restart: on-failure + user: "0:0" + entrypoint: "sh -c 'sleep 30; uvicorn lnbits.__main__:app --port 5000 --host lnbits --reload'" + environment: + HOST: lnbits + LNBITS_BACKEND_WALLET_CLASS: "LndRestWallet" + LNBITS_DATA_FOLDER: "./data" + LND_REST_ENDPOINT: "https://lnd-2:8081/" + LND_REST_CERT: "./lnd/tls.cert" + LND_REST_MACAROON: "./lnd/data/chain/bitcoin/regtest/admin.macaroon" + ports: + - 5000:5000 + volumes: + - ../lnbits:/app/lnbits + - lnbits-data:/app/data + - ./data/lnd-2:/app/lnd:uid=1000,gid=1000 + + boltz: + hostname: boltz + image: boltz/backend + entrypoint: "sh -c 'sleep 40; /boltz-backend/bin/boltzd'" + ports: + - 9000:9000 + - 9001:9001 + volumes: + - ./data/lnd-1:/data/lnd/ + - ./data/boltz/:/root/.boltz/ + + bitcoind: + hostname: bitcoind + image: boltz/bitcoin-core:22.0 + command: "-regtest -fallbackfee=0.00000253 -zmqpubrawtx=tcp://0.0.0.0:29000 -zmqpubrawblock=tcp://0.0.0.0:29001 -txindex -rpcallowip=0.0.0.0/0 -rpcbind=0.0.0.0 -rpcuser=lnbits -rpcpassword=lnbits" + expose: + - 29000 + - 29001 + - 18443 + - 18444 + + clightning-1: + hostname: clightning-1 + image: michael1011/cln:latest + entrypoint: "sh -c 'sleep 15 && lightningd --network regtest --bind-addr=0.0.0.0:9735 --bitcoin-rpcconnect=bitcoind --bitcoin-rpcport=18443 --bitcoin-rpcuser=lnbits --bitcoin-rpcpassword=lnbits'" + expose: + - 9735 + volumes: + - ./data/clightning-1:/root/.lightning/ + + clightning-2: + hostname: clightning-2 + image: michael1011/cln:latest + entrypoint: "sh -c 'sleep 15 && lightningd --network regtest --bind-addr=0.0.0.0:9735 --bitcoin-rpcconnect=bitcoind --bitcoin-rpcport=18443 --bitcoin-rpcuser=lnbits --bitcoin-rpcpassword=lnbits'" + expose: + - 9735 + volumes: + - ./data/clightning-2:/root/.lightning/ + + clightning-3: + hostname: clightning-3 + image: michael1011/cln:latest + entrypoint: "sh -c 'sleep 15 && lightningd --network regtest --bind-addr=0.0.0.0:9735 --bitcoin-rpcconnect=bitcoind --bitcoin-rpcport=18443 --bitcoin-rpcuser=lnbits --bitcoin-rpcpassword=lnbits'" + expose: + - 9735 + volumes: + - ./data/clightning-3:/root/.lightnind/ + + lnd-1: + hostname: lnd-1 + depends_on: + - bitcoind + image: boltz/lnd:0.14.2-beta + restart: on-failure + entrypoint: "sh -c 'sleep 20; lnd --listen=lnd-1:9735 --rpclisten=lnd-1:10009 --restlisten=lnd-1:8081 --bitcoin.active --bitcoin.regtest --bitcoin.node=bitcoind --bitcoind.rpchost=bitcoind --bitcoind.zmqpubrawtx=bitcoind:29000 --bitcoind.zmqpubrawblock=bitcoind:29001 --bitcoind.rpcuser=lnbits --bitcoind.rpcpass=lnbits --noseedbackup --protocol.wumbo-channels'" + expose: + - 8081 + - 9735 + - 10009 + volumes: + - ./data/lnd-1:/root/.lnd/ + + lnd-2: + hostname: lnd-2 + depends_on: + - bitcoind + image: boltz/lnd:0.14.2-beta + restart: on-failure + entrypoint: "sh -c 'sleep 20; lnd --listen=lnd-2:9735 --rpclisten=lnd-2:10009 --restlisten=lnd-2:8081 --bitcoin.active --bitcoin.regtest --bitcoin.node=bitcoind --bitcoind.rpchost=bitcoind --bitcoind.zmqpubrawtx=bitcoind:29000 --bitcoind.zmqpubrawblock=bitcoind:29001 --bitcoind.rpcuser=lnbits --bitcoind.rpcpass=lnbits --noseedbackup --protocol.wumbo-channels'" + expose: + - 8081 + - 9735 + - 10009 + volumes: + - ./data/lnd-2:/root/.lnd/ + + electrs: + depends_on: + - bitcoind + hostname: electrs + image: getumbrel/electrs:latest + environment: + ELECTRS_ELECTRUM_RPC_ADDR: "electrs:50001" + ELECTRS_DAEMON_RPC_ADDR: "bitcoind:18443" + ELECTRS_DAEMON_P2P_ADDR: "bitcoind:18444" + entrypoint: "sh -c 'sleep 15 && electrs'" + ports: + - 50001:50001 + volumes: + - ./data/electrs/:/data/.electrs/ + + mempool-web: + restart: on-failure + environment: + FRONTEND_HTTP_PORT: "8080" + BACKEND_MAINNET_HTTP_HOST: "mempool-api" + image: mempool/frontend:latest + ports: + - 8080:8080 + + mempool-api: + depends_on: + - electrs + environment: + MEMPOOL_BACKEND: "electrum" + ELECTRUM_HOST: electrs + ELECTRUM_PORT: "50001" + ELECTRUM_TLS_ENABLED: "false" + CORE_RPC_HOST: bitcoind + CORE_RPC_PORT: "18443" + CORE_RPC_USERNAME: "lnbits" + CORE_RPC_PASSWORD: "lnbits" + DATABASE_ENABLED: "true" + DATABASE_HOST: "mempool-db" + DATABASE_DATABASE: "mempool" + DATABASE_USERNAME: "mempool" + DATABASE_PASSWORD: "mempool" + STATISTICS_ENABLED: "true" + image: mempool/backend:latest + restart: on-failure + + mempool-db: + environment: + MYSQL_DATABASE: "mempool" + MYSQL_USER: "mempool" + MYSQL_PASSWORD: "mempool" + MYSQL_ROOT_PASSWORD: "admin" + image: mariadb:10.5.8 + +volumes: + lnbits-data: diff --git a/docker-scripts.sh b/docker-scripts.sh new file mode 100644 index 0000000..0826935 --- /dev/null +++ b/docker-scripts.sh @@ -0,0 +1,142 @@ +#!/bin/sh +export COMPOSE_PROJECT_NAME=lnbits-legend + +bitcoin-cli-sim(){ + docker exec lnbits-legend-bitcoind-1 bitcoin-cli -rpcuser=lnbits -rpcpassword=lnbits -regtest $@ +} + +# args(i, cmd) +lightning-cli-sim() { + i=$1 + shift # shift first argument so we can use $@ + docker exec lnbits-legend-clightning-$i-1 lightning-cli --network regtest $@ +} + +# args(i, cmd) +lncli-sim() { + i=$1 + shift # shift first argument so we can use $@ + docker exec lnbits-legend-lnd-$i-1 lncli --network regtest --rpcserver=lnd-$i:10009 $@ +} + +# args(i) +fund_clightning_node() { + address=$(lightning-cli-sim $1 newaddr | jq -r .bech32) + echo "funding: $address on clightning-node: $1" + bitcoin-cli-sim -named sendtoaddress address=$address amount=10 fee_rate=100 > /dev/null +} + +# args(i) +fund_lnd_node() { + address=$(lncli-sim $1 newaddress p2wkh | jq -r .address) + echo "funding: $address on lnd-node: $1" + bitcoin-cli-sim -named sendtoaddress address=$address amount=10 fee_rate=100 > /dev/null +} + +# args(i, j) +connect_clightning_node() { + pubkey=$(lightning-cli-sim $2 getinfo | jq -r '.id') + lightning-cli-sim $1 connect $pubkey@lnbits-legend-clightning-$2-1 +} + +lnbits-regtest-start(){ + lnbits-regtest-stop + docker compose up -d --remove-orphans +} + +lnbits-regtest-start-log(){ + lnbits-regtest-stop + docker compose up --remove-orphans +} + +lnbits-regtest-stop(){ + docker compose down --volumes + # clean up lightning node data + sudo rm -rf ./data/clightning-1 ./data/clightning-2 ./data/clightning-3 ./data/lnd-1 ./data/lnd-2 ./data/boltz/boltz.db + # recreate lightning node data folders preventing permission errors + mkdir ./data/clightning-1 ./data/clightning-2 ./data/clightning-3 ./data/lnd-1 ./data/lnd-2 +} + +lnbits-regtest-restart(){ + lnbits-regtest-stop + lnbits-regtest-start +} + +lnbits-regtest-init(){ + echo "init_bitcoin_wallet..." + bitcoin-cli-sim createwallet lnbits || bitcoin-cli-sim loadwallet lnbits echo "mining 150 blocks..." + bitcoin-cli-sim -generate 150 > /dev/null + + # create 10 UTXOs for each node + for i in 0 1 2 3 4 5 6 7 8 9; do + fund_clightning_node 1 + fund_clightning_node 2 + fund_clightning_node 3 + fund_lnd_node 1 + fund_lnd_node 2 + done + + echo "mining 5 blocks... and waiting for the nodes to catch up" + bitcoin-cli-sim -generate 5 > /dev/null + wait-for-lnd-sync 1 + wait-for-lnd-sync 2 + + channel_size=16000000 # 0.016 btc + balance_size_msat=7000000000 # 0.07 btc + + # open channels 1 -> 2, 2 -> 3, 3 -> 1 + connect_clightning_node 1 3 + lightning-cli-sim 1 fundchannel -k id=$(connect_clightning_node 1 2 | jq -r '.id') amount=$channel_size push_msat=$balance_size_msat + connect_clightning_node 2 1 + lightning-cli-sim 2 fundchannel -k id=$(connect_clightning_node 2 3 | jq -r '.id') amount=$channel_size push_msat=$balance_size_msat + connect_clightning_node 3 2 + lightning-cli-sim 3 fundchannel -k id=$(connect_clightning_node 3 1 | jq -r '.id') amount=$channel_size push_msat=$balance_size_msat + + # lnd node for boltz + lncli-sim 1 connect $(lightning-cli-sim 1 getinfo | jq -r '.id')@lnbits-legend-clightning-1-1 + lncli-sim 1 openchannel $(lncli-sim 1 listpeers | jq -r '.peers[0].pub_key') $channel_size 8000000 + + # lnd doesnt like more than 1 pending channel? + bitcoin-cli-sim -generate 10 > /dev/null + echo "waiting for lnd to catch up..." + wait-for-lnd-channel 1 + + # fund lnbits lnd channel + lncli-sim 1 connect $(lncli-sim 2 getinfo | jq -r '.identity_pubkey')@lnbits-legend-lnd-2-1 + lncli-sim 1 openchannel $(lncli-sim 1 listpeers | jq -r '.peers[1].pub_key') $channel_size 8000000 + + bitcoin-cli-sim -generate 10 > /dev/null + echo "waiting for lnd to catch up..." + wait-for-lnd-channel 1 + + + # lnd node for lnbits + lncli-sim 2 connect $(lightning-cli-sim 1 getinfo | jq -r '.id')@lnbits-legend-clightning-1-1 + lncli-sim 2 openchannel $(lncli-sim 2 listpeers | jq -r '.peers[0].pub_key') $channel_size 8000000 + + echo "waiting for lnd to catch up..." + bitcoin-cli-sim -generate 10 > /dev/null + wait-for-lnd-channel 2 + + # TODO: eclair nodes? +} + +wait-for-lnd-channel(){ + while true; do + pending=$(lncli-sim $1 pendingchannels | jq -r '.pending_open_channels | length') + if [[ "$pending" == "0" ]]; then + break + fi + sleep 1 + done +} + +wait-for-lnd-sync(){ + while true; do + if [[ "$(lncli-sim $1 getinfo 2>&1 | jq -r '.synced_to_chain')" == "true" ]]; then + break + fi + sleep 1 + done + sleep 5 +} diff --git a/docker/README.md b/docker/README.md deleted file mode 100644 index b1b7161..0000000 --- a/docker/README.md +++ /dev/null @@ -1 +0,0 @@ -init