diff --git a/src/wallet/wallet.cpp b/src/wallet/wallet.cpp index d311031a9..7fb1dc3d5 100644 --- a/src/wallet/wallet.cpp +++ b/src/wallet/wallet.cpp @@ -783,6 +783,50 @@ void CopyPreviousWitnesses(NoteDataMap& noteDataMap, int indexHeight, int64_t nW } } +template +void AppendNoteCommitment(NoteDataMap& noteDataMap, int indexHeight, int64_t nWitnessCacheSize, const uint256& note_commitment) +{ + for (auto& item : noteDataMap) { + auto* nd = &(item.second); + if (nd->witnessHeight < indexHeight && nd->witnesses.size() > 0) { + // Check the validity of the cache + // See comment in CopyPreviousWitnesses about validity. + assert(nWitnessCacheSize >= nd->witnesses.size()); + nd->witnesses.front().append(note_commitment); + } + } +} + +template +void WitnessNoteIfMine(std::map& noteDataMap, int indexHeight, int64_t nWitnessCacheSize, const OutPoint& key, const Witness& witness) +{ + if (noteDataMap.count(key) && noteDataMap[key].witnessHeight < indexHeight) { + auto* nd = &(noteDataMap[key]); + if (nd->witnesses.size() > 0) { + // We think this can happen because we write out the + // witness cache state after every block increment or + // decrement, but the block index itself is written in + // batches. So if the node crashes in between these two + // operations, it is possible for IncrementNoteWitnesses + // to be called again on previously-cached blocks. This + // doesn't affect existing cached notes because of the + // NoteData::witnessHeight checks. See #1378 for details. + LogPrintf("Inconsistent witness cache state found for %s\n- Cache size: %d\n- Top (height %d): %s\n- New (height %d): %s\n", + key.ToString(), nd->witnesses.size(), + nd->witnessHeight, + nd->witnesses.front().root().GetHex(), + indexHeight, + witness.root().GetHex()); + nd->witnesses.clear(); + } + nd->witnesses.push_front(witness); + // Set height to one less than pindex so it gets incremented + nd->witnessHeight = indexHeight - 1; + // Check the validity of the cache + assert(nWitnessCacheSize >= nd->witnesses.size()); + } +} + void CWallet::IncrementNoteWitnesses(const CBlockIndex* pindex, const CBlock* pblockIn, ZCIncrementalMerkleTree& tree) @@ -814,47 +858,13 @@ void CWallet::IncrementNoteWitnesses(const CBlockIndex* pindex, // Increment existing witnesses for (std::pair& wtxItem : mapWallet) { - for (mapSproutNoteData_t::value_type& item : wtxItem.second.mapSproutNoteData) { - SproutNoteData* nd = &(item.second); - if (nd->witnessHeight < pindex->nHeight && - nd->witnesses.size() > 0) { - // Check the validity of the cache - // See earlier comment about validity. - assert(nWitnessCacheSize >= nd->witnesses.size()); - nd->witnesses.front().append(note_commitment); - } - } + ::AppendNoteCommitment(wtxItem.second.mapSproutNoteData, pindex->nHeight, nWitnessCacheSize, note_commitment); } // If this is our note, witness it if (txIsOurs) { JSOutPoint jsoutpt {hash, i, j}; - if (mapWallet[hash].mapSproutNoteData.count(jsoutpt) && - mapWallet[hash].mapSproutNoteData[jsoutpt].witnessHeight < pindex->nHeight) { - SproutNoteData* nd = &(mapWallet[hash].mapSproutNoteData[jsoutpt]); - if (nd->witnesses.size() > 0) { - // We think this can happen because we write out the - // witness cache state after every block increment or - // decrement, but the block index itself is written in - // batches. So if the node crashes in between these two - // operations, it is possible for IncrementNoteWitnesses - // to be called again on previously-cached blocks. This - // doesn't affect existing cached notes because of the - // SproutNoteData::witnessHeight checks. See #1378 for details. - LogPrintf("Inconsistent witness cache state found for %s\n- Cache size: %d\n- Top (height %d): %s\n- New (height %d): %s\n", - jsoutpt.ToString(), nd->witnesses.size(), - nd->witnessHeight, - nd->witnesses.front().root().GetHex(), - pindex->nHeight, - tree.witness().root().GetHex()); - nd->witnesses.clear(); - } - nd->witnesses.push_front(tree.witness()); - // Set height to one less than pindex so it gets incremented - nd->witnessHeight = pindex->nHeight - 1; - // Check the validity of the cache - assert(nWitnessCacheSize >= nd->witnesses.size()); - } + ::WitnessNoteIfMine(mapWallet[hash].mapSproutNoteData, pindex->nHeight, nWitnessCacheSize, jsoutpt, tree.witness()); } } }