diff --git a/electrum/submarine_swaps.py b/electrum/submarine_swaps.py index 405e2e491..30a07ec29 100644 --- a/electrum/submarine_swaps.py +++ b/electrum/submarine_swaps.py @@ -300,7 +300,7 @@ class SwapManager(Logger): dummy_output = PartialTxOutput.from_address_and_value(ln_dummy_address(), expected_onchain_amount_sat) tx.outputs().remove(dummy_output) tx.add_outputs([funding_output]) - tx.set_rbf(True) # rbf must not decrease payment + tx.set_rbf(True) # note: rbf must not decrease payment self.wallet.sign_transaction(tx, password) # save swap data in wallet in case we need a refund swap = SwapData( @@ -543,6 +543,12 @@ class SwapManager(Logger): return swap return None + def is_lockup_address_for_a_swap(self, addr: str) -> bool: + for key, swap in self.swaps.items(): # TODO take lock? or add index to avoid looping + if addr == swap.lockup_address: + return True + return False + def sign_tx(self, tx, swap): preimage = swap.preimage if swap.is_reverse else 0 witness_script = swap.redeem_script diff --git a/electrum/wallet.py b/electrum/wallet.py index f056762fd..5c7278e17 100644 --- a/electrum/wallet.py +++ b/electrum/wallet.py @@ -1713,11 +1713,7 @@ class Abstract_Wallet(AddressSynchronizer, ABC): s = list(filter(lambda o: self.is_mine(o.address), outputs)) # ... unless there is none if not s: - s = outputs - x_fee = run_hook('get_tx_extra_fee', self, tx) - if x_fee: - x_fee_address, x_fee_amount = x_fee - s = list(filter(lambda o: o.address != x_fee_address, s)) + s = [out for out in outputs if self._is_rbf_allowed_to_touch_tx_output(out)] if not s: raise CannotBumpFee('No outputs at all??') @@ -1764,11 +1760,7 @@ class Abstract_Wallet(AddressSynchronizer, ABC): # select non-ismine outputs s = [(idx, out) for (idx, out) in enumerate(outputs) if not self.is_mine(out.address)] - # exempt 2fa fee output if present - x_fee = run_hook('get_tx_extra_fee', self, tx) - if x_fee: - x_fee_address, x_fee_amount = x_fee - s = [(idx, out) for (idx, out) in s if out.address != x_fee_address] + s = [(idx, out) for (idx, out) in s if self._is_rbf_allowed_to_touch_tx_output(out)] if not s: raise CannotBumpFee("Cannot find payment output") @@ -1803,6 +1795,15 @@ class Abstract_Wallet(AddressSynchronizer, ABC): outputs = [out for (idx, out) in enumerate(outputs) if idx not in del_out_idxs] return PartialTransaction.from_io(inputs, outputs) + def _is_rbf_allowed_to_touch_tx_output(self, txout: TxOutput) -> bool: + # 2fa fee outputs if present, should not be removed or have their value decreased + if self.is_billing_address(txout.address): + return False + # submarine swap funding outputs must not be decreased + if self.lnworker and self.lnworker.swap_manager.is_lockup_address_for_a_swap(txout.address): + return False + return True + def cpfp(self, tx: Transaction, fee: int) -> Optional[PartialTransaction]: txid = tx.txid() for i, o in enumerate(tx.outputs()):