ic_certified_map/lib.rs
1//! This package provides a map backed by a Merkle tree that can be used
2//! by Internet Computer canisters to implement certified queries.
3//!
4//! You can certify your data by using the [`RbTree`] type as a map of
5//! known names to the values you want certified. After you record its
6//! [`root_hash`](RbTree::root_hash) into your canister's [certified data],
7//! query calls can access a [data certificate] proving that the IC certified
8//! the hash, under the [path] `/canister/<canister id>/certified_data`.
9//! By providing this certificate, as well as a [`witness`](RbTree::witness)
10//! that the value exists in the hash, you can then prove to the caller that
11//! the IC certified the data.
12//!
13//! [certified data]: https://docs.rs/ic-cdk/latest/ic_cdk/api/fn.set_certified_data.html
14//! [data certificate]: https://docs.rs/ic-cdk/latest/ic_cdk/api/fn.data_certificate.html
15//! [path]: https://internetcomputer.org/docs/current/references/ic-interface-spec#state-tree
16//!
17//! # Example
18//!
19//! ```
20//! # use std::cell::*;
21//! # use ic_cdk::*;
22//! # use ic_certified_map::*;
23//! # use candid::CandidType;
24//! # use serde::Serialize;
25//!
26//! thread_local! {
27//! static COUNTER: Cell<i32> = Cell::new(0);
28//! static TREE: RefCell<RbTree<&'static str, Hash>> = RefCell::new(RbTree::new());
29//! }
30//!
31//! #[update]
32//! fn inc() {
33//! let count = COUNTER.with(|counter| {
34//! let count = counter.get() + 1;
35//! counter.set(count);
36//! count
37//! });
38//! TREE.with(|tree| {
39//! let mut tree = tree.borrow_mut();
40//! tree.insert("counter", leaf_hash(&count.to_be_bytes()));
41//! ic_cdk::api::set_certified_data(&tree.root_hash());
42//! })
43//! }
44//!
45//! #[derive(CandidType)]
46//! struct CertifiedCounter {
47//! count: i32,
48//! certificate: Vec<u8>,
49//! witness: Vec<u8>,
50//! }
51//!
52//! #[query]
53//! fn get() -> CertifiedCounter {
54//! let certificate = ic_cdk::api::data_certificate().expect("No data certificate available");
55//! let witness = TREE.with(|tree| {
56//! let tree = tree.borrow();
57//! let mut witness = vec![];
58//! let mut witness_serializer = serde_cbor::Serializer::new(&mut witness);
59//! witness_serializer.self_describe();
60//! tree.witness(b"counter").serialize(&mut witness_serializer).unwrap();
61//! witness
62//! });
63//! let count = COUNTER.with(|counter| counter.get());
64//! CertifiedCounter {
65//! count,
66//! certificate,
67//! witness,
68//! }
69//! }
70//! ```
71
72#![warn(
73 elided_lifetimes_in_paths,
74 missing_debug_implementations,
75 missing_docs,
76 unsafe_op_in_unsafe_fn,
77 clippy::undocumented_unsafe_blocks,
78 clippy::missing_safety_doc
79)]
80
81mod hashtree;
82mod rbtree;
83
84pub use crate::hashtree::*;
85pub use crate::rbtree::*;