Auto merge of #3258 - Eirik0:3056-anchor-test-cases, r=str4d

Add tests for sapling anchors

Closes #3253
This commit is contained in:
Homu
2018-06-19 09:28:20 -07:00
4 changed files with 159 additions and 126 deletions

View File

@@ -222,7 +222,8 @@ void CCoinsViewCache::AbstractPushAnchor(
} }
} }
void CCoinsViewCache::PushSproutAnchor(const ZCIncrementalMerkleTree &tree) { template<> void CCoinsViewCache::PushAnchor(const ZCIncrementalMerkleTree &tree)
{
AbstractPushAnchor<ZCIncrementalMerkleTree, CAnchorsSproutMap, CAnchorsSproutMap::iterator, CAnchorsSproutCacheEntry>( AbstractPushAnchor<ZCIncrementalMerkleTree, CAnchorsSproutMap, CAnchorsSproutMap::iterator, CAnchorsSproutCacheEntry>(
tree, tree,
SPROUT, SPROUT,
@@ -231,7 +232,8 @@ void CCoinsViewCache::PushSproutAnchor(const ZCIncrementalMerkleTree &tree) {
); );
} }
void CCoinsViewCache::PushSaplingAnchor(const ZCSaplingIncrementalMerkleTree &tree) { template<> void CCoinsViewCache::PushAnchor(const ZCSaplingIncrementalMerkleTree &tree)
{
AbstractPushAnchor<ZCSaplingIncrementalMerkleTree, CAnchorsSaplingMap, CAnchorsSaplingMap::iterator, CAnchorsSaplingCacheEntry>( AbstractPushAnchor<ZCSaplingIncrementalMerkleTree, CAnchorsSaplingMap, CAnchorsSaplingMap::iterator, CAnchorsSaplingCacheEntry>(
tree, tree,
SAPLING, SAPLING,

View File

@@ -478,13 +478,9 @@ public:
CNullifiersMap &mapSaplingNullifiers); CNullifiersMap &mapSaplingNullifiers);
// Adds the tree to mapSproutAnchors and sets the current commitment // Adds the tree to mapSproutAnchors (or mapSaplingAnchors based on the type of tree)
// root to this root. // and sets the current commitment root to this root.
void PushSproutAnchor(const ZCIncrementalMerkleTree &tree); template<typename Tree> void PushAnchor(const Tree &tree);
// Adds the tree to mapSaplingAnchors and sets the current commitment
// root to this root.
void PushSaplingAnchor(const ZCSaplingIncrementalMerkleTree &tree);
// Removes the current commitment root from mapAnchors and sets // Removes the current commitment root from mapAnchors and sets
// the new current root. // the new current root.

View File

@@ -2514,8 +2514,8 @@ bool ConnectBlock(const CBlock& block, CValidationState& state, CBlockIndex* pin
pos.nTxOffset += ::GetSerializeSize(tx, SER_DISK, CLIENT_VERSION); pos.nTxOffset += ::GetSerializeSize(tx, SER_DISK, CLIENT_VERSION);
} }
view.PushSproutAnchor(sprout_tree); view.PushAnchor(sprout_tree);
view.PushSaplingAnchor(sapling_tree); view.PushAnchor(sapling_tree);
if (!fJustCheck) { if (!fJustCheck) {
pindex->hashFinalSproutRoot = sprout_tree.root(); pindex->hashFinalSproutRoot = sprout_tree.root();
} }

View File

@@ -142,6 +142,20 @@ public:
mapNullifiers.clear(); mapNullifiers.clear();
} }
template<typename Tree, typename Map>
void BatchWriteAnchors(Map& mapAnchors, std::map<uint256, Tree>& cacheAnchors)
{
for (auto it = mapAnchors.begin(); it != mapAnchors.end(); ) {
if (it->second.entered) {
auto ret = cacheAnchors.insert(std::make_pair(it->first, Tree())).first;
ret->second = it->second.tree;
} else {
cacheAnchors.erase(it->first);
}
mapAnchors.erase(it++);
}
}
bool BatchWrite(CCoinsMap& mapCoins, bool BatchWrite(CCoinsMap& mapCoins,
const uint256& hashBlock, const uint256& hashBlock,
const uint256& hashSproutAnchor, const uint256& hashSproutAnchor,
@@ -159,28 +173,9 @@ public:
} }
mapCoins.erase(it++); mapCoins.erase(it++);
} }
for (CAnchorsSproutMap::iterator it = mapSproutAnchors.begin(); it != mapSproutAnchors.end(); ) {
if (it->second.entered) {
std::map<uint256, ZCIncrementalMerkleTree>::iterator ret =
mapSproutAnchors_.insert(std::make_pair(it->first, ZCIncrementalMerkleTree())).first;
ret->second = it->second.tree; BatchWriteAnchors<ZCIncrementalMerkleTree, CAnchorsSproutMap>(mapSproutAnchors, mapSproutAnchors_);
} else { BatchWriteAnchors<ZCSaplingIncrementalMerkleTree, CAnchorsSaplingMap>(mapSaplingAnchors, mapSaplingAnchors_);
mapSproutAnchors_.erase(it->first);
}
mapSproutAnchors.erase(it++);
}
for (CAnchorsSaplingMap::iterator it = mapSaplingAnchors.begin(); it != mapSaplingAnchors.end(); ) {
if (it->second.entered) {
std::map<uint256, ZCSaplingIncrementalMerkleTree>::iterator ret =
mapSaplingAnchors_.insert(std::make_pair(it->first, ZCSaplingIncrementalMerkleTree())).first;
ret->second = it->second.tree;
} else {
mapSaplingAnchors_.erase(it->first);
}
mapSaplingAnchors.erase(it++);
}
BatchWriteNullifiers(mapSproutNullifiers, mapSproutNullifiers_); BatchWriteNullifiers(mapSproutNullifiers, mapSproutNullifiers_);
BatchWriteNullifiers(mapSaplingNullifiers, mapSaplingNullifiers_); BatchWriteNullifiers(mapSaplingNullifiers, mapSaplingNullifiers_);
@@ -245,7 +240,7 @@ public:
} }
uint256 appendRandomCommitment(ZCIncrementalMerkleTree &tree) uint256 appendRandomSproutCommitment(ZCIncrementalMerkleTree &tree)
{ {
libzcash::SproutSpendingKey k = libzcash::SproutSpendingKey::random(); libzcash::SproutSpendingKey k = libzcash::SproutSpendingKey::random();
libzcash::SproutPaymentAddress addr = k.address(); libzcash::SproutPaymentAddress addr = k.address();
@@ -257,6 +252,10 @@ uint256 appendRandomCommitment(ZCIncrementalMerkleTree &tree)
return cm; return cm;
} }
template<typename Tree> bool GetAnchorAt(const CCoinsViewCacheTest &cache, const uint256 &rt, Tree &tree);
template<> bool GetAnchorAt(const CCoinsViewCacheTest &cache, const uint256 &rt, ZCIncrementalMerkleTree &tree) { return cache.GetSproutAnchorAt(rt, tree); }
template<> bool GetAnchorAt(const CCoinsViewCacheTest &cache, const uint256 &rt, ZCSaplingIncrementalMerkleTree &tree) { return cache.GetSaplingAnchorAt(rt, tree); }
BOOST_FIXTURE_TEST_SUITE(coins_tests, BasicTestingSetup) BOOST_FIXTURE_TEST_SUITE(coins_tests, BasicTestingSetup)
void checkNullifierCache(const CCoinsViewCacheTest &cache, const TxWithNullifiers &txWithNullifiers, bool shouldBeInCache) { void checkNullifierCache(const CCoinsViewCacheTest &cache, const TxWithNullifiers &txWithNullifiers, bool shouldBeInCache) {
@@ -358,7 +357,7 @@ BOOST_AUTO_TEST_CASE(nullifier_regression_test)
} }
} }
BOOST_AUTO_TEST_CASE(anchor_pop_regression_test) template<typename Tree> void anchorPopRegressionTestImpl(ShieldedType type)
{ {
// Correct behavior: // Correct behavior:
{ {
@@ -366,27 +365,26 @@ BOOST_AUTO_TEST_CASE(anchor_pop_regression_test)
CCoinsViewCacheTest cache1(&base); CCoinsViewCacheTest cache1(&base);
// Create dummy anchor/commitment // Create dummy anchor/commitment
ZCIncrementalMerkleTree tree; Tree tree;
uint256 cm = GetRandHash(); tree.append(GetRandHash());
tree.append(cm);
// Add the anchor // Add the anchor
cache1.PushSproutAnchor(tree); cache1.PushAnchor(tree);
cache1.Flush(); cache1.Flush();
// Remove the anchor // Remove the anchor
cache1.PopAnchor(ZCIncrementalMerkleTree::empty_root(), SPROUT); cache1.PopAnchor(Tree::empty_root(), type);
cache1.Flush(); cache1.Flush();
// Add the anchor back // Add the anchor back
cache1.PushSproutAnchor(tree); cache1.PushAnchor(tree);
cache1.Flush(); cache1.Flush();
// The base contains the anchor, of course! // The base contains the anchor, of course!
{ {
ZCIncrementalMerkleTree checktree; Tree checkTree;
BOOST_CHECK(cache1.GetSproutAnchorAt(tree.root(), checktree)); BOOST_CHECK(GetAnchorAt(cache1, tree.root(), checkTree));
BOOST_CHECK(checktree.root() == tree.root()); BOOST_CHECK(checkTree.root() == tree.root());
} }
} }
@@ -396,20 +394,19 @@ BOOST_AUTO_TEST_CASE(anchor_pop_regression_test)
CCoinsViewCacheTest cache1(&base); CCoinsViewCacheTest cache1(&base);
// Create dummy anchor/commitment // Create dummy anchor/commitment
ZCIncrementalMerkleTree tree; Tree tree;
uint256 cm = GetRandHash(); tree.append(GetRandHash());
tree.append(cm);
// Add the anchor and flush to disk // Add the anchor and flush to disk
cache1.PushSproutAnchor(tree); cache1.PushAnchor(tree);
cache1.Flush(); cache1.Flush();
// Remove the anchor, but don't flush yet! // Remove the anchor, but don't flush yet!
cache1.PopAnchor(ZCIncrementalMerkleTree::empty_root(), SPROUT); cache1.PopAnchor(Tree::empty_root(), type);
{ {
CCoinsViewCacheTest cache2(&cache1); // Build cache on top CCoinsViewCacheTest cache2(&cache1); // Build cache on top
cache2.PushSproutAnchor(tree); // Put the same anchor back! cache2.PushAnchor(tree); // Put the same anchor back!
cache2.Flush(); // Flush to cache1 cache2.Flush(); // Flush to cache1
} }
@@ -417,8 +414,8 @@ BOOST_AUTO_TEST_CASE(anchor_pop_regression_test)
// tree is there, but it didn't bring down the correct // tree is there, but it didn't bring down the correct
// treestate... // treestate...
{ {
ZCIncrementalMerkleTree checktree; Tree checktree;
BOOST_CHECK(cache1.GetSproutAnchorAt(tree.root(), checktree)); BOOST_CHECK(GetAnchorAt(cache1, tree.root(), checktree));
BOOST_CHECK(checktree.root() == tree.root()); // Oh, shucks. BOOST_CHECK(checktree.root() == tree.root()); // Oh, shucks.
} }
@@ -426,14 +423,24 @@ BOOST_AUTO_TEST_CASE(anchor_pop_regression_test)
// permanent. // permanent.
cache1.Flush(); cache1.Flush();
{ {
ZCIncrementalMerkleTree checktree; Tree checktree;
BOOST_CHECK(cache1.GetSproutAnchorAt(tree.root(), checktree)); BOOST_CHECK(GetAnchorAt(cache1, tree.root(), checktree));
BOOST_CHECK(checktree.root() == tree.root()); // Oh, shucks. BOOST_CHECK(checktree.root() == tree.root()); // Oh, shucks.
} }
} }
} }
BOOST_AUTO_TEST_CASE(anchor_regression_test) BOOST_AUTO_TEST_CASE(anchor_pop_regression_test)
{
BOOST_TEST_CONTEXT("Sprout") {
anchorPopRegressionTestImpl<ZCIncrementalMerkleTree>(SPROUT);
}
BOOST_TEST_CONTEXT("Sapling") {
anchorPopRegressionTestImpl<ZCSaplingIncrementalMerkleTree>(SAPLING);
}
}
template<typename Tree> void anchorRegressionTestImpl(ShieldedType type)
{ {
// Correct behavior: // Correct behavior:
{ {
@@ -441,15 +448,15 @@ BOOST_AUTO_TEST_CASE(anchor_regression_test)
CCoinsViewCacheTest cache1(&base); CCoinsViewCacheTest cache1(&base);
// Insert anchor into base. // Insert anchor into base.
ZCIncrementalMerkleTree tree; Tree tree;
uint256 cm = GetRandHash(); tree.append(GetRandHash());
tree.append(cm);
cache1.PushSproutAnchor(tree); cache1.PushAnchor(tree);
cache1.Flush(); cache1.Flush();
cache1.PopAnchor(ZCIncrementalMerkleTree::empty_root(), SPROUT); cache1.PopAnchor(Tree::empty_root(), type);
BOOST_CHECK(cache1.GetBestAnchor(SPROUT) == ZCIncrementalMerkleTree::empty_root()); BOOST_CHECK(cache1.GetBestAnchor(type) == Tree::empty_root());
BOOST_CHECK(!cache1.GetSproutAnchorAt(tree.root(), tree)); BOOST_CHECK(!GetAnchorAt(cache1, tree.root(), tree));
} }
// Also correct behavior: // Also correct behavior:
@@ -458,16 +465,15 @@ BOOST_AUTO_TEST_CASE(anchor_regression_test)
CCoinsViewCacheTest cache1(&base); CCoinsViewCacheTest cache1(&base);
// Insert anchor into base. // Insert anchor into base.
ZCIncrementalMerkleTree tree; Tree tree;
uint256 cm = GetRandHash(); tree.append(GetRandHash());
tree.append(cm); cache1.PushAnchor(tree);
cache1.PushSproutAnchor(tree);
cache1.Flush(); cache1.Flush();
cache1.PopAnchor(ZCIncrementalMerkleTree::empty_root(), SPROUT); cache1.PopAnchor(Tree::empty_root(), type);
cache1.Flush(); cache1.Flush();
BOOST_CHECK(cache1.GetBestAnchor(SPROUT) == ZCIncrementalMerkleTree::empty_root()); BOOST_CHECK(cache1.GetBestAnchor(type) == Tree::empty_root());
BOOST_CHECK(!cache1.GetSproutAnchorAt(tree.root(), tree)); BOOST_CHECK(!GetAnchorAt(cache1, tree.root(), tree));
} }
// Works because we bring the anchor in from parent cache. // Works because we bring the anchor in from parent cache.
@@ -476,22 +482,21 @@ BOOST_AUTO_TEST_CASE(anchor_regression_test)
CCoinsViewCacheTest cache1(&base); CCoinsViewCacheTest cache1(&base);
// Insert anchor into base. // Insert anchor into base.
ZCIncrementalMerkleTree tree; Tree tree;
uint256 cm = GetRandHash(); tree.append(GetRandHash());
tree.append(cm); cache1.PushAnchor(tree);
cache1.PushSproutAnchor(tree);
cache1.Flush(); cache1.Flush();
{ {
// Pop anchor. // Pop anchor.
CCoinsViewCacheTest cache2(&cache1); CCoinsViewCacheTest cache2(&cache1);
BOOST_CHECK(cache2.GetSproutAnchorAt(tree.root(), tree)); BOOST_CHECK(GetAnchorAt(cache2, tree.root(), tree));
cache2.PopAnchor(ZCIncrementalMerkleTree::empty_root(), SPROUT); cache2.PopAnchor(Tree::empty_root(), type);
cache2.Flush(); cache2.Flush();
} }
BOOST_CHECK(cache1.GetBestAnchor(SPROUT) == ZCIncrementalMerkleTree::empty_root()); BOOST_CHECK(cache1.GetBestAnchor(type) == Tree::empty_root());
BOOST_CHECK(!cache1.GetSproutAnchorAt(tree.root(), tree)); BOOST_CHECK(!GetAnchorAt(cache1, tree.root(), tree));
} }
// Was broken: // Was broken:
@@ -500,21 +505,30 @@ BOOST_AUTO_TEST_CASE(anchor_regression_test)
CCoinsViewCacheTest cache1(&base); CCoinsViewCacheTest cache1(&base);
// Insert anchor into base. // Insert anchor into base.
ZCIncrementalMerkleTree tree; Tree tree;
uint256 cm = GetRandHash(); tree.append(GetRandHash());
tree.append(cm); cache1.PushAnchor(tree);
cache1.PushSproutAnchor(tree);
cache1.Flush(); cache1.Flush();
{ {
// Pop anchor. // Pop anchor.
CCoinsViewCacheTest cache2(&cache1); CCoinsViewCacheTest cache2(&cache1);
cache2.PopAnchor(ZCIncrementalMerkleTree::empty_root(), SPROUT); cache2.PopAnchor(Tree::empty_root(), type);
cache2.Flush(); cache2.Flush();
} }
BOOST_CHECK(cache1.GetBestAnchor(SPROUT) == ZCIncrementalMerkleTree::empty_root()); BOOST_CHECK(cache1.GetBestAnchor(type) == Tree::empty_root());
BOOST_CHECK(!cache1.GetSproutAnchorAt(tree.root(), tree)); BOOST_CHECK(!GetAnchorAt(cache1, tree.root(), tree));
}
}
BOOST_AUTO_TEST_CASE(anchor_regression_test)
{
BOOST_TEST_CONTEXT("Sprout") {
anchorRegressionTestImpl<ZCIncrementalMerkleTree>(SPROUT);
}
BOOST_TEST_CONTEXT("Sapling") {
anchorRegressionTestImpl<ZCSaplingIncrementalMerkleTree>(SAPLING);
} }
} }
@@ -541,29 +555,29 @@ BOOST_AUTO_TEST_CASE(nullifiers_test)
checkNullifierCache(cache3, txWithNullifiers, false); checkNullifierCache(cache3, txWithNullifiers, false);
} }
BOOST_AUTO_TEST_CASE(anchors_flush_test) template<typename Tree> void anchorsFlushImpl(ShieldedType type)
{ {
CCoinsViewTest base; CCoinsViewTest base;
uint256 newrt; uint256 newrt;
{ {
CCoinsViewCacheTest cache(&base); CCoinsViewCacheTest cache(&base);
ZCIncrementalMerkleTree tree; Tree tree;
BOOST_CHECK(cache.GetSproutAnchorAt(cache.GetBestAnchor(SPROUT), tree)); BOOST_CHECK(GetAnchorAt(cache, cache.GetBestAnchor(type), tree));
appendRandomCommitment(tree); tree.append(GetRandHash());
newrt = tree.root(); newrt = tree.root();
cache.PushSproutAnchor(tree); cache.PushAnchor(tree);
cache.Flush(); cache.Flush();
} }
{ {
CCoinsViewCacheTest cache(&base); CCoinsViewCacheTest cache(&base);
ZCIncrementalMerkleTree tree; Tree tree;
BOOST_CHECK(cache.GetSproutAnchorAt(cache.GetBestAnchor(SPROUT), tree)); BOOST_CHECK(GetAnchorAt(cache, cache.GetBestAnchor(type), tree));
// Get the cached entry. // Get the cached entry.
BOOST_CHECK(cache.GetSproutAnchorAt(cache.GetBestAnchor(SPROUT), tree)); BOOST_CHECK(GetAnchorAt(cache, cache.GetBestAnchor(type), tree));
uint256 check_rt = tree.root(); uint256 check_rt = tree.root();
@@ -571,8 +585,19 @@ BOOST_AUTO_TEST_CASE(anchors_flush_test)
} }
} }
BOOST_AUTO_TEST_CASE(anchors_flush_test)
{
BOOST_TEST_CONTEXT("Sprout") {
anchorsFlushImpl<ZCIncrementalMerkleTree>(SPROUT);
}
BOOST_TEST_CONTEXT("Sapling") {
anchorsFlushImpl<ZCSaplingIncrementalMerkleTree>(SAPLING);
}
}
BOOST_AUTO_TEST_CASE(chained_joinsplits) BOOST_AUTO_TEST_CASE(chained_joinsplits)
{ {
// TODO update this or add a similar test when the SaplingNote class exist
CCoinsViewTest base; CCoinsViewTest base;
CCoinsViewCacheTest cache(&base); CCoinsViewCacheTest cache(&base);
@@ -580,8 +605,8 @@ BOOST_AUTO_TEST_CASE(chained_joinsplits)
JSDescription js1; JSDescription js1;
js1.anchor = tree.root(); js1.anchor = tree.root();
js1.commitments[0] = appendRandomCommitment(tree); js1.commitments[0] = appendRandomSproutCommitment(tree);
js1.commitments[1] = appendRandomCommitment(tree); js1.commitments[1] = appendRandomSproutCommitment(tree);
// Although it's not possible given our assumptions, if // Although it's not possible given our assumptions, if
// two joinsplits create the same treestate twice, we should // two joinsplits create the same treestate twice, we should
@@ -597,11 +622,11 @@ BOOST_AUTO_TEST_CASE(chained_joinsplits)
js2.anchor = tree.root(); js2.anchor = tree.root();
js3.anchor = tree.root(); js3.anchor = tree.root();
js2.commitments[0] = appendRandomCommitment(tree); js2.commitments[0] = appendRandomSproutCommitment(tree);
js2.commitments[1] = appendRandomCommitment(tree); js2.commitments[1] = appendRandomSproutCommitment(tree);
js3.commitments[0] = appendRandomCommitment(tree); js3.commitments[0] = appendRandomSproutCommitment(tree);
js3.commitments[1] = appendRandomCommitment(tree); js3.commitments[1] = appendRandomSproutCommitment(tree);
{ {
CMutableTransaction mtx; CMutableTransaction mtx;
@@ -648,7 +673,7 @@ BOOST_AUTO_TEST_CASE(chained_joinsplits)
} }
} }
BOOST_AUTO_TEST_CASE(anchors_test) template<typename Tree> void anchorsTestImpl(ShieldedType type)
{ {
// TODO: These tests should be more methodical. // TODO: These tests should be more methodical.
// Or, integrate with Bitcoin's tests later. // Or, integrate with Bitcoin's tests later.
@@ -656,68 +681,78 @@ BOOST_AUTO_TEST_CASE(anchors_test)
CCoinsViewTest base; CCoinsViewTest base;
CCoinsViewCacheTest cache(&base); CCoinsViewCacheTest cache(&base);
BOOST_CHECK(cache.GetBestAnchor(SPROUT) == ZCIncrementalMerkleTree::empty_root()); BOOST_CHECK(cache.GetBestAnchor(type) == Tree::empty_root());
{ {
ZCIncrementalMerkleTree tree; Tree tree;
BOOST_CHECK(cache.GetSproutAnchorAt(cache.GetBestAnchor(SPROUT), tree)); BOOST_CHECK(GetAnchorAt(cache, cache.GetBestAnchor(type), tree));
BOOST_CHECK(cache.GetBestAnchor(SPROUT) == tree.root()); BOOST_CHECK(cache.GetBestAnchor(type) == tree.root());
appendRandomCommitment(tree); tree.append(GetRandHash());
appendRandomCommitment(tree); tree.append(GetRandHash());
appendRandomCommitment(tree); tree.append(GetRandHash());
appendRandomCommitment(tree); tree.append(GetRandHash());
appendRandomCommitment(tree); tree.append(GetRandHash());
appendRandomCommitment(tree); tree.append(GetRandHash());
appendRandomCommitment(tree); tree.append(GetRandHash());
ZCIncrementalMerkleTree save_tree_for_later; Tree save_tree_for_later;
save_tree_for_later = tree; save_tree_for_later = tree;
uint256 newrt = tree.root(); uint256 newrt = tree.root();
uint256 newrt2; uint256 newrt2;
cache.PushSproutAnchor(tree); cache.PushAnchor(tree);
BOOST_CHECK(cache.GetBestAnchor(SPROUT) == newrt); BOOST_CHECK(cache.GetBestAnchor(type) == newrt);
{ {
ZCIncrementalMerkleTree confirm_same; Tree confirm_same;
BOOST_CHECK(cache.GetSproutAnchorAt(cache.GetBestAnchor(SPROUT), confirm_same)); BOOST_CHECK(GetAnchorAt(cache, cache.GetBestAnchor(type), confirm_same));
BOOST_CHECK(confirm_same.root() == newrt); BOOST_CHECK(confirm_same.root() == newrt);
} }
appendRandomCommitment(tree); tree.append(GetRandHash());
appendRandomCommitment(tree); tree.append(GetRandHash());
newrt2 = tree.root(); newrt2 = tree.root();
cache.PushSproutAnchor(tree); cache.PushAnchor(tree);
BOOST_CHECK(cache.GetBestAnchor(SPROUT) == newrt2); BOOST_CHECK(cache.GetBestAnchor(type) == newrt2);
ZCIncrementalMerkleTree test_tree; Tree test_tree;
BOOST_CHECK(cache.GetSproutAnchorAt(cache.GetBestAnchor(SPROUT), test_tree)); BOOST_CHECK(GetAnchorAt(cache, cache.GetBestAnchor(type), test_tree));
BOOST_CHECK(tree.root() == test_tree.root()); BOOST_CHECK(tree.root() == test_tree.root());
{ {
ZCIncrementalMerkleTree test_tree2; Tree test_tree2;
cache.GetSproutAnchorAt(newrt, test_tree2); GetAnchorAt(cache, newrt, test_tree2);
BOOST_CHECK(test_tree2.root() == newrt); BOOST_CHECK(test_tree2.root() == newrt);
} }
{ {
cache.PopAnchor(newrt, SPROUT); cache.PopAnchor(newrt, type);
ZCIncrementalMerkleTree obtain_tree; Tree obtain_tree;
assert(!cache.GetSproutAnchorAt(newrt2, obtain_tree)); // should have been popped off assert(!GetAnchorAt(cache, newrt2, obtain_tree)); // should have been popped off
assert(cache.GetSproutAnchorAt(newrt, obtain_tree)); assert(GetAnchorAt(cache, newrt, obtain_tree));
assert(obtain_tree.root() == newrt); assert(obtain_tree.root() == newrt);
} }
} }
} }
BOOST_AUTO_TEST_CASE(anchors_test)
{
BOOST_TEST_CONTEXT("Sprout") {
anchorsTestImpl<ZCIncrementalMerkleTree>(SPROUT);
}
BOOST_TEST_CONTEXT("Sapling") {
anchorsTestImpl<ZCSaplingIncrementalMerkleTree>(SAPLING);
}
}
static const unsigned int NUM_SIMULATION_ITERATIONS = 40000; static const unsigned int NUM_SIMULATION_ITERATIONS = 40000;
// This is a large randomized insert/remove simulation test on a variable-size // This is a large randomized insert/remove simulation test on a variable-size