Browse Source

transaction.py: change update_signatures API. fix trezor segwit signing.

Traceback (most recent call last):
  File "...\electrum\lib\transaction.py", line 498, in parse_witness
    if txin['witness_version'] != 0:
KeyError: 'witness_version'
3.2.x
SomberNight 7 years ago
parent
commit
0438bbc2c2
No known key found for this signature in database GPG Key ID: B33B5F232C6271E9
  1. 5
      lib/tests/test_transaction.py
  2. 16
      lib/transaction.py
  3. 6
      plugins/keepkey/keepkey.py
  4. 6
      plugins/trezor/trezor.py

5
lib/tests/test_transaction.py

@ -13,6 +13,7 @@ signed_blob = '01000000012a5c9a94fcde98f5581cd00162c60a13936ceb75389ea65bf38633b
v2_blob = "0200000001191601a44a81e061502b7bfbc6eaa1cef6d1e6af5308ef96c9342f71dbf4b9b5000000006b483045022100a6d44d0a651790a477e75334adfb8aae94d6612d01187b2c02526e340a7fd6c8022028bdf7a64a54906b13b145cd5dab21a26bd4b85d6044e9b97bceab5be44c2a9201210253e8e0254b0c95776786e40984c1aa32a7d03efa6bdacdea5f421b774917d346feffffff026b20fa04000000001976a914024db2e87dd7cfd0e5f266c5f212e21a31d805a588aca0860100000000001976a91421919b94ae5cefcdf0271191459157cdb41c4cbf88aca6240700"
signed_segwit_blob = "01000000000101b66d722484f2db63e827ebf41d02684fed0c6550e85015a6c9d41ef216a8a6f00000000000fdffffff0280c3c90100000000160014b65ce60857f7e7892b983851c2a8e3526d09e4ab64bac30400000000160014c478ebbc0ab2097706a98e10db7cf101839931c4024730440220789c7d47f876638c58d98733c30ae9821c8fa82b470285dcdf6db5994210bf9f02204163418bbc44af701212ad42d884cc613f3d3d831d2d0cc886f767cca6e0235e012103083a6dc250816d771faa60737bfe78b23ad619f6b458e0a1f1688e3a0605e79c00000000"
signed_blob_signatures = ['3046022100a82bbc57a0136751e5433f41cf000b3f1a99c6744775e76ec764fb78c54ee100022100f9e80b7de89de861dc6fb0c1429d5da72c2b6b2ee2406bc9bfb1beedd729d98501', ]
class TestBCDataStream(SequentialTestCase):
@ -96,7 +97,7 @@ class TestTransaction(SequentialTestCase):
self.assertEqual(tx.serialize(), unsigned_blob)
tx.update_signatures(signed_blob)
tx.update_signatures(signed_blob_signatures)
self.assertEqual(tx.raw, signed_blob)
tx.update(unsigned_blob)
@ -132,7 +133,7 @@ class TestTransaction(SequentialTestCase):
self.assertEqual(tx.serialize(), signed_blob)
tx.update_signatures(signed_blob)
tx.update_signatures(signed_blob_signatures)
self.assertEqual(tx.estimated_total_size(), 193)
self.assertEqual(tx.estimated_base_size(), 193)

16
lib/transaction.py

@ -545,7 +545,7 @@ def parse_output(vds, i):
return d
def deserialize(raw: str, force_full_parse=False) -> dict:
def deserialize(raw: str) -> dict:
raw_bytes = bfh(raw)
d = {}
if raw_bytes[:5] == PARTIAL_TXN_HEADER_MAGIC:
@ -557,7 +557,6 @@ def deserialize(raw: str, force_full_parse=False) -> dict:
raw_bytes = raw_bytes[6:]
else:
d['partial'] = is_partial = False
full_parse = force_full_parse or is_partial
vds = BCDataStream()
vds.write(raw_bytes)
d['version'] = vds.read_int32()
@ -569,13 +568,13 @@ def deserialize(raw: str, force_full_parse=False) -> dict:
raise ValueError('invalid txn marker byte: {}'.format(marker))
n_vin = vds.read_compact_size()
d['segwit_ser'] = is_segwit
d['inputs'] = [parse_input(vds, full_parse=full_parse) for i in range(n_vin)]
d['inputs'] = [parse_input(vds, full_parse=is_partial) for i in range(n_vin)]
n_vout = vds.read_compact_size()
d['outputs'] = [parse_output(vds, i) for i in range(n_vout)]
if is_segwit:
for i in range(n_vin):
txin = d['inputs'][i]
parse_witness(vds, txin, full_parse=full_parse)
parse_witness(vds, txin, full_parse=is_partial)
d['lockTime'] = vds.read_uint32()
if vds.can_read_more():
raise SerializationError('extra junk at the end')
@ -652,17 +651,14 @@ class Transaction:
txin['x_pubkeys'] = x_pubkeys = list(x_pubkeys)
return pubkeys, x_pubkeys
def update_signatures(self, raw):
def update_signatures(self, signatures: Sequence[str]):
"""Add new signatures to a transaction"""
if self.is_complete():
return
d = deserialize(raw, force_full_parse=True)
for i, txin in enumerate(self.inputs()):
pubkeys, x_pubkeys = self.get_sorted_pubkeys(txin)
sigs1 = txin.get('signatures')
sigs2 = d['inputs'][i].get('signatures')
for sig in sigs2:
if sig in sigs1:
for sig in signatures:
if sig in txin.get('signatures'):
continue
pre_hash = Hash(bfh(self.serialize_preimage(i)))
sig_string = ecc.sig_string_from_der_sig(bfh(sig[:-2]))

6
plugins/keepkey/keepkey.py

@ -258,9 +258,9 @@ class KeepKeyPlugin(HW_PluginBase):
client = self.get_client(keystore)
inputs = self.tx_inputs(tx, True, keystore.is_segwit())
outputs = self.tx_outputs(keystore.get_derivation(), tx, keystore.is_segwit())
signed_tx = client.sign_tx(self.get_coin_name(), inputs, outputs, lock_time=tx.locktime)[1]
raw = bh2u(signed_tx)
tx.update_signatures(raw)
signatures = client.sign_tx(self.get_coin_name(), inputs, outputs, lock_time=tx.locktime)[0]
signatures = [(bh2u(x) + '01') for x in signatures]
tx.update_signatures(signatures)
def show_address(self, wallet, address, keystore=None):
if keystore is None:

6
plugins/trezor/trezor.py

@ -318,9 +318,9 @@ class TrezorPlugin(HW_PluginBase):
client = self.get_client(keystore)
inputs = self.tx_inputs(tx, True, keystore.get_script_gen())
outputs = self.tx_outputs(keystore.get_derivation(), tx, keystore.get_script_gen())
signed_tx = client.sign_tx(self.get_coin_name(), inputs, outputs, lock_time=tx.locktime)[1]
raw = bh2u(signed_tx)
tx.update_signatures(raw)
signatures = client.sign_tx(self.get_coin_name(), inputs, outputs, lock_time=tx.locktime)[0]
signatures = [(bh2u(x) + '01') for x in signatures]
tx.update_signatures(signatures)
def show_address(self, wallet, address, keystore=None):
if keystore is None:

Loading…
Cancel
Save