tendermint/
merkle.rs

1//! Merkle tree used in Tendermint networks
2
3pub mod proof;
4
5pub use proof::Proof;
6
7use core::marker::PhantomData;
8
9use digest::{consts::U32, Digest, FixedOutputReset};
10
11use crate::crypto::Sha256;
12use crate::prelude::*;
13
14/// Size of Merkle root hash
15pub use crate::crypto::sha256::HASH_SIZE;
16
17/// Hash is the output of the cryptographic digest function
18pub type Hash = [u8; HASH_SIZE];
19
20/// Compute a simple Merkle root from vectors of arbitrary byte vectors.
21/// The leaves of the tree are the bytes of the given byte vectors in
22/// the given order.
23pub fn simple_hash_from_byte_vectors<H>(byte_vecs: &[impl AsRef<[u8]>]) -> Hash
24where
25    H: MerkleHash + Default,
26{
27    let mut hasher = H::default();
28    hasher.hash_byte_vectors(byte_vecs)
29}
30
31/// Implementation of Merkle tree hashing for Tendermint.
32pub trait MerkleHash {
33    // tmhash({})
34    // Pre and post-conditions: the hasher is in the reset state
35    // before and after calling this function.
36    fn empty_hash(&mut self) -> Hash;
37
38    // tmhash(0x00 || leaf)
39    // Pre and post-conditions: the hasher is in the reset state
40    // before and after calling this function.
41    fn leaf_hash(&mut self, bytes: &[u8]) -> Hash;
42
43    // tmhash(0x01 || left || right)
44    // Pre and post-conditions: the hasher is in the reset state
45    // before and after calling this function.
46    fn inner_hash(&mut self, left: Hash, right: Hash) -> Hash;
47
48    // Implements recursion into subtrees.
49    // Pre and post-conditions: the hasher is in the reset state
50    // before and after calling this function.
51    fn hash_byte_vectors(&mut self, byte_vecs: &[impl AsRef<[u8]>]) -> Hash {
52        let length = byte_vecs.len();
53        match length {
54            0 => self.empty_hash(),
55            1 => self.leaf_hash(byte_vecs[0].as_ref()),
56            _ => {
57                let split = length.next_power_of_two() / 2;
58                let left = self.hash_byte_vectors(&byte_vecs[..split]);
59                let right = self.hash_byte_vectors(&byte_vecs[split..]);
60                self.inner_hash(left, right)
61            },
62        }
63    }
64}
65
66// A helper to copy GenericArray into the human-friendly Hash type.
67fn copy_to_hash(output: impl AsRef<[u8]>) -> Hash {
68    let mut hash_bytes = [0u8; HASH_SIZE];
69    hash_bytes.copy_from_slice(output.as_ref());
70    hash_bytes
71}
72
73impl<H> MerkleHash for H
74where
75    H: Digest<OutputSize = U32> + FixedOutputReset,
76{
77    fn empty_hash(&mut self) -> Hash {
78        // Get the output of an empty digest state.
79        let digest = self.finalize_reset();
80        copy_to_hash(digest)
81    }
82
83    fn leaf_hash(&mut self, bytes: &[u8]) -> Hash {
84        // Feed the data to the hasher, prepended with 0x00.
85        Digest::update(self, [0x00]);
86        Digest::update(self, bytes);
87
88        // Finalize the digest, reset the hasher state.
89        let digest = self.finalize_reset();
90
91        copy_to_hash(digest)
92    }
93
94    fn inner_hash(&mut self, left: Hash, right: Hash) -> Hash {
95        // Feed the data to the hasher: 0x1, then left and right data.
96        Digest::update(self, [0x01]);
97        Digest::update(self, left);
98        Digest::update(self, right);
99
100        // Finalize the digest, reset the hasher state
101        let digest = self.finalize_reset();
102
103        copy_to_hash(digest)
104    }
105}
106
107/// A wrapper for platform-provided host functions which can't do incremental
108/// hashing. One unfortunate example of such platform is Polkadot.
109pub struct NonIncremental<H>(PhantomData<H>);
110
111impl<H> Default for NonIncremental<H> {
112    fn default() -> Self {
113        Self(Default::default())
114    }
115}
116
117impl<H: Sha256> MerkleHash for NonIncremental<H> {
118    fn empty_hash(&mut self) -> Hash {
119        let digest = H::digest([]);
120        copy_to_hash(digest)
121    }
122
123    fn leaf_hash(&mut self, bytes: &[u8]) -> Hash {
124        // This is why non-incremental digest APIs are daft.
125        let mut buf = Vec::with_capacity(1 + bytes.len());
126        buf.push(0);
127        buf.extend_from_slice(bytes);
128        let digest = H::digest(buf);
129        copy_to_hash(digest)
130    }
131
132    fn inner_hash(&mut self, left: Hash, right: Hash) -> Hash {
133        // This is why non-incremental digest APIs are daft.
134        let mut buf = [0u8; 1 + HASH_SIZE * 2];
135        buf[0] = 1;
136        buf[1..HASH_SIZE + 1].copy_from_slice(&left);
137        buf[HASH_SIZE + 1..].copy_from_slice(&right);
138        let digest = H::digest(buf);
139        copy_to_hash(digest)
140    }
141}
142
143#[cfg(all(test, feature = "rust-crypto"))]
144mod tests {
145    use sha2::Sha256;
146    use subtle_encoding::hex;
147
148    use super::*; // TODO: use non-subtle ?
149
150    #[test]
151    fn test_rfc6962_empty_tree() {
152        let empty_tree_root_hex =
153            "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855";
154        let empty_tree_root = &hex::decode(empty_tree_root_hex).unwrap();
155        let empty_tree: Vec<Vec<u8>> = vec![];
156
157        let root = simple_hash_from_byte_vectors::<Sha256>(&empty_tree);
158        assert_eq!(empty_tree_root, &root);
159    }
160
161    #[test]
162    fn test_rfc6962_empty_leaf() {
163        let empty_leaf_root_hex =
164            "6e340b9cffb37a989ca544e6bb780a2c78901d3fb33738768511a30617afa01d";
165        let empty_leaf_root = &hex::decode(empty_leaf_root_hex).unwrap();
166        let one_empty_leaf: Vec<Vec<u8>> = vec![vec![]; 1];
167
168        let root = simple_hash_from_byte_vectors::<Sha256>(&one_empty_leaf);
169        assert_eq!(empty_leaf_root, &root);
170    }
171
172    #[test]
173    fn test_rfc6962_leaf() {
174        let leaf_root_hex = "395aa064aa4c29f7010acfe3f25db9485bbd4b91897b6ad7ad547639252b4d56";
175        let leaf_string = "L123456";
176
177        let leaf_root = &hex::decode(leaf_root_hex).unwrap();
178        let leaf_tree: Vec<Vec<u8>> = vec![leaf_string.as_bytes().to_vec(); 1];
179
180        let root = simple_hash_from_byte_vectors::<Sha256>(&leaf_tree);
181        assert_eq!(leaf_root, &root);
182    }
183
184    #[test]
185    fn test_rfc6962_tree_of_2() {
186        let node_hash_hex = "dc9a0536ff2e196d5a628a5bf377ab247bbddf83342be39699461c1e766e6646";
187        let left = b"N123".to_vec();
188        let right = b"N456".to_vec();
189
190        let node_hash = &hex::decode(node_hash_hex).unwrap();
191        let hash = simple_hash_from_byte_vectors::<Sha256>(&[left, right]);
192        assert_eq!(node_hash, &hash);
193    }
194
195    mod non_incremental {
196        use super::*;
197
198        #[test]
199        fn test_rfc6962_tree_of_2() {
200            let node_hash_hex = "dc9a0536ff2e196d5a628a5bf377ab247bbddf83342be39699461c1e766e6646";
201            let left = b"N123".to_vec();
202            let right = b"N456".to_vec();
203
204            let node_hash = &hex::decode(node_hash_hex).unwrap();
205            let hash = simple_hash_from_byte_vectors::<NonIncremental<Sha256>>(&[left, right]);
206            assert_eq!(node_hash, &hash);
207        }
208    }
209}