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:
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()