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
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
use crate::{
errors::MerkleError,
traits::{MerkleParameters, CRH},
};
use snarkvm_utilities::{FromBytes, ToBytes};
use std::{
io::{Read, Result as IoResult, Write},
sync::Arc,
};
pub type MerkleTreeDigest<P> = <<P as MerkleParameters>::H as CRH>::Output;
#[derive(Clone, Debug)]
pub struct MerklePath<P: MerkleParameters> {
pub parameters: Arc<P>,
pub path: Vec<MerkleTreeDigest<P>>,
pub leaf_index: u64,
}
impl<P: MerkleParameters> MerklePath<P> {
pub fn verify<L: ToBytes>(&self, root_hash: &MerkleTreeDigest<P>, leaf: &L) -> Result<bool, MerkleError> {
if !self.path.is_empty() {
let claimed_leaf_hash = self.parameters.hash_leaf::<L>(leaf)?;
let mut index = self.leaf_index;
let mut curr_path_node = claimed_leaf_hash;
for level in 0..self.path.len() {
let (left_bytes, right_bytes) =
Self::select_left_right_bytes(index, &curr_path_node, &self.path[level])?;
curr_path_node = self.parameters.hash_inner_node(&left_bytes, &right_bytes)?;
index >>= 1;
}
if &curr_path_node != root_hash {
return Ok(false);
}
Ok(true)
} else {
Ok(false)
}
}
fn select_left_right_bytes(
index: u64,
computed_hash: &<P::H as CRH>::Output,
sibling_hash: &<P::H as CRH>::Output,
) -> Result<(<P::H as CRH>::Output, <P::H as CRH>::Output), MerkleError> {
let is_left = index & 1 == 0;
let mut left_bytes = computed_hash;
let mut right_bytes = sibling_hash;
if !is_left {
core::mem::swap(&mut left_bytes, &mut right_bytes);
}
Ok((*left_bytes, *right_bytes))
}
pub fn position_list(&self) -> impl Iterator<Item = bool> + '_ {
(0..self.path.len()).map(move |i| ((self.leaf_index >> i) & 1) != 0)
}
}
impl<P: MerkleParameters> FromBytes for MerklePath<P> {
#[inline]
fn read_le<R: Read>(mut reader: R) -> IoResult<Self> {
let parameters = {
let setup_message_length: u64 = FromBytes::read_le(&mut reader)?;
let mut setup_message_bytes = vec![0u8; setup_message_length as usize];
reader.read_exact(&mut setup_message_bytes)?;
let setup_message =
String::from_utf8(setup_message_bytes).expect("Failed to parse setup message for Merkle parameters");
Arc::new(P::setup(&setup_message))
};
let path_length: u64 = FromBytes::read_le(&mut reader)?;
let mut path = Vec::with_capacity(path_length as usize);
for _ in 0..path_length {
path.push(FromBytes::read_le(&mut reader)?);
}
let leaf_index: u64 = FromBytes::read_le(&mut reader)?;
Ok(Self {
parameters,
path,
leaf_index,
})
}
}
impl<P: MerkleParameters> ToBytes for MerklePath<P> {
#[inline]
fn write_le<W: Write>(&self, mut writer: W) -> IoResult<()> {
let setup_message_bytes: &[u8] = self.parameters.setup_message().as_bytes();
let setup_message_length: u64 = setup_message_bytes.len() as u64;
setup_message_length.write_le(&mut writer)?;
setup_message_bytes.write_le(&mut writer)?;
(self.path.len() as u64).write_le(&mut writer)?;
self.path.write_le(&mut writer)?;
self.leaf_index.write_le(&mut writer)
}
}
impl<P: MerkleParameters> Default for MerklePath<P> {
fn default() -> Self {
let mut path = Vec::with_capacity(P::DEPTH);
for _i in 0..P::DEPTH {
path.push(MerkleTreeDigest::<P>::default());
}
Self {
parameters: Arc::new(P::setup("unsafe")),
path,
leaf_index: 0,
}
}
}