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::*;