twallet: only select mature coins by default - electrum - Electrum Bitcoin wallet HTML git clone https://git.parazyd.org/electrum DIR Log DIR Files DIR Refs DIR Submodules --- DIR commit d2f132738a2a13d896b11ca984d94930cc1c9aad DIR parent 6709ec41174300093a5782debe2787f005bd9b07 HTML Author: SomberNight <somber.night@protonmail.com> Date: Thu, 2 Jan 2020 00:43:49 +0100 wallet: only select mature coins by default tthis is a regression from #5721 Removed the `TxInput.is_coinbase` method as I think it is a confusing API, instead we now have `TxInput.is_coinbase_input` and `TxInput.is_coinbase_output`. related #5872 Diffstat: M electrum/address_synchronizer.py | 13 +++++++------ M electrum/gui/qt/transaction_dialog… | 2 +- M electrum/json_db.py | 2 +- M electrum/plugins/digitalbitbox/dig… | 2 +- M electrum/plugins/keepkey/keepkey.py | 2 +- M electrum/plugins/ledger/ledger.py | 2 +- M electrum/plugins/safe_t/safe_t.py | 2 +- M electrum/plugins/trezor/trezor.py | 2 +- M electrum/plugins/trustedcoin/legac… | 4 ++-- M electrum/transaction.py | 29 ++++++++++++++++++++--------- 10 files changed, 36 insertions(+), 24 deletions(-) --- DIR diff --git a/electrum/address_synchronizer.py b/electrum/address_synchronizer.py t@@ -194,7 +194,7 @@ class AddressSynchronizer(Logger): conflicting_txns = set() with self.transaction_lock: for txin in tx.inputs(): - if txin.is_coinbase(): + if txin.is_coinbase_input(): continue prevout_hash = txin.prevout.txid.hex() prevout_n = txin.prevout.out_idx t@@ -228,7 +228,7 @@ class AddressSynchronizer(Logger): # BUT we track is_mine inputs in a txn, and during subsequent calls # of add_transaction tx, we might learn of more-and-more inputs of # being is_mine, as we roll the gap_limit forward - is_coinbase = tx.inputs()[0].is_coinbase() + is_coinbase = tx.inputs()[0].is_coinbase_input() tx_height = self.get_tx_height(tx_hash).height if not allow_unrelated: # note that during sync, if the transactions are not properly sorted, t@@ -279,7 +279,7 @@ class AddressSynchronizer(Logger): self._get_addr_balance_cache.pop(addr, None) # invalidate cache return for txi in tx.inputs(): - if txi.is_coinbase(): + if txi.is_coinbase_input(): continue prevout_hash = txi.prevout.txid.hex() prevout_n = txi.prevout.out_idx t@@ -314,7 +314,7 @@ class AddressSynchronizer(Logger): if tx is not None: # if we have the tx, this branch is faster for txin in tx.inputs(): - if txin.is_coinbase(): + if txin.is_coinbase_input(): continue prevout_hash = txin.prevout.txid.hex() prevout_n = txin.prevout.out_idx t@@ -758,7 +758,8 @@ class AddressSynchronizer(Logger): for prevout_str, v in coins.items(): tx_height, value, is_cb = v prevout = TxOutpoint.from_str(prevout_str) - utxo = PartialTxInput(prevout=prevout) + utxo = PartialTxInput(prevout=prevout, + is_coinbase_output=is_cb) utxo._trusted_address = address utxo._trusted_value_sats = value utxo.block_height = tx_height t@@ -825,7 +826,7 @@ class AddressSynchronizer(Logger): continue if nonlocal_only and utxo.block_height == TX_HEIGHT_LOCAL: continue - if (mature_only and utxo.prevout.is_coinbase() + if (mature_only and utxo.is_coinbase_output() and utxo.block_height + COINBASE_MATURITY > mempool_height): continue coins.append(utxo) DIR diff --git a/electrum/gui/qt/transaction_dialog.py b/electrum/gui/qt/transaction_dialog.py t@@ -480,7 +480,7 @@ class BaseTxDialog(QDialog, MessageBoxMixin): i_text.setReadOnly(True) cursor = i_text.textCursor() for txin in self.tx.inputs(): - if txin.is_coinbase(): + if txin.is_coinbase_input(): cursor.insertText('coinbase') else: prevout_hash = txin.prevout.txid.hex() DIR diff --git a/electrum/json_db.py b/electrum/json_db.py t@@ -424,7 +424,7 @@ class JsonDB(Logger): for txid, raw_tx in transactions.items(): tx = Transaction(raw_tx) for txin in tx.inputs(): - if txin.is_coinbase(): + if txin.is_coinbase_input(): continue prevout_hash = txin.prevout.txid.hex() prevout_n = txin.prevout.out_idx DIR diff --git a/electrum/plugins/digitalbitbox/digitalbitbox.py b/electrum/plugins/digitalbitbox/digitalbitbox.py t@@ -539,7 +539,7 @@ class DigitalBitbox_KeyStore(Hardware_KeyStore): # Build hasharray from inputs for i, txin in enumerate(tx.inputs()): - if txin.is_coinbase(): + if txin.is_coinbase_input(): self.give_error("Coinbase not supported") # should never happen if txin.script_type != 'p2pkh': DIR diff --git a/electrum/plugins/keepkey/keepkey.py b/electrum/plugins/keepkey/keepkey.py t@@ -364,7 +364,7 @@ class KeepKeyPlugin(HW_PluginBase): inputs = [] for txin in tx.inputs(): txinputtype = self.types.TxInputType() - if txin.is_coinbase(): + if txin.is_coinbase_input(): prev_hash = b"\x00"*32 prev_index = 0xffffffff # signed int -1 else: DIR diff --git a/electrum/plugins/ledger/ledger.py b/electrum/plugins/ledger/ledger.py t@@ -330,7 +330,7 @@ class Ledger_KeyStore(Hardware_KeyStore): # Fetch inputs of the transaction to sign for txin in tx.inputs(): - if txin.is_coinbase(): + if txin.is_coinbase_input(): self.give_error("Coinbase not supported") # should never happen if txin.script_type in ['p2sh']: DIR diff --git a/electrum/plugins/safe_t/safe_t.py b/electrum/plugins/safe_t/safe_t.py t@@ -338,7 +338,7 @@ class SafeTPlugin(HW_PluginBase): inputs = [] for txin in tx.inputs(): txinputtype = self.types.TxInputType() - if txin.is_coinbase(): + if txin.is_coinbase_input(): prev_hash = b"\x00"*32 prev_index = 0xffffffff # signed int -1 else: DIR diff --git a/electrum/plugins/trezor/trezor.py b/electrum/plugins/trezor/trezor.py t@@ -361,7 +361,7 @@ class TrezorPlugin(HW_PluginBase): inputs = [] for txin in tx.inputs(): txinputtype = TxInputType() - if txin.is_coinbase(): + if txin.is_coinbase_input(): prev_hash = b"\x00"*32 prev_index = 0xffffffff # signed int -1 else: DIR diff --git a/electrum/plugins/trustedcoin/legacy_tx_format.py b/electrum/plugins/trustedcoin/legacy_tx_format.py t@@ -38,7 +38,7 @@ def serialize_tx_in_legacy_format(tx: PartialTransaction, *, wallet: Multisig_Wa tx = copy.deepcopy(tx) def get_siglist(txin: 'PartialTxInput', *, estimate_size=False): - if txin.prevout.is_coinbase(): + if txin.is_coinbase_input(): return [], [] if estimate_size: try: t@@ -80,7 +80,7 @@ def serialize_tx_in_legacy_format(tx: PartialTransaction, *, wallet: Multisig_Wa assert estimate_size is False if txin.witness is not None: return txin.witness.hex() - if txin.prevout.is_coinbase(): + if txin.is_coinbase_input(): return '' assert isinstance(txin, PartialTxInput) if not self.is_segwit_input(txin): DIR diff --git a/electrum/transaction.py b/electrum/transaction.py t@@ -192,20 +192,30 @@ class TxInput: script_sig: Optional[bytes] nsequence: int witness: Optional[bytes] + _is_coinbase_output: bool def __init__(self, *, prevout: TxOutpoint, script_sig: bytes = None, nsequence: int = 0xffffffff - 1, - witness: bytes = None): + witness: bytes = None, + is_coinbase_output: bool = False): self.prevout = prevout self.script_sig = script_sig self.nsequence = nsequence self.witness = witness + self._is_coinbase_output = is_coinbase_output - def is_coinbase(self) -> bool: + def is_coinbase_input(self) -> bool: + """Whether this is the input of a coinbase tx.""" return self.prevout.is_coinbase() + def is_coinbase_output(self) -> bool: + """Whether the coin being spent is an output of a coinbase tx. + This matters for coin maturity. + """ + return self._is_coinbase_output + def value_sats(self) -> Optional[int]: return None t@@ -213,7 +223,7 @@ class TxInput: d = { 'prevout_hash': self.prevout.txid.hex(), 'prevout_n': self.prevout.out_idx, - 'coinbase': self.is_coinbase(), + 'coinbase': self.is_coinbase_output(), 'nsequence': self.nsequence, } if self.script_sig is not None: t@@ -550,7 +560,7 @@ class Transaction: @classmethod def get_siglist(self, txin: 'PartialTxInput', *, estimate_size=False): - if txin.prevout.is_coinbase(): + if txin.is_coinbase_input(): return [], [] if estimate_size: t@@ -579,7 +589,7 @@ class Transaction: def serialize_witness(cls, txin: TxInput, *, estimate_size=False) -> str: if txin.witness is not None: return txin.witness.hex() - if txin.prevout.is_coinbase(): + if txin.is_coinbase_input(): return '' assert isinstance(txin, PartialTxInput) t@@ -643,7 +653,7 @@ class Transaction: def input_script(self, txin: TxInput, *, estimate_size=False) -> str: if txin.script_sig is not None: return txin.script_sig.hex() - if txin.prevout.is_coinbase(): + if txin.is_coinbase_input(): return '' assert isinstance(txin, PartialTxInput) t@@ -1090,7 +1100,8 @@ class PartialTxInput(TxInput, PSBTSection): res = PartialTxInput(prevout=txin.prevout, script_sig=None if strip_witness else txin.script_sig, nsequence=txin.nsequence, - witness=None if strip_witness else txin.witness) + witness=None if strip_witness else txin.witness, + is_coinbase_output=txin.is_coinbase_output()) return res def validate_data(self, *, for_signing=False) -> None: t@@ -1243,7 +1254,7 @@ class PartialTxInput(TxInput, PSBTSection): def is_complete(self) -> bool: if self.script_sig is not None and self.witness is not None: return True - if self.prevout.is_coinbase(): + if self.is_coinbase_input(): return True if self.script_sig is not None and not Transaction.is_segwit_input(self): return True t@@ -1750,7 +1761,7 @@ class PartialTransaction(Transaction): s = 0 # "num Sigs we have" r = 0 # "Required" for txin in self.inputs(): - if txin.prevout.is_coinbase(): + if txin.is_coinbase_input(): continue signatures = list(txin.part_sigs.values()) s += len(signatures)