diff --git a/modules/lnd.nix b/modules/lnd.nix index 7d99641..3fd59f2 100644 --- a/modules/lnd.nix +++ b/modules/lnd.nix @@ -174,7 +174,7 @@ let ${optionalString (cfg.tor-socks != null) "tor.socks=${cfg.tor-socks}"} bitcoind.rpchost=${bitcoindRpcAddress}:${toString bitcoind.rpc.port} - bitcoind.rpcuser=${bitcoind.rpc.users.public.name} + bitcoind.rpcuser=${bitcoind.rpc.users.${rpcUser}.name} bitcoind.zmqpubrawblock=${bitcoind.zmqpubrawblock} bitcoind.zmqpubrawtx=${bitcoind.zmqpubrawtx} @@ -182,11 +182,16 @@ let ${cfg.extraConfig} ''; + + isPruned = bitcoind.prune > 0; + # When bitcoind pruning is enabled, lnd requires non-public RPC commands `getpeerinfo`, `getnodeaddresses` + # to fetch missing blocks from peers (implemented in btcsuite/btcwallet/chain/pruned_block_dispatcher.go) + rpcUser = if isPruned then "lnd" else "public"; in { inherit options; - config = mkIf cfg.enable { + config = mkIf cfg.enable (mkMerge [ { assertions = [ { assertion = !(config.services ? clightning) @@ -226,7 +231,7 @@ in { preStart = '' install -m600 ${configFile} '${cfg.dataDir}/lnd.conf' { - echo "bitcoind.rpcpass=$(cat ${secretsDir}/bitcoin-rpcpassword-public)" + echo "bitcoind.rpcpass=$(cat ${secretsDir}/bitcoin-rpcpassword-${rpcUser})" ${optionalString (cfg.getPublicAddressCmd != "") '' echo "externalip=$(${cfg.getPublicAddressCmd})" ''} @@ -304,5 +309,22 @@ in { makePasswordSecret lnd-wallet-password makeCert lnd '${nbLib.mkCertExtraAltNames cfg.certificate}' ''; - }; + } + + (mkIf isPruned { + services.bitcoind.rpc.users.lnd = { + passwordHMACFromFile = true; + rpcwhitelist = bitcoind.rpc.users.public.rpcwhitelist ++ [ + "getpeerinfo" + "getnodeaddresses" + ]; + }; + nix-bitcoin.secrets = { + bitcoin-rpcpassword-lnd.user = cfg.user; + bitcoin-HMAC-lnd.user = bitcoind.user; + }; + nix-bitcoin.generateSecretsCmds.lndBitcoinRPC = '' + makeBitcoinRPCPassword lnd + ''; + }) ]); } diff --git a/test/lib/shellcheck-services.nix b/test/lib/shellcheck-services.nix index bc6d5ba..8d0b209 100644 --- a/test/lib/shellcheck-services.nix +++ b/test/lib/shellcheck-services.nix @@ -1,4 +1,4 @@ -{ config, pkgs, lib, extendModules, ... }: +{ config, pkgs, lib, extendModules, ... }@args: with lib; let options = { @@ -12,68 +12,38 @@ let }; }; - # TODO-EXTERNAL: - # This can be removed when https://github.com/NixOS/nixpkgs/pull/189836 is merged. - # - # A list of all systemd service definitions and their locations, with format - # [ - # { - # file = ...; - # value = { postgresql = ...; }; - # } - # ... - # ] - systemdServiceDefs = - (extendModules { - modules = [ - { - # Currently, NixOS modules only allow accessing option definition locations - # via type.merge. - # Override option `systemd.services` and use it to return the list of service defs. - options.systemd.services = lib.mkOption { - type = lib.types.anything // { - merge = loc: defs: defs; - }; - }; - - # Disable all modules that define options.systemd.services so that these - # defs don't collide with our definition - disabledModules = [ - "system/boot/systemd.nix" - # These files amend option systemd.services - "testing/service-runner.nix" - "security/systemd-confinement.nix" - ]; - - config._module.check = false; - } - ]; - }).config.systemd.services; - # A list of all service names that are defined by nix-bitcoin. # [ "bitcoind", "clightning", ... ] # - # Algorithm: Parse `systemdServiceDefs` and return all services that - # only have definitions located in the nix-bitcoin source. + # Algorithm: Parse defintions of `systemd.services` and return all services + # that only have definitions located in the nix-bitcoin source. nix-bitcoin-services = let + systemdServices = args.options.systemd.services; + configSystemdServices = args.config.systemd.services; nix-bitcoin-source = toString ../..; nbServices = collectServices true; nonNbServices = collectServices false; # Return set of services ({ service1 = true; service2 = true; ... }) # which are either defined or not defined by nix-bitcoin, depending # on `fromNixBitcoin`. - collectServices = fromNixBitcoin: lib.listToAttrs (builtins.concatLists (map (def: + collectServices = fromNixBitcoin: lib.listToAttrs (builtins.concatLists (zipListsWith (services: file: let - isNbSource = lib.hasPrefix nix-bitcoin-source def.file; + isNbSource = lib.hasPrefix nix-bitcoin-source file; in - # Nix has nor boolean XOR, so use `if` + # Nix has no boolean XOR, so use `if` lib.optionals (if fromNixBitcoin then isNbSource else !isNbSource) ( - (map (service: { name = service; value = true; }) (builtins.attrNames def.value)) + (map (service: { name = service; value = true; }) (builtins.attrNames services)) ) - ) systemdServiceDefs)); + # TODO-EXTERNAL: + # Use `systemdServices.definitionsWithLocations` when https://github.com/NixOS/nixpkgs/pull/189836 + # is included in nixpkgs stable. + ) systemdServices.definitions systemdServices.files)); in - # Set difference: nbServices - nonNbServices - builtins.filter (nbService: ! nonNbServices ? ${nbService}) (builtins.attrNames nbServices); + # Calculate set difference: nbServices - nonNbServices + # and exclude unavailable services (defined via `mkIf false ...`) by checking `configSystemdServices`. + builtins.filter (nbService: + configSystemdServices ? ${nbService} && (! nonNbServices ? ${nbService}) + ) (builtins.attrNames nbServices); # The concatenated list of values of ExecStart, ExecStop, ... (`scriptAttrs`) of all `nix-bitcoin-services`. serviceCmds = let diff --git a/test/run-tests.sh b/test/run-tests.sh index f33792d..0fa227e 100755 --- a/test/run-tests.sh +++ b/test/run-tests.sh @@ -306,6 +306,7 @@ buildable() { scenario=regtest buildTest "$@" scenario=hardened buildTest "$@" scenario=clightningReplication buildTest "$@" + scenario=lndPruned buildTest "$@" } examples() { diff --git a/test/tests.nix b/test/tests.nix index 7df63f0..cd30357 100644 --- a/test/tests.nix +++ b/test/tests.nix @@ -318,6 +318,12 @@ let services.btcpayserver.lbtc = mkForce false; }; + # Test the special bitcoin RPC setup that lnd uses when bitcoin is pruned + lndPruned = { + services.lnd.enable = true; + services.bitcoind.prune = 1000; + }; + ## Examples / debug helper # Run a selection of tests in scenario 'netns'