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 ecdsa_k256_keccak::{ECDSA_K256_KECCAK_RECOVER_EVENT_NAME, handle_ecdsa_k256_keccak_recover},
26 falcon_div::{FALCON_DIV_EVENT_NAME, handle_falcon_div},
27 precompiles::{
28 keccak256::{KECCAK256_DIGEST_EVENT_NAME, handle_keccak256_digest},
29 uint_field_inv::{UINT_FIELD_INV_EVENT_NAME, handle_uint_field_inv},
30 },
31 readonly::readonly_noop_handlers,
32 smt_peek::{SMT_PEEK_EVENT_NAME, handle_smt_peek},
33 sorted_array::{
34 LOWERBOUND_ARRAY_EVENT_NAME, LOWERBOUND_KEY_VALUE_EVENT_NAME, handle_lowerbound_array,
35 handle_lowerbound_key_value,
36 },
37 u64_div::{U64_DIV_EVENT_NAME, handle_u64_div},
38 u128_div::{U128_DIV_EVENT_NAME, handle_u128_div},
39 u256_div::{U256_DIV_EVENT_NAME, handle_u256_div},
40};
41
42/// Event emitted by `sys::pvm::request_proof` to request an asynchronously supplied PVM proof
43/// package. The PVM verifier root is at stack positions 1 through 4 and the deferred root is at
44/// positions 5 through 8.
45///
46/// Emitting the event does not authenticate the root. The calling program must establish it before
47/// making the request and must verify the returned PVM proof against the unchanged value.
48///
49/// The core library does not register a default handler. Hosts that support on-demand settlement
50/// should handle this event and return advice-map and Merkle-store mutations containing a package
51/// keyed by `proof_request_key(pvm_verifier_root, deferred_root)`. The procedure fetches that
52/// package after the handler returns.
53pub const PVM_PROOF_REQUEST_EVENT_NAME: EventName =
54 EventName::new("miden::core::sys::pvm::request_proof");
55
56// CORE LIBRARY
57// ================================================================================================
58
59/// The Miden core library, providing a set of optimized procedures for Miden programs.
60///
61/// This library wraps the `miden-core` [`Package`].
62///
63/// When the core library is dynamically linked during assembly time, procedures can be called from
64/// any Miden program and are serialized as 32 bytes, reducing the amount of code that needs to be
65/// shared between parties for proving and verifying program execution.
66///
67/// # Contents
68///
69/// The core library provides several categories of functionality:
70///
71/// - **Cryptographic primitives**: Poseidon2, Blake3, SHA-256, Falcon signature verification,
72/// authenticated encryption (AEAD decryption), and stable core facades for bundled deferred
73/// precompiles under `::miden::core::*`.
74/// - **Mathematical operations**: Division operations for u64, u128, and u256.
75/// - **Data structures**: Sparse Merkle Tree operations, Merkle Mountain Range (MMR), and sorted
76/// array utilities with lower-bound search capabilities.
77/// - **Memory operations**: Efficient hashing and "un-hashing" of large amounts of data.
78///
79/// # Usage
80///
81/// The core library is typically used with the assembler to enable core library procedures
82/// in compiled programs:
83///
84/// ```rust,ignore
85/// use miden_assembly::{Assembler, Linkage};
86/// use miden_core_lib::CoreLibrary;
87///
88/// let core_lib = CoreLibrary::default();
89/// let mut assembler = Assembler::new(source_manager);
90/// assembler.link_package(core_lib.package(), Linkage::Dynamic).unwrap();
91/// ```
92///
93/// For program execution, you'll also need to register the event handlers:
94///
95/// ```rust,ignore
96/// # let core_lib = CoreLibrary::default();
97/// let handlers = core_lib.handlers();
98/// // Register handlers with your host...
99/// ```
100///
101/// Stack and memory print-style debug handlers are registered with stdout writers by default.
102/// These handlers can print private values if a program moves witness data onto the operand stack
103/// or into memory. Privacy-sensitive hosts should replace or unregister these handlers. Advice
104/// debug handlers can expose witness data directly, so hosts must opt into those explicitly.
105///
106/// [`Package`]: miden_mast_package::Package
107#[derive(Clone)]
108pub struct CoreLibrary {
109 package: Arc<Package>,
110}
111
112impl From<&CoreLibrary> for HostLibrary {
113 fn from(core_lib: &CoreLibrary) -> Self {
114 Self {
115 handlers: core_lib.handlers(),
116 ..HostLibrary::from(core_lib.package.clone())
117 }
118 }
119}
120
121impl CoreLibrary {
122 /// Serialized representation of the Miden `core` package.
123 pub const SERIALIZED: &'static [u8] =
124 include_bytes!(concat!(env!("OUT_DIR"), "/assets/miden-core.masp"));
125
126 /// Returns a reference to the [MastForest] used to execute the core library
127 pub fn mast_forest(&self) -> &Arc<MastForest> {
128 self.package.mast_forest()
129 }
130
131 /// Returns the `miden-core` package.
132 pub fn package(&self) -> Arc<Package> {
133 Arc::clone(&self.package)
134 }
135
136 /// Returns the MAST root of `sys::vm::verify_proof`, the verifier identity under
137 /// which recursive proofs are content-addressed.
138 ///
139 /// Operators pass this root when registering a proof package in the advice map
140 /// (`RecursiveVerifierInputs::for_request`). A consumer derives the identical value
141 /// in-VM with `procref` — a procedure's root is intrinsic to its own MAST — so the two sides
142 /// agree without a shared constant; consumers key their proof fetches by this root.
143 pub fn vm_recursive_verifier_root(&self) -> Word {
144 self.package
145 .get_procedure_root_by_path("::miden::core::sys::vm::verify_proof")
146 .expect("vm::verify_proof is exported from the core library")
147 }
148
149 /// Returns the MAST root of `sys::pvm::verify_proof` — the verifier identity under which PVM
150 /// proof packages are content-addressed.
151 ///
152 /// A host passes this root to the PVM advice builder when registering a package. A consumer
153 /// derives the same root in-VM with `procref`, avoiding a duplicated constant.
154 pub fn pvm_recursive_verifier_root(&self) -> Word {
155 self.package
156 .get_procedure_root_by_path("::miden::core::sys::pvm::verify_proof")
157 .expect("pvm::verify_proof is exported from the core library")
158 }
159
160 /// Returns the MAST root of the common recursive conjectured security estimator.
161 ///
162 /// The MVM and PVM verifiers return relation-specific descriptors consumed by this one
163 /// procedure. Its root does not encode an acceptance threshold; each consumer compares the
164 /// returned level with its own threshold. The estimator does not verify proofs or authenticate
165 /// descriptors assembled by the caller.
166 pub fn conjectured_security_estimator_root(&self) -> Word {
167 self.package
168 .get_procedure_root_by_path(
169 "::miden::core::stark::security::compute_conjectured_security_level",
170 )
171 .expect("the conjectured security estimator is exported from the core library")
172 }
173
174 /// Returns the default event handlers required by the core library.
175 ///
176 /// Stack and memory print-style debug handlers write to stdout by default. These handlers can
177 /// print private values if a program moves witness data onto the operand stack or into memory.
178 /// Hosts can replace those handlers to route output to a UI, log, no-op handler, or other sink.
179 /// Advice debug handlers can expose witness data directly, so hosts must opt into those
180 /// explicitly by extending this handler set with
181 /// [`crate::handlers::debug::advice_debug_handlers`].
182 pub fn handlers(&self) -> Vec<(EventName, Arc<dyn EventHandler>)> {
183 let mut handlers: Vec<(EventName, Arc<dyn EventHandler>)> = vec![
184 (SMT_PEEK_EVENT_NAME, Arc::new(handle_smt_peek)),
185 (U64_DIV_EVENT_NAME, Arc::new(handle_u64_div)),
186 (U128_DIV_EVENT_NAME, Arc::new(handle_u128_div)),
187 (U256_DIV_EVENT_NAME, Arc::new(handle_u256_div)),
188 (FALCON_DIV_EVENT_NAME, Arc::new(handle_falcon_div)),
189 (LOWERBOUND_ARRAY_EVENT_NAME, Arc::new(handle_lowerbound_array)),
190 (LOWERBOUND_KEY_VALUE_EVENT_NAME, Arc::new(handle_lowerbound_key_value)),
191 (AEAD_DECRYPT_EVENT_NAME, Arc::new(handle_aead_decrypt)),
192 (ECDSA_K256_KECCAK_RECOVER_EVENT_NAME, Arc::new(handle_ecdsa_k256_keccak_recover)),
193 (KECCAK256_DIGEST_EVENT_NAME, Arc::new(handle_keccak256_digest)),
194 (UINT_FIELD_INV_EVENT_NAME, Arc::new(handle_uint_field_inv)),
195 ];
196 handlers.extend(default_debug_handlers());
197 handlers.extend(readonly_noop_handlers());
198 handlers
199 }
200}
201
202impl Default for CoreLibrary {
203 fn default() -> Self {
204 static CORELIB: LazyLock<CoreLibrary> = LazyLock::new(|| {
205 let package = Arc::new(
206 Package::read_from_bytes_trusted(CoreLibrary::SERIALIZED)
207 .expect("failed to read core package!"),
208 );
209
210 CoreLibrary { package }
211 });
212 CORELIB.clone()
213 }
214}
215
216/// Returns the MAST root of the common recursive conjectured security estimator.
217pub fn conjectured_security_estimator_root() -> Word {
218 CoreLibrary::default().conjectured_security_estimator_root()
219}
220
221// TESTS
222// ================================================================================================
223
224#[cfg(test)]
225mod tests {
226 use miden_verifier::Verifier;
227
228 use super::*;
229
230 #[test]
231 fn core_package_version_matches_crate_version() {
232 let core_lib = CoreLibrary::default();
233 let crate_version = env!("CARGO_PKG_VERSION")
234 .parse::<miden_mast_package::Version>()
235 .expect("crate version should be a valid package version");
236
237 assert_eq!(
238 &core_lib.package.version, &crate_version,
239 "embedded package {} should track the miden-core-lib crate version",
240 core_lib.package.name,
241 );
242 }
243
244 #[test]
245 fn test_compile() {
246 let core_lib = CoreLibrary::default();
247 let exists = core_lib
248 .package
249 .get_procedure_root_by_path("::miden::core::math::u64::overflowing_add")
250 .is_some();
251
252 assert!(exists);
253 }
254
255 #[test]
256 fn proof_compatibility_roots_match_the_embedded_core_library() {
257 let core_lib = CoreLibrary::default();
258 let compatibility = Verifier::proof_compatibility();
259
260 assert_eq!(
261 compatibility.vm_verifier_roots().last(),
262 Some(&core_lib.vm_recursive_verifier_root()),
263 );
264 assert_eq!(
265 compatibility.pvm_verifier_roots().last(),
266 Some(&core_lib.pvm_recursive_verifier_root()),
267 );
268 }
269}