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;
9pub mod handlers;
10
11extern crate alloc;
12
13use alloc::{sync::Arc, vec, vec::Vec};
14
15use miden_core::{
16 events::EventName, mast::MastForest, precompile::PrecompileVerifierRegistry,
17 serde::Deserializable,
18};
19use miden_mast_package::Package;
20use miden_processor::{HostLibrary, event::EventHandler};
21use miden_utils_sync::LazyLock;
22
23use crate::handlers::{
24 aead_decrypt::{AEAD_DECRYPT_EVENT_NAME, handle_aead_decrypt},
25 debug::default_debug_handlers,
26 ecdsa::{ECDSA_VERIFY_EVENT_NAME, EcdsaPrecompile},
27 eddsa_ed25519::{EDDSA25519_VERIFY_EVENT_NAME, EddsaPrecompile},
28 falcon_div::{FALCON_DIV_EVENT_NAME, handle_falcon_div},
29 keccak256::{KECCAK_HASH_BYTES_EVENT_NAME, KeccakPrecompile},
30 readonly::readonly_noop_handlers,
31 sha512::{SHA512_HASH_BYTES_EVENT_NAME, Sha512Precompile},
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// CORE LIBRARY
43// ================================================================================================
44
45/// The Miden core library, providing a set of optimized procedures for Miden programs.
46///
47/// This library wraps a [`Package`] containing highly-optimized and battle-tested implementations
48/// of commonly-used primitives. When the core library is dynamically linked during assembly time,
49/// procedures can be called from any Miden program and are serialized as 32 bytes, reducing the
50/// amount of code that needs to be shared between parties for proving and verifying program
51/// execution.
52///
53/// # Contents
54///
55/// The core library provides several categories of functionality:
56///
57/// - **Cryptographic primitives**: Hash functions (Keccak256, SHA-512), digital signature
58/// verification (ECDSA, EdDSA-Ed25519, Falcon), and authenticated encryption (AEAD decryption).
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/// Many of these operations are implemented as **precompiles** - special procedures that execute
65/// outside the Miden VM but are verified as part of the proof. Precompiles allow for efficient
66/// execution of complex operations that would be expensive to compute directly in the VM, while
67/// maintaining the security guarantees of the Miden proof system. The core library includes
68/// precompiles for cryptographic operations like hash functions and signature verification.
69///
70/// # Usage
71///
72/// The core library is typically used with the assembler to enable core library procedures
73/// in compiled programs:
74///
75/// ```rust,ignore
76/// use miden_assembly::{Assembler, Linkage};
77/// use miden_core_lib::CoreLibrary;
78///
79/// let core_lib = CoreLibrary::default();
80/// let assembler = Assembler::new(source_manager)
81/// .with_package(core_lib.package(), Linkage::Dynamic)
82/// .unwrap();
83/// ```
84///
85/// For program execution, you'll also need to register the event handlers:
86///
87/// ```rust,ignore
88/// # let core_lib = CoreLibrary::default();
89/// let handlers = core_lib.handlers();
90/// // Register handlers with your host...
91/// ```
92///
93/// Stack and memory print-style debug handlers are registered with stdout writers by default.
94/// These handlers can print private values if a program moves witness data onto the operand stack
95/// or into memory. Privacy-sensitive hosts should replace or unregister these handlers. Advice
96/// debug handlers can expose witness data directly, so hosts must opt into those explicitly.
97///
98/// For proof verification, use [`verifier_registry()`](Self::verifier_registry) to get the
99/// precompile verifiers required to validate core library precompile requests.
100///
101/// [`Package`]: miden_mast_package::Package
102#[derive(Clone)]
103pub struct CoreLibrary(Arc<Package>);
104
105impl AsRef<Package> for CoreLibrary {
106 fn as_ref(&self) -> &Package {
107 &self.0
108 }
109}
110
111impl From<&CoreLibrary> for HostLibrary {
112 fn from(core_lib: &CoreLibrary) -> Self {
113 Self {
114 mast_forest: core_lib.mast_forest().clone(),
115 package_debug_info: Ok(None),
116 handlers: core_lib.handlers(),
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] underlying the Miden core library.
127 pub fn mast_forest(&self) -> &Arc<MastForest> {
128 self.0.mast_forest()
129 }
130
131 /// Returns a reference to the underlying [`Arc<Package>`].
132 pub fn package(&self) -> Arc<Package> {
133 self.0.clone()
134 }
135
136 /// Returns the default event handlers required by the core library.
137 ///
138 /// Stack and memory print-style debug handlers write to stdout by default. These handlers can
139 /// print private values if a program moves witness data onto the operand stack or into memory.
140 /// Hosts can replace those handlers to route output to a UI, log, no-op handler, or other sink.
141 /// Advice debug handlers can expose witness data directly, so hosts must opt into those
142 /// explicitly by extending this handler set with
143 /// [`crate::handlers::debug::advice_debug_handlers`].
144 pub fn handlers(&self) -> Vec<(EventName, Arc<dyn EventHandler>)> {
145 let mut handlers: Vec<(EventName, Arc<dyn EventHandler>)> = vec![
146 (KECCAK_HASH_BYTES_EVENT_NAME, Arc::new(KeccakPrecompile)),
147 (SHA512_HASH_BYTES_EVENT_NAME, Arc::new(Sha512Precompile)),
148 (ECDSA_VERIFY_EVENT_NAME, Arc::new(EcdsaPrecompile)),
149 (EDDSA25519_VERIFY_EVENT_NAME, Arc::new(EddsaPrecompile)),
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 ];
159 handlers.extend(default_debug_handlers());
160 handlers.extend(readonly_noop_handlers());
161 handlers
162 }
163
164 /// Returns a [`PrecompileVerifierRegistry`] containing all verifiers required to validate
165 /// core library precompile requests.
166 pub fn verifier_registry(&self) -> PrecompileVerifierRegistry {
167 PrecompileVerifierRegistry::new()
168 .with_verifier(&KECCAK_HASH_BYTES_EVENT_NAME, Arc::new(KeccakPrecompile))
169 .with_verifier(&SHA512_HASH_BYTES_EVENT_NAME, Arc::new(Sha512Precompile))
170 .with_verifier(&ECDSA_VERIFY_EVENT_NAME, Arc::new(EcdsaPrecompile))
171 .with_verifier(&EDDSA25519_VERIFY_EVENT_NAME, Arc::new(EddsaPrecompile))
172 }
173}
174
175impl Default for CoreLibrary {
176 fn default() -> Self {
177 static CORELIB: LazyLock<CoreLibrary> = LazyLock::new(|| {
178 let contents = Package::read_from_bytes(CoreLibrary::SERIALIZED)
179 .expect("failed to read core package!");
180 CoreLibrary(Arc::new(contents))
181 });
182 CORELIB.clone()
183 }
184}
185
186// TESTS
187// ================================================================================================
188
189#[cfg(test)]
190mod tests {
191 use super::*;
192
193 #[test]
194 fn test_compile() {
195 let core_lib = CoreLibrary::default();
196 let exists = core_lib
197 .0
198 .get_procedure_root_by_path("::miden::core::math::u64::overflowing_add")
199 .is_some();
200
201 assert!(exists);
202 }
203}