diff --git a/README.md b/README.md index 0d58630..09f494d 100644 --- a/README.md +++ b/README.md @@ -78,7 +78,6 @@ NixOS modules ([src](modules/modules.nix)) * [rebalance](https://github.com/lightningd/plugins/tree/master/rebalance): keeps your channels balanced * [trustedcoin](https://github.com/nbd-wtf/trustedcoin) ([experimental](docs/services.md#trustedcoin)): replaces bitcoind with trusted public explorers * [zmq](https://github.com/lightningd/plugins/tree/master/zmq): publishes notifications via ZeroMQ to configured endpoints - * [clightning-rest](https://github.com/Ride-The-Lightning/c-lightning-REST): REST server for clightning * [lnd](https://github.com/lightningnetwork/lnd) with support for announcing an onion service and [static channel backups](https://github.com/lightningnetwork/lnd/blob/master/docs/recovery.md) * [Lightning Loop](https://github.com/lightninglabs/loop) * [Lightning Pool](https://github.com/lightninglabs/pool) diff --git a/dev/dev-scenarios.nix b/dev/dev-scenarios.nix index 80e2ea2..e6716ca 100644 --- a/dev/dev-scenarios.nix +++ b/dev/dev-scenarios.nix @@ -66,6 +66,16 @@ with lib; onion = true; }; }; + services.clightning = { + enable = true; + plugins.clnrest = { + enable = true; + lnconnect = { + enable = true; + onion = true; + }; + }; + }; services.clightning-rest = { enable = true; lndconnect = { diff --git a/dev/topics/lndconnect-and-wireguard.sh b/dev/topics/lndconnect-and-wireguard.sh index 7f40ff0..76dc641 100644 --- a/dev/topics/lndconnect-and-wireguard.sh +++ b/dev/topics/lndconnect-and-wireguard.sh @@ -7,13 +7,15 @@ run-tests.sh -s wireguard-lndconnect-online container # 2. Test connecting via Tor # Print QR codes for lnd, clightning-rest connections via Tor c lndconnect +c lnconnect-clnrest c lndconnect-clightning -# Add these to Zeus >= 0.7.1. +# Add these to Zeus >= 0.9.0. # To explicitly check if the connection is successful, press the node logo in the top # left corner, and then "Node Info". # Debug c lndconnect --url +c lnconnect-clnrest --url c lndconnect-clightning --url # 3. Test connecting via WireGuard @@ -33,13 +35,15 @@ c nix-bitcoin-wg-connect --text # Print QR codes for lnd, clightning-rest connections via WireGuard c lndconnect-wg +c lnconnect-clnrest-wg c lndconnect-clightning-wg -# Add these to Zeus >= 0.7.1. -# To explicitly check if the connection is successful, press the node logo in the top +# Add these to Zeus >= 0.9.0. +# To explicitly check if the connection is successful, press the menu button in the top # left corner, and then "Node Info". # Debug c lndconnect-wg --url +c lnconnect-clnrest-wg --url c lndconnect-clightning-wg --url # 3.3.remove external firewall port forward, remove local port forward: @@ -55,6 +59,8 @@ c nodeinfo c lndconnect --url c lndconnect-wg --url +c lndconnect-clnrest --url +c lndconnect-clnrest-wg --url c lndconnect-clightning --url c lndconnect-clightning-wg --url diff --git a/dev/topics/rtl.sh b/dev/topics/rtl.sh index cc9c390..933504a 100644 --- a/dev/topics/rtl.sh +++ b/dev/topics/rtl.sh @@ -17,8 +17,6 @@ c systemctl status rtl c journalctl -u rtl c cat /var/lib/rtl/RTL-Config.json -c systemctl status clightning-rest - # Open webinterface. Password: a runuser -u "$(logname)" -- xdg-open "http://$ip:3000" diff --git a/docs/services.md b/docs/services.md index f4a408d..ad719cd 100644 --- a/docs/services.md +++ b/docs/services.md @@ -143,7 +143,7 @@ The default password location is `$secretsDir/rtl-password`. See: [Secrets dir](./configuration.md#secrets-dir) # Use Zeus (mobile lightning wallet) via Tor -1. Install [Zeus](https://zeusln.app) (version ≥ 0.7.1) +1. Install [Zeus](https://zeusln.app) (version ≥ 0.9.0) 2. Edit your `configuration.nix` @@ -161,9 +161,9 @@ See: [Secrets dir](./configuration.md#secrets-dir) Add the following config: ```nix - services.clightning-rest = { + services.clightning.plugins.clnrest = { enable = true; - lndconnect = { + lnconnect = { enable = true; onion = true; }; @@ -182,7 +182,7 @@ See: [Secrets dir](./configuration.md#secrets-dir) ##### For clightning ``` - lndconnect-clightning + lnconnect-clnrest ``` 5. Configure Zeus @@ -212,7 +212,7 @@ There are two ways to establish a secure, direct connection: - Connecting via WireGuard. This approach is simpler and more versatile, and is described in this guide. -1. Install [Zeus](https://zeusln.app) (version ≥ 0.7.1) and +1. Install [Zeus](https://zeusln.app) (version ≥ 0.9.0) and [WireGuard](https://www.wireguard.com/install/) on your mobile device. 2. Add the following to your `configuration.nix`: @@ -229,9 +229,11 @@ There are two ways to establish a secure, direct connection: services.lnd.lndconnect.enable = true; # For clightning - services.clightning-rest = { - enable = true; - lndconnect.enable = true; + services.clightning = { + plugins.clnrest = { + enable = true; + lnconnect.enable = true; + }; }; ``` 3. Deploy your configuration. @@ -275,7 +277,7 @@ There are two ways to establish a secure, direct connection: ##### For clightning ``` - lndconnect-clightning-wg + lnconnect-clnrest-wg ``` Configure Zeus: diff --git a/examples/configuration.nix b/examples/configuration.nix index 2e45f3a..f4871a9 100644 --- a/examples/configuration.nix +++ b/examples/configuration.nix @@ -56,15 +56,15 @@ # # == REST server # Set this to create a clightning REST onion service. - # This also adds binary `lndconnect-clightning` to the system environment. + # This also adds binary `lnconnect-clnrest` to the system environment. # This binary creates QR codes or URLs for connecting applications to clightning # via the REST onion service. # You can also connect via WireGuard instead of Tor. # See ../docs/services.md for details. # - # services.clightning-rest = { + # services.clightning.plugins.clnrest = { # enable = true; - # lndconnect = { + # lnconnect = { # enable = true; # onion = true; # }; diff --git a/modules/clightning-plugins/clnrest.nix b/modules/clightning-plugins/clnrest.nix new file mode 100644 index 0000000..a5a39ee --- /dev/null +++ b/modules/clightning-plugins/clnrest.nix @@ -0,0 +1,78 @@ +{ config, lib, pkgs, ... }: + +with lib; +let + options = { + services.clightning.plugins.clnrest = { + enable = mkOption { + type = types.bool; + default = false; + description = '' + Enable clnrest (clightning plugin). + + clnrest provides a clightning REST API, using clightning RPC calls as its backend. + It also broadcasts clightning notifications to listeners connected to its websocket server. + + See here for all available options: + https://docs.corelightning.org/docs/rest + Extra options can be set via `services.clightning.extraConfig`. + ''; + }; + address = mkOption { + type = types.str; + default = "127.0.0.1"; + description = "Address to listen for REST connections."; + }; + port = mkOption { + type = types.port; + default = 3010; + description = "REST server port."; + }; + createAdminRune = mkOption { + type = types.bool; + default = true; + description = '' + Create a rune with admin permissions at path `''${config.services.clightning.networkDir}/admin-rune`. + ''; + }; + package = mkOption { + type = types.package; + default = config.nix-bitcoin.pkgs.nbPython3Packages.clnrest; + defaultText = "config.nix-bitcoin.pkgs.nbPython3Packages.clnrest"; + description = "The package providing clnrest binaries."; + }; + }; + + # Internal read-only options used by `./nodeinfo.nix` and `./onion-services.nix` + services.clnrest = let + inherit (config.nix-bitcoin.lib) mkAlias; + in { + enable = mkAlias cfg.enable; + address = mkAlias cfg.address; + port = mkAlias cfg.port; + }; + }; + + cfg = config.services.clightning.plugins.clnrest; + inherit (config.services) clightning; + + runePath = "${clightning.networkDir}/admin-rune"; +in +{ + inherit options; + + config = mkIf cfg.enable { + services.clightning.extraConfig = '' + plugin=${cfg.package}/bin/clnrest + clnrest-host=${cfg.address} + clnrest-port=${toString cfg.port} + ''; + + systemd.services.clightning.postStart = mkIf cfg.createAdminRune (mkAfter '' + if [[ ! -e '${runePath}' ]]; then + rune=$(${clightning.cli}/bin/lightning-cli createrune | ${pkgs.jq}/bin/jq -r .rune) + install -m 640 <(echo "$rune") '${runePath}' + fi + ''); + }; +} diff --git a/modules/clightning-plugins/default.nix b/modules/clightning-plugins/default.nix index 3142008..10744cf 100644 --- a/modules/clightning-plugins/default.nix +++ b/modules/clightning-plugins/default.nix @@ -13,6 +13,7 @@ let in { imports = [ ./clboss.nix + ./clnrest.nix ./feeadjuster.nix ./trustedcoin.nix ./zmq.nix diff --git a/modules/lndconnect.nix b/modules/lndconnect.nix index 4a54782..0bd370a 100644 --- a/modules/lndconnect.nix +++ b/modules/lndconnect.nix @@ -32,6 +32,34 @@ let }; }; + services.clightning.plugins.clnrest.lnconnect = { + enable = mkOption { + type = types.bool; + default = false; + description = '' + Add a `lnconnect-clnrest` binary to the system environment which prints + connection info for clightning clients. + See: https://github.com/LN-Zap/lndconnect + + Usage: + ```bash + # Print QR code + lnconnect-clnrest + + # Print URL + lnconnect-clnrest --url + ``` + ''; + }; + onion = mkOption { + type = types.bool; + default = false; + description = '' + Create an onion service for the clnrest server, + which is used by lnconnect. + ''; + }; + }; services.clightning-rest.lndconnect = { enable = mkOption { @@ -77,14 +105,18 @@ let inherit (config.services) lnd + clightning clightning-rest; + inherit (clightning.plugins) clnrest; + mkLndconnect = { name, shebang ? "#!${pkgs.stdenv.shell} -e", isClightning ? false, + isClnrest ? false, port, - macaroonPath, + authSecretPath, enableOnion, onionService ? null, certPath ? null @@ -99,7 +131,7 @@ let ${optionalString enableOnion "--host=$(cat ${config.nix-bitcoin.onionAddresses.dataDir}/${onionService})"} \ --port=${toString port} \ ${if enableOnion || certPath == null then "--nocert" else "--tlscertpath='${certPath}'"} \ - --adminmacaroonpath='${macaroonPath}' \ + --adminmacaroonpath='${authSecretPath}' \ --configfile=/dev/null "$@" ) @@ -109,7 +141,7 @@ let # Because `macaroon` is always the last URL fragment, the # sed replacement below works correctly. '' - macaroonHex=$(${getExe pkgs.xxd} -p -u -c 99999 '${macaroonPath}') + macaroonHex=$(${getExe pkgs.xxd} -p -u -c 99999 '${authSecretPath}') url=$( echo "$url" | ${getExe pkgs.gnused} " s|^lndconnect|c-lightning-rest| @@ -119,6 +151,18 @@ let '' } + ${optionalString isClnrest + # Change URL procotcol to clnrest + '' + url=$( + echo "$url" | ${getExe pkgs.gnused} " + s|^lndconnect|clnrest| + s|macaroon=.*|rune=$(cat '${authSecretPath}')| + "; + ) + '' + } + # If --url is in args if [[ " $* " =~ " --url " ]]; then echo "$url" @@ -146,7 +190,7 @@ in { onionService = "${lnd.user}/lnd-rest"; port = lnd.restPort; certPath = lnd.certPath; - macaroonPath = "${lnd.networkDir}/admin.macaroon"; + authSecretPath = "${lnd.networkDir}/admin.macaroon"; } )]; @@ -169,6 +213,39 @@ in { }) ])) + (mkIf (clnrest.enable && clnrest.lnconnect.enable) + (mkMerge [ + { + environment.systemPackages = [( + mkLndconnect { + name = "lnconnect-clnrest"; + isClnrest = true; + enableOnion = clnrest.lnconnect.onion; + onionService = "${operatorName}/clnrest"; + port = clnrest.port; + certPath = "${clightning.networkDir}/client.pem"; + authSecretPath = "${clightning.networkDir}/admin-rune"; + } + )]; + + services.clightning.plugins.clnrest.address = mkIf (!clnrest.lnconnect.onion) "0.0.0.0"; + } + + (mkIf clnrest.lnconnect.onion { + services.tor = { + enable = true; + relay.onionServices.clnrest = nbLib.mkOnionService { + target.addr = nbLib.address clnrest.address; + target.port = clnrest.port; + port = clnrest.port; + }; + }; + # This also allows nodeinfo to show the clnrest onion address + nix-bitcoin.onionAddresses.access.${operatorName} = [ "clnrest" ]; + }) + ]) + ) + (mkIf (clightning-rest.enable && clightning-rest.lndconnect.enable) (mkMerge [ { @@ -180,7 +257,7 @@ in { onionService = "${operatorName}/clightning-rest"; port = clightning-rest.port; certPath = "${clightning-rest.dataDir}/certs/certificate.pem"; - macaroonPath = "${clightning-rest.dataDir}/certs/access.macaroon"; + authSecretPath = "${clightning-rest.dataDir}/certs/access.macaroon"; } )]; diff --git a/modules/mempool.nix b/modules/mempool.nix index fc9af10..67382da 100644 --- a/modules/mempool.nix +++ b/modules/mempool.nix @@ -138,11 +138,7 @@ let # Internal read-only options used by `./nodeinfo.nix` and `./onion-services.nix` mempool-frontend = let - mkAlias = default: mkOption { - internal = true; - readOnly = true; - inherit default; - }; + inherit (nbLib) mkAlias; in { enable = mkAlias cfg.frontend.enable; address = mkAlias cfg.frontend.address; diff --git a/modules/netns-isolation.nix b/modules/netns-isolation.nix index 47b59dd..a521d58 100644 --- a/modules/netns-isolation.nix +++ b/modules/netns-isolation.nix @@ -286,7 +286,7 @@ in { in optional nodes.lnd.enable "lnd" ++ optional (nodes.lnd.enable && nodes.lnd.loop) "lightning-loop" ++ - optional nodes.clightning.enable "clightning-rest"; + optional nodes.clightning.enable "clightning"; }; clightning-rest = { id = 30; @@ -315,6 +315,7 @@ in { }; services.clightning.address = netns.clightning.address; + services.clightning.plugins.clnrest.address = netns.clightning.address; services.lnd = { address = netns.lnd.address; diff --git a/modules/nodeinfo.nix b/modules/nodeinfo.nix index bce9ff0..3abeb57 100644 --- a/modules/nodeinfo.nix +++ b/modules/nodeinfo.nix @@ -142,6 +142,10 @@ in { '') + '' info["nodeid"] = shell("lncli getinfo | jq -r '.identity_pubkey'") '') name cfg; + clnrest = name: cfg: mkInfoLong { + inherit name cfg; + systemdServiceName = "clightning"; + }; clightning-rest = mkInfo ""; electrs = mkInfo ""; fulcrum = mkInfo ""; @@ -153,7 +157,6 @@ in { mempool-frontend = name: cfg: mkInfoLong { inherit name cfg; systemdServiceName = "nginx"; - extraCode = ""; }; # Only add sshd when it has an onion service sshd = name: cfg: mkIfOnionPort "sshd" (onionPort: '' diff --git a/modules/presets/wireguard.nix b/modules/presets/wireguard.nix index 4a04b28..47b7133 100644 --- a/modules/presets/wireguard.nix +++ b/modules/presets/wireguard.nix @@ -2,7 +2,8 @@ # Create a WireGuard server with a single peer. # Private/public keys are created via the secrets system. -# Add helper binaries `nix-bitcoin-wg-connect` and optionally `lndconnect-wg`, `lndconnect-clightning-wg`. +# Add helper binaries `nix-bitcoin-wg-connect` and optionally `lndconnect-wg`, +# `lnconnect-clnrest-wg`, `lndconnect-clightning-wg`. # See ../../docs/services.md ("Use Zeus (mobile lightning wallet) via WireGuard") # for usage instructions. @@ -33,9 +34,12 @@ let inherit (config.networking.wireguard.interfaces) wg-nb; inherit (config.services) lnd + clightning clightning-rest; + inherit (clightning.plugins) clnrest; lndconnect = lnd.enable && lnd.lndconnect.enable; + lnconnect-clnrest = clnrest.enable && clnrest.lnconnect.enable; lndconnect-clightning = clightning-rest.enable && clightning-rest.lndconnect.enable; serverAddress = "${wgSubnet}.1"; @@ -150,6 +154,10 @@ in { (pkgs.writers.writeBashBin "lndconnect-wg" '' exec lndconnect --host "${serverAddress}" --nocert "$@" '') + ) ++ (optional lnconnect-clnrest + (pkgs.writers.writeBashBin "lnconnect-clnrest-wg" '' + exec lnconnect-clnrest --host "${serverAddress}" --nocert "$@" + '') ) ++ (optional lndconnect-clightning (pkgs.writers.writeBashBin "lndconnect-clightning-wg" '' exec lndconnect-clightning --host "${serverAddress}" --nocert "$@" @@ -165,6 +173,9 @@ in { optionalString lndconnect '' iptables -w -A nixos-fw -p tcp -s ${wgSubnet}.0/24 --dport ${toString lnd.restPort} -j nixos-fw-accept '' + + optionalString lnconnect-clnrest '' + iptables -w -A nixos-fw -p tcp -s ${wgSubnet}.0/24 --dport ${toString clnrest.port} -j nixos-fw-accept + '' + optionalString lndconnect-clightning '' iptables -w -A nixos-fw -p tcp -s ${wgSubnet}.0/24 --dport ${toString clightning-rest.port} -j nixos-fw-accept '' @@ -187,6 +198,11 @@ in { restAddress = "0.0.0.0"; tor.enforce = false; }; + + services.clightning.plugins.clnrest.address = mkIf lnconnect-clnrest "0.0.0.0"; + # clnrest runs inside `clightning.service` + services.clightning.tor.enforce = mkIf lnconnect-clnrest false; + services.clightning-rest = mkIf lndconnect-clightning { # clightning-rest always listens on "0.0.0.0" tor.enforce = false; diff --git a/modules/rtl.nix b/modules/rtl.nix index 66c9179..53a3453 100644 --- a/modules/rtl.nix +++ b/modules/rtl.nix @@ -107,6 +107,7 @@ let nbLib = config.nix-bitcoin.lib; nbPkgs = config.nix-bitcoin.pkgs; secretsDir = config.nix-bitcoin.secretsDir; + runePath = "${cfg.dataDir}/clightning-admin-rune"; inherit (nbLib) optionalAttr; @@ -116,9 +117,8 @@ let lnImplementation = if isLnd then "LND" else "CLT"; Authentication = { ${optionalAttr (isLnd && lndLoopEnabled) "swapMacaroonPath"} = "${lightning-loop.dataDir}/${bitcoind.network}"; - macaroonPath = if isLnd - then "${cfg.dataDir}/macaroons" - else "${clightning-rest.dataDir}/certs"; + ${optionalAttr (isLnd) "macaroonPath"} = "${cfg.dataDir}/macaroons"; + ${optionalAttr (!isLnd) "runePath"} = runePath; }; Settings = { userPersona = "OPERATOR"; @@ -133,7 +133,7 @@ let lnServerUrl = "https://${ if isLnd then nbLib.addressWithPort lnd.restAddress lnd.restPort - else nbLib.addressWithPort clightning-rest.address clightning-rest.port + else nbLib.addressWithPort clightning.plugins.clnrest.address clightning.plugins.clnrest.port }"; }; }; @@ -159,7 +159,7 @@ let inherit (config.services) bitcoind lnd - clightning-rest + clightning lightning-loop; lndLoopEnabled = cfg.nodes.lnd.enable && cfg.nodes.lnd.loop; @@ -177,7 +177,10 @@ in { services.lnd.enable = mkIf cfg.nodes.lnd.enable true; services.lightning-loop.enable = mkIf lndLoopEnabled true; - services.clightning-rest.enable = mkIf cfg.nodes.clightning.enable true; + services.clightning = mkIf cfg.nodes.clightning.enable { + enable = true; + plugins.clnrest.enable = true; + }; systemd.tmpfiles.rules = [ "d '${cfg.dataDir}' 0770 ${cfg.user} ${cfg.group} - -" @@ -187,7 +190,7 @@ in { systemd.services.rtl = rec { wantedBy = [ "multi-user.target" ]; - requires = optional cfg.nodes.clightning.enable "clightning-rest.service" ++ + requires = optional cfg.nodes.clightning.enable "clightning.service" ++ optional cfg.nodes.lnd.enable "lnd.service"; after = requires ++ [ "nix-bitcoin-secrets.target" ]; environment.RTL_CONFIG_PATH = cfg.dataDir; @@ -198,10 +201,17 @@ in { <${configFile} sed "s|@multiPass@|$(cat ${secretsDir}/rtl-password)|" \ > '${cfg.dataDir}/RTL-Config.json' '') - ] ++ optional cfg.nodes.lnd.enable + ] + ++ optional cfg.nodes.lnd.enable + # The lnd admin macaroon is not readable by group `lnd`, so copy it (nbLib.rootScript "rtl-copy-macaroon" '' - install -D -o ${cfg.user} -g ${cfg.group} ${lnd.networkDir}/admin.macaroon \ + install --compare -m 640 -o ${cfg.user} -g ${cfg.group} -D ${lnd.networkDir}/admin.macaroon \ '${cfg.dataDir}/macaroons/admin.macaroon' + '') + ++ optional cfg.nodes.clightning.enable + (nbLib.rootScript "rtl-create-clnrest-rune-file" '' + rune=$(cat '${clightning.networkDir}/admin-rune') + install --compare -m 640 -o ${cfg.user} -g ${cfg.group} <(printf 'LIGHTNING_RUNE="%s"\n' "$rune") '${runePath}' ''); ExecStart = "${nbPkgs.rtl}/bin/rtl"; # Show "rtl" instead of "node" in the journal @@ -217,10 +227,7 @@ in { users.users.${cfg.user} = { isSystemUser = true; group = cfg.group; - extraGroups = - # Reads cert and macaroon from the clightning-rest datadir - optional cfg.nodes.clightning.enable clightning-rest.group ++ - optional lndLoopEnabled lnd.group; + extraGroups = optional lndLoopEnabled lnd.group; }; users.groups.${cfg.group} = {}; diff --git a/pkgs/lib.nix b/pkgs/lib.nix index 522740e..5bfb639 100644 --- a/pkgs/lib.nix +++ b/pkgs/lib.nix @@ -123,4 +123,10 @@ let self = { mkIfTest = test: mkIf (config.tests.${test} or false); }; + mkAlias = default: mkOption { + internal = true; + readOnly = true; + inherit default; + }; + }; in self diff --git a/pkgs/python-packages/clnrest/default.nix b/pkgs/python-packages/clnrest/default.nix new file mode 100644 index 0000000..7f0e204 --- /dev/null +++ b/pkgs/python-packages/clnrest/default.nix @@ -0,0 +1,58 @@ +{ buildPythonPackage +, clightning +, python +, poetry-core +, flask +, flask-cors +, flask-restx +, flask-socketio +, gevent +, gevent-websocket +, gunicorn +, pyln-client +, json5 +, jsonschema +}: + +let + self = buildPythonPackage rec { + pname = "clnrest"; + version = clightning.version; + format = "pyproject"; + + inherit (clightning) src; + + postUnpack = "sourceRoot=$sourceRoot/plugins/clnrest"; + + postPatch = '' + substituteInPlace pyproject.toml \ + --replace 'gevent = "^23.9.0.post1"' 'gevent = "24.2.1"' \ + --replace 'flask = "^2.3.3"' 'flask = "3.0.3"' + + # Add extra required src files that are missing in pyproject.toml + sed -i '/authors/a include = [ { path = "utilities", format = ["sdist", "wheel"] } ]' pyproject.toml + ''; + + nativeBuildInputs = [ poetry-core ]; + + # From https://github.com/ElementsProject/lightning/blob/master/plugins/clnrest/pyproject.toml + propagatedBuildInputs = [ + flask + flask-cors + flask-restx + flask-socketio + gevent + gevent-websocket + gunicorn + json5 + pyln-client + ]; + + postInstall = '' + makeWrapper ${python}/bin/python $out/bin/clnrest \ + --set NIX_PYTHONPATH ${python.pkgs.makePythonPath self.propagatedBuildInputs} \ + --add-flags "$out/lib/${python.libPrefix}/site-packages/clnrest.py" + ''; + }; +in + self diff --git a/pkgs/python-packages/default.nix b/pkgs/python-packages/default.nix index af056d5..7445beb 100644 --- a/pkgs/python-packages/default.nix +++ b/pkgs/python-packages/default.nix @@ -10,6 +10,7 @@ rec { pyln-proto = clightningPkg ./pyln-proto; pyln-bolt7 = clightningPkg ./pyln-bolt7; pylightning = clightningPkg ./pylightning; + clnrest = clightningPkg ./clnrest; # Packages only used by joinmarket bencoderpyx = callPackage ./bencoderpyx {}; diff --git a/pkgs/rtl/default.nix b/pkgs/rtl/default.nix index e11f61e..8375ad4 100644 --- a/pkgs/rtl/default.nix +++ b/pkgs/rtl/default.nix @@ -9,11 +9,11 @@ }: let self = stdenvNoCC.mkDerivation { pname = "rtl"; - version = "0.14.1"; + version = "0.15.2"; src = fetchurl { url = "https://github.com/Ride-The-Lightning/RTL/archive/refs/tags/v${self.version}.tar.gz"; - hash = "sha256-sbV7d/imdCXglpAS3hh7fETvSxMzegi63AfbS1imqbk="; + hash = "sha256-8Scgrr1An8vwiVgDFxVP6FQksqd6ctwZN2W2ErPp39Y="; }; passthru = { @@ -25,7 +25,7 @@ let self = stdenvNoCC.mkDerivation { # TODO-EXTERNAL: Remove `npmFlags` when no longer required # See: https://github.com/Ride-The-Lightning/RTL/issues/1182 npmFlags = "--legacy-peer-deps"; - hash = "sha256-0fu14j4OvsYGBhu/p67EUFmuHCbIPlLVm4e8qd9tk3o="; + hash = "sha256-LIKZOHc8FqvVX5LCJrq9Z76ZoyXLYiYsPIj6IieBWho="; }; }; diff --git a/pkgs/rtl/generate.sh b/pkgs/rtl/generate.sh index dc99304..31accd4 100755 --- a/pkgs/rtl/generate.sh +++ b/pkgs/rtl/generate.sh @@ -2,7 +2,7 @@ set -euo pipefail . "${BASH_SOURCE[0]%/*}/../../helper/run-in-nix-env" "gnupg wget gnused" "$@" -version="0.14.1" +version="0.15.2" repo=https://github.com/Ride-The-Lightning/RTL scriptDir=$(cd "${BASH_SOURCE[0]%/*}" && pwd) diff --git a/test/tests.nix b/test/tests.nix index 6310cce..f950b62 100644 --- a/test/tests.nix +++ b/test/tests.nix @@ -64,6 +64,7 @@ let nbPkgs = config.nix-bitcoin.pkgs; pluginPkgs = nbPkgs.clightning-plugins // { clboss.path = "${plugins.clboss.package}/bin/clboss"; + clnrest.path = "${plugins.clnrest.package}/bin/clnrest"; trustedcoin.path = "${plugins.trustedcoin.package}/bin/trustedcoin"; }; in map (plugin: pluginPkgs.${plugin}.path) enabled; @@ -102,6 +103,7 @@ let nix-bitcoin.onionServices.lnd.public = true; tests.lndconnect-onion-lnd = with cfg.lnd.lndconnect; enable && onion; + tests.lnconnect-onion-clnrest = with cfg.clightning.plugins.clnrest.lnconnect; enable && onion; tests.lndconnect-onion-clightning = with cfg.clightning-rest.lndconnect; enable && onion; tests.lightning-loop = cfg.lightning-loop.enable; @@ -194,6 +196,10 @@ let encrypt = true; local.directory = "/var/backup/clightning"; }; + services.clightning.plugins.clnrest = { + enable = true; + lnconnect = { enable = true; onion = true; }; + }; test.features.clightningPlugins = true; services.rtl.enable = true; services.clightning-rest.enable = true; diff --git a/test/tests.py b/test/tests.py index 3dfb11d..4dee84c 100644 --- a/test/tests.py +++ b/test/tests.py @@ -179,6 +179,11 @@ def _(): assert_running("lnd") assert_matches("runuser -u operator -- lndconnect --url", ".onion") +@test("lnconnect-onion-clnrest") +def _(): + assert_running("clightning") + assert_matches("runuser -u operator -- lnconnect-clnrest --url", ".onion") + @test("lndconnect-onion-clightning") def _(): assert_running("clightning-rest") diff --git a/test/wireguard-lndconnect.nix b/test/wireguard-lndconnect.nix index d3993ac..e8d8fdc 100644 --- a/test/wireguard-lndconnect.nix +++ b/test/wireguard-lndconnect.nix @@ -18,18 +18,22 @@ makeTestVM { nix-bitcoin.generateSecrets = true; nix-bitcoin.operator.enable = true; + services.clightning = { + enable = true; + plugins.clnrest = { + enable = true; + lnconnect.enable = true; + }; + }; + services.clightning-rest = { enable = true; lndconnect.enable = true; }; # TODO-EXTERNAL: # When WAN is disabled, DNS bootstrapping slows down service startup by ~15 s. - # TODO-EXTERNAL: - # When bitcoind is not fully synced, the offers plugin in clightning 24.05 - # crashes (see https://github.com/ElementsProject/lightning/issues/7378). services.clightning.extraConfig = '' disable-dns - disable-plugin=offers ''; services.lnd = { @@ -55,16 +59,19 @@ makeTestVM { def parse_lndconnect_url(url): u = Url.urlparse(url) + data = {'host': u.hostname, 'port': u.port} queries = Url.parse_qs(u.query) - macaroon = queries['macaroon'][0] - is_clightning = url.startswith("c-lightning-rest") + if url.startswith("clnrest"): + data['rune'] = queries['rune'][0] + else: + macaroon = queries['macaroon'][0] + if url.startswith("c-lightning-rest"): + data['macaroon_hex'] = macaroon + else: + # lnd + data['macaroon_hex'] = base64.urlsafe_b64decode(macaroon + '===').hex().upper() - return SimpleNamespace( - host = u.hostname, - port = u.port, - macaroon_hex = - macaroon if is_clightning else base64.urlsafe_b64decode(macaroon + '===').hex().upper() - ) + return SimpleNamespace(**data) client.start() server.connect() @@ -96,6 +103,16 @@ makeTestVM { f"-X GET https://{api.host}:{api.port}/v1/getinfo" ) + with subtest("lnconnect-clnrest-wg"): + server.wait_for_unit("clightning.service") + lndconnect_url = server.succeed("runuser -u operator -- lnconnect-clnrest-wg --url") + api = parse_lndconnect_url(lndconnect_url) + # Make clnrest API call + client.succeed( + f"curl -fsS --max-time 3 --insecure --header 'rune: {api.rune}' " + f"-X POST https://{api.host}:{api.port}/v1/getinfo" + ) + with subtest("lndconnect-clightning-wg"): server.wait_for_unit("clightning-rest.service") lndconnect_url = server.succeed("runuser -u operator -- lndconnect-clightning-wg --url")