ic_cdk/api/
mod.rs

1//! System API and low level functions for it.
2use candid::Principal;
3use std::convert::TryFrom;
4
5pub mod call;
6pub mod management_canister;
7pub mod stable;
8
9#[cfg(feature = "wasi")]
10#[doc(hidden)]
11pub mod wasi;
12
13/// Prints the given message.
14pub fn print<S: std::convert::AsRef<str>>(s: S) {
15    let s = s.as_ref();
16    // SAFETY: `s`, being &str, is a readable sequence of bytes and therefore can be passed to ic0.debug_print.
17    unsafe {
18        ic0::debug_print(s.as_ptr() as i32, s.len() as i32);
19    }
20}
21
22/// Traps with the given message.
23pub fn trap(message: &str) -> ! {
24    // SAFETY: `message`, being &str, is a readable sequence of bytes and therefore can be passed to ic0.trap.
25    unsafe {
26        ic0::trap(message.as_ptr() as i32, message.len() as i32);
27    }
28    unreachable!()
29}
30
31/// Get current timestamp, in nanoseconds since the epoch (1970-01-01)
32pub fn time() -> u64 {
33    // SAFETY: ic0.time is always safe to call.
34    unsafe { ic0::time() as u64 }
35}
36
37/// Returns the caller of the current call.
38pub fn caller() -> Principal {
39    // SAFETY: ic0.msg_caller_size is always safe to call.
40    let len: u32 = unsafe { ic0::msg_caller_size() as u32 };
41    let mut bytes = vec![0u8; len as usize];
42    // SAFETY: Because `bytes` is mutable, and allocated to `len` bytes, it is safe to be passed to `ic0.msg_caller_copy` with a 0-offset.
43    unsafe {
44        ic0::msg_caller_copy(bytes.as_mut_ptr() as i32, 0, len as i32);
45    }
46    Principal::try_from(&bytes).unwrap()
47}
48
49/// Returns the canister id as a blob.
50pub fn id() -> Principal {
51    // SAFETY: ic0.canister_self_size is always safe to call.
52    let len: u32 = unsafe { ic0::canister_self_size() as u32 };
53    let mut bytes = vec![0u8; len as usize];
54    // SAFETY: Because `bytes` is mutable, and allocated to `len` bytes, it is safe to be passed to `ic0.canister_self_copy` with a 0-offset.
55    unsafe {
56        ic0::canister_self_copy(bytes.as_mut_ptr() as i32, 0, len as i32);
57    }
58    Principal::try_from(&bytes).unwrap()
59}
60
61/// Get the amount of funds available in the canister.
62pub fn canister_balance() -> u64 {
63    // SAFETY: ic0.canister_cycle_balance is always safe to call.
64    unsafe { ic0::canister_cycle_balance() as u64 }
65}
66
67/// Get the amount of funds available in the canister.
68pub fn canister_balance128() -> u128 {
69    let mut recv = 0u128;
70    // SAFETY: recv is writable and the size expected by ic0.canister_cycle_balance128.
71    unsafe { ic0::canister_cycle_balance128(&mut recv as *mut u128 as i32) }
72    recv
73}
74
75/// Sets the certified data of this canister.
76///
77/// Canisters can store up to 32 bytes of data that is certified by
78/// the system on a regular basis.  One can call [data_certificate]
79/// function from a query call to get a certificate authenticating the
80/// value set by calling this function.
81///
82/// This function can only be called from the following contexts:
83///  * "canister_init", "canister_pre_upgrade" and "canister_post_upgrade"
84///    hooks.
85///  * "canister_update" calls.
86///  * reply or reject callbacks.
87///
88/// # Panics
89///
90/// * This function traps if data.len() > 32.
91/// * This function traps if it's called from an illegal context
92///   (e.g., from a query call).
93pub fn set_certified_data(data: &[u8]) {
94    // SAFETY: because data is a slice ref, its pointer and length are valid to pass to ic0.certified_data_set.
95    unsafe { ic0::certified_data_set(data.as_ptr() as i32, data.len() as i32) }
96}
97
98/// When called from a query call, returns the data certificate authenticating
99/// certified_data set by this canister.
100///
101/// Returns None if called not from a query call.
102pub fn data_certificate() -> Option<Vec<u8>> {
103    // SAFETY: ic0.data_certificate_present is always safe to call.
104    if unsafe { ic0::data_certificate_present() } == 0 {
105        return None;
106    }
107
108    // SAFETY: ic0.data_certificate_size is always safe to call.
109    let n = unsafe { ic0::data_certificate_size() };
110    let mut buf = vec![0u8; n as usize];
111    // SAFETY: Because `buf` is mutable and allocated to `n` bytes, it is valid to receive from ic0.data_certificate_bytes with no offset
112    unsafe {
113        ic0::data_certificate_copy(buf.as_mut_ptr() as i32, 0i32, n);
114    }
115    Some(buf)
116}
117
118/// Returns the number of instructions that the canister executed since the last [entry
119/// point](https://internetcomputer.org/docs/current/references/ic-interface-spec/#entry-points).
120#[inline]
121pub fn instruction_counter() -> u64 {
122    performance_counter(0)
123}
124
125/// Get the value of specified performance counter.
126///
127/// Supported counter type:
128/// 0 : instruction counter. The number of WebAssembly instructions the system has determined that the canister has executed.
129#[inline]
130pub fn performance_counter(counter_type: u32) -> u64 {
131    // SAFETY: ic0.performance_counter is always safe to call.
132    unsafe { ic0::performance_counter(counter_type as i32) as u64 }
133}
134
135/// Get the value of canister version.
136pub fn canister_version() -> u64 {
137    // SAFETY: ic0.canister_version is always safe to call.
138    unsafe { ic0::canister_version() as u64 }
139}
140
141/// Determine if a Principal is a controller of the canister.
142pub fn is_controller(principal: &Principal) -> bool {
143    let slice = principal.as_slice();
144    // SAFETY: `principal.as_bytes()`, being `&[u8]`, is a readable sequence of bytes and therefore safe to pass to `ic0.is_controller`.
145    unsafe { ic0::is_controller(slice.as_ptr() as i32, slice.len() as i32) != 0 }
146}