A note found with only an incoming viewing key (z_importviewingkey) never
gets a nullifier: UpdateSaplingNullifierNoteMapWithTx needs the full
viewing key. VerifyAndSetInitialWitness built a witness for such a note
anyway and then dereferenced *item.second.nullifier, aborting the daemon
on the boost::optional assertion.
Importing a viewing key that had received funds therefore crashed the
node during the import's rescan, and again at every start and on every
block, since witnesses are rebuilt then too. Reproduced on regtest
(z_importviewingkey -> ScanForWalletTransactions -> BuildWitnessCache ->
VerifyAndSetInitialWitness).
Skip notes that have no nullifier and no full viewing key: they cannot
be spent and need no witness. Only call SaplingWitnessMinimumHeight when
the nullifier is set, and log the corrupt-data case where a note with a
full viewing key gets no witness, which used to abort as well. A note
whose spending key is imported later is picked up on the next rebuild.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>