From 5552e767b13573594dea1114b587fd003aa153d0 Mon Sep 17 00:00:00 2001 From: Erik Arvstedt Date: Sat, 27 Jul 2024 16:07:35 +0200 Subject: [PATCH] joinmarket: add option `settings` Joinmarket settings can now be freely specified. --- modules/joinmarket-ob-watcher.nix | 38 ++++-- modules/joinmarket.nix | 188 +++++++++++++++--------------- pkgs/joinmarket/default.nix | 2 + 3 files changed, 123 insertions(+), 105 deletions(-) diff --git a/modules/joinmarket-ob-watcher.nix b/modules/joinmarket-ob-watcher.nix index ec232c995..537b0b37c 100644 --- a/modules/joinmarket-ob-watcher.nix +++ b/modules/joinmarket-ob-watcher.nix @@ -19,6 +19,19 @@ let default = "/var/lib/joinmarket-ob-watcher"; description = "The data directory for JoinMarket orderbook watcher."; }; + settings = mkOption { + type = with types; attrsOf anything; + example = { + LOGGING = { + console_log_level = "DEBUG"; + }; + }; + description = '' + Joinmarket settings. + See here for possible options: + https://github.com/JoinMarket-Org/joinmarket-clientserver/blob/v0.9.11/src/jmclient/configure.py#L98 + ''; + }; user = mkOption { type = types.str; default = "joinmarket-ob-watcher"; @@ -40,17 +53,6 @@ let secretsDir = config.nix-bitcoin.secretsDir; inherit (config.services) bitcoind joinmarket; - - configFile = builtins.toFile "config" '' - [BLOCKCHAIN] - blockchain_source = bitcoin-rpc - network = ${bitcoind.network} - rpc_host = ${bitcoind.rpc.address} - rpc_port = ${toString bitcoind.rpc.port} - rpc_user = ${bitcoind.rpc.users.joinmarket-ob-watcher.name} - - ${joinmarket.messagingConfig} - ''; in { inherit options; @@ -72,6 +74,18 @@ in { "d '${cfg.dataDir}' 0770 ${cfg.user} ${cfg.group} - -" ]; + services.joinmarket-ob-watcher.settings = { + BLOCKCHAIN = config.services.joinmarket.settings.BLOCKCHAIN // { + rpc_user = bitcoind.rpc.users.joinmarket-ob-watcher.name; + rpc_wallet_file = ""; + }; + inherit (config.services.joinmarket.settings) + "MESSAGING:onion" + "MESSAGING:server1" + "MESSAGING:server2" + "MESSAGING:server3"; + }; + systemd.services.joinmarket-ob-watcher = rec { wantedBy = [ "multi-user.target" ]; requires = [ "tor.service" "bitcoind.service" ]; @@ -80,7 +94,7 @@ in { environment.HOME = cfg.dataDir; preStart = '' { - cat ${configFile} + cat ${builtins.toFile "joinmarket-ob-watcher.cfg" ((generators.toINI {}) cfg.settings)} echo echo '[BLOCKCHAIN]' echo "rpc_password = $(cat ${secretsDir}/bitcoin-rpcpassword-joinmarket-ob-watcher)" diff --git a/modules/joinmarket.nix b/modules/joinmarket.nix index 7d4554a98..09ae80180 100644 --- a/modules/joinmarket.nix +++ b/modules/joinmarket.nix @@ -41,12 +41,29 @@ let description = "The data directory for JoinMarket."; }; rpcWalletFile = mkOption { - type = types.nullOr types.str; + type = types.nullOr types.nonEmptyStr; default = "jm_wallet"; description = '' Name of the watch-only bitcoind wallet the JoinMarket addresses are imported to. ''; }; + settings = mkOption { + type = with types; attrsOf anything; + example = { + POLICY = { + merge_algorithm = "gradual"; + tx_fees = 5; + }; + LOGGING = { + console_log_level = "DEBUG"; + }; + }; + description = '' + Joinmarket settings. + See here for possible options: + https://github.com/JoinMarket-Org/joinmarket-clientserver/blob/v0.9.11/src/jmclient/configure.py#L98 + ''; + }; user = mkOption { type = types.str; default = "joinmarket"; @@ -61,12 +78,6 @@ let default = cli; defaultText = "(See source)"; }; - # Used by ./joinmarket-ob-watcher.nix - messagingConfig = mkOption { - readOnly = true; - default = messagingConfig; - defaultText = "(See source)"; - }; # This option is only used by netns-isolation. # Tor is always enabled. tor.enforce = nbLib.tor.enforce; @@ -142,88 +153,12 @@ let inherit (config.services) bitcoind; torAddress = config.services.tor.client.socksListenAddress; - socks5Settings = '' - socks5 = true - socks5_host = ${torAddress.addr} - socks5_port = ${toString torAddress.port} - ''; - - messagingConfig = '' - [MESSAGING:onion] - type = onion - ${socks5Settings} - tor_control_host = unix:/run/tor/control - # required option, but ignored for unix socket host - tor_control_port = 9051 - onion_serving_host = ${cfg.messagingAddress} - onion_serving_port = ${toString cfg.messagingPort} - hidden_service_dir = - directory_nodes = g3hv4uynnmynqqq2mchf3fcm3yd46kfzmcdogejuckgwknwyq5ya6iad.onion:5222,3kxw6lf5vf6y26emzwgibzhrzhmhqiw6ekrek3nqfjjmhwznb2moonad.onion:5222,bqlpq6ak24mwvuixixitift4yu42nxchlilrcqwk2ugn45tdclg42qid.onion:5222 - - # irc.darkscience.net - [MESSAGING:server1] - host = darkirc6tqgpnwd3blln3yfv5ckl47eg7llfxkmtovrv7c7iwohhb6ad.onion - channel = joinmarket-pit - port = 6697 - usessl = true - ${socks5Settings} - - # ilita - [MESSAGING:server2] - host = ilitafrzzgxymv6umx2ux7kbz3imyeko6cnqkvy4nisjjj4qpqkrptid.onion - channel = joinmarket-pit - port = 6667 - usessl = false - ${socks5Settings} - - # irc.hackint.org - [MESSAGING:server3] - host = ncwkrwxpq2ikcngxq3dy2xctuheniggtqeibvgofixpzvrwpa77tozqd.onion - channel = joinmarket-pit - port = 6667 - usessl = false - ${socks5Settings} - ''; - - # Based on https://github.com/JoinMarket-Org/joinmarket-clientserver/blob/master/jmclient/jmclient/configure.py - yg = cfg.yieldgenerator; - configFile = builtins.toFile "config" '' - [DAEMON] - no_daemon = 0 - daemon_port = 27183 - daemon_host = 127.0.0.1 - - [BLOCKCHAIN] - blockchain_source = ${bitcoind.makeNetworkName "bitcoin-rpc" "regtest"} - network = ${bitcoind.makeNetworkName "mainnet" "testnet"} - rpc_host = ${nbLib.address bitcoind.rpc.address} - rpc_port = ${toString bitcoind.rpc.port} - rpc_user = ${bitcoind.rpc.users.privileged.name} - ${optionalString (cfg.rpcWalletFile != null) "rpc_wallet_file = ${cfg.rpcWalletFile}"} - - ${messagingConfig} - - [LOGGING] - color = false - - [PAYJOIN] - onion_socks5_host = ${torAddress.addr} - onion_socks5_port = ${toString torAddress.port} - tor_control_host = unix:/run/tor/control - onion_serving_host = ${cfg.payjoinAddress} - onion_serving_port = ${toString cfg.payjoinPort} - hidden_service_ssl = false - [YIELDGENERATOR] - ordertype = ${yg.ordertype} - cjfee_a = ${toString yg.cjfee_a} - cjfee_r = ${toString yg.cjfee_r} - cjfee_factor = ${toString yg.cjfee_factor} - txfee_contribution = 0 - txfee_contribution_factor = ${toString yg.txfee_contribution_factor} - minsize = ${toString yg.minsize} - size_factor = ${toString yg.size_factor} - ''; + socks5Settings = { + socks5 = true; + socks5_host = torAddress.addr; + socks5_port = torAddress.port; + }; # The jm scripts create a 'logs' dir in the working dir, # so run them inside dataDir. @@ -242,7 +177,74 @@ let in { inherit options; - config = mkIf cfg.enable (mkMerge [{ + config = mkMerge [ + { + services.joinmarket.settings = { + DAEMON = { + no_daemon = 0; + daemon_port = 27183; + daemon_host = "127.0.0.1"; + }; + BLOCKCHAIN = { + blockchain_source = bitcoind.makeNetworkName "bitcoin-rpc" "regtest"; + network = bitcoind.makeNetworkName "mainnet" "testnet"; + rpc_host = nbLib.address bitcoind.rpc.address; + rpc_port = bitcoind.rpc.port; + rpc_user = bitcoind.rpc.users.privileged.name; + rpc_wallet_file = if cfg.rpcWalletFile == null then "" else cfg.rpcWalletFile; + }; + LOGGING = { + color = false; + }; + PAYJOIN = { + onion_socks5_host = torAddress.addr; + onion_socks5_port = torAddress.port; + tor_control_host = "unix:/run/tor/control"; + onion_serving_host = cfg.payjoinAddress; + onion_serving_port = cfg.payjoinPort; + hidden_service_ssl = false; + }; + YIELDGENERATOR = removeAttrs cfg.yieldgenerator [ "enable" ]; + + # Messaging settings have to be fully specified because joinmarket doesn't + # provide default messaging settings. + # (`jmclient/configure.py` actually does contain default messaging settings, but + # they are removed via fn `_remove_unwanted_default_settings`) + "MESSAGING:onion" = socks5Settings // { + type = "onion"; + tor_control_host = "unix:/run/tor/control"; + # Required option, but ignored because `tor_control_host` is a unix socket + tor_control_port = 9051; + onion_serving_host = cfg.messagingAddress; + onion_serving_port = cfg.messagingPort; + hidden_service_dir = ""; + directory_nodes = "g3hv4uynnmynqqq2mchf3fcm3yd46kfzmcdogejuckgwknwyq5ya6iad.onion:5222,3kxw6lf5vf6y26emzwgibzhrzhmhqiw6ekrek3nqfjjmhwznb2moonad.onion:5222,bqlpq6ak24mwvuixixitift4yu42nxchlilrcqwk2ugn45tdclg42qid.onion:5222"; + }; + # irc.darkscience.net + "MESSAGING:server1" = socks5Settings // { + host = "darkirc6tqgpnwd3blln3yfv5ckl47eg7llfxkmtovrv7c7iwohhb6ad.onion"; + channel = "joinmarket-pit"; + port = 6697; + usessl = true; + }; + # ilita + "MESSAGING:server2" = socks5Settings // { + host = "ilitafrzzgxymv6umx2ux7kbz3imyeko6cnqkvy4nisjjj4qpqkrptid.onion"; + channel = "joinmarket-pit"; + port = 6667; + usessl = false; + }; + # irc.hackint.org + "MESSAGING:server3" = socks5Settings // { + host = "ncwkrwxpq2ikcngxq3dy2xctuheniggtqeibvgofixpzvrwpa77tozqd.onion"; + channel = "joinmarket-pit"; + port = 6667; + usessl = false; + }; + }; + } + + (mkIf cfg.enable { services.bitcoind = { enable = true; disablewallet = false; @@ -275,7 +277,7 @@ in { after = [ "bitcoind.service" "nix-bitcoin-secrets.target" ]; preStart = '' { - cat ${configFile} + cat ${builtins.toFile "joinmarket.cfg" ((generators.toINI {}) cfg.settings)} echo echo '[BLOCKCHAIN]' echo "rpc_password = $(cat ${secretsDir}/bitcoin-rpcpassword-privileged)" @@ -350,9 +352,9 @@ in { nix-bitcoin.generateSecretsCmds.joinmarket = '' makePasswordSecret jm-wallet-password ''; - } + }) - (mkIf cfg.yieldgenerator.enable { + (mkIf (cfg.enable && cfg.yieldgenerator.enable) { systemd.services.joinmarket-yieldgenerator = { wantedBy = [ "joinmarket.service" ]; requires = [ "joinmarket.service" ]; @@ -373,5 +375,5 @@ in { } // nbLib.allowTor; }; }) - ]); + ]; } diff --git a/pkgs/joinmarket/default.nix b/pkgs/joinmarket/default.nix index fdda3708d..6b3bdd5e2 100644 --- a/pkgs/joinmarket/default.nix +++ b/pkgs/joinmarket/default.nix @@ -4,6 +4,8 @@ let # Note: # After updating this pkg, also update the following items in ../../modules/joinmarket.nix: # - The version number in all URLs pointing to `github.com/JoinMarket-Org` + # - The `MESSAGING:*` sections in the config value of option `settings`. + # Copy the values from `configure.py`. version = "0.9.11"; src = fetchFromGitHub { owner = "joinmarket-org";