From 7a51f034e4696715b198226b88cc26d5d944c816 Mon Sep 17 00:00:00 2001 From: ThomasV Date: Fri, 1 Mar 2019 12:34:38 +0100 Subject: [PATCH] add future transactions to address synchronizer --- electrum/address_synchronizer.py | 10 ++++++++++ electrum/gui/qt/history_list.py | 4 ++-- electrum/lnworker.py | 14 ++++++++------ electrum/wallet.py | 4 +++- 4 files changed, 23 insertions(+), 9 deletions(-) diff --git a/electrum/address_synchronizer.py b/electrum/address_synchronizer.py index 88b7df786..089f06920 100644 --- a/electrum/address_synchronizer.py +++ b/electrum/address_synchronizer.py @@ -43,6 +43,7 @@ if TYPE_CHECKING: from .json_db import JsonDB +TX_HEIGHT_FUTURE = -3 TX_HEIGHT_LOCAL = -2 TX_HEIGHT_UNCONF_PARENT = -1 TX_HEIGHT_UNCONFIRMED = 0 @@ -71,6 +72,7 @@ class AddressSynchronizer(Logger): # locks: if you need to take multiple ones, acquire them in the order they are defined here! self.lock = threading.RLock() self.transaction_lock = threading.RLock() + self.future_tx = {} # txid -> blocks remaining # Transactions pending verification. txid -> tx_height. Access with self.lock. self.unverified_tx = defaultdict(int) # true when synchronized @@ -556,6 +558,11 @@ class AddressSynchronizer(Logger): return cached_local_height return self.network.get_local_height() if self.network else self.db.get('stored_height', 0) + def add_future_tx(self, tx, num_blocks): + with self.lock: + self.add_transaction(tx.txid(), tx) + self.future_tx[tx.txid()] = num_blocks + def get_tx_height(self, tx_hash: str) -> TxMinedInfo: with self.lock: verified_tx_mined_info = self.db.get_verified_tx(tx_hash) @@ -565,6 +572,9 @@ class AddressSynchronizer(Logger): elif tx_hash in self.unverified_tx: height = self.unverified_tx[tx_hash] return TxMinedInfo(height=height, conf=0) + elif tx_hash in self.future_tx: + conf = self.future_tx[tx_hash] + return TxMinedInfo(height=TX_HEIGHT_FUTURE, conf=conf) else: # local transaction return TxMinedInfo(height=TX_HEIGHT_LOCAL, conf=0) diff --git a/electrum/gui/qt/history_list.py b/electrum/gui/qt/history_list.py index bafee0551..ba76af1c3 100644 --- a/electrum/gui/qt/history_list.py +++ b/electrum/gui/qt/history_list.py @@ -39,7 +39,7 @@ from PyQt5.QtWidgets import (QMenu, QHeaderView, QLabel, QMessageBox, QPushButton, QComboBox, QVBoxLayout, QCalendarWidget, QGridLayout) -from electrum.address_synchronizer import TX_HEIGHT_LOCAL +from electrum.address_synchronizer import TX_HEIGHT_LOCAL, TX_HEIGHT_FUTURE from electrum.i18n import _ from electrum.util import (block_explorer_URL, profiler, TxMinedInfo, OrderedDictWithIndex, timestamp_to_datetime, @@ -632,7 +632,7 @@ class HistoryList(MyTreeView, AcceptFileDragDrop): is_unconfirmed = height <= 0 pr_key = self.wallet.invoices.paid.get(tx_hash) menu = QMenu() - if height == TX_HEIGHT_LOCAL: + if height in [TX_HEIGHT_FUTURE, TX_HEIGHT_LOCAL]: menu.addAction(_("Remove"), lambda: self.remove_local_tx(tx_hash)) menu.addAction(_("Copy Transaction ID"), lambda: self.parent.app.clipboard().setText(tx_hash)) diff --git a/electrum/lnworker.py b/electrum/lnworker.py index b77868f7f..ee83f5fdd 100644 --- a/electrum/lnworker.py +++ b/electrum/lnworker.py @@ -349,21 +349,23 @@ class LNWorker(PrintError): broadcast = True if e_tx.cltv_expiry: local_height = self.network.get_local_height() - if local_height > e_tx.cltv_expiry: - self.print_error(e_tx.name, 'CLTV ({} > {}) fulfilled'.format(local_height, e_tx.cltv_expiry)) - else: + remaining = e_tx.cltv_expiry - local_height + if remaining > 0: self.print_error(e_tx.name, 'waiting for {}: CLTV ({} > {}), funding outpoint {} and tx {}' .format(e_tx.name, local_height, e_tx.cltv_expiry, funding_outpoint[:8], prev_txid[:8])) broadcast = False if e_tx.csv_delay: - num_conf = self.network.lnwatcher.get_tx_height(prev_txid).conf - if num_conf < e_tx.csv_delay: + prev_height = self.network.lnwatcher.get_tx_height(prev_txid) + remaining = e_tx.csv_delay - prev_height.conf + if remaining > 0: self.print_error(e_tx.name, 'waiting for {}: CSV ({} >= {}), funding outpoint {} and tx {}' - .format(e_tx.name, num_conf, e_tx.csv_delay, funding_outpoint[:8], prev_txid[:8])) + .format(e_tx.name, prev_height.conf, e_tx.csv_delay, funding_outpoint[:8], prev_txid[:8])) broadcast = False if broadcast: if not await self.network.lnwatcher.broadcast_or_log(funding_outpoint, e_tx): self.print_error(e_tx.name, f'could not publish encumbered tx: {str(e_tx)}, prevout: {prevout}') + else: + self.wallet.add_future_tx(e_tx, remaining) @log_exceptions diff --git a/electrum/wallet.py b/electrum/wallet.py index 76c37d4f9..b5c8a548b 100644 --- a/electrum/wallet.py +++ b/electrum/wallet.py @@ -56,7 +56,7 @@ from . import transaction, bitcoin, coinchooser, paymentrequest, ecc, bip32 from .transaction import Transaction, TxOutput, TxOutputHwInfo from .plugin import run_hook from .address_synchronizer import (AddressSynchronizer, TX_HEIGHT_LOCAL, - TX_HEIGHT_UNCONF_PARENT, TX_HEIGHT_UNCONFIRMED) + TX_HEIGHT_UNCONF_PARENT, TX_HEIGHT_UNCONFIRMED, TX_HEIGHT_FUTURE) from .paymentrequest import (PR_PAID, PR_UNPAID, PR_UNKNOWN, PR_EXPIRED, InvoiceStore) from .contacts import Contacts @@ -626,6 +626,8 @@ class Abstract_Wallet(AddressSynchronizer): height = tx_mined_info.height conf = tx_mined_info.conf timestamp = tx_mined_info.timestamp + if height == TX_HEIGHT_FUTURE: + return 2, 'in %d blocks'%conf if conf == 0: tx = self.db.get_transaction(tx_hash) if not tx: