Browse Source

wallet: kill negative conf numbers for TxMinedInfo

fixes https://github.com/spesmilo/electrum/issues/8240

#8240 was triggering an AssertionError in wallet.get_invoice_status,
as code there was assuming conf >= 0. To trigger, force-close
a LN channel, and while the sweep is waiting on the CSV, try to
make a payment in the Send tab to the ismine change address used
for the sweep in the future_tx. (order of events can also be reversed)
master
SomberNight 3 years ago
parent
commit
7584ba00ce
No known key found for this signature in database
GPG Key ID: B33B5F232C6271E9
  1. 7
      electrum/address_synchronizer.py
  2. 11
      electrum/gui/qt/history_list.py
  3. 3
      electrum/util.py
  4. 9
      electrum/wallet.py

7
electrum/address_synchronizer.py

@ -674,10 +674,9 @@ class AddressSynchronizer(Logger, EventListener):
elif tx_hash in self.unconfirmed_tx:
height = self.unconfirmed_tx[tx_hash]
return TxMinedInfo(height=height, conf=0)
elif tx_hash in self.future_tx:
num_blocks_remainining = self.future_tx[tx_hash] - self.get_local_height()
if num_blocks_remainining > 0:
return TxMinedInfo(height=TX_HEIGHT_FUTURE, conf=-num_blocks_remainining)
elif wanted_height := self.future_tx.get(tx_hash):
if wanted_height > self.get_local_height():
return TxMinedInfo(height=TX_HEIGHT_FUTURE, conf=0, wanted_height=wanted_height)
else:
return TxMinedInfo(height=TX_HEIGHT_LOCAL, conf=0)
else:

11
electrum/gui/qt/history_list.py

@ -425,11 +425,16 @@ class HistoryModel(CustomModel, Logger):
@staticmethod
def tx_mined_info_from_tx_item(tx_item):
tx_mined_info = TxMinedInfo(height=tx_item['height'],
conf=tx_item['confirmations'],
timestamp=tx_item['timestamp'])
# FIXME a bit hackish to have to reconstruct the TxMinedInfo...
tx_mined_info = TxMinedInfo(
height=tx_item['height'],
conf=tx_item['confirmations'],
timestamp=tx_item['timestamp'],
wanted_height=tx_item.get('wanted_height', None),
)
return tx_mined_info
class HistoryList(MyTreeView, AcceptFileDragDrop):
filter_columns = [HistoryColumns.STATUS,
HistoryColumns.DESCRIPTION,

3
electrum/util.py

@ -1275,10 +1275,11 @@ def with_lock(func):
class TxMinedInfo(NamedTuple):
height: int # height of block that mined tx
conf: Optional[int] = None # number of confirmations, SPV verified (None means unknown)
conf: Optional[int] = None # number of confirmations, SPV verified. >=0, or None (None means unknown)
timestamp: Optional[int] = None # timestamp of block that mined tx
txpos: Optional[int] = None # position of tx in serialized block
header_hash: Optional[str] = None # hash of block that mined tx
wanted_height: Optional[int] = None # in case of timelock, min abs block height
class ShortID(bytes):

9
electrum/wallet.py

@ -1000,7 +1000,7 @@ class Abstract_Wallet(ABC, Logger, EventListener):
monotonic_timestamp = 0
for hist_item in self.adb.get_history(domain=domain):
monotonic_timestamp = max(monotonic_timestamp, (hist_item.tx_mined_status.timestamp or 999_999_999_999))
yield {
d = {
'txid': hist_item.txid,
'fee_sat': hist_item.fee,
'height': hist_item.tx_mined_status.height,
@ -1014,6 +1014,9 @@ class Abstract_Wallet(ABC, Logger, EventListener):
'label': self.get_label_for_txid(hist_item.txid),
'txpos_in_block': hist_item.tx_mined_status.txpos,
}
if wanted_height := hist_item.tx_mined_status.wanted_height:
d['wanted_height'] = wanted_height
yield d
def create_invoice(self, *, outputs: List[PartialTxOutput], message, pr, URI) -> Invoice:
height = self.adb.get_local_height()
@ -1473,8 +1476,8 @@ class Abstract_Wallet(ABC, Logger, EventListener):
conf = tx_mined_info.conf
timestamp = tx_mined_info.timestamp
if height == TX_HEIGHT_FUTURE:
assert conf < 0, conf
num_blocks_remainining = -conf
num_blocks_remainining = tx_mined_info.wanted_height - self.adb.get_local_height()
num_blocks_remainining = max(0, num_blocks_remainining)
return 2, f'in {num_blocks_remainining} blocks'
if conf == 0:
tx = self.db.get_transaction(tx_hash)

Loading…
Cancel
Save