URI: 
       twallet/GUI: don't allow "removing" a LN force-close-tx from history - electrum - Electrum Bitcoin wallet
  HTML git clone https://git.parazyd.org/electrum
   DIR Log
   DIR Files
   DIR Refs
   DIR Submodules
       ---
   DIR commit 7a574c3cbc03c982dfa6e8ea40a3a97c33afce7a
   DIR parent 32acc2b10e2049371b38aba875f2f830f06c4676
  HTML Author: SomberNight <somber.night@protonmail.com>
       Date:   Mon,  2 Mar 2020 05:11:08 +0100
       
       wallet/GUI: don't allow "removing" a LN force-close-tx from history
       
       Diffstat:
         M electrum/address_synchronizer.py    |       2 +-
         M electrum/gui/kivy/uix/dialogs/tx_d… |       4 ++--
         M electrum/gui/qt/history_list.py     |      16 +++++++---------
         M electrum/wallet.py                  |       5 +++++
       
       4 files changed, 15 insertions(+), 12 deletions(-)
       ---
   DIR diff --git a/electrum/address_synchronizer.py b/electrum/address_synchronizer.py
       t@@ -345,7 +345,7 @@ class AddressSynchronizer(Logger):
                            prevout = TxOutpoint(bfh(tx_hash), idx)
                            self.db.remove_prevout_by_scripthash(scripthash, prevout=prevout, value=txo.value)
        
       -    def get_depending_transactions(self, tx_hash):
       +    def get_depending_transactions(self, tx_hash: str) -> Set[str]:
                """Returns all (grand-)children of tx_hash in this wallet."""
                with self.transaction_lock:
                    children = set()
   DIR diff --git a/electrum/gui/kivy/uix/dialogs/tx_dialog.py b/electrum/gui/kivy/uix/dialogs/tx_dialog.py
       t@@ -186,7 +186,7 @@ class TxDialog(Factory.Popup):
                for dict_entry in self.ids.output_list.data:
                    dict_entry['color'], dict_entry['background_color'] = address_colors(self.wallet, dict_entry['address'])
        
       -        self.is_local_tx = tx_mined_status.height == TX_HEIGHT_LOCAL
       +        self.can_remove_tx = tx_details.can_remove
                self.update_action_button()
        
            def update_action_button(self):
       t@@ -195,7 +195,7 @@ class TxDialog(Factory.Popup):
                    ActionButtonOption(text=_('Sign'), func=lambda btn: self.do_sign(), enabled=self.can_sign),
                    ActionButtonOption(text=_('Broadcast'), func=lambda btn: self.do_broadcast(), enabled=self.can_broadcast),
                    ActionButtonOption(text=_('Bump fee'), func=lambda btn: self.do_rbf(), enabled=self.can_rbf),
       -            ActionButtonOption(text=_('Remove'), func=lambda btn: self.remove_local_tx(), enabled=self.is_local_tx),
       +            ActionButtonOption(text=_('Remove'), func=lambda btn: self.remove_local_tx(), enabled=self.can_remove_tx),
                )
                num_options = sum(map(lambda o: bool(o.enabled), options))
                # if no options available, hide button
   DIR diff --git a/electrum/gui/qt/history_list.py b/electrum/gui/qt/history_list.py
       t@@ -632,12 +632,11 @@ class HistoryList(MyTreeView, AcceptFileDragDrop):
                if not tx:
                    return
                tx_URL = block_explorer_URL(self.config, 'tx', tx_hash)
       -        height = self.wallet.get_tx_height(tx_hash).height
       -        is_relevant, is_mine, v, fee = self.wallet.get_wallet_delta(tx)
       -        is_unconfirmed = height <= 0
       +        tx_details = self.wallet.get_tx_info(tx)
       +        is_unconfirmed = tx_details.tx_mined_status.height <= 0
                invoice_keys = self.wallet._get_relevant_invoice_keys_for_tx(tx)
                menu = QMenu()
       -        if height in [TX_HEIGHT_FUTURE, TX_HEIGHT_LOCAL]:
       +        if tx_details.can_remove:
                    menu.addAction(_("Remove"), lambda: self.remove_local_tx(tx_hash))
                menu.addAction(_("Copy Transaction ID"), lambda: self.place_text_on_clipboard(tx_hash, title="TXID"))
                self.add_copy_menu(menu, idx)
       t@@ -650,8 +649,7 @@ class HistoryList(MyTreeView, AcceptFileDragDrop):
                menu.addAction(_("Details"), lambda: self.show_transaction(tx_item, tx))
                if is_unconfirmed and tx:
                    # note: the current implementation of RBF *needs* the old tx fee
       -            rbf = is_mine and not tx.is_final() and fee is not None
       -            if rbf:
       +            if tx_details.can_bump and tx_details.fee is not None:
                        menu.addAction(_("Increase fee"), lambda: self.parent.bump_fee_dialog(tx))
                    else:
                        child_tx = self.wallet.cpfp(tx, 0)
       t@@ -663,9 +661,9 @@ class HistoryList(MyTreeView, AcceptFileDragDrop):
                    menu.addAction(_("View on block explorer"), lambda: webopen(tx_URL))
                menu.exec_(self.viewport().mapToGlobal(position))
        
       -    def remove_local_tx(self, delete_tx):
       -        to_delete = {delete_tx}
       -        to_delete |= self.wallet.get_depending_transactions(delete_tx)
       +    def remove_local_tx(self, tx_hash: str):
       +        to_delete = {tx_hash}
       +        to_delete |= self.wallet.get_depending_transactions(tx_hash)
                question = _("Are you sure you want to remove this transaction?")
                if len(to_delete) > 1:
                    question = (_("Are you sure you want to remove this transaction and {} child transactions?")
   DIR diff --git a/electrum/wallet.py b/electrum/wallet.py
       t@@ -210,6 +210,7 @@ class TxWalletDetails(NamedTuple):
            fee: Optional[int]
            tx_mined_status: TxMinedInfo
            mempool_depth_bytes: Optional[int]
       +    can_remove: bool  # whether user should be allowed to delete tx
        
        
        class Abstract_Wallet(AddressSynchronizer, ABC):
       t@@ -495,6 +496,9 @@ class Abstract_Wallet(AddressSynchronizer, ABC):
                                     and (tx_we_already_have_in_db is None or not tx_we_already_have_in_db.is_complete()))
                label = ''
                tx_mined_status = self.get_tx_height(tx_hash)
       +        # note: is_relevant check added to 'can_remove' as otherwise 'height' is unreliable (typically LOCAL).
       +        #       e.g. user should not be allowed to remove a lightning force-close-tx
       +        can_remove = is_relevant and (tx_mined_status.height in [TX_HEIGHT_FUTURE, TX_HEIGHT_LOCAL])
                if tx.is_complete():
                    if tx_we_already_have_in_db:
                        label = self.get_label(tx_hash)
       t@@ -545,6 +549,7 @@ class Abstract_Wallet(AddressSynchronizer, ABC):
                    fee=fee,
                    tx_mined_status=tx_mined_status,
                    mempool_depth_bytes=exp_n,
       +            can_remove=can_remove,
                )
        
            def get_spendable_coins(self, domain, *, nonlocal_only=False) -> Sequence[PartialTxInput]: