wallet.remove_transaction: also rm dependent/child txs
Main motivation is that I often use wallet.remove_transaction from the Qt console, and would find this behaviour more intuitive. Note that previously if one were to call this on a tx with children, the crash reporter would appear with "wallet.get_history() failed balance sanity-check". related: https://github.com/spesmilo/electrum/issues/6960#issuecomment-764716533
This commit is contained in:
@@ -292,11 +292,7 @@ class AddressSynchronizer(Logger):
|
||||
# this is a local tx that conflicts with non-local txns; drop.
|
||||
return False
|
||||
# keep this txn and remove all conflicting
|
||||
to_remove = set()
|
||||
to_remove |= conflicting_txns
|
||||
for conflicting_tx_hash in conflicting_txns:
|
||||
to_remove |= self.get_depending_transactions(conflicting_tx_hash)
|
||||
for tx_hash2 in to_remove:
|
||||
for tx_hash2 in conflicting_txns:
|
||||
self.remove_transaction(tx_hash2)
|
||||
# add inputs
|
||||
def add_value_from_prev_output():
|
||||
@@ -342,6 +338,19 @@ class AddressSynchronizer(Logger):
|
||||
return True
|
||||
|
||||
def remove_transaction(self, tx_hash: str) -> None:
|
||||
"""Removes a transaction AND all its dependents/children
|
||||
from the wallet history.
|
||||
"""
|
||||
with self.lock, self.transaction_lock:
|
||||
to_remove = {tx_hash}
|
||||
to_remove |= self.get_depending_transactions(tx_hash)
|
||||
for txid in to_remove:
|
||||
self._remove_transaction(txid)
|
||||
|
||||
def _remove_transaction(self, tx_hash: str) -> None:
|
||||
"""Removes a single transaction from the wallet history, and attempts
|
||||
to undo all effects of the tx (spending inputs, creating outputs, etc).
|
||||
"""
|
||||
def remove_from_spent_outpoints():
|
||||
# undo spends in spent_outpoints
|
||||
if tx is not None:
|
||||
|
||||
@@ -933,13 +933,10 @@ class Commands:
|
||||
if not is_hash256_str(txid):
|
||||
raise Exception(f"{repr(txid)} is not a txid")
|
||||
height = wallet.get_tx_height(txid).height
|
||||
to_delete = {txid}
|
||||
if height != TX_HEIGHT_LOCAL:
|
||||
raise Exception(f'Only local transactions can be removed. '
|
||||
f'This tx has height: {height} != {TX_HEIGHT_LOCAL}')
|
||||
to_delete |= wallet.get_depending_transactions(txid)
|
||||
for tx_hash in to_delete:
|
||||
wallet.remove_transaction(tx_hash)
|
||||
wallet.remove_transaction(txid)
|
||||
wallet.save_db()
|
||||
|
||||
@command('wn')
|
||||
|
||||
@@ -348,17 +348,15 @@ class TxDialog(Factory.Popup):
|
||||
|
||||
def remove_local_tx(self):
|
||||
txid = self.tx.txid()
|
||||
to_delete = {txid}
|
||||
to_delete |= self.wallet.get_depending_transactions(txid)
|
||||
num_child_txs = len(self.wallet.get_depending_transactions(txid))
|
||||
question = _("Are you sure you want to remove this transaction?")
|
||||
if len(to_delete) > 1:
|
||||
if num_child_txs > 0:
|
||||
question = (_("Are you sure you want to remove this transaction and {} child transactions?")
|
||||
.format(len(to_delete) - 1))
|
||||
.format(num_child_txs))
|
||||
|
||||
def on_prompt(b):
|
||||
if b:
|
||||
for tx in to_delete:
|
||||
self.wallet.remove_transaction(tx)
|
||||
self.wallet.remove_transaction(txid)
|
||||
self.wallet.save_db()
|
||||
self.app._trigger_update_wallet() # FIXME private...
|
||||
self.dismiss()
|
||||
|
||||
@@ -710,17 +710,15 @@ class HistoryList(MyTreeView, AcceptFileDragDrop):
|
||||
menu.exec_(self.viewport().mapToGlobal(position))
|
||||
|
||||
def remove_local_tx(self, tx_hash: str):
|
||||
to_delete = {tx_hash}
|
||||
to_delete |= self.wallet.get_depending_transactions(tx_hash)
|
||||
num_child_txs = len(self.wallet.get_depending_transactions(tx_hash))
|
||||
question = _("Are you sure you want to remove this transaction?")
|
||||
if len(to_delete) > 1:
|
||||
if num_child_txs > 0:
|
||||
question = (_("Are you sure you want to remove this transaction and {} child transactions?")
|
||||
.format(len(to_delete) - 1))
|
||||
.format(num_child_txs))
|
||||
if not self.parent.question(msg=question,
|
||||
title=_("Please confirm")):
|
||||
return
|
||||
for tx in to_delete:
|
||||
self.wallet.remove_transaction(tx)
|
||||
self.wallet.remove_transaction(tx_hash)
|
||||
self.wallet.save_db()
|
||||
# need to update at least: history_list, utxo_list, address_list
|
||||
self.parent.need_update.set()
|
||||
|
||||
Reference in New Issue
Block a user