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
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
//! # Monotree
//! Rust implementation of an optimized Sparse Merkle Tree.
//! This is a kind of binary-radix tree based on bitwise branching, _currently_, no nibble of bit.
//! For now, branching unit is just ___a single bit___, _neither a 4-bit nor a byte nibble_.
//!
//! ## Features
//! - Very ___simple___ and __lightweight__, but ___fast___ and __robust__.
//! - __Fully featured__ Sparse Merkle Tree (SMT) as a storage
//! - <ins>This includes: __non-inclusion proof__ , as well as __inclusion proof__, and its verification.</ins>
//! - Again, _NOT verbose_ at all.
//!
//! This library mostly relies on the _Rust standard library only_ except for `database APIs` and `hashers`.
//! Currently, `monotree` supports these databases and hash functions following,
//! but is designed to be super easy to customize and add:
//!
//! _Databases include_:
//! - [`HashMap`](https://lib.rs/crates/hashbrown)
//! - [`RocksDB`](https://lib.rs/crates/rocksdb)
//! - [`Sled`](https://lib.rs/crates/sled)
//!
//! _Hashers include_:
//! - [`Blake3`](https://lib.rs/crates/blake3)
//! - [`Blake2s`](https://lib.rs/crates/blake2-rfc) and [`Blake2b`](https://lib.rs/crates/blake2-rfc)
//! - [`SHA-2`](https://lib.rs/crates/sha2)
//! - [`SHA-3 (Keccak)`](https://lib.rs/crates/sha3)
//!
//! ## Quick start
//! > Refer to _`examples/basic.rs`_ for a complete working example.
//! >
//! > Regarding __non-inclusion proof__ and __inclusion proof__, See _Merkle proof_ section in [More Examples](#more-examples) below.
//!
//! ### Initialize
//! ```rust,ignore
//! // If no database or hash function is specified,
//! // the tree defaults to using a HashMap and the Blake3 hash function.
//! let mut tree = Monotree::default();
//!
//! // It is natural the tree root initially has 'None'.
//! let root = None;
//! ```
//! ### Insert
//! ```rust,ignore
//! // Generate a random key and leaf pair.
//! // random_hash() creates a fixed-length random array of 32 bytes.
//! let key = random_hash();
//! let leaf = random_hash();
//!
//! // Insert the entry (key, leaf) into tree, yielding a new root of tree
//! let root = tree.insert(root.as_ref(), &key, &leaf)?;
//! assert_ne!(root, None);
//! ```
//! ### Retrieve
//! ```rust,ignore
//! // Retrieve the leaf inserted just before. Note that the last root was used.
//! let found = tree.get(root.as_ref(), &key)?;
//! assert_eq!(found, Some(leaf));
//! ```
//! ### Remove
//! ```rust,ignore
//! // Remove the entry
//! let root = tree.remove(root.as_ref(), &key)?;
//!
//! // The tree is empty now and the root back to 'None'
//! assert_eq!(tree.get(root.as_ref(), &key)?, None);
//! assert_eq!(root, None);
//! ```
//! ### Batch: Atomic Transaction
//! Instead of executing each operation one by one, write them in a batch and then commit them all at once.
//! One can do the same thing above using batch operation for ___performance gain___ and ___atomicity___. In short,
//!
//! `prepare` → many of {`insert`, `get`, `remove`} → `commit`
//!
//! #### Prepare Transaction
//! ```rust,ignore
//! // initialize an empty batch: prepare transaction
//! tree.prepare();
//! ```
//! #### Freely `insert`, `get`, and `remove`
//! ```rust,ignore
//! // Insert the entry (key, leaf) within the batch
//! let root = tree.insert(root.as_ref(), &key, &leaf)?;
//! assert_ne!(root, None);
//!
//! // Retrieve the inserted leaf using the batch root
//! let found = tree.get(root.as_ref(), &key)?;
//! assert_eq!(found, Some(leaf));
//!
//! // Remove the entry within the same batch
//! let root = tree.remove(root.as_ref(), &key)?;
//!
//! // Ensure the entry was removed within the batch
//! assert_eq!(tree.get(root.as_ref(), &key)?, None);
//! ```
//! ##### Commit Transaction
//! ```rust,ignore
//! // Commit the batch operations: commit transaction
//! tree.commit();
//!
//! // Verify that the final root is `None` after commit
//! assert_eq!(tree.get(root.as_ref(), &key)?, None);
//! ```
//! ### Initialize with a specific database and hash function
//! ```rust,ignore
//! // Init a monotree instance with a database and hash function
//! //
//! // Monotree::<DATABASE, HASHER>::new(DB_PATH)
//! // where DATABASE = {MemoryDB, RocksDB, Sled}
//! // HASHER = {Blake3, Blake2s, Blake2b, Sha2, Sha3}
//! let mut tree = Monotree::<RocksDB, Blake2b>::new("/tmp/monotree");
//!
//! // It is natural the tree root initially has 'None'
//! let root = None;
//! ```
//!
//! ### Intrinsic batch processing: `inserts` and `removes`.
//! As shown in [Quick Start](#quick-start) above, __operations executed between__ `tree.prepare()` __and__ `tree.commit()` can be viewed as _a single batch operation_. By default, they are automatically cached and are written together in a batch unit.
//!
//! However, if you need to repeat the same operation, such as `insert` or `remove`, you can easily optimize performance by using `inserts` and `removes`.
//!
//! `inserts()` is ___significantly faster___ than `insert()` for the following reason:
//! - Batch writes
//! - Sorting keys prior to insertion
//! - In-memory caching
//! ```rust,ignore
//! // Prepare 100 random pairs of key and leaf.
//! // random_hash(SIZE) creates a vector of fixed-length random array of 32 bytes.
//! let keys = random_hashes(100);
//! let leaves = random_hashes(100);
//!
//! // Insert a vector of entries of (key, leaf) into tree.
//! let root = tree.inserts(root.as_ref(), &keys, &leaves)?;
//! assert_ne!(root, None);
//! ```
//!
//! Similarly, `gets()` and `removes()` also are designed for batch usage.
//! ```rust,ignore
//! let result = tree.gets(root.as_ref(), &keys)?;
//! assert_eq!(result.len(), keys.len());
//!
//! let root = tree.removes(root.as_ref(), &keys)?;
//! // surely, the tree has nothing nad the root back to 'None'
//! assert_eq!(root, None);
//! ```
//!
//! ### Non-inclusion proof and inclusion proof, _Merkle Proof_
//! `monotree` has compressed representations, but it fully retains the core property of the ___Sparse Merkle Trie___.
//! _non-inclusion proof_ is quite straightforward: Just go walk down the tree with a key (or a path) given.
//! If we ___cannot successfully get a leaf___, we can assure that ___the leaf is not a part of the tree___.
//!
//! The process of __inclusion proof__ is outlined below:
//!
//! #### Generate a Merkle Proof
//! Prepare a random tree for testing.
//! ```rust,ignore
//! // random insertions for testing Merkle proof generation
//! let root = tree.inserts(root.as_ref(), &keys, &leaves)?;
//!
//! // pick a random key from the keys among inserted just before
//! let key = keys[99];
//! ```
//!
//! Generate a Merkle proof for a given root and key.
//! ```rust,ignore
//! let proof = tree.get_merkle_proof(root.as_ref(), &key)?;
//! ```
//!
//! #### Verify the Merkle Proof
//! Prepare a __target leaf__ matched with the __target root__ above.
//! ```rust,ignore
//! // where the Merkle proof verification starts off
//! let leaf = leaves[99];
//! ```
//! To verify the proof correctly, you ___need to provide a hasher matched___.
//! ```rust,ignore
//! // Previously the tree was initialized with `Blake2b`
//! let hasher = Blake2b::new();
//! ```
//!
//! Just call `verify_proof(&HASHER, &ROOT, &LEAF, &PROOF)`. That's all!
//! ```rust,ignore
//! let verified = verify_proof(&hasher, root.as_ref(), &leaf, proof.as_ref());
//! assert_eq!(verified, true);
//! ```
//!
//! ### Tracking the Latest Root
//! ___Sparse Merkle Trie___ is a space where ___multiple states (roots) coexist simultaneously___.
//! There is no reason why a particular state must be stored more preciously than another. The __lastest root__ is _nothing more than the most recently updated state_.
//!
//! `monotree` has a minimal design. It __does not automatically update or track the latest root__.
//! However, `monotree` provides tools to update and fetch the latest root.
//!
//! Use `set_headroot(&LATEST_ROOT)` to set the latest root to the database.
//! ```rust,ignore
//! tree.set_headroot(root.as_ref());
//! ```
//! Use `get_headroot()` to get the latest root from the database.
//! ```rust,ignore
//! let headroot = tree.get_headroot()?;
//! assert_eq!(headroot, root);
//! ```
/// Size of fixed length byte-array from a `Hasher`. Equivalent to `key` length of `monotree`.
pub const HASH_LEN: usize = 32;
/// A type representing length of `Bits`.
pub type BitsLen = u16;
/// A `Result` type redefined for error handling. The same as `std::result::Result<T, Errors>`.
pub type Result<T> = Result;
/// A type indicating fixed length byte-array. This has the length of `HASH_LEN`.
pub type Hash = ;
/// A type representing _Merkle proof_.
pub type Proof = ;
/// The key to be used to restore the latest `root`
pub const ROOT_KEY: &Hash = b"_______monotree::headroot_______";
/// A type indicating database selected by default.
pub type DefaultDatabase = MemoryDB;
/// A type indicating hasher selected by default.
pub type DefaultHasher = Blake3;
pub use Bits;
pub use Database;
pub use Hasher;
pub use ;
pub use ;
/// An `Error` type defiend for handling general errors.