wallet: Remove lock on cs_main from CWallet::ChainTip

We must not lock on cs_main during wallet synchronization, to avoid
locking side channels between the wallet and the networking stack.
However, the wallet code that is called on every block to update tree
states etc. was also checking whether it should run Sprout-to-Sapling
migrations, and that was being gated on IBD completion (to avoid stale
transactions being generated). IsInitialBlockDownload locks on cs_main
before IBD completion :)

We now rely on the fact that IBD does not end until the chain tip is
within nMaxTipAge of the current time, so we can check that as a proxy.
We were already applying a similar check to avoid hibernation-related
issues; these are now merged.
This commit is contained in:
Jack Grigg 2022-09-30 23:22:57 +00:00
parent d41916d26b
commit 444d75fbea
1 changed files with 5 additions and 2 deletions

View File

@ -1443,8 +1443,11 @@ void CWallet::ChainTip(const CBlockIndex *pindex,
ChainTipAdded(pindex, pblock, added.value(), true);
// Prevent migration transactions from being created when node is syncing after launch,
// and also when node wakes up from suspension/hibernation and incoming blocks are old.
if (!IsInitialBlockDownload(consensus) &&
pblock->GetBlockTime() > GetTime() - 3 * 60 * 60)
// We do not call IsInitialBlockDownload() because during IBD that locks on cs_main,
// which we must not do during wallet sync. However, IBD does not end until the chain
// tip is within nMaxTipAge of the current time, so we use that as a proxy.
const int64_t hibernationOld = 3 * 60 * 60;
if (pblock->GetBlockTime() > GetTime() - std::min(nMaxTipAge, hibernationOld))
{
RunSaplingMigration(pindex->nHeight);
}