diff --git a/src/init.cpp b/src/init.cpp index a25179612..8c7a227ba 100644 --- a/src/init.cpp +++ b/src/init.cpp @@ -532,6 +532,11 @@ void ThreadImport(std::vector vImportFiles) RenameThread("bitcoin-loadblk"); // -reindex if (fReindex) { +#ifdef ENABLE_WALLET + if (pwalletMain) { + pwalletMain->ClearNoteWitnessCache(); + } +#endif CImportingNow imp; int nFile = 0; while (true) { diff --git a/src/wallet/gtest/test_wallet.cpp b/src/wallet/gtest/test_wallet.cpp index f0bab2975..e72b8a2f6 100644 --- a/src/wallet/gtest/test_wallet.cpp +++ b/src/wallet/gtest/test_wallet.cpp @@ -639,6 +639,46 @@ TEST(wallet_tests, cached_witnesses_chain_tip) { } } +TEST(wallet_tests, ClearNoteWitnessCache) { + TestWallet wallet; + + auto sk = libzcash::SpendingKey::random(); + wallet.AddSpendingKey(sk); + + auto wtx = GetValidReceive(sk, 10, true); + auto note = GetNote(sk, wtx, 0, 0); + auto nullifier = note.nullifier(sk); + + mapNoteData_t noteData; + JSOutPoint jsoutpt {wtx.GetHash(), 0, 0}; + JSOutPoint jsoutpt2 {wtx.GetHash(), 0, 1}; + CNoteData nd {sk.address(), nullifier}; + noteData[jsoutpt] = nd; + wtx.SetNoteData(noteData); + + // Pretend we mined the tx by adding a fake witness + ZCIncrementalMerkleTree tree; + wtx.mapNoteData[jsoutpt].witnesses.push_front(tree.witness()); + + wallet.AddToWallet(wtx, true, NULL); + + std::vector notes {jsoutpt, jsoutpt2}; + std::vector> witnesses; + uint256 anchor2; + + // Before clearing, we should have a witness for one note + wallet.GetNoteWitnesses(notes, witnesses, anchor2); + EXPECT_TRUE((bool) witnesses[0]); + EXPECT_FALSE((bool) witnesses[1]); + + // After clearing, we should not have a witness for either note + wallet.ClearNoteWitnessCache(); + witnesses.clear(); + wallet.GetNoteWitnesses(notes, witnesses, anchor2); + EXPECT_FALSE((bool) witnesses[0]); + EXPECT_FALSE((bool) witnesses[1]); +} + TEST(wallet_tests, UpdatedNoteData) { TestWallet wallet; @@ -674,12 +714,12 @@ TEST(wallet_tests, UpdatedNoteData) { // The txs should initially be different EXPECT_NE(wtx.mapNoteData, wtx2.mapNoteData); - EXPECT_NE(wtx.mapNoteData[jsoutpt].witnesses, wtx2.mapNoteData[jsoutpt].witnesses); + EXPECT_EQ(1, wtx.mapNoteData[jsoutpt].witnesses.size()); // After updating, they should be the same - EXPECT_TRUE(wallet.UpdatedNoteData(wtx, wtx2)); + EXPECT_TRUE(wallet.UpdatedNoteData(wtx2, wtx)); EXPECT_EQ(wtx.mapNoteData, wtx2.mapNoteData); - EXPECT_EQ(wtx.mapNoteData[jsoutpt].witnesses, wtx2.mapNoteData[jsoutpt].witnesses); + EXPECT_EQ(1, wtx.mapNoteData[jsoutpt].witnesses.size()); // TODO: The new note should get witnessed (but maybe not here) (#1350) } diff --git a/src/wallet/wallet.cpp b/src/wallet/wallet.cpp index 862b38310..79978a270 100644 --- a/src/wallet/wallet.cpp +++ b/src/wallet/wallet.cpp @@ -625,6 +625,16 @@ void CWallet::AddToSpends(const uint256& wtxid) } } +void CWallet::ClearNoteWitnessCache() +{ + LOCK(cs_wallet); + for (std::pair& wtxItem : mapWallet) { + for (mapNoteData_t::value_type& item : wtxItem.second.mapNoteData) { + item.second.witnesses.clear(); + } + } +} + void CWallet::IncrementNoteWitnesses(const CBlockIndex* pindex, const CBlock* pblockIn, ZCIncrementalMerkleTree tree) diff --git a/src/wallet/wallet.h b/src/wallet/wallet.h index ccbc673d6..c3f1fd63f 100644 --- a/src/wallet/wallet.h +++ b/src/wallet/wallet.h @@ -598,6 +598,8 @@ public: */ int64_t nWitnessCacheSize; + void ClearNoteWitnessCache(); + protected: void IncrementNoteWitnesses(const CBlockIndex* pindex, const CBlock* pblock,