miden_processor/host/mod.rs
1use alloc::sync::Arc;
2use core::future::Future;
3
4use miden_core::{DebugOptions, Felt, Word, mast::MastForest};
5
6use crate::{ExecutionError, ProcessState, errors::ErrorContext};
7
8pub(super) mod advice;
9
10#[cfg(feature = "std")]
11mod debug;
12
13mod mast_forest_store;
14pub use mast_forest_store::{MastForestStore, MemMastForestStore};
15
16// HOST TRAIT
17// ================================================================================================
18
19/// Defines the common interface between [SyncHost] and [AsyncHost], by which the VM can interact
20/// with the host.
21///
22/// There are three main categories of interactions between the VM and the host:
23/// 1. getting a library's MAST forest,
24/// 2. handling advice events (which internally mutates the advice provider), and
25/// 3. handling debug and trace events.
26pub trait BaseHost {
27 // REQUIRED METHODS
28 // --------------------------------------------------------------------------------------------
29
30 /// Handles the debug request from the VM.
31 fn on_debug(
32 &mut self,
33 process: &mut ProcessState,
34 options: &DebugOptions,
35 ) -> Result<(), ExecutionError> {
36 let _ = (&process, options);
37 #[cfg(feature = "std")]
38 debug::print_debug_info(process, options);
39 Ok(())
40 }
41
42 /// Handles the trace emitted from the VM.
43 fn on_trace(
44 &mut self,
45 process: &mut ProcessState,
46 trace_id: u32,
47 ) -> Result<(), ExecutionError> {
48 let _ = (&process, trace_id);
49 #[cfg(feature = "std")]
50 std::println!(
51 "Trace with id {} emitted at step {} in context {}",
52 trace_id,
53 process.clk(),
54 process.ctx()
55 );
56 Ok(())
57 }
58
59 /// Handles the failure of the assertion instruction.
60 fn on_assert_failed(&mut self, _process: &mut ProcessState, _err_code: Felt) {}
61}
62
63/// Defines an interface by which the VM can interact with the host.
64///
65/// There are four main categories of interactions between the VM and the host:
66/// 1. accessing the advice provider,
67/// 2. getting a library's MAST forest,
68/// 3. handling advice events (which internally mutates the advice provider), and
69/// 4. handling debug and trace events.
70pub trait SyncHost: BaseHost {
71 // REQUIRED METHODS
72 // --------------------------------------------------------------------------------------------
73
74 /// Returns MAST forest corresponding to the specified digest, or None if the MAST forest for
75 /// this digest could not be found in this [SyncHost].
76 fn get_mast_forest(&self, node_digest: &Word) -> Option<Arc<MastForest>>;
77
78 /// Handles the event emitted from the VM.
79 fn on_event(
80 &mut self,
81 process: &mut ProcessState,
82 event_id: u32,
83 err_ctx: &impl ErrorContext,
84 ) -> Result<(), ExecutionError>;
85}
86
87// DEFAULT HOST IMPLEMENTATION
88// ================================================================================================
89
90/// A default [BaseHost], [SyncHost] and [AsyncHost] implementation that provides the essential
91/// functionality required by the VM.
92#[derive(Debug, Clone, Default)]
93pub struct DefaultHost {
94 store: MemMastForestStore,
95}
96
97impl DefaultHost {
98 pub fn load_mast_forest(&mut self, mast_forest: Arc<MastForest>) -> Result<(), ExecutionError> {
99 self.store.insert(mast_forest);
100 Ok(())
101 }
102}
103
104impl BaseHost for DefaultHost {}
105
106impl SyncHost for DefaultHost {
107 fn get_mast_forest(&self, node_digest: &Word) -> Option<Arc<MastForest>> {
108 self.store.get(node_digest)
109 }
110
111 fn on_event(
112 &mut self,
113 process: &mut ProcessState,
114 event_id: u32,
115 err_ctx: &impl ErrorContext,
116 ) -> Result<(), ExecutionError> {
117 let _ = (&process, event_id, err_ctx);
118 #[cfg(feature = "std")]
119 std::println!(
120 "Event with id {} emitted at step {} in context {}",
121 event_id,
122 process.clk(),
123 process.ctx()
124 );
125 Ok(())
126 }
127}
128
129impl AsyncHost for DefaultHost {
130 async fn get_mast_forest(&self, node_digest: &Word) -> Option<Arc<MastForest>> {
131 self.store.get(node_digest)
132 }
133
134 // Note: clippy complains about this not using the `async` keyword, but if we use `async`, it
135 // doesn't compile.
136 #[allow(clippy::manual_async_fn)]
137 fn on_event(
138 &mut self,
139 _process: &mut ProcessState<'_>,
140 _event_id: u32,
141 _err_ctx: &impl ErrorContext,
142 ) -> impl Future<Output = Result<(), ExecutionError>> + Send {
143 async { Ok(()) }
144 }
145}
146
147// ASYNC HOST trait
148// ================================================================================================
149
150/// Analogous to the [SyncHost] trait, but designed for asynchronous execution contexts.
151pub trait AsyncHost: BaseHost {
152 // REQUIRED METHODS
153 // --------------------------------------------------------------------------------------------
154
155 // Note: we don't use the `async` keyword in both of these methods, since we need to specify the
156 // `+ Send` bound to the returned Future, and `async` doesn't allow us to do that.
157
158 /// Returns MAST forest corresponding to the specified digest, or None if the MAST forest for
159 /// this digest could not be found in this [AsyncHost].
160 fn get_mast_forest(
161 &self,
162 node_digest: &Word,
163 ) -> impl Future<Output = Option<Arc<MastForest>>> + Send;
164
165 /// Handles the event emitted from the VM.
166 fn on_event(
167 &mut self,
168 process: &mut ProcessState<'_>,
169 event_id: u32,
170 err_ctx: &impl ErrorContext,
171 ) -> impl Future<Output = Result<(), ExecutionError>> + Send;
172}