Skip to main content

miden_core_lib/
lib.rs

1#![no_std]
2
3#[cfg(feature = "std")]
4extern crate std;
5
6#[cfg(any(feature = "constraints-tools", all(test, feature = "std")))]
7pub mod constraints_regen;
8pub mod dsa;
9#[cfg(feature = "constraints-tools")]
10pub mod evaluator_regen;
11pub mod handlers;
12
13extern crate alloc;
14
15use alloc::{sync::Arc, vec, vec::Vec};
16
17use miden_core::{Word, events::EventName, mast::MastForest};
18use miden_mast_package::Package;
19use miden_processor::{HostLibrary, event::EventHandler};
20use miden_utils_sync::LazyLock;
21
22use crate::handlers::{
23    aead_decrypt::{AEAD_DECRYPT_EVENT_NAME, handle_aead_decrypt},
24    debug::default_debug_handlers,
25    falcon_div::{FALCON_DIV_EVENT_NAME, handle_falcon_div},
26    precompiles::{
27        keccak256::{KECCAK256_DIGEST_EVENT_NAME, handle_keccak256_digest},
28        uint_field_inv::{UINT_FIELD_INV_EVENT_NAME, handle_uint_field_inv},
29    },
30    readonly::readonly_noop_handlers,
31    smt_peek::{SMT_PEEK_EVENT_NAME, handle_smt_peek},
32    sorted_array::{
33        LOWERBOUND_ARRAY_EVENT_NAME, LOWERBOUND_KEY_VALUE_EVENT_NAME, handle_lowerbound_array,
34        handle_lowerbound_key_value,
35    },
36    u64_div::{U64_DIV_EVENT_NAME, handle_u64_div},
37    u128_div::{U128_DIV_EVENT_NAME, handle_u128_div},
38    u256_div::{U256_DIV_EVENT_NAME, handle_u256_div},
39};
40
41// CORE LIBRARY
42// ================================================================================================
43
44/// The Miden core library, providing a set of optimized procedures for Miden programs.
45///
46/// This library wraps the `miden-core` [`Package`] and its `miden-precompiles` runtime dependency.
47/// When the core library is dynamically linked during assembly time, procedures can be called from
48/// any Miden program and are serialized as 32 bytes, reducing the amount of code that needs to be
49/// shared between parties for proving and verifying program execution.
50///
51/// # Contents
52///
53/// The core library provides several categories of functionality:
54///
55/// - **Cryptographic primitives**: Poseidon2, Blake3, SHA-256, Falcon signature verification,
56///   authenticated encryption (AEAD decryption), and stable core facades for bundled deferred
57///   precompiles under `::miden::core::*`.
58/// - **Mathematical operations**: Division operations for u64, u128, and u256.
59/// - **Data structures**: Sparse Merkle Tree operations, Merkle Mountain Range (MMR), and sorted
60///   array utilities with lower-bound search capabilities.
61/// - **Memory operations**: Efficient hashing and "un-hashing" of large amounts of data.
62///
63/// # Usage
64///
65/// The core library is typically used with the assembler to enable core library procedures
66/// in compiled programs:
67///
68/// ```rust,ignore
69/// use miden_assembly::{Assembler, Linkage};
70/// use miden_core_lib::CoreLibrary;
71///
72/// let core_lib = CoreLibrary::default();
73/// let mut assembler = Assembler::new(source_manager);
74/// for package in core_lib.packages() {
75///     assembler.link_package(package, Linkage::Dynamic).unwrap();
76/// }
77/// ```
78///
79/// For program execution, you'll also need to register the event handlers:
80///
81/// ```rust,ignore
82/// # let core_lib = CoreLibrary::default();
83/// let handlers = core_lib.handlers();
84/// // Register handlers with your host...
85/// ```
86///
87/// Stack and memory print-style debug handlers are registered with stdout writers by default.
88/// These handlers can print private values if a program moves witness data onto the operand stack
89/// or into memory. Privacy-sensitive hosts should replace or unregister these handlers. Advice
90/// debug handlers can expose witness data directly, so hosts must opt into those explicitly.
91///
92/// [`Package`]: miden_mast_package::Package
93#[derive(Clone)]
94pub struct CoreLibrary {
95    core_package: Arc<Package>,
96    precompiles_package: Arc<Package>,
97    mast_forest: Arc<MastForest>,
98}
99
100impl AsRef<Package> for CoreLibrary {
101    fn as_ref(&self) -> &Package {
102        &self.core_package
103    }
104}
105
106impl From<&CoreLibrary> for HostLibrary {
107    fn from(core_lib: &CoreLibrary) -> Self {
108        Self {
109            mast_forest: Arc::clone(core_lib.mast_forest()),
110            package_debug_info: Ok(None),
111            handlers: core_lib.handlers(),
112        }
113    }
114}
115
116impl CoreLibrary {
117    /// Serialized representation of the Miden `core` package.
118    pub const SERIALIZED: &'static [u8] =
119        include_bytes!(concat!(env!("OUT_DIR"), "/assets/miden-core.masp"));
120
121    /// Serialized representation of the `miden-precompiles` package used by the core library.
122    pub const PRECOMPILES_SERIALIZED: &'static [u8] =
123        include_bytes!(concat!(env!("OUT_DIR"), "/assets/miden-precompiles.masp"));
124
125    /// Returns a reference to the merged [MastForest] used to execute the core library and its
126    /// precompiles dependency.
127    pub fn mast_forest(&self) -> &Arc<MastForest> {
128        &self.mast_forest
129    }
130
131    /// Returns the `miden-core` package.
132    pub fn package(&self) -> Arc<Package> {
133        Arc::clone(&self.core_package)
134    }
135
136    /// Returns the `miden-precompiles` package required by `miden-core`.
137    pub fn precompiles_package(&self) -> Arc<Package> {
138        Arc::clone(&self.precompiles_package)
139    }
140
141    /// Returns the core package followed by its precompiles dependency.
142    pub fn packages(&self) -> [Arc<Package>; 2] {
143        [self.package(), self.precompiles_package()]
144    }
145
146    /// Returns the MAST root of `sys::vm::verify_vm_proof` — the verifier identity under
147    /// which recursive proofs are content-addressed.
148    ///
149    /// Operators pass this root when registering a proof package in the advice map
150    /// (`RecursiveVerifierInputs::for_request`). A consumer derives the identical value
151    /// in-VM with `procref` — a procedure's root is intrinsic to its own MAST — so the two sides
152    /// agree without a shared constant; consumers key their proof fetches by this root.
153    pub fn recursive_verifier_root(&self) -> Word {
154        self.core_package
155            .get_procedure_root_by_path("::miden::core::sys::vm::verify_vm_proof")
156            .expect("verify_vm_proof is exported from the core library")
157    }
158
159    /// Returns the default event handlers required by the core library.
160    ///
161    /// Stack and memory print-style debug handlers write to stdout by default. These handlers can
162    /// print private values if a program moves witness data onto the operand stack or into memory.
163    /// Hosts can replace those handlers to route output to a UI, log, no-op handler, or other sink.
164    /// Advice debug handlers can expose witness data directly, so hosts must opt into those
165    /// explicitly by extending this handler set with
166    /// [`crate::handlers::debug::advice_debug_handlers`].
167    pub fn handlers(&self) -> Vec<(EventName, Arc<dyn EventHandler>)> {
168        let mut handlers: Vec<(EventName, Arc<dyn EventHandler>)> = vec![
169            (SMT_PEEK_EVENT_NAME, Arc::new(handle_smt_peek)),
170            (U64_DIV_EVENT_NAME, Arc::new(handle_u64_div)),
171            (U128_DIV_EVENT_NAME, Arc::new(handle_u128_div)),
172            (U256_DIV_EVENT_NAME, Arc::new(handle_u256_div)),
173            (FALCON_DIV_EVENT_NAME, Arc::new(handle_falcon_div)),
174            (LOWERBOUND_ARRAY_EVENT_NAME, Arc::new(handle_lowerbound_array)),
175            (LOWERBOUND_KEY_VALUE_EVENT_NAME, Arc::new(handle_lowerbound_key_value)),
176            (AEAD_DECRYPT_EVENT_NAME, Arc::new(handle_aead_decrypt)),
177            (KECCAK256_DIGEST_EVENT_NAME, Arc::new(handle_keccak256_digest)),
178            (UINT_FIELD_INV_EVENT_NAME, Arc::new(handle_uint_field_inv)),
179        ];
180        handlers.extend(default_debug_handlers());
181        handlers.extend(readonly_noop_handlers());
182        handlers
183    }
184}
185
186impl Default for CoreLibrary {
187    fn default() -> Self {
188        static CORELIB: LazyLock<CoreLibrary> = LazyLock::new(|| {
189            let core_package = Arc::new(
190                Package::read_from_bytes_trusted(CoreLibrary::SERIALIZED)
191                    .expect("failed to read core package!"),
192            );
193            let precompiles_package = Arc::new(
194                Package::read_from_bytes_trusted(CoreLibrary::PRECOMPILES_SERIALIZED)
195                    .expect("failed to read precompiles package!"),
196            );
197            let (mast_forest, _) = MastForest::merge([
198                core_package.mast_forest().as_ref(),
199                precompiles_package.mast_forest().as_ref(),
200            ])
201            .expect("failed to merge core and precompiles MAST forests");
202
203            CoreLibrary {
204                core_package,
205                precompiles_package,
206                mast_forest: Arc::new(mast_forest),
207            }
208        });
209        CORELIB.clone()
210    }
211}
212
213// TESTS
214// ================================================================================================
215
216#[cfg(test)]
217mod tests {
218    use super::*;
219
220    #[test]
221    fn core_package_version_matches_crate_version() {
222        let core_lib = CoreLibrary::default();
223        let crate_version = env!("CARGO_PKG_VERSION")
224            .parse::<miden_mast_package::Version>()
225            .expect("crate version should be a valid package version");
226
227        for package in core_lib.packages() {
228            assert_eq!(
229                &package.version, &crate_version,
230                "embedded package {} should track the miden-core-lib crate version",
231                package.name,
232            );
233        }
234    }
235
236    #[test]
237    fn test_compile() {
238        let core_lib = CoreLibrary::default();
239        let exists = core_lib
240            .core_package
241            .get_procedure_root_by_path("::miden::core::math::u64::overflowing_add")
242            .is_some();
243
244        assert!(exists);
245    }
246}