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_assembly::{Library, mast::MastForest};
16use miden_core::{
17    events::EventName, precompile::PrecompileVerifierRegistry, serde::Deserializable,
18};
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    ecdsa::{ECDSA_VERIFY_EVENT_NAME, EcdsaPrecompile},
25    eddsa_ed25519::{EDDSA25519_VERIFY_EVENT_NAME, EddsaPrecompile},
26    falcon_div::{FALCON_DIV_EVENT_NAME, handle_falcon_div},
27    keccak256::{KECCAK_HASH_BYTES_EVENT_NAME, KeccakPrecompile},
28    readonly::{
29        READONLY_MIDEN_DEBUG_ASSERTION_FAILED, READONLY_MIDEN_DEBUG_FRAME_END,
30        READONLY_MIDEN_DEBUG_FRAME_START, READONLY_MIDEN_DEBUG_PRINTLN,
31        READONLY_MIDEN_DEBUG_UNKNOWN, readonly_noop_handler,
32    },
33    sha512::{SHA512_HASH_BYTES_EVENT_NAME, Sha512Precompile},
34    smt_peek::{SMT_PEEK_EVENT_NAME, handle_smt_peek},
35    sorted_array::{
36        LOWERBOUND_ARRAY_EVENT_NAME, LOWERBOUND_KEY_VALUE_EVENT_NAME, handle_lowerbound_array,
37        handle_lowerbound_key_value,
38    },
39    u64_div::{U64_DIV_EVENT_NAME, handle_u64_div},
40    u128_div::{U128_DIV_EVENT_NAME, handle_u128_div},
41};
42
43// CORE LIBRARY
44// ================================================================================================
45
46/// The Miden core library, providing a set of optimized procedures for Miden programs.
47///
48/// This library wraps a [`Library`] containing highly-optimized and battle-tested implementations
49/// of commonly-used primitives. When the core library is dynamically linked during assembly time,
50/// procedures can be called from any Miden program and are serialized as 32 bytes, reducing the
51/// amount of code that needs to be shared between parties for proving and verifying program
52/// execution.
53///
54/// # Contents
55///
56/// The core library provides several categories of functionality:
57///
58/// - **Cryptographic primitives**: Hash functions (Keccak256, SHA-512), digital signature
59///   verification (ECDSA, EdDSA-Ed25519, Falcon), and authenticated encryption (AEAD decryption).
60/// - **Mathematical operations**: Division operations for u64, u128, and u256.
61/// - **Data structures**: Sparse Merkle Tree operations, Merkle Mountain Range (MMR), and sorted
62///   array utilities with lower-bound search capabilities.
63/// - **Memory operations**: Efficient hashing and "un-hashing" of large amounts of data.
64///
65/// Many of these operations are implemented as **precompiles** - special procedures that execute
66/// outside the Miden VM but are verified as part of the proof. Precompiles allow for efficient
67/// execution of complex operations that would be expensive to compute directly in the VM, while
68/// maintaining the security guarantees of the Miden proof system. The core library includes
69/// precompiles for cryptographic operations like hash functions and signature verification.
70///
71/// # Usage
72///
73/// The core library is typically used with an [`Assembler`] to enable core library procedures
74/// in compiled programs:
75///
76/// ```rust,ignore
77/// use miden_assembly::Assembler;
78/// use miden_core_lib::CoreLibrary;
79///
80/// let assembler = Assembler::new(source_manager)
81///     .with_dynamic_library(&CoreLibrary::default())
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/// For proof verification, use [`verifier_registry()`](Self::verifier_registry) to get the
94/// precompile verifiers required to validate core library precompile requests.
95///
96/// [`Library`]: miden_assembly::Library
97/// [`Assembler`]: miden_assembly::Assembler
98#[derive(Clone)]
99pub struct CoreLibrary(Library);
100
101impl AsRef<Library> for CoreLibrary {
102    fn as_ref(&self) -> &Library {
103        &self.0
104    }
105}
106
107impl From<CoreLibrary> for Library {
108    fn from(value: CoreLibrary) -> Self {
109        value.0
110    }
111}
112
113impl From<&CoreLibrary> for HostLibrary {
114    fn from(core_lib: &CoreLibrary) -> Self {
115        Self {
116            mast_forest: core_lib.mast_forest().clone(),
117            handlers: core_lib.handlers(),
118        }
119    }
120}
121
122impl CoreLibrary {
123    /// Serialized representation of the Miden core library.
124    pub const SERIALIZED: &'static [u8] =
125        include_bytes!(concat!(env!("OUT_DIR"), "/assets/core.masl"));
126
127    /// Returns a reference to the [MastForest] underlying the Miden core library.
128    pub fn mast_forest(&self) -> &Arc<MastForest> {
129        self.0.mast_forest()
130    }
131
132    /// Returns a reference to the underlying [`Library`].
133    pub fn library(&self) -> &Library {
134        &self.0
135    }
136
137    /// List of all `EventHandlers` required to run all of the core library.
138    pub fn handlers(&self) -> Vec<(EventName, Arc<dyn EventHandler>)> {
139        vec![
140            (KECCAK_HASH_BYTES_EVENT_NAME, Arc::new(KeccakPrecompile)),
141            (SHA512_HASH_BYTES_EVENT_NAME, Arc::new(Sha512Precompile)),
142            (ECDSA_VERIFY_EVENT_NAME, Arc::new(EcdsaPrecompile)),
143            (EDDSA25519_VERIFY_EVENT_NAME, Arc::new(EddsaPrecompile)),
144            (SMT_PEEK_EVENT_NAME, Arc::new(handle_smt_peek)),
145            (U64_DIV_EVENT_NAME, Arc::new(handle_u64_div)),
146            (U128_DIV_EVENT_NAME, Arc::new(handle_u128_div)),
147            (FALCON_DIV_EVENT_NAME, Arc::new(handle_falcon_div)),
148            (LOWERBOUND_ARRAY_EVENT_NAME, Arc::new(handle_lowerbound_array)),
149            (LOWERBOUND_KEY_VALUE_EVENT_NAME, Arc::new(handle_lowerbound_key_value)),
150            (AEAD_DECRYPT_EVENT_NAME, Arc::new(handle_aead_decrypt)),
151            (READONLY_MIDEN_DEBUG_FRAME_START, Arc::new(readonly_noop_handler)),
152            (READONLY_MIDEN_DEBUG_FRAME_END, Arc::new(readonly_noop_handler)),
153            (READONLY_MIDEN_DEBUG_ASSERTION_FAILED, Arc::new(readonly_noop_handler)),
154            (READONLY_MIDEN_DEBUG_UNKNOWN, Arc::new(readonly_noop_handler)),
155            (READONLY_MIDEN_DEBUG_PRINTLN, Arc::new(readonly_noop_handler)),
156        ]
157    }
158
159    /// Returns a [`PrecompileVerifierRegistry`] containing all verifiers required to validate
160    /// core library precompile requests.
161    pub fn verifier_registry(&self) -> PrecompileVerifierRegistry {
162        PrecompileVerifierRegistry::new()
163            .with_verifier(&KECCAK_HASH_BYTES_EVENT_NAME, Arc::new(KeccakPrecompile))
164            .with_verifier(&SHA512_HASH_BYTES_EVENT_NAME, Arc::new(Sha512Precompile))
165            .with_verifier(&ECDSA_VERIFY_EVENT_NAME, Arc::new(EcdsaPrecompile))
166            .with_verifier(&EDDSA25519_VERIFY_EVENT_NAME, Arc::new(EddsaPrecompile))
167    }
168}
169
170impl Default for CoreLibrary {
171    fn default() -> Self {
172        static CORELIB: LazyLock<CoreLibrary> = LazyLock::new(|| {
173            let contents = Library::read_from_bytes(CoreLibrary::SERIALIZED)
174                .expect("failed to read core masl!");
175            CoreLibrary(contents)
176        });
177        CORELIB.clone()
178    }
179}
180
181// TESTS
182// ================================================================================================
183
184#[cfg(test)]
185mod tests {
186    use miden_assembly::Path;
187
188    use super::*;
189
190    #[test]
191    fn test_compile() {
192        let path = Path::new("::miden::core::math::u64::overflowing_add");
193        let core_lib = CoreLibrary::default();
194        let exists = core_lib.0.module_infos().any(|module| {
195            module.procedures().any(|(_, proc)| &module.path().join(&proc.name) == path)
196        });
197
198        assert!(exists);
199    }
200}