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
use crate::{bits::ToBytesGadget, integers::uint::UInt8, traits::algorithms::MaskedCRHGadget};
use snarkvm_algorithms::traits::CRH;
use snarkvm_fields::PrimeField;
use snarkvm_r1cs::{errors::SynthesisError, ConstraintSystem};
pub fn compute_root<H: CRH, HG: MaskedCRHGadget<H, F>, F: PrimeField, TB: ToBytesGadget<F>, CS: ConstraintSystem<F>>(
mut cs: CS,
parameters: &HG::ParametersGadget,
mask_parameters: &HG::ParametersGadget,
mask: &TB,
leaves: &[HG::OutputGadget],
) -> Result<HG::OutputGadget, SynthesisError> {
let mask_bytes = mask.to_bytes(cs.ns(|| "mask to bytes"))?;
let mut current_leaves = leaves.to_vec();
let mut level = 0;
while current_leaves.len() != 1 {
current_leaves = current_leaves
.chunks(2)
.enumerate()
.map(|(i, left_right)| {
let inner_hash = hash_inner_node_gadget::<H, HG, F, _, _>(
cs.ns(|| format!("hash left right {} on level {}", i, level)),
parameters,
&left_right[0],
&left_right[1],
mask_parameters,
mask_bytes.clone(),
);
inner_hash
})
.collect::<Result<Vec<_>, _>>()?;
level += 1;
}
let computed_root = current_leaves[0].clone();
Ok(computed_root)
}
pub(crate) fn hash_inner_node_gadget<H, HG, F, TB, CS>(
mut cs: CS,
parameters: &HG::ParametersGadget,
left_child: &TB,
right_child: &TB,
mask_parameters: &HG::ParametersGadget,
mask: Vec<UInt8>,
) -> Result<HG::OutputGadget, SynthesisError>
where
F: PrimeField,
CS: ConstraintSystem<F>,
H: CRH,
HG: MaskedCRHGadget<H, F>,
TB: ToBytesGadget<F>,
{
let left_bytes = left_child.to_bytes(&mut cs.ns(|| "left_to_bytes"))?;
let right_bytes = right_child.to_bytes(&mut cs.ns(|| "right_to_bytes"))?;
let bytes = [left_bytes, right_bytes].concat();
HG::check_evaluation_gadget_masked(cs, parameters, bytes, mask_parameters, mask)
}