From 18322f074ccc00361f43932267062d02249a5fb5 Mon Sep 17 00:00:00 2001 From: Sean Bowe Date: Fri, 27 Apr 2018 16:00:21 -0600 Subject: [PATCH] Introduce support for GetBestAnchor(SAPLING). --- src/coins.cpp | 35 ++++++++++----- src/coins.h | 10 +++-- src/gtest/test_mempool.cpp | 3 +- src/gtest/test_validation.cpp | 3 +- src/main.cpp | 12 ++--- src/rpcblockchain.cpp | 2 +- src/test/coins_tests.cpp | 45 ++++++++++++------- src/txdb.cpp | 22 +++++++-- src/txdb.h | 3 +- .../asyncrpcoperation_mergetoaddress.cpp | 2 +- src/wallet/asyncrpcoperation_sendmany.cpp | 2 +- .../asyncrpcoperation_shieldcoinbase.cpp | 2 +- 12 files changed, 97 insertions(+), 44 deletions(-) diff --git a/src/coins.cpp b/src/coins.cpp index ebcc5e1a8..29bf04dc8 100644 --- a/src/coins.cpp +++ b/src/coins.cpp @@ -47,10 +47,11 @@ bool CCoinsView::GetNullifier(const uint256 &nullifier, ShieldedType type) const bool CCoinsView::GetCoins(const uint256 &txid, CCoins &coins) const { return false; } bool CCoinsView::HaveCoins(const uint256 &txid) const { return false; } uint256 CCoinsView::GetBestBlock() const { return uint256(); } -uint256 CCoinsView::GetBestAnchor() const { return uint256(); }; +uint256 CCoinsView::GetBestAnchor(ShieldedType type) const { return uint256(); }; bool CCoinsView::BatchWrite(CCoinsMap &mapCoins, const uint256 &hashBlock, const uint256 &hashSproutAnchor, + const uint256 &hashSaplingAnchor, CAnchorsSproutMap &mapSproutAnchors, CNullifiersMap &mapSproutNullifiers, CNullifiersMap &mapSaplingNullifiers) { return false; } @@ -64,14 +65,15 @@ bool CCoinsViewBacked::GetNullifier(const uint256 &nullifier, ShieldedType type) bool CCoinsViewBacked::GetCoins(const uint256 &txid, CCoins &coins) const { return base->GetCoins(txid, coins); } bool CCoinsViewBacked::HaveCoins(const uint256 &txid) const { return base->HaveCoins(txid); } uint256 CCoinsViewBacked::GetBestBlock() const { return base->GetBestBlock(); } -uint256 CCoinsViewBacked::GetBestAnchor() const { return base->GetBestAnchor(); } +uint256 CCoinsViewBacked::GetBestAnchor(ShieldedType type) const { return base->GetBestAnchor(type); } void CCoinsViewBacked::SetBackend(CCoinsView &viewIn) { base = &viewIn; } bool CCoinsViewBacked::BatchWrite(CCoinsMap &mapCoins, const uint256 &hashBlock, const uint256 &hashSproutAnchor, + const uint256 &hashSaplingAnchor, CAnchorsSproutMap &mapSproutAnchors, CNullifiersMap &mapSproutNullifiers, - CNullifiersMap &mapSaplingNullifiers) { return base->BatchWrite(mapCoins, hashBlock, hashSproutAnchor, mapSproutAnchors, mapSproutNullifiers, mapSaplingNullifiers); } + CNullifiersMap &mapSaplingNullifiers) { return base->BatchWrite(mapCoins, hashBlock, hashSproutAnchor, hashSaplingAnchor, mapSproutAnchors, mapSproutNullifiers, mapSaplingNullifiers); } bool CCoinsViewBacked::GetStats(CCoinsStats &stats) const { return base->GetStats(stats); } CCoinsKeyHasher::CCoinsKeyHasher() : salt(GetRandHash()) {} @@ -161,7 +163,7 @@ bool CCoinsViewCache::GetNullifier(const uint256 &nullifier, ShieldedType type) void CCoinsViewCache::PushSproutAnchor(const ZCIncrementalMerkleTree &tree) { uint256 newrt = tree.root(); - auto currentRoot = GetBestAnchor(); + auto currentRoot = GetBestAnchor(SPROUT); // We don't want to overwrite an anchor we already have. // This occurs when a block doesn't modify mapSproutAnchors at all, @@ -186,7 +188,7 @@ void CCoinsViewCache::PushSproutAnchor(const ZCIncrementalMerkleTree &tree) { } void CCoinsViewCache::PopAnchor(const uint256 &newrt) { - auto currentRoot = GetBestAnchor(); + auto currentRoot = GetBestAnchor(SPROUT); // Blocks might not change the commitment tree, in which // case restoring the "old" anchor during a reorg must @@ -280,10 +282,21 @@ uint256 CCoinsViewCache::GetBestBlock() const { } -uint256 CCoinsViewCache::GetBestAnchor() const { - if (hashSproutAnchor.IsNull()) - hashSproutAnchor = base->GetBestAnchor(); - return hashSproutAnchor; +uint256 CCoinsViewCache::GetBestAnchor(ShieldedType type) const { + switch (type) { + case SPROUT: + if (hashSproutAnchor.IsNull()) + hashSproutAnchor = base->GetBestAnchor(type); + return hashSproutAnchor; + break; + case SAPLING: + if (hashSaplingAnchor.IsNull()) + hashSaplingAnchor = base->GetBestAnchor(type); + return hashSaplingAnchor; + break; + default: + throw std::runtime_error("Unknown shielded type " + type); + } } void CCoinsViewCache::SetBestBlock(const uint256 &hashBlockIn) { @@ -315,6 +328,7 @@ void BatchWriteNullifiers(CNullifiersMap &mapNullifiers, CNullifiersMap &cacheNu bool CCoinsViewCache::BatchWrite(CCoinsMap &mapCoins, const uint256 &hashBlockIn, const uint256 &hashSproutAnchorIn, + const uint256 &hashSaplingAnchorIn, CAnchorsSproutMap &mapSproutAnchors, CNullifiersMap &mapSproutNullifiers, CNullifiersMap &mapSaplingNullifiers) { @@ -383,12 +397,13 @@ bool CCoinsViewCache::BatchWrite(CCoinsMap &mapCoins, ::BatchWriteNullifiers(mapSaplingNullifiers, cacheSaplingNullifiers); hashSproutAnchor = hashSproutAnchorIn; + hashSaplingAnchor = hashSaplingAnchorIn; hashBlock = hashBlockIn; return true; } bool CCoinsViewCache::Flush() { - bool fOk = base->BatchWrite(cacheCoins, hashBlock, hashSproutAnchor, cacheSproutAnchors, cacheSproutNullifiers, cacheSaplingNullifiers); + bool fOk = base->BatchWrite(cacheCoins, hashBlock, hashSproutAnchor, hashSaplingAnchor, cacheSproutAnchors, cacheSproutNullifiers, cacheSaplingNullifiers); cacheCoins.clear(); cacheSproutAnchors.clear(); cacheSproutNullifiers.clear(); diff --git a/src/coins.h b/src/coins.h index 99273786e..055320056 100644 --- a/src/coins.h +++ b/src/coins.h @@ -343,13 +343,14 @@ public: virtual uint256 GetBestBlock() const; //! Get the current "tip" or the latest anchored tree root in the chain - virtual uint256 GetBestAnchor() const; + virtual uint256 GetBestAnchor(ShieldedType type) const; //! Do a bulk modification (multiple CCoins changes + BestBlock change). //! The passed mapCoins can be modified. virtual bool BatchWrite(CCoinsMap &mapCoins, const uint256 &hashBlock, const uint256 &hashSproutAnchor, + const uint256 &hashSaplingAnchor, CAnchorsSproutMap &mapSproutAnchors, CNullifiersMap &mapSproutNullifiers, CNullifiersMap &mapSaplingNullifiers); @@ -375,11 +376,12 @@ public: bool GetCoins(const uint256 &txid, CCoins &coins) const; bool HaveCoins(const uint256 &txid) const; uint256 GetBestBlock() const; - uint256 GetBestAnchor() const; + uint256 GetBestAnchor(ShieldedType type) const; void SetBackend(CCoinsView &viewIn); bool BatchWrite(CCoinsMap &mapCoins, const uint256 &hashBlock, const uint256 &hashSproutAnchor, + const uint256 &hashSaplingAnchor, CAnchorsSproutMap &mapSproutAnchors, CNullifiersMap &mapSproutNullifiers, CNullifiersMap &mapSaplingNullifiers); @@ -424,6 +426,7 @@ protected: mutable uint256 hashBlock; mutable CCoinsMap cacheCoins; mutable uint256 hashSproutAnchor; + mutable uint256 hashSaplingAnchor; mutable CAnchorsSproutMap cacheSproutAnchors; mutable CNullifiersMap cacheSproutNullifiers; mutable CNullifiersMap cacheSaplingNullifiers; @@ -441,11 +444,12 @@ public: bool GetCoins(const uint256 &txid, CCoins &coins) const; bool HaveCoins(const uint256 &txid) const; uint256 GetBestBlock() const; - uint256 GetBestAnchor() const; + uint256 GetBestAnchor(ShieldedType type) const; void SetBestBlock(const uint256 &hashBlock); bool BatchWrite(CCoinsMap &mapCoins, const uint256 &hashBlock, const uint256 &hashSproutAnchor, + const uint256 &hashSaplingAnchor, CAnchorsSproutMap &mapSproutAnchors, CNullifiersMap &mapSproutNullifiers, CNullifiersMap &mapSaplingNullifiers); diff --git a/src/gtest/test_mempool.cpp b/src/gtest/test_mempool.cpp index 41aa5c832..1d5999de2 100644 --- a/src/gtest/test_mempool.cpp +++ b/src/gtest/test_mempool.cpp @@ -47,7 +47,7 @@ public: return a; } - uint256 GetBestAnchor() const { + uint256 GetBestAnchor(ShieldedType type) const { uint256 a; return a; } @@ -55,6 +55,7 @@ public: bool BatchWrite(CCoinsMap &mapCoins, const uint256 &hashBlock, const uint256 &hashSproutAnchor, + const uint256 &hashSaplingAnchor, CAnchorsSproutMap &mapSproutAnchors, CNullifiersMap &mapSproutNullifiers, CNullifiersMap &mapSaplingNullifiers) { diff --git a/src/gtest/test_validation.cpp b/src/gtest/test_validation.cpp index 564767040..b76c3e77d 100644 --- a/src/gtest/test_validation.cpp +++ b/src/gtest/test_validation.cpp @@ -42,7 +42,7 @@ public: return a; } - uint256 GetBestAnchor() const { + uint256 GetBestAnchor(ShieldedType type) const { uint256 a; return a; } @@ -50,6 +50,7 @@ public: bool BatchWrite(CCoinsMap &mapCoins, const uint256 &hashBlock, const uint256 &hashSproutAnchor, + const uint256 &hashSaplingAnchor, CAnchorsSproutMap &mapSproutAnchors, CNullifiersMap &mapSproutNullifiers, CNullifiersMap saplingNullifiersMap) { diff --git a/src/main.cpp b/src/main.cpp index 96f9b66aa..991e34110 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -2330,7 +2330,7 @@ bool ConnectBlock(const CBlock& block, CValidationState& state, CBlockIndex* pin // Construct the incremental merkle tree at the current // block position, - auto old_tree_root = view.GetBestAnchor(); + auto old_tree_root = view.GetBestAnchor(SPROUT); // saving the top anchor in the block index as we go. if (!fJustCheck) { pindex->hashSproutAnchor = old_tree_root; @@ -2658,7 +2658,7 @@ bool static DisconnectTip(CValidationState &state, bool fBare = false) { if (!ReadBlockFromDisk(block, pindexDelete)) return AbortNode(state, "Failed to read block"); // Apply the block atomically to the chain state. - uint256 anchorBeforeDisconnect = pcoinsTip->GetBestAnchor(); + uint256 anchorBeforeDisconnect = pcoinsTip->GetBestAnchor(SPROUT); int64_t nStart = GetTimeMicros(); { CCoinsViewCache view(pcoinsTip); @@ -2667,7 +2667,7 @@ bool static DisconnectTip(CValidationState &state, bool fBare = false) { assert(view.Flush()); } LogPrint("bench", "- Disconnect block: %.2fms\n", (GetTimeMicros() - nStart) * 0.001); - uint256 anchorAfterDisconnect = pcoinsTip->GetBestAnchor(); + uint256 anchorAfterDisconnect = pcoinsTip->GetBestAnchor(SPROUT); // Write the chain state to disk, if necessary. if (!FlushStateToDisk(state, FLUSH_STATE_IF_NEEDED)) return false; @@ -2692,7 +2692,7 @@ bool static DisconnectTip(CValidationState &state, bool fBare = false) { UpdateTip(pindexDelete->pprev); // Get the current commitment tree ZCIncrementalMerkleTree newTree; - assert(pcoinsTip->GetSproutAnchorAt(pcoinsTip->GetBestAnchor(), newTree)); + assert(pcoinsTip->GetSproutAnchorAt(pcoinsTip->GetBestAnchor(SPROUT), newTree)); // Let wallets know transactions went from 1-confirmed to // 0-confirmed or conflicted: BOOST_FOREACH(const CTransaction &tx, block.vtx) { @@ -2726,7 +2726,7 @@ bool static ConnectTip(CValidationState &state, CBlockIndex *pindexNew, CBlock * } // Get the current commitment tree ZCIncrementalMerkleTree oldTree; - assert(pcoinsTip->GetSproutAnchorAt(pcoinsTip->GetBestAnchor(), oldTree)); + assert(pcoinsTip->GetSproutAnchorAt(pcoinsTip->GetBestAnchor(SPROUT), oldTree)); // Apply the block atomically to the chain state. int64_t nTime2 = GetTimeMicros(); nTimeReadFromDisk += nTime2 - nTime1; int64_t nTime3; @@ -3942,7 +3942,7 @@ bool static LoadBlockIndexDB() return true; chainActive.SetTip(it->second); // Set hashSproutAnchorEnd for the end of best chain - it->second->hashSproutAnchorEnd = pcoinsTip->GetBestAnchor(); + it->second->hashSproutAnchorEnd = pcoinsTip->GetBestAnchor(SPROUT); PruneBlockIndexCandidates(); diff --git a/src/rpcblockchain.cpp b/src/rpcblockchain.cpp index c4d33691d..1633c8b72 100644 --- a/src/rpcblockchain.cpp +++ b/src/rpcblockchain.cpp @@ -770,7 +770,7 @@ UniValue getblockchaininfo(const UniValue& params, bool fHelp) obj.push_back(Pair("pruned", fPruneMode)); ZCIncrementalMerkleTree tree; - pcoinsTip->GetSproutAnchorAt(pcoinsTip->GetBestAnchor(), tree); + pcoinsTip->GetSproutAnchorAt(pcoinsTip->GetBestAnchor(SPROUT), tree); obj.push_back(Pair("commitments", static_cast(tree.size()))); CBlockIndex* tip = chainActive.Tip(); diff --git a/src/test/coins_tests.cpp b/src/test/coins_tests.cpp index 9382edeb2..daae2e009 100644 --- a/src/test/coins_tests.cpp +++ b/src/test/coins_tests.cpp @@ -26,6 +26,7 @@ class CCoinsViewTest : public CCoinsView { uint256 hashBestBlock_; uint256 hashBestSproutAnchor_; + uint256 hashBestSaplingAnchor_; std::map map_; std::map mapSproutAnchors_; std::map mapSproutNullifiers_; @@ -34,6 +35,7 @@ class CCoinsViewTest : public CCoinsView public: CCoinsViewTest() { hashBestSproutAnchor_ = ZCIncrementalMerkleTree::empty_root(); + hashBestSaplingAnchor_ = ZCSaplingIncrementalMerkleTree::empty_root(); } bool GetSproutAnchorAt(const uint256& rt, ZCIncrementalMerkleTree &tree) const { @@ -75,7 +77,18 @@ public: } } - uint256 GetBestAnchor() const { return hashBestSproutAnchor_; } + uint256 GetBestAnchor(ShieldedType type) const { + switch (type) { + case SPROUT: + return hashBestSproutAnchor_; + break; + case SAPLING: + return hashBestSaplingAnchor_; + break; + default: + throw std::runtime_error("Unknown shielded type " + type); + } + } bool GetCoins(const uint256& txid, CCoins& coins) const { @@ -115,6 +128,7 @@ public: bool BatchWrite(CCoinsMap& mapCoins, const uint256& hashBlock, const uint256& hashSproutAnchor, + const uint256& hashSaplingAnchor, CAnchorsSproutMap& mapSproutAnchors, CNullifiersMap& mapSproutNullifiers, CNullifiersMap& mapSaplingNullifiers) @@ -146,6 +160,7 @@ public: mapSproutAnchors.clear(); hashBestBlock_ = hashBlock; hashBestSproutAnchor_ = hashSproutAnchor; + hashBestSaplingAnchor_ = hashSaplingAnchor; return true; } @@ -402,7 +417,7 @@ BOOST_AUTO_TEST_CASE(anchor_regression_test) cache1.Flush(); cache1.PopAnchor(ZCIncrementalMerkleTree::empty_root()); - BOOST_CHECK(cache1.GetBestAnchor() == ZCIncrementalMerkleTree::empty_root()); + BOOST_CHECK(cache1.GetBestAnchor(SPROUT) == ZCIncrementalMerkleTree::empty_root()); BOOST_CHECK(!cache1.GetSproutAnchorAt(tree.root(), tree)); } @@ -420,7 +435,7 @@ BOOST_AUTO_TEST_CASE(anchor_regression_test) cache1.PopAnchor(ZCIncrementalMerkleTree::empty_root()); cache1.Flush(); - BOOST_CHECK(cache1.GetBestAnchor() == ZCIncrementalMerkleTree::empty_root()); + BOOST_CHECK(cache1.GetBestAnchor(SPROUT) == ZCIncrementalMerkleTree::empty_root()); BOOST_CHECK(!cache1.GetSproutAnchorAt(tree.root(), tree)); } @@ -444,7 +459,7 @@ BOOST_AUTO_TEST_CASE(anchor_regression_test) cache2.Flush(); } - BOOST_CHECK(cache1.GetBestAnchor() == ZCIncrementalMerkleTree::empty_root()); + BOOST_CHECK(cache1.GetBestAnchor(SPROUT) == ZCIncrementalMerkleTree::empty_root()); BOOST_CHECK(!cache1.GetSproutAnchorAt(tree.root(), tree)); } @@ -467,7 +482,7 @@ BOOST_AUTO_TEST_CASE(anchor_regression_test) cache2.Flush(); } - BOOST_CHECK(cache1.GetBestAnchor() == ZCIncrementalMerkleTree::empty_root()); + BOOST_CHECK(cache1.GetBestAnchor(SPROUT) == ZCIncrementalMerkleTree::empty_root()); BOOST_CHECK(!cache1.GetSproutAnchorAt(tree.root(), tree)); } } @@ -502,7 +517,7 @@ BOOST_AUTO_TEST_CASE(anchors_flush_test) { CCoinsViewCacheTest cache(&base); ZCIncrementalMerkleTree tree; - BOOST_CHECK(cache.GetSproutAnchorAt(cache.GetBestAnchor(), tree)); + BOOST_CHECK(cache.GetSproutAnchorAt(cache.GetBestAnchor(SPROUT), tree)); appendRandomCommitment(tree); newrt = tree.root(); @@ -514,10 +529,10 @@ BOOST_AUTO_TEST_CASE(anchors_flush_test) { CCoinsViewCacheTest cache(&base); ZCIncrementalMerkleTree tree; - BOOST_CHECK(cache.GetSproutAnchorAt(cache.GetBestAnchor(), tree)); + BOOST_CHECK(cache.GetSproutAnchorAt(cache.GetBestAnchor(SPROUT), tree)); // Get the cached entry. - BOOST_CHECK(cache.GetSproutAnchorAt(cache.GetBestAnchor(), tree)); + BOOST_CHECK(cache.GetSproutAnchorAt(cache.GetBestAnchor(SPROUT), tree)); uint256 check_rt = tree.root(); @@ -610,13 +625,13 @@ BOOST_AUTO_TEST_CASE(anchors_test) CCoinsViewTest base; CCoinsViewCacheTest cache(&base); - BOOST_CHECK(cache.GetBestAnchor() == ZCIncrementalMerkleTree::empty_root()); + BOOST_CHECK(cache.GetBestAnchor(SPROUT) == ZCIncrementalMerkleTree::empty_root()); { ZCIncrementalMerkleTree tree; - BOOST_CHECK(cache.GetSproutAnchorAt(cache.GetBestAnchor(), tree)); - BOOST_CHECK(cache.GetBestAnchor() == tree.root()); + BOOST_CHECK(cache.GetSproutAnchorAt(cache.GetBestAnchor(SPROUT), tree)); + BOOST_CHECK(cache.GetBestAnchor(SPROUT) == tree.root()); appendRandomCommitment(tree); appendRandomCommitment(tree); appendRandomCommitment(tree); @@ -632,11 +647,11 @@ BOOST_AUTO_TEST_CASE(anchors_test) uint256 newrt2; cache.PushSproutAnchor(tree); - BOOST_CHECK(cache.GetBestAnchor() == newrt); + BOOST_CHECK(cache.GetBestAnchor(SPROUT) == newrt); { ZCIncrementalMerkleTree confirm_same; - BOOST_CHECK(cache.GetSproutAnchorAt(cache.GetBestAnchor(), confirm_same)); + BOOST_CHECK(cache.GetSproutAnchorAt(cache.GetBestAnchor(SPROUT), confirm_same)); BOOST_CHECK(confirm_same.root() == newrt); } @@ -647,10 +662,10 @@ BOOST_AUTO_TEST_CASE(anchors_test) newrt2 = tree.root(); cache.PushSproutAnchor(tree); - BOOST_CHECK(cache.GetBestAnchor() == newrt2); + BOOST_CHECK(cache.GetBestAnchor(SPROUT) == newrt2); ZCIncrementalMerkleTree test_tree; - BOOST_CHECK(cache.GetSproutAnchorAt(cache.GetBestAnchor(), test_tree)); + BOOST_CHECK(cache.GetSproutAnchorAt(cache.GetBestAnchor(SPROUT), test_tree)); BOOST_CHECK(tree.root() == test_tree.root()); diff --git a/src/txdb.cpp b/src/txdb.cpp index 8d07d59ba..59ebbdf94 100644 --- a/src/txdb.cpp +++ b/src/txdb.cpp @@ -27,6 +27,7 @@ static const char DB_BLOCK_INDEX = 'b'; static const char DB_BEST_BLOCK = 'B'; static const char DB_BEST_SPROUT_ANCHOR = 'a'; +static const char DB_BEST_SAPLING_ANCHOR = 'x'; static const char DB_FLAG = 'F'; static const char DB_REINDEX_FLAG = 'R'; static const char DB_LAST_BLOCK = 'l'; @@ -83,10 +84,22 @@ uint256 CCoinsViewDB::GetBestBlock() const { return hashBestChain; } -uint256 CCoinsViewDB::GetBestAnchor() const { +uint256 CCoinsViewDB::GetBestAnchor(ShieldedType type) const { uint256 hashBestAnchor; - if (!db.Read(DB_BEST_SPROUT_ANCHOR, hashBestAnchor)) - return ZCIncrementalMerkleTree::empty_root(); + + switch (type) { + case SPROUT: + if (!db.Read(DB_BEST_SPROUT_ANCHOR, hashBestAnchor)) + return ZCIncrementalMerkleTree::empty_root(); + break; + case SAPLING: + if (!db.Read(DB_BEST_SAPLING_ANCHOR, hashBestAnchor)) + return ZCSaplingIncrementalMerkleTree::empty_root(); + break; + default: + throw runtime_error("Unknown shielded type " + type); + } + return hashBestAnchor; } @@ -108,6 +121,7 @@ void BatchWriteNullifiers(CDBBatch& batch, CNullifiersMap& mapToUse, const char& bool CCoinsViewDB::BatchWrite(CCoinsMap &mapCoins, const uint256 &hashBlock, const uint256 &hashSproutAnchor, + const uint256 &hashSaplingAnchor, CAnchorsSproutMap &mapSproutAnchors, CNullifiersMap &mapSproutNullifiers, CNullifiersMap &mapSaplingNullifiers) { @@ -147,6 +161,8 @@ bool CCoinsViewDB::BatchWrite(CCoinsMap &mapCoins, batch.Write(DB_BEST_BLOCK, hashBlock); if (!hashSproutAnchor.IsNull()) batch.Write(DB_BEST_SPROUT_ANCHOR, hashSproutAnchor); + if (!hashSaplingAnchor.IsNull()) + batch.Write(DB_BEST_SAPLING_ANCHOR, hashSaplingAnchor); LogPrint("coindb", "Committing %u changed transactions (out of %u) to coin database...\n", (unsigned int)changed, (unsigned int)count); return db.WriteBatch(batch); diff --git a/src/txdb.h b/src/txdb.h index 3290be28c..d97f18303 100644 --- a/src/txdb.h +++ b/src/txdb.h @@ -40,10 +40,11 @@ public: bool GetCoins(const uint256 &txid, CCoins &coins) const; bool HaveCoins(const uint256 &txid) const; uint256 GetBestBlock() const; - uint256 GetBestAnchor() const; + uint256 GetBestAnchor(ShieldedType type) const; bool BatchWrite(CCoinsMap &mapCoins, const uint256 &hashBlock, const uint256 &hashSproutAnchor, + const uint256 &hashSaplingAnchor, CAnchorsSproutMap &mapSproutAnchors, CNullifiersMap &mapSproutNullifiers, CNullifiersMap &mapSaplingNullifiers); diff --git a/src/wallet/asyncrpcoperation_mergetoaddress.cpp b/src/wallet/asyncrpcoperation_mergetoaddress.cpp index abc9d1338..916ad862b 100644 --- a/src/wallet/asyncrpcoperation_mergetoaddress.cpp +++ b/src/wallet/asyncrpcoperation_mergetoaddress.cpp @@ -693,7 +693,7 @@ UniValue AsyncRPCOperation_mergetoaddress::perform_joinsplit(MergeToAddressJSInf uint256 anchor; { LOCK(cs_main); - anchor = pcoinsTip->GetBestAnchor(); // As there are no inputs, ask the wallet for the best anchor + anchor = pcoinsTip->GetBestAnchor(SPROUT); // As there are no inputs, ask the wallet for the best anchor } return perform_joinsplit(info, witnesses, anchor); } diff --git a/src/wallet/asyncrpcoperation_sendmany.cpp b/src/wallet/asyncrpcoperation_sendmany.cpp index dae33d3f3..ba9f566f6 100644 --- a/src/wallet/asyncrpcoperation_sendmany.cpp +++ b/src/wallet/asyncrpcoperation_sendmany.cpp @@ -914,7 +914,7 @@ UniValue AsyncRPCOperation_sendmany::perform_joinsplit(AsyncJoinSplitInfo & info uint256 anchor; { LOCK(cs_main); - anchor = pcoinsTip->GetBestAnchor(); // As there are no inputs, ask the wallet for the best anchor + anchor = pcoinsTip->GetBestAnchor(SPROUT); // As there are no inputs, ask the wallet for the best anchor } return perform_joinsplit(info, witnesses, anchor); } diff --git a/src/wallet/asyncrpcoperation_shieldcoinbase.cpp b/src/wallet/asyncrpcoperation_shieldcoinbase.cpp index dcadc6a78..45d9321dd 100644 --- a/src/wallet/asyncrpcoperation_shieldcoinbase.cpp +++ b/src/wallet/asyncrpcoperation_shieldcoinbase.cpp @@ -314,7 +314,7 @@ UniValue AsyncRPCOperation_shieldcoinbase::perform_joinsplit(ShieldCoinbaseJSInf { LOCK(cs_main); consensusBranchId = CurrentEpochBranchId(chainActive.Height() + 1, Params().GetConsensus()); - anchor = pcoinsTip->GetBestAnchor(); + anchor = pcoinsTip->GetBestAnchor(SPROUT); }