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
//! This package provides a map backed by a Merkle tree that can be used
//! by Internet Computer canisters to implement certified queries.
//!
//! You can certify your data by using the [`RbTree`] type as a map of
//! known names to the values you want certified. After you record its
//! [`root_hash`](RbTree::root_hash) into your canister's [certified data],
//! query calls can access a [data certificate] proving that the IC certified
//! the hash, under the [path] `/canister/<canister id>/certified_data`.
//! By providing this certificate, as well as a [`witness`](RbTree::witness)
//! that the value exists in the hash, you can then prove to the caller that
//! the IC certified the data.
//!
//! [certified data]: https://docs.rs/ic-cdk/latest/ic_cdk/api/fn.set_certified_data.html
//! [data certificate]: https://docs.rs/ic-cdk/latest/ic_cdk/api/fn.data_certificate.html
//! [path]: https://internetcomputer.org/docs/current/references/ic-interface-spec#state-tree
//!
//! # Example
//!
//! ```
//! # use std::cell::*;
//! # use ic_cdk::*;
//! # use ic_certified_map::*;
//! # use candid::CandidType;
//! # use serde::Serialize;
//!
//! thread_local! {
//!     static COUNTER: Cell<i32> = Cell::new(0);
//!     static TREE: RefCell<RbTree<&'static str, Hash>> = RefCell::new(RbTree::new());
//! }
//!
//! #[update]
//! fn inc() {
//!     let count = COUNTER.with(|counter| {
//!         let count = counter.get() + 1;
//!         counter.set(count);
//!         count
//!     });
//!     TREE.with(|tree| {
//!         let mut tree = tree.borrow_mut();
//!         tree.insert("counter", leaf_hash(&count.to_be_bytes()));
//!         ic_cdk::api::set_certified_data(&tree.root_hash());
//!     })
//! }
//!
//! #[derive(CandidType)]
//! struct CertifiedCounter {
//!     count: i32,
//!     certificate: Vec<u8>,
//!     witness: Vec<u8>,
//! }
//!
//! #[query]
//! fn get() -> CertifiedCounter {
//!     let certificate = ic_cdk::api::data_certificate().expect("No data certificate available");
//!     let witness = TREE.with(|tree| {
//!         let tree = tree.borrow();
//!         let mut witness = vec![];
//!         let mut witness_serializer = serde_cbor::Serializer::new(&mut witness);
//!         witness_serializer.self_describe();
//!         tree.witness(b"counter").serialize(&mut witness_serializer).unwrap();
//!         witness
//!     });
//!     let count = COUNTER.with(|counter| counter.get());
//!     CertifiedCounter {
//!         count,
//!         certificate,
//!         witness,
//!     }
//! }
//! ```

#![warn(
    elided_lifetimes_in_paths,
    missing_debug_implementations,
    missing_docs,
    unsafe_op_in_unsafe_fn,
    clippy::undocumented_unsafe_blocks,
    clippy::missing_safety_doc
)]

mod hashtree;
mod rbtree;

pub use crate::hashtree::*;
pub use crate::rbtree::*;