Introduce support for GetBestAnchor(SAPLING).
This commit is contained in:
parent
2bd59e1473
commit
18322f074c
|
@ -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 {
|
||||
uint256 CCoinsViewCache::GetBestAnchor(ShieldedType type) const {
|
||||
switch (type) {
|
||||
case SPROUT:
|
||||
if (hashSproutAnchor.IsNull())
|
||||
hashSproutAnchor = base->GetBestAnchor();
|
||||
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();
|
||||
|
|
10
src/coins.h
10
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);
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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) {
|
||||
|
|
12
src/main.cpp
12
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();
|
||||
|
||||
|
|
|
@ -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<uint64_t>(tree.size())));
|
||||
|
||||
CBlockIndex* tip = chainActive.Tip();
|
||||
|
|
|
@ -26,6 +26,7 @@ class CCoinsViewTest : public CCoinsView
|
|||
{
|
||||
uint256 hashBestBlock_;
|
||||
uint256 hashBestSproutAnchor_;
|
||||
uint256 hashBestSaplingAnchor_;
|
||||
std::map<uint256, CCoins> map_;
|
||||
std::map<uint256, ZCIncrementalMerkleTree> mapSproutAnchors_;
|
||||
std::map<uint256, bool> 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());
|
||||
|
||||
|
|
18
src/txdb.cpp
18
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;
|
||||
|
||||
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);
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
||||
|
|
Loading…
Reference in New Issue