miden_stdlib_sys/stdlib/collections/smt.rs
1//! Bindings for the `std::collections::smt` module, which exposes sparse Merkle tree
2//! functionality from the Miden standard library.
3
4use crate::intrinsics::{Felt, Word, WordAligned};
5
6/// Result of [`smt_get`], containing the retrieved `value` and the (unchanged) `root`.
7#[derive(Debug, Clone, PartialEq, Eq)]
8pub struct SmtGetResponse {
9 pub value: Word,
10 pub root: Word,
11}
12
13/// Result of [`smt_set`], containing the `old_value` and the updated `new_root`.
14#[derive(Debug, Clone, PartialEq, Eq)]
15pub struct SmtSetResponse {
16 pub old_value: Word,
17 pub new_root: Word,
18}
19
20#[allow(improper_ctypes)]
21unsafe extern "C" {
22 /// Returns the value located under the specified `key` in the sparse Merkle tree defined by
23 /// the specified `root`.
24 ///
25 /// This maps to the `std::collections::smt::get` procedure.
26 ///
27 /// Inputs: `[key, root, ...]`
28 /// Outputs: `[value, root, ...]`
29 ///
30 /// Fails if the tree with the specified `root` does not exist in the VM's advice provider. When
31 /// no value has previously been inserted under `key`, the procedure returns the empty word.
32 #[link_name = "std::collections::smt::get"]
33 fn extern_smt_get(
34 k3: Felt,
35 k2: Felt,
36 k1: Felt,
37 k0: Felt,
38 r3: Felt,
39 r2: Felt,
40 r1: Felt,
41 r0: Felt,
42 ptr: *mut (Word, Word),
43 );
44
45 /// Inserts `value` under `key` in the sparse Merkle tree defined by `root`.
46 ///
47 /// This maps to the `std::collections::smt::set` procedure.
48 ///
49 /// Inputs: `[value, key, root, ...]`
50 /// Outputs: `[old_value, new_root, ...]`
51 ///
52 /// On success, the prior value stored under `key` is returned along with the updated root. If
53 /// `value` is the empty word, the new tree state is equivalent to omitting the update.
54 ///
55 /// Fails if the tree with the specified `root` does not exist in the VM's advice provider.
56 #[link_name = "std::collections::smt::set"]
57 fn extern_smt_set(
58 v3: Felt,
59 v2: Felt,
60 v1: Felt,
61 v0: Felt,
62 k3: Felt,
63 k2: Felt,
64 k1: Felt,
65 k0: Felt,
66 r3: Felt,
67 r2: Felt,
68 r1: Felt,
69 r0: Felt,
70 ptr: *mut (Word, Word),
71 );
72}
73
74/// Returns the value associated with `key` in the sparse Merkle tree rooted at `root` as tracked by
75/// the VM's advice provider. The returned [`SmtGetResponse`] contains the retrieved value and the
76/// (unchanged) root returned by the ABI.
77/// Fails if the tree with the specified `root` does not exist in the VM's advice provider. When
78/// no value has previously been inserted under `key`, the procedure returns the empty word.
79#[inline]
80pub fn smt_get(key: Word, root: Word) -> SmtGetResponse {
81 unsafe {
82 let mut ret_area = ::core::mem::MaybeUninit::<WordAligned<(Word, Word)>>::uninit();
83 let ptr = ret_area.as_mut_ptr() as *mut (Word, Word);
84 extern_smt_get(key[3], key[2], key[1], key[0], root[3], root[2], root[1], root[0], ptr);
85 let (value, returned_root) = ret_area.assume_init().into_inner();
86 SmtGetResponse {
87 value: value.reverse(),
88 root: returned_root.reverse(),
89 }
90 }
91}
92
93/// Inserts `value` at `key` in the sparse Merkle tree rooted at `root`, returning the prior value
94/// stored at `key` along with the new root. The returned [`SmtSetResponse`] contains
95/// the previous value stored under `key` and the updated root.
96/// Fails if the tree with the specified `root` does not exist in the VM's advice provider.
97#[inline]
98pub fn smt_set(value: Word, key: Word, root: Word) -> SmtSetResponse {
99 unsafe {
100 let mut ret_area = ::core::mem::MaybeUninit::<WordAligned<(Word, Word)>>::uninit();
101 let ptr = ret_area.as_mut_ptr() as *mut (Word, Word);
102 extern_smt_set(
103 value[3], value[2], value[1], value[0], key[3], key[2], key[1], key[0], root[3],
104 root[2], root[1], root[0], ptr,
105 );
106 let (old_value, new_root) = ret_area.assume_init().into_inner();
107 SmtSetResponse {
108 old_value: old_value.reverse(),
109 new_root: new_root.reverse(),
110 }
111 }
112}