diff --git a/joinmarket/maker.py b/joinmarket/maker.py index e42cf6f5..5accf60a 100644 --- a/joinmarket/maker.py +++ b/joinmarket/maker.py @@ -234,7 +234,8 @@ def verify_unsigned_tx(self, txd): if outs['value'] != expected_change_value: return False, 'wrong change, i expect ' + str( expected_change_value) - if times_seen_cj_addr != 1 or times_seen_change_addr != 1: + if (times_seen_cj_addr != 1 or # allow "sweeping" empty change + (expected_change_value != 0 and times_seen_change_addr != 1)): fmt = ('cj or change addr not in tx ' 'outputs once, #cjaddr={}, #chaddr={}').format return False, (fmt(times_seen_cj_addr, times_seen_change_addr)) diff --git a/joinmarket/taker.py b/joinmarket/taker.py index 59b50238..8e6da28f 100644 --- a/joinmarket/taker.py +++ b/joinmarket/taker.py @@ -179,18 +179,16 @@ def recv_txio(self, nick, utxo_list, auth_pub, cj_addr, change_addr): change_amount = (total_input - self.cj_amount - self.active_orders[nick]['txfee'] + real_cjfee) - # certain malicious and/or incompetent liquidity providers send - # inputs totalling less than the coinjoin amount! this leads to - # a change output of zero satoshis, so the invalid transaction - # fails harmlessly; let's fail earlier, with a clear message. - if change_amount < jm_single().BITCOIN_DUST_THRESHOLD: - fmt = ('ERROR counterparty requires sub-dust change. No ' - 'action required. nick={}' + # change must either be above the DUST_THRESHOLD, or exactly zero + if change_amount != 0 and change_amount < jm_single().DUST_THRESHOLD: + fmt = ('ERROR counterparty requires sub-dust change. nick={}' 'totalin={:d} cjamount={:d} change={:d}').format - log.warn(fmt(nick, total_input, self.cj_amount, change_amount)) + log.debug(fmt(nick, total_input, self.cj_amount, change_amount)) return # timeout marks this maker as nonresponsive - self.outputs.append({'address': change_addr, 'value': change_amount}) + if change_amount != 0: # FIXME add support for this from maker-side + self.outputs.append({'address': change_addr, 'value': change_amount}) + fmt = ('fee breakdown for {} totalin={:d} ' 'cjamount={:d} txfee={:d} realcjfee={:d}').format log.debug(fmt(nick, total_input, self.cj_amount,