diff --git a/examples/configuration.nix b/examples/configuration.nix index f1030ff..c1a28e9 100644 --- a/examples/configuration.nix +++ b/examples/configuration.nix @@ -44,8 +44,10 @@ # services.clightning.announce-tor = true; ### LND - # Disable clightning and uncomment the following line in order to enable lnd, - # a lightning implementation written in Go. + # Uncomment the following line in order to enable lnd, a lightning + # implementation written in Go. In order to avoid collisions with clightning + # you must disable clightning or change the services.clightning.bindport or + # services.lnd.listenPort to a port other than 9735. # services.lnd.enable = true; # Enable this option to announce our Tor Hidden Service. By default lnd # offers outgoing functionality, but doesn't announce the Tor Hidden Service diff --git a/modules/bitcoind.nix b/modules/bitcoind.nix index c1bc1e7..9e4b306 100644 --- a/modules/bitcoind.nix +++ b/modules/bitcoind.nix @@ -27,6 +27,7 @@ let ${lib.concatMapStrings (node: "addnode=${node}\n") cfg.addnodes} # RPC server options + ${optionalString (cfg.rpcthreads != null) "rpcthreads=${toString cfg.rpcthreads}"} rpcport=${toString cfg.rpc.port} rpcwhitelistdefault=0 ${concatMapStringsSep "\n" @@ -66,7 +67,6 @@ in { default = ""; example = '' par=16 - rpcthreads=16 logips=1 ''; description = "Additional configurations to be appended to bitcoin.conf."; @@ -140,6 +140,11 @@ in { ''; }; }; + rpcthreads = mkOption { + type = types.nullOr types.ints.u16; + default = null; + description = "Set the number of threads to service RPC calls"; + }; rpcbind = mkOption { type = types.listOf types.str; default = [ "127.0.0.1" ]; diff --git a/modules/clightning.nix b/modules/clightning.nix index c7438b4..c70ad23 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}"} + ${optionalString (cfg.bind-addr != null) "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 @@ -46,10 +46,15 @@ in { ''; }; bind-addr = mkOption { - type = types.nullOr types.str; - default = null; + type = types.addCheck types.str (s: builtins.length (builtins.split ":" s) == 1); + default = "127.0.0.1"; description = "Set an IP address or UNIX domain socket to listen to"; }; + bindport = mkOption { + type = types.port; + default = 9735; + description = "Set a Port to listen to locally"; + }; announce-tor = mkOption { type = types.bool; default = false; diff --git a/modules/lnd.nix b/modules/lnd.nix index 1a3489f..48446d4 100644 --- a/modules/lnd.nix +++ b/modules/lnd.nix @@ -14,7 +14,7 @@ let tlscertpath=${secretsDir}/lnd-cert tlskeypath=${secretsDir}/lnd-key - listen=${toString cfg.listen} + listen=${toString cfg.listen}:${toString cfg.listenPort} ${lib.concatMapStrings (rpclisten: "rpclisten=${rpclisten}:${toString cfg.rpcPort}\n") cfg.rpclisten} ${lib.concatMapStrings (restlisten: "restlisten=${restlisten}:${toString cfg.restPort}\n") cfg.restlisten} @@ -47,10 +47,15 @@ in { description = "The data directory for LND."; }; listen = mkOption { - type = types.str; + type = types.addCheck types.str (s: builtins.length (builtins.split ":" s) == 1); default = "localhost"; description = "Bind to given address to listen to peer connections"; }; + listenPort = mkOption { + type = types.port; + default = 9735; + description = "Bind to given port to listen to peer connections"; + }; rpclisten = mkOption { type = types.listOf types.str; default = [ "localhost" ]; diff --git a/modules/modules.nix b/modules/modules.nix index c3965d4..f509cc8 100644 --- a/modules/modules.nix +++ b/modules/modules.nix @@ -30,10 +30,11 @@ config = { assertions = [ - # lnd.wantedBy == [] needed for `test/tests.nix` in which both clightning and lnd are enabled - { assertion = config.services.lnd.enable -> (!config.services.clightning.enable || config.systemd.services.lnd.wantedBy == []); + { assertion = (config.services.lnd.enable -> ( !config.services.clightning.enable || config.services.clightning.bindport != config.services.lnd.listenPort)); message = '' - LND and clightning can't be run in parallel because they both bind to lightning port 9735. + LND and clightning can't both bind to lightning port 9735. Either + disable LND/clightning or change services.clightning.bindPort or + services.lnd.listenPort to a port other than 9735. ''; } ]; diff --git a/modules/netns-isolation.nix b/modules/netns-isolation.nix index a010425..7016f22 100644 --- a/modules/netns-isolation.nix +++ b/modules/netns-isolation.nix @@ -70,244 +70,237 @@ in { }; }; - config = mkMerge [ - (mkIf cfg.enable { - # Prerequisites - networking.dhcpcd.denyInterfaces = [ "br0" "br-nb*" "nb-veth*" ]; - services.tor.client.socksListenAddress = "${bridgeIp}:9050"; - networking.firewall.interfaces.br0.allowedTCPPorts = [ 9050 ]; - boot.kernel.sysctl."net.ipv4.ip_forward" = true; - security.wrappers.netns-exec = { - source = "${pkgs.nix-bitcoin.netns-exec}/netns-exec"; - capabilities = "cap_sys_admin=ep"; - owner = "${config.nix-bitcoin.operatorName}"; - permissions = "u+rx,g+rx,o-rwx"; - }; + config = mkIf cfg.enable { + # Prerequisites + networking.dhcpcd.denyInterfaces = [ "br0" "br-nb*" "nb-veth*" ]; + services.tor.client.socksListenAddress = "${bridgeIp}:9050"; + networking.firewall.interfaces.br0.allowedTCPPorts = [ 9050 ]; + boot.kernel.sysctl."net.ipv4.ip_forward" = true; + security.wrappers.netns-exec = { + source = "${pkgs.nix-bitcoin.netns-exec}/netns-exec"; + capabilities = "cap_sys_admin=ep"; + owner = "${config.nix-bitcoin.operatorName}"; + permissions = "u+rx,g+rx,o-rwx"; + }; - nix-bitcoin.netns-isolation.services = { - bitcoind = { - id = 12; - }; - clightning = { - id = 13; - connections = [ "bitcoind" ]; - }; - lnd = { - id = 14; - connections = [ "bitcoind" ]; - }; - liquidd = { - id = 15; - connections = [ "bitcoind" ]; - }; - electrs = { - id = 16; - connections = [ "bitcoind" ]; - }; - spark-wallet = { - id = 17; - # communicates with clightning over lightning-rpc socket - connections = []; - }; - lightning-charge = { - id = 18; - # communicates with clightning over lightning-rpc socket - connections = []; - }; - nanopos = { - id = 19; - connections = [ "nginx" "lightning-charge" ]; - }; - recurring-donations = { - id = 20; - # communicates with clightning over lightning-rpc socket - connections = []; - }; - nginx = { - id = 21; - connections = []; - }; - lightning-loop = { - id = 22; - connections = [ "lnd" ]; + nix-bitcoin.netns-isolation.services = { + bitcoind = { + id = 12; + }; + clightning = { + id = 13; + connections = [ "bitcoind" ]; + }; + lnd = { + id = 14; + connections = [ "bitcoind" ]; + }; + liquidd = { + id = 15; + connections = [ "bitcoind" ]; + }; + electrs = { + id = 16; + connections = [ "bitcoind" ]; + }; + spark-wallet = { + id = 17; + # communicates with clightning over lightning-rpc socket + connections = []; + }; + lightning-charge = { + id = 18; + # communicates with clightning over lightning-rpc socket + connections = []; + }; + nanopos = { + id = 19; + connections = [ "nginx" "lightning-charge" ]; + }; + recurring-donations = { + id = 20; + # communicates with clightning over lightning-rpc socket + connections = []; + }; + nginx = { + id = 21; + connections = []; + }; + lightning-loop = { + id = 22; + connections = [ "lnd" ]; + }; + }; + + systemd.services = { + netns-bridge = { + description = "Create bridge"; + requiredBy = [ "tor.service" ]; + before = [ "tor.service" ]; + script = '' + ${ip} link add name br0 type bridge + ${ip} link set br0 up + ${ip} addr add ${bridgeIp}/24 brd + dev br0 + ${iptables} -w -t nat -A POSTROUTING -s 169.254.${toString cfg.addressblock}.0/24 -j MASQUERADE + ''; + preStop = '' + ${iptables} -w -t nat -D POSTROUTING -s 169.254.${toString cfg.addressblock}.0/24 -j MASQUERADE + ${ip} link del br0 + ''; + serviceConfig = { + Type = "oneshot"; + RemainAfterExit = "yes"; }; }; - systemd.services = { - netns-bridge = { - description = "Create bridge"; - requiredBy = [ "tor.service" ]; - before = [ "tor.service" ]; + bitcoind-import-banlist.serviceConfig.NetworkNamespacePath = "/var/run/netns/nb-bitcoind"; + } // + (let + makeNetnsServices = n: v: let + vethName = "nb-veth-${toString v.id}"; + netnsName = "nb-${n}"; + ipNetns = "${ip} -n ${netnsName}"; + netnsIptables = "${ip} netns exec ${netnsName} ${config.networking.firewall.package}/bin/iptables"; + in { + "${n}".serviceConfig.NetworkNamespacePath = "/var/run/netns/${netnsName}"; + + "netns-${n}" = rec { + requires = [ "netns-bridge.service" ]; + after = [ "netns-bridge.service" ]; + bindsTo = [ "${n}.service" ]; + requiredBy = bindsTo; + before = bindsTo; script = '' - ${ip} link add name br0 type bridge - ${ip} link set br0 up - ${ip} addr add ${bridgeIp}/24 brd + dev br0 - ${iptables} -w -t nat -A POSTROUTING -s 169.254.${toString cfg.addressblock}.0/24 -j MASQUERADE - ''; + ${ip} netns add ${netnsName} + ${ipNetns} link set lo up + ${ip} link add ${vethName} type veth peer name br-${vethName} + ${ip} link set ${vethName} netns ${netnsName} + ${ipNetns} addr add ${v.address}/24 dev ${vethName} + ${ip} link set br-${vethName} up + ${ipNetns} link set ${vethName} up + ${ip} link set br-${vethName} master br0 + ${ipNetns} route add default via ${bridgeIp} + ${netnsIptables} -w -P INPUT DROP + ${netnsIptables} -w -A INPUT -s 127.0.0.1,${bridgeIp},${v.address} -j ACCEPT + '' + (optionalString (config.services.${n}.enforceTor or false)) '' + ${netnsIptables} -w -P OUTPUT DROP + ${netnsIptables} -w -A OUTPUT -d 127.0.0.1,${bridgeIp},${v.address} -j ACCEPT + '' + concatMapStrings (otherNetns: let + other = netns.${otherNetns}; + in '' + ${netnsIptables} -w -A INPUT -s ${other.address} -j ACCEPT + ${netnsIptables} -w -A OUTPUT -d ${other.address} -j ACCEPT + '') v.availableNetns; preStop = '' - ${iptables} -w -t nat -D POSTROUTING -s 169.254.${toString cfg.addressblock}.0/24 -j MASQUERADE - ${ip} link del br0 + ${ip} netns delete ${netnsName} + ${ip} link del br-${vethName} ''; serviceConfig = { Type = "oneshot"; RemainAfterExit = "yes"; + ExecStartPre = "-${ip} netns delete ${netnsName}"; }; }; - - bitcoind-import-banlist.serviceConfig.NetworkNamespacePath = "/var/run/netns/nb-bitcoind"; - } // - (let - makeNetnsServices = n: v: let - vethName = "nb-veth-${toString v.id}"; - netnsName = "nb-${n}"; - ipNetns = "${ip} -n ${netnsName}"; - netnsIptables = "${ip} netns exec ${netnsName} ${config.networking.firewall.package}/bin/iptables"; - in { - "${n}".serviceConfig.NetworkNamespacePath = "/var/run/netns/${netnsName}"; - - "netns-${n}" = rec { - requires = [ "netns-bridge.service" ]; - after = [ "netns-bridge.service" ]; - bindsTo = [ "${n}.service" ]; - requiredBy = bindsTo; - before = bindsTo; - script = '' - ${ip} netns add ${netnsName} - ${ipNetns} link set lo up - ${ip} link add ${vethName} type veth peer name br-${vethName} - ${ip} link set ${vethName} netns ${netnsName} - ${ipNetns} addr add ${v.address}/24 dev ${vethName} - ${ip} link set br-${vethName} up - ${ipNetns} link set ${vethName} up - ${ip} link set br-${vethName} master br0 - ${ipNetns} route add default via ${bridgeIp} - ${netnsIptables} -w -P INPUT DROP - ${netnsIptables} -w -A INPUT -s 127.0.0.1,${bridgeIp},${v.address} -j ACCEPT - '' + (optionalString (config.services.${n}.enforceTor or false)) '' - ${netnsIptables} -w -P OUTPUT DROP - ${netnsIptables} -w -A OUTPUT -d 127.0.0.1,${bridgeIp},${v.address} -j ACCEPT - '' + concatMapStrings (otherNetns: let - other = netns.${otherNetns}; - in '' - ${netnsIptables} -w -A INPUT -s ${other.address} -j ACCEPT - ${netnsIptables} -w -A OUTPUT -d ${other.address} -j ACCEPT - '') v.availableNetns; - preStop = '' - ${ip} netns delete ${netnsName} - ${ip} link del br-${vethName} - ''; - serviceConfig = { - Type = "oneshot"; - RemainAfterExit = "yes"; - ExecStartPre = "-${ip} netns delete ${netnsName}"; - }; - }; - }; - in foldl (services: n: - services // (makeNetnsServices n netns.${n}) - ) {} (builtins.attrNames netns)); - - # bitcoin: Custom netns configs - services.bitcoind = { - bind = netns.bitcoind.address; - rpcbind = [ - "${netns.bitcoind.address}" - "127.0.0.1" - ]; - rpcallowip = [ - "127.0.0.1" - ] ++ lib.lists.concatMap (s: [ - "${netns.${s}.address}" - ]) netns.bitcoind.availableNetns; - cli = pkgs.writeScriptBin "bitcoin-cli" '' - netns-exec nb-bitcoind ${config.services.bitcoind.package}/bin/bitcoin-cli -datadir='${config.services.bitcoind.dataDir}' "$@" - ''; }; + in foldl (services: n: + services // (makeNetnsServices n netns.${n}) + ) {} (builtins.attrNames netns)); - # clightning: Custom netns configs - services.clightning = mkIf config.services.clightning.enable { - bitcoin-rpcconnect = netns.bitcoind.address; - bind-addr = "${netns.clightning.address}:${toString config.services.clightning.onionport}"; - }; + # bitcoin: Custom netns configs + services.bitcoind = { + bind = netns.bitcoind.address; + rpcbind = [ + "${netns.bitcoind.address}" + "127.0.0.1" + ]; + rpcallowip = [ + "127.0.0.1" + ] ++ lib.lists.concatMap (s: [ + "${netns.${s}.address}" + ]) netns.bitcoind.availableNetns; + cli = pkgs.writeScriptBin "bitcoin-cli" '' + netns-exec nb-bitcoind ${config.services.bitcoind.package}/bin/bitcoin-cli -datadir='${config.services.bitcoind.dataDir}' "$@" + ''; + }; - # lnd: Custom netns configs - services.lnd = mkIf config.services.lnd.enable { - listen = netns.lnd.address; - rpclisten = [ - "${netns.lnd.address}" - "127.0.0.1" - ]; - restlisten = [ - "${netns.lnd.address}" - "127.0.0.1" - ]; - bitcoind-host = netns.bitcoind.address; - cli = pkgs.writeScriptBin "lncli" - # Switch user because lnd makes datadir contents readable by user only - '' - netns-exec nb-lnd sudo -u lnd ${config.services.lnd.package}/bin/lncli --tlscertpath ${config.nix-bitcoin.secretsDir}/lnd-cert \ - --macaroonpath '${config.services.lnd.dataDir}/chain/bitcoin/mainnet/admin.macaroon' "$@" - ''; - }; + # clightning: Custom netns configs + services.clightning = mkIf config.services.clightning.enable { + bitcoin-rpcconnect = netns.bitcoind.address; + bind-addr = netns.clightning.address; + }; - # liquidd: Custom netns configs - services.liquidd = mkIf config.services.liquidd.enable { - bind = netns.liquidd.address; - rpcbind = [ - "${netns.liquidd.address}" - "127.0.0.1" - ]; - rpcallowip = [ - "127.0.0.1" - ] ++ lib.lists.concatMap (s: [ - "${netns.${s}.address}" - ]) netns.liquidd.availableNetns; - mainchainrpchost = netns.bitcoind.address; - cli = pkgs.writeScriptBin "elements-cli" '' - netns-exec nb-liquidd ${pkgs.nix-bitcoin.elementsd}/bin/elements-cli -datadir='${config.services.liquidd.dataDir}' "$@" - ''; - swap-cli = pkgs.writeScriptBin "liquidswap-cli" '' - netns-exec nb-liquidd ${pkgs.nix-bitcoin.liquid-swap}/bin/liquidswap-cli -c '${config.services.liquidd.dataDir}/elements.conf' "$@" - ''; - }; + # lnd: Custom netns configs + services.lnd = mkIf config.services.lnd.enable { + listen = netns.lnd.address; + rpclisten = [ + "${netns.lnd.address}" + "127.0.0.1" + ]; + restlisten = [ + "${netns.lnd.address}" + "127.0.0.1" + ]; + bitcoind-host = netns.bitcoind.address; + cli = pkgs.writeScriptBin "lncli" + # Switch user because lnd makes datadir contents readable by user only + '' + netns-exec nb-lnd sudo -u lnd ${config.services.lnd.package}/bin/lncli --tlscertpath ${config.nix-bitcoin.secretsDir}/lnd-cert \ + --macaroonpath '${config.services.lnd.dataDir}/chain/bitcoin/mainnet/admin.macaroon' "$@" + ''; + }; - # electrs: Custom netns configs - services.electrs = mkIf config.services.electrs.enable { - address = netns.electrs.address; - daemonrpc = "${netns.bitcoind.address}:${toString config.services.bitcoind.rpc.port}"; - }; + # liquidd: Custom netns configs + services.liquidd = mkIf config.services.liquidd.enable { + bind = netns.liquidd.address; + rpcbind = [ + "${netns.liquidd.address}" + "127.0.0.1" + ]; + rpcallowip = [ + "127.0.0.1" + ] ++ lib.lists.concatMap (s: [ + "${netns.${s}.address}" + ]) netns.liquidd.availableNetns; + mainchainrpchost = netns.bitcoind.address; + cli = pkgs.writeScriptBin "elements-cli" '' + netns-exec nb-liquidd ${pkgs.nix-bitcoin.elementsd}/bin/elements-cli -datadir='${config.services.liquidd.dataDir}' "$@" + ''; + swap-cli = pkgs.writeScriptBin "liquidswap-cli" '' + netns-exec nb-liquidd ${pkgs.nix-bitcoin.liquid-swap}/bin/liquidswap-cli -c '${config.services.liquidd.dataDir}/elements.conf' "$@" + ''; + }; - # spark-wallet: Custom netns configs - services.spark-wallet = mkIf config.services.spark-wallet.enable { - host = netns.spark-wallet.address; - extraArgs = "--no-tls"; - }; + # electrs: Custom netns configs + services.electrs = mkIf config.services.electrs.enable { + address = netns.electrs.address; + daemonrpc = "${netns.bitcoind.address}:${toString config.services.bitcoind.rpc.port}"; + }; - # lightning-charge: Custom netns configs - services.lightning-charge.host = mkIf config.services.lightning-charge.enable netns.lightning-charge.address; + # spark-wallet: Custom netns configs + services.spark-wallet = mkIf config.services.spark-wallet.enable { + host = netns.spark-wallet.address; + extraArgs = "--no-tls"; + }; - # nanopos: Custom netns configs - services.nanopos = mkIf config.services.nanopos.enable { - charged-url = "http://${netns.lightning-charge.address}:9112"; - host = netns.nanopos.address; - }; + # lightning-charge: Custom netns configs + services.lightning-charge.host = mkIf config.services.lightning-charge.enable netns.lightning-charge.address; - # nginx: Custom netns configs - services.nix-bitcoin-webindex.host = mkIf config.services.nix-bitcoin-webindex.enable netns.nginx.address; + # nanopos: Custom netns configs + services.nanopos = mkIf config.services.nanopos.enable { + charged-url = "http://${netns.lightning-charge.address}:9112"; + host = netns.nanopos.address; + }; - # loop: Custom netns configs - services.lightning-loop = mkIf config.services.lightning-loop.enable { - cli = pkgs.writeScriptBin "loop" - # Switch user because lnd makes datadir contents readable by user only - '' - netns-exec nb-lightning-loop sudo -u lnd ${config.services.lightning-loop.package}/bin/loop "$@" - ''; - }; - }) - # Custom netns config option values if netns-isolation not enabled - (mkIf (!cfg.enable) { - # clightning - services.clightning.bind-addr = "127.0.0.1:${toString config.services.clightning.onionport}"; - }) - ]; + # nginx: Custom netns configs + services.nix-bitcoin-webindex.host = mkIf config.services.nix-bitcoin-webindex.enable netns.nginx.address; + + # loop: Custom netns configs + services.lightning-loop = mkIf config.services.lightning-loop.enable { + cli = pkgs.writeScriptBin "loop" + # Switch user because lnd makes datadir contents readable by user only + '' + netns-exec nb-lightning-loop sudo -u lnd ${config.services.lightning-loop.package}/bin/loop "$@" + ''; + }; + }; } diff --git a/modules/presets/secure-node.nix b/modules/presets/secure-node.nix index 1f172ba..065bbb6 100644 --- a/modules/presets/secure-node.nix +++ b/modules/presets/secure-node.nix @@ -73,6 +73,9 @@ in { discover = false; addresstype = "bech32"; dbCache = 1000; + # higher rpcthread count due to reports that lightning implementations fail + # under high bitcoind rpc load + rpcthreads = 16; rpc.users.privileged = { name = "bitcoinrpc"; # Placeholder to be sed'd out by bitcoind preStart @@ -152,14 +155,18 @@ in { enforceTor = true; always-use-proxy = true; }; - services.tor.hiddenServices.clightning = mkIf cfg.clightning.enable (mkHiddenService { port = cfg.clightning.onionport; toHost = (builtins.head (builtins.split ":" cfg.clightning.bind-addr)); }); + services.tor.hiddenServices.clightning = mkIf cfg.clightning.enable (mkHiddenService { + port = cfg.clightning.onionport; + toHost = cfg.clightning.bind-addr; + toPort = cfg.clightning.bindport; + }); # lnd services.lnd = { tor-socks = cfg.tor.client.socksListenAddress; enforceTor = true; }; - services.tor.hiddenServices.lnd = mkIf cfg.lnd.enable (mkHiddenService { port = cfg.lnd.onionport; toHost = cfg.lnd.listen; }); + services.tor.hiddenServices.lnd = mkIf cfg.lnd.enable (mkHiddenService { port = cfg.lnd.onionport; toHost = cfg.lnd.listen; toPort = cfg.lnd.listenPort; }); # lightning-loop services.lightning-loop = { diff --git a/test/scenarios/default.py b/test/scenarios/default.py index 9efb3c6..453e3dd 100644 --- a/test/scenarios/default.py +++ b/test/scenarios/default.py @@ -25,7 +25,7 @@ def web_index(): assert_matches("curl -L localhost/store", "tshirt") -def post_clightning(): +def final(): pass @@ -35,7 +35,7 @@ extra_tests = { "lightning-charge": lightning_charge, "nanopos": nanopos, "web-index": web_index, - "post-clightning": post_clightning, + "final": final, } run_tests(extra_tests) diff --git a/test/scenarios/lib.py b/test/scenarios/lib.py index 7346dd8..8595149 100644 --- a/test/scenarios/lib.py +++ b/test/scenarios/lib.py @@ -70,6 +70,18 @@ def run_tests(extra_tests): assert_running("clightning") assert_matches("su operator -c 'lightning-cli getinfo' | jq", '"id"') + assert_running("lnd") + assert_matches("su operator -c 'lncli getinfo' | jq", '"version"') + assert_no_failure("lnd") + + succeed("systemctl start lightning-loop") + assert_matches("su operator -c 'loop --version'", "version") + # Check that lightning-loop fails with the right error, making sure + # lightning-loop can connect to lnd + machine.wait_until_succeeds( + log_has_string("lightning-loop", "chain notifier RPC isstill in the process of starting") + ) + assert_running("spark-wallet") extra_tests.pop("spark-wallet")() @@ -104,7 +116,9 @@ def run_tests(extra_tests): pre_restart = succeed("date +%s.%6N").rstrip() # Sanity-check system by restarting all services - succeed("systemctl restart bitcoind clightning spark-wallet lightning-charge nanopos liquidd") + succeed( + "systemctl restart bitcoind clightning lnd lightning-loop spark-wallet lightning-charge nanopos liquidd" + ) # Now that the bitcoind restart triggered a banlist import restart, check that # re-importing already banned addresses works @@ -113,25 +127,7 @@ def run_tests(extra_tests): ) assert_no_failure("bitcoind-import-banlist") - extra_tests.pop("post-clightning")() - - ### Test lnd - - stopped_services = "nanopos lightning-charge spark-wallet clightning" - succeed("systemctl stop " + stopped_services) - succeed("systemctl start lnd") - assert_matches("su operator -c 'lncli getinfo' | jq", '"version"') - assert_no_failure("lnd") - - ### Test loopd - - succeed("systemctl start lightning-loop") - assert_matches("su operator -c 'loop --version'", "version") - # Check that lightning-loop fails with the right error, making sure - # lightning-loop can connect to lnd - machine.wait_until_succeeds( - log_has_string("lightning-loop", "chain notifier RPC isstill in the process of starting") - ) + extra_tests.pop("final")() ### Check that all extra_tests have been run assert len(extra_tests) == 0 diff --git a/test/scenarios/withnetns.py b/test/scenarios/withnetns.py index 3ae3f0c..bc6f9f5 100644 --- a/test/scenarios/withnetns.py +++ b/test/scenarios/withnetns.py @@ -9,6 +9,7 @@ lightningcharge_ip = "169.254.1.18" nanopos_ip = "169.254.1.19" recurringdonations_ip = "169.254.1.20" nginx_ip = "169.254.1.21" +lightningloop_ip = "169.254.1.22" def electrs(): @@ -46,7 +47,7 @@ def web_index(): assert_matches("ip netns exec nb-nginx curl -L localhost/store", "tshirt") -def post_clightning(): +def final(): ping_bitcoind = "ip netns exec nb-bitcoind ping -c 1 -w 1" ping_nanopos = "ip netns exec nb-nanopos ping -c 1 -w 1" @@ -54,6 +55,7 @@ def post_clightning(): machine.succeed( "%s %s &&" % (ping_bitcoind, bitcoind_ip) + "%s %s &&" % (ping_bitcoind, clightning_ip) + + "%s %s &&" % (ping_bitcoind, lnd_ip) + "%s %s &&" % (ping_bitcoind, liquidd_ip) + "%s %s &&" % (ping_nanopos, lightningcharge_ip) + "%s %s &&" % (ping_nanopos, nanopos_ip) @@ -63,6 +65,7 @@ def post_clightning(): # Negative ping tests (non-exhaustive) machine.fail( "%s %s ||" % (ping_bitcoind, sparkwallet_ip) + + "%s %s ||" % (ping_bitcoind, lightningloop_ip) + "%s %s ||" % (ping_bitcoind, lightningcharge_ip) + "%s %s ||" % (ping_bitcoind, nanopos_ip) + "%s %s ||" % (ping_bitcoind, recurringdonations_ip) @@ -70,6 +73,7 @@ def post_clightning(): + "%s %s ||" % (ping_nanopos, bitcoind_ip) + "%s %s ||" % (ping_nanopos, clightning_ip) + "%s %s ||" % (ping_nanopos, lnd_ip) + + "%s %s ||" % (ping_nanopos, lightningloop_ip) + "%s %s ||" % (ping_nanopos, liquidd_ip) + "%s %s ||" % (ping_nanopos, electrs_ip) + "%s %s ||" % (ping_nanopos, sparkwallet_ip) @@ -94,7 +98,7 @@ extra_tests = { "lightning-charge": lightning_charge, "nanopos": nanopos, "web-index": web_index, - "post-clightning": post_clightning, + "final": final, } run_tests(extra_tests) diff --git a/test/test.nix b/test/test.nix index 640820c..fa7c64c 100644 --- a/test/test.nix +++ b/test/test.nix @@ -33,8 +33,10 @@ import ./make-test.nix rec { services.nanopos.enable = true; services.lnd.enable = true; - systemd.services.lnd.wantedBy = mkForce []; + services.lnd.listenPort = 9736; services.lightning-loop.enable = true; + # needed because we must control when lightning-loop starts so it doesn't + # fail before we run commands in the nb-lightning-loop netns systemd.services.lightning-loop.wantedBy = mkForce []; services.electrs.enable = true;