electrum

Electrum Bitcoin wallet
git clone https://git.parazyd.org/electrum
Log | Files | Refs | Submodules

commit 5f038a4157b1c24c8fef5b7519640ca74be99dfe
parent 03c66bb5f966aa1f90faab052a826cc6cea5e889
Author: ThomasV <thomasv@electrum.org>
Date:   Thu, 22 Sep 2016 10:25:03 +0200

ledger plugin: parse xpubkey instead of using txin['derivation']; always use client.finalizeInputFull

Diffstat:
Mplugins/ledger/ledger.py | 63+++++++++++++++++++++++++++++++--------------------------------
1 file changed, 31 insertions(+), 32 deletions(-)

diff --git a/plugins/ledger/ledger.py b/plugins/ledger/ledger.py @@ -2,12 +2,14 @@ from binascii import hexlify from struct import pack, unpack import hashlib import time +import sys +import traceback import electrum from electrum.bitcoin import EncodeBase58Check, DecodeBase58Check, TYPE_ADDRESS, int_to_hex, var_int from electrum.i18n import _ from electrum.plugins import BasePlugin, hook -from electrum.keystore import Hardware_KeyStore +from electrum.keystore import Hardware_KeyStore, parse_xpubkey from ..hw_wallet import HW_PluginBase from electrum.util import format_satoshis_plain, print_error @@ -257,43 +259,45 @@ class Ledger_KeyStore(Hardware_KeyStore): self.get_client() # prompt for the PIN before displaying the dialog if necessary rawTx = tx.serialize() # Fetch inputs of the transaction to sign - for txinput in tx.inputs(): - if ('is_coinbase' in txinput and txinput['is_coinbase']): + for txin in tx.inputs(): + if txin.get('is_coinbase'): self.give_error("Coinbase not supported") # should never happen redeemScript = None signingPos = -1 - hwAddress = "%s/%d/%d" % (self.get_derivation()[2:], txinput['derivation'][0], txinput['derivation'][1]) - if len(txinput['pubkeys']) > 1: - p2shTransaction = True - if 'redeemScript' in txinput: - redeemScript = txinput['redeemScript'] + xpub, s = parse_xpubkey(txin['x_pubkeys'][0]) + hwAddress = "%s/%d/%d" % (self.get_derivation()[2:], s[0], s[1]) + + if len(txin['pubkeys']) > 1: + p2shTransaction = True + if 'redeemScript' in txin: + redeemScript = txin['redeemScript'] if p2shTransaction: chipPublicKey = compress_public_key(self.get_client().getWalletPublicKey(hwAddress)['publicKey']) - for currentIndex, key in enumerate(txinput['pubkeys']): + for currentIndex, key in enumerate(txin['pubkeys']): if chipPublicKey == key.decode('hex'): signingPos = currentIndex break if signingPos == -1: self.give_error("No matching key for multisignature input") # should never happen - inputs.append([ txinput['prev_tx'].raw, - txinput['prevout_n'], redeemScript, txinput['prevout_hash'], signingPos ]) + inputs.append([txin['prev_tx'].raw, txin['prevout_n'], redeemScript, txin['prevout_hash'], signingPos ]) inputsPaths.append(hwAddress) - pubKeys.append(txinput['pubkeys']) - + pubKeys.append(txin['pubkeys']) + # Sanity check if p2shTransaction: for txinput in tx.inputs(): if len(txinput['pubkeys']) < 2: self.give_error("P2SH / regular input mixed in same transaction not supported") # should never happen - txOutput = var_int(len(tx.outputs())) - for output in tx.outputs(): - output_type, addr, amount = output - txOutput += int_to_hex(amount, 8) - script = tx.pay_script(output_type, addr) - txOutput += var_int(len(script)/2) - txOutput += script - txOutput = txOutput.decode('hex') + + txOutput = var_int(len(tx.outputs())) + for txout in tx.outputs(): + output_type, addr, amount = txout + txOutput += int_to_hex(amount, 8) + script = tx.pay_script(output_type, addr) + txOutput += var_int(len(script)/2) + txOutput += script + txOutput = txOutput.decode('hex') # Recognize outputs - only one output and one change is authorized if not p2shTransaction: @@ -306,11 +310,9 @@ class Ledger_KeyStore(Hardware_KeyStore): changePath = "%s/%d/%d" % (self.get_derivation()[2:], change, index) changeAmount = amount else: - if output <> None: # should never happen - self.give_error("Multiple outputs with no change not supported") output = address outputAmount = amount - + self.handler.show_message("Signing Transaction ...") try: # Get trusted inputs from the original transactions @@ -330,13 +332,9 @@ class Ledger_KeyStore(Hardware_KeyStore): inputIndex = 0 while inputIndex < len(inputs): self.get_client().startUntrustedTransaction(firstTransaction, inputIndex, - chipInputs, redeemScripts[inputIndex]) - if not p2shTransaction: - outputData = self.get_client().finalizeInput(output, format_satoshis_plain(outputAmount), - format_satoshis_plain(tx.get_fee()), changePath, bytearray(rawTx.decode('hex'))) - else: - outputData = self.get_client().finalizeInputFull(txOutput) - outputData['outputData'] = txOutput + chipInputs, redeemScripts[inputIndex]) + outputData = self.get_client().finalizeInputFull(txOutput) + outputData['outputData'] = txOutput if firstTransaction: transactionOutput = outputData['outputData'] if outputData['confirmationNeeded']: @@ -378,7 +376,8 @@ class Ledger_KeyStore(Hardware_KeyStore): signatures.append(inputSignature) inputIndex = inputIndex + 1 firstTransaction = False - except Exception, e: + except BaseException as e: + traceback.print_exc(file=sys.stdout) self.give_error(e, True) finally: self.handler.clear_dialog()