From 8c125ec48c3f3caabab65acd2d7c9f2dffe1a2d3 Mon Sep 17 00:00:00 2001 From: nixbitcoin Date: Sun, 17 Jan 2021 12:24:57 +0000 Subject: [PATCH] joinmarket-obwatcher: add pkg & module --- README.md | 1 + examples/configuration.nix | 2 + modules/joinmarket-ob-watcher.nix | 99 +++++++++++++++++++++++++++++++ modules/modules.nix | 1 + modules/netns-isolation.nix | 5 ++ modules/nodeinfo.nix | 1 + modules/onion-services.nix | 3 + modules/presets/enable-tor.nix | 1 + pkgs/joinmarket/default.nix | 5 ++ test/tests.nix | 2 + test/tests.py | 6 ++ 11 files changed, 126 insertions(+) create mode 100644 modules/joinmarket-ob-watcher.nix diff --git a/README.md b/README.md index 2f5d5f9..e98cd28 100644 --- a/README.md +++ b/README.md @@ -69,6 +69,7 @@ NixOS modules * [liquid](https://github.com/elementsproject/elements) * [Lightning Loop](https://github.com/lightninglabs/loop) * [JoinMarket](https://github.com/joinmarket-org/joinmarket-clientserver) + * [JoinMarket Orderbook Watcher](https://github.com/JoinMarket-Org/joinmarket-clientserver/blob/master/docs/orderbook.md) * [recurring-donations](modules/recurring-donations.nix): for periodic lightning payments * [bitcoin-core-hwi](https://github.com/bitcoin-core/HWI) * Helper diff --git a/examples/configuration.nix b/examples/configuration.nix index 8ebd037..4d92217 100644 --- a/examples/configuration.nix +++ b/examples/configuration.nix @@ -179,6 +179,8 @@ # earn sats by providing CoinJoin liquidity. This makes it impossible to use other # scripts that access your wallet. # services.joinmarket.yieldgenerator.enable = true; + # Enable this option to enable the JoinMarket order book watcher. + # services.joinmarket-ob-watcher.enable = true; # FIXME: Define your hostname. networking.hostName = "nix-bitcoin"; diff --git a/modules/joinmarket-ob-watcher.nix b/modules/joinmarket-ob-watcher.nix new file mode 100644 index 0000000..e65bd7d --- /dev/null +++ b/modules/joinmarket-ob-watcher.nix @@ -0,0 +1,99 @@ +{ config, lib, pkgs, ... }: + +with lib; +let + cfg = config.services.joinmarket-ob-watcher; + inherit (config) nix-bitcoin-services; + nbPkgs = config.nix-bitcoin.pkgs; + torAddress = builtins.head (builtins.split ":" config.services.tor.client.socksListenAddress); + configFile = builtins.toFile "config" '' + [BLOCKCHAIN] + blockchain_source = no-blockchain + + [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 + ''; +in { + options.services.joinmarket-ob-watcher = { + enable = mkEnableOption "JoinMarket orderbook watcher"; + address = mkOption { + type = types.str; + default = "127.0.0.1"; + description = "HTTP server address."; + }; + port = mkOption { + type = types.port; + default = 62601; + description = "HTTP server port."; + }; + dataDir = mkOption { + readOnly = true; + default = "/var/lib/joinmarket-ob-watcher"; + description = "The data directory for JoinMarket orderbook watcher."; + }; + user = mkOption { + type = types.str; + default = "joinmarket-ob-watcher"; + description = "The user as which to run JoinMarket orderbook watcher."; + }; + group = mkOption { + type = types.str; + default = cfg.user; + description = "The group as which to run JoinMarket orderbook watcher."; + }; + # This option is only used by netns-isolation + enforceTor = mkOption { + readOnly = true; + default = true; + }; + }; + + config = mkIf cfg.enable { + services.tor = { + enable = true; + client.enable = true; + }; + + systemd.services.joinmarket-ob-watcher = { + wantedBy = [ "multi-user.target" ]; + requires = [ "tor.service" ]; + after = [ "tor.service" ]; + preStart = '' + ln -snf ${configFile} ${cfg.dataDir}/joinmarket.cfg + ''; + serviceConfig = nix-bitcoin-services.defaultHardening // rec { + StateDirectory = "joinmarket-ob-watcher"; + StateDirectoryMode = "0770"; + WorkingDirectory = "${cfg.dataDir}"; # The service creates dir 'logs' in the working dir + ExecStart = '' + ${nbPkgs.joinmarket}/bin/ob-watcher --datadir=${cfg.dataDir} \ + --host=${cfg.address} --port=${toString cfg.port} + ''; + User = cfg.user; + Restart = "on-failure"; + RestartSec = "10s"; + } // nix-bitcoin-services.allowTor; + }; + + users.users.${cfg.user} = { + group = cfg.group; + home = cfg.dataDir; # The service writes to HOME/.config/matplotlib + }; + users.groups.${cfg.group} = {}; + }; +} diff --git a/modules/modules.nix b/modules/modules.nix index 4788da6..6ca7e18 100644 --- a/modules/modules.nix +++ b/modules/modules.nix @@ -18,6 +18,7 @@ with lib; ./electrs.nix ./liquid.nix ./joinmarket.nix + ./joinmarket-ob-watcher.nix ./hardware-wallets.nix ./recurring-donations.nix diff --git a/modules/netns-isolation.nix b/modules/netns-isolation.nix index 36e5300..e4f02f1 100644 --- a/modules/netns-isolation.nix +++ b/modules/netns-isolation.nix @@ -242,6 +242,9 @@ in { id = 25; connections = [ "bitcoind" ]; }; + joinmarket-ob-watcher = { + id = 26; + }; }; services.bitcoind = { @@ -285,6 +288,8 @@ in { services.joinmarket.cliExec = mkCliExec "joinmarket"; systemd.services.joinmarket-yieldgenerator.serviceConfig.NetworkNamespacePath = "/var/run/netns/nb-joinmarket"; + + services.joinmarket-ob-watcher.address = netns.joinmarket-ob-watcher.address; } ]); } diff --git a/modules/nodeinfo.nix b/modules/nodeinfo.nix index afd3fa6..23f3eb1 100644 --- a/modules/nodeinfo.nix +++ b/modules/nodeinfo.nix @@ -19,6 +19,7 @@ let spark-wallet = mkInfo ""; btcpayserver = mkInfo ""; liquidd = mkInfo ""; + joinmarket-ob-watcher = mkInfo ""; # Only add sshd when it has an onion service sshd = name: cfg: mkIfOnionPort "sshd" (onionPort: '' add_service("sshd", """set_onion_address(info, "sshd", ${onionPort})""") diff --git a/modules/onion-services.nix b/modules/onion-services.nix index db0dac1..f73318f 100644 --- a/modules/onion-services.nix +++ b/modules/onion-services.nix @@ -115,6 +115,9 @@ in { btcpayserver = { externalPort = 80; }; + joinmarket-ob-watcher = { + externalPort = 80; + }; }; } ]; diff --git a/modules/presets/enable-tor.nix b/modules/presets/enable-tor.nix index 8d16a9e..7c5fda5 100644 --- a/modules/presets/enable-tor.nix +++ b/modules/presets/enable-tor.nix @@ -28,5 +28,6 @@ in { liquidd.enable = defaultTrue; electrs.enable = defaultTrue; spark-wallet.enable = defaultTrue; + joinmarket-ob-watcher.enable = defaultTrue; }; } diff --git a/pkgs/joinmarket/default.nix b/pkgs/joinmarket/default.nix index a49b295..4649953 100644 --- a/pkgs/joinmarket/default.nix +++ b/pkgs/joinmarket/default.nix @@ -12,6 +12,7 @@ let joinmarketclient joinmarketbitcoin joinmarketdaemon + matplotlib # for ob-watcher ]; pythonEnv = python3.withPackages (_: runtimePackages); @@ -31,6 +32,7 @@ stdenv.mkDerivation { } cp scripts/joinmarketd.py $out/bin/joinmarketd + cp scripts/obwatch/ob-watcher.py $out/bin/ob-watcher cpBin add-utxo.py cpBin convert_old_wallet.py cpBin receive-payjoin.py @@ -43,5 +45,8 @@ stdenv.mkDerivation { chmod +x -R $out/bin patchShebangs $out/bin + + # This file must be placed in the same dir as ob-watcher + cp scripts/obwatch/orderbook.html $out/bin/orderbook.html ''; } diff --git a/test/tests.nix b/test/tests.nix index 83e4629..95a6604 100644 --- a/test/tests.nix +++ b/test/tests.nix @@ -60,6 +60,7 @@ let testEnv = rec { tests.joinmarket = cfg.joinmarket.enable; tests.joinmarket-yieldgenerator = cfg.joinmarket.yieldgenerator.enable; + tests.joinmarket-ob-watcher = cfg.joinmarket-ob-watcher.enable; services.joinmarket.yieldgenerator = { enable = config.services.joinmarket.enable; customParameters = '' @@ -119,6 +120,7 @@ let testEnv = rec { services.liquidd.enable = true; services.btcpayserver.enable = true; services.joinmarket.enable = true; + services.joinmarket-ob-watcher.enable = true; services.backups.enable = true; nix-bitcoin.nodeinfo.enable = true; diff --git a/test/tests.py b/test/tests.py index 329dcc6..49f881b 100644 --- a/test/tests.py +++ b/test/tests.py @@ -216,6 +216,12 @@ def _(): ) +@test("joinmarket-ob-watcher") +def _(): + assert_running("joinmarket-ob-watcher") + machine.wait_until_succeeds(log_has_string("joinmarket-ob-watcher", "Starting ob-watcher")) + + @test("nodeinfo") def _(): status, _ = machine.execute("systemctl is-enabled --quiet onion-addresses 2> /dev/null")