+impl IsMerkleTreeBackend for TreePoseidon
where
- F: IsPrimeField,
+ P: Poseidon + Default,
+ FieldElement: Sync + Send,
{
- fn default() -> Self {
- let params = PermutationParameters::new_with(DefaultPoseidonParams::CairoStark252);
- let poseidon = Poseidon::new_with_params(params);
-
- Self { poseidon }
- }
-}
-
-impl IsMerkleTreeBackend for TreePoseidon
-where
- F: IsPrimeField,
-{
- type Node = FieldElement;
- type Data = FieldElement;
+ type Node = FieldElement;
+ type Data = FieldElement;
- fn hash_data(&self, input: &FieldElement) -> FieldElement {
- self.poseidon.hash_single(input)
+ fn hash_data(input: &FieldElement) -> FieldElement {
+ P::hash_single(input)
}
- fn hash_new_parent(&self, left: &FieldElement, right: &FieldElement) -> FieldElement {
- self.poseidon.hash(left, right)
+ fn hash_new_parent(
+ left: &FieldElement,
+ right: &FieldElement,
+ ) -> FieldElement {
+ P::hash(left, right)
}
}
diff --git a/crypto/src/merkle_tree/backends/field_element_vector.rs b/crypto/src/merkle_tree/backends/field_element_vector.rs
index dd245001a6..509c56752c 100644
--- a/crypto/src/merkle_tree/backends/field_element_vector.rs
+++ b/crypto/src/merkle_tree/backends/field_element_vector.rs
@@ -1,13 +1,9 @@
use std::marker::PhantomData;
-use crate::hash::poseidon::starknet::parameters::{DefaultPoseidonParams, PermutationParameters};
-use crate::hash::poseidon::starknet::Poseidon;
+use crate::hash::poseidon::Poseidon;
use crate::merkle_tree::traits::IsMerkleTreeBackend;
use lambdaworks_math::{
- field::{
- element::FieldElement,
- traits::{IsField, IsPrimeField},
- },
+ field::{element::FieldElement, traits::IsField},
traits::Serializable,
};
use sha3::{
@@ -36,11 +32,12 @@ where
F: IsField,
FieldElement: Serializable,
[u8; NUM_BYTES]: From::OutputSize>>,
+ Vec>: Sync + Send,
{
type Node = [u8; NUM_BYTES];
type Data = Vec>;
- fn hash_data(&self, input: &Vec>) -> [u8; NUM_BYTES] {
+ fn hash_data(input: &Vec>) -> [u8; NUM_BYTES] {
let mut hasher = D::new();
for element in input.iter() {
hasher.update(element.serialize());
@@ -50,7 +47,7 @@ where
result_hash
}
- fn hash_new_parent(&self, left: &[u8; NUM_BYTES], right: &[u8; NUM_BYTES]) -> [u8; NUM_BYTES] {
+ fn hash_new_parent(left: &[u8; NUM_BYTES], right: &[u8; NUM_BYTES]) -> [u8; NUM_BYTES] {
let mut hasher = D::new();
hasher.update(left);
hasher.update(right);
@@ -60,36 +57,29 @@ where
}
}
-#[derive(Clone)]
-pub struct BatchPoseidonTree {
- poseidon: Poseidon,
+#[derive(Clone, Default)]
+pub struct BatchPoseidonTree {
+ _poseidon: PhantomData,
}
-impl Default for BatchPoseidonTree
+impl IsMerkleTreeBackend for BatchPoseidonTree
where
- F: IsPrimeField,
+ P: Poseidon + Default,
+ Vec>: Sync + Send,
+ FieldElement: Sync + Send,
{
- fn default() -> Self {
- let params = PermutationParameters::new_with(DefaultPoseidonParams::CairoStark252);
- let poseidon = Poseidon::new_with_params(params);
-
- Self { poseidon }
- }
-}
-
-impl IsMerkleTreeBackend for BatchPoseidonTree
-where
- F: IsPrimeField,
-{
- type Node = FieldElement;
- type Data = Vec>;
+ type Node = FieldElement;
+ type Data = Vec>;
- fn hash_data(&self, input: &Vec>) -> FieldElement {
- self.poseidon.hash_many(input)
+ fn hash_data(input: &Vec>) -> FieldElement {
+ P::hash_many(input)
}
- fn hash_new_parent(&self, left: &FieldElement, right: &FieldElement) -> FieldElement {
- self.poseidon.hash(left, right)
+ fn hash_new_parent(
+ left: &FieldElement,
+ right: &FieldElement,
+ ) -> FieldElement {
+ P::hash(left, right)
}
}
diff --git a/crypto/src/merkle_tree/merkle.rs b/crypto/src/merkle_tree/merkle.rs
index e97d821f5b..a7ff332444 100644
--- a/crypto/src/merkle_tree/merkle.rs
+++ b/crypto/src/merkle_tree/merkle.rs
@@ -13,8 +13,7 @@ where
B: IsMerkleTreeBackend,
{
pub fn build(unhashed_leaves: &[B::Data]) -> Self {
- let hasher = B::default();
- let mut hashed_leaves: Vec = hasher.hash_leaves(unhashed_leaves);
+ let mut hashed_leaves: Vec = B::hash_leaves(unhashed_leaves);
//The leaf must be a power of 2 set
hashed_leaves = complete_until_power_of_two(&mut hashed_leaves);
@@ -26,7 +25,7 @@ where
inner_nodes.extend(hashed_leaves);
//Build the inner nodes of the tree
- build(&mut inner_nodes, ROOT, &hasher);
+ build::(&mut inner_nodes, ROOT);
MerkleTree {
root: inner_nodes[ROOT].clone(),
diff --git a/crypto/src/merkle_tree/proof.rs b/crypto/src/merkle_tree/proof.rs
index c2914cf503..21c1b9c746 100644
--- a/crypto/src/merkle_tree/proof.rs
+++ b/crypto/src/merkle_tree/proof.rs
@@ -20,14 +20,13 @@ impl Proof {
where
B: IsMerkleTreeBackend,
{
- let hasher = B::default();
- let mut hashed_value = hasher.hash_data(value);
+ let mut hashed_value = B::hash_data(value);
for sibling_node in self.merkle_path.iter() {
if index % 2 == 0 {
- hashed_value = hasher.hash_new_parent(&hashed_value, sibling_node);
+ hashed_value = B::hash_new_parent(&hashed_value, sibling_node);
} else {
- hashed_value = hasher.hash_new_parent(sibling_node, &hashed_value);
+ hashed_value = B::hash_new_parent(sibling_node, &hashed_value);
}
index >>= 1;
diff --git a/crypto/src/merkle_tree/test_merkle.rs b/crypto/src/merkle_tree/test_merkle.rs
index 076e26fce7..4fc8e2cdc1 100644
--- a/crypto/src/merkle_tree/test_merkle.rs
+++ b/crypto/src/merkle_tree/test_merkle.rs
@@ -23,15 +23,18 @@ impl Default for TestBackend {
}
}
-impl IsMerkleTreeBackend for TestBackend {
+impl IsMerkleTreeBackend for TestBackend
+where
+ FieldElement: Sync + Send,
+{
type Node = FieldElement;
type Data = FieldElement;
- fn hash_data(&self, input: &Self::Data) -> Self::Node {
+ fn hash_data(input: &Self::Data) -> Self::Node {
input + input
}
- fn hash_new_parent(&self, left: &Self::Node, right: &Self::Node) -> Self::Node {
+ fn hash_new_parent(left: &Self::Node, right: &Self::Node) -> Self::Node {
left + right
}
}
diff --git a/crypto/src/merkle_tree/traits.rs b/crypto/src/merkle_tree/traits.rs
index e8e010eb0f..dce3e253b6 100644
--- a/crypto/src/merkle_tree/traits.rs
+++ b/crypto/src/merkle_tree/traits.rs
@@ -1,23 +1,28 @@
+#[cfg(feature = "parallel")]
+use rayon::prelude::{IntoParallelRefIterator, ParallelIterator};
+
/// A backend for Merkle trees. This defines raw `Data` from which the Merkle
/// tree is built from. It also defines the `Node` type and the hash function
/// used to build parent nodes from children nodes.
pub trait IsMerkleTreeBackend: Default {
- type Node: PartialEq + Eq + Clone;
- type Data;
+ type Node: PartialEq + Eq + Clone + Sync + Send;
+ type Data: Sync + Send;
/// This function takes a single variable `Data` and converts it to a node.
- fn hash_data(&self, leaf: &Self::Data) -> Self::Node;
+ fn hash_data(leaf: &Self::Data) -> Self::Node;
/// This function takes the list of data from which the Merkle
/// tree will be built from and converts it to a list of leaf nodes.
- fn hash_leaves(&self, unhashed_leaves: &[Self::Data]) -> Vec {
- unhashed_leaves
- .iter()
- .map(|leaf| self.hash_data(leaf))
- .collect()
+ fn hash_leaves(unhashed_leaves: &[Self::Data]) -> Vec {
+ #[cfg(feature = "parallel")]
+ let iter = unhashed_leaves.par_iter();
+ #[cfg(not(feature = "parallel"))]
+ let iter = unhashed_leaves.iter();
+
+ iter.map(|leaf| Self::hash_data(leaf)).collect()
}
/// This function takes to children nodes and builds a new parent node.
/// It will be used in the construction of the Merkle tree.
- fn hash_new_parent(&self, child_1: &Self::Node, child_2: &Self::Node) -> Self::Node;
+ fn hash_new_parent(child_1: &Self::Node, child_2: &Self::Node) -> Self::Node;
}
diff --git a/crypto/src/merkle_tree/utils.rs b/crypto/src/merkle_tree/utils.rs
index 64dc0de833..ab76176bb7 100644
--- a/crypto/src/merkle_tree/utils.rs
+++ b/crypto/src/merkle_tree/utils.rs
@@ -28,7 +28,7 @@ pub fn is_power_of_two(x: usize) -> bool {
(x != 0) && ((x & (x - 1)) == 0)
}
-pub fn build(nodes: &mut Vec, parent_index: usize, hasher: &B)
+pub fn build(nodes: &mut Vec, parent_index: usize)
where
B::Node: Clone,
{
@@ -39,11 +39,10 @@ where
let left_child_index = left_child_index(parent_index);
let right_child_index = right_child_index(parent_index);
- build(nodes, left_child_index, hasher);
- build(nodes, right_child_index, hasher);
+ build::(nodes, left_child_index);
+ build::(nodes, right_child_index);
- nodes[parent_index] =
- hasher.hash_new_parent(&nodes[left_child_index], &nodes[right_child_index]);
+ nodes[parent_index] = B::hash_new_parent(&nodes[left_child_index], &nodes[right_child_index]);
}
pub fn is_leaf(lenght: usize, node_index: usize) -> bool {
@@ -73,8 +72,7 @@ mod tests {
// expected |2|4|6|8|
fn hash_leaves_from_a_list_of_field_elemnts() {
let values: Vec = (1..5).map(FE::new).collect();
- let hasher = TestBackend::default();
- let hashed_leaves = hasher.hash_leaves(&values);
+ let hashed_leaves = TestBackend::hash_leaves(&values);
let list_of_nodes = &[FE::new(2), FE::new(4), FE::new(6), FE::new(8)];
for (leaf, expected_leaf) in hashed_leaves.iter().zip(list_of_nodes) {
assert_eq!(leaf, expected_leaf);
@@ -105,8 +103,7 @@ mod tests {
let mut nodes = vec![FE::zero(); leaves.len() - 1];
nodes.extend(leaves);
- let hasher = TestBackend::default();
- build::>(&mut nodes, ROOT, &hasher);
+ build::>(&mut nodes, ROOT);
assert_eq!(nodes[ROOT], FE::new(10));
}
}
diff --git a/examples/merkle-tree-cli/src/main.rs b/examples/merkle-tree-cli/src/main.rs
index 9817bf39d6..b23b3f5e1d 100644
--- a/examples/merkle-tree-cli/src/main.rs
+++ b/examples/merkle-tree-cli/src/main.rs
@@ -1,13 +1,12 @@
mod commands;
use clap::Parser;
use commands::{MerkleArgs, MerkleEntity};
-use lambdaworks_crypto::{
- hash::poseidon::Poseidon,
- merkle_tree::{merkle::MerkleTree, proof::Proof},
+use lambdaworks_crypto::hash::poseidon::starknet::PoseidonCairoStark252;
+use lambdaworks_crypto::merkle_tree::{
+ backends::field_element::TreePoseidon, merkle::MerkleTree, proof::Proof,
};
-use lambdaworks_math::{
- elliptic_curve::short_weierstrass::curves::bls12_381::field_extension::BLS12381PrimeField,
- field::element::FieldElement,
+use lambdaworks_math::field::{
+ element::FieldElement, fields::fft_friendly::stark_252_prime_field::Stark252PrimeField,
};
use std::io::BufWriter;
use std::{
@@ -15,7 +14,7 @@ use std::{
io::{self, Write},
};
-type FE = FieldElement;
+type FE = FieldElement;
fn load_fe_from_file(file_path: &String) -> Result {
FE::from_hex(&fs::read_to_string(file_path)?.replace('\n', ""))
@@ -32,7 +31,7 @@ fn load_tree_values(tree_path: &String) -> Result, io::Error> {
fn generate_merkle_tree(tree_path: String) -> Result<(), io::Error> {
let values: Vec