lambdaworks_crypto/merkle_tree/backends/
field_element.rs1use crate::hash::poseidon::Poseidon;
2
3use crate::merkle_tree::traits::IsMerkleTreeBackend;
4use core::marker::PhantomData;
5use lambdaworks_math::{
6 field::{element::FieldElement, traits::IsField},
7 traits::AsBytes,
8};
9use sha3::{
10 digest::{generic_array::GenericArray, OutputSizeUser},
11 Digest,
12};
13
14#[derive(Clone)]
15pub struct FieldElementBackend<F, D: Digest, const NUM_BYTES: usize> {
16 phantom1: PhantomData<F>,
17 phantom2: PhantomData<D>,
18}
19
20impl<F, D: Digest, const NUM_BYTES: usize> Default for FieldElementBackend<F, D, NUM_BYTES> {
21 fn default() -> Self {
22 Self {
23 phantom1: PhantomData,
24 phantom2: PhantomData,
25 }
26 }
27}
28
29impl<F, D: Digest, const NUM_BYTES: usize> IsMerkleTreeBackend
30 for FieldElementBackend<F, D, NUM_BYTES>
31where
32 F: IsField,
33 FieldElement<F>: AsBytes + Sync + Send,
34 [u8; NUM_BYTES]: From<GenericArray<u8, <D as OutputSizeUser>::OutputSize>>,
35{
36 type Node = [u8; NUM_BYTES];
37 type Data = FieldElement<F>;
38
39 fn hash_data(input: &FieldElement<F>) -> [u8; NUM_BYTES] {
40 let mut hasher = D::new();
41 hasher.update(input.as_bytes());
42 hasher.finalize().into()
43 }
44
45 fn hash_new_parent(left: &[u8; NUM_BYTES], right: &[u8; NUM_BYTES]) -> [u8; NUM_BYTES] {
46 let mut hasher = D::new();
47 hasher.update(left);
48 hasher.update(right);
49 hasher.finalize().into()
50 }
51}
52
53#[derive(Clone, Default)]
54pub struct TreePoseidon<P: Poseidon + Default> {
55 _poseidon: PhantomData<P>,
56}
57
58impl<P> IsMerkleTreeBackend for TreePoseidon<P>
59where
60 P: Poseidon + Default,
61 FieldElement<P::F>: Sync + Send,
62{
63 type Node = FieldElement<P::F>;
64 type Data = FieldElement<P::F>;
65
66 fn hash_data(input: &FieldElement<P::F>) -> FieldElement<P::F> {
67 P::hash_single(input)
68 }
69
70 fn hash_new_parent(
71 left: &FieldElement<P::F>,
72 right: &FieldElement<P::F>,
73 ) -> FieldElement<P::F> {
74 P::hash(left, right)
75 }
76}
77
78#[cfg(test)]
79mod tests {
80 use alloc::vec::Vec;
81 use lambdaworks_math::field::{
82 element::FieldElement, fields::fft_friendly::stark_252_prime_field::Stark252PrimeField,
83 };
84 use sha3::{Keccak256, Keccak512, Sha3_256, Sha3_512};
85
86 use crate::merkle_tree::{backends::field_element::FieldElementBackend, merkle::MerkleTree};
87
88 type F = Stark252PrimeField;
89 type FE = FieldElement<F>;
90
91 #[test]
92 fn hash_data_field_element_backend_works_with_keccak_256() {
93 let values: Vec<FE> = (1..6).map(FE::from).collect();
94 let merkle_tree =
95 MerkleTree::<FieldElementBackend<F, Keccak256, 32>>::build(&values).unwrap();
96 let proof = merkle_tree.get_proof_by_pos(0).unwrap();
97 assert!(proof.verify::<FieldElementBackend<F, Keccak256, 32>>(
98 &merkle_tree.root,
99 0,
100 &values[0]
101 ));
102 }
103
104 #[test]
105 fn hash_data_field_element_backend_works_with_sha3_256() {
106 let values: Vec<FE> = (1..6).map(FE::from).collect();
107 let merkle_tree =
108 MerkleTree::<FieldElementBackend<F, Sha3_256, 32>>::build(&values).unwrap();
109 let proof = merkle_tree.get_proof_by_pos(0).unwrap();
110 assert!(proof.verify::<FieldElementBackend<F, Sha3_256, 32>>(
111 &merkle_tree.root,
112 0,
113 &values[0]
114 ));
115 }
116
117 #[test]
118 fn hash_data_field_element_backend_works_with_keccak_512() {
119 let values: Vec<FE> = (1..6).map(FE::from).collect();
120 let merkle_tree =
121 MerkleTree::<FieldElementBackend<F, Keccak512, 64>>::build(&values).unwrap();
122 let proof = merkle_tree.get_proof_by_pos(0).unwrap();
123 assert!(proof.verify::<FieldElementBackend<F, Keccak512, 64>>(
124 &merkle_tree.root,
125 0,
126 &values[0]
127 ));
128 }
129
130 #[test]
131 fn hash_data_field_element_backend_works_with_sha3_512() {
132 let values: Vec<FE> = (1..6).map(FE::from).collect();
133 let merkle_tree =
134 MerkleTree::<FieldElementBackend<F, Sha3_512, 64>>::build(&values).unwrap();
135 let proof = merkle_tree.get_proof_by_pos(0).unwrap();
136 assert!(proof.verify::<FieldElementBackend<F, Sha3_512, 64>>(
137 &merkle_tree.root,
138 0,
139 &values[0]
140 ));
141 }
142}