From 03018fa2183f0c60519bb968c1ebfe4cf0081a3a Mon Sep 17 00:00:00 2001 From: f321x Date: Fri, 28 Mar 2025 15:49:25 +0100 Subject: [PATCH] make txbatcher wait for network connection --- electrum/txbatcher.py | 16 ++++++++++++---- tests/test_txbatcher.py | 3 +++ 2 files changed, 15 insertions(+), 4 deletions(-) diff --git a/electrum/txbatcher.py b/electrum/txbatcher.py index a6d97905e..aa48f6897 100644 --- a/electrum/txbatcher.py +++ b/electrum/txbatcher.py @@ -6,11 +6,14 @@ from typing import Dict, Sequence from . import util from .bitcoin import dust_threshold from .logging import Logger -from .util import log_exceptions, NotEnoughFunds, BelowDustLimit +from .util import log_exceptions, NotEnoughFunds, BelowDustLimit, NoDynamicFeeEstimates from .transaction import PartialTransaction, PartialTxOutput, Transaction from .address_synchronizer import TX_HEIGHT_LOCAL, TX_HEIGHT_FUTURE from .lnsweep import SweepInfo -from typing import Optional +from typing import Optional, TYPE_CHECKING + +if TYPE_CHECKING: + from .wallet import Abstract_Wallet # This class batches outgoing payments and incoming utxo sweeps. # It ensures that we do not send a payment twice. @@ -80,7 +83,7 @@ class TxBatcher(Logger): SLEEP_INTERVAL = 1 - def __init__(self, wallet): + def __init__(self, wallet: 'Abstract_Wallet'): Logger.__init__(self) self.lock = threading.RLock() self.storage = wallet.db.get_stored_item("tx_batches", {}) @@ -140,6 +143,8 @@ class TxBatcher(Logger): password = self.wallet.get_unlocked_password() if self.wallet.has_keystore_encryption() and not password: continue + if not (self.wallet.network and self.wallet.network.is_connected()): + continue for key, txbatch in list(self.tx_batches.items()): try: await txbatch.run_iteration(password) @@ -286,7 +291,7 @@ class TxBatch(Logger): if not self.is_mine(base_tx.txid()): return False base_tx_fee = base_tx.get_fee() - recommended_fee = self.fee_policy.estimate_fee(base_tx.estimated_size(), network=self.wallet.network, allow_fallback_to_static_rates=True) + recommended_fee = self.fee_policy.estimate_fee(base_tx.estimated_size(), network=self.wallet.network) should_bump_fee = base_tx_fee * 1.1 < recommended_fee if should_bump_fee: self.logger.info(f'base tx fee too low {base_tx_fee} < {recommended_fee}. we will bump the fee') @@ -307,6 +312,9 @@ class TxBatch(Logger): # if base tx has been RBF-replaced, detect it here try: tx = self.create_next_transaction(base_tx, password) + except NoDynamicFeeEstimates: + self.logger.debug('no dynamic fee estimates available') + return except Exception as e: if base_tx: self.logger.exception(f'Cannot create batch transaction: {repr(e)}') diff --git a/tests/test_txbatcher.py b/tests/test_txbatcher.py index 31e8d6cd6..10f83ab57 100644 --- a/tests/test_txbatcher.py +++ b/tests/test_txbatcher.py @@ -50,6 +50,9 @@ class MockNetwork(Logger): tx = await util.wait_for2(self._tx_queue.get(), timeout=10) return tx + def is_connected(self): + return True + SWAP_FUNDING_TX = "01000000000101500e9d67647481864edfb020b5c45e1c40d90f06b0130f9faed1a5149c6d26450000000000ffffffff0226080300000000002200205059c44bf57534303ab8f090f06b7bde58f5d2522440247a1ff6b41bdca9348df312c20100000000160014021d4f3b17921d790e1c022367a5bb078ce4deb402483045022100d41331089a2031396a1db8e4dec6dda9cacefe1288644b92f8e08a23325aa19b02204159230691601f7d726e4e6e0b7124d3377620f400d699a01095f0b0a09ee26a012102d60315c72c0cefd41c6d07883c20b88be3fc37aac7912f0052722a95de0de71600000000" SWAP_CLAIM_TX = "02000000000101f9db8580febd5c0f85b6f1576c83f7739109e3a2d772743e3217e9537fea7e890000000000fdffffff017005030000000000160014b113a47f3718da3fd161339a6681c150fef2cfe30347304402206736066ce15d34eed20951a9d974a100a72dc034f9c878769ddf27f9a584dcb1022042b14d627b8e8465a3a129bb43c0bd8369f49bbcf473879b9a477263655f1f930120f1939b5723155713855d7ebea6e174f77d41d669269e7f138856c3de190e7a366a8201208763a914d7a62ef0270960fe23f0f351b28caadab62c21838821030bfd61153816df786036ea293edce851d3a4b9f4a1c66bdc1a17f00ffef3d6b167750334ef24b1752102fc8128f17f9e666ea281c702171ab16c1dd2a4337b71f08970f5aa10c608a93268ac00000000"