From f832c33d76dd07f6cf63699e9e347095827cf8d1 Mon Sep 17 00:00:00 2001 From: SomberNight Date: Thu, 9 Oct 2025 14:36:15 +0000 Subject: [PATCH 1/4] qt: main_window.confirm_tx_dialog: rm dead code --- electrum/gui/qt/main_window.py | 9 +-------- 1 file changed, 1 insertion(+), 8 deletions(-) diff --git a/electrum/gui/qt/main_window.py b/electrum/gui/qt/main_window.py index 31f0b8446..086b735a7 100644 --- a/electrum/gui/qt/main_window.py +++ b/electrum/gui/qt/main_window.py @@ -1509,15 +1509,8 @@ class ElectrumWindow(QMainWindow, MessageBoxMixin, Logger, QtEventListener): return self._open_channel(connect_str, funding_sat, push_amt, funding_tx) - def confirm_tx_dialog(self, make_tx, output_value, allow_preview=True, batching_candidates=None): + def confirm_tx_dialog(self, make_tx, output_value, *, allow_preview=True, batching_candidates=None) -> tuple[Optional[PartialTransaction], bool]: d = ConfirmTxDialog(window=self, make_tx=make_tx, output_value=output_value, allow_preview=allow_preview, batching_candidates=batching_candidates) - if d.not_enough_funds: # FIXME this check looks broken? - # note: use confirmed_only=False here, regardless of config setting, - # as the user needs to get to ConfirmTxDialog to change the config setting - if not d.can_pay_assuming_zero_fees(confirmed_only=False): - text = self.wallet.get_text_not_enough_funds_mentioning_frozen(for_amount=output_value) - self.show_message(text) - return return d.run(), d.is_preview @protected From f1ad5bc23d99a300ca5c527fdf43ed3eb535a8ea Mon Sep 17 00:00:00 2001 From: SomberNight Date: Thu, 9 Oct 2025 14:46:42 +0000 Subject: [PATCH 2/4] transaction: (move-only) move some methods from Tx to PartialTx cls these were already assuming `isinstance(self, PartialTransaction)` --- electrum/transaction.py | 48 ++++++++++++++++++++--------------------- 1 file changed, 24 insertions(+), 24 deletions(-) diff --git a/electrum/transaction.py b/electrum/transaction.py index 7126e0c88..eed3820e7 100644 --- a/electrum/transaction.py +++ b/electrum/transaction.py @@ -1436,30 +1436,6 @@ class Transaction: script = bitcoin.address_to_script(addr) return self.get_output_idxs_from_scriptpubkey(script) - def replace_output_address(self, old_address: str, new_address: str) -> None: - idx = list(self.get_output_idxs_from_address(old_address)) - assert len(idx) == 1 - amount = self._outputs[idx[0]].value - funding_output = PartialTxOutput.from_address_and_value(new_address, amount) - old_output = PartialTxOutput.from_address_and_value(old_address, amount) - self._outputs.remove(old_output) - self.add_outputs([funding_output]) - delattr(self, '_script_to_output_idx') - - def get_change_outputs(self): - return [o for o in self._outputs if o.is_change] - - def has_change(self): - return len(self.get_change_outputs()) > 0 - - def get_dummy_output(self, dummy_addr: str) -> Optional['PartialTxOutput']: - idxs = self.get_output_idxs_from_address(dummy_addr) - if not idxs: - return - assert len(idxs) == 1 - for i in idxs: - return self.outputs()[i] - def output_value_for_address(self, addr): # assumes exactly one output has that address for o in self.outputs(): @@ -2434,6 +2410,30 @@ class PartialTransaction(Transaction): self.BIP69_sort(inputs=False) self.invalidate_ser_cache() + def replace_output_address(self, old_address: str, new_address: str) -> None: + idx = list(self.get_output_idxs_from_address(old_address)) + assert len(idx) == 1 + amount = self._outputs[idx[0]].value + funding_output = PartialTxOutput.from_address_and_value(new_address, amount) + old_output = PartialTxOutput.from_address_and_value(old_address, amount) + self._outputs.remove(old_output) + self.add_outputs([funding_output]) + delattr(self, '_script_to_output_idx') + + def get_change_outputs(self): + return [o for o in self._outputs if o.is_change] + + def has_change(self): + return len(self.get_change_outputs()) > 0 + + def get_dummy_output(self, dummy_addr: str) -> Optional['PartialTxOutput']: + idxs = self.get_output_idxs_from_address(dummy_addr) + if not idxs: + return + assert len(idxs) == 1 + for i in idxs: + return self.outputs()[i] + def set_rbf(self, rbf: bool) -> None: nSequence = 0xffffffff - (2 if rbf else 1) for txin in self.inputs(): From 3379e462498cee56b909f2e1a9a8cdfdabdae4e5 Mon Sep 17 00:00:00 2001 From: SomberNight Date: Thu, 9 Oct 2025 14:57:41 +0000 Subject: [PATCH 3/4] follow-up prev: add type-hints, etc --- electrum/transaction.py | 12 ++++++------ electrum/txbatcher.py | 2 +- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/electrum/transaction.py b/electrum/transaction.py index eed3820e7..cca06ff18 100644 --- a/electrum/transaction.py +++ b/electrum/transaction.py @@ -2420,19 +2420,19 @@ class PartialTransaction(Transaction): self.add_outputs([funding_output]) delattr(self, '_script_to_output_idx') - def get_change_outputs(self): - return [o for o in self._outputs if o.is_change] + def get_change_outputs(self) -> Sequence[PartialTxOutput]: + return [o for o in self._outputs if o.is_change] - def has_change(self): + def has_change(self) -> bool: return len(self.get_change_outputs()) > 0 def get_dummy_output(self, dummy_addr: str) -> Optional['PartialTxOutput']: idxs = self.get_output_idxs_from_address(dummy_addr) if not idxs: - return + return None assert len(idxs) == 1 - for i in idxs: - return self.outputs()[i] + idx = list(idxs)[0] + return self.outputs()[idx] def set_rbf(self, rbf: bool) -> None: nSequence = 0xffffffff - (2 if rbf else 1) diff --git a/electrum/txbatcher.py b/electrum/txbatcher.py index 3dcf159fd..6451bfb33 100644 --- a/electrum/txbatcher.py +++ b/electrum/txbatcher.py @@ -559,7 +559,7 @@ class TxBatch(Logger): self._prevout = None @locked - def _new_base_tx(self, tx: Transaction) -> None: + def _new_base_tx(self, tx: PartialTransaction) -> None: self._prevout = tx.inputs()[0].prevout.to_str() self.storage['prevout'] = self._prevout if tx.has_change(): From 6e45d6e690282ea417c4d2d8b4e07f7480719bec Mon Sep 17 00:00:00 2001 From: SomberNight Date: Thu, 9 Oct 2025 15:06:23 +0000 Subject: [PATCH 4/4] lnworker: (trivial) add a few missing type-hints --- electrum/lnworker.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/electrum/lnworker.py b/electrum/lnworker.py index 1501ef023..607968d2e 100644 --- a/electrum/lnworker.py +++ b/electrum/lnworker.py @@ -1435,12 +1435,12 @@ class LNWallet(LNWorker): def cb_data(self, node_id: bytes) -> bytes: return CB_MAGIC_BYTES + node_id[0:NODE_ID_PREFIX_LEN] - def decrypt_cb_data(self, encrypted_data, funding_address): + def decrypt_cb_data(self, encrypted_data: bytes, funding_address: str) -> bytes: funding_scripthash = bytes.fromhex(address_to_scripthash(funding_address)) nonce = funding_scripthash[0:12] return chacha20_decrypt(key=self.backup_key, data=encrypted_data, nonce=nonce) - def encrypt_cb_data(self, data, funding_address): + def encrypt_cb_data(self, data: bytes, funding_address: str) -> bytes: funding_scripthash = bytes.fromhex(address_to_scripthash(funding_address)) nonce = funding_scripthash[0:12] # note: we are only using chacha20 instead of chacha20+poly1305 to save onchain space @@ -1473,7 +1473,7 @@ class LNWallet(LNWorker): tx.locktime = get_locktime_for_new_transaction(self.network, include_random_component=False) return tx - def suggest_funding_amount(self, amount_to_pay, coins) -> Tuple[int, int] | None: + def suggest_funding_amount(self, amount_to_pay: int, coins: Sequence[PartialTxInput]) -> Tuple[int, int] | None: """ whether we can pay amount_sat after opening a new channel""" num_sats_can_send = int(self.num_sats_can_send()) lightning_needed = amount_to_pay - num_sats_can_send