1
0

trezor: TrezorPlugin._make_multisig to use MultisigDescriptor

This fixes a regression where the plugin was assuming ordering for
txin.pubkeys (which is now a set).
(previously txin.pubkeys was a list ordered according to the final
sort order of keys inside the bitcoin script)
This commit is contained in:
SomberNight
2023-02-28 18:47:17 +00:00
parent 31f457c242
commit e457bb50e9
4 changed files with 54 additions and 82 deletions

View File

@@ -1,9 +1,10 @@
import traceback
import sys
from typing import NamedTuple, Any, Optional, Dict, Union, List, Tuple, TYPE_CHECKING
from typing import NamedTuple, Any, Optional, Dict, Union, List, Tuple, TYPE_CHECKING, Sequence
from electrum.util import bfh, versiontuple, UserCancelled, UserFacingException
from electrum.bip32 import BIP32Node, convert_bip32_path_to_list_of_uint32 as parse_path
from electrum import descriptor
from electrum import constants
from electrum.i18n import _
from electrum.plugin import Device, runs_in_hwd_thread
@@ -14,8 +15,7 @@ from electrum.logging import get_logger
from ..hw_wallet import HW_PluginBase
from ..hw_wallet.plugin import (is_any_tx_output_on_change_branch, trezor_validate_op_return_output_and_get_data,
LibraryFoundButUnusable, OutdatedHwFirmwareException,
get_xpubs_and_der_suffixes_from_txinout)
LibraryFoundButUnusable, OutdatedHwFirmwareException)
_logger = get_logger(__name__)
@@ -284,7 +284,7 @@ class TrezorPlugin(HW_PluginBase):
else:
raise RuntimeError("Unsupported recovery method")
def _make_node_path(self, xpub, address_n):
def _make_node_path(self, xpub: str, address_n: Sequence[int]):
bip32node = BIP32Node.from_xkey(xpub)
node = HDNodeType(
depth=bip32node.depth,
@@ -386,14 +386,9 @@ class TrezorPlugin(HW_PluginBase):
script_type = self.get_trezor_input_script_type(wallet.txin_type)
# prepare multisig, if available:
xpubs = wallet.get_master_public_keys()
if len(xpubs) > 1:
pubkeys = wallet.get_public_keys(address)
# sort xpubs using the order of pubkeys
sorted_pairs = sorted(zip(pubkeys, xpubs))
multisig = self._make_multisig(
wallet.m,
[(xpub, deriv_suffix) for pubkey, xpub in sorted_pairs])
desc = wallet.get_script_descriptor_for_address(address)
if multi := desc.get_simple_multisig():
multisig = self._make_multisig(multi)
else:
multisig = None
@@ -419,8 +414,7 @@ class TrezorPlugin(HW_PluginBase):
assert keystore
assert (desc := txin.script_descriptor)
if multi := desc.get_simple_multisig():
xpubs_and_deriv_suffixes = get_xpubs_and_der_suffixes_from_txinout(tx, txin)
txinputtype.multisig = self._make_multisig(multi.thresh, xpubs_and_deriv_suffixes)
txinputtype.multisig = self._make_multisig(multi)
txinputtype.script_type = self.get_trezor_input_script_type(desc.to_legacy_electrum_script_type())
my_pubkey, full_path = keystore.find_my_pubkey_in_txinout(txin)
if full_path:
@@ -434,14 +428,18 @@ class TrezorPlugin(HW_PluginBase):
return inputs
def _make_multisig(self, m, xpubs):
if len(xpubs) == 1:
return None
pubkeys = [self._make_node_path(xpub, deriv) for xpub, deriv in xpubs]
def _make_multisig(self, desc: descriptor.MultisigDescriptor):
pubkeys = []
for pubkey_provider in desc.pubkeys:
assert not pubkey_provider.is_range()
assert pubkey_provider.extkey is not None
xpub = pubkey_provider.pubkey
der_suffix = pubkey_provider.get_der_suffix_int_list()
pubkeys.append(self._make_node_path(xpub, der_suffix))
return MultisigRedeemScriptType(
pubkeys=pubkeys,
signatures=[b''] * len(pubkeys),
m=m)
m=desc.thresh)
def tx_outputs(self, tx: PartialTransaction, *, keystore: 'TrezorKeyStore'):
@@ -449,8 +447,7 @@ class TrezorPlugin(HW_PluginBase):
assert (desc := txout.script_descriptor)
script_type = self.get_trezor_output_script_type(desc.to_legacy_electrum_script_type())
if multi := desc.get_simple_multisig():
xpubs_and_deriv_suffixes = get_xpubs_and_der_suffixes_from_txinout(tx, txout)
multisig = self._make_multisig(multi.thresh, xpubs_and_deriv_suffixes)
multisig = self._make_multisig(multi)
else:
multisig = None
my_pubkey, full_path = keystore.find_my_pubkey_in_txinout(txout)