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
extern crate crypto;
use crypto::digest::Digest;
mod error;
pub use error::MerkleTreeError;
type Hash = Vec<u8>;
type Round = Vec<Hash>;
pub struct MerkleTree<D: Digest> {
digest: D,
state: Vec<Hash>,
}
impl<D: Digest> MerkleTree<D> {
pub fn new(digest: D) -> MerkleTree<D> {
let state = Vec::new();
MerkleTree { digest, state }
}
pub fn add_hash<H: Into<Hash>>(&mut self, hash: H) {
self.state.push(hash.into());
}
pub fn root(&mut self) -> Result<Hash, MerkleTreeError> {
if self.state.len() < 2 {
return Err(MerkleTreeError::NotEnoughHashes)
}
let mut current_round = self.state.clone() as Round;
loop {
current_round = self.round(current_round);
if current_round.len() == 1 {
return Ok(current_round[0].clone());
}
}
}
fn round(&mut self, prev_round: Round) -> Round {
prev_round
.chunks(2)
.map(|chunk| if chunk.len() == 2 {
self.digest.input(&chunk[0]);
self.digest.input(&chunk[1]);
let mut pair_hash = vec![0; self.digest.output_bytes()];
self.digest.result(&mut pair_hash);
self.digest.reset();
pair_hash
} else {
chunk[0].clone()
})
.collect()
}
}
pub mod crypto_reexport {
pub use crypto::*;
}