From 30fc80b33ef036d79041fbd2a7b97aff4b237471 Mon Sep 17 00:00:00 2001
From: j-berman <justinberman@protonmail.com>
Date: Fri, 2 Aug 2024 22:34:06 -0700
Subject: [PATCH] Don't copy when flattening leaves

---
 src/blockchain_db/lmdb/db_lmdb.cpp |  2 +-
 src/fcmp/curve_trees.cpp           | 11 +++++------
 src/fcmp/curve_trees.h             |  4 ++--
 tests/unit_tests/curve_trees.cpp   |  4 ++--
 4 files changed, 10 insertions(+), 11 deletions(-)

diff --git a/src/blockchain_db/lmdb/db_lmdb.cpp b/src/blockchain_db/lmdb/db_lmdb.cpp
index af7de2ef3..b498bc659 100644
--- a/src/blockchain_db/lmdb/db_lmdb.cpp
+++ b/src/blockchain_db/lmdb/db_lmdb.cpp
@@ -2038,7 +2038,7 @@ bool BlockchainLMDB::audit_tree(const uint64_t expected_n_leaf_tuples) const
       throw0(DB_ERROR(lmdb_error("Failed to get parent in first layer: ", result).c_str()));
 
     // Get the expected leaf chunk hash
-    const auto leaves = m_curve_trees->flatten_leaves(leaf_tuples_chunk);
+    const auto leaves = m_curve_trees->flatten_leaves(std::move(leaf_tuples_chunk));
     const fcmp::curve_trees::Selene::Chunk chunk{leaves.data(), leaves.size()};
 
     // Hash the chunk of leaves
diff --git a/src/fcmp/curve_trees.cpp b/src/fcmp/curve_trees.cpp
index cb2b82f58..d03099319 100644
--- a/src/fcmp/curve_trees.cpp
+++ b/src/fcmp/curve_trees.cpp
@@ -677,17 +677,16 @@ CurveTrees<Helios, Selene>::LeafTuple CurveTrees<Helios, Selene>::leaf_tuple(
 };
 //----------------------------------------------------------------------------------------------------------------------
 template<typename C1, typename C2>
-std::vector<typename C2::Scalar> CurveTrees<C1, C2>::flatten_leaves(const std::vector<LeafTuple> &leaves) const
+std::vector<typename C2::Scalar> CurveTrees<C1, C2>::flatten_leaves(std::vector<LeafTuple> &&leaves) const
 {
     std::vector<typename C2::Scalar> flattened_leaves;
     flattened_leaves.reserve(leaves.size() * LEAF_TUPLE_SIZE);
 
-    for (const auto &l : leaves)
+    for (auto &l : leaves)
     {
-        // TODO: implement without cloning
-        flattened_leaves.emplace_back(l.O_x);
-        flattened_leaves.emplace_back(l.I_x);
-        flattened_leaves.emplace_back(l.C_x);
+        flattened_leaves.emplace_back(std::move(l.O_x));
+        flattened_leaves.emplace_back(std::move(l.I_x));
+        flattened_leaves.emplace_back(std::move(l.C_x));
     }
 
     return flattened_leaves;
diff --git a/src/fcmp/curve_trees.h b/src/fcmp/curve_trees.h
index 8f1270552..867894211 100644
--- a/src/fcmp/curve_trees.h
+++ b/src/fcmp/curve_trees.h
@@ -237,8 +237,8 @@ public:
 
     LeafTuple leaf_tuple(const PreprocessedLeafTuple &preprocessed_leaf_tuple) const;
 
-    // Flatten leaves [(O.x, I.x, C.x),(O.x, I.x, C.x),...] -> [scalar,scalar,scalar,scalar,scalar,scalar,...]
-    std::vector<typename C2::Scalar> flatten_leaves(const std::vector<LeafTuple> &leaves) 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<typename C2::Scalar> flatten_leaves(std::vector<LeafTuple> &&leaves) const;
 
     // Convert cryptonote tx outs to contexts ready to be converted to leaf tuples, grouped by unlock height
     void tx_outs_to_leaf_tuple_contexts(const cryptonote::transaction &tx,
diff --git a/tests/unit_tests/curve_trees.cpp b/tests/unit_tests/curve_trees.cpp
index a71d0d239..45d756255 100644
--- a/tests/unit_tests/curve_trees.cpp
+++ b/tests/unit_tests/curve_trees.cpp
@@ -495,7 +495,7 @@ bool CurveTreesGlobalTree::audit_tree(const std::size_t expected_n_leaf_tuples)
 {
     MDEBUG("Auditing global tree");
 
-    const auto &leaves = m_tree.leaves;
+    auto leaves = m_tree.leaves;
     const auto &c1_layers = m_tree.c1_layers;
     const auto &c2_layers = m_tree.c2_layers;
 
@@ -582,7 +582,7 @@ bool CurveTreesGlobalTree::audit_tree(const std::size_t expected_n_leaf_tuples)
     // Now validate leaves
     return validate_layer<Selene>(m_curve_trees.m_c2,
         c2_layers[0],
-        m_curve_trees.flatten_leaves(leaves),
+        m_curve_trees.flatten_leaves(std::move(leaves)),
         m_curve_trees.m_leaf_layer_chunk_width);
 }
 //----------------------------------------------------------------------------------------------------------------------