miden_processor/host/
mod.rs

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