From cc4f6804b0f0d700c4876293248d60851bd170d9 Mon Sep 17 00:00:00 2001 From: SomberNight Date: Tue, 5 Nov 2019 23:32:00 +0100 Subject: [PATCH] psbt: follow-ups: fix trezor --- electrum/plugins/hw_wallet/plugin.py | 10 +++++++--- electrum/plugins/keepkey/keepkey.py | 18 ++++++++++++------ electrum/plugins/safe_t/safe_t.py | 18 ++++++++++++------ electrum/plugins/trezor/trezor.py | 16 +++++++++++----- electrum/transaction.py | 7 ++++--- 5 files changed, 46 insertions(+), 23 deletions(-) diff --git a/electrum/plugins/hw_wallet/plugin.py b/electrum/plugins/hw_wallet/plugin.py index 42f7662b4..ab9984cfe 100644 --- a/electrum/plugins/hw_wallet/plugin.py +++ b/electrum/plugins/hw_wallet/plugin.py @@ -24,16 +24,16 @@ # CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE # SOFTWARE. -from typing import TYPE_CHECKING, Dict, List, Union, Tuple +from typing import TYPE_CHECKING, Dict, List, Union, Tuple, Sequence from electrum.plugin import BasePlugin, hook from electrum.i18n import _ from electrum.bitcoin import is_address, TYPE_SCRIPT, opcodes from electrum.util import bfh, versiontuple, UserFacingException from electrum.transaction import TxOutput, Transaction, PartialTransaction, PartialTxInput, PartialTxOutput +from electrum.bip32 import BIP32Node if TYPE_CHECKING: - from electrum.bip32 import BIP32Node from electrum.wallet import Abstract_Wallet from electrum.keystore import Hardware_KeyStore @@ -162,7 +162,11 @@ def get_xpubs_and_der_suffixes_from_txinout(tx: PartialTransaction, xfp_to_xpub_map = {xfp: bip32node for bip32node, (xfp, path) in tx.xpubs.items()} # type: Dict[bytes, BIP32Node] xfps = [txinout.bip32_paths[pubkey][0] for pubkey in txinout.pubkeys] - xpubs = [xfp_to_xpub_map[xfp] for xfp in xfps] + try: + xpubs = [xfp_to_xpub_map[xfp] for xfp in xfps] + except KeyError as e: + raise Exception(f"Partial transaction is missing global xpub for " + f"fingerprint ({str(e)}) in input/output") from e xpubs_and_deriv_suffixes = [] for bip32node, pubkey in zip(xpubs, txinout.pubkeys): xfp, path = txinout.bip32_paths[pubkey] diff --git a/electrum/plugins/keepkey/keepkey.py b/electrum/plugins/keepkey/keepkey.py index da48ab9c5..296f0e636 100644 --- a/electrum/plugins/keepkey/keepkey.py +++ b/electrum/plugins/keepkey/keepkey.py @@ -351,15 +351,18 @@ class KeepKeyPlugin(HW_PluginBase): assert isinstance(tx, PartialTransaction) assert isinstance(txin, PartialTxInput) assert keystore - xpubs_and_deriv_suffixes = get_xpubs_and_der_suffixes_from_txinout(tx, txin) - multisig = self._make_multisig(txin.num_sig, xpubs_and_deriv_suffixes) + if len(txin.pubkeys) > 1: + xpubs_and_deriv_suffixes = get_xpubs_and_der_suffixes_from_txinout(tx, txin) + multisig = self._make_multisig(txin.num_sig, xpubs_and_deriv_suffixes) + else: + multisig = None script_type = self.get_keepkey_input_script_type(txin.script_type) txinputtype = self.types.TxInputType( script_type=script_type, multisig=multisig) my_pubkey, full_path = keystore.find_my_pubkey_in_txinout(txin) if full_path: - txinputtype.address_n = full_path + txinputtype.address_n.extend(full_path) prev_hash = txin.prevout.txid prev_index = txin.prevout.out_idx @@ -387,12 +390,15 @@ class KeepKeyPlugin(HW_PluginBase): signatures=[b''] * len(pubkeys), m=m) - def tx_outputs(self, tx: PartialTransaction, *, keystore: 'KeepKey_KeyStore' = None): + def tx_outputs(self, tx: PartialTransaction, *, keystore: 'KeepKey_KeyStore'): def create_output_by_derivation(): script_type = self.get_keepkey_output_script_type(txout.script_type) - xpubs_and_deriv_suffixes = get_xpubs_and_der_suffixes_from_txinout(tx, txout) - multisig = self._make_multisig(txout.num_sig, xpubs_and_deriv_suffixes) + if len(txout.pubkeys) > 1: + xpubs_and_deriv_suffixes = get_xpubs_and_der_suffixes_from_txinout(tx, txout) + multisig = self._make_multisig(txout.num_sig, xpubs_and_deriv_suffixes) + else: + multisig = None my_pubkey, full_path = keystore.find_my_pubkey_in_txinout(txout) assert full_path txoutputtype = self.types.TxOutputType( diff --git a/electrum/plugins/safe_t/safe_t.py b/electrum/plugins/safe_t/safe_t.py index 0bd6ba07c..d195f3196 100644 --- a/electrum/plugins/safe_t/safe_t.py +++ b/electrum/plugins/safe_t/safe_t.py @@ -347,15 +347,18 @@ class SafeTPlugin(HW_PluginBase): assert isinstance(tx, PartialTransaction) assert isinstance(txin, PartialTxInput) assert keystore - xpubs_and_deriv_suffixes = get_xpubs_and_der_suffixes_from_txinout(tx, txin) - multisig = self._make_multisig(txin.num_sig, xpubs_and_deriv_suffixes) + if len(txin.pubkeys) > 1: + xpubs_and_deriv_suffixes = get_xpubs_and_der_suffixes_from_txinout(tx, txin) + multisig = self._make_multisig(txin.num_sig, xpubs_and_deriv_suffixes) + else: + multisig = None script_type = self.get_safet_input_script_type(txin.script_type) txinputtype = self.types.TxInputType( script_type=script_type, multisig=multisig) my_pubkey, full_path = keystore.find_my_pubkey_in_txinout(txin) if full_path: - txinputtype.address_n = full_path + txinputtype._extend_address_n(full_path) prev_hash = txin.prevout.txid prev_index = txin.prevout.out_idx @@ -383,12 +386,15 @@ class SafeTPlugin(HW_PluginBase): signatures=[b''] * len(pubkeys), m=m) - def tx_outputs(self, tx: PartialTransaction, *, keystore: 'SafeTKeyStore' = None): + def tx_outputs(self, tx: PartialTransaction, *, keystore: 'SafeTKeyStore'): def create_output_by_derivation(): script_type = self.get_safet_output_script_type(txout.script_type) - xpubs_and_deriv_suffixes = get_xpubs_and_der_suffixes_from_txinout(tx, txout) - multisig = self._make_multisig(txout.num_sig, xpubs_and_deriv_suffixes) + if len(txout.pubkeys) > 1: + xpubs_and_deriv_suffixes = get_xpubs_and_der_suffixes_from_txinout(tx, txout) + multisig = self._make_multisig(txout.num_sig, xpubs_and_deriv_suffixes) + else: + multisig = None my_pubkey, full_path = keystore.find_my_pubkey_in_txinout(txout) assert full_path txoutputtype = self.types.TxOutputType( diff --git a/electrum/plugins/trezor/trezor.py b/electrum/plugins/trezor/trezor.py index d839da707..a0b6ec0a0 100644 --- a/electrum/plugins/trezor/trezor.py +++ b/electrum/plugins/trezor/trezor.py @@ -365,8 +365,11 @@ class TrezorPlugin(HW_PluginBase): assert isinstance(tx, PartialTransaction) assert isinstance(txin, PartialTxInput) assert keystore - xpubs_and_deriv_suffixes = get_xpubs_and_der_suffixes_from_txinout(tx, txin) - multisig = self._make_multisig(txin.num_sig, xpubs_and_deriv_suffixes) + if len(txin.pubkeys) > 1: + xpubs_and_deriv_suffixes = get_xpubs_and_der_suffixes_from_txinout(tx, txin) + multisig = self._make_multisig(txin.num_sig, xpubs_and_deriv_suffixes) + else: + multisig = None script_type = self.get_trezor_input_script_type(txin.script_type) txinputtype = TxInputType( script_type=script_type, @@ -401,12 +404,15 @@ class TrezorPlugin(HW_PluginBase): signatures=[b''] * len(pubkeys), m=m) - def tx_outputs(self, tx: PartialTransaction, *, keystore: 'TrezorKeyStore' = None): + def tx_outputs(self, tx: PartialTransaction, *, keystore: 'TrezorKeyStore'): def create_output_by_derivation(): script_type = self.get_trezor_output_script_type(txout.script_type) - xpubs_and_deriv_suffixes = get_xpubs_and_der_suffixes_from_txinout(tx, txout) - multisig = self._make_multisig(txout.num_sig, xpubs_and_deriv_suffixes) + if len(txout.pubkeys) > 1: + xpubs_and_deriv_suffixes = get_xpubs_and_der_suffixes_from_txinout(tx, txout) + multisig = self._make_multisig(txout.num_sig, xpubs_and_deriv_suffixes) + else: + multisig = None my_pubkey, full_path = keystore.find_my_pubkey_in_txinout(txout) assert full_path txoutputtype = TxOutputType( diff --git a/electrum/transaction.py b/electrum/transaction.py index c552725e3..09cd640a7 100644 --- a/electrum/transaction.py +++ b/electrum/transaction.py @@ -1753,9 +1753,10 @@ class PartialTransaction(Transaction): if self.is_complete(): return only_der_suffix = not include_xpubs_and_full_paths - # only include xpubs for multisig wallets; currently only they need it in practice, - # and also the coldcard fw have a limitation that if they are included then all - # inputs are assumed to be multisig... https://github.com/spesmilo/electrum/pull/5440#issuecomment-549504761 + # only include xpubs for multisig wallets; currently only they need it in practice + # note: coldcard fw have a limitation that if they are included then all + # inputs are assumed to be multisig... https://github.com/spesmilo/electrum/pull/5440#issuecomment-549504761 + # note: trezor plugin needs xpubs included, if there are multisig inputs/change_outputs from .wallet import Multisig_Wallet if include_xpubs_and_full_paths and isinstance(wallet, Multisig_Wallet): from .keystore import Xpub