From f539b02ed7b283670f05df1170b8956c8ef45d91 Mon Sep 17 00:00:00 2001 From: AdamISZ Date: Fri, 25 Jan 2019 17:25:28 +0100 Subject: [PATCH] Check sequence and locktime are conforming to payjoin v0 in transaction from receiver to sender. Also add note about implicit defence against attack mentioned in BIP79; we only ever sign the predetermined set of inputs. --- jmclient/jmclient/taker.py | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/jmclient/jmclient/taker.py b/jmclient/jmclient/taker.py index 78b45b9..93f20ed 100644 --- a/jmclient/jmclient/taker.py +++ b/jmclient/jmclient/taker.py @@ -1054,6 +1054,18 @@ class P2EPTaker(Taker): ins['outpoint']['index']) for ins in tx['ins']) if not tx_utxo_set.issuperset(set(self.utxos[None])): return (False, "my utxos are not contained") + # Check that the sequence numbers of all inputs are unaltered + # from the intended 0xffffffff - 1, and that the locktime + # is not zero (could go further and check exact block). + # Note that this is hacky and is most elegantly addressed by + # use of PSBT (although any object encapsulation of tx input + # would serve the same purpose). + if tx["locktime"] == 0: + return (False, "Invalid PayJoin v0 transaction: locktime 0") + for i in tx["ins"]: + if i["sequence"] != 0xffffffff - 1: + return (False, "Invalid PayJoin v0 transaction: "+\ + "sequence is not 0xffffffff -1") # Before even starting fee calculations, reject > 5 # inputs from counterparty as an abuse (accidental or @@ -1180,6 +1192,9 @@ class P2EPTaker(Taker): # All checks have passed; we sign and broadcast self.latest_tx = tx + # Note that self.self_sign will only sign the self.input_utxos specified at + # the start of the processing, which guards against the "unwittingly sign + # extra inputs" attack mentioned in BIP79. self.self_sign_and_push() # returning False here is not an error condition, only stops processing. return (False, "OK")