commit 0438bbc2c26d32ec17c76a0c8f1beb69255142f2
parent 05e5ef16eb0b11f580ded5ad5501316888f97d26
Author: SomberNight <somber.night@protonmail.com>
Date: Thu, 14 Jun 2018 20:13:04 +0200
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'
Diffstat:
4 files changed, 15 insertions(+), 18 deletions(-)
diff --git a/lib/tests/test_transaction.py b/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)
diff --git a/lib/transaction.py b/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]))
diff --git a/plugins/keepkey/keepkey.py b/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:
diff --git a/plugins/trezor/trezor.py b/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: