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