-
Notifications
You must be signed in to change notification settings - Fork 109
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge #164: Add JoinMarket Clientserver
dd88275 joinmarket: add usage documentation (nixbitcoin) d0701f5 joinmarket: automatically generate wallet (nixbitcoin) d6d3e8f joinmarket: add tests (nixbitcoin) cce27da backups: add joinmarket datadir to includelist (nixbitcoin) 173891f joinmarket: add module (nixbitcoin) 263525d nix-bitcoin-services: add nb-services.privileged helper (nixbitcoin) f00d1d2 joinmarket: add pkg and local dependencies (nixbitcoin) Pull request description: ACKs for top commit: jonasnick: ACK dd88275 Tree-SHA512: ad7bf56314877045bc8dc6037f966535dc3607d9e941cd03d19b610ee789307eac07447df7f93569dfa3e7553e8fc6d9757bdf8542fb123c5a2e2adec8f907a2
- Loading branch information
Showing
29 changed files
with
764 additions
and
4 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,219 @@ | ||
{ config, lib, pkgs, ... }: | ||
|
||
with lib; | ||
|
||
let | ||
cfg = config.services.joinmarket; | ||
inherit (config) nix-bitcoin-services; | ||
secretsDir = config.nix-bitcoin.secretsDir; | ||
|
||
torAddress = builtins.head (builtins.split ":" config.services.tor.client.socksListenAddress); | ||
configFile = builtins.toFile "config" '' | ||
# Based on https://github.com/JoinMarket-Org/joinmarket-clientserver/blob/master/jmclient/jmclient/configure.py | ||
[DAEMON] | ||
no_daemon = 0 | ||
daemon_port = 27183 | ||
daemon_host = localhost | ||
use_ssl = false | ||
[BLOCKCHAIN] | ||
blockchain_source = bitcoin-rpc | ||
network = mainnet | ||
rpc_host = ${builtins.elemAt config.services.bitcoind.rpcbind 0} | ||
rpc_port = 8332 | ||
rpc_user = ${config.services.bitcoind.rpc.users.privileged.name} | ||
@@RPC_PASSWORD@@ | ||
[MESSAGING:server1] | ||
host = darksci3bfoka7tw.onion | ||
channel = joinmarket-pit | ||
port = 6697 | ||
usessl = true | ||
socks5 = true | ||
socks5_host = ${torAddress} | ||
socks5_port = 9050 | ||
[MESSAGING:server2] | ||
host = ncwkrwxpq2ikcngxq3dy2xctuheniggtqeibvgofixpzvrwpa77tozqd.onion | ||
channel = joinmarket-pit | ||
port = 6667 | ||
usessl = false | ||
socks5 = true | ||
socks5_host = ${torAddress} | ||
socks5_port = 9050 | ||
[LOGGING] | ||
console_log_level = INFO | ||
color = false | ||
[POLICY] | ||
segwit = true | ||
native = false | ||
merge_algorithm = default | ||
tx_fees = 3 | ||
absurd_fee_per_kb = 350000 | ||
tx_broadcast = self | ||
minimum_makers = 4 | ||
max_sats_freeze_reuse = -1 | ||
taker_utxo_retries = 3 | ||
taker_utxo_age = 5 | ||
taker_utxo_amtpercent = 20 | ||
accept_commitment_broadcasts = 1 | ||
commit_file_location = cmtdata/commitments.json | ||
''; | ||
|
||
# The jm scripts create a 'logs' dir in the working dir, | ||
# so run them inside dataDir. | ||
cli = pkgs.runCommand "joinmarket-cli" {} '' | ||
mkdir -p $out/bin | ||
jm=${pkgs.nix-bitcoin.joinmarket}/bin | ||
cd $jm | ||
for bin in jm-*; do | ||
{ | ||
echo "#!${pkgs.bash}/bin/bash"; | ||
echo "cd '${cfg.dataDir}' && ${cfg.cliExec} sudo -u ${cfg.user} $jm/$bin --datadir='${cfg.dataDir}' \"\$@\""; | ||
} > $out/bin/$bin | ||
done | ||
chmod -R +x $out/bin | ||
''; | ||
in { | ||
options.services.joinmarket = { | ||
enable = mkEnableOption "JoinMarket"; | ||
yieldgenerator = { | ||
enable = mkEnableOption "yield generator bot"; | ||
customParameters = mkOption { | ||
type = types.str; | ||
default = ""; | ||
example = '' | ||
txfee = 200 | ||
cjfee_a = 300 | ||
''; | ||
description = '' | ||
Python code to define custom yield generator parameters, as described in | ||
https://github.com/JoinMarket-Org/joinmarket-clientserver/blob/master/docs/YIELDGENERATOR.md | ||
''; | ||
}; | ||
}; | ||
dataDir = mkOption { | ||
type = types.path; | ||
default = "/var/lib/joinmarket"; | ||
description = "The data directory for JoinMarket."; | ||
}; | ||
user = mkOption { | ||
type = types.str; | ||
default = "joinmarket"; | ||
description = "The user as which to run JoinMarket."; | ||
}; | ||
group = mkOption { | ||
type = types.str; | ||
default = cfg.user; | ||
description = "The group as which to run JoinMarket."; | ||
}; | ||
cli = mkOption { | ||
default = cli; | ||
}; | ||
inherit (nix-bitcoin-services) cliExec; | ||
}; | ||
|
||
config = mkIf cfg.enable (mkMerge [{ | ||
environment.systemPackages = [ | ||
(hiPrio cfg.cli) | ||
]; | ||
users.users.${cfg.user} = { | ||
description = "joinmarket User"; | ||
group = "${cfg.group}"; | ||
home = cfg.dataDir; | ||
}; | ||
users.groups.${cfg.group} = {}; | ||
|
||
systemd.tmpfiles.rules = [ | ||
"d '${cfg.dataDir}' 0770 ${cfg.user} ${cfg.group} - -" | ||
]; | ||
|
||
services.bitcoind.disablewallet = false; | ||
|
||
# Joinmarket is TOR-only | ||
services.tor = { | ||
enable = true; | ||
client.enable = true; | ||
}; | ||
|
||
systemd.services.joinmarket = { | ||
description = "JoinMarket Daemon"; | ||
wantedBy = [ "multi-user.target" ]; | ||
requires = [ "bitcoind.service" ]; | ||
after = [ "bitcoind.service" ]; | ||
path = [ pkgs.sudo ]; | ||
serviceConfig = nix-bitcoin-services.defaultHardening // { | ||
ExecStartPre = nix-bitcoin-services.privileged '' | ||
install -o '${cfg.user}' -g '${cfg.group}' -m 640 ${configFile} ${cfg.dataDir}/joinmarket.cfg | ||
sed -i \ | ||
"s|@@RPC_PASSWORD@@|rpc_password = $(cat ${secretsDir}/bitcoin-rpcpassword-privileged)|" \ | ||
'${cfg.dataDir}/joinmarket.cfg' | ||
''; | ||
ExecStartPost = nix-bitcoin-services.privileged '' | ||
walletname=wallet.jmdat | ||
pw=$(cat "${secretsDir}"/jm-wallet-password) | ||
mnemonic=${secretsDir}/jm-wallet-seed | ||
if [[ ! -f ${cfg.dataDir}/wallets/$walletname ]]; then | ||
echo Create joinmarket wallet | ||
# Use bash variables so commands don't proceed on previous failures | ||
# (like with pipes) | ||
cd ${cfg.dataDir} && \ | ||
out=$(sudo -u ${cfg.user} \ | ||
${pkgs.nix-bitcoin.joinmarket}/bin/jm-genwallet \ | ||
--datadir=${cfg.dataDir} $walletname $pw) | ||
recoveryseed=$(echo "$out" | grep 'recovery_seed') | ||
echo "$recoveryseed" | cut -d ':' -f2 > $mnemonic | ||
fi | ||
''; | ||
ExecStart = "${pkgs.nix-bitcoin.joinmarket}/bin/joinmarketd"; | ||
WorkingDirectory = "${cfg.dataDir}"; # The service creates 'commitmentlist' in the working dir | ||
User = "${cfg.user}"; | ||
Restart = "on-failure"; | ||
RestartSec = "10s"; | ||
ReadWritePaths = "${cfg.dataDir}"; | ||
} // nix-bitcoin-services.allowTor; | ||
}; | ||
} | ||
|
||
(mkIf cfg.yieldgenerator.enable { | ||
nix-bitcoin.secrets.jm-wallet-password.user = cfg.user; | ||
|
||
systemd.services.joinmarket-yieldgenerator = let | ||
ygDefault = "${pkgs.nix-bitcoin.joinmarket}/bin/jm-yg-privacyenhanced"; | ||
ygBinary = if cfg.yieldgenerator.customParameters == "" then | ||
ygDefault | ||
else | ||
pkgs.runCommand "jm-yieldgenerator-custom" { | ||
inherit (cfg.yieldgenerator) customParameters; | ||
} '' | ||
substitute ${ygDefault} $out \ | ||
--replace "# end of settings customization" "$customParameters" | ||
chmod +x $out | ||
''; | ||
in { | ||
description = "CoinJoin maker bot to gain privacy and passively generate income"; | ||
wantedBy = [ "joinmarket.service" ]; | ||
requires = [ "joinmarket.service" ]; | ||
after = [ "joinmarket.service" ]; | ||
preStart = let | ||
start = '' | ||
exec ${ygBinary} --datadir='${cfg.dataDir}' --wallet-password-stdin wallet.jmdat | ||
''; | ||
in '' | ||
pw=$(cat "${secretsDir}"/jm-wallet-password) | ||
echo "echo -n $pw | ${start}" > $RUNTIME_DIRECTORY/start | ||
''; | ||
serviceConfig = nix-bitcoin-services.defaultHardening // rec { | ||
RuntimeDirectory = "joinmarket-yieldgenerator"; # Only used to create start script | ||
RuntimeDirectoryMode = "700"; | ||
WorkingDirectory = "${cfg.dataDir}"; # The service creates dir 'logs' in the working dir | ||
ExecStart = "${pkgs.bash}/bin/bash /run/${RuntimeDirectory}/start"; | ||
User = "${cfg.user}"; | ||
ReadWritePaths = "${cfg.dataDir}"; | ||
} // nix-bitcoin-services.allowTor; | ||
}; | ||
}) | ||
]); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.