ethereum/
util.rs

1//! Utility functions for Ethereum.
2
3use alloc::vec::Vec;
4
5use ethereum_types::H256;
6use hash256_std_hasher::Hash256StdHasher;
7use hash_db::Hasher;
8use sha3::{Digest, Keccak256};
9use trie_root::Value as TrieStreamValue;
10
11/// Concrete `Hasher` impl for the Keccak-256 hash
12#[derive(Default, Debug, Clone, PartialEq, Eq)]
13pub struct KeccakHasher;
14impl Hasher for KeccakHasher {
15	type Out = H256;
16	type StdHasher = Hash256StdHasher;
17	const LENGTH: usize = 32;
18
19	fn hash(x: &[u8]) -> Self::Out {
20		H256::from_slice(Keccak256::digest(x).as_slice())
21	}
22}
23
24/// Concrete `TrieStream` impl for the ethereum trie.
25#[derive(Default)]
26pub struct Hash256RlpTrieStream {
27	stream: rlp::RlpStream,
28}
29
30impl trie_root::TrieStream for Hash256RlpTrieStream {
31	fn new() -> Self {
32		Self {
33			stream: rlp::RlpStream::new(),
34		}
35	}
36
37	fn append_empty_data(&mut self) {
38		self.stream.append_empty_data();
39	}
40
41	fn begin_branch(
42		&mut self,
43		_maybe_key: Option<&[u8]>,
44		_maybe_value: Option<TrieStreamValue>,
45		_has_children: impl Iterator<Item = bool>,
46	) {
47		// an item for every possible nibble/suffix
48		// + 1 for data
49		self.stream.begin_list(17);
50	}
51
52	fn append_empty_child(&mut self) {
53		self.stream.append_empty_data();
54	}
55
56	fn end_branch(&mut self, value: Option<TrieStreamValue>) {
57		match value {
58			Some(value) => match value {
59				TrieStreamValue::Inline(value) => self.stream.append(&value),
60				TrieStreamValue::Node(value) => self.stream.append(&value),
61			},
62			None => self.stream.append_empty_data(),
63		};
64	}
65
66	fn append_leaf(&mut self, key: &[u8], value: TrieStreamValue) {
67		self.stream.begin_list(2);
68		self.stream.append_iter(hex_prefix_encode(key, true));
69		match value {
70			TrieStreamValue::Inline(value) => self.stream.append(&value),
71			TrieStreamValue::Node(value) => self.stream.append(&value),
72		};
73	}
74
75	fn append_extension(&mut self, key: &[u8]) {
76		self.stream.begin_list(2);
77		self.stream.append_iter(hex_prefix_encode(key, false));
78	}
79
80	fn append_substream<H: Hasher>(&mut self, other: Self) {
81		let out = other.out();
82		match out.len() {
83			0..=31 => self.stream.append_raw(&out, 1),
84			_ => self.stream.append(&H::hash(&out).as_ref()),
85		};
86	}
87
88	fn out(self) -> Vec<u8> {
89		self.stream.out().freeze().into()
90	}
91}
92
93// Copy from `triehash` crate.
94/// Hex-prefix Notation. First nibble has flags: oddness = 2^0 & termination = 2^1.
95///
96/// The "termination marker" and "leaf-node" specifier are completely equivalent.
97///
98/// Input values are in range `[0, 0xf]`.
99///
100/// ```markdown
101///  [0,0,1,2,3,4,5]   0x10012345 // 7 > 4
102///  [0,1,2,3,4,5]     0x00012345 // 6 > 4
103///  [1,2,3,4,5]       0x112345   // 5 > 3
104///  [0,0,1,2,3,4]     0x00001234 // 6 > 3
105///  [0,1,2,3,4]       0x101234   // 5 > 3
106///  [1,2,3,4]         0x001234   // 4 > 3
107///  [0,0,1,2,3,4,5,T] 0x30012345 // 7 > 4
108///  [0,0,1,2,3,4,T]   0x20001234 // 6 > 4
109///  [0,1,2,3,4,5,T]   0x20012345 // 6 > 4
110///  [1,2,3,4,5,T]     0x312345   // 5 > 3
111///  [1,2,3,4,T]       0x201234   // 4 > 3
112/// ```
113fn hex_prefix_encode(nibbles: &[u8], leaf: bool) -> impl Iterator<Item = u8> + '_ {
114	let inlen = nibbles.len();
115	let oddness_factor = inlen % 2;
116
117	let first_byte = {
118		let mut bits = ((inlen as u8 & 1) + (2 * leaf as u8)) << 4;
119		if oddness_factor == 1 {
120			bits += nibbles[0];
121		}
122		bits
123	};
124	core::iter::once(first_byte).chain(
125		nibbles[oddness_factor..]
126			.chunks(2)
127			.map(|ch| ch[0] << 4 | ch[1]),
128	)
129}
130
131/// Generates a trie root hash for a vector of key-value tuples
132pub fn trie_root<I, K, V>(input: I) -> H256
133where
134	I: IntoIterator<Item = (K, V)>,
135	K: AsRef<[u8]> + Ord,
136	V: AsRef<[u8]>,
137{
138	trie_root::trie_root::<KeccakHasher, Hash256RlpTrieStream, _, _, _>(input, None)
139}
140
141/// Generates a key-hashed (secure) trie root hash for a vector of key-value tuples.
142pub fn sec_trie_root<I, K, V>(input: I) -> H256
143where
144	I: IntoIterator<Item = (K, V)>,
145	K: AsRef<[u8]>,
146	V: AsRef<[u8]>,
147{
148	trie_root::sec_trie_root::<KeccakHasher, Hash256RlpTrieStream, _, _, _>(input, None)
149}
150
151/// Generates a trie root hash for a vector of values
152pub fn ordered_trie_root<I, V>(input: I) -> H256
153where
154	I: IntoIterator<Item = V>,
155	V: AsRef<[u8]>,
156{
157	trie_root::trie_root::<KeccakHasher, Hash256RlpTrieStream, _, _, _>(
158		input
159			.into_iter()
160			.enumerate()
161			.map(|(i, v)| (rlp::encode(&i), v)),
162		None,
163	)
164}
165
166#[cfg(test)]
167mod tests {
168	use ethereum_types::H256;
169	use hash256_std_hasher::Hash256StdHasher;
170	use hex_literal::hex;
171	use sha3::{Digest, Keccak256};
172
173	#[derive(Default, Debug, Clone, PartialEq, Eq)]
174	struct KeccakHasher15;
175	impl hash_db15::Hasher for KeccakHasher15 {
176		type Out = H256;
177		type StdHasher = Hash256StdHasher;
178		const LENGTH: usize = 32;
179
180		fn hash(x: &[u8]) -> Self::Out {
181			H256::from_slice(Keccak256::digest(x).as_slice())
182		}
183	}
184
185	#[test]
186	fn test_trie_root() {
187		let v = vec![
188			("doe", "reindeer"),
189			("dog", "puppy"),
190			("dogglesworth", "cat"),
191		];
192		let root = hex!("8aad789dff2f538bca5d8ea56e8abe10f4c7ba3a5dea95fea4cd6e7c3a1168d3");
193
194		let before = triehash::trie_root::<KeccakHasher15, _, _, _>(v.clone());
195		assert_eq!(before.0, root);
196
197		let after = super::trie_root::<_, _, _>(v);
198		assert_eq!(after.0, root);
199	}
200
201	#[test]
202	fn test_sec_trie_root() {
203		let v = vec![
204			("doe", "reindeer"),
205			("dog", "puppy"),
206			("dogglesworth", "cat"),
207		];
208		let root = hex!("d4cd937e4a4368d7931a9cf51686b7e10abb3dce38a39000fd7902a092b64585");
209
210		let before = triehash::sec_trie_root::<KeccakHasher15, _, _, _>(v.clone());
211		assert_eq!(before.0, root);
212
213		let after = super::sec_trie_root::<_, _, _>(v);
214		assert_eq!(after.0, root);
215	}
216
217	#[test]
218	fn test_ordered_trie_root() {
219		let v = &["doe", "reindeer"];
220		let root = hex!("e766d5d51b89dc39d981b41bda63248d7abce4f0225eefd023792a540bcffee3");
221
222		let before = triehash::ordered_trie_root::<KeccakHasher15, _>(v);
223		assert_eq!(before.0, root);
224
225		let after = super::ordered_trie_root::<_, _>(v);
226		assert_eq!(after.0, root);
227	}
228}