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
//!
//! SMT hash functions.
//!
//! The hash domain is the **compressed** binary trie with a
//! depth-independent leaf shortcut (the Diem/JMT construction):
//!
//! - **Empty**: `EMPTY_HASH = [0u8; 32]`
//! - **Lone leaf**: a subtree containing exactly one leaf commits to
//! `Keccak256(0x01 || key_hash || value)` — *regardless of the
//! subtree's depth or the leaf's residual path*. The full `key_hash`
//! binds the leaf's position, so depth-independence costs nothing:
//! relocating the leaf changes the sibling fold and thus the root.
//! - **Internal**: a subtree containing two or more leaves commits to
//! `Keccak256(0x00 || left_hash || right_hash)`; if both children are
//! empty → `EMPTY_HASH`.
//!
//! Leaf and internal preimages live in disjoint domains (`0x01` vs
//! `0x00` tag), the standard second-preimage hardening for Merkle
//! trees.
//!
//! The empty-empty special case ensures that `wrap_hash(EMPTY, path)`
//! stays `EMPTY` regardless of path length, which is essential for
//! proof verification (non-membership proofs fold `EMPTY_HASH` upward
//! and must reconstruct empty subtrees correctly).
//!
//! A compressed **internal** node that skips N levels is equivalent to
//! N nested single-child internal nodes (each with an empty sibling);
//! [`wrap_hash`] reproduces that chain. Leaf paths are *not* wrapped —
//! that is exactly the leaf shortcut, which keeps hashing O(N) total
//! instead of O(N × 256).
//!
use ;
use ;
/// Hashes a leaf: `Keccak256(0x01 || key_hash || value)`.
/// Hashes an internal node.
///
/// If both children are empty, returns `EMPTY_HASH` (preserving the
/// empty-subtree invariant). Otherwise `Keccak256(0x00 || left_hash ||
/// right_hash)` — the `0x00` domain tag keeps internal preimages
/// disjoint from leaf preimages (`0x01`).
/// "Lifts" a hash through a compressed **internal** path by nesting it
/// inside single-child internal nodes.
///
/// For each bit in `path` (from the last bit back to the first):
/// - bit = 0 → `H(hash || EMPTY_HASH)` (hash is on the left)
/// - bit = 1 → `H(EMPTY_HASH || hash)` (hash is on the right)
///
/// Only internal-node prefixes are wrapped; lone-leaf subtrees commit
/// depth-independently (see the module docs).