diff --git a/src/wallet/wallet.cpp b/src/wallet/wallet.cpp index e596767d7..109ad2237 100644 --- a/src/wallet/wallet.cpp +++ b/src/wallet/wallet.cpp @@ -1266,8 +1266,15 @@ int CWallet::VerifyAndSetInitialWitness(const CBlockIndex* pindex, bool witnessO uint256 blockRoot; uint256 witnessRoot; - if (!nd->nullifier) + if (!nd->nullifier) { ::ClearSingleNoteWitnessCache(nd); + // A note found with only an incoming viewing key (z_importviewingkey) never gets a + // nullifier (UpdateSaplingNullifierNoteMapWithTx needs the full viewing key) and can't be + // spent, so it needs no witness. Building one re-read its block on every call and then + // aborted on *item.second.nullifier below. + if (!HaveSaplingFullViewingKey(nd->ivk)) + continue; + } if (!nd->witnesses.empty() && nd->witnessHeight > 0) { @@ -1358,7 +1365,10 @@ int CWallet::VerifyAndSetInitialWitness(const CBlockIndex* pindex, bool witnessO } nd->witnessHeight = pblockindex->GetHeight(); UpdateSaplingNullifierNoteMapWithTx(wtxItem.second); - nMinimumHeight = SaplingWitnessMinimumHeight(*item.second.nullifier, nd->witnessHeight, nMinimumHeight); + if (item.second.nullifier) + nMinimumHeight = SaplingWitnessMinimumHeight(*item.second.nullifier, nd->witnessHeight, nMinimumHeight); + else + LogPrintf("%s: no witness found for note %s:%d in its block; it stays unspendable until a rescan\n", __func__, wtxHash.ToString(), op.n); } } }