utreexo/
lib.rs

1#![forbid(unsafe_code)]
2#![deny(missing_docs, unstable_features)]
3#![cfg_attr(not(any(test, feature = "std")), no_std)]
4
5//! # Utreexo
6extern crate alloc;
7
8mod forest;
9mod hash;
10mod path;
11mod proof;
12
13pub(crate) use self::path::{Direction, Path};
14
15pub use self::forest::Forest;
16pub use self::hash::Hash;
17pub use self::proof::Proof;
18
19use alloc::vec;
20use core::iter::{repeat, Iterator};
21
22use blake2b_simd::{many::update_many, Params};
23
24use self::hash::HASH_SIZE;
25
26/// Calculates hash of a leaf
27pub(crate) fn hash_leaf<T: AsRef<[u8]>>(value: T) -> Hash {
28    let mut params = Params::default();
29    params.hash_length(HASH_SIZE);
30
31    let mut state = params.to_state();
32
33    // Add `0` byte to leaf nodes to prevent second preimage attack
34    // https://en.wikipedia.org/wiki/Merkle_tree#Second_preimage_attack
35    state.update(&[0]);
36    state.update(value.as_ref());
37
38    state.finalize().into()
39}
40
41/// Calculates hash of many leaves
42pub(crate) fn hash_many_leaves<T: AsRef<[u8]>>(values: &[T]) -> impl Iterator<Item = Hash> {
43    let mut params = Params::default();
44    params.hash_length(HASH_SIZE);
45
46    let mut states = vec![params.to_state(); values.len()];
47
48    // Add `0` byte to leaf nodes to prevent second preimage attack
49    // https://en.wikipedia.org/wiki/Merkle_tree#Second_preimage_attack
50    update_many(states.iter_mut().zip(repeat(&[0]).take(values.len())));
51    update_many(states.iter_mut().zip(values.iter()));
52
53    states.into_iter().map(|state| state.finalize().into())
54}
55
56pub(crate) fn hash_intermediate<T: AsRef<[u8]>>(a: T, b: T) -> Hash {
57    let mut params = Params::default();
58    params.hash_length(HASH_SIZE);
59
60    let mut state = params.to_state();
61
62    // Add `1` byte to intermediate nodes to prevent second preimage attack
63    // https://en.wikipedia.org/wiki/Merkle_tree#Second_preimage_attack
64    state.update(&[1]);
65    state.update(a.as_ref());
66    state.update(b.as_ref());
67
68    state.finalize().into()
69}