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}