add future transactions to address synchronizer
This commit is contained in:
@@ -43,6 +43,7 @@ if TYPE_CHECKING:
|
|||||||
from .json_db import JsonDB
|
from .json_db import JsonDB
|
||||||
|
|
||||||
|
|
||||||
|
TX_HEIGHT_FUTURE = -3
|
||||||
TX_HEIGHT_LOCAL = -2
|
TX_HEIGHT_LOCAL = -2
|
||||||
TX_HEIGHT_UNCONF_PARENT = -1
|
TX_HEIGHT_UNCONF_PARENT = -1
|
||||||
TX_HEIGHT_UNCONFIRMED = 0
|
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!
|
# locks: if you need to take multiple ones, acquire them in the order they are defined here!
|
||||||
self.lock = threading.RLock()
|
self.lock = threading.RLock()
|
||||||
self.transaction_lock = threading.RLock()
|
self.transaction_lock = threading.RLock()
|
||||||
|
self.future_tx = {} # txid -> blocks remaining
|
||||||
# Transactions pending verification. txid -> tx_height. Access with self.lock.
|
# Transactions pending verification. txid -> tx_height. Access with self.lock.
|
||||||
self.unverified_tx = defaultdict(int)
|
self.unverified_tx = defaultdict(int)
|
||||||
# true when synchronized
|
# true when synchronized
|
||||||
@@ -556,6 +558,11 @@ class AddressSynchronizer(Logger):
|
|||||||
return cached_local_height
|
return cached_local_height
|
||||||
return self.network.get_local_height() if self.network else self.db.get('stored_height', 0)
|
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:
|
def get_tx_height(self, tx_hash: str) -> TxMinedInfo:
|
||||||
with self.lock:
|
with self.lock:
|
||||||
verified_tx_mined_info = self.db.get_verified_tx(tx_hash)
|
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:
|
elif tx_hash in self.unverified_tx:
|
||||||
height = self.unverified_tx[tx_hash]
|
height = self.unverified_tx[tx_hash]
|
||||||
return TxMinedInfo(height=height, conf=0)
|
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:
|
else:
|
||||||
# local transaction
|
# local transaction
|
||||||
return TxMinedInfo(height=TX_HEIGHT_LOCAL, conf=0)
|
return TxMinedInfo(height=TX_HEIGHT_LOCAL, conf=0)
|
||||||
|
|||||||
@@ -39,7 +39,7 @@ from PyQt5.QtWidgets import (QMenu, QHeaderView, QLabel, QMessageBox,
|
|||||||
QPushButton, QComboBox, QVBoxLayout, QCalendarWidget,
|
QPushButton, QComboBox, QVBoxLayout, QCalendarWidget,
|
||||||
QGridLayout)
|
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.i18n import _
|
||||||
from electrum.util import (block_explorer_URL, profiler, TxMinedInfo,
|
from electrum.util import (block_explorer_URL, profiler, TxMinedInfo,
|
||||||
OrderedDictWithIndex, timestamp_to_datetime,
|
OrderedDictWithIndex, timestamp_to_datetime,
|
||||||
@@ -632,7 +632,7 @@ class HistoryList(MyTreeView, AcceptFileDragDrop):
|
|||||||
is_unconfirmed = height <= 0
|
is_unconfirmed = height <= 0
|
||||||
pr_key = self.wallet.invoices.paid.get(tx_hash)
|
pr_key = self.wallet.invoices.paid.get(tx_hash)
|
||||||
menu = QMenu()
|
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(_("Remove"), lambda: self.remove_local_tx(tx_hash))
|
||||||
menu.addAction(_("Copy Transaction ID"), lambda: self.parent.app.clipboard().setText(tx_hash))
|
menu.addAction(_("Copy Transaction ID"), lambda: self.parent.app.clipboard().setText(tx_hash))
|
||||||
|
|
||||||
|
|||||||
@@ -349,21 +349,23 @@ class LNWorker(PrintError):
|
|||||||
broadcast = True
|
broadcast = True
|
||||||
if e_tx.cltv_expiry:
|
if e_tx.cltv_expiry:
|
||||||
local_height = self.network.get_local_height()
|
local_height = self.network.get_local_height()
|
||||||
if local_height > e_tx.cltv_expiry:
|
remaining = e_tx.cltv_expiry - local_height
|
||||||
self.print_error(e_tx.name, 'CLTV ({} > {}) fulfilled'.format(local_height, e_tx.cltv_expiry))
|
if remaining > 0:
|
||||||
else:
|
|
||||||
self.print_error(e_tx.name, 'waiting for {}: CLTV ({} > {}), funding outpoint {} and tx {}'
|
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]))
|
.format(e_tx.name, local_height, e_tx.cltv_expiry, funding_outpoint[:8], prev_txid[:8]))
|
||||||
broadcast = False
|
broadcast = False
|
||||||
if e_tx.csv_delay:
|
if e_tx.csv_delay:
|
||||||
num_conf = self.network.lnwatcher.get_tx_height(prev_txid).conf
|
prev_height = self.network.lnwatcher.get_tx_height(prev_txid)
|
||||||
if num_conf < e_tx.csv_delay:
|
remaining = e_tx.csv_delay - prev_height.conf
|
||||||
|
if remaining > 0:
|
||||||
self.print_error(e_tx.name, 'waiting for {}: CSV ({} >= {}), funding outpoint {} and tx {}'
|
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
|
broadcast = False
|
||||||
if broadcast:
|
if broadcast:
|
||||||
if not await self.network.lnwatcher.broadcast_or_log(funding_outpoint, e_tx):
|
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}')
|
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
|
@log_exceptions
|
||||||
|
|||||||
@@ -56,7 +56,7 @@ from . import transaction, bitcoin, coinchooser, paymentrequest, ecc, bip32
|
|||||||
from .transaction import Transaction, TxOutput, TxOutputHwInfo
|
from .transaction import Transaction, TxOutput, TxOutputHwInfo
|
||||||
from .plugin import run_hook
|
from .plugin import run_hook
|
||||||
from .address_synchronizer import (AddressSynchronizer, TX_HEIGHT_LOCAL,
|
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,
|
from .paymentrequest import (PR_PAID, PR_UNPAID, PR_UNKNOWN, PR_EXPIRED,
|
||||||
InvoiceStore)
|
InvoiceStore)
|
||||||
from .contacts import Contacts
|
from .contacts import Contacts
|
||||||
@@ -626,6 +626,8 @@ class Abstract_Wallet(AddressSynchronizer):
|
|||||||
height = tx_mined_info.height
|
height = tx_mined_info.height
|
||||||
conf = tx_mined_info.conf
|
conf = tx_mined_info.conf
|
||||||
timestamp = tx_mined_info.timestamp
|
timestamp = tx_mined_info.timestamp
|
||||||
|
if height == TX_HEIGHT_FUTURE:
|
||||||
|
return 2, 'in %d blocks'%conf
|
||||||
if conf == 0:
|
if conf == 0:
|
||||||
tx = self.db.get_transaction(tx_hash)
|
tx = self.db.get_transaction(tx_hash)
|
||||||
if not tx:
|
if not tx:
|
||||||
|
|||||||
Reference in New Issue
Block a user