merkrs/
lib.rs

1//! # merkrs
2//!
3//! A Rust implementation of Merkle tree library, compatible with OpenZeppelin's JavaScript implementation.
4//!
5//! ## Features
6//!
7//! - **`StandardMerkleTree`**: For structured data with ABI encoding (Solidity compatible)
8//! - **`SimpleMerkleTree`**: For simple bytes32 values
9//! - Full proof generation and verification
10//! - Multi-proof support
11//! - Serialization/deserialization with serde
12//! - Keccak256 hashing (Ethereum compatible)
13//!
14//! ## Example
15//!
16//! ```rust
17//! use merkrs::{SimpleMerkleTree, SimpleMerkleTreeOptions, Bytes32};
18//!
19//! let values: Vec<Bytes32> = vec![[1u8; 32], [2u8; 32], [3u8; 32], [4u8; 32]];
20//! let tree = SimpleMerkleTree::of(&values, SimpleMerkleTreeOptions::default()).unwrap();
21//!
22//! let proof = tree.get_proof(&values[0]).unwrap();
23//! assert!(tree.verify_proof(&values[0], &proof).unwrap());
24//! ```
25
26#![deny(unsafe_code)]
27#![allow(clippy::module_name_repetitions)]
28
29pub mod bytes;
30pub mod core;
31pub mod error;
32pub mod hashes;
33pub mod options;
34pub mod simple;
35pub mod standard;
36
37pub use bytes::{Bytes32, HexString, ToBytes32};
38pub use core::MultiProof;
39pub use error::{MerkleTreeError, Result};
40pub use hashes::{NodeHashFn, keccak256, standard_leaf_hash, standard_node_hash};
41pub use options::MerkleTreeOptions;
42pub use simple::{SimpleMerkleTree, SimpleMerkleTreeData, SimpleMerkleTreeOptions};
43pub use standard::{StandardMerkleTree, StandardMerkleTreeData};
44
45#[cfg(test)]
46mod tests {
47    use super::*;
48    use serde_json::json;
49
50    #[test]
51    fn test_simple_tree_e2e() {
52        let values: Vec<Bytes32> = (0..4)
53            .map(|i| {
54                let mut bytes = [0u8; 32];
55                bytes[31] = i;
56                bytes
57            })
58            .collect();
59
60        let tree = SimpleMerkleTree::of(&values, SimpleMerkleTreeOptions::default()).unwrap();
61
62        assert_eq!(tree.len(), 4);
63
64        for value in &values {
65            let proof = tree.get_proof(value).unwrap();
66            assert!(tree.verify_proof(value, &proof).unwrap());
67        }
68
69        let data = tree.dump();
70        let loaded = SimpleMerkleTree::load(data, None).unwrap();
71        assert_eq!(tree.root(), loaded.root());
72    }
73
74    #[test]
75    fn test_standard_tree_e2e() {
76        let values = vec![
77            vec![
78                json!("0x1111111111111111111111111111111111111111"),
79                json!(100u64),
80            ],
81            vec![
82                json!("0x2222222222222222222222222222222222222222"),
83                json!(200u64),
84            ],
85            vec![
86                json!("0x3333333333333333333333333333333333333333"),
87                json!(300u64),
88            ],
89            vec![
90                json!("0x4444444444444444444444444444444444444444"),
91                json!(400u64),
92            ],
93        ];
94
95        let tree = StandardMerkleTree::of(
96            values.clone(),
97            vec!["address".to_string(), "uint256".to_string()],
98            MerkleTreeOptions::default(),
99        )
100        .unwrap();
101
102        assert_eq!(tree.len(), 4);
103
104        for value in &values {
105            let proof = tree.get_proof(value).unwrap();
106            assert!(tree.verify_proof(value, &proof).unwrap());
107        }
108
109        let data = tree.dump();
110        let json_str = serde_json::to_string_pretty(&data).unwrap();
111        let loaded_data: StandardMerkleTreeData = serde_json::from_str(&json_str).unwrap();
112        let loaded = StandardMerkleTree::load(loaded_data).unwrap();
113        assert_eq!(tree.root(), loaded.root());
114    }
115
116    #[test]
117    fn test_static_verification() {
118        let values = vec![
119            vec![
120                json!("0x1111111111111111111111111111111111111111"),
121                json!(100u64),
122            ],
123            vec![
124                json!("0x2222222222222222222222222222222222222222"),
125                json!(200u64),
126            ],
127        ];
128
129        let tree = StandardMerkleTree::of(
130            values.clone(),
131            vec!["address".to_string(), "uint256".to_string()],
132            MerkleTreeOptions::default(),
133        )
134        .unwrap();
135
136        let proof = tree.get_proof(&values[0]).unwrap();
137
138        let result = StandardMerkleTree::verify(
139            tree.root(),
140            &["address".to_string(), "uint256".to_string()],
141            &values[0],
142            &proof,
143        )
144        .unwrap();
145
146        assert!(result);
147    }
148}