|
41 | 41 | description = "The data directory for JoinMarket."; |
42 | 42 | }; |
43 | 43 | rpcWalletFile = mkOption { |
44 | | - type = types.nullOr types.str; |
| 44 | + type = types.nullOr types.nonEmptyStr; |
45 | 45 | default = "jm_wallet"; |
46 | 46 | description = '' |
47 | 47 | Name of the watch-only bitcoind wallet the JoinMarket addresses are imported to. |
48 | 48 | ''; |
49 | 49 | }; |
| 50 | + settings = mkOption { |
| 51 | + type = with types; attrsOf anything; |
| 52 | + example = { |
| 53 | + POLICY = { |
| 54 | + merge_algorithm = "gradual"; |
| 55 | + tx_fees = 5; |
| 56 | + }; |
| 57 | + LOGGING = { |
| 58 | + console_log_level = "DEBUG"; |
| 59 | + }; |
| 60 | + }; |
| 61 | + description = '' |
| 62 | + Joinmarket settings. |
| 63 | + See here for possible options: |
| 64 | + https://raw.githubusercontent.com/JoinMarket-Org/joinmarket-clientserver/master/src/jmclient/configure.py#:~:text=defaultconfig%20= |
| 65 | + If your web browser does not support text fragment URLs, you can can manually |
| 66 | + search for string `defaultconfig =` to jump to the correct location. |
| 67 | + ''; |
| 68 | + }; |
50 | 69 | user = mkOption { |
51 | 70 | type = types.str; |
52 | 71 | default = "joinmarket"; |
|
61 | 80 | default = cli; |
62 | 81 | defaultText = "(See source)"; |
63 | 82 | }; |
64 | | - # Used by ./joinmarket-ob-watcher.nix |
65 | | - messagingConfig = mkOption { |
66 | | - readOnly = true; |
67 | | - default = messagingConfig; |
68 | | - defaultText = "(See source)"; |
69 | | - }; |
70 | 83 | # This option is only used by netns-isolation. |
71 | 84 | # Tor is always enabled. |
72 | 85 | tor.enforce = nbLib.tor.enforce; |
73 | 86 | inherit (nbLib) cliExec; |
74 | 87 |
|
75 | 88 | yieldgenerator = { |
76 | | - enable = mkEnableOption "JoinMarket yield generator bot"; |
| 89 | + enable = mkOption { |
| 90 | + type = types.bool; |
| 91 | + default = false; |
| 92 | + description = '' |
| 93 | + Enable the JoinMarket yield generator bot. |
| 94 | + Documentation: https://github.com/JoinMarket-Org/joinmarket-clientserver/blob/master/docs/YIELDGENERATOR.md |
| 95 | + ''; |
| 96 | + }; |
77 | 97 | ordertype = mkOption { |
78 | 98 | type = types.enum [ "reloffer" "absoffer" ]; |
79 | 99 | default = "reloffer"; |
|
102 | 122 | Variance around the average cj fee. |
103 | 123 | ''; |
104 | 124 | }; |
105 | | - txfee = mkOption { |
106 | | - type = types.ints.unsigned; |
107 | | - default = 100; |
108 | | - description = '' |
109 | | - The average transaction fee you're adding to coinjoin transactions. |
110 | | - ''; |
111 | | - }; |
112 | 125 | txfee_contribution_factor = mkOption { |
113 | 126 | type = types.float; |
114 | 127 | default = 0.3; |
@@ -142,124 +155,12 @@ let |
142 | 155 | inherit (config.services) bitcoind; |
143 | 156 |
|
144 | 157 | torAddress = config.services.tor.client.socksListenAddress; |
145 | | - socks5Settings = '' |
146 | | - socks5 = true |
147 | | - socks5_host = ${torAddress.addr} |
148 | | - socks5_port = ${toString torAddress.port} |
149 | | - ''; |
150 | | - |
151 | | - messagingConfig = '' |
152 | | - [MESSAGING:onion] |
153 | | - type = onion |
154 | | - ${socks5Settings} |
155 | | - tor_control_host = unix:/run/tor/control |
156 | | - # required option, but ignored for unix socket host |
157 | | - tor_control_port = 9051 |
158 | | - onion_serving_host = ${cfg.messagingAddress} |
159 | | - onion_serving_port = ${toString cfg.messagingPort} |
160 | | - hidden_service_dir = |
161 | | - directory_nodes = g3hv4uynnmynqqq2mchf3fcm3yd46kfzmcdogejuckgwknwyq5ya6iad.onion:5222,3kxw6lf5vf6y26emzwgibzhrzhmhqiw6ekrek3nqfjjmhwznb2moonad.onion:5222,bqlpq6ak24mwvuixixitift4yu42nxchlilrcqwk2ugn45tdclg42qid.onion:5222 |
162 | | -
|
163 | | - # irc.darkscience.net |
164 | | - [MESSAGING:server1] |
165 | | - host = darkirc6tqgpnwd3blln3yfv5ckl47eg7llfxkmtovrv7c7iwohhb6ad.onion |
166 | | - channel = joinmarket-pit |
167 | | - port = 6697 |
168 | | - usessl = true |
169 | | - ${socks5Settings} |
170 | | -
|
171 | | - # ilita |
172 | | - [MESSAGING:server2] |
173 | | - host = ilitafrzzgxymv6umx2ux7kbz3imyeko6cnqkvy4nisjjj4qpqkrptid.onion |
174 | | - channel = joinmarket-pit |
175 | | - port = 6667 |
176 | | - usessl = false |
177 | | - ${socks5Settings} |
178 | | -
|
179 | | - # irc.hackint.org |
180 | | - [MESSAGING:server3] |
181 | | - host = ncwkrwxpq2ikcngxq3dy2xctuheniggtqeibvgofixpzvrwpa77tozqd.onion |
182 | | - channel = joinmarket-pit |
183 | | - port = 6667 |
184 | | - usessl = false |
185 | | - ${socks5Settings} |
186 | | - ''; |
187 | | - |
188 | | - # Based on https://github.com/JoinMarket-Org/joinmarket-clientserver/blob/master/jmclient/jmclient/configure.py |
189 | | - yg = cfg.yieldgenerator; |
190 | | - configFile = builtins.toFile "config" '' |
191 | | - [DAEMON] |
192 | | - no_daemon = 0 |
193 | | - daemon_port = 27183 |
194 | | - daemon_host = 127.0.0.1 |
195 | | - use_ssl = false |
196 | | -
|
197 | | - [BLOCKCHAIN] |
198 | | - blockchain_source = ${bitcoind.makeNetworkName "bitcoin-rpc" "regtest"} |
199 | | - network = ${bitcoind.makeNetworkName "mainnet" "testnet"} |
200 | | - rpc_host = ${nbLib.address bitcoind.rpc.address} |
201 | | - rpc_port = ${toString bitcoind.rpc.port} |
202 | | - rpc_user = ${bitcoind.rpc.users.privileged.name} |
203 | | - ${optionalString (cfg.rpcWalletFile != null) "rpc_wallet_file = ${cfg.rpcWalletFile}"} |
204 | | -
|
205 | | - ${messagingConfig} |
206 | 158 |
|
207 | | - [LOGGING] |
208 | | - console_log_level = INFO |
209 | | - color = false |
210 | | -
|
211 | | - [POLICY] |
212 | | - segwit = true |
213 | | - native = true |
214 | | - merge_algorithm = default |
215 | | - gaplimit = 6 |
216 | | - tx_fees = 3 |
217 | | - tx_fees_factor = 0.2 |
218 | | - absurd_fee_per_kb = 350000 |
219 | | - max_sweep_fee_change = 0.8 |
220 | | - tx_broadcast = self |
221 | | - minimum_makers = 4 |
222 | | - max_sats_freeze_reuse = -1 |
223 | | - interest_rate = 0.015 |
224 | | - bondless_makers_allowance = 0.125 |
225 | | - bond_value_exponent = 1.3 |
226 | | - taker_utxo_retries = 3 |
227 | | - taker_utxo_age = 5 |
228 | | - taker_utxo_amtpercent = 20 |
229 | | - accept_commitment_broadcasts = 1 |
230 | | - commit_file_location = cmtdata/commitments.json |
231 | | - commitment_list_location = cmtdata/commitmentlist |
232 | | -
|
233 | | - [PAYJOIN] |
234 | | - payjoin_version = 1 |
235 | | - disable_output_substitution = 0 |
236 | | - max_additional_fee_contribution = default |
237 | | - min_fee_rate = 1.1 |
238 | | - onion_socks5_host = ${torAddress.addr} |
239 | | - onion_socks5_port = ${toString torAddress.port} |
240 | | - tor_control_host = unix:/run/tor/control |
241 | | - # Required option, but unused because `tor_control_host` is a Unix socket |
242 | | - tor_control_port = 9051 |
243 | | - onion_serving_host = ${cfg.payjoinAddress} |
244 | | - onion_serving_port = ${toString cfg.payjoinPort} |
245 | | - hidden_service_ssl = false |
246 | | -
|
247 | | - [YIELDGENERATOR] |
248 | | - ordertype = ${yg.ordertype} |
249 | | - cjfee_a = ${toString yg.cjfee_a} |
250 | | - cjfee_r = ${toString yg.cjfee_r} |
251 | | - cjfee_factor = ${toString yg.cjfee_factor} |
252 | | - txfee_contribution = 0 |
253 | | - txfee_contribution_factor = ${toString yg.txfee_contribution_factor} |
254 | | - minsize = ${toString yg.minsize} |
255 | | - size_factor = ${toString yg.size_factor} |
256 | | -
|
257 | | - [SNICKER] |
258 | | - enabled = false |
259 | | - lowest_net_gain = 0 |
260 | | - servers = cn5lfwvrswicuxn3gjsxoved6l2gu5hdvwy5l3ev7kg6j7lbji2k7hqd.onion, |
261 | | - polling_interval_minutes = 60 |
262 | | - ''; |
| 159 | + socks5Settings = { |
| 160 | + socks5 = true; |
| 161 | + socks5_host = torAddress.addr; |
| 162 | + socks5_port = torAddress.port; |
| 163 | + }; |
263 | 164 |
|
264 | 165 | # The jm scripts create a 'logs' dir in the working dir, |
265 | 166 | # so run them inside dataDir. |
|
278 | 179 | in { |
279 | 180 | inherit options; |
280 | 181 |
|
281 | | - config = mkIf cfg.enable (mkMerge [{ |
| 182 | + config = mkMerge [ |
| 183 | + { |
| 184 | + services.joinmarket.settings = { |
| 185 | + DAEMON = { |
| 186 | + no_daemon = 0; |
| 187 | + daemon_port = 27183; |
| 188 | + daemon_host = "127.0.0.1"; |
| 189 | + }; |
| 190 | + BLOCKCHAIN = { |
| 191 | + blockchain_source = bitcoind.makeNetworkName "bitcoin-rpc" "regtest"; |
| 192 | + network = bitcoind.makeNetworkName "mainnet" "testnet"; |
| 193 | + rpc_host = nbLib.address bitcoind.rpc.address; |
| 194 | + rpc_port = bitcoind.rpc.port; |
| 195 | + rpc_user = bitcoind.rpc.users.privileged.name; |
| 196 | + rpc_wallet_file = if cfg.rpcWalletFile == null then "" else cfg.rpcWalletFile; |
| 197 | + }; |
| 198 | + LOGGING = { |
| 199 | + color = false; |
| 200 | + }; |
| 201 | + PAYJOIN = { |
| 202 | + onion_socks5_host = torAddress.addr; |
| 203 | + onion_socks5_port = torAddress.port; |
| 204 | + tor_control_host = "unix:/run/tor/control"; |
| 205 | + onion_serving_host = cfg.payjoinAddress; |
| 206 | + onion_serving_port = cfg.payjoinPort; |
| 207 | + hidden_service_ssl = false; |
| 208 | + }; |
| 209 | + YIELDGENERATOR = removeAttrs cfg.yieldgenerator [ |
| 210 | + "enable" |
| 211 | + # TODO: This is only needed when ./obsolete-options.nix is imported |
| 212 | + "txfee" |
| 213 | + ]; |
| 214 | + |
| 215 | + # Messaging settings have to be fully specified because joinmarket doesn't |
| 216 | + # provide default messaging settings. |
| 217 | + # (`jmclient/configure.py` actually does contain default messaging settings, but |
| 218 | + # they are removed via fn `_remove_unwanted_default_settings`) |
| 219 | + "MESSAGING:onion" = socks5Settings // { |
| 220 | + type = "onion"; |
| 221 | + tor_control_host = "unix:/run/tor/control"; |
| 222 | + # Required option, but ignored because `tor_control_host` is a unix socket |
| 223 | + tor_control_port = 9051; |
| 224 | + onion_serving_host = cfg.messagingAddress; |
| 225 | + onion_serving_port = cfg.messagingPort; |
| 226 | + hidden_service_dir = ""; |
| 227 | + directory_nodes = "g3hv4uynnmynqqq2mchf3fcm3yd46kfzmcdogejuckgwknwyq5ya6iad.onion:5222,3kxw6lf5vf6y26emzwgibzhrzhmhqiw6ekrek3nqfjjmhwznb2moonad.onion:5222,bqlpq6ak24mwvuixixitift4yu42nxchlilrcqwk2ugn45tdclg42qid.onion:5222"; |
| 228 | + }; |
| 229 | + # irc.darkscience.net |
| 230 | + "MESSAGING:server1" = socks5Settings // { |
| 231 | + host = "darkirc6tqgpnwd3blln3yfv5ckl47eg7llfxkmtovrv7c7iwohhb6ad.onion"; |
| 232 | + channel = "joinmarket-pit"; |
| 233 | + port = 6697; |
| 234 | + usessl = true; |
| 235 | + }; |
| 236 | + # ilita |
| 237 | + "MESSAGING:server2" = socks5Settings // { |
| 238 | + host = "ilitafrzzgxymv6umx2ux7kbz3imyeko6cnqkvy4nisjjj4qpqkrptid.onion"; |
| 239 | + channel = "joinmarket-pit"; |
| 240 | + port = 6667; |
| 241 | + usessl = false; |
| 242 | + }; |
| 243 | + # irc.hackint.org |
| 244 | + "MESSAGING:server3" = socks5Settings // { |
| 245 | + host = "ncwkrwxpq2ikcngxq3dy2xctuheniggtqeibvgofixpzvrwpa77tozqd.onion"; |
| 246 | + channel = "joinmarket-pit"; |
| 247 | + port = 6667; |
| 248 | + usessl = false; |
| 249 | + }; |
| 250 | + }; |
| 251 | + } |
| 252 | + |
| 253 | + (mkIf cfg.enable { |
282 | 254 | services.bitcoind = { |
283 | 255 | enable = true; |
284 | 256 | disablewallet = false; |
|
311 | 283 | after = [ "bitcoind.service" "nix-bitcoin-secrets.target" ]; |
312 | 284 | preStart = '' |
313 | 285 | { |
314 | | - cat ${configFile} |
| 286 | + cat ${builtins.toFile "joinmarket.cfg" ((generators.toINI {}) cfg.settings)} |
315 | 287 | echo |
316 | 288 | echo '[BLOCKCHAIN]' |
317 | 289 | echo "rpc_password = $(cat ${secretsDir}/bitcoin-rpcpassword-privileged)" |
|
386 | 358 | nix-bitcoin.generateSecretsCmds.joinmarket = '' |
387 | 359 | makePasswordSecret jm-wallet-password |
388 | 360 | ''; |
389 | | - } |
| 361 | + }) |
390 | 362 |
|
391 | | - (mkIf cfg.yieldgenerator.enable { |
| 363 | + (mkIf (cfg.enable && cfg.yieldgenerator.enable) { |
392 | 364 | systemd.services.joinmarket-yieldgenerator = { |
393 | 365 | wantedBy = [ "joinmarket.service" ]; |
394 | 366 | requires = [ "joinmarket.service" ]; |
|
409 | 381 | } // nbLib.allowTor; |
410 | 382 | }; |
411 | 383 | }) |
412 | | - ]); |
| 384 | + ]; |
413 | 385 | } |
0 commit comments