From 00ae19b4357a6ba88c7576c455e3bacb140f4f63 Mon Sep 17 00:00:00 2001 From: Alex Cato Date: Fri, 17 Feb 2017 23:36:08 +0100 Subject: [PATCH] takers: ignore makers with more than max_offers_allowed (configurable, default 15) offers --- joinmarket/configure.py | 13 +++++++++++++ joinmarket/taker.py | 11 ++++++++--- 2 files changed, 21 insertions(+), 3 deletions(-) diff --git a/joinmarket/configure.py b/joinmarket/configure.py index 1d35af0c..43f66de3 100644 --- a/joinmarket/configure.py +++ b/joinmarket/configure.py @@ -60,6 +60,7 @@ def __getitem__(self, key): global_singleton.ordername_list = ['absoffer', 'reloffer'] global_singleton.commitment_broadcast_list = ['hp2'] global_singleton.maker_timeout_sec = 60 +global_singleton.max_maker_offers_allowed = 15 global_singleton.debug_file_lock = threading.Lock() global_singleton.debug_file_handle = None global_singleton.blacklist_file_lock = threading.Lock() @@ -131,6 +132,11 @@ def jm_single(): # responsive. Should be an integer >=2 for privacy, or set to 0 if you # want to disallow any reduction from your chosen number of makers. minimum_makers = 2 +# For takers: to filter out potentially malicious makers, this is +# the maximum number of offers a maker is allowed to have. If a +# makers has more offers, then he will be disregarded as potential +# counterparty for coinjoins +max_maker_offers_allowed = 15 # the fee estimate is based on a projection of how many satoshis # per kB are needed to get in one of the next N blocks, N set here # as the value of 'tx_fees'. This estimate is high if you set N=2, @@ -348,6 +354,13 @@ def load_program_config(): log.info('TIMEOUT/maker_timeout_sec not found in .cfg file, ' 'using default value') + try: + global_singleton.max_maker_offers_allowed = global_singleton.config.getint( + 'POLICY', 'max_maker_offers_allowed') + except NoOptionError: + log.info('POLICY/max_maker_offers_allowed not found in .cfg file, ' + 'using default value') + # configure the interface to the blockchain on startup global_singleton.bc_interface = get_blockchain_interface_instance( global_singleton.config) diff --git a/joinmarket/taker.py b/joinmarket/taker.py index 59b50238..d266fbdc 100644 --- a/joinmarket/taker.py +++ b/joinmarket/taker.py @@ -542,6 +542,7 @@ def __init__(self, msgchan): self.msgchan.register_channel_callbacks( self.on_welcome, self.on_set_topic, None, self.on_disconnect, self.on_nick_leave, None) + self.banned_makers = [] self.dblock = threading.Lock() con = sqlite3.connect(":memory:", check_same_thread=False) con.row_factory = sqlite3.Row @@ -552,11 +553,16 @@ def __init__(self, msgchan): def on_order_seen(self, counterparty, oid, ordertype, minsize, maxsize, txfee, cjfee): + if counterparty in self.banned_makers: + log.debug('Saw offer by blacklisted maker, ignoring: ' + str(counterparty)) + return try: self.dblock.acquire(True) - if int(oid) < 0 or int(oid) > sys.maxint: + if int(oid) < 0 or int(oid) >= jm_single().config.getint("POLICY", "max_maker_offers_allowed"): log.debug( - "Got invalid order ID: " + oid + " from " + counterparty) + "Got invalid order ID: " + oid + " from " + counterparty + ". Adding to blacklist.") + self.db.execute("DELETE FROM orderbook WHERE counterparty=?;", (counterparty, )) + self.banned_makers.append(counterparty) return # delete orders eagerly, so in case a buggy maker sends an # invalid offer, we won't accidentally !fill based on the ghost @@ -582,7 +588,6 @@ def on_order_seen(self, counterparty, oid, ordertype, minsize, maxsize, txfee, counterparty)) return if int(minsize) > int(maxsize): - fmt = ("Got minsize bigger than maxsize: {} - {} " "from {}").format log.debug(fmt(minsize, maxsize, counterparty))