Skip to content

Commit 4cf9fa0

Browse files
committed
Merge bitcoin/bitcoin#24984: wallet: ignore chainStateFlushed notifications while attaching chain
2052e3a wallet: ignore chainStateFlushed notifications while attaching chain (Martin Zumsande) Pull request description: Fixes #24487 When a rescan is performed during `CWallet::AttachChain()` (e.g. when loading an old wallet) but this is interrupted by a shutdown signal, the wallet will currently stop the rescan, receive a `chainStateFlushed` signal, set the saved best block to the tip and shut down. At next startup, the rescan is not continued or repeated because of this. But some blocks have never been scanned by the wallet, which could lead to an incorrect balance. Fix this by ignoring `chainStateFlushed` notifications until the chain is attached. Since `CWallet::chainStateFlushed` is being manually called by `AttachChain()` anyway after finishing with the rescan, it is not a problem if intermediate notifications are ignored. Manual rescans started / aborted by the `rescanblockchain` / `abortrescan` RPCs are not affected by this. I didn't choose alternative ways of fixing this issue that would delay the validationinterface registration or change anything else about the handling of `blockConnected` signals for the reasons mentioned in [this existing comment](https://github.com/bitcoin/bitcoin/blob/master/src/wallet/wallet.cpp#L2937-L2944). ACKs for top commit: achow101: ACK 2052e3a ryanofsky: Code review ACK 2052e3a. This is a straightforward fix for the bug described in #24487 where a wallet could skip scanning blocks if is shut down in the middle of a sync and a chainStateFlushed notification was received during the sync. It would be nice to write a test for this but probably would be tricky to write. w0xlt: Code Review ACK bitcoin/bitcoin@2052e3a Tree-SHA512: a6186173d72b26bd4adbf2315e11af365004a723ea5565a0f7b868584dc47c321a6572eafaeb2420bd21eed1c7ad92b47e6218c5eb72313a3c6bee58364e2247
2 parents dabec99 + 2052e3a commit 4cf9fa0

File tree

2 files changed

+10
-0
lines changed

2 files changed

+10
-0
lines changed

src/wallet/wallet.cpp

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -523,6 +523,11 @@ bool CWallet::ChangeWalletPassphrase(const SecureString& strOldWalletPassphrase,
523523

524524
void CWallet::chainStateFlushed(const CBlockLocator& loc)
525525
{
526+
// Don't update the best block until the chain is attached so that in case of a shutdown,
527+
// the rescan will be restarted at next startup.
528+
if (m_attaching_chain) {
529+
return;
530+
}
526531
WalletBatch batch(GetDatabase());
527532
batch.WriteBestBlock(loc);
528533
}
@@ -2940,6 +2945,8 @@ bool CWallet::AttachChain(const std::shared_ptr<CWallet>& walletInstance, interf
29402945
// be pending on the validation-side until lock release. It's likely to have
29412946
// block processing duplicata (if rescan block range overlaps with notification one)
29422947
// but we guarantee at least than wallet state is correct after notifications delivery.
2948+
// However, chainStateFlushed notifications are ignored until the rescan is finished
2949+
// so that in case of a shutdown event, the rescan will be repeated at the next start.
29432950
// This is temporary until rescan and notifications delivery are unified under same
29442951
// interface.
29452952
walletInstance->m_chain_notifications_handler = walletInstance->chain().handleNotifications(walletInstance);
@@ -2968,6 +2975,7 @@ bool CWallet::AttachChain(const std::shared_ptr<CWallet>& walletInstance, interf
29682975

29692976
if (tip_height && *tip_height != rescan_height)
29702977
{
2978+
walletInstance->m_attaching_chain = true; //ignores chainStateFlushed notifications
29712979
if (chain.havePruned()) {
29722980
int block_height = *tip_height;
29732981
while (block_height > 0 && chain.haveBlockOnDisk(block_height - 1) && rescan_height != block_height) {
@@ -3007,6 +3015,7 @@ bool CWallet::AttachChain(const std::shared_ptr<CWallet>& walletInstance, interf
30073015
return false;
30083016
}
30093017
}
3018+
walletInstance->m_attaching_chain = false;
30103019
walletInstance->chainStateFlushed(chain.getTipLocator());
30113020
walletInstance->GetDatabase().IncrementUpdateCounter();
30123021
}

src/wallet/wallet.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -237,6 +237,7 @@ class CWallet final : public WalletStorage, public interfaces::Chain::Notificati
237237

238238
std::atomic<bool> fAbortRescan{false};
239239
std::atomic<bool> fScanningWallet{false}; // controlled by WalletRescanReserver
240+
std::atomic<bool> m_attaching_chain{false};
240241
std::atomic<int64_t> m_scanning_start{0};
241242
std::atomic<double> m_scanning_progress{0};
242243
friend class WalletRescanReserver;

0 commit comments

Comments
 (0)