diff --git a/src/blockchain_db/lmdb/db_lmdb.cpp b/src/blockchain_db/lmdb/db_lmdb.cpp index 1200b5f680..602f1b391b 100644 --- a/src/blockchain_db/lmdb/db_lmdb.cpp +++ b/src/blockchain_db/lmdb/db_lmdb.cpp @@ -922,8 +922,6 @@ void BlockchainLMDB::remove_block() // must use h now; deleting from m_block_info will invalidate it mdb_block_info *bi = (mdb_block_info *)h.mv_data; - const uint64_t block_id = bi->bi_height; - const uint64_t old_n_leaf_tuples = bi->bi_n_leaf_tuples; blk_height bh = {bi->bi_hash, 0}; h.mv_data = (void *)&bh; h.mv_size = sizeof(bh); @@ -1445,45 +1443,45 @@ void BlockchainLMDB::grow_tree(std::vector // Grow the layers // TODO: grow_layers - const auto &c2_extensions = tree_extension.c2_layer_extensions; const auto &c1_extensions = tree_extension.c1_layer_extensions; + const auto &c2_extensions = tree_extension.c2_layer_extensions; - bool use_c2 = true; - uint64_t c2_idx = 0; + bool parent_is_c1 = true; uint64_t c1_idx = 0; - for (uint64_t i = 0; i < (c2_extensions.size() + c1_extensions.size()); ++i) + uint64_t c2_idx = 0; + for (uint64_t i = 0; i < (c1_extensions.size() + c2_extensions.size()); ++i) { - const uint64_t layer_idx = c2_idx + c1_idx; + const uint64_t layer_idx = c1_idx + c2_idx; MDEBUG("Growing layer " << layer_idx); - if (use_c2) + if (parent_is_c1) { if (layer_idx % 2 != 0) - throw0(DB_ERROR(("Growing odd c2 layer, expected even layer idx for c2: " + throw0(DB_ERROR(("Growing odd c1 layer, expected even layer idx for c1: " + std::to_string(layer_idx)).c_str())); - this->grow_layer(m_curve_trees->m_c2, - c2_extensions, - c2_idx, + this->grow_layer(m_curve_trees->m_c1, + c1_extensions, + c1_idx, layer_idx); - ++c2_idx; + ++c1_idx; } else { if (layer_idx % 2 == 0) - throw0(DB_ERROR(("Growing even c1 layer, expected odd layer idx for c1: " + throw0(DB_ERROR(("Growing even c2 layer, expected odd layer idx for c2: " + std::to_string(layer_idx)).c_str())); - this->grow_layer(m_curve_trees->m_c1, - c1_extensions, - c1_idx, + this->grow_layer(m_curve_trees->m_c2, + c2_extensions, + c2_idx, layer_idx); - ++c1_idx; + ++c2_idx; } - use_c2 = !use_c2; + parent_is_c1 = !parent_is_c1; } } @@ -1598,20 +1596,12 @@ std::pair BlockchainLMDB::get_last_pa return { tree_reduction.new_total_leaf_tuples, path }; // Use the tree reduction to update last hashes in each layer if needed - bool use_c2 = true; + bool parent_is_c1 = true; std::size_t c1_idx = 0; std::size_t c2_idx = 0; for (auto &layer : path.layer_chunks) { - if (use_c2) - { - CHECK_AND_ASSERT_THROW_MES(c2_idx < tree_reduction.c2_layer_reductions.size(), "unexpected c2 layer reduction"); - const auto &layer_reduction = tree_reduction.c2_layer_reductions[c2_idx]; - if (layer_reduction.update_existing_last_hash) - layer.chunk_bytes.back() = m_curve_trees->m_c2->to_bytes(layer_reduction.new_last_hash); - ++c2_idx; - } - else + if (parent_is_c1) { CHECK_AND_ASSERT_THROW_MES(c1_idx < tree_reduction.c1_layer_reductions.size(), "unexpected c1 layer reduction"); const auto &layer_reduction = tree_reduction.c1_layer_reductions[c1_idx]; @@ -1619,8 +1609,16 @@ std::pair BlockchainLMDB::get_last_pa layer.chunk_bytes.back() = m_curve_trees->m_c1->to_bytes(layer_reduction.new_last_hash); ++c1_idx; } + else + { + CHECK_AND_ASSERT_THROW_MES(c2_idx < tree_reduction.c2_layer_reductions.size(), "unexpected c2 layer reduction"); + const auto &layer_reduction = tree_reduction.c2_layer_reductions[c2_idx]; + if (layer_reduction.update_existing_last_hash) + layer.chunk_bytes.back() = m_curve_trees->m_c2->to_bytes(layer_reduction.new_last_hash); + ++c2_idx; + } - use_c2 = !use_c2; + parent_is_c1 = !parent_is_c1; } TXN_POSTFIX_RDONLY(); @@ -1778,32 +1776,32 @@ void BlockchainLMDB::trim_tree(const uint64_t new_n_leaf_tuples, const uint64_t // Trim the layers // TODO: trim_layers - const auto &c2_layer_reductions = tree_reduction.c2_layer_reductions; const auto &c1_layer_reductions = tree_reduction.c1_layer_reductions; + const auto &c2_layer_reductions = tree_reduction.c2_layer_reductions; - const std::size_t n_layers = c2_layer_reductions.size() + c1_layer_reductions.size(); + const std::size_t n_layers = c1_layer_reductions.size() + c2_layer_reductions.size(); - bool use_c2 = true; - uint64_t c2_idx = 0; + bool parent_is_c1 = true; uint64_t c1_idx = 0; + uint64_t c2_idx = 0; for (uint64_t i = 0; i < n_layers; ++i) { - if (use_c2) - { - CHECK_AND_ASSERT_THROW_MES(c2_idx < c2_layer_reductions.size(), "unexpected c2 layer reduction"); - const auto &c2_reduction = c2_layer_reductions[c2_idx]; - this->trim_layer(m_curve_trees->m_c2, c2_reduction, i); - ++c2_idx; - } - else + if (parent_is_c1) { CHECK_AND_ASSERT_THROW_MES(c1_idx < c1_layer_reductions.size(), "unexpected c1 layer reduction"); const auto &c1_reduction = c1_layer_reductions[c1_idx]; this->trim_layer(m_curve_trees->m_c1, c1_reduction, i); ++c1_idx; } + else + { + CHECK_AND_ASSERT_THROW_MES(c2_idx < c2_layer_reductions.size(), "unexpected c2 layer reduction"); + const auto &c2_reduction = c2_layer_reductions[c2_idx]; + this->trim_layer(m_curve_trees->m_c2, c2_reduction, i); + ++c2_idx; + } - use_c2 = !use_c2; + parent_is_c1 = !parent_is_c1; } // Trim any remaining layers in layers after the root @@ -2027,16 +2025,16 @@ fcmp_pp::curve_trees::CurveTreesV1::LastHashes BlockchainLMDB::get_tree_last_has const auto *lv = (layer_val *)v.mv_data; MDEBUG("Reading last hash at layer_idx: " << layer_idx << " , lv->child_chunk_idx: " << lv->child_chunk_idx); - const bool use_c2 = (layer_idx % 2) == 0; - if (use_c2) + const bool parent_is_c1 = (layer_idx % 2) == 0; + if (parent_is_c1) { - auto point = m_curve_trees->m_c2->from_bytes(lv->child_chunk_hash); - c2_last_hashes.emplace_back(std::move(point)); + auto point = m_curve_trees->m_c1->from_bytes(lv->child_chunk_hash); + c1_last_hashes.emplace_back(std::move(point)); } else { - auto point = m_curve_trees->m_c1->from_bytes(lv->child_chunk_hash); - c1_last_hashes.emplace_back(std::move(point)); + auto point = m_curve_trees->m_c2->from_bytes(lv->child_chunk_hash); + c2_last_hashes.emplace_back(std::move(point)); } ++layer_idx; @@ -2176,13 +2174,13 @@ fcmp_pp::curve_trees::CurveTreesV1::LastHashes BlockchainLMDB::get_last_hashes_f const auto *lv = (layer_val *)v.mv_data; if ((layer_idx % 2) == 0) { - auto point = m_curve_trees->m_c2->from_bytes(lv->child_chunk_hash); - last_hashes_out.c2_last_hashes.emplace_back(std::move(point)); + auto point = m_curve_trees->m_c1->from_bytes(lv->child_chunk_hash); + last_hashes_out.c1_last_hashes.emplace_back(std::move(point)); } else { - auto point = m_curve_trees->m_c1->from_bytes(lv->child_chunk_hash); - last_hashes_out.c1_last_hashes.emplace_back(std::move(point)); + auto point = m_curve_trees->m_c2->from_bytes(lv->child_chunk_hash); + last_hashes_out.c2_last_hashes.emplace_back(std::move(point)); } ++layer_idx; @@ -2233,7 +2231,7 @@ bool BlockchainLMDB::audit_tree(const uint64_t expected_n_leaf_tuples) const { // Get next leaf chunk std::vector leaf_tuples_chunk; - leaf_tuples_chunk.reserve(m_curve_trees->m_c2_width); + leaf_tuples_chunk.reserve(m_curve_trees->m_c1_width); if (child_chunk_idx && child_chunk_idx % 1000 == 0) MINFO("Auditing layer " << layer_idx << ", child_chunk_idx " << child_chunk_idx); @@ -2254,7 +2252,7 @@ bool BlockchainLMDB::audit_tree(const uint64_t expected_n_leaf_tuples) const leaf_tuples_chunk.emplace_back(std::move(leaf)); - if (leaf_tuples_chunk.size() == m_curve_trees->m_c2_width) + if (leaf_tuples_chunk.size() == m_curve_trees->m_c1_width) break; } @@ -2286,12 +2284,12 @@ bool BlockchainLMDB::audit_tree(const uint64_t expected_n_leaf_tuples) const // Hash the chunk of leaves for (uint64_t i = 0; i < leaves.size(); ++i) - MDEBUG("Hashing " << m_curve_trees->m_c2->to_string(leaves[i])); + MDEBUG("Hashing " << m_curve_trees->m_c1->to_string(leaves[i])); - const auto chunk_hash = fcmp_pp::curve_trees::get_new_parent(m_curve_trees->m_c2, chunk); - const auto expected_chunk_hash = m_curve_trees->m_c2->to_string(chunk_hash); + const auto chunk_hash = fcmp_pp::curve_trees::get_new_parent(m_curve_trees->m_c1, chunk); + const auto expected_chunk_hash = m_curve_trees->m_c1->to_string(chunk_hash); MDEBUG("chunk_hash " << expected_chunk_hash << " , hash init point: " - << m_curve_trees->m_c2->to_string(m_curve_trees->m_c2->hash_init_point()) << " (" << leaves.size() << " leaves)"); + << m_curve_trees->m_c1->to_string(m_curve_trees->m_c1->hash_init_point()) << " (" << leaves.size() << " leaves)"); // Now compare to value from the db const auto *lv = (layer_val *)v_parent.mv_data; @@ -2312,23 +2310,23 @@ bool BlockchainLMDB::audit_tree(const uint64_t expected_n_leaf_tuples) const { MDEBUG("Auditing layer " << layer_idx); - // Alternate starting with c1 as parent (we already audited c2 leaf parents), then c2 as parent, then c1, etc. - const bool parent_is_c1 = layer_idx % 2 == 0; - if (parent_is_c1) + // Alternate starting with c2 as parent (we already audited c1 leaf parents), then c1 as parent, then c2, etc. + const bool parent_is_c2 = layer_idx % 2 == 0; + if (parent_is_c2) { audit_complete = this->audit_layer( - /*c_child*/ m_curve_trees->m_c2, - /*c_parent*/ m_curve_trees->m_c1, + /*c_child*/ m_curve_trees->m_c1, + /*c_parent*/ m_curve_trees->m_c2, layer_idx, - /*chunk_width*/ m_curve_trees->m_c1_width); + /*chunk_width*/ m_curve_trees->m_c2_width); } else { audit_complete = this->audit_layer( - /*c_child*/ m_curve_trees->m_c1, - /*c_parent*/ m_curve_trees->m_c2, + /*c_child*/ m_curve_trees->m_c2, + /*c_parent*/ m_curve_trees->m_c1, layer_idx, - /*chunk_width*/ m_curve_trees->m_c2_width); + /*chunk_width*/ m_curve_trees->m_c1_width); } ++layer_idx; diff --git a/src/fcmp_pp/curve_trees.cpp b/src/fcmp_pp/curve_trees.cpp index 2ef73401fb..71f06ceef7 100644 --- a/src/fcmp_pp/curve_trees.cpp +++ b/src/fcmp_pp/curve_trees.cpp @@ -41,7 +41,7 @@ namespace curve_trees //---------------------------------------------------------------------------------------------------------------------- //---------------------------------------------------------------------------------------------------------------------- // Instantiate the tower cycle types -template class CurveTrees; +template class CurveTrees; //---------------------------------------------------------------------------------------------------------------------- //---------------------------------------------------------------------------------------------------------------------- // Public helper functions @@ -59,10 +59,10 @@ typename C::Point get_new_parent(const std::unique_ptr &curve, const typename new_children ); }; -template Helios::Point get_new_parent(const std::unique_ptr &curve, - const typename Helios::Chunk &new_children); template Selene::Point get_new_parent(const std::unique_ptr &curve, const typename Selene::Chunk &new_children); +template Helios::Point get_new_parent(const std::unique_ptr &curve, + const typename Helios::Chunk &new_children); //---------------------------------------------------------------------------------------------------------------------- OutputTuple output_to_tuple(const OutputPair &output_pair) { @@ -141,16 +141,16 @@ OutputTuple output_to_tuple(const OutputPair &output_pair) }; } //---------------------------------------------------------------------------------------------------------------------- -std::shared_ptr curve_trees_v1(const std::size_t helios_chunk_width, const std::size_t selene_chunk_width) +std::shared_ptr curve_trees_v1(const std::size_t selene_chunk_width, const std::size_t helios_chunk_width) { - std::unique_ptr helios(new Helios()); std::unique_ptr selene(new Selene()); + std::unique_ptr helios(new Helios()); return std::shared_ptr( new CurveTreesV1( - std::move(helios), std::move(selene), - helios_chunk_width, - selene_chunk_width + std::move(helios), + selene_chunk_width, + helios_chunk_width ) ); }; @@ -850,21 +850,21 @@ static PreLeafTuple output_to_pre_leaf_tuple(const OutputPair &output_pair) return output_tuple_to_pre_leaf_tuple(o); } //---------------------------------------------------------------------------------------------------------------------- -static CurveTrees::LeafTuple pre_leaf_tuple_to_leaf_tuple(const PreLeafTuple &plt) +static CurveTrees::LeafTuple pre_leaf_tuple_to_leaf_tuple(const PreLeafTuple &plt) { rct::key O_x, I_x, C_x; fcmp_pp::ed_y_derivatives_to_wei_x(plt.O_pre_x, O_x); fcmp_pp::ed_y_derivatives_to_wei_x(plt.I_pre_x, I_x); fcmp_pp::ed_y_derivatives_to_wei_x(plt.C_pre_x, C_x); - return CurveTrees::LeafTuple{ + return CurveTrees::LeafTuple{ .O_x = tower_cycle::selene_scalar_from_bytes(O_x), .I_x = tower_cycle::selene_scalar_from_bytes(I_x), .C_x = tower_cycle::selene_scalar_from_bytes(C_x) }; } //---------------------------------------------------------------------------------------------------------------------- -static CurveTrees::LeafTuple output_tuple_to_leaf_tuple(const OutputTuple &output_tuple) +static CurveTrees::LeafTuple output_tuple_to_leaf_tuple(const OutputTuple &output_tuple) { const auto plt = output_tuple_to_pre_leaf_tuple(output_tuple); return pre_leaf_tuple_to_leaf_tuple(plt); @@ -874,16 +874,16 @@ static CurveTrees::LeafTuple output_tuple_to_leaf_tuple(const Ou // CurveTrees public member functions //---------------------------------------------------------------------------------------------------------------------- template<> -CurveTrees::LeafTuple CurveTrees::leaf_tuple(const OutputPair &output_pair) const +CurveTrees::LeafTuple CurveTrees::leaf_tuple(const OutputPair &output_pair) const { const auto plt = output_to_pre_leaf_tuple(output_pair); return pre_leaf_tuple_to_leaf_tuple(plt); }; //---------------------------------------------------------------------------------------------------------------------- template -std::vector CurveTrees::flatten_leaves(std::vector &&leaves) const +std::vector CurveTrees::flatten_leaves(std::vector &&leaves) const { - std::vector flattened_leaves; + std::vector flattened_leaves; flattened_leaves.reserve(leaves.size() * LEAF_TUPLE_SIZE); for (auto &l : leaves) @@ -897,7 +897,7 @@ std::vector CurveTrees::flatten_leaves(std::vector< }; // Explicit instantiation -template std::vector CurveTrees::flatten_leaves( +template std::vector CurveTrees::flatten_leaves( std::vector &&leaves) const; //---------------------------------------------------------------------------------------------------------------------- template @@ -932,7 +932,7 @@ typename CurveTrees::TreeExtension CurveTrees::get_tree_extensio // Convert sorted outputs into leaf tuples, place each element of each leaf tuple in a flat vector to be hashed, // and place the outputs in a tree extension struct for insertion into the db. We ignore invalid outputs, since // they cannot be inserted to the tree. - std::vector flattened_leaves; + std::vector flattened_leaves; this->set_valid_leaves(flattened_leaves, tree_extension.leaves.tuples, std::move(flat_sorted_outputs)); if (flattened_leaves.empty()) @@ -948,12 +948,12 @@ typename CurveTrees::TreeExtension CurveTrees::get_tree_extensio m_leaf_layer_chunk_width); if (grow_layer_instructions.need_old_last_parent) - CHECK_AND_ASSERT_THROW_MES(!existing_last_hashes.c2_last_hashes.empty(), "missing last c2 parent"); + CHECK_AND_ASSERT_THROW_MES(!existing_last_hashes.c1_last_hashes.empty(), "missing last c1 parent"); // Hash the leaf layer - auto leaf_parents = hash_children_chunks(m_c2, + auto leaf_parents = hash_children_chunks(m_c1, nullptr, // We never need the old last child from leaf layer because the leaf layer is always append-only - grow_layer_instructions.need_old_last_parent ? &existing_last_hashes.c2_last_hashes[0] : nullptr, + grow_layer_instructions.need_old_last_parent ? &existing_last_hashes.c1_last_hashes[0] : nullptr, grow_layer_instructions.start_offset, grow_layer_instructions.next_parent_start_index, flattened_leaves, @@ -965,10 +965,10 @@ typename CurveTrees::TreeExtension CurveTrees::get_tree_extensio (leaf_parents.start_idx + leaf_parents.hashes.size()) == grow_layer_instructions.new_total_parents, "unexpected num leaf parents extended"); - tree_extension.c2_layer_extensions.emplace_back(std::move(leaf_parents)); + tree_extension.c1_layer_extensions.emplace_back(std::move(leaf_parents)); - // Alternate between hashing c2 children, c1 children, c2, c1, ... - bool parent_is_c1 = true; + // Alternate between hashing c1 children, c2 children, c1, c2, ... + bool parent_is_c2 = true; std::size_t c1_last_idx = 0; std::size_t c2_last_idx = 0; @@ -981,7 +981,7 @@ typename CurveTrees::TreeExtension CurveTrees::get_tree_extensio grow_layer_instructions = this->set_next_layer_extension( grow_layer_instructions, - parent_is_c1, + parent_is_c2, existing_last_hashes, c1_last_idx, c2_last_idx, @@ -992,7 +992,7 @@ typename CurveTrees::TreeExtension CurveTrees::get_tree_extensio CHECK_AND_ASSERT_THROW_MES(grow_layer_instructions.new_total_parents < new_total_children, "expect fewer parents than children in every layer"); - parent_is_c1 = !parent_is_c1; + parent_is_c2 = !parent_is_c2; } TIME_MEASURE_FINISH(hashing_layers); @@ -1008,7 +1008,7 @@ typename CurveTrees::TreeExtension CurveTrees::get_tree_extensio }; // Explicit instantiation -template CurveTrees::TreeExtension CurveTrees::get_tree_extension( +template CurveTrees::TreeExtension CurveTrees::get_tree_extension( const uint64_t old_n_leaf_tuples, const LastHashes &existing_last_hashes, std::vector> &&new_outputs); @@ -1049,7 +1049,7 @@ std::vector CurveTrees::get_trim_instructions( trim_instructions.emplace_back(std::move(trim_leaf_layer_instructions)); } - bool use_c2 = false; + bool parent_is_c2 = true; while (trim_instructions.back().new_total_parents > 1) { MDEBUG("Getting trim layer instructions for layer " << trim_instructions.size()); @@ -1057,19 +1057,19 @@ std::vector CurveTrees::get_trim_instructions( auto trim_layer_instructions = get_trim_layer_instructions( trim_instructions.back().old_total_parents, trim_instructions.back().new_total_parents, - use_c2 ? m_c2_width : m_c1_width, + parent_is_c2 ? m_c2_width : m_c1_width, trim_instructions.back().update_existing_last_hash, always_regrow_with_remaining); trim_instructions.emplace_back(std::move(trim_layer_instructions)); - use_c2 = !use_c2; + parent_is_c2 = !parent_is_c2; } return trim_instructions; } // Explicit instantiation -template std::vector CurveTrees::get_trim_instructions( +template std::vector CurveTrees::get_trim_instructions( const uint64_t old_n_leaf_tuples, const uint64_t trim_n_leaf_tuples, const bool always_regrow_with_remaining) const; @@ -1093,7 +1093,7 @@ typename CurveTrees::TreeReduction CurveTrees::get_tree_reductio const uint64_t new_total_leaf_tuples = trim_instructions[0].new_total_children / LEAF_TUPLE_SIZE; tree_reduction_out.new_total_leaf_tuples = new_total_leaf_tuples; - bool use_c2 = true; + bool parent_is_c1 = true; std::size_t c1_idx = 0; std::size_t c2_idx = 0; @@ -1101,49 +1101,49 @@ typename CurveTrees::TreeReduction CurveTrees::get_tree_reductio { MDEBUG("Trimming layer " << (c1_idx + c2_idx) << " (c1_idx: " << c1_idx << " , c2_idx: " << c2_idx << ")"); - if (use_c2) + if (parent_is_c1) { - auto c2_layer_reduction_out = get_next_layer_reduction( - m_c1, + auto c1_layer_reduction_out = get_next_layer_reduction( m_c2, + m_c1, trim_layer_instructions, - last_hashes.c2_last_hashes, - children_for_trim.c2_children, last_hashes.c1_last_hashes, - c2_idx, + children_for_trim.c1_children, + last_hashes.c2_last_hashes, c1_idx, - tree_reduction_out.c1_layer_reductions + c2_idx, + tree_reduction_out.c2_layer_reductions ); - tree_reduction_out.c2_layer_reductions.emplace_back(std::move(c2_layer_reduction_out)); - ++c2_idx; + tree_reduction_out.c1_layer_reductions.emplace_back(std::move(c1_layer_reduction_out)); + ++c1_idx; } else { - auto c1_layer_reduction_out = get_next_layer_reduction( - m_c2, + auto c2_layer_reduction_out = get_next_layer_reduction( m_c1, + m_c2, trim_layer_instructions, - last_hashes.c1_last_hashes, - children_for_trim.c1_children, last_hashes.c2_last_hashes, - c1_idx, + children_for_trim.c2_children, + last_hashes.c1_last_hashes, c2_idx, - tree_reduction_out.c2_layer_reductions + c1_idx, + tree_reduction_out.c1_layer_reductions ); - tree_reduction_out.c1_layer_reductions.emplace_back(std::move(c1_layer_reduction_out)); - ++c1_idx; + tree_reduction_out.c2_layer_reductions.emplace_back(std::move(c2_layer_reduction_out)); + ++c2_idx; } - use_c2 = !use_c2; + parent_is_c1 = !parent_is_c1; } return tree_reduction_out; }; // Explicit instantiation -template CurveTrees::TreeReduction CurveTrees::get_tree_reduction( +template CurveTrees::TreeReduction CurveTrees::get_tree_reduction( const std::vector &trim_instructions, const LastChunkChildrenForTrim &children_for_trim, const LastHashes &last_hashes) const; @@ -1156,13 +1156,13 @@ std::size_t CurveTrees::n_layers(const uint64_t n_leaf_tuples) const uint64_t n_children = n_leaf_tuples; std::size_t n_layers = 0; - bool use_c2 = true; + bool parent_is_c1 = true; do { - const std::size_t parent_chunk_width = use_c2 ? m_c2_width : m_c1_width; + const std::size_t parent_chunk_width = parent_is_c1 ? m_c1_width : m_c2_width; const uint64_t n_parents = ((n_children - 1) / parent_chunk_width) + 1; n_children = n_parents; - use_c2 = !use_c2; + parent_is_c1 = !parent_is_c1; ++n_layers; } while (n_children > 1); @@ -1171,7 +1171,7 @@ std::size_t CurveTrees::n_layers(const uint64_t n_leaf_tuples) const } // Explicit instantiation -template std::size_t CurveTrees::n_layers(const uint64_t n_leaf_tuples) const; +template std::size_t CurveTrees::n_layers(const uint64_t n_leaf_tuples) const; //---------------------------------------------------------------------------------------------------------------------- template PathIndexes CurveTrees::get_path_indexes(const uint64_t n_leaf_tuples, const uint64_t leaf_tuple_idx) const @@ -1186,10 +1186,10 @@ PathIndexes CurveTrees::get_path_indexes(const uint64_t n_leaf_tuples, c uint64_t child_idx = leaf_tuple_idx; uint64_t n_children = n_leaf_tuples; bool leaf_layer = true; - bool parent_is_c2 = true; + bool parent_is_c1 = true; do { - const std::size_t parent_chunk_width = parent_is_c2 ? m_c2_width : m_c1_width; + const std::size_t parent_chunk_width = parent_is_c1 ? m_c1_width : m_c2_width; const uint64_t parent_idx = child_idx / parent_chunk_width; const uint64_t start_range = parent_idx * parent_chunk_width; @@ -1201,11 +1201,11 @@ PathIndexes CurveTrees::get_path_indexes(const uint64_t n_leaf_tuples, c ? (((n_children - 1) / parent_chunk_width) + 1) : 0; - MDEBUG("start_range: " << start_range - << " , end_range: " << end_range + MDEBUG("start_range: " << start_range + << " , end_range: " << end_range << " , parent_chunk_width: " << parent_chunk_width - << " , n_parents: " << n_parents - << " , parent_idx: " << parent_idx); + << " , n_parents: " << n_parents + << " , parent_idx: " << parent_idx); std::pair range = { start_range, end_range }; if (leaf_layer) @@ -1217,7 +1217,7 @@ PathIndexes CurveTrees::get_path_indexes(const uint64_t n_leaf_tuples, c n_children = n_parents; leaf_layer = false; - parent_is_c2 = !parent_is_c2; + parent_is_c1 = !parent_is_c1; } while (n_children > 0); @@ -1225,11 +1225,11 @@ PathIndexes CurveTrees::get_path_indexes(const uint64_t n_leaf_tuples, c } // Explicit instantiation -template PathIndexes CurveTrees::get_path_indexes(const uint64_t n_leaf_tuples, +template PathIndexes CurveTrees::get_path_indexes(const uint64_t n_leaf_tuples, const uint64_t leaf_tuple_idx) const; //---------------------------------------------------------------------------------------------------------------------- template<> -bool CurveTrees::audit_path(const CurveTrees::Path &path, +bool CurveTrees::audit_path(const CurveTrees::Path &path, const OutputPair &output, const uint64_t n_leaf_tuples_in_tree) const { @@ -1242,8 +1242,8 @@ bool CurveTrees::audit_path(const CurveTrees::Pa // Initial checks CHECK_AND_ASSERT_MES(!leaves.empty(), false, "empty leaves"); - CHECK_AND_ASSERT_MES(!c2_layers.empty(), false, "empty c2 layers"); - CHECK_AND_ASSERT_MES(leaves.size() <= m_c2_width, false, "too many leaves"); + CHECK_AND_ASSERT_MES(!c1_layers.empty(), false, "empty c1 layers"); + CHECK_AND_ASSERT_MES(leaves.size() <= m_c1_width, false, "too many leaves"); const std::size_t n_layers = c1_layers.size() + c2_layers.size(); CHECK_AND_ASSERT_MES(n_layers == this->n_layers(n_leaf_tuples_in_tree), false, "unexpected n_layers"); @@ -1269,30 +1269,30 @@ bool CurveTrees::audit_path(const CurveTrees::Pa // Hash the leaf chunk MDEBUG("Path contains " << leaves.size() << " leaf tuples and " << n_layers << " layers, hashing leaf tuples"); const Selene::Chunk leaf_chunk{leaf_scalars.data(), leaf_scalars.size()}; - const Selene::Point leaf_parent_hash = get_new_parent(m_c2, leaf_chunk); - const auto leaf_parent_str = m_c2->to_string(leaf_parent_hash); + const Selene::Point leaf_parent_hash = get_new_parent(m_c1, leaf_chunk); + const auto leaf_parent_str = m_c1->to_string(leaf_parent_hash); // Make sure leaf chunk hash is present in first c2_layer - const auto &first_c2_layer = c2_layers.front(); + const auto &first_c1_layer = c1_layers.front(); found = false; - MDEBUG("Looking for leaf chunk hash: " << leaf_parent_str << " among " << first_c2_layer.size() << " hashes"); - for (std::size_t i = 0; !found && i < first_c2_layer.size(); ++i) + MDEBUG("Looking for leaf chunk hash: " << leaf_parent_str << " among " << first_c1_layer.size() << " hashes"); + for (std::size_t i = 0; !found && i < first_c1_layer.size(); ++i) { - MDEBUG("Reading: " << m_c2->to_string(first_c2_layer[i])); - found = (leaf_parent_str == m_c2->to_string(first_c2_layer[i])); + MDEBUG("Reading: " << m_c1->to_string(first_c1_layer[i])); + found = (leaf_parent_str == m_c1->to_string(first_c1_layer[i])); } CHECK_AND_ASSERT_MES(found, false, "did not find leaf chunk hash"); // If there are no more layers to audit, we're done - if (c2_layers.size() == 1 && c1_layers.empty()) + if (c1_layers.size() == 1 && c2_layers.empty()) { // We must have encountered the root - CHECK_AND_ASSERT_MES(c2_layers.front().size() == 1, false, "expected to encounter c2 root"); + CHECK_AND_ASSERT_MES(c1_layers.front().size() == 1, false, "expected to encounter c1 root"); return true; } // Continue hashing every layer chunk until there are no more layers - bool parent_is_c1 = true; + bool parent_is_c2 = true; std::size_t c1_idx = 0, c2_idx = 0; for (std::size_t i = 0; i < n_layers; ++i) { @@ -1303,12 +1303,43 @@ bool CurveTrees::audit_path(const CurveTrees::Pa auto &c2_layer = c2_layers[c2_idx]; // TODO: template - if (parent_is_c1) + if (parent_is_c2) + { + MDEBUG("Layer " << i << " has " << c1_layer.size() << " elems"); + + // Collect c2 scalars so we can hash them + std::vector c2_scalars; + c2_scalars.reserve(c1_layer.size()); + for (auto &c1_point : c1_layer) + c2_scalars.emplace_back(m_c1->point_to_cycle_scalar(c1_point)); + + // Hash c2 scalars + const Helios::Chunk chunk{c2_scalars.data(), c2_scalars.size()}; + const Helios::Point hash = get_new_parent(m_c2, chunk); + const auto hash_str = m_c2->to_string(hash); + + // Make sure hash is present in c2 layer + MDEBUG("Looking for c2 hash: " << hash_str << " among " << c2_layer.size() << " hashes"); + found = false; + for (std::size_t j = 0; !found && j < c2_layer.size(); ++j) + { + MDEBUG("Reading: " << m_c2->to_string(c2_layer[j])); + found = (hash_str == m_c2->to_string(c2_layer[j])); + } + CHECK_AND_ASSERT_MES(found, false, "did not find c2 hash"); + + // Check if we have encountered the root + if (c2_layer.size() == 1 && (c1_idx + 1) >= c1_layers.size() && (c2_idx + 1) >= c2_layers.size()) + break; + + ++c1_idx; + } + else { MDEBUG("Layer " << i << " has " << c2_layer.size() << " elems"); // Collect c1 scalars so we can hash them - std::vector c1_scalars; + std::vector c1_scalars; c1_scalars.reserve(c2_layer.size()); for (auto &c2_point : c2_layer) { @@ -1317,8 +1348,8 @@ bool CurveTrees::audit_path(const CurveTrees::Pa } // Hash c1 scalars - const Helios::Chunk chunk{c1_scalars.data(), c1_scalars.size()}; - const Helios::Point hash = get_new_parent(m_c1, chunk); + const Selene::Chunk chunk{c1_scalars.data(), c1_scalars.size()}; + const Selene::Point hash = get_new_parent(m_c1, chunk); const auto hash_str = m_c1->to_string(hash); // Make sure hash is present in c1 layer @@ -1337,39 +1368,8 @@ bool CurveTrees::audit_path(const CurveTrees::Pa ++c2_idx; } - else - { - MDEBUG("Layer " << i << " has " << c1_layer.size() << " elems"); - - // Collect c2 scalars so we can hash them - std::vector c2_scalars; - c2_scalars.reserve(c1_layer.size()); - for (auto &c1_point : c1_layer) - c2_scalars.emplace_back(m_c1->point_to_cycle_scalar(c1_point)); - - // Hash c2 scalars - const Selene::Chunk chunk{c2_scalars.data(), c2_scalars.size()}; - const Selene::Point hash = get_new_parent(m_c2, chunk); - const auto hash_str = m_c2->to_string(hash); - - // Make sure hash is present in c2 layer - MDEBUG("Looking for c2 hash: " << hash_str << " among " << c2_layer.size() << " hashes"); - found = false; - for (std::size_t j = 0; !found && j < c2_layer.size(); ++j) - { - MDEBUG("Reading: " << m_c2->to_string(c2_layer[j])); - found = (hash_str == m_c2->to_string(c2_layer[j])); - } - CHECK_AND_ASSERT_MES(found, false, "did not find c2 hash"); - - // Check if we have encountered the root - if (c2_layer.size() == 1 && (c1_idx + 1) >= c1_layers.size() && (c2_idx + 1) >= c2_layers.size()) - break; - - ++c1_idx; - } - parent_is_c1 = !parent_is_c1; + parent_is_c2 = !parent_is_c2; } return true; @@ -1379,69 +1379,68 @@ template typename CurveTrees::LastChunkChildrenForTrim CurveTrees::last_chunk_children_from_path_bytes( const PathBytes &path_bytes) const { - LastChunkChildrenForTrim last_chunk_children_for_trim; + LastChunkChildrenForTrim last_chunk_children_for_trim; - auto &c1_last_children_out = last_chunk_children_for_trim.c1_children; - auto &c2_last_children_out = last_chunk_children_for_trim.c2_children; + auto &c1_last_children_out = last_chunk_children_for_trim.c1_children; + auto &c2_last_children_out = last_chunk_children_for_trim.c2_children; - // Get the leaves as C2 scalars - { - std::vector leaves_to_trim; - for (const auto &output_context : path_bytes.leaves) + // Get the leaves as C1 scalars { - auto leaf = this->leaf_tuple(output_context.output_pair); + std::vector leaves_to_trim; + for (const auto &output_context : path_bytes.leaves) + { + auto leaf = this->leaf_tuple(output_context.output_pair); - leaves_to_trim.emplace_back(std::move(leaf.O_x)); - leaves_to_trim.emplace_back(std::move(leaf.I_x)); - leaves_to_trim.emplace_back(std::move(leaf.C_x)); - } - c2_last_children_out.emplace_back(std::move(leaves_to_trim)); - } - - // Get the layer elems - bool parent_is_c1 = true; - for (const auto &layer_chunk : path_bytes.layer_chunks) - { - if (parent_is_c1) - { - std::vector c1_children; - for (const auto &c2_child : layer_chunk.chunk_bytes) - { - const auto point = m_c2->from_bytes(c2_child); - auto child_scalar = m_c2->point_to_cycle_scalar(point); - c1_children.emplace_back(std::move(child_scalar)); - } - c1_last_children_out.emplace_back(std::move(c1_children)); + leaves_to_trim.emplace_back(std::move(leaf.O_x)); + leaves_to_trim.emplace_back(std::move(leaf.I_x)); + leaves_to_trim.emplace_back(std::move(leaf.C_x)); + } + c1_last_children_out.emplace_back(std::move(leaves_to_trim)); } - else + + // Get the layer elems + bool parent_is_c2 = true; + for (const auto &layer_chunk : path_bytes.layer_chunks) { - std::vector c2_children; - for (const auto &c1_child : layer_chunk.chunk_bytes) - { - const auto point = m_c1->from_bytes(c1_child); - auto child_scalar = m_c1->point_to_cycle_scalar(point); - c2_children.emplace_back(std::move(child_scalar)); - } - c2_last_children_out.emplace_back(std::move(c2_children)); + if (parent_is_c2) + { + std::vector c2_children; + for (const auto &c1_child : layer_chunk.chunk_bytes) + { + const auto point = m_c1->from_bytes(c1_child); + auto child_scalar = m_c1->point_to_cycle_scalar(point); + c2_children.emplace_back(std::move(child_scalar)); + } + c2_last_children_out.emplace_back(std::move(c2_children)); + } + else + { + std::vector c1_children; + for (const auto &c2_child : layer_chunk.chunk_bytes) + { + const auto point = m_c2->from_bytes(c2_child); + auto child_scalar = m_c2->point_to_cycle_scalar(point); + c1_children.emplace_back(std::move(child_scalar)); + } + c1_last_children_out.emplace_back(std::move(c1_children)); + } + parent_is_c2 = !parent_is_c2; } - parent_is_c1 = !parent_is_c1; - } - - return last_chunk_children_for_trim; + return last_chunk_children_for_trim; } // Explicit instantiation template -CurveTrees::LastChunkChildrenForTrim -CurveTrees::last_chunk_children_from_path_bytes(const PathBytes &path_bytes) const; +CurveTrees::LastChunkChildrenForTrim +CurveTrees::last_chunk_children_from_path_bytes(const PathBytes &path_bytes) const; //---------------------------------------------------------------------------------------------------------------------- //---------------------------------------------------------------------------------------------------------------------- // CurveTrees private member functions //---------------------------------------------------------------------------------------------------------------------- template void CurveTrees::set_valid_leaves( - std::vector &flattened_leaves_out, + std::vector &flattened_leaves_out, std::vector &tuples_out, std::vector &&new_outputs) { @@ -1624,7 +1623,7 @@ void CurveTrees::set_valid_leaves( template GrowLayerInstructions CurveTrees::set_next_layer_extension( const GrowLayerInstructions &prev_layer_instructions, - const bool parent_is_c1, + const bool parent_is_c2, const LastHashes &last_hashes, std::size_t &c1_last_idx_inout, std::size_t &c2_last_idx_inout, @@ -1636,7 +1635,7 @@ GrowLayerInstructions CurveTrees::set_next_layer_extension( auto &c1_layer_extensions_out = tree_extension_inout.c1_layer_extensions; auto &c2_layer_extensions_out = tree_extension_inout.c2_layer_extensions; - const std::size_t parent_chunk_width = parent_is_c1 ? m_c1_width : m_c2_width; + const std::size_t parent_chunk_width = parent_is_c2 ? m_c2_width : m_c1_width; const auto grow_layer_instructions = get_grow_layer_instructions( prev_layer_instructions.old_total_parents, @@ -1645,23 +1644,7 @@ GrowLayerInstructions CurveTrees::set_next_layer_extension( prev_layer_instructions.need_old_last_parent ); - if (parent_is_c1) - { - auto c1_layer_extension = get_next_layer_extension( - m_c2, - m_c1, - grow_layer_instructions, - c2_last_hashes, - c1_last_hashes, - c2_layer_extensions_out, - c2_last_idx_inout, - c1_last_idx_inout - ); - - c1_layer_extensions_out.emplace_back(std::move(c1_layer_extension)); - ++c2_last_idx_inout; - } - else + if (parent_is_c2) { auto c2_layer_extension = get_next_layer_extension( m_c1, @@ -1677,6 +1660,22 @@ GrowLayerInstructions CurveTrees::set_next_layer_extension( c2_layer_extensions_out.emplace_back(std::move(c2_layer_extension)); ++c1_last_idx_inout; } + else + { + auto c1_layer_extension = get_next_layer_extension( + m_c2, + m_c1, + grow_layer_instructions, + c2_last_hashes, + c1_last_hashes, + c2_layer_extensions_out, + c2_last_idx_inout, + c1_last_idx_inout + ); + + c1_layer_extensions_out.emplace_back(std::move(c1_layer_extension)); + ++c2_last_idx_inout; + } return grow_layer_instructions; }; diff --git a/src/fcmp_pp/curve_trees.h b/src/fcmp_pp/curve_trees.h index 2135148e1a..09a2c704ad 100644 --- a/src/fcmp_pp/curve_trees.h +++ b/src/fcmp_pp/curve_trees.h @@ -250,7 +250,7 @@ OutputTuple output_to_tuple(const OutputPair &output_pair); //---------------------------------------------------------------------------------------------------------------------- // This class is useful to help update the curve trees merkle tree without needing to keep the entire tree in memory // - It requires instantiation with the C1 and C2 curve classes and widths, hardening the tree structure -// - It ties the C2 curve in the tree to the leaf layer (the leaf layer is composed of C2 scalars) +// - It ties the C1 curve in the tree to the leaf layer (the leaf layer is composed of C1 scalars) template class CurveTrees { @@ -263,7 +263,7 @@ class CurveTrees m_c2{std::move(c2)}, m_c1_width{c1_width}, m_c2_width{c2_width}, - m_leaf_layer_chunk_width{LEAF_TUPLE_SIZE * c2_width} + m_leaf_layer_chunk_width{LEAF_TUPLE_SIZE * c1_width} { assert(c1_width > 0); assert(c2_width > 0); @@ -275,14 +275,14 @@ class CurveTrees struct LeafTuple final { // Output ed25519 point x-coordinate - typename C2::Scalar O_x; + typename C1::Scalar O_x; // Key image generator x-coordinate - typename C2::Scalar I_x; + typename C1::Scalar I_x; // Commitment x-coordinate - typename C2::Scalar C_x; + typename C1::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"); + static_assert(sizeof(LeafTuple) == (sizeof(typename C1::Scalar) * LEAF_TUPLE_SIZE), "unexpected LeafTuple size"); // Contiguous leaves in the tree, starting a specified start_idx in the leaf layer struct Leaves final @@ -295,7 +295,7 @@ class CurveTrees // A struct useful to extend an existing tree // - layers alternate between C1 and C2 - // - c2_layer_extensions[0] is first layer after leaves, then c1_layer_extensions[0], c2_layer_extensions[1], etc + // - c1_layer_extensions[0] is first layer after leaves, then c2_layer_extensions[0], c1_layer_extensions[1], etc struct TreeExtension final { Leaves leaves; @@ -305,7 +305,7 @@ class CurveTrees // A struct useful to reduce the number of leaves in an existing tree // - layers alternate between C1 and C2 - // - c2_layer_reductions[0] is first layer after leaves, then c1_layer_reductions[0], c2_layer_reductions[1], etc + // - c1_layer_reductions[0] is first layer after leaves, then c2_layer_reductions[0], c1_layer_reductions[1], etc struct TreeReduction final { uint64_t new_total_leaf_tuples{0}; @@ -316,7 +316,7 @@ class CurveTrees // Last hashes from each layer in the tree // - layers alternate between C1 and C2 - // - c2_last_hashes[0] refers to the layer after leaves, then c1_last_hashes[0], then c2_last_hashes[1], etc + // - c1_last_hashes[0] refers to the layer after leaves, then c2_last_hashes[0], then c1_last_hashes[1], etc struct LastHashes final { std::vector c1_last_hashes; @@ -325,7 +325,7 @@ class CurveTrees // The children we'll trim from each last chunk in the tree // - layers alternate between C1 and C2 - // - c2_children[0] refers to the layer after leaves, then c1_children[0], then c2_children[1], etc + // - c1_children[0] refers to the layer after leaves, then c2_children[0], then c1_children[1], etc struct LastChunkChildrenForTrim final { std::vector> c1_children; @@ -334,13 +334,13 @@ class CurveTrees // A path in the tree containing whole chunks at each layer // - leaves contain a complete chunk of leaves, encoded as compressed ed25519 points - // - c2_layers[0] refers to the chunk of elems in the tree in the layer after leaves. The hash of the chunk of - // leaves is 1 member of the c2_layers[0] chunk. The rest of c2_layers[0] is the chunk of elems that hash is in. + // - c1_layers[0] refers to the chunk of elems in the tree in the layer after leaves. The hash of the chunk of + // leaves is 1 member of the c1_layers[0] chunk. The rest of c1_layers[0] is the chunk of elems that hash is in. // - layers alternate between C1 and C2 - // - c1_layers[0] refers to the chunk of elems in the tree in the layer after c2_layers[0]. The hash of the chunk - // of c2_layers[0] is 1 member of the c1_layers[0] chunk. The rest of c1_layers[0] is the chunk of elems that hash + // - c2_layers[0] refers to the chunk of elems in the tree in the layer after c1_layers[0]. The hash of the chunk + // of c1_layers[0] is 1 member of the c2_layers[0] chunk. The rest of c2_layers[0] is the chunk of elems that hash // is in. - // - c2_layers[1] refers to the chunk of elems in the tree in the layer after c1_layers[0] etc. + // - c1_layers[1] refers to the chunk of elems in the tree in the layer after c2_layers[0] etc. struct Path final { std::vector leaves; @@ -363,7 +363,7 @@ class CurveTrees LeafTuple leaf_tuple(const OutputPair &output_pair) const; // Flatten leaves [(O.x, I.x, C.x),(O.x, I.x, C.x),...] -> [O.x, I.x, C.x, O.x, I.x, C.x...] - std::vector flatten_leaves(std::vector &&leaves) const; + std::vector flatten_leaves(std::vector &&leaves) const; // Take in the existing number of leaf tuples and the existing last hash in each layer in the tree, as well as new // outputs to add to the tree, and return a tree extension struct that can be used to extend a tree @@ -404,7 +404,7 @@ class CurveTrees private: // Multithreaded helper function to convert outputs to leaf tuples and set leaves on tree extension void set_valid_leaves( - std::vector &flattened_leaves_out, + std::vector &flattened_leaves_out, std::vector &tuples_out, std::vector &&new_outputs); @@ -445,18 +445,18 @@ class CurveTrees const std::size_t m_c2_width; }; //---------------------------------------------------------------------------------------------------------------------- -using Helios = tower_cycle::Helios; using Selene = tower_cycle::Selene; -using CurveTreesV1 = CurveTrees; +using Helios = tower_cycle::Helios; +using CurveTreesV1 = CurveTrees; // https://github.com/kayabaNerve/fcmp-plus-plus/blob // /b2742e86f3d18155fd34dd1ed69cb8f79b900fce/crypto/fcmps/src/tests.rs#L81-L82 -const std::size_t HELIOS_CHUNK_WIDTH = 38; -const std::size_t SELENE_CHUNK_WIDTH = 18; +const std::size_t SELENE_CHUNK_WIDTH = 38; +const std::size_t HELIOS_CHUNK_WIDTH = 18; std::shared_ptr curve_trees_v1( - const std::size_t helios_chunk_width = HELIOS_CHUNK_WIDTH, - const std::size_t selene_chunk_width = SELENE_CHUNK_WIDTH); + const std::size_t selene_chunk_width = SELENE_CHUNK_WIDTH, + const std::size_t helios_chunk_width = HELIOS_CHUNK_WIDTH); //---------------------------------------------------------------------------------------------------------------------- //---------------------------------------------------------------------------------------------------------------------- } //namespace curve_trees diff --git a/src/fcmp_pp/fcmp_pp_rust/fcmp++.h b/src/fcmp_pp/fcmp_pp_rust/fcmp++.h index 151beab2de..62fff44216 100644 --- a/src/fcmp_pp/fcmp_pp_rust/fcmp++.h +++ b/src/fcmp_pp/fcmp_pp_rust/fcmp++.h @@ -186,8 +186,8 @@ CResult fcmp_prove_input_new(const uint8_t *x, const uint8_t *rerandomized_output, const uint8_t *path, const uint8_t *output_blinds, - Slicehelios_branch_blinds, - Sliceselene_branch_blinds); + Sliceselene_branch_blinds, + Slicehelios_branch_blinds); CResult prove(const uint8_t *signable_tx_hash, Slice fcmp_prove_inputs, diff --git a/src/fcmp_pp/fcmp_pp_rust/src/lib.rs b/src/fcmp_pp/fcmp_pp_rust/src/lib.rs index 4c1ac56bdc..f30472c986 100644 --- a/src/fcmp_pp/fcmp_pp_rust/src/lib.rs +++ b/src/fcmp_pp/fcmp_pp_rust/src/lib.rs @@ -35,6 +35,7 @@ use monero_generators::{FCMP_U, FCMP_V, T}; // TODO: don't use CResult for types the FFI supports (e.g. SelenePoint, SeleneScalar), don't want the raw * because need to manually from_raw it to dealloc // TODO: Use a macro to de-duplicate some of of this code // TODO: Don't unwrap anywhere and populate the CResult error type in all fn's +// TODO: repalce asserts with error returns where reasonable //-------------------------------------------------------------------------------------- Curve points @@ -569,8 +570,8 @@ pub unsafe extern "C" fn fcmp_prove_input_new( rerandomized_output: *const RerandomizedOutput, path: *const Path, output_blinds: *const OutputBlinds, - helios_branch_blinds: HeliosBranchBlindSlice, selene_branch_blinds: SeleneBranchBlindSlice, + helios_branch_blinds: HeliosBranchBlindSlice, ) -> CResult { // SAL let x = ed25519_scalar_from_bytes(x); @@ -637,16 +638,17 @@ pub unsafe extern "C" fn prove( let x = sal_input.x; let y = sal_input.y; + assert_eq!( + prove_input.path.output.O(), + EdwardsPoint((*x * *EdwardsPoint::generator()) + (*y * *EdwardsPoint(T()))) + ); + let input = rerandomized_output.input(); let opening = OpenedInputTuple::open(rerandomized_output.clone(), &x, &y).unwrap(); let (key_image, spend_auth_and_linkability) = SpendAuthAndLinkability::prove(&mut OsRng, signable_tx_hash, opening); - assert_eq!( - prove_input.path.output.O(), - EdwardsPoint((*x * *EdwardsPoint::generator()) + (*y * *EdwardsPoint(T()))) - ); assert_eq!(prove_input.path.output.I() * x, key_image); (input, spend_auth_and_linkability) diff --git a/src/fcmp_pp/tower_cycle.cpp b/src/fcmp_pp/tower_cycle.cpp index 9f69cd42aa..8f322c6e89 100644 --- a/src/fcmp_pp/tower_cycle.cpp +++ b/src/fcmp_pp/tower_cycle.cpp @@ -35,19 +35,14 @@ namespace tower_cycle { //---------------------------------------------------------------------------------------------------------------------- //---------------------------------------------------------------------------------------------------------------------- -Helios::Point Helios::hash_init_point() const -{ - return fcmp_pp_rust::helios_hash_init_point(); -} -//---------------------------------------------------------------------------------------------------------------------- Selene::Point Selene::hash_init_point() const { return fcmp_pp_rust::selene_hash_init_point(); } //---------------------------------------------------------------------------------------------------------------------- -Helios::CycleScalar Helios::point_to_cycle_scalar(const Helios::Point &point) const +Helios::Point Helios::hash_init_point() const { - return fcmp_pp_rust::helios_point_to_selene_scalar(point); + return fcmp_pp_rust::helios_hash_init_point(); } //---------------------------------------------------------------------------------------------------------------------- Selene::CycleScalar Selene::point_to_cycle_scalar(const Selene::Point &point) const @@ -55,13 +50,18 @@ Selene::CycleScalar Selene::point_to_cycle_scalar(const Selene::Point &point) co return fcmp_pp_rust::selene_point_to_helios_scalar(point); } //---------------------------------------------------------------------------------------------------------------------- -Helios::Point Helios::hash_grow( - const Helios::Point &existing_hash, +Helios::CycleScalar Helios::point_to_cycle_scalar(const Helios::Point &point) const +{ + return fcmp_pp_rust::helios_point_to_selene_scalar(point); +} +//---------------------------------------------------------------------------------------------------------------------- +Selene::Point Selene::hash_grow( + const Selene::Point &existing_hash, const std::size_t offset, - const Helios::Scalar &existing_child_at_offset, - const Helios::Chunk &new_children) const + const Selene::Scalar &existing_child_at_offset, + const Selene::Chunk &new_children) const { - auto result = fcmp_pp_rust::hash_grow_helios( + auto result = fcmp_pp_rust::hash_grow_selene( existing_hash, offset, existing_child_at_offset, @@ -73,19 +73,19 @@ Helios::Point Helios::hash_grow( throw std::runtime_error("failed to hash grow"); } - typename Helios::Point res; - memcpy(&res, result.value, sizeof(typename Helios::Point)); + typename Selene::Point res; + memcpy(&res, result.value, sizeof(typename Selene::Point)); free(result.value); return res; } //---------------------------------------------------------------------------------------------------------------------- -Helios::Point Helios::hash_trim( - const Helios::Point &existing_hash, +Selene::Point Selene::hash_trim( + const Selene::Point &existing_hash, const std::size_t offset, - const Helios::Chunk &children, - const Helios::Scalar &child_to_grow_back) const + const Selene::Chunk &children, + const Selene::Scalar &child_to_grow_back) const { - auto result = fcmp_pp_rust::hash_trim_helios( + auto result = fcmp_pp_rust::hash_trim_selene( existing_hash, offset, children, @@ -97,19 +97,19 @@ Helios::Point Helios::hash_trim( throw std::runtime_error("failed to hash trim"); } - typename Helios::Point res; - memcpy(&res, result.value, sizeof(typename Helios::Point)); + typename Selene::Point res; + memcpy(&res, result.value, sizeof(typename Selene::Point)); free(result.value); return res; } //---------------------------------------------------------------------------------------------------------------------- -Selene::Point Selene::hash_grow( - const Selene::Point &existing_hash, +Helios::Point Helios::hash_grow( + const Helios::Point &existing_hash, const std::size_t offset, - const Selene::Scalar &existing_child_at_offset, - const Selene::Chunk &new_children) const + const Helios::Scalar &existing_child_at_offset, + const Helios::Chunk &new_children) const { - auto result = fcmp_pp_rust::hash_grow_selene( + auto result = fcmp_pp_rust::hash_grow_helios( existing_hash, offset, existing_child_at_offset, @@ -121,19 +121,19 @@ Selene::Point Selene::hash_grow( throw std::runtime_error("failed to hash grow"); } - typename Selene::Point res; - memcpy(&res, result.value, sizeof(typename Selene::Point)); + typename Helios::Point res; + memcpy(&res, result.value, sizeof(typename Helios::Point)); free(result.value); return res; } //---------------------------------------------------------------------------------------------------------------------- -Selene::Point Selene::hash_trim( - const Selene::Point &existing_hash, +Helios::Point Helios::hash_trim( + const Helios::Point &existing_hash, const std::size_t offset, - const Selene::Chunk &children, - const Selene::Scalar &child_to_grow_back) const + const Helios::Chunk &children, + const Helios::Scalar &child_to_grow_back) const { - auto result = fcmp_pp_rust::hash_trim_selene( + auto result = fcmp_pp_rust::hash_trim_helios( existing_hash, offset, children, @@ -145,29 +145,20 @@ Selene::Point Selene::hash_trim( throw std::runtime_error("failed to hash trim"); } - typename Selene::Point res; - memcpy(&res, result.value, sizeof(typename Selene::Point)); + typename Helios::Point res; + memcpy(&res, result.value, sizeof(typename Helios::Point)); free(result.value); return res; } //---------------------------------------------------------------------------------------------------------------------- -Helios::Scalar Helios::zero_scalar() const -{ - return fcmp_pp_rust::helios_zero_scalar(); -} -//---------------------------------------------------------------------------------------------------------------------- Selene::Scalar Selene::zero_scalar() const { return fcmp_pp_rust::selene_zero_scalar(); } //---------------------------------------------------------------------------------------------------------------------- -crypto::ec_scalar Helios::to_bytes(const Helios::Scalar &scalar) const +Helios::Scalar Helios::zero_scalar() const { - auto bytes = fcmp_pp_rust::helios_scalar_to_bytes(scalar); - crypto::ec_scalar res; - memcpy(&res, bytes, 32); - free(bytes); - return res; + return fcmp_pp_rust::helios_zero_scalar(); } //---------------------------------------------------------------------------------------------------------------------- crypto::ec_scalar Selene::to_bytes(const Selene::Scalar &scalar) const @@ -179,10 +170,10 @@ crypto::ec_scalar Selene::to_bytes(const Selene::Scalar &scalar) const return res; } //---------------------------------------------------------------------------------------------------------------------- -crypto::ec_point Helios::to_bytes(const Helios::Point &point) const +crypto::ec_scalar Helios::to_bytes(const Helios::Scalar &scalar) const { - auto bytes = fcmp_pp_rust::helios_point_to_bytes(point); - crypto::ec_point res; + auto bytes = fcmp_pp_rust::helios_scalar_to_bytes(scalar); + crypto::ec_scalar res; memcpy(&res, bytes, 32); free(bytes); return res; @@ -197,9 +188,13 @@ crypto::ec_point Selene::to_bytes(const Selene::Point &point) const return res; } //---------------------------------------------------------------------------------------------------------------------- -Helios::Point Helios::from_bytes(const crypto::ec_point &bytes) const +crypto::ec_point Helios::to_bytes(const Helios::Point &point) const { - return fcmp_pp_rust::helios_point_from_bytes(reinterpret_cast(&bytes)); + auto bytes = fcmp_pp_rust::helios_point_to_bytes(point); + crypto::ec_point res; + memcpy(&res, bytes, 32); + free(bytes); + return res; } //---------------------------------------------------------------------------------------------------------------------- Selene::Point Selene::from_bytes(const crypto::ec_point &bytes) const @@ -207,9 +202,9 @@ Selene::Point Selene::from_bytes(const crypto::ec_point &bytes) const return fcmp_pp_rust::selene_point_from_bytes(reinterpret_cast(&bytes)); } //---------------------------------------------------------------------------------------------------------------------- -std::string Helios::to_string(const typename Helios::Scalar &scalar) const +Helios::Point Helios::from_bytes(const crypto::ec_point &bytes) const { - return epee::string_tools::pod_to_hex(this->to_bytes(scalar)); + return fcmp_pp_rust::helios_point_from_bytes(reinterpret_cast(&bytes)); } //---------------------------------------------------------------------------------------------------------------------- std::string Selene::to_string(const typename Selene::Scalar &scalar) const @@ -217,9 +212,9 @@ std::string Selene::to_string(const typename Selene::Scalar &scalar) const return epee::string_tools::pod_to_hex(this->to_bytes(scalar)); } //---------------------------------------------------------------------------------------------------------------------- -std::string Helios::to_string(const typename Helios::Point &point) const +std::string Helios::to_string(const typename Helios::Scalar &scalar) const { - return epee::string_tools::pod_to_hex(this->to_bytes(point)); + return epee::string_tools::pod_to_hex(this->to_bytes(scalar)); } //---------------------------------------------------------------------------------------------------------------------- std::string Selene::to_string(const typename Selene::Point &point) const @@ -227,6 +222,11 @@ std::string Selene::to_string(const typename Selene::Point &point) const return epee::string_tools::pod_to_hex(this->to_bytes(point)); } //---------------------------------------------------------------------------------------------------------------------- +std::string Helios::to_string(const typename Helios::Point &point) const +{ + return epee::string_tools::pod_to_hex(this->to_bytes(point)); +} +//---------------------------------------------------------------------------------------------------------------------- //---------------------------------------------------------------------------------------------------------------------- // Exposed helper functions //---------------------------------------------------------------------------------------------------------------------- @@ -373,15 +373,15 @@ uint8_t *output_blinds_new(const uint8_t *blinded_o_blind, return handle_res_ptr(__func__, res); } -uint8_t *helios_branch_blind() +uint8_t *selene_branch_blind() { - const auto res = fcmp_pp_rust::helios_branch_blind(); + const auto res = fcmp_pp_rust::selene_branch_blind(); return handle_res_ptr(__func__, res); } -uint8_t *selene_branch_blind() +uint8_t *helios_branch_blind() { - const auto res = fcmp_pp_rust::selene_branch_blind(); + const auto res = fcmp_pp_rust::helios_branch_blind(); return handle_res_ptr(__func__, res); } @@ -390,16 +390,16 @@ uint8_t *fcmp_prove_input_new(const uint8_t *x, const uint8_t *rerandomized_output, const uint8_t *path, const uint8_t *output_blinds, - const std::vector &helios_branch_blinds, - const std::vector &selene_branch_blinds) + const std::vector &selene_branch_blinds, + const std::vector &helios_branch_blinds) { auto res = fcmp_pp_rust::fcmp_prove_input_new(x, y, rerandomized_output, path, output_blinds, - {helios_branch_blinds.data(), helios_branch_blinds.size()}, - {selene_branch_blinds.data(), selene_branch_blinds.size()}); + {selene_branch_blinds.data(), selene_branch_blinds.size()}, + {helios_branch_blinds.data(), helios_branch_blinds.size()}); return handle_res_ptr(__func__, res); } diff --git a/src/fcmp_pp/tower_cycle.h b/src/fcmp_pp/tower_cycle.h index 3ec2f5e4c8..311587f116 100644 --- a/src/fcmp_pp/tower_cycle.h +++ b/src/fcmp_pp/tower_cycle.h @@ -49,15 +49,6 @@ using OutputChunk = fcmp_pp_rust::OutputSlice; using SeleneScalar = fcmp_pp_rust::SeleneScalar; using HeliosScalar = fcmp_pp_rust::HeliosScalar; //---------------------------------------------------------------------------------------------------------------------- -struct HeliosT final -{ - using Scalar = HeliosScalar; - using Point = fcmp_pp_rust::HeliosPoint; - using Chunk = fcmp_pp_rust::HeliosScalarSlice; - using CycleScalar = SeleneScalar; - using ScalarChunks = fcmp_pp_rust::HeliosScalarChunks; -}; -//---------------------------------------------------------------------------------------------------------------------- struct SeleneT final { using Scalar = SeleneScalar; @@ -67,6 +58,15 @@ struct SeleneT final using ScalarChunks = fcmp_pp_rust::SeleneScalarChunks; }; //---------------------------------------------------------------------------------------------------------------------- +struct HeliosT final +{ + using Scalar = HeliosScalar; + using Point = fcmp_pp_rust::HeliosPoint; + using Chunk = fcmp_pp_rust::HeliosScalarSlice; + using CycleScalar = SeleneScalar; + using ScalarChunks = fcmp_pp_rust::HeliosScalarChunks; +}; +//---------------------------------------------------------------------------------------------------------------------- //---------------------------------------------------------------------------------------------------------------------- // Abstract parent curve class that curves in a cycle must implement template @@ -102,15 +102,15 @@ class Curve virtual std::string to_string(const typename C::Point &point) const = 0; }; //---------------------------------------------------------------------------------------------------------------------- -class Helios final : public Curve +class Selene final : public Curve { //typedefs public: - using Scalar = HeliosT::Scalar; - using Point = HeliosT::Point; - using Chunk = HeliosT::Chunk; - using CycleScalar = HeliosT::CycleScalar; - using ScalarChunks = HeliosT::ScalarChunks; + using Scalar = SeleneT::Scalar; + using Point = SeleneT::Point; + using Chunk = SeleneT::Chunk; + using CycleScalar = SeleneT::CycleScalar; + using ScalarChunks = SeleneT::ScalarChunks; //member functions public: @@ -141,15 +141,15 @@ class Helios final : public Curve std::string to_string(const Point &point) const override; }; //---------------------------------------------------------------------------------------------------------------------- -class Selene final : public Curve +class Helios final : public Curve { //typedefs public: - using Scalar = SeleneT::Scalar; - using Point = SeleneT::Point; - using Chunk = SeleneT::Chunk; - using CycleScalar = SeleneT::CycleScalar; - using ScalarChunks = SeleneT::ScalarChunks; + using Scalar = HeliosT::Scalar; + using Point = HeliosT::Point; + using Chunk = HeliosT::Chunk; + using CycleScalar = HeliosT::CycleScalar; + using ScalarChunks = HeliosT::ScalarChunks; //member functions public: @@ -221,16 +221,16 @@ uint8_t *output_blinds_new(const uint8_t *blinded_o_blind, const uint8_t *blinded_i_blind_blind, const uint8_t *blinded_c_blind); -uint8_t *helios_branch_blind(); uint8_t *selene_branch_blind(); +uint8_t *helios_branch_blind(); uint8_t *fcmp_prove_input_new(const uint8_t *x, const uint8_t *y, const uint8_t *rerandomized_output, const uint8_t *path, const uint8_t *output_blinds, - const std::vector &helios_branch_blinds, - const std::vector &selene_branch_blinds); + const std::vector &selene_branch_blinds, + const std::vector &helios_branch_blinds); struct FcmpPpProof final { diff --git a/src/fcmp_pp/tree_sync_memory.cpp b/src/fcmp_pp/tree_sync_memory.cpp index 91b6c85228..a2d33f52b0 100644 --- a/src/fcmp_pp/tree_sync_memory.cpp +++ b/src/fcmp_pp/tree_sync_memory.cpp @@ -393,26 +393,26 @@ static void cache_path_chunks(const LeafIdx leaf_idx, CHECK_AND_ASSERT_THROW_MES(n_leaf_tuples > leaf_idx, "high leaf_idx"); - const ChildChunkIdx child_chunk_idx = leaf_idx / curve_trees->m_c2_width; - ChildChunkIdx parent_idx = child_chunk_idx / curve_trees->m_c1_width; + const ChildChunkIdx child_chunk_idx = leaf_idx / curve_trees->m_c1_width; + ChildChunkIdx parent_idx = child_chunk_idx / curve_trees->m_c2_width; const LeafIdx last_leaf_idx = n_leaf_tuples - 1; - const ChildChunkIdx last_chunk_idx = last_leaf_idx / curve_trees->m_c2_width; + const ChildChunkIdx last_chunk_idx = last_leaf_idx / curve_trees->m_c1_width; uint64_t n_layer_elems = last_chunk_idx + 1; - ChildChunkIdx last_parent_idx = last_chunk_idx / curve_trees->m_c1_width; + ChildChunkIdx last_parent_idx = last_chunk_idx / curve_trees->m_c2_width; std::size_t c1_idx = 0, c2_idx = 0; - bool parent_is_c1 = true; + bool parent_is_c2 = true; const std::size_t n_layers = curve_trees->n_layers(n_leaf_tuples); for (LayerIdx layer_idx = 0; layer_idx < n_layers; ++layer_idx) { MDEBUG("Caching tree elems from layer_idx " << layer_idx << " parent_idx " << parent_idx); - if (parent_is_c1) + if (parent_is_c2) { - cache_path_chunk(curve_trees->m_c2, - curve_trees->m_c1_width, - c2_layer_exts, - c2_idx, + cache_path_chunk(curve_trees->m_c1, + curve_trees->m_c2_width, + c1_layer_exts, + c1_idx, layer_idx, bump_ref_count, parent_idx, @@ -420,17 +420,17 @@ static void cache_path_chunks(const LeafIdx leaf_idx, tree_elem_cache_inout ); - parent_idx /= curve_trees->m_c2_width; + parent_idx /= curve_trees->m_c1_width; n_layer_elems = last_parent_idx + 1; - last_parent_idx /= curve_trees->m_c2_width; - ++c2_idx; + last_parent_idx /= curve_trees->m_c1_width; + ++c1_idx; } else { - cache_path_chunk(curve_trees->m_c1, - curve_trees->m_c2_width, - c1_layer_exts, - c1_idx, + cache_path_chunk(curve_trees->m_c2, + curve_trees->m_c1_width, + c2_layer_exts, + c2_idx, layer_idx, bump_ref_count, parent_idx, @@ -438,13 +438,13 @@ static void cache_path_chunks(const LeafIdx leaf_idx, tree_elem_cache_inout ); - parent_idx /= curve_trees->m_c1_width; + parent_idx /= curve_trees->m_c2_width; n_layer_elems = last_parent_idx + 1; - last_parent_idx /= curve_trees->m_c1_width; - ++c1_idx; + last_parent_idx /= curve_trees->m_c2_width; + ++c2_idx; } - parent_is_c1 = !parent_is_c1; + parent_is_c2 = !parent_is_c2; } } //---------------------------------------------------------------------------------------------------------------------- @@ -460,43 +460,43 @@ static void update_existing_last_hashes(const std::shared_ptr const auto &c1_layer_exts = tree_extension.c1_layer_extensions; const auto &c2_layer_exts = tree_extension.c2_layer_extensions; - const ChildChunkIdx child_chunk_idx = old_n_leaf_tuples / curve_trees->m_c2_width; - ChildChunkIdx last_parent_idx = child_chunk_idx / curve_trees->m_c1_width; + const ChildChunkIdx child_chunk_idx = old_n_leaf_tuples / curve_trees->m_c1_width; + ChildChunkIdx last_parent_idx = child_chunk_idx / curve_trees->m_c2_width; std::size_t c1_idx = 0, c2_idx = 0; - bool parent_is_c1 = true; + bool parent_is_c2 = true; const std::size_t n_layers = curve_trees->n_layers(old_n_leaf_tuples); for (LayerIdx layer_idx = 0; layer_idx < n_layers; ++layer_idx) { MDEBUG("Updating existing last hash from layer_idx " << layer_idx << " last_parent_idx " << last_parent_idx); - if (parent_is_c1) + if (parent_is_c2) { - update_last_hash(curve_trees->m_c2, - c2_layer_exts, - c2_idx, + update_last_hash(curve_trees->m_c1, + c1_layer_exts, + c1_idx, layer_idx, last_parent_idx, tree_elem_cache_inout ); - last_parent_idx /= curve_trees->m_c2_width; - ++c2_idx; + last_parent_idx /= curve_trees->m_c1_width; + ++c1_idx; } else { - update_last_hash(curve_trees->m_c1, - c1_layer_exts, - c1_idx, + update_last_hash(curve_trees->m_c2, + c2_layer_exts, + c2_idx, layer_idx, last_parent_idx, tree_elem_cache_inout ); - last_parent_idx /= curve_trees->m_c1_width; - ++c1_idx; + last_parent_idx /= curve_trees->m_c2_width; + ++c2_idx; } - parent_is_c1 = !parent_is_c1; + parent_is_c2 = !parent_is_c2; } } //---------------------------------------------------------------------------------------------------------------------- @@ -549,17 +549,17 @@ static void remove_path_chunks_refs(const LeafIdx leaf_idx, if (n_leaf_tuples == 0) return; - const ChildChunkIdx child_chunk_idx = leaf_idx / curve_trees->m_c2_width; - ChildChunkIdx parent_idx = child_chunk_idx / curve_trees->m_c1_width; + const ChildChunkIdx child_chunk_idx = leaf_idx / curve_trees->m_c1_width; + ChildChunkIdx parent_idx = child_chunk_idx / curve_trees->m_c2_width; const std::size_t n_layers = curve_trees->n_layers(n_leaf_tuples); - bool parent_is_c1 = true; + bool parent_is_c2 = true; for (LayerIdx layer_idx = 0; layer_idx < n_layers; ++layer_idx) { remove_path_chunk_ref(layer_idx, parent_idx, tree_elem_cache_inout); - parent_is_c1 = !parent_is_c1; - parent_idx /= parent_is_c1 ? curve_trees->m_c1_width : curve_trees->m_c2_width; + parent_is_c2 = !parent_is_c2; + parent_idx /= parent_is_c2 ? curve_trees->m_c2_width : curve_trees->m_c1_width; } } //---------------------------------------------------------------------------------------------------------------------- @@ -596,18 +596,18 @@ static void reduce_cached_last_chunks( return; const LeafIdx last_leaf_idx = n_leaf_tuples - 1; - ChildChunkIdx last_chunk_idx = last_leaf_idx / curve_trees->m_c2_width; + ChildChunkIdx last_chunk_idx = last_leaf_idx / curve_trees->m_c1_width; const auto &c1_layer_reductions = tree_reduction.c1_layer_reductions; const auto &c2_layer_reductions = tree_reduction.c2_layer_reductions; std::size_t c1_idx = 0, c2_idx = 0; - bool parent_is_c1 = true; - const std::size_t n_layers = c2_layer_reductions.size() + c1_layer_reductions.size(); + bool parent_is_c2 = true; + const std::size_t n_layers = c1_layer_reductions.size() + c2_layer_reductions.size(); for (LayerIdx layer_idx = 0; layer_idx < n_layers; ++layer_idx) { // TODO: separate templated function - const std::size_t parent_width = parent_is_c1 ? curve_trees->m_c1_width : curve_trees->m_c2_width; + const std::size_t parent_width = parent_is_c2 ? curve_trees->m_c2_width : curve_trees->m_c1_width; const ChildChunkIdx parent_idx = last_chunk_idx / parent_width; // Get the layer @@ -632,35 +632,36 @@ static void reduce_cached_last_chunks( cached_chunk_it->second.tree_elems.resize(new_chunk_size); // Update the last hash in the chunk if necessary - if (parent_is_c1) + if (parent_is_c2) { - CHECK_AND_ASSERT_THROW_MES(c2_layer_reductions.size() > c2_idx, "missing c2 layer reduction"); - const auto &c2_reduction = c2_layer_reductions[c2_idx]; + CHECK_AND_ASSERT_THROW_MES(c1_layer_reductions.size() > c1_idx, "missing c1 layer reduction"); + const auto &c1_reduction = c1_layer_reductions[c1_idx]; - if (c2_reduction.update_existing_last_hash) + if (c1_reduction.update_existing_last_hash) { - auto tree_elem = curve_trees->m_c2->to_bytes(c2_reduction.new_last_hash); + auto tree_elem = curve_trees->m_c1->to_bytes(c1_reduction.new_last_hash); cached_chunk_it->second.tree_elems.back() = std::move(tree_elem); } - ++c2_idx; + ++c1_idx; + } else { - CHECK_AND_ASSERT_THROW_MES(c1_layer_reductions.size() > c1_idx, "missing c1 layer reduction"); - const auto &c1_reduction = c1_layer_reductions[c1_idx]; + CHECK_AND_ASSERT_THROW_MES(c2_layer_reductions.size() > c2_idx, "missing c2 layer reduction"); + const auto &c2_reduction = c2_layer_reductions[c2_idx]; - if (c1_reduction.update_existing_last_hash) + if (c2_reduction.update_existing_last_hash) { - auto tree_elem = curve_trees->m_c1->to_bytes(c1_reduction.new_last_hash); + auto tree_elem = curve_trees->m_c2->to_bytes(c2_reduction.new_last_hash); cached_chunk_it->second.tree_elems.back() = std::move(tree_elem); } - ++c1_idx; + ++c2_idx; } last_chunk_idx = parent_idx; - parent_is_c1 = !parent_is_c1; + parent_is_c2 = !parent_is_c2; } } //---------------------------------------------------------------------------------------------------------------------- @@ -681,8 +682,8 @@ static void update_registered_path(const std::shared_ptr> &cu const bool bump_ref_count = leaf_idx >= start_leaf_tuple_idx && leaf_idx < n_leaf_tuples; // Cache registered leaf's chunk - cache_leaf_chunk(leaf_idx / curve_trees->m_c2_width, - curve_trees->m_c2_width, + cache_leaf_chunk(leaf_idx / curve_trees->m_c1_width, + curve_trees->m_c1_width, tree_extension.leaves, start_leaf_tuple_idx, n_leaf_tuples, @@ -715,13 +716,13 @@ static void cache_last_chunk_leaves(const std::shared_ptr> &c return; const LeafIdx last_leaf_idx = n_leaf_tuples - 1; - const ChildChunkIdx chunk_idx = last_leaf_idx / curve_trees->m_c2_width; + const ChildChunkIdx chunk_idx = last_leaf_idx / curve_trees->m_c1_width; // Always bump the ref count for last chunk of leaves so that it sticks around until pruned const bool bump_ref_count = true; cache_leaf_chunk(chunk_idx, - curve_trees->m_c2_width, + curve_trees->m_c1_width, leaves, start_leaf_tuple_idx, n_leaf_tuples, @@ -814,7 +815,7 @@ bool TreeSyncMemory::register_output(const OutputPair &output, const uin } // Explicit instantiation -template bool TreeSyncMemory::register_output(const OutputPair &output, const uint64_t unlock_block_idx); +template bool TreeSyncMemory::register_output(const OutputPair &output, const uint64_t unlock_block_idx); //---------------------------------------------------------------------------------------------------------------------- template void TreeSyncMemory::sync_block(const uint64_t block_idx, @@ -839,7 +840,7 @@ void TreeSyncMemory::sync_block(const uint64_t block_idx, } // Explicit instantiation -template void TreeSyncMemory::sync_block(const uint64_t block_idx, +template void TreeSyncMemory::sync_block(const uint64_t block_idx, const crypto::hash &block_hash, const crypto::hash &prev_block_hash, const fcmp_pp::curve_trees::OutputsByUnlockBlock &outs_by_unlock_block); @@ -963,11 +964,11 @@ void TreeSyncMemory::sync_blocks(const uint64_t start_block_idx, } // Explicit instantiation -template void TreeSyncMemory::sync_blocks(const uint64_t start_block_idx, +template void TreeSyncMemory::sync_blocks(const uint64_t start_block_idx, const crypto::hash &prev_block_hash, const std::vector &new_block_hashes, const std::vector &outs_by_unlock_blocks, - typename fcmp_pp::curve_trees::CurveTrees::TreeExtension &tree_extension_out, + typename fcmp_pp::curve_trees::CurveTrees::TreeExtension &tree_extension_out, std::vector &n_new_leaf_tuples_per_block_out); //---------------------------------------------------------------------------------------------------------------------- template @@ -1101,9 +1102,9 @@ void TreeSyncMemory::process_synced_blocks(const uint64_t start_block_id LOG_ERROR("Cached blocks exceeded max reorg depth"); } -template void TreeSyncMemory::process_synced_blocks(const uint64_t start_block_idx, +template void TreeSyncMemory::process_synced_blocks(const uint64_t start_block_idx, const std::vector &new_block_hashes, - const typename fcmp_pp::curve_trees::CurveTrees::TreeExtension &tree_extension, + const typename fcmp_pp::curve_trees::CurveTrees::TreeExtension &tree_extension, const std::vector &n_new_leaf_tuples_per_block); //---------------------------------------------------------------------------------------------------------------------- template @@ -1160,10 +1161,10 @@ bool TreeSyncMemory::pop_block() const auto &c1_layer_reductions = tree_reduction.c1_layer_reductions; const auto &c2_layer_reductions = tree_reduction.c2_layer_reductions; - const std::size_t new_n_layers = c2_layer_reductions.size() + c1_layer_reductions.size(); + const std::size_t new_n_layers = c1_layer_reductions.size() + c2_layer_reductions.size(); // Shrink the current last chunk if some of the leaves in it got cut off - shrink_cached_last_leaf_chunk(new_n_leaf_tuples, TreeSync::m_curve_trees->m_c2_width, m_leaf_cache); + shrink_cached_last_leaf_chunk(new_n_leaf_tuples, TreeSync::m_curve_trees->m_c1_width, m_leaf_cache); // Use the tree reduction to update ref'd last hashes and shrink current last chunks as necessary reduce_cached_last_chunks(tree_reduction, TreeSync::m_curve_trees, m_tree_elem_cache); @@ -1181,7 +1182,7 @@ bool TreeSyncMemory::pop_block() continue; // The output was just removed from the tree, so remove its refs - const ChildChunkIdx leaf_chunk_idx = leaf_idx / TreeSync::m_curve_trees->m_c2_width; + const ChildChunkIdx leaf_chunk_idx = leaf_idx / TreeSync::m_curve_trees->m_c1_width; remove_leaf_chunk_ref(leaf_chunk_idx, m_leaf_cache); remove_path_chunks_refs(leaf_idx, TreeSync::m_curve_trees, old_n_leaf_tuples, m_tree_elem_cache); @@ -1207,7 +1208,7 @@ bool TreeSyncMemory::pop_block() } // Explicit instantiation -template bool TreeSyncMemory::pop_block(); +template bool TreeSyncMemory::pop_block(); //---------------------------------------------------------------------------------------------------------------------- template bool TreeSyncMemory::get_output_path(const OutputPair &output, @@ -1235,7 +1236,7 @@ bool TreeSyncMemory::get_output_path(const OutputPair &output, const auto path_indexes = TreeSync::m_curve_trees->get_path_indexes(n_leaf_tuples, leaf_idx); // Collect cached leaves from the leaf chunk the leaf is in - const uint64_t leaf_chunk_idx = path_indexes.leaf_range.first / TreeSync::m_curve_trees->m_c2_width; + const uint64_t leaf_chunk_idx = path_indexes.leaf_range.first / TreeSync::m_curve_trees->m_c1_width; const auto leaf_chunk_it = m_leaf_cache.find(leaf_chunk_idx); CHECK_AND_ASSERT_THROW_MES(leaf_chunk_it != m_leaf_cache.end(), "missing cached leaf chunk"); @@ -1248,16 +1249,16 @@ bool TreeSyncMemory::get_output_path(const OutputPair &output, // Collect cached tree elems in the leaf's path LayerIdx layer_idx = 0; - bool parent_is_c1 = true; + bool parent_is_c2 = true; while (1) { auto cached_layer_it = m_tree_elem_cache.find(layer_idx); if (cached_layer_it == m_tree_elem_cache.end()) break; - const std::size_t parent_width = parent_is_c1 - ? TreeSync::m_curve_trees->m_c1_width - : TreeSync::m_curve_trees->m_c2_width; + const std::size_t parent_width = parent_is_c2 + ? TreeSync::m_curve_trees->m_c2_width + : TreeSync::m_curve_trees->m_c1_width; CHECK_AND_ASSERT_THROW_MES(path_indexes.layers.size() > layer_idx, "missing layer path idxs"); const auto &layer_range = path_indexes.layers[layer_idx]; @@ -1268,10 +1269,10 @@ bool TreeSyncMemory::get_output_path(const OutputPair &output, const auto cached_chunk_it = cached_layer_it->second.find(chunk_idx); CHECK_AND_ASSERT_THROW_MES(cached_chunk_it != cached_layer_it->second.end(), "missing cached chunk"); - if (parent_is_c1) - path_out.c2_layers.emplace_back(); - else + if (parent_is_c2) path_out.c1_layers.emplace_back(); + else + path_out.c2_layers.emplace_back(); const uint64_t n_chunk_elems = layer_range.second - layer_range.first; CHECK_AND_ASSERT_THROW_MES(cached_chunk_it->second.tree_elems.size() == n_chunk_elems, @@ -1281,13 +1282,13 @@ bool TreeSyncMemory::get_output_path(const OutputPair &output, { const auto &tree_elem = cached_chunk_it->second.tree_elems[i]; MDEBUG("Found elem: " << epee::string_tools::pod_to_hex(tree_elem)); - if (parent_is_c1) - path_out.c2_layers.back().push_back(TreeSync::m_curve_trees->m_c2->from_bytes(tree_elem)); - else + if (parent_is_c2) path_out.c1_layers.back().push_back(TreeSync::m_curve_trees->m_c1->from_bytes(tree_elem)); + else + path_out.c2_layers.back().push_back(TreeSync::m_curve_trees->m_c2->from_bytes(tree_elem)); } - parent_is_c1 = !parent_is_c1; + parent_is_c2 = !parent_is_c2; ++layer_idx; } @@ -1295,8 +1296,8 @@ bool TreeSyncMemory::get_output_path(const OutputPair &output, } // Explicit instantiation -template bool TreeSyncMemory::get_output_path(const OutputPair &output, - CurveTrees::Path &path_out) const; +template bool TreeSyncMemory::get_output_path(const OutputPair &output, + CurveTrees::Path &path_out) const; //---------------------------------------------------------------------------------------------------------------------- //---------------------------------------------------------------------------------------------------------------------- template @@ -1332,7 +1333,7 @@ void TreeSyncMemory::init(const uint64_t start_block_idx, // TODO: {const n_leaf_tuples, const &last_chunks} -> TreeExtension can be implemented in m_curve_trees typename CurveTrees::TreeExtension tree_extension; tree_extension.leaves = std::move(leaves); - bool use_c2 = true; + bool parent_is_c1 = true; LayerIdx layer_idx = 0; for (const auto &child_chunk : last_path.layer_chunks) { @@ -1342,27 +1343,27 @@ void TreeSyncMemory::init(const uint64_t start_block_idx, CHECK_AND_ASSERT_THROW_MES(end_idx > start_idx, "unexpected end_idx <= start_idx"); CHECK_AND_ASSERT_THROW_MES(child_chunk.chunk_bytes.size() == (end_idx - start_idx), "size mismatch last chunk"); - if (use_c2) + if (parent_is_c1) { - LayerExtension layer_ext; + LayerExtension layer_ext; layer_ext.start_idx = start_idx; layer_ext.update_existing_last_hash = false; for (const auto &child : child_chunk.chunk_bytes) - layer_ext.hashes.emplace_back(TreeSync::m_curve_trees->m_c2->from_bytes(child)); - tree_extension.c2_layer_extensions.emplace_back(std::move(layer_ext)); + layer_ext.hashes.emplace_back(TreeSync::m_curve_trees->m_c1->from_bytes(child)); + tree_extension.c1_layer_extensions.emplace_back(std::move(layer_ext)); } else { - LayerExtension layer_ext; + LayerExtension layer_ext; layer_ext.start_idx = start_idx; layer_ext.update_existing_last_hash = false; for (const auto &child : child_chunk.chunk_bytes) - layer_ext.hashes.emplace_back(TreeSync::m_curve_trees->m_c1->from_bytes(child)); - tree_extension.c1_layer_extensions.emplace_back(std::move(layer_ext)); + layer_ext.hashes.emplace_back(TreeSync::m_curve_trees->m_c2->from_bytes(child)); + tree_extension.c2_layer_extensions.emplace_back(std::move(layer_ext)); } ++layer_idx; - use_c2 = !use_c2; + parent_is_c1 = !parent_is_c1; } // Cache the last chunk of leaves, so if a registered output appears in the first chunk next block, we'll have @@ -1398,7 +1399,7 @@ void TreeSyncMemory::init(const uint64_t start_block_idx, } // Explicit instantiation -template void TreeSyncMemory::init(const uint64_t start_block_idx, +template void TreeSyncMemory::init(const uint64_t start_block_idx, const crypto::hash &start_block_hash, const uint64_t n_leaf_tuples, const fcmp_pp::curve_trees::PathBytes &last_hashes, @@ -1429,7 +1430,7 @@ crypto::ec_point TreeSyncMemory::get_tree_root() const } // Explicit instantiation -template crypto::ec_point TreeSyncMemory::get_tree_root() const; +template crypto::ec_point TreeSyncMemory::get_tree_root() const; //---------------------------------------------------------------------------------------------------------------------- template uint64_t TreeSyncMemory::get_n_leaf_tuples() const @@ -1439,7 +1440,7 @@ uint64_t TreeSyncMemory::get_n_leaf_tuples() const } // Explicit instantiation -template uint64_t TreeSyncMemory::get_n_leaf_tuples() const; +template uint64_t TreeSyncMemory::get_n_leaf_tuples() const; //---------------------------------------------------------------------------------------------------------------------- template void TreeSyncMemory::clear() @@ -1452,7 +1453,7 @@ void TreeSyncMemory::clear() m_tree_elem_cache.clear(); m_cached_blocks.clear(); } -template void TreeSyncMemory::clear(); +template void TreeSyncMemory::clear(); //---------------------------------------------------------------------------------------------------------------------- //---------------------------------------------------------------------------------------------------------------------- template @@ -1465,18 +1466,18 @@ typename CurveTrees::LastHashes TreeSyncMemory::get_last_hashes( return last_hashes; uint64_t n_children = n_leaf_tuples; - bool use_c2 = true; + bool parent_is_c1 = true; LayerIdx layer_idx = 0; do { - const std::size_t width = use_c2 - ? TreeSync::m_curve_trees->m_c2_width - : TreeSync::m_curve_trees->m_c1_width; - - const std::size_t parent_width = use_c2 + const std::size_t width = parent_is_c1 ? TreeSync::m_curve_trees->m_c1_width : TreeSync::m_curve_trees->m_c2_width; + const std::size_t parent_width = parent_is_c1 + ? TreeSync::m_curve_trees->m_c2_width + : TreeSync::m_curve_trees->m_c1_width; + const ChildChunkIdx last_child_chunk_idx = (n_children - 1) / width; const ChildChunkIdx last_parent_idx = last_child_chunk_idx / parent_width; @@ -1491,14 +1492,14 @@ typename CurveTrees::LastHashes TreeSyncMemory::get_last_hashes( CHECK_AND_ASSERT_THROW_MES(!cached_chunk_it->second.tree_elems.empty(), "empty cached last chunk"); const auto &last_hash = cached_chunk_it->second.tree_elems.back(); - if (use_c2) - last_hashes.c2_last_hashes.push_back(TreeSync::m_curve_trees->m_c2->from_bytes(last_hash)); - else + if (parent_is_c1) last_hashes.c1_last_hashes.push_back(TreeSync::m_curve_trees->m_c1->from_bytes(last_hash)); + else + last_hashes.c2_last_hashes.push_back(TreeSync::m_curve_trees->m_c2->from_bytes(last_hash)); ++layer_idx; n_children = last_child_chunk_idx + 1; - use_c2 = !use_c2; + parent_is_c1 = !parent_is_c1; } while (n_children > 1); @@ -1506,7 +1507,7 @@ typename CurveTrees::LastHashes TreeSyncMemory::get_last_hashes( } // Explicit instantiation -template CurveTrees::LastHashes TreeSyncMemory::get_last_hashes( +template CurveTrees::LastHashes TreeSyncMemory::get_last_hashes( const uint64_t n_leaf_tuples) const; //---------------------------------------------------------------------------------------------------------------------- template @@ -1520,7 +1521,7 @@ typename CurveTrees::LastChunkChildrenForTrim TreeSyncMemory::ge // Leaf layer const auto &trim_leaf_layer_instructions = trim_instructions[0]; - std::vector leaves_to_regrow; + std::vector leaves_to_regrow; const std::size_t LEAF_TUPLE_SIZE = CurveTrees::LEAF_TUPLE_SIZE; // TODO: separate function if (trim_leaf_layer_instructions.end_trim_idx > trim_leaf_layer_instructions.start_trim_idx) @@ -1551,9 +1552,9 @@ typename CurveTrees::LastChunkChildrenForTrim TreeSyncMemory::ge while (idx < trim_leaf_layer_instructions.end_trim_idx); } - all_children_to_regrow.c2_children.emplace_back(std::move(leaves_to_regrow)); + all_children_to_regrow.c1_children.emplace_back(std::move(leaves_to_regrow)); - bool parent_is_c2 = false; + bool parent_is_c2 = true; for (std::size_t i = 1; i < trim_instructions.size(); ++i) { MDEBUG("Getting last chunk children to re-grow layer " << i); @@ -1600,7 +1601,7 @@ typename CurveTrees::LastChunkChildrenForTrim TreeSyncMemory::ge } template -CurveTrees::LastChunkChildrenForTrim TreeSyncMemory::get_last_chunk_children_to_regrow( +CurveTrees::LastChunkChildrenForTrim TreeSyncMemory::get_last_chunk_children_to_regrow( const std::vector &trim_instructions) const; //---------------------------------------------------------------------------------------------------------------------- template @@ -1612,7 +1613,7 @@ typename CurveTrees::LastHashes TreeSyncMemory::get_last_hashes_ if (trim_instructions.empty()) return last_hashes; - bool parent_is_c2 = true; + bool parent_is_c1 = true; for (LayerIdx i = 0; i < trim_instructions.size(); ++i) { const auto &trim_layer_instructions = trim_instructions[i]; @@ -1621,9 +1622,9 @@ typename CurveTrees::LastHashes TreeSyncMemory::get_last_hashes_ CHECK_AND_ASSERT_THROW_MES(new_total_parents > 0, "no new parents"); const ChildChunkIdx new_last_idx = new_total_parents - 1; - const std::size_t grandparent_width = parent_is_c2 - ? TreeSync::m_curve_trees->m_c1_width - : TreeSync::m_curve_trees->m_c2_width; + const std::size_t grandparent_width = parent_is_c1 + ? TreeSync::m_curve_trees->m_c2_width + : TreeSync::m_curve_trees->m_c1_width; const ChildChunkIdx chunk_idx = new_last_idx / grandparent_width; const auto cached_layer_it = m_tree_elem_cache.find(i); @@ -1644,33 +1645,33 @@ typename CurveTrees::LastHashes TreeSyncMemory::get_last_hashes_ CHECK_AND_ASSERT_THROW_MES(cached_chunk_it->second.tree_elems.size() > new_offset, "small cached chunk"); auto &last_hash = cached_chunk_it->second.tree_elems[new_offset]; - if (parent_is_c2) + if (parent_is_c1) { - auto c2_point = TreeSync::m_curve_trees->m_c2->from_bytes(last_hash); + auto c1_point = TreeSync::m_curve_trees->m_c1->from_bytes(last_hash); MDEBUG("Last hash at layer: " << i << " , new_last_idx: " << new_last_idx - << " , hash: " << (TreeSync::m_curve_trees->m_c2->to_string(c2_point))); + << " , hash: " << (TreeSync::m_curve_trees->m_c1->to_string(c1_point))); - last_hashes.c2_last_hashes.push_back(std::move(c2_point)); + last_hashes.c1_last_hashes.push_back(std::move(c1_point)); } else { - auto c1_point = TreeSync::m_curve_trees->m_c1->from_bytes(last_hash); + auto c2_point = TreeSync::m_curve_trees->m_c2->from_bytes(last_hash); MDEBUG("Last hash at layer: " << i << " , new_last_idx: " << new_last_idx - << " , hash: " << (TreeSync::m_curve_trees->m_c1->to_string(c1_point))); + << " , hash: " << (TreeSync::m_curve_trees->m_c2->to_string(c2_point))); - last_hashes.c1_last_hashes.push_back(std::move(c1_point)); + last_hashes.c2_last_hashes.push_back(std::move(c2_point)); } - parent_is_c2 = !parent_is_c2; + parent_is_c1 = !parent_is_c1; } return last_hashes; } // Explicit instantiation -template CurveTrees::LastHashes TreeSyncMemory::get_last_hashes_for_trim( +template CurveTrees::LastHashes TreeSyncMemory::get_last_hashes_for_trim( const std::vector &trim_instructions) const; //---------------------------------------------------------------------------------------------------------------------- template @@ -1681,7 +1682,7 @@ void TreeSyncMemory::deque_block(const uint64_t n_leaf_tuples_at_block) // Remove ref to last chunk leaves from the cache const LeafIdx old_last_leaf_idx = n_leaf_tuples_at_block - 1; - const ChildChunkIdx leaf_chunk_idx = old_last_leaf_idx / TreeSync::m_curve_trees->m_c2_width; + const ChildChunkIdx leaf_chunk_idx = old_last_leaf_idx / TreeSync::m_curve_trees->m_c1_width; remove_leaf_chunk_ref(leaf_chunk_idx, m_leaf_cache); // Remove refs to last chunk in every layer diff --git a/src/wallet/wallet2.cpp b/src/wallet/wallet2.cpp index 0956120949..562ddb5475 100644 --- a/src/wallet/wallet2.cpp +++ b/src/wallet/wallet2.cpp @@ -1258,7 +1258,7 @@ wallet2::wallet2(network_type nettype, uint64_t kdf_rounds, bool unattended, std m_pool_info_query_time(0), m_has_ever_refreshed_from_node(false), m_allow_mismatched_daemon_version(false), - m_tree_sync(fcmp_pp::curve_trees::TreeSyncMemory( + m_tree_sync(fcmp_pp::curve_trees::TreeSyncMemory( fcmp_pp::curve_trees::curve_trees_v1(), m_max_reorg_depth)) { diff --git a/src/wallet/wallet2.h b/src/wallet/wallet2.h index 568280b71b..48476c9f7b 100644 --- a/src/wallet/wallet2.h +++ b/src/wallet/wallet2.h @@ -897,9 +897,9 @@ namespace tools tx_entry_data(): lowest_height((uint64_t)-1), highest_height(0) {} }; - using Helios = fcmp_pp::curve_trees::Helios; using Selene = fcmp_pp::curve_trees::Selene; - using TreeSyncV1 = fcmp_pp::curve_trees::TreeSyncMemory; + using Helios = fcmp_pp::curve_trees::Helios; + using TreeSyncV1 = fcmp_pp::curve_trees::TreeSyncMemory; /*! * \brief Generates a wallet or restores one. Assumes the multisig setup diff --git a/tests/unit_tests/curve_trees.cpp b/tests/unit_tests/curve_trees.cpp index 4f50a0edc6..bbf0387f0c 100644 --- a/tests/unit_tests/curve_trees.cpp +++ b/tests/unit_tests/curve_trees.cpp @@ -77,14 +77,14 @@ const std::vector generate_random_outputs(c return outs; } //---------------------------------------------------------------------------------------------------------------------- -std::shared_ptr init_curve_trees_test(const std::size_t helios_chunk_width, - const std::size_t selene_chunk_width, +std::shared_ptr init_curve_trees_test(const std::size_t selene_chunk_width, + const std::size_t helios_chunk_width, const std::size_t tree_depth, uint64_t &n_leaves_out) { - CHECK_AND_ASSERT_THROW_MES(helios_chunk_width > 1, "helios width must be > 1"); CHECK_AND_ASSERT_THROW_MES(selene_chunk_width > 1, "selene width must be > 1"); - const auto curve_trees = fcmp_pp::curve_trees::curve_trees_v1(helios_chunk_width, selene_chunk_width); + CHECK_AND_ASSERT_THROW_MES(helios_chunk_width > 1, "helios width must be > 1"); + const auto curve_trees = fcmp_pp::curve_trees::curve_trees_v1(selene_chunk_width, helios_chunk_width); /* Number of leaves required for tree to reach given depth */ n_leaves_out = (uint64_t) selene_chunk_width; @@ -156,14 +156,14 @@ static bool trim_tree_db(const std::size_t expected_old_n_leaf_tuples, return true; } //---------------------------------------------------------------------------------------------------------------------- -#define INIT_CURVE_TREES_TEST(helios_chunk_width, selene_chunk_width, tree_depth) \ - static_assert(helios_chunk_width > 1, "helios width must be > 1"); \ +#define INIT_CURVE_TREES_TEST \ static_assert(selene_chunk_width > 1, "selene width must be > 1"); \ + static_assert(helios_chunk_width > 1, "helios width must be > 1"); \ \ /* Number of leaves required for tree to reach given depth */ \ uint64_t min_leaves_needed_for_tree_depth = 0; \ - const auto curve_trees = test::init_curve_trees_test(helios_chunk_width, \ - selene_chunk_width, \ + const auto curve_trees = test::init_curve_trees_test(selene_chunk_width, \ + helios_chunk_width, \ tree_depth, \ min_leaves_needed_for_tree_depth); \ \ @@ -350,86 +350,86 @@ bool CurveTreesGlobalTree::audit_tree(const std::size_t expected_n_leaf_tuples) if (leaves.empty()) { - CHECK_AND_ASSERT_MES(c2_layers.empty() && c1_layers.empty(), false, "expected empty tree"); + CHECK_AND_ASSERT_MES(c1_layers.empty() && c2_layers.empty(), false, "expected empty tree"); return true; } - CHECK_AND_ASSERT_MES(!c2_layers.empty(), false, "must have at least 1 c2 layer in tree"); - CHECK_AND_ASSERT_MES(c2_layers.size() == c1_layers.size() || c2_layers.size() == (c1_layers.size() + 1), - false, "unexpected mismatch of c2 and c1 layers"); + CHECK_AND_ASSERT_MES(!c1_layers.empty(), false, "must have at least 1 c1 layer in tree"); + CHECK_AND_ASSERT_MES(c1_layers.size() == c2_layers.size() || c1_layers.size() == (c2_layers.size() + 1), + false, "unexpected mismatch of c1 and c2 layers"); const std::size_t n_layers = c1_layers.size() + c2_layers.size(); CHECK_AND_ASSERT_MES(n_layers == m_curve_trees.n_layers(leaves.size()), false, "unexpected n_layers"); // Verify root has 1 member in it - const bool c2_is_root = c2_layers.size() > c1_layers.size(); - CHECK_AND_ASSERT_MES(c2_is_root ? c2_layers.back().size() == 1 : c1_layers.back().size() == 1, false, + const bool c1_is_root = c1_layers.size() > c2_layers.size(); + CHECK_AND_ASSERT_MES(c1_is_root ? c1_layers.back().size() == 1 : c2_layers.back().size() == 1, false, "root must have 1 member in it"); // Iterate from root down to layer above leaves, and check hashes match up correctly - bool parent_is_c2 = c2_is_root; - std::size_t c2_idx = c2_layers.size() - 1; - std::size_t c1_idx = c1_layers.empty() ? 0 : (c1_layers.size() - 1); + bool parent_is_c1 = c1_is_root; + std::size_t c1_idx = c1_layers.size() - 1; + std::size_t c2_idx = c2_layers.empty() ? 0 : (c2_layers.size() - 1); for (std::size_t i = 1; i < n_layers; ++i) { // TODO: implement templated function for below if statement - if (parent_is_c2) + if (parent_is_c1) { - MDEBUG("Validating parent c2 layer " << c2_idx << " , child c1 layer " << c1_idx); + MDEBUG("Validating parent c1 layer " << c1_idx << " , child c2 layer " << c2_idx); - CHECK_AND_ASSERT_THROW_MES(c2_idx < c2_layers.size(), "unexpected c2_idx"); CHECK_AND_ASSERT_THROW_MES(c1_idx < c1_layers.size(), "unexpected c1_idx"); + CHECK_AND_ASSERT_THROW_MES(c2_idx < c2_layers.size(), "unexpected c2_idx"); - const Layer &parents = c2_layers[c2_idx]; - const Layer &children = c1_layers[c1_idx]; + const Layer &parents = c1_layers[c1_idx]; + const Layer &children = c2_layers[c2_idx]; - CHECK_AND_ASSERT_MES(!parents.empty(), false, "no parents at c2_idx " + std::to_string(c2_idx)); - CHECK_AND_ASSERT_MES(!children.empty(), false, "no children at c1_idx " + std::to_string(c1_idx)); + CHECK_AND_ASSERT_MES(!parents.empty(), false, "no parents at c1_idx " + std::to_string(c1_idx)); + CHECK_AND_ASSERT_MES(!children.empty(), false, "no children at c2_idx " + std::to_string(c2_idx)); std::vector child_scalars; - fcmp_pp::tower_cycle::extend_scalars_from_cycle_points(m_curve_trees.m_c1, + fcmp_pp::tower_cycle::extend_scalars_from_cycle_points(m_curve_trees.m_c2, children, child_scalars); - const bool valid = validate_layer(m_curve_trees.m_c2, + const bool valid = validate_layer( + m_curve_trees.m_c1, parents, child_scalars, - m_curve_trees.m_c2_width); + m_curve_trees.m_c1_width); - CHECK_AND_ASSERT_MES(valid, false, "failed to validate c2_idx " + std::to_string(c2_idx)); + CHECK_AND_ASSERT_MES(valid, false, "failed to validate c1_idx " + std::to_string(c1_idx)); - --c2_idx; + --c1_idx; } else { - MDEBUG("Validating parent c1 layer " << c1_idx << " , child c2 layer " << c2_idx); + MDEBUG("Validating parent c2 layer " << c2_idx << " , child c1 layer " << c1_idx); - CHECK_AND_ASSERT_THROW_MES(c1_idx < c1_layers.size(), "unexpected c1_idx"); CHECK_AND_ASSERT_THROW_MES(c2_idx < c2_layers.size(), "unexpected c2_idx"); + CHECK_AND_ASSERT_THROW_MES(c1_idx < c1_layers.size(), "unexpected c1_idx"); - const Layer &parents = c1_layers[c1_idx]; - const Layer &children = c2_layers[c2_idx]; + const Layer &parents = c2_layers[c2_idx]; + const Layer &children = c1_layers[c1_idx]; - CHECK_AND_ASSERT_MES(!parents.empty(), false, "no parents at c1_idx " + std::to_string(c1_idx)); - CHECK_AND_ASSERT_MES(!children.empty(), false, "no children at c2_idx " + std::to_string(c2_idx)); + CHECK_AND_ASSERT_MES(!parents.empty(), false, "no parents at c2_idx " + std::to_string(c2_idx)); + CHECK_AND_ASSERT_MES(!children.empty(), false, "no children at c1_idx " + std::to_string(c1_idx)); std::vector child_scalars; - fcmp_pp::tower_cycle::extend_scalars_from_cycle_points(m_curve_trees.m_c2, + fcmp_pp::tower_cycle::extend_scalars_from_cycle_points(m_curve_trees.m_c1, children, child_scalars); - const bool valid = validate_layer( - m_curve_trees.m_c1, + const bool valid = validate_layer(m_curve_trees.m_c2, parents, child_scalars, - m_curve_trees.m_c1_width); + m_curve_trees.m_c2_width); - CHECK_AND_ASSERT_MES(valid, false, "failed to validate c1_idx " + std::to_string(c1_idx)); + CHECK_AND_ASSERT_MES(valid, false, "failed to validate c2_idx " + std::to_string(c2_idx)); - --c1_idx; + --c2_idx; } - parent_is_c2 = !parent_is_c2; + parent_is_c1 = !parent_is_c1; } MDEBUG("Validating leaves"); @@ -444,8 +444,8 @@ bool CurveTreesGlobalTree::audit_tree(const std::size_t expected_n_leaf_tuples) } // Now validate leaves - return validate_layer(m_curve_trees.m_c2, - c2_layers[0], + return validate_layer(m_curve_trees.m_c1, + c1_layers[0], m_curve_trees.flatten_leaves(std::move(leaf_tuples)), m_curve_trees.m_leaf_layer_chunk_width); } @@ -485,43 +485,43 @@ CurveTreesV1::Path CurveTreesGlobalTree::get_path_at_leaf_idx(const std::size_t // Get parents const auto &layer_ranges = path_idxs.layers; std::size_t c1_idx = 0, c2_idx = 0; - bool use_c2 = true; + bool parent_is_c1 = true; for (const auto &layer_range : layer_ranges) { - if (use_c2) + if (parent_is_c1) { - path_out.c2_layers.emplace_back(); - auto &layer_out = path_out.c2_layers.back(); + path_out.c1_layers.emplace_back(); + auto &layer_out = path_out.c1_layers.back(); - CHECK_AND_ASSERT_THROW_MES(m_tree.c2_layers.size() > c2_idx, "too high c2_idx"); - const std::size_t n_layer_elems = m_tree.c2_layers[c2_idx].size(); + CHECK_AND_ASSERT_THROW_MES(m_tree.c1_layers.size() > c1_idx, "too high c1_idx"); + const std::size_t n_layer_elems = m_tree.c1_layers[c1_idx].size(); CHECK_AND_ASSERT_THROW_MES(n_layer_elems >= layer_range.second, "too high parent idx"); for (std::size_t j = layer_range.first; j < layer_range.second; ++j) { - layer_out.emplace_back(m_tree.c2_layers[c2_idx][j]); + layer_out.emplace_back(m_tree.c1_layers[c1_idx][j]); } - ++c2_idx; + ++c1_idx; } else { - path_out.c1_layers.emplace_back(); - auto &layer_out = path_out.c1_layers.back(); + path_out.c2_layers.emplace_back(); + auto &layer_out = path_out.c2_layers.back(); - CHECK_AND_ASSERT_THROW_MES(m_tree.c1_layers.size() > c1_idx, "too high c1_idx"); - const std::size_t n_layer_elems = m_tree.c1_layers[c1_idx].size(); + CHECK_AND_ASSERT_THROW_MES(m_tree.c2_layers.size() > c2_idx, "too high c2_idx"); + const std::size_t n_layer_elems = m_tree.c2_layers[c2_idx].size(); CHECK_AND_ASSERT_THROW_MES(n_layer_elems >= layer_range.second, "too high parent idx"); for (std::size_t j = layer_range.first; j < layer_range.second; ++j) { - layer_out.emplace_back(m_tree.c1_layers[c1_idx][j]); + layer_out.emplace_back(m_tree.c2_layers[c2_idx][j]); } - ++c1_idx; + ++c2_idx; } - use_c2 = !use_c2; + parent_is_c1 = !parent_is_c1; } return path_out; @@ -536,16 +536,16 @@ uint8_t *CurveTreesGlobalTree::get_tree_root() const if ((n_layers % 2) == 0) { - CHECK_AND_ASSERT_THROW_MES(!m_tree.c1_layers.empty(), "missing c1 layers"); - const auto &last_layer = m_tree.c1_layers.back(); - CHECK_AND_ASSERT_THROW_MES(last_layer.size() == 1, "unexpected n elems in c1 root"); + CHECK_AND_ASSERT_THROW_MES(!m_tree.c2_layers.empty(), "missing c2 layers"); + const auto &last_layer = m_tree.c2_layers.back(); + CHECK_AND_ASSERT_THROW_MES(last_layer.size() == 1, "unexpected n elems in c2 root"); return fcmp_pp::tower_cycle::helios_tree_root(last_layer.back()); } else { - CHECK_AND_ASSERT_THROW_MES(!m_tree.c2_layers.empty(), "missing c2 layers"); - const auto &last_layer = m_tree.c2_layers.back(); - CHECK_AND_ASSERT_THROW_MES(last_layer.size() == 1, "unexpected n elems in c2 root"); + CHECK_AND_ASSERT_THROW_MES(!m_tree.c1_layers.empty(), "missing c1 layers"); + const auto &last_layer = m_tree.c1_layers.back(); + CHECK_AND_ASSERT_THROW_MES(last_layer.size() == 1, "unexpected n elems in c1 root"); return fcmp_pp::tower_cycle::selene_tree_root(last_layer.back()); } } @@ -566,84 +566,83 @@ void CurveTreesGlobalTree::extend_tree(const CurveTreesV1::TreeExtension &tree_e } // Add the layers - const auto &c2_extensions = tree_extension.c2_layer_extensions; const auto &c1_extensions = tree_extension.c1_layer_extensions; - CHECK_AND_ASSERT_THROW_MES(!c2_extensions.empty(), "empty c2 extensions"); + const auto &c2_extensions = tree_extension.c2_layer_extensions; + CHECK_AND_ASSERT_THROW_MES(!c1_extensions.empty(), "empty c1 extensions"); - bool use_c2 = true; - std::size_t c2_idx = 0; - std::size_t c1_idx = 0; - for (std::size_t i = 0; i < (c2_extensions.size() + c1_extensions.size()); ++i) + bool parent_is_c1 = true; + std::size_t c1_idx = 0, c2_idx = 0; + for (std::size_t i = 0; i < (c1_extensions.size() + c2_extensions.size()); ++i) { // TODO: template below if statement - if (use_c2) + if (parent_is_c1) { - CHECK_AND_ASSERT_THROW_MES(c2_idx < c2_extensions.size(), "unexpected c2 layer extension"); - const fcmp_pp::curve_trees::LayerExtension &c2_ext = c2_extensions[c2_idx]; + CHECK_AND_ASSERT_THROW_MES(c1_idx < c1_extensions.size(), "unexpected c1 layer extension"); + const fcmp_pp::curve_trees::LayerExtension &c1_ext = c1_extensions[c1_idx]; - CHECK_AND_ASSERT_THROW_MES(!c2_ext.hashes.empty(), "empty c2 layer extension"); + CHECK_AND_ASSERT_THROW_MES(!c1_ext.hashes.empty(), "empty c1 layer extension"); - 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{}); + 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 &c2_inout = m_tree.c2_layers[c2_idx]; + auto &c1_inout = m_tree.c1_layers[c1_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)); - CHECK_AND_ASSERT_THROW_MES(started_after_tip || started_at_tip, "unexpected c2 layer start"); + 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)); + CHECK_AND_ASSERT_THROW_MES(started_after_tip || started_at_tip, "unexpected c1 layer start"); // We updated the last hash if (started_at_tip) { - CHECK_AND_ASSERT_THROW_MES(c2_ext.update_existing_last_hash, "expect to be updating last hash"); - c2_inout.back() = c2_ext.hashes.front(); + CHECK_AND_ASSERT_THROW_MES(c1_ext.update_existing_last_hash, "expect to be updating last hash"); + c1_inout.back() = c1_ext.hashes.front(); } else { - CHECK_AND_ASSERT_THROW_MES(!c2_ext.update_existing_last_hash, "unexpected last hash update"); + CHECK_AND_ASSERT_THROW_MES(!c1_ext.update_existing_last_hash, "unexpected last hash update"); } - for (std::size_t i = started_at_tip ? 1 : 0; i < c2_ext.hashes.size(); ++i) - c2_inout.emplace_back(c2_ext.hashes[i]); + for (std::size_t i = started_at_tip ? 1 : 0; i < c1_ext.hashes.size(); ++i) + c1_inout.emplace_back(c1_ext.hashes[i]); - ++c2_idx; + ++c1_idx; } else { - CHECK_AND_ASSERT_THROW_MES(c1_idx < c1_extensions.size(), "unexpected c1 layer extension"); - const fcmp_pp::curve_trees::LayerExtension &c1_ext = c1_extensions[c1_idx]; + CHECK_AND_ASSERT_THROW_MES(c2_idx < c2_extensions.size(), "unexpected c2 layer extension"); + const fcmp_pp::curve_trees::LayerExtension &c2_ext = c2_extensions[c2_idx]; - CHECK_AND_ASSERT_THROW_MES(!c1_ext.hashes.empty(), "empty c1 layer extension"); + CHECK_AND_ASSERT_THROW_MES(!c2_ext.hashes.empty(), "empty c2 layer extension"); - 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{}); + 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 &c1_inout = m_tree.c1_layers[c1_idx]; + auto &c2_inout = m_tree.c2_layers[c2_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)); - CHECK_AND_ASSERT_THROW_MES(started_after_tip || started_at_tip, "unexpected c1 layer start"); + 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)); + CHECK_AND_ASSERT_THROW_MES(started_after_tip || started_at_tip, "unexpected c2 layer start"); // We updated the last hash if (started_at_tip) { - CHECK_AND_ASSERT_THROW_MES(c1_ext.update_existing_last_hash, "expect to be updating last hash"); - c1_inout.back() = c1_ext.hashes.front(); + CHECK_AND_ASSERT_THROW_MES(c2_ext.update_existing_last_hash, "expect to be updating last hash"); + c2_inout.back() = c2_ext.hashes.front(); } else { - CHECK_AND_ASSERT_THROW_MES(!c1_ext.update_existing_last_hash, "unexpected last hash update"); + CHECK_AND_ASSERT_THROW_MES(!c2_ext.update_existing_last_hash, "unexpected last hash update"); } - for (std::size_t i = started_at_tip ? 1 : 0; i < c1_ext.hashes.size(); ++i) - c1_inout.emplace_back(c1_ext.hashes[i]); + for (std::size_t i = started_at_tip ? 1 : 0; i < c2_ext.hashes.size(); ++i) + c2_inout.emplace_back(c2_ext.hashes[i]); - ++c1_idx; + ++c2_idx; } - use_c2 = !use_c2; + parent_is_c1 = !parent_is_c1; } } //---------------------------------------------------------------------------------------------------------------------- @@ -656,41 +655,19 @@ void CurveTreesGlobalTree::reduce_tree(const CurveTreesV1::TreeReduction &tree_r m_tree.leaves.pop_back(); // Trim the layers - const auto &c2_layer_reductions = tree_reduction.c2_layer_reductions; const auto &c1_layer_reductions = tree_reduction.c1_layer_reductions; - CHECK_AND_ASSERT_THROW_MES(c2_layer_reductions.size() == c1_layer_reductions.size() - || c2_layer_reductions.size() == (c1_layer_reductions.size() + 1), - "unexpected mismatch of c2 and c1 layer reductions"); + const auto &c2_layer_reductions = tree_reduction.c2_layer_reductions; + CHECK_AND_ASSERT_THROW_MES(c1_layer_reductions.size() == c2_layer_reductions.size() + || c1_layer_reductions.size() == (c2_layer_reductions.size() + 1), + "unexpected mismatch of c1 and c2 layer reductions"); - bool use_c2 = true; - std::size_t c2_idx = 0; + bool parent_is_c1 = true; std::size_t c1_idx = 0; - for (std::size_t i = 0; i < (c2_layer_reductions.size() + c1_layer_reductions.size()); ++i) + std::size_t c2_idx = 0; + for (std::size_t i = 0; i < (c1_layer_reductions.size() + c2_layer_reductions.size()); ++i) { // TODO: template below if statement - if (use_c2) - { - CHECK_AND_ASSERT_THROW_MES(c2_idx < c2_layer_reductions.size(), "unexpected c2 layer reduction"); - const auto &c2_reduction = c2_layer_reductions[c2_idx]; - - CHECK_AND_ASSERT_THROW_MES(c2_idx < m_tree.c2_layers.size(), "missing c2 layer"); - auto &c2_inout = m_tree.c2_layers[c2_idx]; - - CHECK_AND_ASSERT_THROW_MES(c2_reduction.new_total_parents <= c2_inout.size(), - "unexpected c2 new total parents"); - - c2_inout.resize(c2_reduction.new_total_parents); - c2_inout.shrink_to_fit(); - - // We updated the last hash - if (c2_reduction.update_existing_last_hash) - { - c2_inout.back() = c2_reduction.new_last_hash; - } - - ++c2_idx; - } - else + if (parent_is_c1) { CHECK_AND_ASSERT_THROW_MES(c1_idx < c1_layer_reductions.size(), "unexpected c1 layer reduction"); const auto &c1_reduction = c1_layer_reductions[c1_idx]; @@ -712,8 +689,30 @@ void CurveTreesGlobalTree::reduce_tree(const CurveTreesV1::TreeReduction &tree_r ++c1_idx; } + else + { + CHECK_AND_ASSERT_THROW_MES(c2_idx < c2_layer_reductions.size(), "unexpected c2 layer reduction"); + const auto &c2_reduction = c2_layer_reductions[c2_idx]; + + CHECK_AND_ASSERT_THROW_MES(c2_idx < m_tree.c2_layers.size(), "missing c2 layer"); + auto &c2_inout = m_tree.c2_layers[c2_idx]; + + CHECK_AND_ASSERT_THROW_MES(c2_reduction.new_total_parents <= c2_inout.size(), + "unexpected c2 new total parents"); - use_c2 = !use_c2; + c2_inout.resize(c2_reduction.new_total_parents); + c2_inout.shrink_to_fit(); + + // We updated the last hash + if (c2_reduction.update_existing_last_hash) + { + c2_inout.back() = c2_reduction.new_last_hash; + } + + ++c2_idx; + } + + parent_is_c1 = !parent_is_c1; } // Delete remaining layers @@ -733,38 +732,38 @@ CurveTreesV1::LastHashes CurveTreesGlobalTree::get_last_hashes() const 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), + // We started with c1 and then alternated, so c1 is the same size or 1 higher than c2 + CHECK_AND_ASSERT_THROW_MES(c1_layers.size() == c2_layers.size() || c1_layers.size() == (c2_layers.size() + 1), "unexpected number of curve layers"); c1_last_hashes_out.reserve(c1_layers.size()); c2_last_hashes_out.reserve(c2_layers.size()); - if (c2_layers.empty()) + if (c1_layers.empty()) return last_hashes_out; - // Next parents will be c2 - bool use_c2 = true; + // Next parents will be c1 + bool parent_is_c1 = true; // Then get last chunks up until the root std::size_t c1_idx = 0; std::size_t c2_idx = 0; while (c1_last_hashes_out.size() < c1_layers.size() || c2_last_hashes_out.size() < c2_layers.size()) { - if (use_c2) - { - CHECK_AND_ASSERT_THROW_MES(c2_layers.size() > c2_idx, "missing c2 layer"); - c2_last_hashes_out.push_back(c2_layers[c2_idx].back()); - ++c2_idx; - } - else + if (parent_is_c1) { CHECK_AND_ASSERT_THROW_MES(c1_layers.size() > c1_idx, "missing c1 layer"); c1_last_hashes_out.push_back(c1_layers[c1_idx].back()); ++c1_idx; } + else + { + CHECK_AND_ASSERT_THROW_MES(c2_layers.size() > c2_idx, "missing c2 layer"); + c2_last_hashes_out.push_back(c2_layers[c2_idx].back()); + ++c2_idx; + } - use_c2 = !use_c2; + parent_is_c1 = !parent_is_c1; } return last_hashes_out; @@ -806,9 +805,9 @@ CurveTreesV1::LastChunkChildrenForTrim CurveTreesGlobalTree::get_last_chunk_chil while (idx < trim_leaf_layer_instructions.end_trim_idx); } - all_children_for_trim.c2_children.emplace_back(std::move(leaves_to_trim)); + all_children_for_trim.c1_children.emplace_back(std::move(leaves_to_trim)); - bool parent_is_c2 = false; + bool parent_is_c2 = true; std::size_t c1_idx = 0; std::size_t c2_idx = 0; for (std::size_t i = 1; i < trim_instructions.size(); ++i) @@ -824,7 +823,7 @@ CurveTreesV1::LastChunkChildrenForTrim CurveTreesGlobalTree::get_last_chunk_chil { CHECK_AND_ASSERT_THROW_MES(m_tree.c1_layers.size() > c1_idx, "c1_idx too high"); - auto children_for_trim = get_layer_last_chunk_children_for_trim( + auto children_for_trim = get_layer_last_chunk_children_for_trim( m_curve_trees.m_c1, m_tree.c1_layers[c1_idx], start_trim_idx, @@ -837,7 +836,7 @@ CurveTreesV1::LastChunkChildrenForTrim CurveTreesGlobalTree::get_last_chunk_chil { CHECK_AND_ASSERT_THROW_MES(m_tree.c2_layers.size() > c2_idx, "c2_idx too high"); - auto children_for_trim = get_layer_last_chunk_children_for_trim( + auto children_for_trim = get_layer_last_chunk_children_for_trim( m_curve_trees.m_c2, m_tree.c2_layers[c2_idx], start_trim_idx, @@ -861,7 +860,7 @@ CurveTreesV1::LastHashes CurveTreesGlobalTree::get_last_hashes_for_trim( if (trim_instructions.empty()) return last_hashes; - bool parent_is_c2 = true; + bool parent_is_c1 = true; std::size_t c1_idx = 0; std::size_t c2_idx = 0; for (const auto &trim_layer_instructions : trim_instructions) @@ -869,17 +868,7 @@ CurveTreesV1::LastHashes CurveTreesGlobalTree::get_last_hashes_for_trim( const std::size_t new_total_parents = trim_layer_instructions.new_total_parents; CHECK_AND_ASSERT_THROW_MES(new_total_parents > 0, "no new parents"); - if (parent_is_c2) - { - CHECK_AND_ASSERT_THROW_MES(m_tree.c2_layers.size() > c2_idx, "c2_idx too high"); - const auto &c2_layer = m_tree.c2_layers[c2_idx]; - - CHECK_AND_ASSERT_THROW_MES(c2_layer.size() >= new_total_parents, "not enough c2 parents"); - - last_hashes.c2_last_hashes.push_back(c2_layer[new_total_parents - 1]); - ++c2_idx; - } - else + if (parent_is_c1) { CHECK_AND_ASSERT_THROW_MES(m_tree.c1_layers.size() > c1_idx, "c1_idx too high"); const auto &c1_layer = m_tree.c1_layers[c1_idx]; @@ -889,8 +878,18 @@ CurveTreesV1::LastHashes CurveTreesGlobalTree::get_last_hashes_for_trim( last_hashes.c1_last_hashes.push_back(c1_layer[new_total_parents - 1]); ++c1_idx; } + else + { + CHECK_AND_ASSERT_THROW_MES(m_tree.c2_layers.size() > c2_idx, "c2_idx too high"); + const auto &c2_layer = m_tree.c2_layers[c2_idx]; - parent_is_c2 = !parent_is_c2; + CHECK_AND_ASSERT_THROW_MES(c2_layer.size() >= new_total_parents, "not enough c2 parents"); + + last_hashes.c2_last_hashes.push_back(c2_layer[new_total_parents - 1]); + ++c2_idx; + } + + parent_is_c1 = !parent_is_c1; } return last_hashes; @@ -908,31 +907,31 @@ void CurveTreesGlobalTree::log_last_hashes(const CurveTreesV1::LastHashes &last_ MDEBUG("Total of " << c1_last_hashes.size() << " Helios layers and " << c2_last_hashes.size() << " Selene layers"); - bool use_c2 = true; + bool parent_is_c1 = true; std::size_t c1_idx = 0; std::size_t c2_idx = 0; for (std::size_t i = 0; i < (c1_last_hashes.size() + c2_last_hashes.size()); ++i) { - if (use_c2) + if (parent_is_c1) { - CHECK_AND_ASSERT_THROW_MES(c2_idx < c2_last_hashes.size(), "unexpected c2 layer"); + CHECK_AND_ASSERT_THROW_MES(c1_idx < c1_last_hashes.size(), "unexpected c1 layer"); - const auto &last_hash = c2_last_hashes[c2_idx]; - MDEBUG("c2_idx: " << c2_idx << " , last_hash: " << m_curve_trees.m_c2->to_string(last_hash)); + const auto &last_hash = c1_last_hashes[c1_idx]; + MDEBUG("c1_idx: " << c1_idx << " , last_hash: " << m_curve_trees.m_c1->to_string(last_hash)); - ++c2_idx; + ++c1_idx; } else { - CHECK_AND_ASSERT_THROW_MES(c1_idx < c1_last_hashes.size(), "unexpected c1 layer"); + CHECK_AND_ASSERT_THROW_MES(c2_idx < c2_last_hashes.size(), "unexpected c2 layer"); - const auto &last_hash = c1_last_hashes[c1_idx]; - MDEBUG("c1_idx: " << c1_idx << " , last_hash: " << m_curve_trees.m_c1->to_string(last_hash)); + const auto &last_hash = c2_last_hashes[c2_idx]; + MDEBUG("c2_idx: " << c2_idx << " , last_hash: " << m_curve_trees.m_c2->to_string(last_hash)); - ++c1_idx; + ++c2_idx; } - use_c2 = !use_c2; + parent_is_c1 = !parent_is_c1; } } //---------------------------------------------------------------------------------------------------------------------- @@ -953,47 +952,47 @@ void CurveTreesGlobalTree::log_tree_extension(const CurveTreesV1::TreeExtension const auto &output_pair = tree_extension.leaves.tuples[i].output_pair; const auto leaf = m_curve_trees.leaf_tuple(output_pair); - 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); - const auto C_x = m_curve_trees.m_c2->to_string(leaf.C_x); + const auto O_x = m_curve_trees.m_c1->to_string(leaf.O_x); + const auto I_x = m_curve_trees.m_c1->to_string(leaf.I_x); + const auto C_x = m_curve_trees.m_c1->to_string(leaf.C_x); MDEBUG("Leaf tuple idx " << (tree_extension.leaves.start_leaf_tuple_idx + (i * CurveTreesV1::LEAF_TUPLE_SIZE)) << " : { O_x: " << O_x << " , I_x: " << I_x << " , C_x: " << C_x << " }"); } - bool use_c2 = true; + bool parent_is_c1 = true; std::size_t c1_idx = 0; std::size_t c2_idx = 0; for (std::size_t i = 0; i < (c1_extensions.size() + c2_extensions.size()); ++i) { - if (use_c2) + if (parent_is_c1) { - CHECK_AND_ASSERT_THROW_MES(c2_idx < c2_extensions.size(), "unexpected c2 layer"); + CHECK_AND_ASSERT_THROW_MES(c1_idx < c1_extensions.size(), "unexpected c1 layer"); - const fcmp_pp::curve_trees::LayerExtension &c2_layer = c2_extensions[c2_idx]; - MDEBUG("Selene tree extension start idx: " << c2_layer.start_idx); + const fcmp_pp::curve_trees::LayerExtension &c1_layer = c1_extensions[c1_idx]; + MDEBUG("Selene tree extension start idx: " << c1_layer.start_idx); - for (std::size_t j = 0; j < c2_layer.hashes.size(); ++j) - MDEBUG("Child chunk start idx: " << (j + c2_layer.start_idx) << " , hash: " - << m_curve_trees.m_c2->to_string(c2_layer.hashes[j])); + for (std::size_t j = 0; j < c1_layer.hashes.size(); ++j) + MDEBUG("Child chunk start idx: " << (j + c1_layer.start_idx) << " , hash: " + << m_curve_trees.m_c1->to_string(c1_layer.hashes[j])); - ++c2_idx; + ++c1_idx; } else { - CHECK_AND_ASSERT_THROW_MES(c1_idx < c1_extensions.size(), "unexpected c1 layer"); + CHECK_AND_ASSERT_THROW_MES(c2_idx < c2_extensions.size(), "unexpected c2 layer"); - const fcmp_pp::curve_trees::LayerExtension &c1_layer = c1_extensions[c1_idx]; - MDEBUG("Helios tree extension start idx: " << c1_layer.start_idx); + const fcmp_pp::curve_trees::LayerExtension &c2_layer = c2_extensions[c2_idx]; + MDEBUG("Helios tree extension start idx: " << c2_layer.start_idx); - for (std::size_t j = 0; j < c1_layer.hashes.size(); ++j) - MDEBUG("Child chunk start idx: " << (j + c1_layer.start_idx) << " , hash: " - << m_curve_trees.m_c1->to_string(c1_layer.hashes[j])); + for (std::size_t j = 0; j < c2_layer.hashes.size(); ++j) + MDEBUG("Child chunk start idx: " << (j + c2_layer.start_idx) << " , hash: " + << m_curve_trees.m_c2->to_string(c2_layer.hashes[j])); - ++c1_idx; + ++c2_idx; } - use_c2 = !use_c2; + parent_is_c1 = !parent_is_c1; } } //---------------------------------------------------------------------------------------------------------------------- @@ -1003,50 +1002,50 @@ void CurveTreesGlobalTree::log_tree() return; MDEBUG("Tree has " << m_tree.leaves.size() << " leaves, " - << m_tree.c1_layers.size() << " helios layers, " << m_tree.c2_layers.size() << " selene layers"); + << m_tree.c1_layers.size() << " selene layers, " << m_tree.c2_layers.size() << " helios layers"); for (std::size_t i = 0; i < m_tree.leaves.size(); ++i) { const auto leaf = m_curve_trees.leaf_tuple(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); - const auto C_x = m_curve_trees.m_c2->to_string(leaf.C_x); + const auto O_x = m_curve_trees.m_c1->to_string(leaf.O_x); + const auto I_x = m_curve_trees.m_c1->to_string(leaf.I_x); + const auto C_x = m_curve_trees.m_c1->to_string(leaf.C_x); MDEBUG("Leaf idx " << i << " : { O_x: " << O_x << " , I_x: " << I_x << " , C_x: " << C_x << " }"); } - bool use_c2 = true; + bool parent_is_c1 = true; std::size_t c1_idx = 0; std::size_t c2_idx = 0; for (std::size_t i = 0; i < (m_tree.c1_layers.size() + m_tree.c2_layers.size()); ++i) { - if (use_c2) + if (parent_is_c1) { - CHECK_AND_ASSERT_THROW_MES(c2_idx < m_tree.c2_layers.size(), "unexpected c2 layer"); + CHECK_AND_ASSERT_THROW_MES(c1_idx < m_tree.c1_layers.size(), "unexpected c1 layer"); - const CurveTreesGlobalTree::Layer &c2_layer = m_tree.c2_layers[c2_idx]; - MDEBUG("Selene layer size: " << c2_layer.size() << " , tree layer: " << i); + const CurveTreesGlobalTree::Layer &c1_layer = m_tree.c1_layers[c1_idx]; + MDEBUG("Selene layer size: " << c1_layer.size() << " , tree layer: " << i); - for (std::size_t j = 0; j < c2_layer.size(); ++j) - MDEBUG("Child chunk start idx: " << j << " , hash: " << m_curve_trees.m_c2->to_string(c2_layer[j])); + for (std::size_t j = 0; j < c1_layer.size(); ++j) + MDEBUG("Child chunk start idx: " << j << " , hash: " << m_curve_trees.m_c1->to_string(c1_layer[j])); - ++c2_idx; + ++c1_idx; } else { - CHECK_AND_ASSERT_THROW_MES(c1_idx < m_tree.c1_layers.size(), "unexpected c1 layer"); + CHECK_AND_ASSERT_THROW_MES(c2_idx < m_tree.c2_layers.size(), "unexpected c2 layer"); - const CurveTreesGlobalTree::Layer &c1_layer = m_tree.c1_layers[c1_idx]; - MDEBUG("Helios layer size: " << c1_layer.size() << " , tree layer: " << i); + const CurveTreesGlobalTree::Layer &c2_layer = m_tree.c2_layers[c2_idx]; + MDEBUG("Helios layer size: " << c2_layer.size() << " , tree layer: " << i); - for (std::size_t j = 0; j < c1_layer.size(); ++j) - MDEBUG("Child chunk start idx: " << j << " , hash: " << m_curve_trees.m_c1->to_string(c1_layer[j])); + for (std::size_t j = 0; j < c2_layer.size(); ++j) + MDEBUG("Child chunk start idx: " << j << " , hash: " << m_curve_trees.m_c2->to_string(c2_layer[j])); - ++c1_idx; + ++c2_idx; } - use_c2 = !use_c2; + parent_is_c1 = !parent_is_c1; } } //---------------------------------------------------------------------------------------------------------------------- @@ -1056,15 +1055,14 @@ void CurveTreesGlobalTree::log_tree() TEST(curve_trees, grow_tree) { // Use lower values for chunk width than prod so that we can quickly test a many-layer deep tree - static const std::size_t helios_chunk_width = 3; static const std::size_t selene_chunk_width = 2; - + static const std::size_t helios_chunk_width = 3; static const std::size_t tree_depth = 4; - LOG_PRINT_L1("Test grow tree with helios chunk width " << helios_chunk_width - << ", selene chunk width " << selene_chunk_width << ", tree depth " << tree_depth); + LOG_PRINT_L1("Test grow tree with selene chunk width " << selene_chunk_width + << ", helios chunk width " << helios_chunk_width << ", tree depth " << tree_depth); - INIT_CURVE_TREES_TEST(helios_chunk_width, selene_chunk_width, tree_depth); + INIT_CURVE_TREES_TEST; // First initialize the tree with init_leaves BEGIN_INIT_TREE_ITER(curve_trees) @@ -1091,15 +1089,14 @@ TEST(curve_trees, grow_tree) TEST(curve_trees, trim_tree) { // Use lower values for chunk width than prod so that we can quickly test a many-layer deep tree - static const std::size_t helios_chunk_width = 3; static const std::size_t selene_chunk_width = 3; - + static const std::size_t helios_chunk_width = 3; static const std::size_t tree_depth = 4; - LOG_PRINT_L1("Test trim tree with helios chunk width " << helios_chunk_width - << ", selene chunk width " << selene_chunk_width << ", tree depth " << tree_depth); + LOG_PRINT_L1("Test trim tree with selene chunk width " << selene_chunk_width + << ", helios chunk width " << helios_chunk_width << ", tree depth " << tree_depth); - INIT_CURVE_TREES_TEST(helios_chunk_width, selene_chunk_width, tree_depth); + INIT_CURVE_TREES_TEST; // First initialize the tree with init_leaves BEGIN_INIT_TREE_ITER(curve_trees) @@ -1128,18 +1125,17 @@ TEST(curve_trees, trim_tree) TEST(curve_trees, trim_tree_then_grow) { // Use lower values for chunk width than prod so that we can quickly test a many-layer deep tree - static const std::size_t helios_chunk_width = 3; static const std::size_t selene_chunk_width = 3; - + static const std::size_t helios_chunk_width = 3; static const std::size_t tree_depth = 2; static const std::size_t grow_after_trim = 1; - LOG_PRINT_L1("Test trim tree with helios chunk width " << helios_chunk_width - << ", selene chunk width " << selene_chunk_width << ", tree depth " << tree_depth + LOG_PRINT_L1("Test trim tree with selene chunk width " << selene_chunk_width + << ", helios chunk width " << helios_chunk_width << ", tree depth " << tree_depth << ", then grow " << grow_after_trim << " leaf/leaves"); - INIT_CURVE_TREES_TEST(helios_chunk_width, selene_chunk_width, tree_depth); + INIT_CURVE_TREES_TEST; // First initialize the tree with init_leaves BEGIN_INIT_TREE_ITER(curve_trees) @@ -1183,29 +1179,29 @@ TEST(curve_trees, hash_trim) // Get the initial hash of the 2 scalars std::vector init_children{selene_scalar_0, selene_scalar_1}; - const auto init_hash = curve_trees->m_c2->hash_grow( - /*existing_hash*/ curve_trees->m_c2->hash_init_point(), + const auto init_hash = curve_trees->m_c1->hash_grow( + /*existing_hash*/ curve_trees->m_c1->hash_init_point(), /*offset*/ 0, - /*existing_child_at_offset*/ curve_trees->m_c2->zero_scalar(), + /*existing_child_at_offset*/ curve_trees->m_c1->zero_scalar(), /*children*/ Selene::Chunk{init_children.data(), init_children.size()}); // Trim selene_scalar_1 const auto &trimmed_children = Selene::Chunk{init_children.data() + 1, 1}; - const auto trim_res = curve_trees->m_c2->hash_trim( + const auto trim_res = curve_trees->m_c1->hash_trim( init_hash, 1, trimmed_children, - curve_trees->m_c2->zero_scalar()); - const auto trim_res_str = curve_trees->m_c2->to_string(trim_res); + curve_trees->m_c1->zero_scalar()); + const auto trim_res_str = curve_trees->m_c1->to_string(trim_res); // Now compare to calling hash_grow{selene_scalar_0} std::vector remaining_children{selene_scalar_0}; - const auto grow_res = curve_trees->m_c2->hash_grow( - /*existing_hash*/ curve_trees->m_c2->hash_init_point(), + const auto grow_res = curve_trees->m_c1->hash_grow( + /*existing_hash*/ curve_trees->m_c1->hash_init_point(), /*offset*/ 0, - /*existing_child_at_offset*/ curve_trees->m_c2->zero_scalar(), + /*existing_child_at_offset*/ curve_trees->m_c1->zero_scalar(), /*children*/ Selene::Chunk{remaining_children.data(), remaining_children.size()}); - const auto grow_res_str = curve_trees->m_c2->to_string(grow_res); + const auto grow_res_str = curve_trees->m_c1->to_string(grow_res); ASSERT_EQ(trim_res_str, grow_res_str); } @@ -1220,29 +1216,29 @@ TEST(curve_trees, hash_trim) // Get the initial hash of the 3 selene scalars std::vector init_children{selene_scalar_0, selene_scalar_1, selene_scalar_2}; - const auto init_hash = curve_trees->m_c2->hash_grow( - /*existing_hash*/ curve_trees->m_c2->hash_init_point(), + const auto init_hash = curve_trees->m_c1->hash_grow( + /*existing_hash*/ curve_trees->m_c1->hash_init_point(), /*offset*/ 0, - /*existing_child_at_offset*/ curve_trees->m_c2->zero_scalar(), + /*existing_child_at_offset*/ curve_trees->m_c1->zero_scalar(), /*children*/ Selene::Chunk{init_children.data(), init_children.size()}); // Trim the initial result by 2 children const auto &trimmed_children = Selene::Chunk{init_children.data() + 1, 2}; - const auto trim_res = curve_trees->m_c2->hash_trim( + const auto trim_res = curve_trees->m_c1->hash_trim( init_hash, 1, trimmed_children, - curve_trees->m_c2->zero_scalar()); - const auto trim_res_str = curve_trees->m_c2->to_string(trim_res); + curve_trees->m_c1->zero_scalar()); + const auto trim_res_str = curve_trees->m_c1->to_string(trim_res); // Now compare to calling hash_grow{selene_scalar_0} std::vector remaining_children{selene_scalar_0}; - const auto grow_res = curve_trees->m_c2->hash_grow( - /*existing_hash*/ curve_trees->m_c2->hash_init_point(), + const auto grow_res = curve_trees->m_c1->hash_grow( + /*existing_hash*/ curve_trees->m_c1->hash_init_point(), /*offset*/ 0, - /*existing_child_at_offset*/ curve_trees->m_c2->zero_scalar(), + /*existing_child_at_offset*/ curve_trees->m_c1->zero_scalar(), /*children*/ Selene::Chunk{remaining_children.data(), remaining_children.size()}); - const auto grow_res_str = curve_trees->m_c2->to_string(grow_res); + const auto grow_res_str = curve_trees->m_c1->to_string(grow_res); ASSERT_EQ(trim_res_str, grow_res_str); } @@ -1256,31 +1252,31 @@ TEST(curve_trees, hash_trim) // Get the initial hash of the 2 selene scalars std::vector init_children{selene_scalar_0, selene_scalar_1}; - const auto init_hash = curve_trees->m_c2->hash_grow( - /*existing_hash*/ curve_trees->m_c2->hash_init_point(), + const auto init_hash = curve_trees->m_c1->hash_grow( + /*existing_hash*/ curve_trees->m_c1->hash_init_point(), /*offset*/ 0, - /*existing_child_at_offset*/ curve_trees->m_c2->zero_scalar(), + /*existing_child_at_offset*/ curve_trees->m_c1->zero_scalar(), /*children*/ Selene::Chunk{init_children.data(), init_children.size()}); const auto selene_scalar_2 = generate_random_selene_scalar(); // Trim the 2nd child and grow with new child const auto &trimmed_children = Selene::Chunk{init_children.data() + 1, 1}; - const auto trim_res = curve_trees->m_c2->hash_trim( + const auto trim_res = curve_trees->m_c1->hash_trim( init_hash, 1, trimmed_children, selene_scalar_2); - const auto trim_res_str = curve_trees->m_c2->to_string(trim_res); + const auto trim_res_str = curve_trees->m_c1->to_string(trim_res); // Now compare to calling hash_grow{selene_scalar_0, selene_scalar_2} std::vector remaining_children{selene_scalar_0, selene_scalar_2}; - const auto grow_res = curve_trees->m_c2->hash_grow( - /*existing_hash*/ curve_trees->m_c2->hash_init_point(), + const auto grow_res = curve_trees->m_c1->hash_grow( + /*existing_hash*/ curve_trees->m_c1->hash_init_point(), /*offset*/ 0, - /*existing_child_at_offset*/ curve_trees->m_c2->zero_scalar(), + /*existing_child_at_offset*/ curve_trees->m_c1->zero_scalar(), /*children*/ Selene::Chunk{remaining_children.data(), remaining_children.size()}); - const auto grow_res_str = curve_trees->m_c2->to_string(grow_res); + const auto grow_res_str = curve_trees->m_c1->to_string(grow_res); ASSERT_EQ(trim_res_str, grow_res_str); } @@ -1295,31 +1291,31 @@ TEST(curve_trees, hash_trim) // Get the initial hash of the 3 selene scalars std::vector init_children{selene_scalar_0, selene_scalar_1, selene_scalar_2}; - const auto init_hash = curve_trees->m_c2->hash_grow( - /*existing_hash*/ curve_trees->m_c2->hash_init_point(), + const auto init_hash = curve_trees->m_c1->hash_grow( + /*existing_hash*/ curve_trees->m_c1->hash_init_point(), /*offset*/ 0, - /*existing_child_at_offset*/ curve_trees->m_c2->zero_scalar(), + /*existing_child_at_offset*/ curve_trees->m_c1->zero_scalar(), /*children*/ Selene::Chunk{init_children.data(), init_children.size()}); const auto selene_scalar_3 = generate_random_selene_scalar(); // Trim the initial result by 2 children+grow by 1 const auto &trimmed_children = Selene::Chunk{init_children.data() + 1, 2}; - const auto trim_res = curve_trees->m_c2->hash_trim( + const auto trim_res = curve_trees->m_c1->hash_trim( init_hash, 1, trimmed_children, selene_scalar_3); - const auto trim_res_str = curve_trees->m_c2->to_string(trim_res); + const auto trim_res_str = curve_trees->m_c1->to_string(trim_res); // Now compare to calling hash_grow{selene_scalar_0, selene_scalar_3} std::vector remaining_children{selene_scalar_0, selene_scalar_3}; - const auto grow_res = curve_trees->m_c2->hash_grow( - /*existing_hash*/ curve_trees->m_c2->hash_init_point(), + const auto grow_res = curve_trees->m_c1->hash_grow( + /*existing_hash*/ curve_trees->m_c1->hash_init_point(), /*offset*/ 0, - /*existing_child_at_offset*/ curve_trees->m_c2->zero_scalar(), + /*existing_child_at_offset*/ curve_trees->m_c1->zero_scalar(), /*children*/ Selene::Chunk{remaining_children.data(), remaining_children.size()}); - const auto grow_res_str = curve_trees->m_c2->to_string(grow_res); + const auto grow_res_str = curve_trees->m_c1->to_string(grow_res); ASSERT_EQ(trim_res_str, grow_res_str); } @@ -1337,30 +1333,30 @@ TEST(curve_trees, hash_grow) // Get the initial hash of the 2 selene scalars std::vector all_children{selene_scalar_0, selene_scalar_1}; - const auto init_hash = curve_trees->m_c2->hash_grow( - /*existing_hash*/ curve_trees->m_c2->hash_init_point(), + const auto init_hash = curve_trees->m_c1->hash_grow( + /*existing_hash*/ curve_trees->m_c1->hash_init_point(), /*offset*/ 0, - /*existing_child_at_offset*/ curve_trees->m_c2->zero_scalar(), + /*existing_child_at_offset*/ curve_trees->m_c1->zero_scalar(), /*children*/ Selene::Chunk{all_children.data(), all_children.size()}); // Extend with a new child const auto selene_scalar_2 = generate_random_selene_scalar(); std::vector new_children{selene_scalar_2}; - const auto ext_hash = curve_trees->m_c2->hash_grow( + const auto ext_hash = curve_trees->m_c1->hash_grow( init_hash, all_children.size(), - curve_trees->m_c2->zero_scalar(), + curve_trees->m_c1->zero_scalar(), Selene::Chunk{new_children.data(), new_children.size()}); - const auto ext_hash_str = curve_trees->m_c2->to_string(ext_hash); + const auto ext_hash_str = curve_trees->m_c1->to_string(ext_hash); // Now compare to calling hash_grow{selene_scalar_0, selene_scalar_1, selene_scalar_2} all_children.push_back(selene_scalar_2); - const auto grow_res = curve_trees->m_c2->hash_grow( - /*existing_hash*/ curve_trees->m_c2->hash_init_point(), + const auto grow_res = curve_trees->m_c1->hash_grow( + /*existing_hash*/ curve_trees->m_c1->hash_init_point(), /*offset*/ 0, - /*existing_child_at_offset*/ curve_trees->m_c2->zero_scalar(), + /*existing_child_at_offset*/ curve_trees->m_c1->zero_scalar(), /*children*/ Selene::Chunk{all_children.data(), all_children.size()}); - const auto grow_res_str = curve_trees->m_c2->to_string(grow_res); + const auto grow_res_str = curve_trees->m_c1->to_string(grow_res); ASSERT_EQ(ext_hash_str, grow_res_str); @@ -1368,21 +1364,21 @@ TEST(curve_trees, hash_grow) const auto selene_scalar_3 = generate_random_selene_scalar(); new_children.clear(); new_children = {selene_scalar_3}; - const auto ext_hash2 = curve_trees->m_c2->hash_grow( + const auto ext_hash2 = curve_trees->m_c1->hash_grow( ext_hash, all_children.size(), - curve_trees->m_c2->zero_scalar(), + curve_trees->m_c1->zero_scalar(), Selene::Chunk{new_children.data(), new_children.size()}); - const auto ext_hash_str2 = curve_trees->m_c2->to_string(ext_hash2); + const auto ext_hash_str2 = curve_trees->m_c1->to_string(ext_hash2); // Now compare to calling hash_grow{selene_scalar_0, selene_scalar_1, selene_scalar_2, selene_scalar_3} all_children.push_back(selene_scalar_3); - const auto grow_res2 = curve_trees->m_c2->hash_grow( - /*existing_hash*/ curve_trees->m_c2->hash_init_point(), + const auto grow_res2 = curve_trees->m_c1->hash_grow( + /*existing_hash*/ curve_trees->m_c1->hash_init_point(), /*offset*/ 0, - /*existing_child_at_offset*/ curve_trees->m_c2->zero_scalar(), + /*existing_child_at_offset*/ curve_trees->m_c1->zero_scalar(), /*children*/ Selene::Chunk{all_children.data(), all_children.size()}); - const auto grow_res_str2 = curve_trees->m_c2->to_string(grow_res2); + const auto grow_res_str2 = curve_trees->m_c1->to_string(grow_res2); ASSERT_EQ(ext_hash_str2, grow_res_str2); } diff --git a/tests/unit_tests/curve_trees.h b/tests/unit_tests/curve_trees.h index e6c5ccd421..1133cacc81 100644 --- a/tests/unit_tests/curve_trees.h +++ b/tests/unit_tests/curve_trees.h @@ -32,8 +32,8 @@ #include "fcmp_pp/tower_cycle.h" #include "unit_tests_utils.h" -using Helios = fcmp_pp::curve_trees::Helios; using Selene = fcmp_pp::curve_trees::Selene; +using Helios = fcmp_pp::curve_trees::Helios; using CurveTreesV1 = fcmp_pp::curve_trees::CurveTreesV1; //---------------------------------------------------------------------------------------------------------------------- @@ -66,8 +66,8 @@ class CurveTreesGlobalTree struct Tree final { std::vector leaves; - std::vector> c1_layers; - std::vector> c2_layers; + std::vector> c1_layers; + std::vector> c2_layers; }; //public member functions diff --git a/tests/unit_tests/fcmp_pp.cpp b/tests/unit_tests/fcmp_pp.cpp index 8aef232840..10f637d082 100644 --- a/tests/unit_tests/fcmp_pp.cpp +++ b/tests/unit_tests/fcmp_pp.cpp @@ -92,18 +92,16 @@ TEST(fcmp_pp, prove) { static const std::size_t N_INPUTS = 8; - // TODO: fix C++ to match layer widths with rust side. These are mixed because I switched it for C++ - static const std::size_t helios_chunk_width = fcmp_pp::curve_trees::SELENE_CHUNK_WIDTH; - static const std::size_t selene_chunk_width = fcmp_pp::curve_trees::HELIOS_CHUNK_WIDTH; - + static const std::size_t selene_chunk_width = fcmp_pp::curve_trees::SELENE_CHUNK_WIDTH; + static const std::size_t helios_chunk_width = fcmp_pp::curve_trees::HELIOS_CHUNK_WIDTH; static const std::size_t tree_depth = 3; - LOG_PRINT_L1("Test prove with helios chunk width " << helios_chunk_width - << ", selene chunk width " << selene_chunk_width << ", tree depth " << tree_depth); + LOG_PRINT_L1("Test prove with selene chunk width " << selene_chunk_width + << ", helios chunk width " << helios_chunk_width << ", tree depth " << tree_depth); uint64_t min_leaves_needed_for_tree_depth = 0; - const auto curve_trees = test::init_curve_trees_test(helios_chunk_width, - selene_chunk_width, + const auto curve_trees = test::init_curve_trees_test(selene_chunk_width, + helios_chunk_width, tree_depth, min_leaves_needed_for_tree_depth); @@ -119,8 +117,8 @@ TEST(fcmp_pp, prove) const auto tree_root = global_tree.get_tree_root(); // Keep them cached across runs - std::vector helios_branch_blinds; std::vector selene_branch_blinds; + std::vector helios_branch_blinds; std::vector fcmp_prove_inputs; std::vector key_images; @@ -132,7 +130,7 @@ TEST(fcmp_pp, prove) LOG_PRINT_L1("Constructing proof inputs for leaf idx " << leaf_idx); const auto path = global_tree.get_path_at_leaf_idx(leaf_idx); - const std::size_t output_idx = leaf_idx % curve_trees->m_c2_width; + const std::size_t output_idx = leaf_idx % curve_trees->m_c1_width; // const fcmp_pp::curve_trees::OutputPair output_pair = {rct::rct2pk(path.leaves[output_idx].O), path.leaves[output_idx].C}; // ASSERT_TRUE(curve_trees->audit_path(path, output_pair, global_tree.get_n_leaf_tuples())); @@ -163,30 +161,10 @@ TEST(fcmp_pp, prove) new_outputs.x_vec[leaf_idx], key_images.back()); - // helios scalars from selene points - std::vector> helios_scalars; - std::vector helios_chunks; - for (const auto &selene_points : path.c2_layers) - { - // Exclude the root - if (selene_points.size() == 1) - break; - helios_scalars.emplace_back(); - auto &helios_layer = helios_scalars.back(); - helios_layer.reserve(selene_points.size()); - for (const auto &selene_point : selene_points) - helios_layer.emplace_back(curve_trees->m_c2->point_to_cycle_scalar(selene_point)); - // Padding with 0's - for (std::size_t i = selene_points.size(); i < curve_trees->m_c1_width; ++i) - helios_layer.emplace_back(curve_trees->m_c1->zero_scalar()); - helios_chunks.emplace_back(fcmp_pp::tower_cycle::Helios::Chunk{helios_layer.data(), helios_layer.size()}); - } - const Helios::ScalarChunks helios_scalar_chunks{helios_chunks.data(), helios_chunks.size()}; - // selene scalars from helios points std::vector> selene_scalars; std::vector selene_chunks; - for (const auto &helios_points : path.c1_layers) + for (const auto &helios_points : path.c2_layers) { // Exclude the root if (helios_points.size() == 1) @@ -194,15 +172,35 @@ TEST(fcmp_pp, prove) selene_scalars.emplace_back(); auto &selene_layer = selene_scalars.back(); selene_layer.reserve(helios_points.size()); - for (const auto &c1_point : helios_points) - selene_layer.emplace_back(curve_trees->m_c1->point_to_cycle_scalar(c1_point)); + for (const auto &c2_point : helios_points) + selene_layer.emplace_back(curve_trees->m_c2->point_to_cycle_scalar(c2_point)); // Padding with 0's - for (std::size_t i = helios_points.size(); i < curve_trees->m_c2_width; ++i) - selene_layer.emplace_back(curve_trees->m_c2->zero_scalar()); + for (std::size_t i = helios_points.size(); i < curve_trees->m_c1_width; ++i) + selene_layer.emplace_back(curve_trees->m_c1->zero_scalar()); selene_chunks.emplace_back(fcmp_pp::tower_cycle::Selene::Chunk{selene_layer.data(), selene_layer.size()}); } const Selene::ScalarChunks selene_scalar_chunks{selene_chunks.data(), selene_chunks.size()}; + // helios scalars from selene points + std::vector> helios_scalars; + std::vector helios_chunks; + for (const auto &selene_points : path.c1_layers) + { + // Exclude the root + if (selene_points.size() == 1) + break; + helios_scalars.emplace_back(); + auto &helios_layer = helios_scalars.back(); + helios_layer.reserve(selene_points.size()); + for (const auto &c1_point : selene_points) + helios_layer.emplace_back(curve_trees->m_c1->point_to_cycle_scalar(c1_point)); + // Padding with 0's + for (std::size_t i = selene_points.size(); i < curve_trees->m_c2_width; ++i) + helios_layer.emplace_back(curve_trees->m_c2->zero_scalar()); + helios_chunks.emplace_back(fcmp_pp::tower_cycle::Helios::Chunk{helios_layer.data(), helios_layer.size()}); + } + const Helios::ScalarChunks helios_scalar_chunks{helios_chunks.data(), helios_chunks.size()}; + const auto path_rust = fcmp_pp::tower_cycle::path_new(leaves, output_idx, helios_scalar_chunks, @@ -225,21 +223,21 @@ TEST(fcmp_pp, prove) blinded_c_blind); // Cache branch blinds - if (helios_branch_blinds.empty()) - for (std::size_t i = 0; i < selene_scalars.size(); ++i) - helios_branch_blinds.emplace_back(fcmp_pp::tower_cycle::helios_branch_blind()); - if (selene_branch_blinds.empty()) for (std::size_t i = 0; i < helios_scalars.size(); ++i) selene_branch_blinds.emplace_back(fcmp_pp::tower_cycle::selene_branch_blind()); + if (helios_branch_blinds.empty()) + for (std::size_t i = 0; i < selene_scalars.size(); ++i) + helios_branch_blinds.emplace_back(fcmp_pp::tower_cycle::helios_branch_blind()); + auto fcmp_prove_input = fcmp_pp::tower_cycle::fcmp_prove_input_new(x, y, rerandomized_output, path_rust, output_blinds, - helios_branch_blinds, - selene_branch_blinds); + selene_branch_blinds, + helios_branch_blinds); fcmp_prove_inputs.emplace_back(std::move(fcmp_prove_input)); if (fcmp_prove_inputs.size() < N_INPUTS) diff --git a/tests/unit_tests/tree_sync_memory.cpp b/tests/unit_tests/tree_sync_memory.cpp index 1b9830deea..0a2a3e199c 100644 --- a/tests/unit_tests/tree_sync_memory.cpp +++ b/tests/unit_tests/tree_sync_memory.cpp @@ -38,12 +38,12 @@ //---------------------------------------------------------------------------------------------------------------------- #define INIT_SYNC_TEST(tree_depth) \ - static const std::size_t helios_chunk_width = 3; \ static const std::size_t selene_chunk_width = 2; \ + static const std::size_t helios_chunk_width = 3; \ \ uint64_t n_leaves_needed = 0; \ - auto curve_trees = test::init_curve_trees_test(helios_chunk_width, \ - selene_chunk_width, \ + auto curve_trees = test::init_curve_trees_test(selene_chunk_width, \ + helios_chunk_width, \ tree_depth, \ n_leaves_needed); \ \ @@ -56,7 +56,7 @@ TEST(tree_sync, register_output) { // 1. Init auto curve_trees = fcmp_pp::curve_trees::curve_trees_v1(); - auto tree_sync = new fcmp_pp::curve_trees::TreeSyncMemory(curve_trees); + auto tree_sync = new fcmp_pp::curve_trees::TreeSyncMemory(curve_trees); const std::size_t INIT_LEAVES = 10; auto outputs = test::generate_random_outputs(*curve_trees, 0, INIT_LEAVES); @@ -102,7 +102,7 @@ TEST(tree_sync, sync_block_simple) static const std::size_t INIT_LEAVES = 10; auto curve_trees = fcmp_pp::curve_trees::curve_trees_v1(); - auto tree_sync = new fcmp_pp::curve_trees::TreeSyncMemory(curve_trees); + auto tree_sync = new fcmp_pp::curve_trees::TreeSyncMemory(curve_trees); auto outputs = test::generate_random_outputs(*curve_trees, 0, INIT_LEAVES); CHECK_AND_ASSERT_THROW_MES(outputs.size() == INIT_LEAVES, "unexpected size of outputs"); @@ -128,8 +128,8 @@ TEST(tree_sync, sync_block_simple) CurveTreesV1::Path output_path; ASSERT_TRUE(tree_sync->get_output_path(output, output_path)); - // If the c2 layer chunk width < INIT_LEAVES, the test won't use expected values below - ASSERT_GE(curve_trees->m_c2_width, INIT_LEAVES); + // If the c1 layer chunk width < INIT_LEAVES, the test won't use expected values below + ASSERT_GE(curve_trees->m_c1_width, INIT_LEAVES); ASSERT_EQ(output_path.leaves.size(), INIT_LEAVES); ASSERT_TRUE(curve_trees->audit_path(output_path, output, INIT_LEAVES)); } @@ -146,7 +146,7 @@ TEST(tree_sync, sync_n_chunks_of_blocks) const std::size_t rand_leaf = crypto::rand_idx(INIT_LEAVES); auto curve_trees = fcmp_pp::curve_trees::curve_trees_v1(); - auto tree_sync = new fcmp_pp::curve_trees::TreeSyncMemory(curve_trees); + auto tree_sync = new fcmp_pp::curve_trees::TreeSyncMemory(curve_trees); const crypto::hash mock_block_hash{}; @@ -188,7 +188,7 @@ TEST(tree_sync, sync_n_chunks_of_blocks) { const uint64_t start_block_idx = i * N_BLOCKS_PER_CHUNK; - fcmp_pp::curve_trees::CurveTrees::TreeExtension tree_extension; + fcmp_pp::curve_trees::CurveTrees::TreeExtension tree_extension; std::vector n_new_leaf_tuples_per_block; tree_sync->sync_blocks(start_block_idx, @@ -225,7 +225,7 @@ TEST(tree_sync, sync_n_blocks_register_n_outputs) INIT_SYNC_TEST(tree_depth); // Sync until we've synced all the leaves needed to get to the desired tree depth - auto tree_sync = new fcmp_pp::curve_trees::TreeSyncMemory(curve_trees); + auto tree_sync = new fcmp_pp::curve_trees::TreeSyncMemory(curve_trees); uint64_t block_idx = 0; uint64_t n_outputs = 0; uint64_t n_unlocked_outputs = 0; @@ -300,7 +300,7 @@ TEST(tree_sync, sync_n_blocks_register_one_output) for (std::size_t i = 0; i < n_leaves_needed; ++i) { LOG_PRINT_L1("Register output " << (i+1) << " / " << n_leaves_needed); - auto tree_sync = new fcmp_pp::curve_trees::TreeSyncMemory(curve_trees); + auto tree_sync = new fcmp_pp::curve_trees::TreeSyncMemory(curve_trees); fcmp_pp::curve_trees::OutputPair registered_output; bool registered = false; @@ -388,7 +388,7 @@ TEST(tree_sync, sync_past_max_reorg_depth) LOG_PRINT_L1("Register output " << (i+1) << " / " << n_leaves_needed); // Sync until we've synced all the leaves needed to get to the desired tree depth - auto tree_sync = new fcmp_pp::curve_trees::TreeSyncMemory(curve_trees, max_reorg_depth); + auto tree_sync = new fcmp_pp::curve_trees::TreeSyncMemory(curve_trees, max_reorg_depth); uint64_t block_idx = 0; uint64_t n_outputs = 0; @@ -468,7 +468,7 @@ TEST(tree_sync, reorg_after_register) for (std::size_t i = 0; i < n_leaves_needed; ++i) { LOG_PRINT_L1("Register output " << (i+1) << " / " << n_leaves_needed); - auto tree_sync = new fcmp_pp::curve_trees::TreeSyncMemory(curve_trees); + auto tree_sync = new fcmp_pp::curve_trees::TreeSyncMemory(curve_trees); fcmp_pp::curve_trees::OutputPair registered_output; bool registered = false; @@ -600,7 +600,7 @@ TEST(tree_sync, register_after_reorg) // Init static const std::size_t tree_depth = 5; INIT_SYNC_TEST(tree_depth); - auto tree_sync = new fcmp_pp::curve_trees::TreeSyncMemory(curve_trees); + auto tree_sync = new fcmp_pp::curve_trees::TreeSyncMemory(curve_trees); // Sync until we reach expected tree depth uint64_t block_idx = 0; @@ -687,7 +687,7 @@ TEST(tree_sync, serialization) // 1. Grow the tree with a registered output static const std::size_t INIT_LEAVES = 10; auto curve_trees = fcmp_pp::curve_trees::curve_trees_v1(); - auto tree_sync = new fcmp_pp::curve_trees::TreeSyncMemory(curve_trees); + auto tree_sync = new fcmp_pp::curve_trees::TreeSyncMemory(curve_trees); auto outputs = test::generate_random_outputs(*curve_trees, 0, INIT_LEAVES); CHECK_AND_ASSERT_THROW_MES(outputs.size() == INIT_LEAVES, "unexpected size of outputs"); @@ -710,7 +710,7 @@ TEST(tree_sync, serialization) ASSERT_TRUE(blob_hex.find(epee::string_tools::pod_to_hex(output.commitment)) != std::string::npos); // 4. De-serialize the string into a new tree_sync2 object - auto tree_sync2 = fcmp_pp::curve_trees::TreeSyncMemory(curve_trees); + auto tree_sync2 = fcmp_pp::curve_trees::TreeSyncMemory(curve_trees); ASSERT_TRUE(serialization::parse_binary(blob, tree_sync2)); // 5. Sync 1 more block in tree_sync and tree_sync2 so the init outputs unlock and enter the trees