1
0

wallet: fix is_mine/can_sign. don't just rely on ks, also check script

Previously a standard (single-sig) wallet would consider a multisig txin as is_mine
(if the keystore found its pubkey in the txin).

fixes #5948
This commit is contained in:
SomberNight
2020-02-12 18:07:08 +01:00
parent 0d33da2f95
commit ab4e2dd9f0
3 changed files with 91 additions and 15 deletions

View File

@@ -33,7 +33,7 @@ from abc import ABC, abstractmethod
from . import bitcoin, ecc, constants, bip32
from .bitcoin import deserialize_privkey, serialize_privkey
from .transaction import Transaction, PartialTransaction, PartialTxInput, PartialTxOutput
from .transaction import Transaction, PartialTransaction, PartialTxInput, PartialTxOutput, TxInput
from .bip32 import (convert_bip32_path_to_list_of_uint32, BIP32_PRIME,
is_xpub, is_xprv, BIP32Node, normalize_bip32_derivation,
convert_bip32_intpath_to_strpath)
@@ -78,16 +78,21 @@ class KeyStore(Logger, ABC):
def _get_tx_derivations(self, tx: 'PartialTransaction') -> Dict[str, Union[Sequence[int], str]]:
keypairs = {}
for txin in tx.inputs():
if txin.is_complete():
keypairs.update(self._get_txin_derivations(txin))
return keypairs
def _get_txin_derivations(self, txin: 'PartialTxInput') -> Dict[str, Union[Sequence[int], str]]:
if txin.is_complete():
return {}
keypairs = {}
for pubkey in txin.pubkeys:
if pubkey in txin.part_sigs:
# this pubkey already signed
continue
for pubkey in txin.pubkeys:
if pubkey in txin.part_sigs:
# this pubkey already signed
continue
derivation = self.get_pubkey_derivation(pubkey, txin)
if not derivation:
continue
keypairs[pubkey.hex()] = derivation
derivation = self.get_pubkey_derivation(pubkey, txin)
if not derivation:
continue
keypairs[pubkey.hex()] = derivation
return keypairs
def can_sign(self, tx: 'Transaction', *, ignore_watching_only=False) -> bool:
@@ -98,6 +103,14 @@ class KeyStore(Logger, ABC):
return False
return bool(self._get_tx_derivations(tx))
def can_sign_txin(self, txin: 'TxInput', *, ignore_watching_only=False) -> bool:
"""Returns whether this keystore could sign this txin."""
if not ignore_watching_only and self.is_watching_only():
return False
if not isinstance(txin, PartialTxInput):
return False
return bool(self._get_txin_derivations(txin))
def ready_to_sign(self) -> bool:
return not self.is_watching_only()