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 a [`Package`] containing highly-optimized and battle-tested implementations
47/// of commonly-used primitives. When the core library is dynamically linked during assembly time,
48/// procedures can be called from any Miden program and are serialized as 32 bytes, reducing the
49/// amount of code that needs to be shared between parties for proving and verifying program
50/// execution.
51///
52/// # Contents
53///
54/// The core library provides several categories of functionality:
55///
56/// - **Cryptographic primitives**: Poseidon2, Blake3, SHA-256, Falcon signature verification,
57/// authenticated encryption (AEAD decryption), and stable core facades for bundled deferred
58/// precompiles under `::miden::core::*`.
59/// - **Mathematical operations**: Division operations for u64, u128, and u256.
60/// - **Data structures**: Sparse Merkle Tree operations, Merkle Mountain Range (MMR), and sorted
61/// array utilities with lower-bound search capabilities.
62/// - **Memory operations**: Efficient hashing and "un-hashing" of large amounts of data.
63///
64/// # Usage
65///
66/// The core library is typically used with the assembler to enable core library procedures
67/// in compiled programs:
68///
69/// ```rust,ignore
70/// use miden_assembly::{Assembler, Linkage};
71/// use miden_core_lib::CoreLibrary;
72///
73/// let core_lib = CoreLibrary::default();
74/// let assembler = Assembler::new(source_manager)
75/// .with_package(core_lib.package(), Linkage::Dynamic)
76/// .unwrap();
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(Arc<Package>);
95
96impl AsRef<Package> for CoreLibrary {
97 fn as_ref(&self) -> &Package {
98 &self.0
99 }
100}
101
102impl From<&CoreLibrary> for HostLibrary {
103 fn from(core_lib: &CoreLibrary) -> Self {
104 Self {
105 mast_forest: core_lib.mast_forest().clone(),
106 package_debug_info: Ok(None),
107 handlers: core_lib.handlers(),
108 }
109 }
110}
111
112impl CoreLibrary {
113 /// Serialized representation of the Miden `core` package.
114 pub const SERIALIZED: &'static [u8] =
115 include_bytes!(concat!(env!("OUT_DIR"), "/assets/miden-core.masp"));
116
117 /// Returns a reference to the [MastForest] underlying the Miden core library.
118 pub fn mast_forest(&self) -> &Arc<MastForest> {
119 self.0.mast_forest()
120 }
121
122 /// Returns a reference to the underlying [`Arc<Package>`].
123 pub fn package(&self) -> Arc<Package> {
124 self.0.clone()
125 }
126
127 /// Returns the MAST root of `sys::vm::verify_vm_proof` — the verifier identity under
128 /// which recursive proofs are content-addressed.
129 ///
130 /// Operators pass this root when registering a proof package in the advice map
131 /// (`RecursiveVerifierInputs::into_request_package`). A consumer derives the identical value
132 /// in-VM with `procref` — a procedure's root is intrinsic to its own MAST — so the two sides
133 /// agree without a shared constant; consumers key their proof fetches by this root.
134 pub fn recursive_verifier_root(&self) -> Word {
135 self.0
136 .get_procedure_root_by_path("::miden::core::sys::vm::verify_vm_proof")
137 .expect("verify_vm_proof is exported from the core library")
138 }
139
140 /// Returns the default event handlers required by the core library.
141 ///
142 /// Stack and memory print-style debug handlers write to stdout by default. These handlers can
143 /// print private values if a program moves witness data onto the operand stack or into memory.
144 /// Hosts can replace those handlers to route output to a UI, log, no-op handler, or other sink.
145 /// Advice debug handlers can expose witness data directly, so hosts must opt into those
146 /// explicitly by extending this handler set with
147 /// [`crate::handlers::debug::advice_debug_handlers`].
148 pub fn handlers(&self) -> Vec<(EventName, Arc<dyn EventHandler>)> {
149 let mut handlers: Vec<(EventName, Arc<dyn EventHandler>)> = vec![
150 (SMT_PEEK_EVENT_NAME, Arc::new(handle_smt_peek)),
151 (U64_DIV_EVENT_NAME, Arc::new(handle_u64_div)),
152 (U128_DIV_EVENT_NAME, Arc::new(handle_u128_div)),
153 (U256_DIV_EVENT_NAME, Arc::new(handle_u256_div)),
154 (FALCON_DIV_EVENT_NAME, Arc::new(handle_falcon_div)),
155 (LOWERBOUND_ARRAY_EVENT_NAME, Arc::new(handle_lowerbound_array)),
156 (LOWERBOUND_KEY_VALUE_EVENT_NAME, Arc::new(handle_lowerbound_key_value)),
157 (AEAD_DECRYPT_EVENT_NAME, Arc::new(handle_aead_decrypt)),
158 (KECCAK256_DIGEST_EVENT_NAME, Arc::new(handle_keccak256_digest)),
159 (UINT_FIELD_INV_EVENT_NAME, Arc::new(handle_uint_field_inv)),
160 ];
161 handlers.extend(default_debug_handlers());
162 handlers.extend(readonly_noop_handlers());
163 handlers
164 }
165}
166
167impl Default for CoreLibrary {
168 fn default() -> Self {
169 static CORELIB: LazyLock<CoreLibrary> = LazyLock::new(|| {
170 let contents = Package::read_from_bytes_trusted(CoreLibrary::SERIALIZED)
171 .expect("failed to read core package!");
172 CoreLibrary(Arc::new(contents))
173 });
174 CORELIB.clone()
175 }
176}
177
178// TESTS
179// ================================================================================================
180
181#[cfg(test)]
182mod tests {
183 use super::*;
184
185 #[test]
186 fn core_package_version_matches_crate_version() {
187 let core_lib = CoreLibrary::default();
188 let package = core_lib.package();
189 let crate_version = env!("CARGO_PKG_VERSION")
190 .parse::<miden_mast_package::Version>()
191 .expect("crate version should be a valid package version");
192
193 assert_eq!(
194 &package.version, &crate_version,
195 "embedded core package version should track the miden-core-lib crate version",
196 );
197 }
198
199 #[test]
200 fn test_compile() {
201 let core_lib = CoreLibrary::default();
202 let exists = core_lib
203 .0
204 .get_procedure_root_by_path("::miden::core::math::u64::overflowing_add")
205 .is_some();
206
207 assert!(exists);
208 }
209}