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
use blake2_rfc::blake2b::blake2b;
pub use cmmr::helper::{get_peaks, leaf_index_to_mmr_size, leaf_index_to_pos};
use cmmr::{helper, Error, Result};
type Hash = [u8; 32];
pub fn merge(lhs: &[u8], rhs: &[u8]) -> Hash {
let mut data = vec![];
data.append(&mut lhs.to_vec());
data.append(&mut rhs.to_vec());
let mut dest = [0; 32];
dest.copy_from_slice(blake2b(32, &[], &data).as_bytes());
dest
}
pub fn bag_rhs_peaks(mut peaks: Vec<Hash>) -> Result<Hash> {
let last = peaks.pop().ok_or(Error::GenProofForInvalidLeaves)?;
peaks.reverse();
Ok(peaks.iter().fold(last, |prev, &next| merge(&prev, &next)))
}
pub fn gen_proof_positions(
verified_leaf_position: u64,
mmr_size: u64,
) -> (Vec<u64>, Vec<u64>, u64) {
let mut height = 0;
let mut merkle_proof_positions = Vec::new();
let mut pos = verified_leaf_position;
while pos < mmr_size - 1 {
let pos_height = helper::pos_height_in_tree(pos);
let next_height = helper::pos_height_in_tree(pos + 1);
if next_height > pos_height {
let sib = pos - helper::sibling_offset(height);
if sib > mmr_size - 1 {
break;
}
merkle_proof_positions.push(sib);
pos += 1;
} else {
let sib = pos + helper::sibling_offset(height);
if sib > mmr_size - 1 {
break;
}
merkle_proof_positions.push(sib);
pos += 2 << height;
}
height += 1;
}
let peak_positions = get_peaks(mmr_size);
(merkle_proof_positions, peak_positions, pos)
}
pub fn gen_proof(
mut merkle_proof: Vec<Hash>,
peaks: Vec<(u64, Hash)>,
peak_pos_of_verified_leaf: u64,
) -> Vec<Hash> {
let mut proof = peaks
.iter()
.filter(|(pos, _)| pos < &peak_pos_of_verified_leaf)
.map(|(_, h)| *h)
.collect::<Vec<Hash>>();
proof.append(&mut merkle_proof);
let rhs_peaks = peaks
.iter()
.filter(|(pos, _)| pos > &peak_pos_of_verified_leaf)
.map(|(_, h)| *h)
.collect::<Vec<Hash>>();
if let Ok(rhs_peak_hash) = bag_rhs_peaks(rhs_peaks) {
proof.push(rhs_peak_hash);
}
proof
}