Skip to main content

miden_processor/host/
mod.rs

1use alloc::{sync::Arc, vec::Vec};
2use core::future::Future;
3
4use miden_core::{
5    Felt, Word,
6    advice::AdviceMap,
7    crypto::merkle::InnerNodeInfo,
8    events::{EventId, EventName},
9    mast::MastForest,
10    operations::DebugOptions,
11    precompile::PrecompileRequest,
12};
13use miden_debug_types::{Location, SourceFile, SourceSpan};
14
15use crate::{DebugError, ProcessorState, TraceError};
16
17pub(super) mod advice;
18
19pub mod debug;
20
21pub mod default;
22
23pub mod handlers;
24use handlers::{DebugHandler, EventError};
25
26mod mast_forest_store;
27pub use mast_forest_store::{MastForestStore, MemMastForestStore};
28
29// ADVICE MAP MUTATIONS
30// ================================================================================================
31
32/// Any possible way an event can modify the advice provider.
33#[derive(Debug, PartialEq, Eq)]
34pub enum AdviceMutation {
35    ExtendStack { values: Vec<Felt> },
36    ExtendMap { other: AdviceMap },
37    ExtendMerkleStore { infos: Vec<InnerNodeInfo> },
38    ExtendPrecompileRequests { data: Vec<PrecompileRequest> },
39}
40
41impl AdviceMutation {
42    pub fn extend_stack(iter: impl IntoIterator<Item = Felt>) -> Self {
43        Self::ExtendStack { values: Vec::from_iter(iter) }
44    }
45
46    pub fn extend_map(other: AdviceMap) -> Self {
47        Self::ExtendMap { other }
48    }
49
50    pub fn extend_merkle_store(infos: impl IntoIterator<Item = InnerNodeInfo>) -> Self {
51        Self::ExtendMerkleStore { infos: Vec::from_iter(infos) }
52    }
53
54    pub fn extend_precompile_requests(data: impl IntoIterator<Item = PrecompileRequest>) -> Self {
55        Self::ExtendPrecompileRequests { data: Vec::from_iter(data) }
56    }
57}
58// HOST TRAIT
59// ================================================================================================
60
61/// Defines an interface by which the VM can interact with the host.
62///
63/// There are three main categories of interactions between the VM and the host:
64/// 1. getting a library's MAST forest,
65/// 2. handling VM events (which can mutate the process' advice provider), and
66/// 3. handling debug and trace events.
67pub trait Host {
68    // REQUIRED METHODS
69    // --------------------------------------------------------------------------------------------
70
71    /// Returns the [`SourceSpan`] and optional [`SourceFile`] for the provided location.
72    fn get_label_and_source_file(
73        &self,
74        location: &Location,
75    ) -> (SourceSpan, Option<Arc<SourceFile>>);
76
77    // Note: we don't use the `async` keyword in get_mast_forest and on_event, since we need to
78    // specify the `+ Send` bound to the returned Future, and `async` doesn't allow us to do that.
79
80    /// Returns MAST forest corresponding to the specified digest, or None if the MAST forest for
81    /// this digest could not be found in this host.
82    fn get_mast_forest(&self, node_digest: &Word) -> impl FutureMaybeSend<Option<Arc<MastForest>>>;
83
84    /// Handles the event emitted from the VM and provides advice mutations to be applied to
85    /// the advice provider.
86    ///
87    /// The event ID is available at the top of the stack (position 0) when this handler is called.
88    /// This allows the handler to access both the event ID and any additional context data that
89    /// may have been pushed onto the stack prior to the emit operation.
90    ///
91    /// ## Implementation notes
92    /// - Extract the event ID via `EventId::from_felt(process.get_stack_item(0))`
93    /// - Return errors without event names or IDs - the caller will enrich them via
94    ///   [`Host::resolve_event()`]
95    /// - System events (IDs 0-255) are handled by the VM before calling this method
96    fn on_event(
97        &mut self,
98        process: &ProcessorState<'_>,
99    ) -> impl FutureMaybeSend<Result<Vec<AdviceMutation>, EventError>>;
100
101    // PROVIDED METHODS
102    // --------------------------------------------------------------------------------------------
103
104    /// Handles the debug request from the VM.
105    fn on_debug(
106        &mut self,
107        process: &ProcessorState,
108        options: &DebugOptions,
109    ) -> Result<(), DebugError> {
110        let mut handler = debug::DefaultDebugHandler::default();
111        handler.on_debug(process, options)
112    }
113
114    /// Handles the trace emitted from the VM.
115    fn on_trace(&mut self, process: &ProcessorState, trace_id: u32) -> Result<(), TraceError> {
116        let mut handler = debug::DefaultDebugHandler::default();
117        handler.on_trace(process, trace_id)
118    }
119
120    /// Returns the [`EventName`] registered for the provided [`EventId`], if any.
121    ///
122    /// Hosts that maintain an event registry can override this method to surface human-readable
123    /// names for diagnostics. The default implementation returns `None`.
124    fn resolve_event(&self, _event_id: EventId) -> Option<&EventName> {
125        None
126    }
127}
128
129/// Alias for a `Future`
130///
131/// Unless the compilation target family is `wasm`, we add `Send` to the required bounds. For
132/// `wasm` compilation targets there is no `Send` bound.
133///
134/// We also provide a blank implementation of this trait for all features.
135#[cfg(target_family = "wasm")]
136pub trait FutureMaybeSend<O>: Future<Output = O> {}
137
138#[cfg(target_family = "wasm")]
139impl<T, O> FutureMaybeSend<O> for T where T: Future<Output = O> {}
140
141/// Alias for a `Future`
142///
143/// Unless the compilation target family is `wasm`, we add `Send` to the required bounds. For
144/// `wasm` compilation targets there is no `Send` bound.
145///
146/// We also provide a blank implementation of this trait for all features.
147#[cfg(not(target_family = "wasm"))]
148pub trait FutureMaybeSend<O>: Future<Output = O> + Send {}
149
150#[cfg(not(target_family = "wasm"))]
151impl<T, O> FutureMaybeSend<O> for T where T: Future<Output = O> + Send {}