From 42f2a3da317471748848d04cc6d3b136b71103f4 Mon Sep 17 00:00:00 2001 From: SomberNight <somber.night@protonmail.com> Date: Tue, 30 Aug 2022 11:46:52 +0000 Subject: [PATCH] Qt pay_lightning_invoice: handle NoDynamicFeeEstimates `wallet.make_unsigned_transaction` can raise NotEnoughFunds or NoDynamicFeeEstimates. These are "expected" exceptions that need to be handled or worked around. Added a note of this in the docstring now. We now handle NoDynamicFeeEstimates by allowing a static fallback fee in `wallet.can_pay_onchain` and `lnworker.suggest_funding_amount`. It should be fine to have a static fallback in these cases, as the user still has a chance to set their own fee later in the flow. (though ofc the static fallback might be too high in some mempool conditions, in which case e.g. can_pay_onchain might return a false-negative, but this is still an improvement over raising I believe) fixes https://github.com/spesmilo/electrum/issues/5784 --- electrum/gui/qt/send_tab.py | 2 +- electrum/lnworker.py | 5 +++-- electrum/wallet.py | 4 +++- 3 files changed, 7 insertions(+), 4 deletions(-) diff --git a/electrum/gui/qt/send_tab.py b/electrum/gui/qt/send_tab.py index a3fe4966a..395cba612 100644 --- a/electrum/gui/qt/send_tab.py +++ b/electrum/gui/qt/send_tab.py @@ -686,7 +686,7 @@ class SendTab(QWidget, MessageBoxMixin, Logger): choices[3] = msg msg = _('You cannot pay that invoice using Lightning.') if self.wallet.lnworker.channels: - msg += '\n' + _('Your channels can send {}.').format(self.format_amount(num_sats_can_send) + self.base_unit()) + msg += '\n' + _('Your channels can send {}.').format(self.format_amount(num_sats_can_send) + ' ' + self.base_unit()) if not choices: self.window.show_error(msg) return diff --git a/electrum/lnworker.py b/electrum/lnworker.py index 07bf038f2..20a67e5da 100644 --- a/electrum/lnworker.py +++ b/electrum/lnworker.py @@ -1097,15 +1097,16 @@ class LNWallet(LNWorker): min_funding_sat = max(min_funding_sat, 100_000) # at least 1mBTC if min_funding_sat > LN_MAX_FUNDING_SAT: return + fee_est = partial(self.config.estimate_fee, allow_fallback_to_static_rates=True) # to avoid NoDynamicFeeEstimates try: - self.mktx_for_open_channel(coins=coins, funding_sat=min_funding_sat, node_id=bytes(32), fee_est=None) + self.mktx_for_open_channel(coins=coins, funding_sat=min_funding_sat, node_id=bytes(32), fee_est=fee_est) funding_sat = min_funding_sat except NotEnoughFunds: return # if available, suggest twice that amount: if 2 * min_funding_sat <= LN_MAX_FUNDING_SAT: try: - self.mktx_for_open_channel(coins=coins, funding_sat=2*min_funding_sat, node_id=bytes(32), fee_est=None) + self.mktx_for_open_channel(coins=coins, funding_sat=2*min_funding_sat, node_id=bytes(32), fee_est=fee_est) funding_sat = 2 * min_funding_sat except NotEnoughFunds: pass diff --git a/electrum/wallet.py b/electrum/wallet.py index f8c4f1440..b70685b0d 100644 --- a/electrum/wallet.py +++ b/electrum/wallet.py @@ -1548,11 +1548,12 @@ class Abstract_Wallet(ABC, Logger, EventListener): return selected_addr def can_pay_onchain(self, outputs, coins=None): + fee = partial(self.config.estimate_fee, allow_fallback_to_static_rates=True) # to avoid NoDynamicFeeEstimates try: self.make_unsigned_transaction( coins=coins, outputs=outputs, - fee=None) + fee=fee) except NotEnoughFunds: return False return True @@ -1565,6 +1566,7 @@ class Abstract_Wallet(ABC, Logger, EventListener): change_addr: str = None, is_sweep=False, rbf=False) -> PartialTransaction: + """Can raise NotEnoughFunds or NoDynamicFeeEstimates.""" if not coins: # any bitcoin tx must have at least 1 input by consensus raise NotEnoughFunds()