diff --git a/jmbase/jmbase/commands.py b/jmbase/jmbase/commands.py index ec039c3..935d30e 100644 --- a/jmbase/jmbase/commands.py +++ b/jmbase/jmbase/commands.py @@ -31,7 +31,8 @@ class JMInit(JMCommand): (b'network', Unicode()), (b'irc_configs', Unicode()), (b'minmakers', Integer()), - (b'maker_timeout_sec', Integer())] + (b'maker_timeout_sec', Integer()), + (b'dust_threshold', Integer())] errors = {DaemonNotReady: b'daemon is not ready'} class JMStartMC(JMCommand): diff --git a/jmbase/jmbase/support.py b/jmbase/jmbase/support.py index 7fe91b6..6429e9a 100644 --- a/jmbase/jmbase/support.py +++ b/jmbase/jmbase/support.py @@ -71,9 +71,6 @@ joinmarket_alert = [''] core_alert = [''] debug_silence = [False] -#TODO pass this through from client, bitcoin paramater: -DUST_THRESHOLD = 2730 - class JoinMarketStreamHandler(ColorizingStreamHandler): def __init__(self): diff --git a/jmbitcoin/jmbitcoin/__init__.py b/jmbitcoin/jmbitcoin/__init__.py index 999e603..f3a3d50 100644 --- a/jmbitcoin/jmbitcoin/__init__.py +++ b/jmbitcoin/jmbitcoin/__init__.py @@ -14,6 +14,9 @@ if os.path.exists(expected_secp_location): import bitcointx bitcointx.set_custom_secp256k1_path(expected_secp_location) +# Bitcoin network level utxo amount limit: +DUST_THRESHOLD = 2730 + from jmbitcoin.secp256k1_main import * from jmbitcoin.secp256k1_transaction import * from jmbitcoin.secp256k1_deterministic import * diff --git a/jmclient/jmclient/client_protocol.py b/jmclient/jmclient/client_protocol.py index 45155c9..d19b32b 100644 --- a/jmclient/jmclient/client_protocol.py +++ b/jmclient/jmclient/client_protocol.py @@ -425,7 +425,8 @@ class JMMakerClientProtocol(JMClientProtocol): network=network, irc_configs=json.dumps(irc_configs), minmakers=minmakers, - maker_timeout_sec=maker_timeout_sec) + maker_timeout_sec=maker_timeout_sec, + dust_threshold=jm_single().DUST_THRESHOLD) self.defaultCallbacks(d) @commands.JMFidelityBondProofRequest.responder @@ -602,7 +603,8 @@ class JMTakerClientProtocol(JMClientProtocol): network=network, irc_configs=json.dumps(irc_configs), minmakers=minmakers, - maker_timeout_sec=maker_timeout_sec) + maker_timeout_sec=maker_timeout_sec, + dust_threshold=jm_single().DUST_THRESHOLD) self.defaultCallbacks(d) def stallMonitor(self, schedule_index): diff --git a/jmclient/jmclient/configure.py b/jmclient/jmclient/configure.py index 97955c5..e648681 100644 --- a/jmclient/jmclient/configure.py +++ b/jmclient/jmclient/configure.py @@ -63,7 +63,7 @@ global_singleton.JM_VERSION = 5 global_singleton.APPNAME = JM_APP_NAME global_singleton.datadir = None global_singleton.nickname = None -global_singleton.BITCOIN_DUST_THRESHOLD = 2730 +global_singleton.BITCOIN_DUST_THRESHOLD = btc.DUST_THRESHOLD global_singleton.DUST_THRESHOLD = 10 * global_singleton.BITCOIN_DUST_THRESHOLD global_singleton.bc_interface = None global_singleton.maker_timeout_sec = 60 diff --git a/jmclient/test/test_client_protocol.py b/jmclient/test/test_client_protocol.py index 7ade6db..fa15b6e 100644 --- a/jmclient/test/test_client_protocol.py +++ b/jmclient/test/test_client_protocol.py @@ -166,9 +166,9 @@ class JMTestServerProtocol(JMBaseProtocol): @JMInit.responder def on_JM_INIT(self, bcsource, network, irc_configs, minmakers, - maker_timeout_sec): + maker_timeout_sec, dust_threshold): show_receipt("JMINIT", bcsource, network, irc_configs, minmakers, - maker_timeout_sec) + maker_timeout_sec, dust_threshold) d = self.callRemote(JMInitProto, nick_hash_length=1, nick_max_encoded=2, diff --git a/jmdaemon/jmdaemon/daemon_protocol.py b/jmdaemon/jmdaemon/daemon_protocol.py index c2992fd..44280c9 100644 --- a/jmdaemon/jmdaemon/daemon_protocol.py +++ b/jmdaemon/jmdaemon/daemon_protocol.py @@ -495,7 +495,7 @@ class JMDaemonServerProtocol(amp.AMP, OrderbookWatch): @JMInit.responder def on_JM_INIT(self, bcsource, network, irc_configs, minmakers, - maker_timeout_sec): + maker_timeout_sec, dust_threshold): """Reads in required configuration from client for a new session; feeds back joinmarket messaging protocol constants (required for nick creation). @@ -503,6 +503,8 @@ class JMDaemonServerProtocol(amp.AMP, OrderbookWatch): one is shutdown in preparation. """ self.maker_timeout_sec = int(maker_timeout_sec) + # used in OrderbookWatch: + self.dust_threshold = int(dust_threshold) self.minmakers = int(minmakers) irc_configs = json.loads(irc_configs) #(bitcoin) network only referenced in channel name construction diff --git a/jmdaemon/jmdaemon/orderbookwatch.py b/jmdaemon/jmdaemon/orderbookwatch.py index abd8b57..2b02590 100644 --- a/jmdaemon/jmdaemon/orderbookwatch.py +++ b/jmdaemon/jmdaemon/orderbookwatch.py @@ -8,7 +8,7 @@ from numbers import Integral from jmdaemon.protocol import JM_VERSION from jmdaemon import fidelity_bond_sanity_check -from jmbase.support import get_log, joinmarket_alert, DUST_THRESHOLD +from jmbase.support import get_log, joinmarket_alert log = get_log() @@ -88,8 +88,8 @@ class OrderbookWatch(object): log.debug("Got invalid minsize: {} from {}".format( minsize, counterparty)) return - if int(minsize) < DUST_THRESHOLD: - minsize = DUST_THRESHOLD + if int(minsize) < self.dust_threshold: + minsize = self.dust_threshold log.debug("{} has dusty minsize, capping at {}".format( counterparty, minsize)) # do not pass return, go not drop this otherwise fine offer diff --git a/jmdaemon/test/test_daemon_protocol.py b/jmdaemon/test/test_daemon_protocol.py index 8d44d47..4d19413 100644 --- a/jmdaemon/test/test_daemon_protocol.py +++ b/jmdaemon/test/test_daemon_protocol.py @@ -66,7 +66,8 @@ class JMTestClientProtocol(JMBaseProtocol): network="dummynetwork", irc_configs=json.dumps(irc), minmakers=2, - maker_timeout_sec=3) + maker_timeout_sec=3, + dust_threshold=27300) self.defaultCallbacks(d) @JMInitProto.responder @@ -213,8 +214,9 @@ class JMDaemonTestServerProtocol(JMDaemonServerProtocol): @JMInit.responder def on_JM_INIT(self, bcsource, network, irc_configs, minmakers, - maker_timeout_sec): + maker_timeout_sec, dust_threshold): self.maker_timeout_sec = int(maker_timeout_sec) + self.dust_threshold = int(dust_threshold) self.minmakers = int(minmakers) mcs = [DummyMC(None)] self.mcc = MessageChannelCollection(mcs) diff --git a/jmdaemon/test/test_orderbookwatch.py b/jmdaemon/test/test_orderbookwatch.py index 1232787..50d7f71 100644 --- a/jmdaemon/test/test_orderbookwatch.py +++ b/jmdaemon/test/test_orderbookwatch.py @@ -30,6 +30,9 @@ def get_ob(): ob = OrderbookWatch() ob.on_welcome = on_welcome ob.set_msgchan(mc) + # would usually be set in JMInit; we use + # a fake small value to allow small orders: + ob.dust_threshold = 2 return ob @pytest.mark.parametrize( diff --git a/scripts/joinmarket-qt.py b/scripts/joinmarket-qt.py index 4c53130..9f0182c 100755 --- a/scripts/joinmarket-qt.py +++ b/scripts/joinmarket-qt.py @@ -56,7 +56,7 @@ donation_address_url = "https://bitcoinprivacy.me/joinmarket-donations" JM_GUI_VERSION = '22dev' from jmbase import get_log, stop_reactor -from jmbase.support import DUST_THRESHOLD, EXIT_FAILURE, utxo_to_utxostr,\ +from jmbase.support import EXIT_FAILURE, utxo_to_utxostr,\ hextobin, JM_CORE_VERSION import jmbitcoin as btc from jmclient import load_program_config, get_network, update_persist_config,\ @@ -370,11 +370,11 @@ class SpendTab(QWidget): except ValueError as e: JMQtMessageBox(self, e.args[0], title="Error", mbtype="warn") return False - if amount_sat < DUST_THRESHOLD: + if amount_sat < jm_single().DUST_THRESHOLD: JMQtMessageBox(self, "Amount " + btc.amount_to_str(amount_sat) + " is below dust threshold " + - btc.amount_to_str(DUST_THRESHOLD) + ".", + btc.amount_to_str(jm_single().DUST_THRESHOLD) + ".", mbtype='warn', title="Error") return False diff --git a/scripts/sendpayment.py b/scripts/sendpayment.py index c152a90..ef104b5 100755 --- a/scripts/sendpayment.py +++ b/scripts/sendpayment.py @@ -21,7 +21,7 @@ from jmclient import Taker, load_program_config, get_schedule,\ detect_script_type, EngineError from twisted.python.log import startLogging from jmbase.support import get_log, jmprint, \ - EXIT_FAILURE, EXIT_ARGERROR, DUST_THRESHOLD + EXIT_FAILURE, EXIT_ARGERROR import jmbitcoin as btc @@ -102,10 +102,10 @@ def main(): jmprint("The required options for burning coins are zero makers" + " (-N 0), sweeping (amount = 0) and not using BIP78 Payjoin", "info") sys.exit(EXIT_ARGERROR) - if sweeping == False and amount < DUST_THRESHOLD: + if sweeping == False and amount < jm_single().DUST_THRESHOLD: jmprint('ERROR: Amount ' + btc.amount_to_str(amount) + ' is below dust threshold ' + - btc.amount_to_str(DUST_THRESHOLD) + '.', "error") + btc.amount_to_str(jm_single().DUST_THRESHOLD) + '.', "error") sys.exit(EXIT_ARGERROR) if (options.makercount != 0 and options.makercount < jm_single().config.getint(