mirror of
https://github.com/monero-project/monero.git
synced 2025-01-09 12:49:28 -05:00
Cleaner template usage, moved static functions out of CurveTrees class
This commit is contained in:
parent
9ba00be519
commit
5ad026975a
@ -31,192 +31,22 @@
|
|||||||
|
|
||||||
namespace fcmp
|
namespace fcmp
|
||||||
{
|
{
|
||||||
|
namespace curve_trees
|
||||||
|
{
|
||||||
//----------------------------------------------------------------------------------------------------------------------
|
//----------------------------------------------------------------------------------------------------------------------
|
||||||
//----------------------------------------------------------------------------------------------------------------------
|
//----------------------------------------------------------------------------------------------------------------------
|
||||||
using Helios = tower_cycle::Helios;
|
|
||||||
using Selene = tower_cycle::Selene;
|
|
||||||
|
|
||||||
// Instantiate the tower cycle types
|
// Instantiate the tower cycle types
|
||||||
template class CurveTrees<Helios, Selene>;
|
template class CurveTrees<Helios, Selene>;
|
||||||
//----------------------------------------------------------------------------------------------------------------------
|
//----------------------------------------------------------------------------------------------------------------------
|
||||||
//----------------------------------------------------------------------------------------------------------------------
|
//----------------------------------------------------------------------------------------------------------------------
|
||||||
template<>
|
// Public helper functions
|
||||||
CurveTrees<Helios, Selene>::LeafTuple CurveTrees<Helios, Selene>::output_to_leaf_tuple(
|
|
||||||
const crypto::public_key &O,
|
|
||||||
const crypto::public_key &C) const
|
|
||||||
{
|
|
||||||
crypto::ec_point I;
|
|
||||||
crypto::derive_key_image_generator(O, I);
|
|
||||||
|
|
||||||
return LeafTuple{
|
|
||||||
.O_x = fcmp::tower_cycle::ed_25519_point_to_scalar(O),
|
|
||||||
.I_x = fcmp::tower_cycle::ed_25519_point_to_scalar(I),
|
|
||||||
.C_x = fcmp::tower_cycle::ed_25519_point_to_scalar(C)
|
|
||||||
};
|
|
||||||
};
|
|
||||||
//----------------------------------------------------------------------------------------------------------------------
|
//----------------------------------------------------------------------------------------------------------------------
|
||||||
template <typename C1, typename C2>
|
template<typename C>
|
||||||
typename CurveTrees<C1, C2>::TreeExtension CurveTrees<C1, C2>::get_tree_extension(
|
typename C::Point get_new_parent(const C &curve, const typename C::Chunk &new_children)
|
||||||
const LastChunks &existing_last_chunks,
|
|
||||||
const std::vector<LeafTuple> &new_leaf_tuples)
|
|
||||||
{
|
|
||||||
TreeExtension tree_extension;
|
|
||||||
|
|
||||||
if (new_leaf_tuples.empty())
|
|
||||||
return tree_extension;
|
|
||||||
|
|
||||||
const auto &c1_last_chunks = existing_last_chunks.c1_last_chunks;
|
|
||||||
const auto &c2_last_chunks = existing_last_chunks.c2_last_chunks;
|
|
||||||
|
|
||||||
// Set the leaf start idx
|
|
||||||
tree_extension.leaves.start_idx = c2_last_chunks.empty()
|
|
||||||
? 0
|
|
||||||
: c2_last_chunks[0].child_layer_size;
|
|
||||||
|
|
||||||
// Copy the leaves
|
|
||||||
// TODO: don't copy here
|
|
||||||
tree_extension.leaves.tuples.reserve(new_leaf_tuples.size());
|
|
||||||
for (const auto &leaf : new_leaf_tuples)
|
|
||||||
{
|
|
||||||
tree_extension.leaves.tuples.emplace_back(LeafTuple{
|
|
||||||
.O_x = m_c2.clone(leaf.O_x),
|
|
||||||
.I_x = m_c2.clone(leaf.I_x),
|
|
||||||
.C_x = m_c2.clone(leaf.C_x)
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
auto &c1_layer_extensions_out = tree_extension.c1_layer_extensions;
|
|
||||||
auto &c2_layer_extensions_out = tree_extension.c2_layer_extensions;
|
|
||||||
|
|
||||||
const std::vector<typename C2::Scalar> flattened_leaves = this->flatten_leaves(new_leaf_tuples);
|
|
||||||
|
|
||||||
// Hash the leaf layer
|
|
||||||
LayerExtension<C2> leaf_parents;
|
|
||||||
this->hash_layer(m_c2,
|
|
||||||
c2_last_chunks.empty() ? nullptr : &c2_last_chunks[0],
|
|
||||||
flattened_leaves,
|
|
||||||
tree_extension.leaves.start_idx,
|
|
||||||
m_leaf_layer_chunk_width,
|
|
||||||
leaf_parents);
|
|
||||||
|
|
||||||
c2_layer_extensions_out.emplace_back(std::move(leaf_parents));
|
|
||||||
|
|
||||||
// Check if we just added the root
|
|
||||||
if (c2_layer_extensions_out.back().hashes.size() == 1 && c2_layer_extensions_out.back().start_idx == 0)
|
|
||||||
return tree_extension;
|
|
||||||
|
|
||||||
// Alternate between hashing c2 children, c1 children, c2, c1, ...
|
|
||||||
bool parent_is_c1 = true;
|
|
||||||
|
|
||||||
std::size_t c1_last_idx = 0;
|
|
||||||
std::size_t c2_last_idx = 0;
|
|
||||||
// TODO: calculate max number of layers it should take to add all leaves (existing leaves + new leaves)
|
|
||||||
while (true)
|
|
||||||
{
|
|
||||||
const LastChunkData<C1> *c1_last_chunk_ptr = (c1_last_chunks.size() <= c1_last_idx)
|
|
||||||
? nullptr
|
|
||||||
: &c1_last_chunks[c1_last_idx];
|
|
||||||
|
|
||||||
const LastChunkData<C2> *c2_last_chunk_ptr = (c2_last_chunks.size() <= c2_last_idx)
|
|
||||||
? nullptr
|
|
||||||
: &c2_last_chunks[c2_last_idx];
|
|
||||||
|
|
||||||
// TODO: templated function
|
|
||||||
if (parent_is_c1)
|
|
||||||
{
|
|
||||||
CHECK_AND_ASSERT_THROW_MES(c2_layer_extensions_out.size() > c2_last_idx, "missing c2 layer");
|
|
||||||
|
|
||||||
const auto &c2_child_extension = c2_layer_extensions_out[c2_last_idx];
|
|
||||||
|
|
||||||
const auto c1_child_scalars = this->next_child_scalars_from_children<C2, C1>(m_c2,
|
|
||||||
c2_last_chunk_ptr,
|
|
||||||
c1_last_chunk_ptr,
|
|
||||||
c2_child_extension);
|
|
||||||
|
|
||||||
LayerExtension<C1> c1_layer_extension;
|
|
||||||
this->hash_layer<C1>(m_c1,
|
|
||||||
c1_last_chunk_ptr,
|
|
||||||
c1_child_scalars,
|
|
||||||
c2_child_extension.start_idx,
|
|
||||||
m_c1_width,
|
|
||||||
c1_layer_extension);
|
|
||||||
|
|
||||||
c1_layer_extensions_out.emplace_back(std::move(c1_layer_extension));
|
|
||||||
|
|
||||||
// Check if we just added the root
|
|
||||||
if (c1_layer_extensions_out.back().hashes.size() == 1 && c1_layer_extensions_out.back().start_idx == 0)
|
|
||||||
return tree_extension;
|
|
||||||
|
|
||||||
++c2_last_idx;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
CHECK_AND_ASSERT_THROW_MES(c1_layer_extensions_out.size() > c1_last_idx, "missing c1 layer");
|
|
||||||
|
|
||||||
const auto &c1_child_extension = c1_layer_extensions_out[c1_last_idx];
|
|
||||||
|
|
||||||
const auto c2_child_scalars = this->next_child_scalars_from_children<C1, C2>(m_c1,
|
|
||||||
c1_last_chunk_ptr,
|
|
||||||
c2_last_chunk_ptr,
|
|
||||||
c1_child_extension);
|
|
||||||
|
|
||||||
LayerExtension<C2> c2_layer_extension;
|
|
||||||
this->hash_layer<C2>(m_c2,
|
|
||||||
c2_last_chunk_ptr,
|
|
||||||
c2_child_scalars,
|
|
||||||
c1_child_extension.start_idx,
|
|
||||||
m_c2_width,
|
|
||||||
c2_layer_extension);
|
|
||||||
|
|
||||||
c2_layer_extensions_out.emplace_back(std::move(c2_layer_extension));
|
|
||||||
|
|
||||||
// Check if we just added the root
|
|
||||||
if (c2_layer_extensions_out.back().hashes.size() == 1 && c2_layer_extensions_out.back().start_idx == 0)
|
|
||||||
return tree_extension;
|
|
||||||
|
|
||||||
++c1_last_idx;
|
|
||||||
}
|
|
||||||
|
|
||||||
parent_is_c1 = !parent_is_c1;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
//----------------------------------------------------------------------------------------------------------------------
|
|
||||||
//----------------------------------------------------------------------------------------------------------------------
|
|
||||||
// Private member functions
|
|
||||||
//----------------------------------------------------------------------------------------------------------------------
|
|
||||||
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> flattened_leaves;
|
|
||||||
flattened_leaves.reserve(leaves.size() * LEAF_TUPLE_SIZE);
|
|
||||||
|
|
||||||
for (const auto &l : leaves)
|
|
||||||
{
|
|
||||||
// TODO: implement without cloning
|
|
||||||
flattened_leaves.emplace_back(m_c2.clone(l.O_x));
|
|
||||||
flattened_leaves.emplace_back(m_c2.clone(l.I_x));
|
|
||||||
flattened_leaves.emplace_back(m_c2.clone(l.C_x));
|
|
||||||
}
|
|
||||||
|
|
||||||
return flattened_leaves;
|
|
||||||
};
|
|
||||||
//----------------------------------------------------------------------------------------------------------------------
|
|
||||||
// Explicit instantiations
|
|
||||||
template Helios::Point CurveTrees<Helios, Selene>::get_new_parent(const Helios &curve,
|
|
||||||
const Helios::Chunk &new_children) const;
|
|
||||||
|
|
||||||
template Selene::Point CurveTrees<Helios, Selene>::get_new_parent(const Selene &curve,
|
|
||||||
const Selene::Chunk &new_children) const;
|
|
||||||
//----------------------------------------------------------------------------------------------------------------------
|
|
||||||
// Implementation
|
|
||||||
template <typename C1, typename C2>
|
|
||||||
template <typename C>
|
|
||||||
typename C::Point CurveTrees<C1, C2>::get_new_parent(const C &curve,
|
|
||||||
const typename C::Chunk &new_children) const
|
|
||||||
{
|
{
|
||||||
// New parent means no prior children, fill priors with 0
|
// New parent means no prior children, fill priors with 0
|
||||||
std::vector<typename C::Scalar> prior_children;
|
std::vector<typename C::Scalar> prior_children;
|
||||||
fcmp::tower_cycle::extend_zeroes(curve, new_children.size(), prior_children);
|
tower_cycle::extend_zeroes(curve, new_children.size(), prior_children);
|
||||||
|
|
||||||
return curve.hash_grow(
|
return curve.hash_grow(
|
||||||
curve.m_hash_init_point,
|
curve.m_hash_init_point,
|
||||||
@ -227,34 +57,20 @@ typename C::Point CurveTrees<C1, C2>::get_new_parent(const C &curve,
|
|||||||
};
|
};
|
||||||
//----------------------------------------------------------------------------------------------------------------------
|
//----------------------------------------------------------------------------------------------------------------------
|
||||||
//----------------------------------------------------------------------------------------------------------------------
|
//----------------------------------------------------------------------------------------------------------------------
|
||||||
// Explicit instantiations
|
// Static functions
|
||||||
template Helios::Point CurveTrees<Helios, Selene>::get_first_parent(const Helios &curve,
|
|
||||||
const Helios::Chunk &new_children,
|
|
||||||
const std::size_t chunk_width,
|
|
||||||
const bool child_layer_last_hash_updated,
|
|
||||||
const LastChunkData<Helios> *last_chunk_ptr,
|
|
||||||
const std::size_t offset) const;
|
|
||||||
|
|
||||||
template Selene::Point CurveTrees<Helios, Selene>::get_first_parent(const Selene &curve,
|
|
||||||
const Selene::Chunk &new_children,
|
|
||||||
const std::size_t chunk_width,
|
|
||||||
const bool child_layer_last_hash_updated,
|
|
||||||
const LastChunkData<Selene> *last_chunk_ptr,
|
|
||||||
const std::size_t offset) const;
|
|
||||||
//----------------------------------------------------------------------------------------------------------------------
|
//----------------------------------------------------------------------------------------------------------------------
|
||||||
// Implementation
|
// Hash the first chunk of children being added to a layer
|
||||||
template <typename C1, typename C2>
|
template<typename C>
|
||||||
template <typename C>
|
static typename C::Point get_first_parent(const C &curve,
|
||||||
typename C::Point CurveTrees<C1, C2>::get_first_parent(const C &curve,
|
|
||||||
const typename C::Chunk &new_children,
|
const typename C::Chunk &new_children,
|
||||||
const std::size_t chunk_width,
|
const std::size_t chunk_width,
|
||||||
const bool child_layer_last_hash_updated,
|
const bool child_layer_last_hash_updated,
|
||||||
const LastChunkData<C> *last_chunk_ptr,
|
const LastChunkData<C> *last_chunk_ptr,
|
||||||
const std::size_t offset) const
|
const std::size_t offset)
|
||||||
{
|
{
|
||||||
// If no last chunk exists, we can get a new parent
|
// If no last chunk exists, we can get a new parent
|
||||||
if (last_chunk_ptr == nullptr)
|
if (last_chunk_ptr == nullptr)
|
||||||
return this->get_new_parent<C>(curve, new_children);
|
return get_new_parent<C>(curve, new_children);
|
||||||
|
|
||||||
std::vector<typename C::Scalar> prior_children;
|
std::vector<typename C::Scalar> prior_children;
|
||||||
|
|
||||||
@ -265,18 +81,18 @@ typename C::Point CurveTrees<C1, C2>::get_first_parent(const C &curve,
|
|||||||
|
|
||||||
// Extend prior children by zeroes for any additional new children, since they must be new
|
// Extend prior children by zeroes for any additional new children, since they must be new
|
||||||
if (new_children.size() > 1)
|
if (new_children.size() > 1)
|
||||||
fcmp::tower_cycle::extend_zeroes(curve, new_children.size() - 1, prior_children);
|
tower_cycle::extend_zeroes(curve, new_children.size() - 1, prior_children);
|
||||||
}
|
}
|
||||||
else if (offset > 0)
|
else if (offset > 0)
|
||||||
{
|
{
|
||||||
// If we're updating the parent hash and no children were updated, then we're just adding new children
|
// If we're updating the parent hash and no children were updated, then we're just adding new children
|
||||||
// to the existing last chunk and can fill priors with 0
|
// to the existing last chunk and can fill priors with 0
|
||||||
fcmp::tower_cycle::extend_zeroes(curve, new_children.size(), prior_children);
|
tower_cycle::extend_zeroes(curve, new_children.size(), prior_children);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// If the last chunk is already full and isn't updated in any way, then we just get a new parent
|
// If the last chunk is already full and isn't updated in any way, then we just get a new parent
|
||||||
return this->get_new_parent<C>(curve, new_children);
|
return get_new_parent<C>(curve, new_children);
|
||||||
}
|
}
|
||||||
|
|
||||||
return curve.hash_grow(
|
return curve.hash_grow(
|
||||||
@ -287,22 +103,10 @@ typename C::Point CurveTrees<C1, C2>::get_first_parent(const C &curve,
|
|||||||
);
|
);
|
||||||
};
|
};
|
||||||
//----------------------------------------------------------------------------------------------------------------------
|
//----------------------------------------------------------------------------------------------------------------------
|
||||||
//----------------------------------------------------------------------------------------------------------------------
|
// After hashing a layer of children points, convert those children x-coordinates into their respective cycle
|
||||||
// Explicit instantiations
|
// scalars, and prepare them to be hashed for the next layer
|
||||||
template std::vector<Helios::Scalar> CurveTrees<Helios, Selene>::next_child_scalars_from_children(const Selene &c_child,
|
|
||||||
const LastChunkData<Selene> *last_child_chunk_ptr,
|
|
||||||
const LastChunkData<Helios> *last_parent_chunk_ptr,
|
|
||||||
const LayerExtension<Selene> &children);
|
|
||||||
|
|
||||||
template std::vector<Selene::Scalar> CurveTrees<Helios, Selene>::next_child_scalars_from_children(const Helios &c_child,
|
|
||||||
const LastChunkData<Helios> *last_child_chunk_ptr,
|
|
||||||
const LastChunkData<Selene> *last_parent_chunk_ptr,
|
|
||||||
const LayerExtension<Helios> &children);
|
|
||||||
//----------------------------------------------------------------------------------------------------------------------
|
|
||||||
// Implementation
|
|
||||||
template <typename C1, typename C2>
|
|
||||||
template<typename C_CHILD, typename C_PARENT>
|
template<typename C_CHILD, typename C_PARENT>
|
||||||
std::vector<typename C_PARENT::Scalar> CurveTrees<C1, C2>::next_child_scalars_from_children(const C_CHILD &c_child,
|
static std::vector<typename C_PARENT::Scalar> next_child_scalars_from_children(const C_CHILD &c_child,
|
||||||
const LastChunkData<C_CHILD> *last_child_chunk_ptr,
|
const LastChunkData<C_CHILD> *last_child_chunk_ptr,
|
||||||
const LastChunkData<C_PARENT> *last_parent_chunk_ptr,
|
const LastChunkData<C_PARENT> *last_parent_chunk_ptr,
|
||||||
const LayerExtension<C_CHILD> &children)
|
const LayerExtension<C_CHILD> &children)
|
||||||
@ -333,26 +137,9 @@ std::vector<typename C_PARENT::Scalar> CurveTrees<C1, C2>::next_child_scalars_fr
|
|||||||
return child_scalars;
|
return child_scalars;
|
||||||
};
|
};
|
||||||
//----------------------------------------------------------------------------------------------------------------------
|
//----------------------------------------------------------------------------------------------------------------------
|
||||||
//----------------------------------------------------------------------------------------------------------------------
|
// Hash chunks of a layer of new children, outputting the next layer's parents
|
||||||
// Explicit instantiations
|
|
||||||
template void CurveTrees<Helios, Selene>::hash_layer(const Helios &curve,
|
|
||||||
const LastChunkData<Helios> *last_parent_chunk_ptr,
|
|
||||||
const std::vector<Helios::Scalar> &child_scalars,
|
|
||||||
const std::size_t children_start_idx,
|
|
||||||
const std::size_t chunk_width,
|
|
||||||
LayerExtension<Helios> &parents_out);
|
|
||||||
|
|
||||||
template void CurveTrees<Helios, Selene>::hash_layer(const Selene &curve,
|
|
||||||
const LastChunkData<Selene> *last_parent_chunk_ptr,
|
|
||||||
const std::vector<Selene::Scalar> &child_scalars,
|
|
||||||
const std::size_t children_start_idx,
|
|
||||||
const std::size_t chunk_width,
|
|
||||||
LayerExtension<Selene> &parents_out);
|
|
||||||
//----------------------------------------------------------------------------------------------------------------------
|
|
||||||
// Implementation
|
|
||||||
template <typename C1, typename C2>
|
|
||||||
template<typename C>
|
template<typename C>
|
||||||
void CurveTrees<C1, C2>::hash_layer(const C &curve,
|
static void hash_layer(const C &curve,
|
||||||
const LastChunkData<C> *last_parent_chunk_ptr,
|
const LastChunkData<C> *last_parent_chunk_ptr,
|
||||||
const std::vector<typename C::Scalar> &child_scalars,
|
const std::vector<typename C::Scalar> &child_scalars,
|
||||||
const std::size_t children_start_idx,
|
const std::size_t children_start_idx,
|
||||||
@ -415,7 +202,7 @@ void CurveTrees<C1, C2>::hash_layer(const C &curve,
|
|||||||
child_layer_last_hash_updated,
|
child_layer_last_hash_updated,
|
||||||
last_parent_chunk_ptr,
|
last_parent_chunk_ptr,
|
||||||
offset)
|
offset)
|
||||||
: this->get_new_parent<C>(curve, chunk);
|
: get_new_parent<C>(curve, chunk);
|
||||||
|
|
||||||
MDEBUG("Hash chunk_start_idx " << chunk_start_idx << " result: " << curve.to_string(chunk_hash)
|
MDEBUG("Hash chunk_start_idx " << chunk_start_idx << " result: " << curve.to_string(chunk_hash)
|
||||||
<< " , chunk_size: " << chunk_size);
|
<< " , chunk_size: " << chunk_size);
|
||||||
@ -437,4 +224,169 @@ void CurveTrees<C1, C2>::hash_layer(const C &curve,
|
|||||||
};
|
};
|
||||||
//----------------------------------------------------------------------------------------------------------------------
|
//----------------------------------------------------------------------------------------------------------------------
|
||||||
//----------------------------------------------------------------------------------------------------------------------
|
//----------------------------------------------------------------------------------------------------------------------
|
||||||
|
// CurveTrees public member functions
|
||||||
|
//----------------------------------------------------------------------------------------------------------------------
|
||||||
|
template<>
|
||||||
|
CurveTrees<Helios, Selene>::LeafTuple CurveTrees<Helios, Selene>::output_to_leaf_tuple(
|
||||||
|
const crypto::public_key &O,
|
||||||
|
const crypto::public_key &C) const
|
||||||
|
{
|
||||||
|
crypto::ec_point I;
|
||||||
|
crypto::derive_key_image_generator(O, I);
|
||||||
|
|
||||||
|
return LeafTuple{
|
||||||
|
.O_x = tower_cycle::ed_25519_point_to_scalar(O),
|
||||||
|
.I_x = tower_cycle::ed_25519_point_to_scalar(I),
|
||||||
|
.C_x = tower_cycle::ed_25519_point_to_scalar(C)
|
||||||
|
};
|
||||||
|
};
|
||||||
|
//----------------------------------------------------------------------------------------------------------------------
|
||||||
|
template<typename C1, typename C2>
|
||||||
|
typename CurveTrees<C1, C2>::TreeExtension CurveTrees<C1, C2>::get_tree_extension(
|
||||||
|
const LastChunks &existing_last_chunks,
|
||||||
|
const std::vector<LeafTuple> &new_leaf_tuples)
|
||||||
|
{
|
||||||
|
TreeExtension tree_extension;
|
||||||
|
|
||||||
|
if (new_leaf_tuples.empty())
|
||||||
|
return tree_extension;
|
||||||
|
|
||||||
|
const auto &c1_last_chunks = existing_last_chunks.c1_last_chunks;
|
||||||
|
const auto &c2_last_chunks = existing_last_chunks.c2_last_chunks;
|
||||||
|
|
||||||
|
// Set the leaf start idx
|
||||||
|
tree_extension.leaves.start_idx = c2_last_chunks.empty()
|
||||||
|
? 0
|
||||||
|
: c2_last_chunks[0].child_layer_size;
|
||||||
|
|
||||||
|
// Copy the leaves
|
||||||
|
// TODO: don't copy here
|
||||||
|
tree_extension.leaves.tuples.reserve(new_leaf_tuples.size());
|
||||||
|
for (const auto &leaf : new_leaf_tuples)
|
||||||
|
{
|
||||||
|
tree_extension.leaves.tuples.emplace_back(LeafTuple{
|
||||||
|
.O_x = m_c2.clone(leaf.O_x),
|
||||||
|
.I_x = m_c2.clone(leaf.I_x),
|
||||||
|
.C_x = m_c2.clone(leaf.C_x)
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
auto &c1_layer_extensions_out = tree_extension.c1_layer_extensions;
|
||||||
|
auto &c2_layer_extensions_out = tree_extension.c2_layer_extensions;
|
||||||
|
|
||||||
|
const std::vector<typename C2::Scalar> flattened_leaves = this->flatten_leaves(new_leaf_tuples);
|
||||||
|
|
||||||
|
// Hash the leaf layer
|
||||||
|
LayerExtension<C2> leaf_parents;
|
||||||
|
hash_layer(m_c2,
|
||||||
|
c2_last_chunks.empty() ? nullptr : &c2_last_chunks[0],
|
||||||
|
flattened_leaves,
|
||||||
|
tree_extension.leaves.start_idx,
|
||||||
|
m_leaf_layer_chunk_width,
|
||||||
|
leaf_parents);
|
||||||
|
|
||||||
|
c2_layer_extensions_out.emplace_back(std::move(leaf_parents));
|
||||||
|
|
||||||
|
// Check if we just added the root
|
||||||
|
if (c2_layer_extensions_out.back().hashes.size() == 1 && c2_layer_extensions_out.back().start_idx == 0)
|
||||||
|
return tree_extension;
|
||||||
|
|
||||||
|
// Alternate between hashing c2 children, c1 children, c2, c1, ...
|
||||||
|
bool parent_is_c1 = true;
|
||||||
|
|
||||||
|
std::size_t c1_last_idx = 0;
|
||||||
|
std::size_t c2_last_idx = 0;
|
||||||
|
// TODO: calculate max number of layers it should take to add all leaves (existing leaves + new leaves)
|
||||||
|
while (true)
|
||||||
|
{
|
||||||
|
const LastChunkData<C1> *c1_last_chunk_ptr = (c1_last_chunks.size() <= c1_last_idx)
|
||||||
|
? nullptr
|
||||||
|
: &c1_last_chunks[c1_last_idx];
|
||||||
|
|
||||||
|
const LastChunkData<C2> *c2_last_chunk_ptr = (c2_last_chunks.size() <= c2_last_idx)
|
||||||
|
? nullptr
|
||||||
|
: &c2_last_chunks[c2_last_idx];
|
||||||
|
|
||||||
|
// TODO: templated function
|
||||||
|
if (parent_is_c1)
|
||||||
|
{
|
||||||
|
CHECK_AND_ASSERT_THROW_MES(c2_layer_extensions_out.size() > c2_last_idx, "missing c2 layer");
|
||||||
|
|
||||||
|
const auto &c2_child_extension = c2_layer_extensions_out[c2_last_idx];
|
||||||
|
|
||||||
|
const auto c1_child_scalars = next_child_scalars_from_children<C2, C1>(m_c2,
|
||||||
|
c2_last_chunk_ptr,
|
||||||
|
c1_last_chunk_ptr,
|
||||||
|
c2_child_extension);
|
||||||
|
|
||||||
|
LayerExtension<C1> c1_layer_extension;
|
||||||
|
hash_layer<C1>(m_c1,
|
||||||
|
c1_last_chunk_ptr,
|
||||||
|
c1_child_scalars,
|
||||||
|
c2_child_extension.start_idx,
|
||||||
|
m_c1_width,
|
||||||
|
c1_layer_extension);
|
||||||
|
|
||||||
|
c1_layer_extensions_out.emplace_back(std::move(c1_layer_extension));
|
||||||
|
|
||||||
|
// Check if we just added the root
|
||||||
|
if (c1_layer_extensions_out.back().hashes.size() == 1 && c1_layer_extensions_out.back().start_idx == 0)
|
||||||
|
return tree_extension;
|
||||||
|
|
||||||
|
++c2_last_idx;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
CHECK_AND_ASSERT_THROW_MES(c1_layer_extensions_out.size() > c1_last_idx, "missing c1 layer");
|
||||||
|
|
||||||
|
const auto &c1_child_extension = c1_layer_extensions_out[c1_last_idx];
|
||||||
|
|
||||||
|
const auto c2_child_scalars = next_child_scalars_from_children<C1, C2>(m_c1,
|
||||||
|
c1_last_chunk_ptr,
|
||||||
|
c2_last_chunk_ptr,
|
||||||
|
c1_child_extension);
|
||||||
|
|
||||||
|
LayerExtension<C2> c2_layer_extension;
|
||||||
|
hash_layer<C2>(m_c2,
|
||||||
|
c2_last_chunk_ptr,
|
||||||
|
c2_child_scalars,
|
||||||
|
c1_child_extension.start_idx,
|
||||||
|
m_c2_width,
|
||||||
|
c2_layer_extension);
|
||||||
|
|
||||||
|
c2_layer_extensions_out.emplace_back(std::move(c2_layer_extension));
|
||||||
|
|
||||||
|
// Check if we just added the root
|
||||||
|
if (c2_layer_extensions_out.back().hashes.size() == 1 && c2_layer_extensions_out.back().start_idx == 0)
|
||||||
|
return tree_extension;
|
||||||
|
|
||||||
|
++c1_last_idx;
|
||||||
|
}
|
||||||
|
|
||||||
|
parent_is_c1 = !parent_is_c1;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
//----------------------------------------------------------------------------------------------------------------------
|
||||||
|
//----------------------------------------------------------------------------------------------------------------------
|
||||||
|
// CurveTrees private member functions
|
||||||
|
//----------------------------------------------------------------------------------------------------------------------
|
||||||
|
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> flattened_leaves;
|
||||||
|
flattened_leaves.reserve(leaves.size() * LEAF_TUPLE_SIZE);
|
||||||
|
|
||||||
|
for (const auto &l : leaves)
|
||||||
|
{
|
||||||
|
// TODO: implement without cloning
|
||||||
|
flattened_leaves.emplace_back(m_c2.clone(l.O_x));
|
||||||
|
flattened_leaves.emplace_back(m_c2.clone(l.I_x));
|
||||||
|
flattened_leaves.emplace_back(m_c2.clone(l.C_x));
|
||||||
|
}
|
||||||
|
|
||||||
|
return flattened_leaves;
|
||||||
|
};
|
||||||
|
//----------------------------------------------------------------------------------------------------------------------
|
||||||
|
//----------------------------------------------------------------------------------------------------------------------
|
||||||
|
} //namespace curve_trees
|
||||||
} //namespace fcmp
|
} //namespace fcmp
|
||||||
|
@ -37,10 +37,45 @@
|
|||||||
// forward declarations
|
// forward declarations
|
||||||
class CurveTreesUnitTest;
|
class CurveTreesUnitTest;
|
||||||
|
|
||||||
|
|
||||||
namespace fcmp
|
namespace fcmp
|
||||||
{
|
{
|
||||||
|
namespace curve_trees
|
||||||
|
{
|
||||||
|
//----------------------------------------------------------------------------------------------------------------------
|
||||||
|
//----------------------------------------------------------------------------------------------------------------------
|
||||||
|
// Hash a chunk of new children
|
||||||
|
template<typename C>
|
||||||
|
typename C::Point get_new_parent(const C &curve, const typename C::Chunk &new_children);
|
||||||
|
//----------------------------------------------------------------------------------------------------------------------
|
||||||
|
// A layer of contiguous hashes starting from a specific start_idx in the tree
|
||||||
|
template<typename C>
|
||||||
|
struct LayerExtension final
|
||||||
|
{
|
||||||
|
std::size_t start_idx;
|
||||||
|
std::vector<typename C::Point> hashes;
|
||||||
|
};
|
||||||
|
|
||||||
// TODO: longer descriptions
|
// Useful data from the last chunk in a layer
|
||||||
|
template<typename C>
|
||||||
|
struct LastChunkData final
|
||||||
|
{
|
||||||
|
// The total number of children % child layer chunk width
|
||||||
|
const std::size_t child_offset;
|
||||||
|
// The last child in the chunk (and therefore the last child in the child layer)
|
||||||
|
/* TODO: const */ typename C::Scalar last_child;
|
||||||
|
// The hash of the last chunk of child scalars
|
||||||
|
/* TODO: const */ typename C::Point last_parent;
|
||||||
|
// Total number of children in the child layer
|
||||||
|
const std::size_t child_layer_size;
|
||||||
|
// Total number of hashes in the parent layer
|
||||||
|
const std::size_t parent_layer_size;
|
||||||
|
};
|
||||||
|
//----------------------------------------------------------------------------------------------------------------------
|
||||||
|
//----------------------------------------------------------------------------------------------------------------------
|
||||||
|
// This class is useful help update the curve trees 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
|
||||||
template<typename C1, typename C2>
|
template<typename C1, typename C2>
|
||||||
class CurveTrees
|
class CurveTrees
|
||||||
{
|
{
|
||||||
@ -72,7 +107,7 @@ public:
|
|||||||
static const std::size_t LEAF_TUPLE_SIZE = 3;
|
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 C2::Scalar) * LEAF_TUPLE_SIZE), "unexpected LeafTuple size");
|
||||||
|
|
||||||
// Leaves in the tree
|
// Contiguous leaves in the tree, starting a specified start_idx in the leaf layer
|
||||||
struct Leaves final
|
struct Leaves final
|
||||||
{
|
{
|
||||||
// Starting index in the leaf layer
|
// Starting index in the leaf layer
|
||||||
@ -81,14 +116,6 @@ public:
|
|||||||
std::vector<LeafTuple> tuples;
|
std::vector<LeafTuple> tuples;
|
||||||
};
|
};
|
||||||
|
|
||||||
// A layer of contiguous hashes starting from a specific start_idx in the tree
|
|
||||||
template<typename C>
|
|
||||||
struct LayerExtension final
|
|
||||||
{
|
|
||||||
std::size_t start_idx;
|
|
||||||
std::vector<typename C::Point> hashes;
|
|
||||||
};
|
|
||||||
|
|
||||||
// A struct useful to extend an existing tree
|
// A struct useful to extend an existing tree
|
||||||
// - layers alternate between C1 and C2
|
// - 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
|
// - c2_layer_extensions[0] is first layer after leaves, then c1_layer_extensions[0], c2_layer_extensions[1], etc
|
||||||
@ -99,22 +126,6 @@ public:
|
|||||||
std::vector<LayerExtension<C2>> c2_layer_extensions;
|
std::vector<LayerExtension<C2>> c2_layer_extensions;
|
||||||
};
|
};
|
||||||
|
|
||||||
// Useful data from the last chunk in a layer
|
|
||||||
template<typename C>
|
|
||||||
struct LastChunkData final
|
|
||||||
{
|
|
||||||
// The total number of children % child layer chunk width
|
|
||||||
/*TODO: const*/ std::size_t child_offset;
|
|
||||||
// The last child in the chunk (and therefore the last child in the child layer)
|
|
||||||
/*TODO: const*/ typename C::Scalar last_child;
|
|
||||||
// The hash of the last chunk of child scalars
|
|
||||||
/*TODO: const*/ typename C::Point last_parent;
|
|
||||||
// Total number of children in the child layer
|
|
||||||
/*TODO: const*/ std::size_t child_layer_size;
|
|
||||||
// Total number of hashes in the parent layer
|
|
||||||
/*TODO: const*/ std::size_t parent_layer_size;
|
|
||||||
};
|
|
||||||
|
|
||||||
// Last chunk data from each layer in the tree
|
// Last chunk data from each layer in the tree
|
||||||
// - layers alternate between C1 and C2
|
// - layers alternate between C1 and C2
|
||||||
// - c2_last_chunks[0] is first layer after leaves, then c1_last_chunks[0], then c2_last_chunks[1], etc
|
// - c2_last_chunks[0] is first layer after leaves, then c1_last_chunks[0], then c2_last_chunks[1], etc
|
||||||
@ -139,46 +150,24 @@ private:
|
|||||||
// Flatten leaves [(O.x, I.x, C.x),(O.x, I.x, C.x),...] -> [scalar,scalar,scalar,scalar,scalar,scalar,...]
|
// 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;
|
std::vector<typename C2::Scalar> flatten_leaves(const std::vector<LeafTuple> &leaves) const;
|
||||||
|
|
||||||
// TODO: make below functions static functions inside curve_trees.cpp
|
|
||||||
// Hash a chunk of new children
|
|
||||||
template <typename C>
|
|
||||||
typename C::Point get_new_parent(const C &curve, const typename C::Chunk &new_children) const;
|
|
||||||
|
|
||||||
// Hash the first chunk of children being added to a layer
|
|
||||||
template <typename C>
|
|
||||||
typename C::Point get_first_parent(const C &curve,
|
|
||||||
const typename C::Chunk &new_children,
|
|
||||||
const std::size_t chunk_width,
|
|
||||||
const bool child_layer_last_hash_updated,
|
|
||||||
const LastChunkData<C> *last_chunk_ptr,
|
|
||||||
const std::size_t offset) const;
|
|
||||||
|
|
||||||
// After hashing a layer of children points, convert those children x-coordinates into their respective cycle
|
|
||||||
// scalars, and prepare them to be hashed for the next layer
|
|
||||||
template<typename C_CHILD, typename C_PARENT>
|
|
||||||
std::vector<typename C_PARENT::Scalar> next_child_scalars_from_children(const C_CHILD &c_child,
|
|
||||||
const LastChunkData<C_CHILD> *last_child_chunk_ptr,
|
|
||||||
const LastChunkData<C_PARENT> *last_parent_chunk_ptr,
|
|
||||||
const LayerExtension<C_CHILD> &children);
|
|
||||||
|
|
||||||
// Hash chunks of a layer of new children, outputting the next layer's parents
|
|
||||||
template<typename C>
|
|
||||||
void hash_layer(const C &curve,
|
|
||||||
const LastChunkData<C> *last_parent_chunk_ptr,
|
|
||||||
const std::vector<typename C::Scalar> &child_scalars,
|
|
||||||
const std::size_t children_start_idx,
|
|
||||||
const std::size_t chunk_width,
|
|
||||||
LayerExtension<C> &parents_out);
|
|
||||||
|
|
||||||
//member variables
|
//member variables
|
||||||
private:
|
private:
|
||||||
|
// The curves
|
||||||
const C1 &m_c1;
|
const C1 &m_c1;
|
||||||
const C2 &m_c2;
|
const C2 &m_c2;
|
||||||
|
|
||||||
|
// The chunk widths of the layers in the tree tied to each curve
|
||||||
const std::size_t m_c1_width;
|
const std::size_t m_c1_width;
|
||||||
const std::size_t m_c2_width;
|
const std::size_t m_c2_width;
|
||||||
|
|
||||||
|
// The leaf layer has a distinct chunk width than the other layers
|
||||||
const std::size_t m_leaf_layer_chunk_width;
|
const std::size_t m_leaf_layer_chunk_width;
|
||||||
};
|
};
|
||||||
|
//----------------------------------------------------------------------------------------------------------------------
|
||||||
|
using Helios = tower_cycle::Helios;
|
||||||
|
using Selene = tower_cycle::Selene;
|
||||||
|
using CurveTreesV1 = CurveTrees<Helios, Selene>;
|
||||||
|
//----------------------------------------------------------------------------------------------------------------------
|
||||||
|
//----------------------------------------------------------------------------------------------------------------------
|
||||||
|
} //namespace curve_trees
|
||||||
} //namespace fcmp
|
} //namespace fcmp
|
||||||
|
@ -144,16 +144,7 @@ std::string Selene::to_string(const typename Selene::Point &point) const
|
|||||||
}
|
}
|
||||||
//----------------------------------------------------------------------------------------------------------------------
|
//----------------------------------------------------------------------------------------------------------------------
|
||||||
//----------------------------------------------------------------------------------------------------------------------
|
//----------------------------------------------------------------------------------------------------------------------
|
||||||
SeleneScalar ed_25519_point_to_scalar(const crypto::ec_point &point)
|
// Exposed helper functions
|
||||||
{
|
|
||||||
static_assert(sizeof(RustEd25519Point) == sizeof(crypto::ec_point),
|
|
||||||
"expected same size ed25519 point to rust representation");
|
|
||||||
|
|
||||||
// TODO: implement reading just the x coordinate of ed25519 point in C/C++
|
|
||||||
fcmp::tower_cycle::RustEd25519Point rust_point;
|
|
||||||
memcpy(&rust_point, &point, sizeof(fcmp::tower_cycle::RustEd25519Point));
|
|
||||||
return fcmp_rust::ed25519_point_to_selene_scalar(rust_point);
|
|
||||||
}
|
|
||||||
//----------------------------------------------------------------------------------------------------------------------
|
//----------------------------------------------------------------------------------------------------------------------
|
||||||
Helios::Generators random_helios_generators(std::size_t n)
|
Helios::Generators random_helios_generators(std::size_t n)
|
||||||
{
|
{
|
||||||
@ -175,6 +166,61 @@ Selene::Point random_selene_hash_init_point()
|
|||||||
return fcmp_rust::random_selene_hash_init_point();
|
return fcmp_rust::random_selene_hash_init_point();
|
||||||
}
|
}
|
||||||
//----------------------------------------------------------------------------------------------------------------------
|
//----------------------------------------------------------------------------------------------------------------------
|
||||||
|
SeleneScalar ed_25519_point_to_scalar(const crypto::ec_point &point)
|
||||||
|
{
|
||||||
|
static_assert(sizeof(RustEd25519Point) == sizeof(crypto::ec_point),
|
||||||
|
"expected same size ed25519 point to rust representation");
|
||||||
|
|
||||||
|
// TODO: implement reading just the x coordinate of ed25519 point in C/C++
|
||||||
|
fcmp::tower_cycle::RustEd25519Point rust_point;
|
||||||
|
memcpy(&rust_point, &point, sizeof(fcmp::tower_cycle::RustEd25519Point));
|
||||||
|
return fcmp_rust::ed25519_point_to_selene_scalar(rust_point);
|
||||||
|
}
|
||||||
|
//----------------------------------------------------------------------------------------------------------------------
|
||||||
|
template<typename C>
|
||||||
|
void extend_zeroes(const C &curve,
|
||||||
|
const std::size_t num_zeroes,
|
||||||
|
std::vector<typename C::Scalar> &zeroes_inout)
|
||||||
|
{
|
||||||
|
zeroes_inout.reserve(zeroes_inout.size() + num_zeroes);
|
||||||
|
|
||||||
|
for (std::size_t i = 0; i < num_zeroes; ++i)
|
||||||
|
zeroes_inout.emplace_back(curve.zero_scalar());
|
||||||
|
}
|
||||||
|
|
||||||
|
// Explicit instantiations
|
||||||
|
template void extend_zeroes<Helios>(const Helios &curve,
|
||||||
|
const std::size_t num_zeroes,
|
||||||
|
std::vector<Helios::Scalar> &zeroes_inout);
|
||||||
|
|
||||||
|
template void extend_zeroes<Selene>(const Selene &curve,
|
||||||
|
const std::size_t num_zeroes,
|
||||||
|
std::vector<Selene::Scalar> &zeroes_inout);
|
||||||
|
//----------------------------------------------------------------------------------------------------------------------
|
||||||
|
template<typename C_POINTS, typename C_SCALARS>
|
||||||
|
void extend_scalars_from_cycle_points(const C_POINTS &curve,
|
||||||
|
const std::vector<typename C_POINTS::Point> &points,
|
||||||
|
std::vector<typename C_SCALARS::Scalar> &scalars_out)
|
||||||
|
{
|
||||||
|
scalars_out.reserve(scalars_out.size() + points.size());
|
||||||
|
|
||||||
|
for (const auto &point : points)
|
||||||
|
{
|
||||||
|
// TODO: implement reading just the x coordinate of points on curves in curve cycle in C/C++
|
||||||
|
typename C_SCALARS::Scalar scalar = curve.point_to_cycle_scalar(point);
|
||||||
|
scalars_out.push_back(std::move(scalar));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Explicit instantiations
|
||||||
|
template void extend_scalars_from_cycle_points<Helios, Selene>(const Helios &curve,
|
||||||
|
const std::vector<Helios::Point> &points,
|
||||||
|
std::vector<Selene::Scalar> &scalars_out);
|
||||||
|
|
||||||
|
template void extend_scalars_from_cycle_points<Selene, Helios>(const Selene &curve,
|
||||||
|
const std::vector<Selene::Point> &points,
|
||||||
|
std::vector<Helios::Scalar> &scalars_out);
|
||||||
|
//----------------------------------------------------------------------------------------------------------------------
|
||||||
//----------------------------------------------------------------------------------------------------------------------
|
//----------------------------------------------------------------------------------------------------------------------
|
||||||
} //namespace tower_cycle
|
} //namespace tower_cycle
|
||||||
} //namespace fcmp
|
} //namespace fcmp
|
||||||
|
@ -67,8 +67,7 @@ struct SeleneT final
|
|||||||
};
|
};
|
||||||
//----------------------------------------------------------------------------------------------------------------------
|
//----------------------------------------------------------------------------------------------------------------------
|
||||||
//----------------------------------------------------------------------------------------------------------------------
|
//----------------------------------------------------------------------------------------------------------------------
|
||||||
// Parent curve class that curves in a cycle must implement
|
// Abstract parent curve class that curves in a cycle must implement
|
||||||
//----------------------------------------------------------------------------------------------------------------------
|
|
||||||
template<typename C>
|
template<typename C>
|
||||||
class Curve
|
class Curve
|
||||||
{
|
{
|
||||||
@ -185,9 +184,6 @@ public:
|
|||||||
};
|
};
|
||||||
//----------------------------------------------------------------------------------------------------------------------
|
//----------------------------------------------------------------------------------------------------------------------
|
||||||
//----------------------------------------------------------------------------------------------------------------------
|
//----------------------------------------------------------------------------------------------------------------------
|
||||||
// Ed25519 point x-coordinates are Selene scalars
|
|
||||||
SeleneScalar ed_25519_point_to_scalar(const crypto::ec_point &point);
|
|
||||||
//----------------------------------------------------------------------------------------------------------------------
|
|
||||||
// TODO: use static constants and get rid of the below functions (WARNING: number of generators must be >= curve's
|
// TODO: use static constants and get rid of the below functions (WARNING: number of generators must be >= curve's
|
||||||
// width, and also need to account for selene leaf layer 3x)
|
// width, and also need to account for selene leaf layer 3x)
|
||||||
Helios::Generators random_helios_generators(std::size_t n);
|
Helios::Generators random_helios_generators(std::size_t n);
|
||||||
@ -195,35 +191,19 @@ Selene::Generators random_selene_generators(std::size_t n);
|
|||||||
Helios::Point random_helios_hash_init_point();
|
Helios::Point random_helios_hash_init_point();
|
||||||
Selene::Point random_selene_hash_init_point();
|
Selene::Point random_selene_hash_init_point();
|
||||||
//----------------------------------------------------------------------------------------------------------------------
|
//----------------------------------------------------------------------------------------------------------------------
|
||||||
|
// Ed25519 point x-coordinates are Selene scalars
|
||||||
|
SeleneScalar ed_25519_point_to_scalar(const crypto::ec_point &point);
|
||||||
//----------------------------------------------------------------------------------------------------------------------
|
//----------------------------------------------------------------------------------------------------------------------
|
||||||
// TODO: implement in cpp file
|
template<typename C>
|
||||||
template <typename C>
|
void extend_zeroes(const C &curve,
|
||||||
static void extend_zeroes(const C &curve,
|
|
||||||
const std::size_t num_zeroes,
|
const std::size_t num_zeroes,
|
||||||
std::vector<typename C::Scalar> &zeroes_inout)
|
std::vector<typename C::Scalar> &zeroes_inout);
|
||||||
{
|
|
||||||
zeroes_inout.reserve(zeroes_inout.size() + num_zeroes);
|
|
||||||
|
|
||||||
for (std::size_t i = 0; i < num_zeroes; ++i)
|
|
||||||
zeroes_inout.emplace_back(curve.zero_scalar());
|
|
||||||
}
|
|
||||||
//----------------------------------------------------------------------------------------------------------------------
|
//----------------------------------------------------------------------------------------------------------------------
|
||||||
// TODO: move impl into cpp
|
template<typename C_POINTS, typename C_SCALARS>
|
||||||
template <typename C_POINTS, typename C_SCALARS>
|
void extend_scalars_from_cycle_points(const C_POINTS &curve,
|
||||||
static void extend_scalars_from_cycle_points(const C_POINTS &curve,
|
|
||||||
const std::vector<typename C_POINTS::Point> &points,
|
const std::vector<typename C_POINTS::Point> &points,
|
||||||
std::vector<typename C_SCALARS::Scalar> &scalars_out)
|
std::vector<typename C_SCALARS::Scalar> &scalars_out);
|
||||||
{
|
|
||||||
scalars_out.reserve(scalars_out.size() + points.size());
|
|
||||||
|
|
||||||
for (const auto &point : points)
|
|
||||||
{
|
|
||||||
// TODO: implement reading just the x coordinate of points on curves in curve cycle in C/C++
|
|
||||||
typename C_SCALARS::Scalar scalar = curve.point_to_cycle_scalar(point);
|
|
||||||
scalars_out.push_back(std::move(scalar));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
//----------------------------------------------------------------------------------------------------------------------
|
//----------------------------------------------------------------------------------------------------------------------
|
||||||
//----------------------------------------------------------------------------------------------------------------------
|
//----------------------------------------------------------------------------------------------------------------------
|
||||||
}//namespace curves
|
}//namespace tower_cycle
|
||||||
}//namespace fcmp
|
}//namespace fcmp
|
||||||
|
@ -35,7 +35,7 @@
|
|||||||
// CurveTreesUnitTest helpers
|
// CurveTreesUnitTest helpers
|
||||||
//----------------------------------------------------------------------------------------------------------------------
|
//----------------------------------------------------------------------------------------------------------------------
|
||||||
template<typename C>
|
template<typename C>
|
||||||
static CurveTreesV1::LastChunkData<C> get_last_child_layer_chunk(const C &curve,
|
static fcmp::curve_trees::LastChunkData<C> get_last_child_layer_chunk(const C &curve,
|
||||||
const std::size_t child_layer_size,
|
const std::size_t child_layer_size,
|
||||||
const std::size_t parent_layer_size,
|
const std::size_t parent_layer_size,
|
||||||
const std::size_t chunk_width,
|
const std::size_t chunk_width,
|
||||||
@ -47,7 +47,7 @@ static CurveTreesV1::LastChunkData<C> get_last_child_layer_chunk(const C &curve,
|
|||||||
|
|
||||||
const std::size_t child_offset = child_layer_size % chunk_width;
|
const std::size_t child_offset = child_layer_size % chunk_width;
|
||||||
|
|
||||||
return CurveTreesV1::LastChunkData<C>{
|
return fcmp::curve_trees::LastChunkData<C>{
|
||||||
.child_offset = child_offset,
|
.child_offset = child_offset,
|
||||||
.last_child = curve.clone(last_child),
|
.last_child = curve.clone(last_child),
|
||||||
.last_parent = curve.clone(last_parent),
|
.last_parent = curve.clone(last_parent),
|
||||||
@ -56,6 +56,39 @@ static CurveTreesV1::LastChunkData<C> get_last_child_layer_chunk(const C &curve,
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
//----------------------------------------------------------------------------------------------------------------------
|
//----------------------------------------------------------------------------------------------------------------------
|
||||||
|
template<typename C_PARENT>
|
||||||
|
static bool validate_layer(const C_PARENT &c_parent,
|
||||||
|
const CurveTreesUnitTest::Layer<C_PARENT> &parents,
|
||||||
|
const std::vector<typename C_PARENT::Scalar> &child_scalars,
|
||||||
|
const std::size_t max_chunk_size)
|
||||||
|
{
|
||||||
|
// Hash chunk of children scalars, then see if the hash matches up to respective parent
|
||||||
|
std::size_t chunk_start_idx = 0;
|
||||||
|
for (std::size_t i = 0; i < parents.size(); ++i)
|
||||||
|
{
|
||||||
|
CHECK_AND_ASSERT_MES(child_scalars.size() > chunk_start_idx, false, "chunk start too high");
|
||||||
|
const std::size_t chunk_size = std::min(child_scalars.size() - chunk_start_idx, max_chunk_size);
|
||||||
|
CHECK_AND_ASSERT_MES(child_scalars.size() >= (chunk_start_idx + chunk_size), false, "chunk size too large");
|
||||||
|
|
||||||
|
const typename C_PARENT::Point &parent = parents[i];
|
||||||
|
|
||||||
|
const auto chunk_start = child_scalars.data() + chunk_start_idx;
|
||||||
|
const typename C_PARENT::Chunk chunk{chunk_start, chunk_size};
|
||||||
|
|
||||||
|
const typename C_PARENT::Point chunk_hash = fcmp::curve_trees::get_new_parent(c_parent, chunk);
|
||||||
|
|
||||||
|
const auto actual_bytes = c_parent.to_bytes(parent);
|
||||||
|
const auto expected_bytes = c_parent.to_bytes(chunk_hash);
|
||||||
|
CHECK_AND_ASSERT_MES(actual_bytes == expected_bytes, false, "unexpected hash");
|
||||||
|
|
||||||
|
chunk_start_idx += chunk_size;
|
||||||
|
}
|
||||||
|
|
||||||
|
CHECK_AND_ASSERT_THROW_MES(chunk_start_idx == child_scalars.size(), "unexpected ending chunk start idx");
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
//----------------------------------------------------------------------------------------------------------------------
|
||||||
//----------------------------------------------------------------------------------------------------------------------
|
//----------------------------------------------------------------------------------------------------------------------
|
||||||
// CurveTreesUnitTest implementations
|
// CurveTreesUnitTest implementations
|
||||||
//----------------------------------------------------------------------------------------------------------------------
|
//----------------------------------------------------------------------------------------------------------------------
|
||||||
@ -191,7 +224,7 @@ void CurveTreesUnitTest::extend_tree(const CurveTreesV1::TreeExtension &tree_ext
|
|||||||
if (use_c2)
|
if (use_c2)
|
||||||
{
|
{
|
||||||
CHECK_AND_ASSERT_THROW_MES(c2_idx < c2_extensions.size(), "unexpected c2 layer extension");
|
CHECK_AND_ASSERT_THROW_MES(c2_idx < c2_extensions.size(), "unexpected c2 layer extension");
|
||||||
const CurveTreesV1::LayerExtension<Selene> &c2_ext = c2_extensions[c2_idx];
|
const fcmp::curve_trees::LayerExtension<Selene> &c2_ext = c2_extensions[c2_idx];
|
||||||
|
|
||||||
CHECK_AND_ASSERT_THROW_MES(!c2_ext.hashes.empty(), "empty c2 layer extension");
|
CHECK_AND_ASSERT_THROW_MES(!c2_ext.hashes.empty(), "empty c2 layer extension");
|
||||||
|
|
||||||
@ -217,7 +250,7 @@ void CurveTreesUnitTest::extend_tree(const CurveTreesV1::TreeExtension &tree_ext
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
CHECK_AND_ASSERT_THROW_MES(c1_idx < c1_extensions.size(), "unexpected c1 layer extension");
|
CHECK_AND_ASSERT_THROW_MES(c1_idx < c1_extensions.size(), "unexpected c1 layer extension");
|
||||||
const CurveTreesV1::LayerExtension<Helios> &c1_ext = c1_extensions[c1_idx];
|
const fcmp::curve_trees::LayerExtension<Helios> &c1_ext = c1_extensions[c1_idx];
|
||||||
|
|
||||||
CHECK_AND_ASSERT_THROW_MES(!c1_ext.hashes.empty(), "empty c1 layer extension");
|
CHECK_AND_ASSERT_THROW_MES(!c1_ext.hashes.empty(), "empty c1 layer extension");
|
||||||
|
|
||||||
@ -245,39 +278,6 @@ void CurveTreesUnitTest::extend_tree(const CurveTreesV1::TreeExtension &tree_ext
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
//----------------------------------------------------------------------------------------------------------------------
|
//----------------------------------------------------------------------------------------------------------------------
|
||||||
template<typename C_PARENT>
|
|
||||||
bool CurveTreesUnitTest::validate_layer(const C_PARENT &c_parent,
|
|
||||||
const CurveTreesUnitTest::Layer<C_PARENT> &parents,
|
|
||||||
const std::vector<typename C_PARENT::Scalar> &child_scalars,
|
|
||||||
const std::size_t max_chunk_size)
|
|
||||||
{
|
|
||||||
// Hash chunk of children scalars, then see if the hash matches up to respective parent
|
|
||||||
std::size_t chunk_start_idx = 0;
|
|
||||||
for (std::size_t i = 0; i < parents.size(); ++i)
|
|
||||||
{
|
|
||||||
CHECK_AND_ASSERT_MES(child_scalars.size() > chunk_start_idx, false, "chunk start too high");
|
|
||||||
const std::size_t chunk_size = std::min(child_scalars.size() - chunk_start_idx, max_chunk_size);
|
|
||||||
CHECK_AND_ASSERT_MES(child_scalars.size() >= (chunk_start_idx + chunk_size), false, "chunk size too large");
|
|
||||||
|
|
||||||
const typename C_PARENT::Point &parent = parents[i];
|
|
||||||
|
|
||||||
const auto chunk_start = child_scalars.data() + chunk_start_idx;
|
|
||||||
const typename C_PARENT::Chunk chunk{chunk_start, chunk_size};
|
|
||||||
|
|
||||||
const typename C_PARENT::Point chunk_hash = m_curve_trees.get_new_parent(c_parent, chunk);
|
|
||||||
|
|
||||||
const auto actual_bytes = c_parent.to_bytes(parent);
|
|
||||||
const auto expected_bytes = c_parent.to_bytes(chunk_hash);
|
|
||||||
CHECK_AND_ASSERT_MES(actual_bytes == expected_bytes, false, "unexpected hash");
|
|
||||||
|
|
||||||
chunk_start_idx += chunk_size;
|
|
||||||
}
|
|
||||||
|
|
||||||
CHECK_AND_ASSERT_THROW_MES(chunk_start_idx == child_scalars.size(), "unexpected ending chunk start idx");
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
//----------------------------------------------------------------------------------------------------------------------
|
|
||||||
bool CurveTreesUnitTest::validate_tree(const CurveTreesUnitTest::Tree &tree)
|
bool CurveTreesUnitTest::validate_tree(const CurveTreesUnitTest::Tree &tree)
|
||||||
{
|
{
|
||||||
const auto &leaves = tree.leaves;
|
const auto &leaves = tree.leaves;
|
||||||
@ -317,7 +317,7 @@ bool CurveTreesUnitTest::validate_tree(const CurveTreesUnitTest::Tree &tree)
|
|||||||
children,
|
children,
|
||||||
child_scalars);
|
child_scalars);
|
||||||
|
|
||||||
const bool valid = this->validate_layer<Selene>(m_curve_trees.m_c2,
|
const bool valid = validate_layer<Selene>(m_curve_trees.m_c2,
|
||||||
parents,
|
parents,
|
||||||
child_scalars,
|
child_scalars,
|
||||||
m_curve_trees.m_c2_width);
|
m_curve_trees.m_c2_width);
|
||||||
@ -342,7 +342,7 @@ bool CurveTreesUnitTest::validate_tree(const CurveTreesUnitTest::Tree &tree)
|
|||||||
children,
|
children,
|
||||||
child_scalars);
|
child_scalars);
|
||||||
|
|
||||||
const bool valid = this->validate_layer<Helios>(
|
const bool valid = validate_layer<Helios>(
|
||||||
m_curve_trees.m_c1,
|
m_curve_trees.m_c1,
|
||||||
parents,
|
parents,
|
||||||
child_scalars,
|
child_scalars,
|
||||||
@ -357,7 +357,7 @@ bool CurveTreesUnitTest::validate_tree(const CurveTreesUnitTest::Tree &tree)
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Now validate leaves
|
// Now validate leaves
|
||||||
return this->validate_layer<Selene>(m_curve_trees.m_c2,
|
return validate_layer<Selene>(m_curve_trees.m_c2,
|
||||||
c2_layers[0],
|
c2_layers[0],
|
||||||
m_curve_trees.flatten_leaves(leaves),
|
m_curve_trees.flatten_leaves(leaves),
|
||||||
m_curve_trees.m_leaf_layer_chunk_width);
|
m_curve_trees.m_leaf_layer_chunk_width);
|
||||||
@ -382,7 +382,7 @@ void CurveTreesUnitTest::log_last_chunks(const CurveTreesV1::LastChunks &last_ch
|
|||||||
{
|
{
|
||||||
CHECK_AND_ASSERT_THROW_MES(c2_idx < c2_last_chunks.size(), "unexpected c2 layer");
|
CHECK_AND_ASSERT_THROW_MES(c2_idx < c2_last_chunks.size(), "unexpected c2 layer");
|
||||||
|
|
||||||
const CurveTreesV1::LastChunkData<Selene> &last_chunk = c2_last_chunks[c2_idx];
|
const fcmp::curve_trees::LastChunkData<Selene> &last_chunk = c2_last_chunks[c2_idx];
|
||||||
|
|
||||||
MDEBUG("child_offset: " << last_chunk.child_offset
|
MDEBUG("child_offset: " << last_chunk.child_offset
|
||||||
<< " , last_child: " << m_curve_trees.m_c2.to_string(last_chunk.last_child)
|
<< " , last_child: " << m_curve_trees.m_c2.to_string(last_chunk.last_child)
|
||||||
@ -396,7 +396,7 @@ void CurveTreesUnitTest::log_last_chunks(const CurveTreesV1::LastChunks &last_ch
|
|||||||
{
|
{
|
||||||
CHECK_AND_ASSERT_THROW_MES(c1_idx < c1_last_chunks.size(), "unexpected c1 layer");
|
CHECK_AND_ASSERT_THROW_MES(c1_idx < c1_last_chunks.size(), "unexpected c1 layer");
|
||||||
|
|
||||||
const CurveTreesV1::LastChunkData<Helios> &last_chunk = c1_last_chunks[c1_idx];
|
const fcmp::curve_trees::LastChunkData<Helios> &last_chunk = c1_last_chunks[c1_idx];
|
||||||
|
|
||||||
MDEBUG("child_offset: " << last_chunk.child_offset
|
MDEBUG("child_offset: " << last_chunk.child_offset
|
||||||
<< " , last_child: " << m_curve_trees.m_c1.to_string(last_chunk.last_child)
|
<< " , last_child: " << m_curve_trees.m_c1.to_string(last_chunk.last_child)
|
||||||
@ -441,7 +441,7 @@ void CurveTreesUnitTest::log_tree_extension(const CurveTreesV1::TreeExtension &t
|
|||||||
{
|
{
|
||||||
CHECK_AND_ASSERT_THROW_MES(c2_idx < c2_extensions.size(), "unexpected c2 layer");
|
CHECK_AND_ASSERT_THROW_MES(c2_idx < c2_extensions.size(), "unexpected c2 layer");
|
||||||
|
|
||||||
const CurveTreesV1::LayerExtension<Selene> &c2_layer = c2_extensions[c2_idx];
|
const fcmp::curve_trees::LayerExtension<Selene> &c2_layer = c2_extensions[c2_idx];
|
||||||
MDEBUG("Selene tree extension start idx: " << c2_layer.start_idx);
|
MDEBUG("Selene tree extension start idx: " << c2_layer.start_idx);
|
||||||
|
|
||||||
for (std::size_t j = 0; j < c2_layer.hashes.size(); ++j)
|
for (std::size_t j = 0; j < c2_layer.hashes.size(); ++j)
|
||||||
@ -454,7 +454,7 @@ void CurveTreesUnitTest::log_tree_extension(const CurveTreesV1::TreeExtension &t
|
|||||||
{
|
{
|
||||||
CHECK_AND_ASSERT_THROW_MES(c1_idx < c1_extensions.size(), "unexpected c1 layer");
|
CHECK_AND_ASSERT_THROW_MES(c1_idx < c1_extensions.size(), "unexpected c1 layer");
|
||||||
|
|
||||||
const CurveTreesV1::LayerExtension<Helios> &c1_layer = c1_extensions[c1_idx];
|
const fcmp::curve_trees::LayerExtension<Helios> &c1_layer = c1_extensions[c1_idx];
|
||||||
MDEBUG("Helios tree extension start idx: " << c1_layer.start_idx);
|
MDEBUG("Helios tree extension start idx: " << c1_layer.start_idx);
|
||||||
|
|
||||||
for (std::size_t j = 0; j < c1_layer.hashes.size(); ++j)
|
for (std::size_t j = 0; j < c1_layer.hashes.size(); ++j)
|
||||||
@ -582,7 +582,7 @@ static void grow_tree_test(Helios &helios,
|
|||||||
helios_width,
|
helios_width,
|
||||||
selene_width);
|
selene_width);
|
||||||
|
|
||||||
CurveTreesUnitTest curve_trees_accesor{curve_trees};
|
CurveTreesUnitTest curve_trees_accessor{curve_trees};
|
||||||
|
|
||||||
CHECK_AND_ASSERT_THROW_MES(helios_width > 1, "helios width must be > 1");
|
CHECK_AND_ASSERT_THROW_MES(helios_width > 1, "helios width must be > 1");
|
||||||
CHECK_AND_ASSERT_THROW_MES(selene_width > 1, "selene width must be > 1");
|
CHECK_AND_ASSERT_THROW_MES(selene_width > 1, "selene width must be > 1");
|
||||||
@ -629,7 +629,7 @@ static void grow_tree_test(Helios &helios,
|
|||||||
MDEBUG("Adding " << init_leaves << " leaves to tree");
|
MDEBUG("Adding " << init_leaves << " leaves to tree");
|
||||||
|
|
||||||
grow_tree(curve_trees,
|
grow_tree(curve_trees,
|
||||||
curve_trees_accesor,
|
curve_trees_accessor,
|
||||||
init_leaves,
|
init_leaves,
|
||||||
global_tree);
|
global_tree);
|
||||||
|
|
||||||
@ -639,7 +639,7 @@ static void grow_tree_test(Helios &helios,
|
|||||||
MDEBUG("Extending tree by " << ext_leaves << " leaves");
|
MDEBUG("Extending tree by " << ext_leaves << " leaves");
|
||||||
|
|
||||||
grow_tree(curve_trees,
|
grow_tree(curve_trees,
|
||||||
curve_trees_accesor,
|
curve_trees_accessor,
|
||||||
ext_leaves,
|
ext_leaves,
|
||||||
global_tree);
|
global_tree);
|
||||||
|
|
||||||
|
@ -32,11 +32,11 @@
|
|||||||
#include "fcmp/tower_cycle.h"
|
#include "fcmp/tower_cycle.h"
|
||||||
#include "misc_log_ex.h"
|
#include "misc_log_ex.h"
|
||||||
|
|
||||||
using Helios = fcmp::tower_cycle::Helios;
|
using Helios = fcmp::curve_trees::Helios;
|
||||||
using Selene = fcmp::tower_cycle::Selene;
|
using Selene = fcmp::curve_trees::Selene;
|
||||||
|
using CurveTreesV1 = fcmp::curve_trees::CurveTreesV1;
|
||||||
using CurveTreesV1 = fcmp::CurveTrees<Helios, Selene>;
|
|
||||||
|
|
||||||
|
// Helper class that can access the private members of the CurveTrees class
|
||||||
class CurveTreesUnitTest
|
class CurveTreesUnitTest
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
@ -71,14 +71,6 @@ public:
|
|||||||
void log_tree_extension(const CurveTreesV1::TreeExtension &tree_extension);
|
void log_tree_extension(const CurveTreesV1::TreeExtension &tree_extension);
|
||||||
void log_tree(const CurveTreesUnitTest::Tree &tree);
|
void log_tree(const CurveTreesUnitTest::Tree &tree);
|
||||||
|
|
||||||
//private member functions
|
|
||||||
private:
|
|
||||||
template<typename C_PARENT>
|
|
||||||
bool validate_layer(const C_PARENT &c_parent,
|
|
||||||
const Layer<C_PARENT> &parents,
|
|
||||||
const std::vector<typename C_PARENT::Scalar> &child_scalars,
|
|
||||||
const std::size_t max_chunk_size);
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
CurveTreesV1 &m_curve_trees;
|
CurveTreesV1 &m_curve_trees;
|
||||||
};
|
};
|
||||||
|
Loading…
Reference in New Issue
Block a user