This fully closes bitcoin/bitcoin#12179. Currently, when a user abandons a transaction by clicking “Abandon Transaction” in the context menu, a call is made to remove it from the GUI view:
model->getTransactionTableModel()->updateTransaction(hashQStr, CT_UPDATED, false);
(The false
parameter is for bool showTransaction
)
This behavior is probably unwanted, as the transaction is not actually removed from the wallet and would show up again if the node is restarted.
However, the previous line, model->wallet().abandonTransaction(hash);
, changes the underlying model and calls NotifyTransactionChanged(wtx.GetHash(), CT_UPDATED);
, which queues a signal that eventually calls back to updateTransaction
, this time with showTransaction
set to true
. This runs on a separate thread, so it gets called after the ‘subsequent’ updateTransaction
. The transaction gets removed from the GUI and immediately added back.
In a nutshell, updateTransaction
gets called twice. The first (direct) call deletes the transaction from the GUI. The second (sent via a queued signal) brings it back to the GUI. The first direct call is redundant and unwanted. Worse, if the abandonTransaction
call fails for any reason, the transaction still gets removed from the GUI. (This is what caused bitcoin#12179. It can still be triggered if, eg., a user clicks “Abandon Transaction” the moment after a new block is found.)
There are no conditions (to my knowledge) where an abandoned transaction should be directly removed from the GUI. If the underlying model changes, the deletion should be reflected anyway by the queued signal to updateTransaction
.
The behavior is borne out by the QT logs. To reproduce, send a transaction with RBF enabled, then bump the fee, then ‘abandon transaction’ on the first transaction. The logs will show something like this:
02022-11-28T14:48:00Z [qt] GUI: "NotifyTransactionChanged: 2c5811484f1adec92a739a5e70b453b03eaed0f7cc0538fbd0ee1589e586b951 status= 1"
12022-11-28T14:48:00Z [qt] GUI: "TransactionTablePriv::updateWallet: 2c5811484f1adec92a739a5e70b453b03eaed0f7cc0538fbd0ee1589e586b951 1"
22022-11-28T14:48:00Z [qt] GUI: " inModel=1 Index=381-382 showTransaction=0 derivedStatus=2"
32022-11-28T14:48:00Z [qt] GUI: "TransactionTablePriv::updateWallet: 2c5811484f1adec92a739a5e70b453b03eaed0f7cc0538fbd0ee1589e586b951 1"
42022-11-28T14:48:00Z [qt] GUI: " inModel=0 Index=381-381 showTransaction=1 derivedStatus=0"
Notice the duplicate updateWallet
calls with different showTransaction
values.