From 474139aa9bf7109df78e46936e5a649c70703386 Mon Sep 17 00:00:00 2001 From: furszy Date: Tue, 4 Feb 2025 10:34:48 -0500 Subject: [PATCH] wallet: abandon inactive coinbase tx and their descendants during startup --- src/wallet/wallet.cpp | 13 ++++++++----- src/wallet/wallet.h | 1 + src/wallet/walletdb.cpp | 8 ++++++++ 3 files changed, 17 insertions(+), 5 deletions(-) diff --git a/src/wallet/wallet.cpp b/src/wallet/wallet.cpp index dd9dfcd516a..2a67d9e8db2 100644 --- a/src/wallet/wallet.cpp +++ b/src/wallet/wallet.cpp @@ -1315,12 +1315,15 @@ void CWallet::MarkInputsDirty(const CTransactionRef& tx) bool CWallet::AbandonTransaction(const uint256& hashTx) { LOCK(cs_wallet); - - // Can't mark abandoned if confirmed or in mempool auto it = mapWallet.find(hashTx); assert(it != mapWallet.end()); - const CWalletTx& origtx = it->second; - if (GetTxDepthInMainChain(origtx) != 0 || origtx.InMempool()) { + return AbandonTransaction(it->second); +} + +bool CWallet::AbandonTransaction(CWalletTx& tx) +{ + // Can't mark abandoned if confirmed or in mempool + if (GetTxDepthInMainChain(tx) != 0 || tx.InMempool()) { return false; } @@ -1342,7 +1345,7 @@ bool CWallet::AbandonTransaction(const uint256& hashTx) // Note: If the reorged coinbase is re-added to the main chain, the descendants that have not had their // states change will remain abandoned and will require manual broadcast if the user wants them. - RecursiveUpdateTxState(hashTx, try_updating_state); + RecursiveUpdateTxState(tx.GetHash(), try_updating_state); return true; } diff --git a/src/wallet/wallet.h b/src/wallet/wallet.h index 0afe71a40ef..c475718eb94 100644 --- a/src/wallet/wallet.h +++ b/src/wallet/wallet.h @@ -871,6 +871,7 @@ public: /* Mark a transaction (and it in-wallet descendants) as abandoned so its inputs may be respent. */ bool AbandonTransaction(const uint256& hashTx); + bool AbandonTransaction(CWalletTx& tx) EXCLUSIVE_LOCKS_REQUIRED(cs_wallet); /** Mark a transaction as replaced by another transaction. */ bool MarkReplaced(const uint256& originalHash, const uint256& newHash); diff --git a/src/wallet/walletdb.cpp b/src/wallet/walletdb.cpp index 801c2ab97b8..c939ebb1fd4 100644 --- a/src/wallet/walletdb.cpp +++ b/src/wallet/walletdb.cpp @@ -1115,6 +1115,14 @@ static DBErrors LoadTxRecords(CWallet* pwallet, DatabaseBatch& batch, std::vecto }); result = std::max(result, order_pos_res.m_result); + // After loading all tx records, abandon any coinbase that is no longer in the active chain. + // This could happen during an external wallet load, or if the user replaced the chain data. + for (auto& [id, wtx] : pwallet->mapWallet) { + if (wtx.IsCoinBase() && wtx.isInactive()) { + pwallet->AbandonTransaction(wtx); + } + } + return result; }