#![no_std]
#[cfg(feature = "std")]
extern crate std;
#[cfg(any(feature = "constraints-tools", all(test, feature = "std")))]
pub mod constraints_regen;
pub mod dsa;
#[cfg(feature = "constraints-tools")]
pub mod evaluator_regen;
pub mod handlers;
extern crate alloc;
use alloc::{sync::Arc, vec, vec::Vec};
use miden_core::{Word, events::EventName, mast::MastForest};
use miden_mast_package::Package;
use miden_processor::{HostLibrary, event::EventHandler};
use miden_utils_sync::LazyLock;
use crate::handlers::{
aead_decrypt::{AEAD_DECRYPT_EVENT_NAME, handle_aead_decrypt},
debug::default_debug_handlers,
falcon_div::{FALCON_DIV_EVENT_NAME, handle_falcon_div},
precompiles::{
keccak256::{KECCAK256_DIGEST_EVENT_NAME, handle_keccak256_digest},
uint_field_inv::{UINT_FIELD_INV_EVENT_NAME, handle_uint_field_inv},
},
readonly::readonly_noop_handlers,
smt_peek::{SMT_PEEK_EVENT_NAME, handle_smt_peek},
sorted_array::{
LOWERBOUND_ARRAY_EVENT_NAME, LOWERBOUND_KEY_VALUE_EVENT_NAME, handle_lowerbound_array,
handle_lowerbound_key_value,
},
u64_div::{U64_DIV_EVENT_NAME, handle_u64_div},
u128_div::{U128_DIV_EVENT_NAME, handle_u128_div},
u256_div::{U256_DIV_EVENT_NAME, handle_u256_div},
};
#[derive(Clone)]
pub struct CoreLibrary {
core_package: Arc<Package>,
precompiles_package: Arc<Package>,
mast_forest: Arc<MastForest>,
}
impl AsRef<Package> for CoreLibrary {
fn as_ref(&self) -> &Package {
&self.core_package
}
}
impl From<&CoreLibrary> for HostLibrary {
fn from(core_lib: &CoreLibrary) -> Self {
Self {
mast_forest: Arc::clone(core_lib.mast_forest()),
package_debug_info: Ok(None),
handlers: core_lib.handlers(),
}
}
}
impl CoreLibrary {
pub const SERIALIZED: &'static [u8] =
include_bytes!(concat!(env!("OUT_DIR"), "/assets/miden-core.masp"));
pub const PRECOMPILES_SERIALIZED: &'static [u8] =
include_bytes!(concat!(env!("OUT_DIR"), "/assets/miden-precompiles.masp"));
pub fn mast_forest(&self) -> &Arc<MastForest> {
&self.mast_forest
}
pub fn package(&self) -> Arc<Package> {
Arc::clone(&self.core_package)
}
pub fn precompiles_package(&self) -> Arc<Package> {
Arc::clone(&self.precompiles_package)
}
pub fn packages(&self) -> [Arc<Package>; 2] {
[self.package(), self.precompiles_package()]
}
pub fn recursive_verifier_root(&self) -> Word {
self.core_package
.get_procedure_root_by_path("::miden::core::sys::vm::verify_vm_proof")
.expect("verify_vm_proof is exported from the core library")
}
pub fn handlers(&self) -> Vec<(EventName, Arc<dyn EventHandler>)> {
let mut handlers: Vec<(EventName, Arc<dyn EventHandler>)> = vec![
(SMT_PEEK_EVENT_NAME, Arc::new(handle_smt_peek)),
(U64_DIV_EVENT_NAME, Arc::new(handle_u64_div)),
(U128_DIV_EVENT_NAME, Arc::new(handle_u128_div)),
(U256_DIV_EVENT_NAME, Arc::new(handle_u256_div)),
(FALCON_DIV_EVENT_NAME, Arc::new(handle_falcon_div)),
(LOWERBOUND_ARRAY_EVENT_NAME, Arc::new(handle_lowerbound_array)),
(LOWERBOUND_KEY_VALUE_EVENT_NAME, Arc::new(handle_lowerbound_key_value)),
(AEAD_DECRYPT_EVENT_NAME, Arc::new(handle_aead_decrypt)),
(KECCAK256_DIGEST_EVENT_NAME, Arc::new(handle_keccak256_digest)),
(UINT_FIELD_INV_EVENT_NAME, Arc::new(handle_uint_field_inv)),
];
handlers.extend(default_debug_handlers());
handlers.extend(readonly_noop_handlers());
handlers
}
}
impl Default for CoreLibrary {
fn default() -> Self {
static CORELIB: LazyLock<CoreLibrary> = LazyLock::new(|| {
let core_package = Arc::new(
Package::read_from_bytes_trusted(CoreLibrary::SERIALIZED)
.expect("failed to read core package!"),
);
let precompiles_package = Arc::new(
Package::read_from_bytes_trusted(CoreLibrary::PRECOMPILES_SERIALIZED)
.expect("failed to read precompiles package!"),
);
let (mast_forest, _) = MastForest::merge([
core_package.mast_forest().as_ref(),
precompiles_package.mast_forest().as_ref(),
])
.expect("failed to merge core and precompiles MAST forests");
CoreLibrary {
core_package,
precompiles_package,
mast_forest: Arc::new(mast_forest),
}
});
CORELIB.clone()
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn core_package_version_matches_crate_version() {
let core_lib = CoreLibrary::default();
let crate_version = env!("CARGO_PKG_VERSION")
.parse::<miden_mast_package::Version>()
.expect("crate version should be a valid package version");
for package in core_lib.packages() {
assert_eq!(
&package.version, &crate_version,
"embedded package {} should track the miden-core-lib crate version",
package.name,
);
}
}
#[test]
fn test_compile() {
let core_lib = CoreLibrary::default();
let exists = core_lib
.core_package
.get_procedure_root_by_path("::miden::core::math::u64::overflowing_add")
.is_some();
assert!(exists);
}
}