diff --git a/src/utiltest.cpp b/src/utiltest.cpp index 017cd84cd..80ff9ef0d 100644 --- a/src/utiltest.cpp +++ b/src/utiltest.cpp @@ -46,6 +46,10 @@ CWalletTx GetValidReceive(ZCJoinSplit& params, inputs, outputs, 2*value, 0, false}; mtx.vjoinsplit.push_back(jsdesc); + // Shielded Output + OutputDescription od; + mtx.vShieldedOutput.push_back(od); + // Empty output script. uint32_t consensusBranchId = SPROUT_BRANCH_ID; CScript scriptCode; diff --git a/src/wallet/gtest/test_wallet.cpp b/src/wallet/gtest/test_wallet.cpp index d74a50fd4..7ba91e2f4 100644 --- a/src/wallet/gtest/test_wallet.cpp +++ b/src/wallet/gtest/test_wallet.cpp @@ -83,7 +83,17 @@ CWalletTx GetValidSpend(const libzcash::SproutSpendingKey& sk, return GetValidSpend(*params, sk, note, value); } -JSOutPoint CreateValidBlock(TestWallet& wallet, +std::vector SetSaplingNoteData(CWalletTx& wtx) { + mapSaplingNoteData_t saplingNoteData; + SaplingOutPoint saplingOutPoint = {wtx.GetHash(), 0}; + SaplingNoteData saplingNd; + saplingNoteData[saplingOutPoint] = saplingNd; + wtx.SetSaplingNoteData(saplingNoteData); + std::vector saplingNotes {saplingOutPoint}; + return saplingNotes; +} + +std::pair CreateValidBlock(TestWallet& wallet, const libzcash::SproutSpendingKey& sk, const CBlockIndex& index, CBlock& block, @@ -98,12 +108,27 @@ JSOutPoint CreateValidBlock(TestWallet& wallet, SproutNoteData nd {sk.address(), nullifier}; noteData[jsoutpt] = nd; wtx.SetSproutNoteData(noteData); + auto saplingNotes = SetSaplingNoteData(wtx); wallet.AddToWallet(wtx, true, NULL); block.vtx.push_back(wtx); wallet.IncrementNoteWitnesses(&index, &block, sproutTree, saplingTree); - return jsoutpt; + return std::make_pair(jsoutpt, saplingNotes[0]); +} + +std::pair GetWitnessesAndAnchors(TestWallet& wallet, + std::vector& sproutNotes, + std::vector& saplingNotes, + std::vector>& sproutWitnesses, + std::vector>& saplingWitnesses) { + sproutWitnesses.clear(); + saplingWitnesses.clear(); + uint256 sproutAnchor; + uint256 saplingAnchor; + wallet.GetSproutNoteWitnesses(sproutNotes, sproutWitnesses, sproutAnchor); + wallet.GetSaplingNoteWitnesses(saplingNotes, saplingWitnesses, saplingAnchor); + return std::make_pair(sproutAnchor, saplingAnchor); } TEST(wallet_tests, setup_datadir_location_run_as_first_test) { @@ -548,28 +573,34 @@ TEST(wallet_tests, cached_witnesses_empty_chain) { auto nullifier = note.nullifier(sk); auto nullifier2 = note2.nullifier(sk); - mapSproutNoteData_t noteData; + mapSproutNoteData_t sproutNoteData; JSOutPoint jsoutpt {wtx.GetHash(), 0, 0}; JSOutPoint jsoutpt2 {wtx.GetHash(), 0, 1}; SproutNoteData nd {sk.address(), nullifier}; SproutNoteData nd2 {sk.address(), nullifier2}; - noteData[jsoutpt] = nd; - noteData[jsoutpt2] = nd2; - wtx.SetSproutNoteData(noteData); + sproutNoteData[jsoutpt] = nd; + sproutNoteData[jsoutpt2] = nd2; + wtx.SetSproutNoteData(sproutNoteData); - std::vector notes {jsoutpt, jsoutpt2}; - std::vector> witnesses; - uint256 anchor; + std::vector sproutNotes {jsoutpt, jsoutpt2}; + std::vector saplingNotes = SetSaplingNoteData(wtx); - wallet.GetSproutNoteWitnesses(notes, witnesses, anchor); - EXPECT_FALSE((bool) witnesses[0]); - EXPECT_FALSE((bool) witnesses[1]); + std::vector> sproutWitnesses; + std::vector> saplingWitnesses; + + ::GetWitnessesAndAnchors(wallet, sproutNotes, saplingNotes, sproutWitnesses, saplingWitnesses); + + EXPECT_FALSE((bool) sproutWitnesses[0]); + EXPECT_FALSE((bool) sproutWitnesses[1]); + EXPECT_FALSE((bool) saplingWitnesses[0]); wallet.AddToWallet(wtx, true, NULL); - witnesses.clear(); - wallet.GetSproutNoteWitnesses(notes, witnesses, anchor); - EXPECT_FALSE((bool) witnesses[0]); - EXPECT_FALSE((bool) witnesses[1]); + + ::GetWitnessesAndAnchors(wallet, sproutNotes, saplingNotes, sproutWitnesses, saplingWitnesses); + + EXPECT_FALSE((bool) sproutWitnesses[0]); + EXPECT_FALSE((bool) sproutWitnesses[1]); + EXPECT_FALSE((bool) saplingWitnesses[0]); CBlock block; block.vtx.push_back(wtx); @@ -577,10 +608,12 @@ TEST(wallet_tests, cached_witnesses_empty_chain) { ZCIncrementalMerkleTree sproutTree; ZCSaplingIncrementalMerkleTree saplingTree; wallet.IncrementNoteWitnesses(&index, &block, sproutTree, saplingTree); - witnesses.clear(); - wallet.GetSproutNoteWitnesses(notes, witnesses, anchor); - EXPECT_TRUE((bool) witnesses[0]); - EXPECT_TRUE((bool) witnesses[1]); + + ::GetWitnessesAndAnchors(wallet, sproutNotes, saplingNotes, sproutWitnesses, saplingWitnesses); + + EXPECT_TRUE((bool) sproutWitnesses[0]); + EXPECT_TRUE((bool) sproutWitnesses[1]); + EXPECT_TRUE((bool) saplingWitnesses[0]); // Until #1302 is implemented, this should triggger an assertion EXPECT_DEATH(wallet.DecrementNoteWitnesses(&index), @@ -589,7 +622,7 @@ TEST(wallet_tests, cached_witnesses_empty_chain) { TEST(wallet_tests, cached_witnesses_chain_tip) { TestWallet wallet; - uint256 anchor1; + std::pair anchors1; CBlock block1; ZCIncrementalMerkleTree sproutTree; ZCSaplingIncrementalMerkleTree saplingTree; @@ -601,12 +634,16 @@ TEST(wallet_tests, cached_witnesses_chain_tip) { // First block (case tested in _empty_chain) CBlockIndex index1(block1); index1.nHeight = 1; - auto jsoutpt = CreateValidBlock(wallet, sk, index1, block1, sproutTree, saplingTree); + auto outpts = CreateValidBlock(wallet, sk, index1, block1, sproutTree, saplingTree); // Called to fetch anchor - std::vector notes {jsoutpt}; - std::vector> witnesses; - wallet.GetSproutNoteWitnesses(notes, witnesses, anchor1); + std::vector sproutNotes {outpts.first}; + std::vector saplingNotes {outpts.second}; + std::vector> sproutWitnesses; + std::vector> saplingWitnesses; + + anchors1 = GetWitnessesAndAnchors(wallet, sproutNotes, saplingNotes, sproutWitnesses, saplingWitnesses); + EXPECT_NE(anchors1.first, anchors1.second); } { @@ -615,19 +652,22 @@ TEST(wallet_tests, cached_witnesses_chain_tip) { auto note = GetNote(sk, wtx, 0, 1); auto nullifier = note.nullifier(sk); - mapSproutNoteData_t noteData; + mapSproutNoteData_t sproutNoteData; JSOutPoint jsoutpt {wtx.GetHash(), 0, 1}; SproutNoteData nd {sk.address(), nullifier}; - noteData[jsoutpt] = nd; - wtx.SetSproutNoteData(noteData); + sproutNoteData[jsoutpt] = nd; + wtx.SetSproutNoteData(sproutNoteData); + std::vector saplingNotes = SetSaplingNoteData(wtx); wallet.AddToWallet(wtx, true, NULL); - std::vector notes {jsoutpt}; - std::vector> witnesses; - uint256 anchor2; + std::vector sproutNotes {jsoutpt}; + std::vector> sproutWitnesses; + std::vector> saplingWitnesses; - wallet.GetSproutNoteWitnesses(notes, witnesses, anchor2); - EXPECT_FALSE((bool) witnesses[0]); + GetWitnessesAndAnchors(wallet, sproutNotes, saplingNotes, sproutWitnesses, saplingWitnesses); + + EXPECT_FALSE((bool) sproutWitnesses[0]); + EXPECT_FALSE((bool) saplingWitnesses[0]); // Second block CBlock block2; @@ -638,43 +678,52 @@ TEST(wallet_tests, cached_witnesses_chain_tip) { ZCIncrementalMerkleTree sproutTree2 {sproutTree}; ZCSaplingIncrementalMerkleTree saplingTree2 {saplingTree}; wallet.IncrementNoteWitnesses(&index2, &block2, sproutTree2, saplingTree2); - witnesses.clear(); - wallet.GetSproutNoteWitnesses(notes, witnesses, anchor2); - EXPECT_TRUE((bool) witnesses[0]); - EXPECT_NE(anchor1, anchor2); + + auto anchors2 = GetWitnessesAndAnchors(wallet, sproutNotes, saplingNotes, sproutWitnesses, saplingWitnesses); + EXPECT_NE(anchors2.first, anchors2.second); + + EXPECT_TRUE((bool) sproutWitnesses[0]); + EXPECT_TRUE((bool) saplingWitnesses[0]); + EXPECT_NE(anchors1.first, anchors2.first); + EXPECT_NE(anchors1.second, anchors2.second); // Decrementing should give us the previous anchor - uint256 anchor3; wallet.DecrementNoteWitnesses(&index2); - witnesses.clear(); - wallet.GetSproutNoteWitnesses(notes, witnesses, anchor3); - EXPECT_FALSE((bool) witnesses[0]); + auto anchors3 = GetWitnessesAndAnchors(wallet, sproutNotes, saplingNotes, sproutWitnesses, saplingWitnesses); + + EXPECT_FALSE((bool) sproutWitnesses[0]); + EXPECT_FALSE((bool) saplingWitnesses[0]); // Should not equal first anchor because none of these notes had witnesses - EXPECT_NE(anchor1, anchor3); + EXPECT_NE(anchors1.first, anchors3.first); + EXPECT_NE(anchors1.second, anchors3.second); // Re-incrementing with the same block should give the same result - uint256 anchor4; wallet.IncrementNoteWitnesses(&index2, &block2, sproutTree, saplingTree); - witnesses.clear(); - wallet.GetSproutNoteWitnesses(notes, witnesses, anchor4); - EXPECT_TRUE((bool) witnesses[0]); - EXPECT_EQ(anchor2, anchor4); + auto anchors4 = GetWitnessesAndAnchors(wallet, sproutNotes, saplingNotes, sproutWitnesses, saplingWitnesses); + EXPECT_NE(anchors4.first, anchors4.second); + + EXPECT_TRUE((bool) sproutWitnesses[0]); + EXPECT_TRUE((bool) saplingWitnesses[0]); + EXPECT_EQ(anchors2.first, anchors4.first); + EXPECT_EQ(anchors2.second, anchors4.second); // Incrementing with the same block again should not change the cache - uint256 anchor5; wallet.IncrementNoteWitnesses(&index2, &block2, sproutTree, saplingTree); - std::vector> witnesses5; - wallet.GetSproutNoteWitnesses(notes, witnesses5, anchor5); - EXPECT_EQ(witnesses, witnesses5); - EXPECT_EQ(anchor4, anchor5); + std::vector> sproutWitnesses5; + std::vector> saplingWitnesses5; + + auto anchors5 = GetWitnessesAndAnchors(wallet, sproutNotes, saplingNotes, sproutWitnesses5, saplingWitnesses5); + EXPECT_NE(anchors5.first, anchors5.second); + + EXPECT_EQ(sproutWitnesses, sproutWitnesses5); + EXPECT_EQ(saplingWitnesses, saplingWitnesses5); + EXPECT_EQ(anchors4.first, anchors5.first); + EXPECT_EQ(anchors4.second, anchors5.second); } } TEST(wallet_tests, CachedWitnessesDecrementFirst) { TestWallet wallet; - uint256 anchor2; - CBlock block2; - CBlockIndex index2(block2); ZCIncrementalMerkleTree sproutTree; ZCSaplingIncrementalMerkleTree saplingTree; @@ -689,18 +738,24 @@ TEST(wallet_tests, CachedWitnessesDecrementFirst) { CreateValidBlock(wallet, sk, index1, block1, sproutTree, saplingTree); } + std::pair anchors2; + CBlock block2; + CBlockIndex index2(block2); + { // Second block (case tested in _chain_tip) index2.nHeight = 2; - auto jsoutpt = CreateValidBlock(wallet, sk, index2, block2, sproutTree, saplingTree); + auto outpts = CreateValidBlock(wallet, sk, index2, block2, sproutTree, saplingTree); // Called to fetch anchor - std::vector notes {jsoutpt}; - std::vector> witnesses; - wallet.GetSproutNoteWitnesses(notes, witnesses, anchor2); + std::vector sproutNotes {outpts.first}; + std::vector saplingNotes {outpts.second}; + std::vector> sproutWitnesses; + std::vector> saplingWitnesses; + anchors2 = GetWitnessesAndAnchors(wallet, sproutNotes, saplingNotes, sproutWitnesses, saplingWitnesses); } - { +{ // Third transaction - never mined auto wtx = GetValidReceive(sk, 20, true); auto note = GetNote(sk, wtx, 0, 1); @@ -711,32 +766,39 @@ TEST(wallet_tests, CachedWitnessesDecrementFirst) { SproutNoteData nd {sk.address(), nullifier}; noteData[jsoutpt] = nd; wtx.SetSproutNoteData(noteData); + std::vector saplingNotes = SetSaplingNoteData(wtx); wallet.AddToWallet(wtx, true, NULL); - std::vector notes {jsoutpt}; - std::vector> witnesses; - uint256 anchor3; + std::vector sproutNotes {jsoutpt}; + std::vector> sproutWitnesses; + std::vector> saplingWitnesses; - wallet.GetSproutNoteWitnesses(notes, witnesses, anchor3); - EXPECT_FALSE((bool) witnesses[0]); + auto anchors3 = GetWitnessesAndAnchors(wallet, sproutNotes, saplingNotes, sproutWitnesses, saplingWitnesses); + + EXPECT_FALSE((bool) sproutWitnesses[0]); + EXPECT_FALSE((bool) saplingWitnesses[0]); // Decrementing (before the transaction has ever seen an increment) // should give us the previous anchor - uint256 anchor4; wallet.DecrementNoteWitnesses(&index2); - witnesses.clear(); - wallet.GetSproutNoteWitnesses(notes, witnesses, anchor4); - EXPECT_FALSE((bool) witnesses[0]); + + auto anchors4 = GetWitnessesAndAnchors(wallet, sproutNotes, saplingNotes, sproutWitnesses, saplingWitnesses); + + EXPECT_FALSE((bool) sproutWitnesses[0]); + EXPECT_FALSE((bool) saplingWitnesses[0]); // Should not equal second anchor because none of these notes had witnesses - EXPECT_NE(anchor2, anchor4); + EXPECT_NE(anchors2.first, anchors4.first); + EXPECT_NE(anchors2.second, anchors4.second); // Re-incrementing with the same block should give the same result - uint256 anchor5; wallet.IncrementNoteWitnesses(&index2, &block2, sproutTree, saplingTree); - witnesses.clear(); - wallet.GetSproutNoteWitnesses(notes, witnesses, anchor5); - EXPECT_FALSE((bool) witnesses[0]); - EXPECT_EQ(anchor3, anchor5); + + auto anchors5 = GetWitnessesAndAnchors(wallet, sproutNotes, saplingNotes, sproutWitnesses, saplingWitnesses); + + EXPECT_FALSE((bool) sproutWitnesses[0]); + EXPECT_FALSE((bool) saplingWitnesses[0]); + EXPECT_EQ(anchors3.first, anchors5.first); + EXPECT_EQ(anchors3.second, anchors5.second); } } @@ -744,13 +806,16 @@ TEST(wallet_tests, CachedWitnessesCleanIndex) { TestWallet wallet; std::vector blocks; std::vector indices; - std::vector notes; - std::vector anchors; + std::vector sproutNotes; + std::vector saplingNotes; + std::vector sproutAnchors; + std::vector saplingAnchors; ZCIncrementalMerkleTree sproutTree; ZCIncrementalMerkleTree sproutRiTree = sproutTree; ZCSaplingIncrementalMerkleTree saplingTree; ZCSaplingIncrementalMerkleTree saplingRiTree = saplingTree; - std::vector> witnesses; + std::vector> sproutWitnesses; + std::vector> saplingWitnesses; auto sk = libzcash::SproutSpendingKey::random(); wallet.AddSpendingKey(sk); @@ -761,18 +826,21 @@ TEST(wallet_tests, CachedWitnessesCleanIndex) { indices.resize(numBlocks); for (size_t i = 0; i < numBlocks; i++) { indices[i].nHeight = i; - auto old = sproutTree.root(); - auto jsoutpt = CreateValidBlock(wallet, sk, indices[i], blocks[i], sproutTree, saplingTree); - EXPECT_NE(old, sproutTree.root()); - notes.push_back(jsoutpt); + auto oldSproutRoot = sproutTree.root(); + auto oldSaplingRoot = saplingTree.root(); + auto outpts = CreateValidBlock(wallet, sk, indices[i], blocks[i], sproutTree, saplingTree); + EXPECT_NE(oldSproutRoot, sproutTree.root()); + EXPECT_NE(oldSaplingRoot, saplingTree.root()); + sproutNotes.push_back(outpts.first); + saplingNotes.push_back(outpts.second); - witnesses.clear(); - uint256 anchor; - wallet.GetSproutNoteWitnesses(notes, witnesses, anchor); + auto anchors = GetWitnessesAndAnchors(wallet, sproutNotes, saplingNotes, sproutWitnesses, saplingWitnesses); for (size_t j = 0; j <= i; j++) { - EXPECT_TRUE((bool) witnesses[j]); + EXPECT_TRUE((bool) sproutWitnesses[j]); + EXPECT_TRUE((bool) saplingWitnesses[j]); } - anchors.push_back(anchor); + sproutAnchors.push_back(anchors.first); + saplingAnchors.push_back(anchors.second); } // Now pretend we are reindexing: the chain is cleared, and each block is @@ -781,39 +849,41 @@ TEST(wallet_tests, CachedWitnessesCleanIndex) { ZCIncrementalMerkleTree sproutRiPrevTree {sproutRiTree}; ZCSaplingIncrementalMerkleTree saplingRiPrevTree {saplingRiTree}; wallet.IncrementNoteWitnesses(&(indices[i]), &(blocks[i]), sproutRiTree, saplingRiTree); - witnesses.clear(); - uint256 anchor; - wallet.GetSproutNoteWitnesses(notes, witnesses, anchor); + + auto anchors = GetWitnessesAndAnchors(wallet, sproutNotes, saplingNotes, sproutWitnesses, saplingWitnesses); for (size_t j = 0; j < numBlocks; j++) { - EXPECT_TRUE((bool) witnesses[j]); + EXPECT_TRUE((bool) sproutWitnesses[j]); + EXPECT_TRUE((bool) saplingWitnesses[j]); } // Should equal final anchor because witness cache unaffected - EXPECT_EQ(anchors.back(), anchor); + EXPECT_EQ(sproutAnchors.back(), anchors.first); + EXPECT_EQ(saplingAnchors.back(), anchors.second); if ((i == 5) || (i == 50)) { // Pretend a reorg happened that was recorded in the block files { wallet.DecrementNoteWitnesses(&(indices[i])); - witnesses.clear(); - uint256 anchor; - wallet.GetSproutNoteWitnesses(notes, witnesses, anchor); + + auto anchors = GetWitnessesAndAnchors(wallet, sproutNotes, saplingNotes, sproutWitnesses, saplingWitnesses); for (size_t j = 0; j < numBlocks; j++) { - EXPECT_TRUE((bool) witnesses[j]); + EXPECT_TRUE((bool) sproutWitnesses[j]); + EXPECT_TRUE((bool) saplingWitnesses[j]); } // Should equal final anchor because witness cache unaffected - EXPECT_EQ(anchors.back(), anchor); + EXPECT_EQ(sproutAnchors.back(), anchors.first); + EXPECT_EQ(saplingAnchors.back(), anchors.second); } { wallet.IncrementNoteWitnesses(&(indices[i]), &(blocks[i]), sproutRiPrevTree, saplingRiPrevTree); - witnesses.clear(); - uint256 anchor; - wallet.GetSproutNoteWitnesses(notes, witnesses, anchor); + auto anchors = GetWitnessesAndAnchors(wallet, sproutNotes, saplingNotes, sproutWitnesses, saplingWitnesses); for (size_t j = 0; j < numBlocks; j++) { - EXPECT_TRUE((bool) witnesses[j]); + EXPECT_TRUE((bool) sproutWitnesses[j]); + EXPECT_TRUE((bool) saplingWitnesses[j]); } // Should equal final anchor because witness cache unaffected - EXPECT_EQ(anchors.back(), anchor); + EXPECT_EQ(sproutAnchors.back(), anchors.first); + EXPECT_EQ(saplingAnchors.back(), anchors.second); } } } @@ -836,33 +906,44 @@ TEST(wallet_tests, ClearNoteWitnessCache) { SproutNoteData nd {sk.address(), nullifier}; noteData[jsoutpt] = nd; wtx.SetSproutNoteData(noteData); + auto saplingNotes = SetSaplingNoteData(wtx); // Pretend we mined the tx by adding a fake witness - ZCIncrementalMerkleTree tree; - wtx.mapSproutNoteData[jsoutpt].witnesses.push_front(tree.witness()); + ZCIncrementalMerkleTree sproutTree; + wtx.mapSproutNoteData[jsoutpt].witnesses.push_front(sproutTree.witness()); wtx.mapSproutNoteData[jsoutpt].witnessHeight = 1; wallet.nWitnessCacheSize = 1; + ZCSaplingIncrementalMerkleTree saplingTree; + wtx.mapSaplingNoteData[saplingNotes[0]].witnesses.push_front(saplingTree.witness()); + wtx.mapSaplingNoteData[saplingNotes[0]].witnessHeight = 1; + wallet.nWitnessCacheSize = 2; + wallet.AddToWallet(wtx, true, NULL); - std::vector notes {jsoutpt, jsoutpt2}; - std::vector> witnesses; - uint256 anchor2; + std::vector sproutNotes {jsoutpt, jsoutpt2}; + std::vector> sproutWitnesses; + std::vector> saplingWitnesses; // Before clearing, we should have a witness for one note - wallet.GetSproutNoteWitnesses(notes, witnesses, anchor2); - EXPECT_TRUE((bool) witnesses[0]); - EXPECT_FALSE((bool) witnesses[1]); + GetWitnessesAndAnchors(wallet, sproutNotes, saplingNotes, sproutWitnesses, saplingWitnesses); + EXPECT_TRUE((bool) sproutWitnesses[0]); + EXPECT_FALSE((bool) sproutWitnesses[1]); + EXPECT_TRUE((bool) saplingWitnesses[0]); + EXPECT_FALSE((bool) saplingWitnesses[1]); EXPECT_EQ(1, wallet.mapWallet[hash].mapSproutNoteData[jsoutpt].witnessHeight); - EXPECT_EQ(1, wallet.nWitnessCacheSize); + EXPECT_EQ(1, wallet.mapWallet[hash].mapSaplingNoteData[saplingNotes[0]].witnessHeight); + EXPECT_EQ(2, wallet.nWitnessCacheSize); // After clearing, we should not have a witness for either note wallet.ClearNoteWitnessCache(); - witnesses.clear(); - wallet.GetSproutNoteWitnesses(notes, witnesses, anchor2); - EXPECT_FALSE((bool) witnesses[0]); - EXPECT_FALSE((bool) witnesses[1]); + auto anchros2 = GetWitnessesAndAnchors(wallet, sproutNotes, saplingNotes, sproutWitnesses, saplingWitnesses); + EXPECT_FALSE((bool) sproutWitnesses[0]); + EXPECT_FALSE((bool) sproutWitnesses[1]); + EXPECT_FALSE((bool) saplingWitnesses[0]); + EXPECT_FALSE((bool) saplingWitnesses[1]); EXPECT_EQ(-1, wallet.mapWallet[hash].mapSproutNoteData[jsoutpt].witnessHeight); + EXPECT_EQ(-1, wallet.mapWallet[hash].mapSaplingNoteData[saplingNotes[0]].witnessHeight); EXPECT_EQ(0, wallet.nWitnessCacheSize); } diff --git a/src/wallet/wallet.cpp b/src/wallet/wallet.cpp index 761cf6a8b..efec41780 100644 --- a/src/wallet/wallet.cpp +++ b/src/wallet/wallet.cpp @@ -1496,6 +1496,33 @@ void CWallet::GetSproutNoteWitnesses(std::vector notes, } } +void CWallet::GetSaplingNoteWitnesses(std::vector notes, + std::vector>& witnesses, + uint256 &final_anchor) +{ + LOCK(cs_wallet); + witnesses.resize(notes.size()); + boost::optional rt; + int i = 0; + for (SaplingOutPoint note : notes) { + if (mapWallet.count(note.hash) && + mapWallet[note.hash].mapSaplingNoteData.count(note) && + mapWallet[note.hash].mapSaplingNoteData[note].witnesses.size() > 0) { + witnesses[i] = mapWallet[note.hash].mapSaplingNoteData[note].witnesses.front(); + if (!rt) { + rt = witnesses[i]->root(); + } else { + assert(*rt == witnesses[i]->root()); + } + } + i++; + } + // All returned witnesses have the same anchor + if (rt) { + final_anchor = *rt; + } +} + isminetype CWallet::IsMine(const CTxIn &txin) const { { @@ -1643,6 +1670,18 @@ void CWalletTx::SetSproutNoteData(mapSproutNoteData_t ¬eData) } } +void CWalletTx::SetSaplingNoteData(mapSaplingNoteData_t ¬eData) +{ + mapSaplingNoteData.clear(); + for (const std::pair nd : noteData) { + if (nd.first.n < vShieldedOutput.size()) { + mapSaplingNoteData[nd.first] = nd.second; + } else { + throw std::logic_error("CWalletTx::SetSaplingNoteData(): Invalid note"); + } + } +} + int64_t CWalletTx::GetTxTime() const { int64_t n = nTimeSmart; diff --git a/src/wallet/wallet.h b/src/wallet/wallet.h index 6ae83b5cb..43fdc5d77 100644 --- a/src/wallet/wallet.h +++ b/src/wallet/wallet.h @@ -514,6 +514,7 @@ public: } void SetSproutNoteData(mapSproutNoteData_t ¬eData); + void SetSaplingNoteData(mapSaplingNoteData_t ¬eData); //! filter decides which addresses will count towards the debit CAmount GetDebit(const isminefilter& filter) const; @@ -1078,6 +1079,10 @@ public: std::vector notes, std::vector>& witnesses, uint256 &final_anchor); + void GetSaplingNoteWitnesses( + std::vector notes, + std::vector>& witnesses, + uint256 &final_anchor); isminetype IsMine(const CTxIn& txin) const; CAmount GetDebit(const CTxIn& txin, const isminefilter& filter) const;