joinmarket: add option settings

Joinmarket settings can now be freely specified.
This commit is contained in:
Erik Arvstedt 2024-07-29 11:24:58 +02:00
parent da2e473158
commit cf3f0dbb2d
No known key found for this signature in database
GPG key ID: 33312B944DD97846
3 changed files with 131 additions and 105 deletions

View file

@ -19,6 +19,19 @@ let
default = "/var/lib/joinmarket-ob-watcher"; default = "/var/lib/joinmarket-ob-watcher";
description = "The data directory for JoinMarket orderbook 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 { user = mkOption {
type = types.str; type = types.str;
default = "joinmarket-ob-watcher"; default = "joinmarket-ob-watcher";
@ -40,17 +53,6 @@ let
secretsDir = config.nix-bitcoin.secretsDir; secretsDir = config.nix-bitcoin.secretsDir;
inherit (config.services) bitcoind joinmarket; 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 { in {
inherit options; inherit options;
@ -72,6 +74,18 @@ in {
"d '${cfg.dataDir}' 0770 ${cfg.user} ${cfg.group} - -" "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 { systemd.services.joinmarket-ob-watcher = rec {
wantedBy = [ "multi-user.target" ]; wantedBy = [ "multi-user.target" ];
requires = [ "tor.service" "bitcoind.service" ]; requires = [ "tor.service" "bitcoind.service" ];
@ -80,7 +94,7 @@ in {
environment.HOME = cfg.dataDir; environment.HOME = cfg.dataDir;
preStart = '' preStart = ''
{ {
cat ${configFile} cat ${builtins.toFile "joinmarket-ob-watcher.cfg" ((generators.toINI {}) cfg.settings)}
echo echo
echo '[BLOCKCHAIN]' echo '[BLOCKCHAIN]'
echo "rpc_password = $(cat ${secretsDir}/bitcoin-rpcpassword-joinmarket-ob-watcher)" echo "rpc_password = $(cat ${secretsDir}/bitcoin-rpcpassword-joinmarket-ob-watcher)"

View file

@ -41,12 +41,31 @@ let
description = "The data directory for JoinMarket."; description = "The data directory for JoinMarket.";
}; };
rpcWalletFile = mkOption { rpcWalletFile = mkOption {
type = types.nullOr types.str; type = types.nullOr types.nonEmptyStr;
default = "jm_wallet"; default = "jm_wallet";
description = '' description = ''
Name of the watch-only bitcoind wallet the JoinMarket addresses are imported to. 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://raw.githubusercontent.com/JoinMarket-Org/joinmarket-clientserver/master/src/jmclient/configure.py#:~:text=defaultconfig%20=
If your web browser does not support text fragment URLs, you can can manually
search for string `defaultconfig =` to jump to the correct location.
'';
};
user = mkOption { user = mkOption {
type = types.str; type = types.str;
default = "joinmarket"; default = "joinmarket";
@ -61,12 +80,6 @@ let
default = cli; default = cli;
defaultText = "(See source)"; 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. # This option is only used by netns-isolation.
# Tor is always enabled. # Tor is always enabled.
tor.enforce = nbLib.tor.enforce; tor.enforce = nbLib.tor.enforce;
@ -142,88 +155,12 @@ let
inherit (config.services) bitcoind; inherit (config.services) bitcoind;
torAddress = config.services.tor.client.socksListenAddress; torAddress = config.services.tor.client.socksListenAddress;
socks5Settings = ''
socks5 = true
socks5_host = ${torAddress.addr}
socks5_port = ${toString torAddress.port}
'';
messagingConfig = '' socks5Settings = {
[MESSAGING:onion] socks5 = true;
type = onion socks5_host = torAddress.addr;
${socks5Settings} socks5_port = torAddress.port;
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}
'';
# The jm scripts create a 'logs' dir in the working dir, # The jm scripts create a 'logs' dir in the working dir,
# so run them inside dataDir. # so run them inside dataDir.
@ -242,7 +179,78 @@ let
in { in {
inherit options; 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"
# TODO: This is only needed when ./obsolete-options.nix is imported
"txfee"
];
# 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 = { services.bitcoind = {
enable = true; enable = true;
disablewallet = false; disablewallet = false;
@ -275,7 +283,7 @@ in {
after = [ "bitcoind.service" "nix-bitcoin-secrets.target" ]; after = [ "bitcoind.service" "nix-bitcoin-secrets.target" ];
preStart = '' preStart = ''
{ {
cat ${configFile} cat ${builtins.toFile "joinmarket.cfg" ((generators.toINI {}) cfg.settings)}
echo echo
echo '[BLOCKCHAIN]' echo '[BLOCKCHAIN]'
echo "rpc_password = $(cat ${secretsDir}/bitcoin-rpcpassword-privileged)" echo "rpc_password = $(cat ${secretsDir}/bitcoin-rpcpassword-privileged)"
@ -350,9 +358,9 @@ in {
nix-bitcoin.generateSecretsCmds.joinmarket = '' nix-bitcoin.generateSecretsCmds.joinmarket = ''
makePasswordSecret jm-wallet-password makePasswordSecret jm-wallet-password
''; '';
} })
(mkIf cfg.yieldgenerator.enable { (mkIf (cfg.enable && cfg.yieldgenerator.enable) {
systemd.services.joinmarket-yieldgenerator = { systemd.services.joinmarket-yieldgenerator = {
wantedBy = [ "joinmarket.service" ]; wantedBy = [ "joinmarket.service" ];
requires = [ "joinmarket.service" ]; requires = [ "joinmarket.service" ];
@ -373,5 +381,5 @@ in {
} // nbLib.allowTor; } // nbLib.allowTor;
}; };
}) })
]); ];
} }

View file

@ -1,6 +1,10 @@
{ stdenv, lib, fetchFromGitHub, python3, nbPython3PackagesJoinmarket }: { stdenv, lib, fetchFromGitHub, python3, nbPython3PackagesJoinmarket }:
let let
# Note:
# After updating this pkg, also update the following items in ../../modules/joinmarket.nix:
# - The `MESSAGING:*` sections in the config value of option `settings`.
# Copy the values from `jmclient/configure.py`.
version = "0.9.11"; version = "0.9.11";
src = fetchFromGitHub { src = fetchFromGitHub {
owner = "joinmarket-org"; owner = "joinmarket-org";