jam_std_common/crypto/
mmr.rs

1use super::hashing::keccak_concat;
2use jam_types::{Hash, MmrPeakHash};
3use scale::{Decode, Encode};
4
5#[derive(Debug, Encode, Decode, Eq, PartialEq, Clone, Default)]
6pub struct Mmr {
7	pub peaks: Vec<Option<Hash>>,
8}
9
10impl Mmr {
11	/// Construct an empty MMR.
12	pub fn new() -> Self {
13		Default::default()
14	}
15
16	/// Append a new peak to the MMR.
17	pub fn append(&mut self, mut peak: Hash) {
18		for height in 0..usize::MAX {
19			match self.peaks.get_mut(height) {
20				None => {
21					self.peaks.push(Some(peak));
22					break
23				},
24				Some(p) => match p.take() {
25					None => {
26						*p = Some(peak);
27						break
28					},
29					Some(left) => peak = keccak_concat([&left[..], &peak[..]]),
30				},
31			}
32		}
33	}
34
35	/// MMR root.
36	pub fn root(&self) -> MmrPeakHash {
37		let mut iter = self.peaks.iter().filter_map(Option::as_ref);
38		let mut root = iter.next().cloned().unwrap_or_default();
39		for node in iter {
40			root = keccak_concat([b"peak", &root[..], &node[..]]);
41		}
42		root.into()
43	}
44}