#![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,
ecdsa_k256_keccak::{ECDSA_K256_KECCAK_RECOVER_EVENT_NAME, handle_ecdsa_k256_keccak_recover},
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},
};
pub const PVM_PROOF_REQUEST_EVENT_NAME: EventName =
EventName::new("miden::core::sys::pvm::request_proof");
#[derive(Clone)]
pub struct CoreLibrary {
package: Arc<Package>,
}
impl From<&CoreLibrary> for HostLibrary {
fn from(core_lib: &CoreLibrary) -> Self {
Self {
handlers: core_lib.handlers(),
..HostLibrary::from(core_lib.package.clone())
}
}
}
impl CoreLibrary {
pub const SERIALIZED: &'static [u8] =
include_bytes!(concat!(env!("OUT_DIR"), "/assets/miden-core.masp"));
pub fn mast_forest(&self) -> &Arc<MastForest> {
self.package.mast_forest()
}
pub fn package(&self) -> Arc<Package> {
Arc::clone(&self.package)
}
pub fn vm_recursive_verifier_root(&self) -> Word {
self.package
.get_procedure_root_by_path("::miden::core::sys::vm::verify_proof")
.expect("vm::verify_proof is exported from the core library")
}
pub fn pvm_recursive_verifier_root(&self) -> Word {
self.package
.get_procedure_root_by_path("::miden::core::sys::pvm::verify_proof")
.expect("pvm::verify_proof is exported from the core library")
}
pub fn conjectured_security_estimator_root(&self) -> Word {
self.package
.get_procedure_root_by_path(
"::miden::core::stark::security::compute_conjectured_security_level",
)
.expect("the conjectured security estimator 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)),
(ECDSA_K256_KECCAK_RECOVER_EVENT_NAME, Arc::new(handle_ecdsa_k256_keccak_recover)),
(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 package = Arc::new(
Package::read_from_bytes_trusted(CoreLibrary::SERIALIZED)
.expect("failed to read core package!"),
);
CoreLibrary { package }
});
CORELIB.clone()
}
}
pub fn conjectured_security_estimator_root() -> Word {
CoreLibrary::default().conjectured_security_estimator_root()
}
#[cfg(test)]
mod tests {
use miden_verifier::Verifier;
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");
assert_eq!(
&core_lib.package.version, &crate_version,
"embedded package {} should track the miden-core-lib crate version",
core_lib.package.name,
);
}
#[test]
fn exported_procedures_have_type_signatures() {
use miden_mast_package::PackageExport;
let core_lib = CoreLibrary::default();
let missing: Vec<_> = core_lib
.package()
.manifest
.exports()
.filter_map(|export| match export {
PackageExport::Procedure(procedure) if procedure.signature.is_none() => {
Some(procedure.path.clone())
},
_ => None,
})
.collect();
assert!(missing.is_empty(), "procedures without binding signatures: {missing:?}");
}
#[test]
fn test_compile() {
let core_lib = CoreLibrary::default();
let exists = core_lib
.package
.get_procedure_root_by_path("::miden::core::math::u64::overflowing_add")
.is_some();
assert!(exists);
}
#[test]
fn proof_compatibility_roots_match_the_embedded_core_library() {
let core_lib = CoreLibrary::default();
let compatibility = Verifier::proof_compatibility();
assert_eq!(
compatibility.vm_verifier_roots().last(),
Some(&core_lib.vm_recursive_verifier_root()),
);
assert_eq!(
compatibility.pvm_verifier_roots().last(),
Some(&core_lib.pvm_recursive_verifier_root()),
);
}
}