wallet/init: decrypt every wallet note into the plaintext cache at startup
The plaintext cache is in memory only, so a restart empties it. Without a warm-up, the first balance call after a restart decrypts the whole wallet under LOCK2(cs_main, cs_wallet): ~6s for a 12k-note wallet. That is the observed failure: restart, the GUI connects, and the node looks stuck. CWallet::WarmSaplingNoteCache decrypts every note whose plaintext isn't cached, spent ones included, because z_listreceivedbyaddress (ignoreSpent=false) is called once per address by the GUI's history scan. init runs it at the end of the wallet block, just before SetBroadcastTransactions. At that point RPC is still in warmup (it shows "Decrypting wallet notes...") and the wallet notification thread, whose startup witness rebuild can hold cs_wallet for a long time, has not started yet. It takes cs_wallet only. -notecachewarmup=0 (debug help) skips it, which leaves the lazy fill in GetFilteredNotes to do the work. Unlike GetFilteredNotes, the warm-up never asserts. A note that doesn't decrypt under its ivk, or names an output its tx lacks, is counted in the summary line and listed under -debug=zrpcunsafe. A corrupt note therefore can't stop the node from starting, or from serving the key-export RPCs allowed during warmup; GetFilteredNotes still asserts on it, as before. Tests: - WarmUpFillsEveryNote: spent, locked, unconfirmed and stale-block notes included; walks afterwards decrypt nothing. - WarmUpSkipsBadNotes: undecryptable and out-of-range notes are skipped without aborting. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
@@ -1497,6 +1497,9 @@ public:
|
||||
/** Notes FillSaplingNoteCache has decrypted since startup (FindMySaplingNotes' fills not counted).
|
||||
* Guarded by cs_wallet. */
|
||||
uint64_t nSaplingNoteCacheFills = 0;
|
||||
/** Decrypts every wallet note whose plaintext isn't cached yet (all of them after wallet.dat is loaded).
|
||||
* Never asserts: a note that won't decrypt is logged and left unfilled. Run at startup. */
|
||||
void WarmSaplingNoteCache();
|
||||
|
||||
void GetFilteredNotes(std::vector<SaplingNoteEntry>& saplingEntries,
|
||||
std::string address,
|
||||
|
||||
Reference in New Issue
Block a user