From c7c6c6afffc8b15819855106892e9e5c973c4ca0 Mon Sep 17 00:00:00 2001 From: j-berman Date: Mon, 27 May 2024 16:03:58 -0700 Subject: [PATCH] CurveTreesUnitTest -> CurveTreesGlobalTree class --- src/fcmp/curve_trees.h | 11 ++-- tests/unit_tests/curve_trees.cpp | 109 +++++++++++++++---------------- tests/unit_tests/curve_trees.h | 16 +++-- 3 files changed, 65 insertions(+), 71 deletions(-) diff --git a/src/fcmp/curve_trees.h b/src/fcmp/curve_trees.h index 1b8838cd7..361b9ade2 100644 --- a/src/fcmp/curve_trees.h +++ b/src/fcmp/curve_trees.h @@ -34,8 +34,6 @@ #include -// forward declarations -class CurveTreesUnitTest; namespace fcmp @@ -52,7 +50,7 @@ typename C::Point get_new_parent(const C &curve, const typename C::Chunk &new_ch template struct LayerExtension final { - std::size_t start_idx; + std::size_t start_idx{0}; std::vector hashes; }; @@ -86,7 +84,6 @@ struct LastChunkData final template class CurveTrees { - friend class ::CurveTreesUnitTest; public: CurveTrees(const C1 &c1, const C2 &c2, const std::size_t c1_width, const std::size_t c2_width): m_c1{c1}, @@ -105,11 +102,11 @@ public: struct LeafTuple final { // Output ed25519 point x-coordinate - typename C2::Scalar O_x; + const typename C2::Scalar O_x; // Key image generator x-coordinate - typename C2::Scalar I_x; + const typename C2::Scalar I_x; // Commitment x-coordinate - typename C2::Scalar C_x; + const typename C2::Scalar C_x; }; static const std::size_t LEAF_TUPLE_SIZE = 3; static_assert(sizeof(LeafTuple) == (sizeof(typename C2::Scalar) * LEAF_TUPLE_SIZE), "unexpected LeafTuple size"); diff --git a/tests/unit_tests/curve_trees.cpp b/tests/unit_tests/curve_trees.cpp index b37895a12..522021f5c 100644 --- a/tests/unit_tests/curve_trees.cpp +++ b/tests/unit_tests/curve_trees.cpp @@ -35,7 +35,7 @@ //---------------------------------------------------------------------------------------------------------------------- //---------------------------------------------------------------------------------------------------------------------- -// CurveTreesUnitTest helpers +// CurveTreesGlobalTree helpers //---------------------------------------------------------------------------------------------------------------------- template static fcmp::curve_trees::LastChunkData get_last_child_layer_chunk(const bool update_last_parent, @@ -61,7 +61,7 @@ static fcmp::curve_trees::LastChunkData get_last_child_layer_chunk(const bool //---------------------------------------------------------------------------------------------------------------------- template static bool validate_layer(const C &curve, - const CurveTreesUnitTest::Layer &parents, + const CurveTreesGlobalTree::Layer &parents, const std::vector &child_scalars, const std::size_t max_chunk_size) { @@ -98,13 +98,13 @@ static bool validate_layer(const C &curve, } //---------------------------------------------------------------------------------------------------------------------- //---------------------------------------------------------------------------------------------------------------------- -// CurveTreesUnitTest implementations +// CurveTreesGlobalTree implementations //---------------------------------------------------------------------------------------------------------------------- -CurveTreesV1::LastChunks CurveTreesUnitTest::get_last_chunks(const CurveTreesUnitTest::Tree &tree) +CurveTreesV1::LastChunks CurveTreesGlobalTree::get_last_chunks() { - const auto &leaves = tree.leaves; - const auto &c1_layers = tree.c1_layers; - const auto &c2_layers = tree.c2_layers; + const auto &leaves = m_tree.leaves; + const auto &c1_layers = m_tree.c1_layers; + const auto &c2_layers = m_tree.c2_layers; // We started with c2 and then alternated, so c2 is the same size or 1 higher than c1 CHECK_AND_ASSERT_THROW_MES(c2_layers.size() == c1_layers.size() || c2_layers.size() == (c1_layers.size() + 1), @@ -201,18 +201,17 @@ CurveTreesV1::LastChunks CurveTreesUnitTest::get_last_chunks(const CurveTreesUni return last_chunks; } //---------------------------------------------------------------------------------------------------------------------- -void CurveTreesUnitTest::extend_tree(const CurveTreesV1::TreeExtension &tree_extension, - CurveTreesUnitTest::Tree &tree_inout) +void CurveTreesGlobalTree::extend_tree(const CurveTreesV1::TreeExtension &tree_extension) { // Add the leaves - const std::size_t init_num_leaves = tree_inout.leaves.size() * m_curve_trees.LEAF_TUPLE_SIZE; + const std::size_t init_num_leaves = m_tree.leaves.size() * m_curve_trees.LEAF_TUPLE_SIZE; CHECK_AND_ASSERT_THROW_MES(init_num_leaves == tree_extension.leaves.start_idx, "unexpected leaf start idx"); - tree_inout.leaves.reserve(tree_inout.leaves.size() + tree_extension.leaves.tuples.size()); + m_tree.leaves.reserve(m_tree.leaves.size() + tree_extension.leaves.tuples.size()); for (const auto &leaf : tree_extension.leaves.tuples) { - tree_inout.leaves.emplace_back(CurveTreesV1::LeafTuple{ + m_tree.leaves.emplace_back(CurveTreesV1::LeafTuple{ .O_x = leaf.O_x, .I_x = leaf.I_x, .C_x = leaf.C_x @@ -237,11 +236,11 @@ void CurveTreesUnitTest::extend_tree(const CurveTreesV1::TreeExtension &tree_ext CHECK_AND_ASSERT_THROW_MES(!c2_ext.hashes.empty(), "empty c2 layer extension"); - CHECK_AND_ASSERT_THROW_MES(c2_idx <= tree_inout.c2_layers.size(), "missing c2 layer"); - if (tree_inout.c2_layers.size() == c2_idx) - tree_inout.c2_layers.emplace_back(Layer{}); + CHECK_AND_ASSERT_THROW_MES(c2_idx <= m_tree.c2_layers.size(), "missing c2 layer"); + if (m_tree.c2_layers.size() == c2_idx) + m_tree.c2_layers.emplace_back(Layer{}); - auto &c2_inout = tree_inout.c2_layers[c2_idx]; + auto &c2_inout = m_tree.c2_layers[c2_idx]; const bool started_after_tip = (c2_inout.size() == c2_ext.start_idx); const bool started_at_tip = (c2_inout.size() == (c2_ext.start_idx + 1)); @@ -263,11 +262,11 @@ void CurveTreesUnitTest::extend_tree(const CurveTreesV1::TreeExtension &tree_ext CHECK_AND_ASSERT_THROW_MES(!c1_ext.hashes.empty(), "empty c1 layer extension"); - CHECK_AND_ASSERT_THROW_MES(c1_idx <= tree_inout.c1_layers.size(), "missing c1 layer"); - if (tree_inout.c1_layers.size() == c1_idx) - tree_inout.c1_layers.emplace_back(Layer{}); + CHECK_AND_ASSERT_THROW_MES(c1_idx <= m_tree.c1_layers.size(), "missing c1 layer"); + if (m_tree.c1_layers.size() == c1_idx) + m_tree.c1_layers.emplace_back(Layer{}); - auto &c1_inout = tree_inout.c1_layers[c1_idx]; + auto &c1_inout = m_tree.c1_layers[c1_idx]; const bool started_after_tip = (c1_inout.size() == c1_ext.start_idx); const bool started_at_tip = (c1_inout.size() == (c1_ext.start_idx + 1)); @@ -287,11 +286,11 @@ void CurveTreesUnitTest::extend_tree(const CurveTreesV1::TreeExtension &tree_ext } } //---------------------------------------------------------------------------------------------------------------------- -bool CurveTreesUnitTest::validate_tree(const CurveTreesUnitTest::Tree &tree) +bool CurveTreesGlobalTree::audit_tree() { - const auto &leaves = tree.leaves; - const auto &c1_layers = tree.c1_layers; - const auto &c2_layers = tree.c2_layers; + const auto &leaves = m_tree.leaves; + const auto &c1_layers = m_tree.c1_layers; + const auto &c2_layers = m_tree.c2_layers; CHECK_AND_ASSERT_MES(!leaves.empty(), false, "must have at least 1 leaf in tree"); CHECK_AND_ASSERT_MES(!c2_layers.empty(), false, "must have at least 1 c2 layer in tree"); @@ -380,7 +379,7 @@ bool CurveTreesUnitTest::validate_tree(const CurveTreesUnitTest::Tree &tree) //---------------------------------------------------------------------------------------------------------------------- // Logging helpers //---------------------------------------------------------------------------------------------------------------------- -void CurveTreesUnitTest::log_last_chunks(const CurveTreesV1::LastChunks &last_chunks) +void CurveTreesGlobalTree::log_last_chunks(const CurveTreesV1::LastChunks &last_chunks) { const auto &c1_last_chunks = last_chunks.c1_last_chunks; const auto &c2_last_chunks = last_chunks.c2_last_chunks; @@ -424,7 +423,7 @@ void CurveTreesUnitTest::log_last_chunks(const CurveTreesV1::LastChunks &last_ch } } //---------------------------------------------------------------------------------------------------------------------- -void CurveTreesUnitTest::log_tree_extension(const CurveTreesV1::TreeExtension &tree_extension) +void CurveTreesGlobalTree::log_tree_extension(const CurveTreesV1::TreeExtension &tree_extension) { const auto &c1_extensions = tree_extension.c1_layer_extensions; const auto &c2_extensions = tree_extension.c2_layer_extensions; @@ -481,14 +480,14 @@ void CurveTreesUnitTest::log_tree_extension(const CurveTreesV1::TreeExtension &t } } //---------------------------------------------------------------------------------------------------------------------- -void CurveTreesUnitTest::log_tree(const CurveTreesUnitTest::Tree &tree) +void CurveTreesGlobalTree::log_tree() { - LOG_PRINT_L1("Tree has " << tree.leaves.size() << " leaves, " - << tree.c1_layers.size() << " helios layers, " << tree.c2_layers.size() << " selene layers"); + MDEBUG("Tree has " << m_tree.leaves.size() << " leaves, " + << m_tree.c1_layers.size() << " helios layers, " << m_tree.c2_layers.size() << " selene layers"); - for (std::size_t i = 0; i < tree.leaves.size(); ++i) + for (std::size_t i = 0; i < m_tree.leaves.size(); ++i) { - const auto &leaf = tree.leaves[i]; + const auto &leaf = m_tree.leaves[i]; const auto O_x = m_curve_trees.m_c2.to_string(leaf.O_x); const auto I_x = m_curve_trees.m_c2.to_string(leaf.I_x); @@ -500,13 +499,13 @@ void CurveTreesUnitTest::log_tree(const CurveTreesUnitTest::Tree &tree) bool use_c2 = true; std::size_t c1_idx = 0; std::size_t c2_idx = 0; - for (std::size_t i = 0; i < (tree.c1_layers.size() + tree.c2_layers.size()); ++i) + for (std::size_t i = 0; i < (m_tree.c1_layers.size() + m_tree.c2_layers.size()); ++i) { if (use_c2) { - CHECK_AND_ASSERT_THROW_MES(c2_idx < tree.c2_layers.size(), "unexpected c2 layer"); + CHECK_AND_ASSERT_THROW_MES(c2_idx < m_tree.c2_layers.size(), "unexpected c2 layer"); - const CurveTreesUnitTest::Layer &c2_layer = tree.c2_layers[c2_idx]; + const CurveTreesGlobalTree::Layer &c2_layer = m_tree.c2_layers[c2_idx]; MDEBUG("Selene layer size: " << c2_layer.size() << " , tree layer: " << i); for (std::size_t j = 0; j < c2_layer.size(); ++j) @@ -516,9 +515,9 @@ void CurveTreesUnitTest::log_tree(const CurveTreesUnitTest::Tree &tree) } else { - CHECK_AND_ASSERT_THROW_MES(c1_idx < tree.c1_layers.size(), "unexpected c1 layer"); + CHECK_AND_ASSERT_THROW_MES(c1_idx < m_tree.c1_layers.size(), "unexpected c1 layer"); - const CurveTreesUnitTest::Layer &c1_layer = tree.c1_layers[c1_idx]; + const CurveTreesGlobalTree::Layer &c1_layer = m_tree.c1_layers[c1_idx]; MDEBUG("Helios layer size: " << c1_layer.size() << " , tree layer: " << i); for (std::size_t j = 0; j < c1_layer.size(); ++j) @@ -557,47 +556,45 @@ const std::vector generate_random_leaves(const CurveTre } //---------------------------------------------------------------------------------------------------------------------- static bool grow_tree(CurveTreesV1 &curve_trees, - CurveTreesUnitTest &curve_trees_accessor, - const std::size_t num_leaves, - CurveTreesUnitTest::Tree &tree_inout) + CurveTreesGlobalTree &global_tree, + const std::size_t num_leaves) { // Get the last chunk from each layer in the tree; empty if tree is empty - const auto last_chunks = curve_trees_accessor.get_last_chunks(tree_inout); + const auto last_chunks = global_tree.get_last_chunks(); - curve_trees_accessor.log_last_chunks(last_chunks); + global_tree.log_last_chunks(last_chunks); // Get a tree extension object to the existing tree using randomly generated leaves // - The tree extension includes all elements we'll need to add to the existing tree when adding the new leaves const auto tree_extension = curve_trees.get_tree_extension(last_chunks, generate_random_leaves(curve_trees, num_leaves)); - curve_trees_accessor.log_tree_extension(tree_extension); + global_tree.log_tree_extension(tree_extension); // Use the tree extension to extend the existing tree - curve_trees_accessor.extend_tree(tree_extension, tree_inout); + global_tree.extend_tree(tree_extension); - curve_trees_accessor.log_tree(tree_inout); + global_tree.log_tree(); // Validate tree structure and all hashes - return curve_trees_accessor.validate_tree(tree_inout); + return global_tree.audit_tree(); } //---------------------------------------------------------------------------------------------------------------------- static bool grow_tree_in_memory(const std::size_t init_leaves, const std::size_t ext_leaves, - CurveTreesV1 &curve_trees, - CurveTreesUnitTest &curve_trees_accessor) + CurveTreesV1 &curve_trees) { - LOG_PRINT_L1("Adding " << init_leaves << " leaves to tree, then extending by " << ext_leaves << " leaves"); + LOG_PRINT_L1("Adding " << init_leaves << " leaves to tree in memory, then extending by " + << ext_leaves << " leaves"); - CurveTreesUnitTest::Tree global_tree; + CurveTreesGlobalTree global_tree(curve_trees); // Initialize global tree with `init_leaves` MDEBUG("Adding " << init_leaves << " leaves to tree"); bool res = grow_tree(curve_trees, - curve_trees_accessor, - init_leaves, - global_tree); + global_tree, + init_leaves); CHECK_AND_ASSERT_MES(res, false, "failed to add inital leaves to tree in memory"); @@ -607,9 +604,8 @@ static bool grow_tree_in_memory(const std::size_t init_leaves, MDEBUG("Extending tree by " << ext_leaves << " leaves"); res = grow_tree(curve_trees, - curve_trees_accessor, - ext_leaves, - global_tree); + global_tree, + ext_leaves); CHECK_AND_ASSERT_MES(res, false, "failed to extend tree in memory"); @@ -661,7 +657,6 @@ TEST(curve_trees, grow_tree) HELIOS_CHUNK_WIDTH, SELENE_CHUNK_WIDTH); - CurveTreesUnitTest curve_trees_accessor{curve_trees}; unit_test::BlockchainLMDBTest test_db; CHECK_AND_ASSERT_THROW_MES(HELIOS_CHUNK_WIDTH > 1, "helios width must be > 1"); @@ -699,7 +694,7 @@ TEST(curve_trees, grow_tree) if (ext_leaves > 1 && init_leaves == NEED_3_LAYERS) continue; - ASSERT_TRUE(grow_tree_in_memory(init_leaves, ext_leaves, curve_trees, curve_trees_accessor)); + ASSERT_TRUE(grow_tree_in_memory(init_leaves, ext_leaves, curve_trees)); ASSERT_TRUE(grow_tree_db(init_leaves, ext_leaves, curve_trees, test_db)); } } diff --git a/tests/unit_tests/curve_trees.h b/tests/unit_tests/curve_trees.h index 6d838ec1d..6342497ce 100644 --- a/tests/unit_tests/curve_trees.h +++ b/tests/unit_tests/curve_trees.h @@ -43,11 +43,12 @@ const std::vector generate_random_leaves(const CurveTre const std::size_t HELIOS_CHUNK_WIDTH = 38; const std::size_t SELENE_CHUNK_WIDTH = 18; -// Helper class that can access the private members of the CurveTrees class -class CurveTreesUnitTest +// Helper class to read/write a global tree in memory. It's only used in testing because normally the tree isn't kept +// in memory (it's stored in the db) +class CurveTreesGlobalTree { public: - CurveTreesUnitTest(CurveTreesV1 &curve_trees): m_curve_trees(curve_trees) {}; + CurveTreesGlobalTree(CurveTreesV1 &curve_trees): m_curve_trees(curve_trees) {}; //member structs public: @@ -65,20 +66,21 @@ public: //public member functions public: // Read the in-memory tree and get data from last chunks from each layer - CurveTreesV1::LastChunks get_last_chunks(const Tree &tree); + CurveTreesV1::LastChunks get_last_chunks(); // Use the tree extension to extend the in-memory tree - void extend_tree(const CurveTreesV1::TreeExtension &tree_extension, Tree &tree_inout); + void extend_tree(const CurveTreesV1::TreeExtension &tree_extension); // Validate the in-memory tree by re-hashing every layer, starting from root and working down to leaf layer - bool validate_tree(const Tree &tree); + bool audit_tree(); // logging helpers void log_last_chunks(const CurveTreesV1::LastChunks &last_chunks); void log_tree_extension(const CurveTreesV1::TreeExtension &tree_extension); - void log_tree(const CurveTreesUnitTest::Tree &tree); + void log_tree(); private: CurveTreesV1 &m_curve_trees; + Tree m_tree = Tree{}; };