miden_processor/host/mod.rs
1use alloc::{sync::Arc, vec::Vec};
2use core::future::Future;
3
4use miden_core::{
5 AdviceMap, DebugOptions, Felt, Word, crypto::merkle::InnerNodeInfo, mast::MastForest,
6};
7use miden_debug_types::{Location, SourceFile, SourceSpan};
8
9use crate::{EventError, ExecutionError, ProcessState};
10
11pub(super) mod advice;
12
13#[cfg(feature = "std")]
14mod debug;
15
16pub mod default;
17use default::DefaultDebugHandler;
18
19pub mod handlers;
20use handlers::DebugHandler;
21
22mod mast_forest_store;
23pub use mast_forest_store::{MastForestStore, MemMastForestStore};
24
25// ADVICE MAP MUTATIONS
26// ================================================================================================
27
28/// Any possible way an event can modify the advice map
29#[derive(Debug, PartialEq, Eq)]
30pub enum AdviceMutation {
31 ExtendStack { values: Vec<Felt> },
32 ExtendMap { other: AdviceMap },
33 ExtendMerkleStore { infos: Vec<InnerNodeInfo> },
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// HOST TRAIT
50// ================================================================================================
51
52/// Defines the common interface between [SyncHost] and [AsyncHost], by which the VM can interact
53/// with the host.
54///
55/// There are three main categories of interactions between the VM and the host:
56/// 1. getting a library's MAST forest,
57/// 2. handling VM events (which can mutate the process' advice provider), and
58/// 3. handling debug and trace events.
59pub trait BaseHost {
60 // REQUIRED METHODS
61 // --------------------------------------------------------------------------------------------
62
63 /// Returns MAST forest corresponding to the specified digest, or None if the MAST forest for
64 /// this digest could not be found in this host.
65 fn get_mast_forest(&self, node_digest: &Word) -> Option<Arc<MastForest>>;
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<(), ExecutionError> {
79 DefaultDebugHandler.on_debug(process, options)
80 }
81
82 /// Handles the trace emitted from the VM.
83 fn on_trace(
84 &mut self,
85 process: &mut ProcessState,
86 trace_id: u32,
87 ) -> Result<(), ExecutionError> {
88 DefaultDebugHandler.on_trace(process, trace_id)
89 }
90
91 /// Handles the failure of the assertion instruction.
92 fn on_assert_failed(&mut self, _process: &ProcessState, _err_code: Felt) {}
93}
94
95/// Defines an interface by which the VM can interact with the host.
96///
97/// There are four main categories of interactions between the VM and the host:
98/// 1. accessing the advice provider,
99/// 2. getting a library's MAST forest,
100/// 3. handling VM events (which can mutate the process' advice provider), and
101/// 4. handling debug and trace events.
102pub trait SyncHost: BaseHost {
103 // REQUIRED METHODS
104 // --------------------------------------------------------------------------------------------
105
106 /// Handles the event emitted from the VM.
107 fn on_event(
108 &mut self,
109 process: &ProcessState,
110 event_id: u32,
111 ) -> Result<Vec<AdviceMutation>, EventError>;
112}
113
114// ASYNC HOST trait
115// ================================================================================================
116
117/// Analogous to the [SyncHost] trait, but designed for asynchronous execution contexts.
118pub trait AsyncHost: BaseHost {
119 // REQUIRED METHODS
120 // --------------------------------------------------------------------------------------------
121
122 // Note: we don't use the `async` keyword in this method, since we need to specify the `+ Send`
123 // bound to the returned Future, and `async` doesn't allow us to do that.
124
125 /// Handles the event emitted from the VM and provides advice mutations to be applied to
126 /// the advice provider.
127 fn on_event(
128 &mut self,
129 process: &ProcessState<'_>,
130 event_id: u32,
131 ) -> impl FutureMaybeSend<Result<Vec<AdviceMutation>, EventError>>;
132}
133
134/// Alias for a `Future`
135///
136/// Unless the compilation target family is `wasm`, we add `Send` to the required bounds. For
137/// `wasm` compilation targets there is no `Send` bound.
138///
139/// We also provide a blank implementation of this trait for all features.
140#[cfg(target_family = "wasm")]
141pub trait FutureMaybeSend<O>: Future<Output = O> {}
142
143#[cfg(target_family = "wasm")]
144impl<T, O> FutureMaybeSend<O> for T where T: Future<Output = O> {}
145
146/// Alias for a `Future`
147///
148/// Unless the compilation target family is `wasm`, we add `Send` to the required bounds. For
149/// `wasm` compilation targets there is no `Send` bound.
150///
151/// We also provide a blank implementation of this trait for all features.
152#[cfg(not(target_family = "wasm"))]
153pub trait FutureMaybeSend<O>: Future<Output = O> + Send {}
154
155#[cfg(not(target_family = "wasm"))]
156impl<T, O> FutureMaybeSend<O> for T where T: Future<Output = O> + Send {}