Browse Source

Correct handling of invalid, duplicate or spurious signatures by taker.

Signatures sent a second time now are correctly ignored, rather than prompting
a removal for the utxo entry which fails since it's already been removed.
Also corrects the case where a junk signature can trigger a crash in verify_tx_input,
if its script deserialization results in non-string entries (integer or None).
Test cases in test_taker updated to include these error cases, now passing.
master
AdamISZ 8 years ago
parent
commit
db458ec1cf
No known key found for this signature in database
GPG Key ID: B3AE09F1E9A3197A
  1. 20
      jmclient/jmclient/taker.py
  2. 4
      jmclient/test/test_taker.py

20
jmclient/jmclient/taker.py

@ -434,6 +434,10 @@ class Taker(object):
"""
if self.aborted:
return False
if nick not in self.nonrespondants:
jlog.debug(('add_signature => nick={} '
'not in nonrespondants {}').format(nick, self.nonrespondants))
return
sig = base64.b64decode(sigb64).encode('hex')
inserted_sig = False
txhex = btc.serialize(self.latest_tx)
@ -462,6 +466,11 @@ class Taker(object):
#the segwit-style signature. Note that this allows a mixed
#SW/non-SW transaction as each utxo is interpreted separately.
sig_deserialized = btc.deserialize_script(sig)
#verify_tx_input will not even parse the script if it has integers or None,
#so abort in case we were given a junk sig:
if not all([not isinstance(x, int) and x for x in sig_deserialized]):
print("Junk signature: ", sig_deserialized, ", not attempting to verify")
break
if len(sig_deserialized) == 2:
ver_sig, ver_pub = sig_deserialized
wit = None
@ -470,6 +479,7 @@ class Taker(object):
else:
jlog.debug("Invalid signature message - more than 3 items")
break
print("Got sig_deserialized: ", sig_deserialized)
ver_amt = utxo_data[i]['value'] if wit else None
sig_good = btc.verify_tx_input(txhex, u[0], utxo_data[i]['script'],
ver_sig, ver_pub, witness=wit,
@ -483,11 +493,17 @@ class Taker(object):
self.latest_tx["ins"][u[0]]["script"] = sig
inserted_sig = True
# check if maker has sent everything possible
self.utxos[nick].remove(u[1])
try:
self.utxos[nick].remove(u[1])
except ValueError:
pass
if len(self.utxos[nick]) == 0:
jlog.debug(('nick = {} sent all sigs, removing from '
'nonrespondant list').format(nick))
self.nonrespondants.remove(nick)
try:
self.nonrespondants.remove(nick)
except ValueError:
pass
break
if not inserted_sig:
jlog.debug('signature did not match anything in the tx')

4
jmclient/test/test_taker.py

@ -416,8 +416,12 @@ def test_on_sig(createcmtdata, dummyaddr, signmethod, schedule):
tx3 = bitcoin.sign(tx, 2, privs[2])
sig3 = b64encode(bitcoin.deserialize(tx3)['ins'][2]['script'].decode('hex'))
taker.on_sig("cp1", sig3)
#try sending the same sig again; should be ignored
taker.on_sig("cp1", sig3)
tx4 = bitcoin.sign(tx, 3, privs[3])
sig4 = b64encode(bitcoin.deserialize(tx4)['ins'][3]['script'].decode('hex'))
#try sending junk instead of cp2's correct sig
taker.on_sig("cp2", str("junk"))
taker.on_sig("cp2", sig4)
tx5 = bitcoin.sign(tx, 4, privs[4])
#Before completing with the final signature, which will trigger our own

Loading…
Cancel
Save