Skip to content

Commit

Permalink
Merge #722: joinmarket: Add option settings
Browse files Browse the repository at this point in the history
cf3f0db joinmarket: add option `settings` (Erik Arvstedt)
da2e473 joinmarket: don't set default config options (Erik Arvstedt)
74eb9a1 joinmarket/yieldgenerator: add docs link to description (Erik Arvstedt)
5694408 joinmarket: remove deleted option `txfee` (Erik Arvstedt)

Pull request description:

ACKs for top commit:
  jonasnick:
    utACK cf3f0db

Tree-SHA512: 36754539670dedcc494b28fa8383b189bd8fcf4044e0be624f47db953b189d706ed76df305e10fbea69f4e0dd9c419eb1eaf35de75e860883ea3305456fc31ed
  • Loading branch information
jonasnick committed Aug 13, 2024
2 parents 9429c4a + cf3f0db commit 6e208d6
Show file tree
Hide file tree
Showing 6 changed files with 150 additions and 152 deletions.
2 changes: 1 addition & 1 deletion docs/services.md
Original file line number Diff line number Diff line change
Expand Up @@ -543,8 +543,8 @@ See [here](https://github.com/JoinMarket-Org/joinmarket-clientserver/blob/master
services.joinmarket.yieldgenerator = {
enable = true;
# Optional: Add custom parameters
txfee = 200;
cjfee_a = 300;
cjfee_r = 0.00003;
};
'';
```
Expand Down
38 changes: 26 additions & 12 deletions modules/joinmarket-ob-watcher.nix
Original file line number Diff line number Diff line change
Expand Up @@ -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";
Expand All @@ -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;

Expand All @@ -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" ];
Expand All @@ -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)"
Expand Down
246 changes: 109 additions & 137 deletions modules/joinmarket.nix
Original file line number Diff line number Diff line change
Expand Up @@ -41,12 +41,31 @@ 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://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 {
type = types.str;
default = "joinmarket";
Expand All @@ -61,19 +80,20 @@ 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;
inherit (nbLib) cliExec;

yieldgenerator = {
enable = mkEnableOption "JoinMarket yield generator bot";
enable = mkOption {
type = types.bool;
default = false;
description = ''
Enable the JoinMarket yield generator bot.
Documentation: https://github.com/JoinMarket-Org/joinmarket-clientserver/blob/master/docs/YIELDGENERATOR.md
'';
};
ordertype = mkOption {
type = types.enum [ "reloffer" "absoffer" ];
default = "reloffer";
Expand Down Expand Up @@ -102,13 +122,6 @@ let
Variance around the average cj fee.
'';
};
txfee = mkOption {
type = types.ints.unsigned;
default = 100;
description = ''
The average transaction fee you're adding to coinjoin transactions.
'';
};
txfee_contribution_factor = mkOption {
type = types.float;
default = 0.3;
Expand Down Expand Up @@ -142,124 +155,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
use_ssl = false
[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]
console_log_level = INFO
color = false
[POLICY]
segwit = true
native = true
merge_algorithm = default
gaplimit = 6
tx_fees = 3
tx_fees_factor = 0.2
absurd_fee_per_kb = 350000
max_sweep_fee_change = 0.8
tx_broadcast = self
minimum_makers = 4
max_sats_freeze_reuse = -1
interest_rate = 0.015
bondless_makers_allowance = 0.125
bond_value_exponent = 1.3
taker_utxo_retries = 3
taker_utxo_age = 5
taker_utxo_amtpercent = 20
accept_commitment_broadcasts = 1
commit_file_location = cmtdata/commitments.json
commitment_list_location = cmtdata/commitmentlist
[PAYJOIN]
payjoin_version = 1
disable_output_substitution = 0
max_additional_fee_contribution = default
min_fee_rate = 1.1
onion_socks5_host = ${torAddress.addr}
onion_socks5_port = ${toString torAddress.port}
tor_control_host = unix:/run/tor/control
# Required option, but unused because `tor_control_host` is a Unix socket
tor_control_port = 9051
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}
[SNICKER]
enabled = false
lowest_net_gain = 0
servers = cn5lfwvrswicuxn3gjsxoved6l2gu5hdvwy5l3ev7kg6j7lbji2k7hqd.onion,
polling_interval_minutes = 60
'';
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.
Expand All @@ -278,7 +179,78 @@ 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"
# 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 = {
enable = true;
disablewallet = false;
Expand Down Expand Up @@ -311,7 +283,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)"
Expand Down Expand Up @@ -386,9 +358,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" ];
Expand All @@ -409,5 +381,5 @@ in {
} // nbLib.allowTor;
};
})
]);
];
}
Loading

0 comments on commit 6e208d6

Please sign in to comment.