From 9e928e2097e55259bf8b61ed3690d1902538fa3b Mon Sep 17 00:00:00 2001 From: Erik Arvstedt Date: Fri, 16 Oct 2020 17:42:57 +0200 Subject: [PATCH 01/23] bitcoind: add regtest support Remove unsupported option 'testnet'. --- modules/bitcoind.nix | 17 ++++++++++++++--- 1 file changed, 14 insertions(+), 3 deletions(-) diff --git a/modules/bitcoind.nix b/modules/bitcoind.nix index 3b1e5d1..683b08f 100644 --- a/modules/bitcoind.nix +++ b/modules/bitcoind.nix @@ -11,7 +11,10 @@ let # We're already logging via journald nodebuglogfile=1 - ${optionalString cfg.testnet "testnet=1"} + ${optionalString cfg.regtest '' + regtest=1 + [regtest] + ''} ${optionalString (cfg.dbCache != null) "dbcache=${toString cfg.dbCache}"} prune=${toString cfg.prune} ${optionalString (cfg.sysperms != null) "sysperms=${if cfg.sysperms then "1" else "0"}"} @@ -159,10 +162,18 @@ in { Allow JSON-RPC connections from specified source. ''; }; - testnet = mkOption { + regtest = mkOption { type = types.bool; default = false; - description = "Whether to use the test chain."; + description = "Enable regtest mode."; + }; + network = mkOption { + readOnly = true; + default = if cfg.regtest then "regtest" else "mainnet"; + }; + makeNetworkName = mkOption { + readOnly = true; + default = mainnet: regtest: if cfg.regtest then regtest else mainnet; }; port = mkOption { type = types.nullOr types.port; From ddadaed3da6e3e4266ca78d3f5f3faf66f48bd21 Mon Sep 17 00:00:00 2001 From: Erik Arvstedt Date: Fri, 16 Oct 2020 17:42:58 +0200 Subject: [PATCH 02/23] clightning: always use bind-addr in config bind-addr can't be null. --- modules/clightning.nix | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/clightning.nix b/modules/clightning.nix index 50dc7c0..7c60c93 100644 --- a/modules/clightning.nix +++ b/modules/clightning.nix @@ -11,7 +11,7 @@ let bitcoin-datadir=${config.services.bitcoind.dataDir} ${optionalString (cfg.proxy != null) "proxy=${cfg.proxy}"} always-use-proxy=${if cfg.always-use-proxy then "true" else "false"} - ${optionalString (cfg.bind-addr != null) "bind-addr=${cfg.bind-addr}:${toString cfg.bindport}"} + bind-addr=${cfg.bind-addr}:${toString cfg.bindport} ${optionalString (cfg.bitcoin-rpcconnect != null) "bitcoin-rpcconnect=${cfg.bitcoin-rpcconnect}"} bitcoin-rpcuser=${config.services.bitcoind.rpc.users.public.name} rpc-file-mode=0660 From abd32cde3004175550b8987addfce94518550904 Mon Sep 17 00:00:00 2001 From: Erik Arvstedt Date: Fri, 16 Oct 2020 17:42:59 +0200 Subject: [PATCH 03/23] clightning: enable config file read access for group Enables lightning-cli group access when nonstandard config options are set. --- modules/clightning.nix | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/clightning.nix b/modules/clightning.nix index 7c60c93..3cb4131 100644 --- a/modules/clightning.nix +++ b/modules/clightning.nix @@ -123,7 +123,7 @@ in { chown -R '${cfg.user}:${cfg.group}' '${cfg.dataDir}' # The RPC socket has to be removed otherwise we might have stale sockets rm -f ${cfg.dataDir}/bitcoin/lightning-rpc - chmod 600 ${cfg.dataDir}/config + chmod 640 ${cfg.dataDir}/config echo "bitcoin-rpcpassword=$(cat ${config.nix-bitcoin.secretsDir}/bitcoin-rpcpassword-public)" >> '${cfg.dataDir}/config' ${optionalString cfg.announce-tor "echo announce-addr=$(cat /var/lib/onion-chef/clightning/clightning) >> '${cfg.dataDir}/config'"} ''; From c24ac5d3633fbd55ab3c8fa4540a11313be85d85 Mon Sep 17 00:00:00 2001 From: Erik Arvstedt Date: Fri, 16 Oct 2020 17:43:00 +0200 Subject: [PATCH 04/23] clightning: remove redundant option 'bitcoin-rpcconnect' --- modules/clightning.nix | 8 ++------ modules/netns-isolation.nix | 5 +---- 2 files changed, 3 insertions(+), 10 deletions(-) diff --git a/modules/clightning.nix b/modules/clightning.nix index 3cb4131..cb4cb5e 100644 --- a/modules/clightning.nix +++ b/modules/clightning.nix @@ -12,7 +12,8 @@ let ${optionalString (cfg.proxy != null) "proxy=${cfg.proxy}"} always-use-proxy=${if cfg.always-use-proxy then "true" else "false"} bind-addr=${cfg.bind-addr}:${toString cfg.bindport} - ${optionalString (cfg.bitcoin-rpcconnect != null) "bitcoin-rpcconnect=${cfg.bitcoin-rpcconnect}"} + bitcoin-rpcconnect=${builtins.elemAt config.services.bitcoind.rpcbind 0} + bitcoin-rpcport=${toString config.services.bitcoind.rpc.port} bitcoin-rpcuser=${config.services.bitcoind.rpc.users.public.name} rpc-file-mode=0660 ${cfg.extraConfig} @@ -61,11 +62,6 @@ in { default = false; description = "Announce clightning Tor Hidden Service"; }; - bitcoin-rpcconnect = mkOption { - type = types.nullOr types.str; - default = null; - description = "The bitcoind RPC host to connect to."; - }; dataDir = mkOption { type = types.path; default = "/var/lib/clightning"; diff --git a/modules/netns-isolation.nix b/modules/netns-isolation.nix index a85d3db..07360be 100644 --- a/modules/netns-isolation.nix +++ b/modules/netns-isolation.nix @@ -267,10 +267,7 @@ in { }; systemd.services.bitcoind-import-banlist.serviceConfig.NetworkNamespacePath = "/var/run/netns/nb-bitcoind"; - services.clightning = { - bitcoin-rpcconnect = netns.bitcoind.address; - bind-addr = netns.clightning.address; - }; + services.clightning.bind-addr = netns.clightning.address; services.lnd = { listen = netns.lnd.address; From 0f32f3c99eaedb6bad77523796d46aa8f4bb9017 Mon Sep 17 00:00:00 2001 From: Erik Arvstedt Date: Fri, 16 Oct 2020 17:43:01 +0200 Subject: [PATCH 05/23] clightning: add regtest support --- modules/clightning.nix | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/modules/clightning.nix b/modules/clightning.nix index cb4cb5e..2c32adf 100644 --- a/modules/clightning.nix +++ b/modules/clightning.nix @@ -6,8 +6,9 @@ let cfg = config.services.clightning; inherit (config) nix-bitcoin-services; onion-chef-service = (if cfg.announce-tor then [ "onion-chef.service" ] else []); + network = config.services.bitcoind.makeNetworkName "bitcoin" "regtest"; configFile = pkgs.writeText "config" '' - network=bitcoin + network=${network} bitcoin-datadir=${config.services.bitcoind.dataDir} ${optionalString (cfg.proxy != null) "proxy=${cfg.proxy}"} always-use-proxy=${if cfg.always-use-proxy then "true" else "false"} @@ -135,11 +136,11 @@ in { ); # Wait until the rpc socket appears postStart = '' - while [[ ! -e ${cfg.dataDir}/bitcoin/lightning-rpc ]]; do + while [[ ! -e ${cfg.dataDir}/${network}/lightning-rpc ]]; do sleep 0.1 done # Needed to enable lightning-cli for users with group 'clightning' - chmod g+x ${cfg.dataDir}/bitcoin + chmod g+x ${cfg.dataDir}/${network} ''; }; }; From 127b186c3cd9df03f6408940ba2dbd4d5001e93c Mon Sep 17 00:00:00 2001 From: Erik Arvstedt Date: Fri, 16 Oct 2020 17:43:02 +0200 Subject: [PATCH 06/23] spark-wallet: simplify start script Also: - quote paths - use long form args --- modules/spark-wallet.nix | 30 ++++++++++++++++-------------- 1 file changed, 16 insertions(+), 14 deletions(-) diff --git a/modules/spark-wallet.nix b/modules/spark-wallet.nix index cd2a860..1ef8d56 100644 --- a/modules/spark-wallet.nix +++ b/modules/spark-wallet.nix @@ -6,19 +6,21 @@ let cfg = config.services.spark-wallet; inherit (config) nix-bitcoin-services; onion-chef-service = (if cfg.onion-service then [ "onion-chef.service" ] else []); - run-spark-wallet = pkgs.writeScript "run-spark-wallet" '' - CMD="${pkgs.nix-bitcoin.spark-wallet}/bin/spark-wallet --ln-path ${cfg.ln-path} --host ${cfg.host} -Q -k -c ${config.nix-bitcoin.secretsDir}/spark-wallet-login ${cfg.extraArgs}" - ${optionalString cfg.onion-service - '' - echo Getting onion hostname - CMD="$CMD --public-url http://$(cat /var/lib/onion-chef/spark-wallet/spark-wallet)" - '' - } - # Use rate provide wasabi because default (bitstamp) doesn't accept - # connections through Tor and add proxy for rate lookup. - CMD="$CMD --rate-provider wasabi --proxy socks5h://${config.services.tor.client.socksListenAddress}" - echo Running $CMD - $CMD + + # Use wasabi rate provider because the default (bitstamp) doesn't accept + # connections through Tor + torRateProvider = "--rate-provider wasabi --proxy socks5h://${config.services.tor.client.socksListenAddress}"; + startScript = '' + ${optionalString cfg.onion-service '' + publicURL="--public-url http://$(cat /var/lib/onion-chef/spark-wallet/spark-wallet)" + ''} + exec ${pkgs.nix-bitcoin.spark-wallet}/bin/spark-wallet \ + --ln-path '${cfg.ln-path}' \ + --host ${cfg.host} \ + --config '${config.nix-bitcoin.secretsDir}/spark-wallet-login' \ + ${torRateProvider} \ + $publicURL \ + --pairing-qr --print-key ${cfg.extraArgs} ''; in { options.services.spark-wallet = { @@ -84,8 +86,8 @@ in { wantedBy = [ "multi-user.target" ]; requires = [ "clightning.service" ] ++ onion-chef-service; after = [ "clightning.service" ] ++ onion-chef-service; + script = startScript; serviceConfig = nix-bitcoin-services.defaultHardening // { - ExecStart = "${pkgs.bash}/bin/bash ${run-spark-wallet}"; User = "spark-wallet"; Restart = "on-failure"; RestartSec = "10s"; From 47d611b5ef1ecb2826061f4970141a3c0346f70d Mon Sep 17 00:00:00 2001 From: Erik Arvstedt Date: Fri, 16 Oct 2020 17:43:03 +0200 Subject: [PATCH 07/23] spark-wallet: use tor rate provider only when enforceTor --- modules/spark-wallet.nix | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/spark-wallet.nix b/modules/spark-wallet.nix index 1ef8d56..9296359 100644 --- a/modules/spark-wallet.nix +++ b/modules/spark-wallet.nix @@ -18,7 +18,7 @@ let --ln-path '${cfg.ln-path}' \ --host ${cfg.host} \ --config '${config.nix-bitcoin.secretsDir}/spark-wallet-login' \ - ${torRateProvider} \ + ${optionalString cfg.enforceTor torRateProvider} \ $publicURL \ --pairing-qr --print-key ${cfg.extraArgs} ''; From 937aee00629393847a60871bb758995ee2825cce Mon Sep 17 00:00:00 2001 From: Erik Arvstedt Date: Fri, 16 Oct 2020 17:43:04 +0200 Subject: [PATCH 08/23] spark-wallet: add regtest support --- modules/clightning.nix | 11 ++++++++--- modules/spark-wallet.nix | 9 +-------- 2 files changed, 9 insertions(+), 11 deletions(-) diff --git a/modules/clightning.nix b/modules/clightning.nix index 2c32adf..d33aac0 100644 --- a/modules/clightning.nix +++ b/modules/clightning.nix @@ -68,6 +68,11 @@ in { default = "/var/lib/clightning"; description = "The data directory for clightning."; }; + networkDir = mkOption { + readOnly = true; + default = "${cfg.dataDir}/${network}"; + description = "The network data directory."; + }; extraConfig = mkOption { type = types.lines; default = ""; @@ -119,7 +124,7 @@ in { cp ${configFile} ${cfg.dataDir}/config chown -R '${cfg.user}:${cfg.group}' '${cfg.dataDir}' # The RPC socket has to be removed otherwise we might have stale sockets - rm -f ${cfg.dataDir}/bitcoin/lightning-rpc + rm -f ${cfg.networkDir}/lightning-rpc chmod 640 ${cfg.dataDir}/config echo "bitcoin-rpcpassword=$(cat ${config.nix-bitcoin.secretsDir}/bitcoin-rpcpassword-public)" >> '${cfg.dataDir}/config' ${optionalString cfg.announce-tor "echo announce-addr=$(cat /var/lib/onion-chef/clightning/clightning) >> '${cfg.dataDir}/config'"} @@ -136,11 +141,11 @@ in { ); # Wait until the rpc socket appears postStart = '' - while [[ ! -e ${cfg.dataDir}/${network}/lightning-rpc ]]; do + while [[ ! -e ${cfg.networkDir}/lightning-rpc ]]; do sleep 0.1 done # Needed to enable lightning-cli for users with group 'clightning' - chmod g+x ${cfg.dataDir}/${network} + chmod g+x ${cfg.networkDir} ''; }; }; diff --git a/modules/spark-wallet.nix b/modules/spark-wallet.nix index 9296359..af3760f 100644 --- a/modules/spark-wallet.nix +++ b/modules/spark-wallet.nix @@ -15,7 +15,7 @@ let publicURL="--public-url http://$(cat /var/lib/onion-chef/spark-wallet/spark-wallet)" ''} exec ${pkgs.nix-bitcoin.spark-wallet}/bin/spark-wallet \ - --ln-path '${cfg.ln-path}' \ + --ln-path '${config.services.clightning.networkDir}' \ --host ${cfg.host} \ --config '${config.nix-bitcoin.secretsDir}/spark-wallet-login' \ ${optionalString cfg.enforceTor torRateProvider} \ @@ -36,13 +36,6 @@ in { default = "localhost"; description = "http(s) server listen address."; }; - ln-path = mkOption { - type = types.path; - default = "${config.services.clightning.dataDir}/bitcoin"; - description = '' - "The path of the clightning network data directory."; - ''; - }; onion-service = mkOption { type = types.bool; default = false; From b1a862922362780e465e8a0bed18dc699a13d608 Mon Sep 17 00:00:00 2001 From: Erik Arvstedt Date: Fri, 16 Oct 2020 17:43:05 +0200 Subject: [PATCH 09/23] lnd: add variable 'bitcoind' --- modules/lnd.nix | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/modules/lnd.nix b/modules/lnd.nix index c58263e..9cf87cd 100644 --- a/modules/lnd.nix +++ b/modules/lnd.nix @@ -5,8 +5,10 @@ with lib; let cfg = config.services.lnd; inherit (config) nix-bitcoin-services; - onion-chef-service = (if cfg.announce-tor then [ "onion-chef.service" ] else []); secretsDir = config.nix-bitcoin.secretsDir; + + bitcoind = config.services.bitcoind; + onion-chef-service = (if cfg.announce-tor then [ "onion-chef.service" ] else []); mainnetDir = "${cfg.dataDir}/chain/bitcoin/mainnet"; configFile = pkgs.writeText "lnd.conf" '' datadir=${cfg.dataDir} @@ -26,9 +28,9 @@ let ${optionalString (cfg.tor-socks != null) "tor.socks=${cfg.tor-socks}"} bitcoind.rpchost=${cfg.bitcoind-host} - bitcoind.rpcuser=${config.services.bitcoind.rpc.users.public.name} - bitcoind.zmqpubrawblock=${config.services.bitcoind.zmqpubrawblock} - bitcoind.zmqpubrawtx=${config.services.bitcoind.zmqpubrawtx} + bitcoind.rpcuser=${bitcoind.rpc.users.public.name} + bitcoind.zmqpubrawblock=${bitcoind.zmqpubrawblock} + bitcoind.zmqpubrawtx=${bitcoind.zmqpubrawtx} ${cfg.extraConfig} ''; @@ -148,7 +150,7 @@ in { config = mkIf cfg.enable { assertions = [ - { assertion = config.services.bitcoind.prune == 0; + { assertion = bitcoind.prune == 0; message = "lnd does not support bitcoind pruning."; } ]; From 1935c252eca5cda5450ef9ecd3a0cf1f1e83bc20 Mon Sep 17 00:00:00 2001 From: Erik Arvstedt Date: Fri, 16 Oct 2020 17:43:06 +0200 Subject: [PATCH 10/23] lnd: remove redundant option 'bitcoind-host' Also set bitcoind rpc port. --- modules/lnd.nix | 14 ++++---------- modules/netns-isolation.nix | 1 - 2 files changed, 4 insertions(+), 11 deletions(-) diff --git a/modules/lnd.nix b/modules/lnd.nix index 9cf87cd..5f74202 100644 --- a/modules/lnd.nix +++ b/modules/lnd.nix @@ -8,6 +8,7 @@ let secretsDir = config.nix-bitcoin.secretsDir; bitcoind = config.services.bitcoind; + bitcoindRpcAddress = builtins.elemAt bitcoind.rpcbind 0; onion-chef-service = (if cfg.announce-tor then [ "onion-chef.service" ] else []); mainnetDir = "${cfg.dataDir}/chain/bitcoin/mainnet"; configFile = pkgs.writeText "lnd.conf" '' @@ -27,7 +28,7 @@ let tor.active=true ${optionalString (cfg.tor-socks != null) "tor.socks=${cfg.tor-socks}"} - bitcoind.rpchost=${cfg.bitcoind-host} + bitcoind.rpchost=${bitcoindRpcAddress}:${toString bitcoind.rpc.port} bitcoind.rpcuser=${bitcoind.rpc.users.public.name} bitcoind.zmqpubrawblock=${bitcoind.zmqpubrawblock} bitcoind.zmqpubrawtx=${bitcoind.zmqpubrawtx} @@ -83,13 +84,6 @@ in { default = 8080; description = "Port on which to listen for REST connections."; }; - bitcoind-host = mkOption { - type = types.str; - default = "127.0.0.1"; - description = '' - The host that your local bitcoind daemon is listening on. - ''; - }; tor-socks = mkOption { type = types.nullOr types.str; default = null; @@ -162,8 +156,8 @@ in { ]; services.bitcoind = { - zmqpubrawblock = "tcp://${cfg.bitcoind-host}:28332"; - zmqpubrawtx = "tcp://${cfg.bitcoind-host}:28333"; + zmqpubrawblock = "tcp://${bitcoindRpcAddress}:28332"; + zmqpubrawtx = "tcp://${bitcoindRpcAddress}:28333"; }; services.onion-chef.access.lnd = if cfg.announce-tor then [ "lnd" ] else []; diff --git a/modules/netns-isolation.nix b/modules/netns-isolation.nix index 07360be..aa664cd 100644 --- a/modules/netns-isolation.nix +++ b/modules/netns-isolation.nix @@ -279,7 +279,6 @@ in { "${netns.lnd.address}" "127.0.0.1" ]; - bitcoind-host = netns.bitcoind.address; cliExec = mkCliExec "lnd"; }; From 75ec85bea209973f56f1f363cf7bb56e39aa8ec2 Mon Sep 17 00:00:00 2001 From: Erik Arvstedt Date: Fri, 16 Oct 2020 17:43:07 +0200 Subject: [PATCH 11/23] lnd: add regtest support --- modules/lnd.nix | 19 ++++++++++++------- 1 file changed, 12 insertions(+), 7 deletions(-) diff --git a/modules/lnd.nix b/modules/lnd.nix index 5f74202..6023170 100644 --- a/modules/lnd.nix +++ b/modules/lnd.nix @@ -10,11 +10,10 @@ let bitcoind = config.services.bitcoind; bitcoindRpcAddress = builtins.elemAt bitcoind.rpcbind 0; onion-chef-service = (if cfg.announce-tor then [ "onion-chef.service" ] else []); - mainnetDir = "${cfg.dataDir}/chain/bitcoin/mainnet"; + networkDir = "${cfg.dataDir}/chain/bitcoin/${bitcoind.network}"; configFile = pkgs.writeText "lnd.conf" '' datadir=${cfg.dataDir} logdir=${cfg.dataDir}/logs - bitcoin.mainnet=1 tlscertpath=${secretsDir}/lnd-cert tlskeypath=${secretsDir}/lnd-key @@ -22,6 +21,7 @@ let ${lib.concatMapStrings (rpclisten: "rpclisten=${rpclisten}:${toString cfg.rpcPort}\n") cfg.rpclisten} ${lib.concatMapStrings (restlisten: "restlisten=${restlisten}:${toString cfg.restPort}\n") cfg.restlisten} + bitcoin.${bitcoind.network}=1 bitcoin.active=1 bitcoin.node=bitcoind @@ -50,6 +50,11 @@ in { default = "/var/lib/lnd"; description = "The data directory for LND."; }; + networkDir = mkOption { + readOnly = true; + default = networkDir; + description = "The network data directory."; + }; listen = mkOption { type = pkgs.nix-bitcoin.lib.ipv4Address; default = "localhost"; @@ -134,7 +139,7 @@ in { # Switch user because lnd makes datadir contents readable by user only '' ${cfg.cliExec} sudo -u lnd ${cfg.package}/bin/lncli --tlscertpath ${secretsDir}/lnd-cert \ - --macaroonpath '${cfg.dataDir}/chain/bitcoin/mainnet/admin.macaroon' "$@" + --macaroonpath '${networkDir}/admin.macaroon' "$@" ''; description = "Binary to connect with the lnd instance."; }; @@ -202,7 +207,7 @@ in { chown lnd: "$mnemonic" ''}" "${nix-bitcoin-services.script '' - if [[ ! -f ${mainnetDir}/wallet.db ]]; then + if [[ ! -f ${networkDir}/wallet.db ]]; then echo Create lnd wallet ${pkgs.curl}/bin/curl -s --output /dev/null --show-error \ @@ -213,14 +218,14 @@ in { # Guarantees that RPC calls with cfg.cli succeed after the service is started echo Wait until wallet is created - while [[ ! -f ${mainnetDir}/admin.macaroon ]]; do + while [[ ! -f ${networkDir}/admin.macaroon ]]; do sleep 0.1 done else echo Unlock lnd wallet ${pkgs.curl}/bin/curl -s \ - -H "Grpc-Metadata-macaroon: $(${pkgs.xxd}/bin/xxd -ps -u -c 99999 '${mainnetDir}/admin.macaroon')" \ + -H "Grpc-Metadata-macaroon: $(${pkgs.xxd}/bin/xxd -ps -u -c 99999 '${networkDir}/admin.macaroon')" \ --cacert ${secretsDir}/lnd-cert \ -X POST \ -d "{\"wallet_password\": \"$(cat ${secretsDir}/lnd-wallet-password | tr -d '\n' | base64 -w0)\"}" \ @@ -240,7 +245,7 @@ in { echo "Create custom macaroon ${macaroon}" macaroonPath="$RUNTIME_DIRECTORY/${macaroon}.macaroon" ${pkgs.curl}/bin/curl -s \ - -H "Grpc-Metadata-macaroon: $(${pkgs.xxd}/bin/xxd -ps -u -c 99999 '${mainnetDir}/admin.macaroon')" \ + -H "Grpc-Metadata-macaroon: $(${pkgs.xxd}/bin/xxd -ps -u -c 99999 '${networkDir}/admin.macaroon')" \ --cacert ${secretsDir}/lnd-cert \ -X POST \ -d '{"permissions":[${cfg.macaroons.${macaroon}.permissions}]}' \ From 46efd141a194a6321558276943ce2f66c84d2222 Mon Sep 17 00:00:00 2001 From: Erik Arvstedt Date: Fri, 16 Oct 2020 17:43:08 +0200 Subject: [PATCH 12/23] lightning-loop: add regtest support --- modules/lightning-loop.nix | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/modules/lightning-loop.nix b/modules/lightning-loop.nix index 6260a12..af2a2fb 100644 --- a/modules/lightning-loop.nix +++ b/modules/lightning-loop.nix @@ -8,12 +8,13 @@ let secretsDir = config.nix-bitcoin.secretsDir; configFile = builtins.toFile "loop.conf" '' datadir=${cfg.dataDir} + network=${config.services.bitcoind.network} logdir=${cfg.dataDir}/logs tlscertpath=${secretsDir}/loop-cert tlskeypath=${secretsDir}/loop-key lnd.host=${builtins.elemAt config.services.lnd.rpclisten 0}:${toString config.services.lnd.rpcPort} - lnd.macaroondir=${config.services.lnd.dataDir}/chain/bitcoin/mainnet + lnd.macaroondir=${config.services.lnd.networkDir} lnd.tlspath=${secretsDir}/lnd-cert ${optionalString (cfg.proxy != null) "server.proxy=${cfg.proxy}"} From 6f4715ac2a9617b900a1e6b1eda05683722b1b2e Mon Sep 17 00:00:00 2001 From: Erik Arvstedt Date: Fri, 16 Oct 2020 17:43:09 +0200 Subject: [PATCH 13/23] electrs: add regtest support --- modules/electrs.nix | 1 + 1 file changed, 1 insertion(+) diff --git a/modules/electrs.nix b/modules/electrs.nix index 4804eb7..960186a 100644 --- a/modules/electrs.nix +++ b/modules/electrs.nix @@ -90,6 +90,7 @@ in { else "--jsonrpc-import --index-batch-size=10" } \ + --network=${bitcoind.makeNetworkName "bitcoin" "regtest"} \ --db-dir='${cfg.dataDir}' \ --daemon-dir='${bitcoind.dataDir}' \ --electrum-rpc-addr=${cfg.address}:${toString cfg.port} \ From 001f8fe8d3c617a17a47b4ba943cbea53bc07e39 Mon Sep 17 00:00:00 2001 From: Erik Arvstedt Date: Fri, 16 Oct 2020 17:43:10 +0200 Subject: [PATCH 14/23] btcpayserver: use option bitcoind.rpc.port --- modules/btcpayserver.nix | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/btcpayserver.nix b/modules/btcpayserver.nix index ab69837..a5f43ff 100644 --- a/modules/btcpayserver.nix +++ b/modules/btcpayserver.nix @@ -106,7 +106,7 @@ in { configFile = builtins.toFile "config" '' network=mainnet btcrpcuser=${cfg.bitcoind.rpc.users.btcpayserver.name} - btcrpcurl=http://${builtins.elemAt config.services.bitcoind.rpcbind 0}:8332 + btcrpcurl=http://${builtins.elemAt config.services.bitcoind.rpcbind 0}:${toString cfg.bitcoind.rpc.port} btcnodeendpoint=${config.services.bitcoind.bind}:8333 bind=${cfg.nbxplorer.bind} ''; From bd2145dc77b2ac2432e64df6427c700b7dd9585a Mon Sep 17 00:00:00 2001 From: Erik Arvstedt Date: Fri, 16 Oct 2020 17:43:11 +0200 Subject: [PATCH 15/23] btcpayserver: add 'port' option --- modules/btcpayserver.nix | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/modules/btcpayserver.nix b/modules/btcpayserver.nix index a5f43ff..c3142b3 100644 --- a/modules/btcpayserver.nix +++ b/modules/btcpayserver.nix @@ -34,6 +34,11 @@ in { default = "127.0.0.1"; description = "The address on which to bind."; }; + port = mkOption { + type = types.port; + default = 24444; + description = "Port on which to bind."; + }; enable = mkOption { # This option is only used by netns-isolation internal = true; @@ -70,6 +75,11 @@ in { default = "127.0.0.1"; description = "The address on which to bind."; }; + port = mkOption { + type = types.port; + default = 23000; + description = "Port on which to bind."; + }; lightningBackend = mkOption { type = types.nullOr (types.enum [ "clightning" "lnd" ]); default = null; @@ -109,6 +119,7 @@ in { btcrpcurl=http://${builtins.elemAt config.services.bitcoind.rpcbind 0}:${toString cfg.bitcoind.rpc.port} btcnodeendpoint=${config.services.bitcoind.bind}:8333 bind=${cfg.nbxplorer.bind} + port=${toString cfg.nbxplorer.port} ''; in { description = "Run nbxplorer"; @@ -141,9 +152,10 @@ in { network=mainnet postgres=User ID=${cfg.btcpayserver.user};Host=/run/postgresql;Database=btcpaydb socksendpoint=${cfg.tor.client.socksListenAddress} - btcexplorerurl=http://${cfg.nbxplorer.bind}:24444/ + btcexplorerurl=http://${cfg.nbxplorer.bind}:${toString cfg.nbxplorer.port}/ btcexplorercookiefile=${cfg.nbxplorer.dataDir}/Main/.cookie bind=${cfg.btcpayserver.bind} + port=${toString cfg.btcpayserver.port} '' + optionalString (cfg.btcpayserver.lightningBackend == "clightning") '' btclightning=type=clightning;server=unix:///${cfg.clightning.dataDir}/bitcoin/lightning-rpc ''); From 96b08f5d60b4a2f3dc1b65732d80707c131656fe Mon Sep 17 00:00:00 2001 From: Erik Arvstedt Date: Fri, 16 Oct 2020 17:43:12 +0200 Subject: [PATCH 16/23] btcpayserver: add regtest support --- modules/btcpayserver.nix | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/modules/btcpayserver.nix b/modules/btcpayserver.nix index c3142b3..5a6ebf0 100644 --- a/modules/btcpayserver.nix +++ b/modules/btcpayserver.nix @@ -114,7 +114,7 @@ in { systemd.services.nbxplorer = let configFile = builtins.toFile "config" '' - network=mainnet + network=${config.services.bitcoind.network} btcrpcuser=${cfg.bitcoind.rpc.users.btcpayserver.name} btcrpcurl=http://${builtins.elemAt config.services.bitcoind.rpcbind 0}:${toString cfg.bitcoind.rpc.port} btcnodeendpoint=${config.services.bitcoind.bind}:8333 @@ -149,11 +149,11 @@ in { systemd.services.btcpayserver = let configFile = builtins.toFile "config" ('' - network=mainnet + network=${config.services.bitcoind.network} postgres=User ID=${cfg.btcpayserver.user};Host=/run/postgresql;Database=btcpaydb socksendpoint=${cfg.tor.client.socksListenAddress} btcexplorerurl=http://${cfg.nbxplorer.bind}:${toString cfg.nbxplorer.port}/ - btcexplorercookiefile=${cfg.nbxplorer.dataDir}/Main/.cookie + btcexplorercookiefile=${cfg.nbxplorer.dataDir}/${config.services.bitcoind.makeNetworkName "Main" "RegTest"}/.cookie bind=${cfg.btcpayserver.bind} port=${toString cfg.btcpayserver.port} '' + optionalString (cfg.btcpayserver.lightningBackend == "clightning") '' From 848c4c6eda77ecfdf74bb18bc6b37636cff2fc97 Mon Sep 17 00:00:00 2001 From: Erik Arvstedt Date: Fri, 16 Oct 2020 17:43:13 +0200 Subject: [PATCH 17/23] joinmarket: add variable 'bitcoind' --- modules/joinmarket.nix | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/modules/joinmarket.nix b/modules/joinmarket.nix index 752c0dc..f534750 100644 --- a/modules/joinmarket.nix +++ b/modules/joinmarket.nix @@ -7,6 +7,7 @@ let inherit (config) nix-bitcoin-services; secretsDir = config.nix-bitcoin.secretsDir; + inherit (config.services) bitcoind; torAddress = builtins.head (builtins.split ":" config.services.tor.client.socksListenAddress); configFile = builtins.toFile "config" '' # Based on https://github.com/JoinMarket-Org/joinmarket-clientserver/blob/master/jmclient/jmclient/configure.py @@ -19,9 +20,9 @@ let [BLOCKCHAIN] blockchain_source = bitcoin-rpc network = mainnet - rpc_host = ${builtins.elemAt config.services.bitcoind.rpcbind 0} + rpc_host = ${builtins.elemAt bitcoind.rpcbind 0} rpc_port = 8332 - rpc_user = ${config.services.bitcoind.rpc.users.privileged.name} + rpc_user = ${bitcoind.rpc.users.privileged.name} @@RPC_PASSWORD@@ [MESSAGING:server1] From 031df4231fbb7e4d8c82646cebdf4b7a801ed5b2 Mon Sep 17 00:00:00 2001 From: Erik Arvstedt Date: Fri, 16 Oct 2020 17:43:14 +0200 Subject: [PATCH 18/23] joinmarket: move comment out of config file --- modules/joinmarket.nix | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/joinmarket.nix b/modules/joinmarket.nix index f534750..b2abaed 100644 --- a/modules/joinmarket.nix +++ b/modules/joinmarket.nix @@ -9,8 +9,8 @@ let inherit (config.services) bitcoind; torAddress = builtins.head (builtins.split ":" config.services.tor.client.socksListenAddress); + # Based on https://github.com/JoinMarket-Org/joinmarket-clientserver/blob/master/jmclient/jmclient/configure.py configFile = builtins.toFile "config" '' - # Based on https://github.com/JoinMarket-Org/joinmarket-clientserver/blob/master/jmclient/jmclient/configure.py [DAEMON] no_daemon = 0 daemon_port = 27183 From 975b30c90e49ff734c6ad8417ef319b8fb38f4dd Mon Sep 17 00:00:00 2001 From: Erik Arvstedt Date: Fri, 16 Oct 2020 17:43:15 +0200 Subject: [PATCH 19/23] joinmarket: don't hardcode bitcoind rpc port --- modules/joinmarket.nix | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/joinmarket.nix b/modules/joinmarket.nix index b2abaed..0785289 100644 --- a/modules/joinmarket.nix +++ b/modules/joinmarket.nix @@ -21,7 +21,7 @@ let blockchain_source = bitcoin-rpc network = mainnet rpc_host = ${builtins.elemAt bitcoind.rpcbind 0} - rpc_port = 8332 + rpc_port = ${toString bitcoind.rpc.port} rpc_user = ${bitcoind.rpc.users.privileged.name} @@RPC_PASSWORD@@ From 06b2ec5b0293328b9a3cf7f818be19ded229d347 Mon Sep 17 00:00:00 2001 From: Erik Arvstedt Date: Fri, 16 Oct 2020 17:43:16 +0200 Subject: [PATCH 20/23] joinmarket: add regtest support --- modules/joinmarket.nix | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/modules/joinmarket.nix b/modules/joinmarket.nix index 0785289..6738478 100644 --- a/modules/joinmarket.nix +++ b/modules/joinmarket.nix @@ -19,7 +19,7 @@ let [BLOCKCHAIN] blockchain_source = bitcoin-rpc - network = mainnet + network = ${bitcoind.network} rpc_host = ${builtins.elemAt bitcoind.rpcbind 0} rpc_port = ${toString bitcoind.rpc.port} rpc_user = ${bitcoind.rpc.users.privileged.name} @@ -156,7 +156,8 @@ in { "s|@@RPC_PASSWORD@@|rpc_password = $(cat ${secretsDir}/bitcoin-rpcpassword-privileged)|" \ '${cfg.dataDir}/joinmarket.cfg' ''; - ExecStartPost = nix-bitcoin-services.privileged '' + # Generating wallets (jmclient/wallet.py) is only supported for mainnet or testnet + ExecStartPost = mkIf (bitcoind.network == "mainnet") (nix-bitcoin-services.privileged '' walletname=wallet.jmdat pw=$(cat "${secretsDir}"/jm-wallet-password) mnemonic=${secretsDir}/jm-wallet-seed @@ -171,7 +172,7 @@ in { recoveryseed=$(echo "$out" | grep 'recovery_seed') echo "$recoveryseed" | cut -d ':' -f2 > $mnemonic fi - ''; + ''); ExecStart = "${pkgs.nix-bitcoin.joinmarket}/bin/joinmarketd"; WorkingDirectory = "${cfg.dataDir}"; # The service creates 'commitmentlist' in the working dir User = "${cfg.user}"; From eb42fc8e0618188211090ca3875a83cd6cd37b87 Mon Sep 17 00:00:00 2001 From: Erik Arvstedt Date: Fri, 16 Oct 2020 17:43:17 +0200 Subject: [PATCH 21/23] test: extract test 'joinmarket-yieldgenerator' Needed for regtest scenario. --- test/tests.nix | 1 + test/tests.py | 4 ++++ 2 files changed, 5 insertions(+) diff --git a/test/tests.nix b/test/tests.nix index 7456a90..799328f 100644 --- a/test/tests.nix +++ b/test/tests.nix @@ -52,6 +52,7 @@ let testEnv = rec { environment.systemPackages = mkIfTest "btcpayserver" (with pkgs; [ openssl xxd ]); tests.joinmarket = cfg.joinmarket.enable; + tests.joinmarket-yieldgenerator = cfg.joinmarket.yieldgenerator.enable; services.joinmarket.yieldgenerator = { enable = config.services.joinmarket.enable; customParameters = '' diff --git a/test/tests.py b/test/tests.py index 6d1f2e3..7d0409a 100644 --- a/test/tests.py +++ b/test/tests.py @@ -206,6 +206,10 @@ def _(): machine.wait_until_succeeds( log_has_string("joinmarket", "P2EPDaemonServerProtocolFactory starting on 27184") ) + + +@test("joinmarket-yieldgenerator") +def _(): machine.wait_until_succeeds( log_has_string("joinmarket-yieldgenerator", "Failure to get blockheight",) ) From 1f96ca67c5eed4bdf206dc4870e4aad6c5c48d12 Mon Sep 17 00:00:00 2001 From: Erik Arvstedt Date: Fri, 16 Oct 2020 17:43:18 +0200 Subject: [PATCH 22/23] electrs test: make service shutdown optional Needed for regtest scenario. --- test/tests.nix | 3 +++ test/tests.py | 8 ++++++-- 2 files changed, 9 insertions(+), 2 deletions(-) diff --git a/test/tests.nix b/test/tests.nix index 799328f..2444245 100644 --- a/test/tests.nix +++ b/test/tests.nix @@ -105,6 +105,9 @@ let testEnv = rec { services.nix-bitcoin-webindex.enable = true; tests.secure-node = true; tests.banlist-and-restart = true; + + # Stop electrs from spamming the test log with 'WARN - wait until IBD is over' messages + tests.stop-electrs = true; }; netns = { diff --git a/test/tests.py b/test/tests.py index 7d0409a..685ccde 100644 --- a/test/tests.py +++ b/test/tests.py @@ -111,14 +111,18 @@ def _(): ) -# Impure: Stops electrs @test("electrs") def _(): assert_running("electrs") wait_for_open_port(ip("electrs"), 4224) # prometeus metrics provider # Check RPC connection to bitcoind machine.wait_until_succeeds(log_has_string("electrs", "NetworkInfo")) - # Stop electrs from spamming the test log with 'wait for bitcoind sync' messages + + +# Impure: Stops electrs +# Stop electrs from spamming the test log with 'WARN - wait until IBD is over' messages +@test("stop-electrs") +def _(): succeed("systemctl stop electrs") From 9951f10e745948210e217d4b0f0cefc147ef8769 Mon Sep 17 00:00:00 2001 From: Erik Arvstedt Date: Fri, 16 Oct 2020 17:43:19 +0200 Subject: [PATCH 23/23] test: add scenario 'regtest' --- test/run-tests.sh | 1 + test/tests.nix | 32 ++++++++++++++++++++++++++++++++ test/tests.py | 21 +++++++++++++++++++++ 3 files changed, 54 insertions(+) diff --git a/test/run-tests.sh b/test/run-tests.sh index 0b0197c..0776b40 100755 --- a/test/run-tests.sh +++ b/test/run-tests.sh @@ -181,6 +181,7 @@ all() { scenario=default buildTest "$@" scenario=netns buildTest "$@" scenario=full buildTest "$@" + scenario=regtest buildTest "$@" } build() { diff --git a/test/tests.nix b/test/tests.nix index 2444245..634b97f 100644 --- a/test/tests.nix +++ b/test/tests.nix @@ -120,6 +120,38 @@ let testEnv = rec { tests.backups = mkForce false; }; + # All regtest-enabled services + regtest = { + imports = [ scenarios.regtestBase ]; + services.clightning.enable = true; + services.spark-wallet.enable = true; + services.lnd.enable = true; + services.lightning-loop.enable = true; + services.electrs.enable = true; + services.btcpayserver.enable = true; + services.joinmarket.enable = true; + }; + + regtestBase = { + tests.regtest = true; + + services.bitcoind.regtest = true; + systemd.services.bitcoind.postStart = mkAfter '' + cli=${config.services.bitcoind.cli}/bin/bitcoin-cli + address=$($cli getnewaddress) + $cli generatetoaddress 10 $address + ''; + + # lightning-loop contains no builtin swap server for regtest. + # Add a dummy definition. + services.lightning-loop.extraConfig = '' + server.host=localhost + ''; + + # Needs wallet support which is unavailable for regtest + services.joinmarket.yieldgenerator.enable = mkForce false; + }; + ## Examples / debug helper # Run a selection of tests in scenario 'netns' diff --git a/test/tests.py b/test/tests.py index 685ccde..94a723d 100644 --- a/test/tests.py +++ b/test/tests.py @@ -326,6 +326,27 @@ def _(): assert_no_failure("bitcoind-import-banlist") +@test("regtest") +def _(): + if "electrs" in enabled_tests: + machine.wait_until_succeeds(log_has_string("electrs", "BlockchainInfo")) + get_block_height_cmd = ( + """echo '{"method": "blockchain.headers.subscribe", "id": 0, "params": []}'""" + f" | nc -N {ip('electrs')} 50001 | jq -M .result.height" + ) + assert_full_match(get_block_height_cmd, "10\n") + if "clightning" in enabled_tests: + machine.wait_until_succeeds( + "[[ $(sudo -u operator lightning-cli getinfo | jq -M .blockheight) == 10 ]]" + ) + if "lnd" in enabled_tests: + machine.wait_until_succeeds( + "[[ $(sudo -u operator lncli getinfo | jq -M .block_height) == 10 ]]" + ) + if "lightning-loop" in enabled_tests: + machine.wait_until_succeeds(log_has_string("lightning-loop", "Connected to lnd node")) + + if "netns-isolation" in enabled_tests: def ip(name):