From c5644dfbc4e96c6bec4da39c241f18f3880a87af Mon Sep 17 00:00:00 2001 From: Alex Cato Date: Sun, 22 Jul 2018 12:56:09 +0200 Subject: [PATCH] Fixes the sweep issue (#171), in which a maker with severals offers has a higher chance to be selected by a taker's sweeping coinjoin. This is done by approximating the cjamount ceiling and filtering to one offer per maker before the actual selection algorithm runs. --- jmclient/jmclient/support.py | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/jmclient/jmclient/support.py b/jmclient/jmclient/support.py index 7020d4f..5906f1f 100644 --- a/jmclient/jmclient/support.py +++ b/jmclient/jmclient/support.py @@ -233,6 +233,7 @@ def choose_orders(offers, cj_amount, n, chooseOrdersBy, ignored_makers=None, """ feekey = lambda x: x[1] if not pick: + # filter to only the cheapest suitable offer for each maker orders_fees = sorted( dict((v[0]['counterparty'], v) for v in sorted(orders_fees, @@ -248,6 +249,7 @@ def choose_orders(offers, cj_amount, n, chooseOrdersBy, ignored_makers=None, for i in range(n): chosen_order, chosen_fee = chooseOrdersBy(orders_fees, n) # remove all orders from that same counterparty + # only needed if offers are manually picked orders_fees = [o for o in orders_fees if o[0]['counterparty'] != chosen_order['counterparty']] @@ -305,6 +307,8 @@ def choose_sweep_orders(offers, #Filter ignored makers and inappropriate amounts offers = [o for o in offers if o['counterparty'] not in ignored_makers] offers = [o for o in offers if o['minsize'] < total_input_value] + # while we do not know the exact cj value yet, we can approximate a ceiling: + offers = [o for o in offers if o['maxsize'] > (total_input_value - total_txfee)] log.debug('orderlist = \n' + '\n'.join([str(o) for o in offers])) orders_fees = [(o, calc_cj_fee(o['ordertype'], o['cjfee'], @@ -312,7 +316,13 @@ def choose_sweep_orders(offers, feekey = lambda x: x[1] # sort from smallest to biggest cj fee - orders_fees = sorted(orders_fees, key=feekey) + # filter to only the cheapest suitable offer for each maker + orders_fees = sorted( + dict((v[0]['counterparty'], v) + for v in sorted(orders_fees, + key=feekey, + reverse=True)).values(), + key=feekey) chosen_orders = [] while len(chosen_orders) < n: for i in range(n - len(chosen_orders)):