-
Notifications
You must be signed in to change notification settings - Fork 154
/
Copy pathutils.rs
144 lines (118 loc) · 4.61 KB
/
utils.rs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
use alloc::vec::Vec;
use super::traits::IsMerkleTreeBackend;
#[cfg(feature = "parallel")]
use rayon::prelude::*;
pub fn sibling_index(node_index: usize) -> usize {
if node_index % 2 == 0 {
node_index - 1
} else {
node_index + 1
}
}
pub fn parent_index(node_index: usize) -> usize {
if node_index % 2 == 0 {
(node_index - 1) / 2
} else {
node_index / 2
}
}
// The list of values is completed repeating the last value to a power of two length
pub fn complete_until_power_of_two<T: Clone>(mut values: Vec<T>) -> Vec<T> {
while !is_power_of_two(values.len()) {
values.push(values[values.len() - 1].clone());
}
values
}
// ! NOTE !
// In this function we say 2^0 = 1 is a power of two.
// In turn, this makes the smallest tree of one leaf, possible.
// The function is private and is only used to ensure the tree
// has a power of 2 number of leaves.
fn is_power_of_two(x: usize) -> bool {
(x & (x - 1)) == 0
}
// ! CAUTION !
// Make sure n=nodes.len()+1 is a power of two, and the last n/2 elements (leaves) are populated with hashes.
// This function takes no precautions for other cases.
pub fn build<B: IsMerkleTreeBackend>(nodes: &mut [B::Node], leaves_len: usize)
where
B::Node: Clone,
{
let mut level_begin_index = leaves_len - 1;
let mut level_end_index = 2 * level_begin_index;
while level_begin_index != level_end_index {
let new_level_begin_index = level_begin_index / 2;
let new_level_length = level_begin_index - new_level_begin_index;
let (new_level_iter, children_iter) =
nodes[new_level_begin_index..level_end_index + 1].split_at_mut(new_level_length);
#[cfg(feature = "parallel")]
let parent_and_children_zipped_iter = new_level_iter
.into_par_iter()
.zip(children_iter.par_chunks_exact(2));
#[cfg(not(feature = "parallel"))]
let parent_and_children_zipped_iter =
new_level_iter.iter_mut().zip(children_iter.chunks_exact(2));
parent_and_children_zipped_iter.for_each(|(new_parent, children)| {
*new_parent = B::hash_new_parent(&children[0], &children[1]);
});
level_end_index = level_begin_index - 1;
level_begin_index = new_level_begin_index;
}
}
#[cfg(test)]
mod tests {
use alloc::vec::Vec;
use lambdaworks_math::field::{element::FieldElement, fields::u64_prime_field::U64PrimeField};
use crate::merkle_tree::{test_merkle::TestBackend, traits::IsMerkleTreeBackend};
use super::{build, complete_until_power_of_two};
const MODULUS: u64 = 13;
type U64PF = U64PrimeField<MODULUS>;
type FE = FieldElement<U64PF>;
#[test]
fn build_merkle_tree_one_element_must_succeed() {
let mut nodes = [FE::zero()];
build::<TestBackend<U64PF>>(&mut nodes, 1);
}
#[test]
// expected |2|4|6|8|
fn hash_leaves_from_a_list_of_field_elemnts() {
let values: Vec<FE> = (1..5).map(FE::new).collect();
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);
}
}
#[test]
// expected |1|2|3|4|5|5|5|5|
fn complete_the_length_of_a_list_of_fields_elements_to_be_a_power_of_two() {
let values: Vec<FE> = (1..6).map(FE::new).collect();
let hashed_leaves = complete_until_power_of_two(values);
let mut expected_leaves = (1..6).map(FE::new).collect::<Vec<FE>>();
expected_leaves.extend([FE::new(5); 3]);
for (leaf, expected_leaves) in hashed_leaves.iter().zip(expected_leaves) {
assert_eq!(*leaf, expected_leaves);
}
}
#[test]
// expected |2|2|
fn complete_the_length_of_one_field_element_to_be_a_power_of_two() {
let values: Vec<FE> = vec![FE::new(2)];
let hashed_leaves = complete_until_power_of_two(values);
let mut expected_leaves = vec![FE::new(2)];
expected_leaves.extend([FE::new(2)]);
assert_eq!(hashed_leaves.len(), 1);
assert_eq!(hashed_leaves[0], expected_leaves[0]);
}
const ROOT: usize = 0;
#[test]
// expected |10|10|13|3|7|11|2|1|2|3|4|5|6|7|8|
fn complete_a_merkle_tree_from_a_set_of_leaves() {
let leaves: Vec<FE> = (1..9).map(FE::new).collect();
let leaves_len = leaves.len();
let mut nodes = vec![FE::zero(); leaves.len() - 1];
nodes.extend(leaves);
build::<TestBackend<U64PF>>(&mut nodes, leaves_len);
assert_eq!(nodes[ROOT], FE::new(10));
}
}