1use alloc::sync::Arc;
2
3use vm_core::{
4 DebugOptions,
5 crypto::hash::RpoDigest,
6 mast::{MastForest, MastNodeExt},
7};
8
9use super::{ExecutionError, ProcessState};
10use crate::{Felt, KvMap, MemAdviceProvider, errors::ErrorContext};
11
12pub(super) mod advice;
13use advice::AdviceProvider;
14
15#[cfg(feature = "std")]
16mod debug;
17
18mod mast_forest_store;
19pub use mast_forest_store::{MastForestStore, MemMastForestStore};
20
21pub trait Host {
32 type AdviceProvider: AdviceProvider;
33
34 fn advice_provider(&self) -> &Self::AdviceProvider;
39
40 fn advice_provider_mut(&mut self) -> &mut Self::AdviceProvider;
42
43 fn get_mast_forest(&self, node_digest: &RpoDigest) -> Option<Arc<MastForest>>;
46
47 fn on_event(
52 &mut self,
53 _process: ProcessState,
54 _event_id: u32,
55 _err_ctx: &ErrorContext<'_, impl MastNodeExt>,
56 ) -> Result<(), ExecutionError> {
57 #[cfg(feature = "std")]
58 std::println!(
59 "Event with id {} emitted at step {} in context {}",
60 _event_id,
61 _process.clk(),
62 _process.ctx()
63 );
64 Ok(())
65 }
66
67 fn on_debug(
69 &mut self,
70 _process: ProcessState,
71 _options: &DebugOptions,
72 ) -> Result<(), ExecutionError> {
73 #[cfg(feature = "std")]
74 debug::print_debug_info(_process, _options);
75 Ok(())
76 }
77
78 fn on_trace(&mut self, _process: ProcessState, _trace_id: u32) -> Result<(), ExecutionError> {
80 #[cfg(feature = "std")]
81 std::println!(
82 "Trace with id {} emitted at step {} in context {}",
83 _trace_id,
84 _process.clk(),
85 _process.ctx()
86 );
87 Ok(())
88 }
89
90 fn on_assert_failed(&mut self, _process: ProcessState, _err_code: Felt) {}
92}
93
94impl<H> Host for &mut H
95where
96 H: Host,
97{
98 type AdviceProvider = H::AdviceProvider;
99
100 fn advice_provider(&self) -> &Self::AdviceProvider {
101 H::advice_provider(self)
102 }
103
104 fn advice_provider_mut(&mut self) -> &mut Self::AdviceProvider {
105 H::advice_provider_mut(self)
106 }
107
108 fn get_mast_forest(&self, node_digest: &RpoDigest) -> Option<Arc<MastForest>> {
109 H::get_mast_forest(self, node_digest)
110 }
111
112 fn on_debug(
113 &mut self,
114 process: ProcessState,
115 options: &DebugOptions,
116 ) -> Result<(), ExecutionError> {
117 H::on_debug(self, process, options)
118 }
119
120 fn on_event(
121 &mut self,
122 process: ProcessState,
123 event_id: u32,
124 err_ctx: &ErrorContext<'_, impl MastNodeExt>,
125 ) -> Result<(), ExecutionError> {
126 H::on_event(self, process, event_id, err_ctx)
127 }
128
129 fn on_trace(&mut self, process: ProcessState, trace_id: u32) -> Result<(), ExecutionError> {
130 H::on_trace(self, process, trace_id)
131 }
132
133 fn on_assert_failed(&mut self, process: ProcessState, err_code: Felt) {
134 H::on_assert_failed(self, process, err_code)
135 }
136}
137
138pub struct DefaultHost<A> {
143 adv_provider: A,
144 store: MemMastForestStore,
145}
146
147impl<A: Clone> Clone for DefaultHost<A> {
148 fn clone(&self) -> Self {
149 Self {
150 adv_provider: self.adv_provider.clone(),
151 store: self.store.clone(),
152 }
153 }
154}
155
156impl Default for DefaultHost<MemAdviceProvider> {
157 fn default() -> Self {
158 Self {
159 adv_provider: MemAdviceProvider::default(),
160 store: MemMastForestStore::default(),
161 }
162 }
163}
164
165impl<A: AdviceProvider> DefaultHost<A> {
166 pub fn new(adv_provider: A) -> Self {
167 Self {
168 adv_provider,
169 store: MemMastForestStore::default(),
170 }
171 }
172
173 pub fn load_mast_forest(&mut self, mast_forest: Arc<MastForest>) -> Result<(), ExecutionError> {
174 for (digest, values) in mast_forest.advice_map().iter() {
177 if let Some(stored_values) = self.advice_provider().get_mapped_values(digest) {
178 if stored_values != values {
179 return Err(ExecutionError::AdviceMapKeyAlreadyPresent {
180 key: digest.into(),
181 prev_values: stored_values.to_vec(),
182 new_values: values.clone(),
183 });
184 }
185 } else {
186 self.advice_provider_mut().insert_into_map(digest.into(), values.clone());
187 }
188 }
189
190 self.store.insert(mast_forest);
191 Ok(())
192 }
193
194 #[cfg(any(test, feature = "testing"))]
195 pub fn advice_provider(&self) -> &A {
196 &self.adv_provider
197 }
198
199 #[cfg(any(test, feature = "testing"))]
200 pub fn advice_provider_mut(&mut self) -> &mut A {
201 &mut self.adv_provider
202 }
203
204 pub fn into_inner(self) -> A {
205 self.adv_provider
206 }
207}
208
209impl<A: AdviceProvider> Host for DefaultHost<A> {
210 type AdviceProvider = A;
211
212 fn advice_provider(&self) -> &Self::AdviceProvider {
213 &self.adv_provider
214 }
215
216 fn advice_provider_mut(&mut self) -> &mut Self::AdviceProvider {
217 &mut self.adv_provider
218 }
219
220 fn get_mast_forest(&self, node_digest: &RpoDigest) -> Option<Arc<MastForest>> {
221 self.store.get(node_digest)
222 }
223
224 fn on_event(
225 &mut self,
226 _process: ProcessState,
227 _event_id: u32,
228 _err_ctx: &ErrorContext<'_, impl MastNodeExt>,
229 ) -> Result<(), ExecutionError> {
230 #[cfg(feature = "std")]
231 std::println!(
232 "Event with id {} emitted at step {} in context {}",
233 _event_id,
234 _process.clk(),
235 _process.ctx()
236 );
237 Ok(())
238 }
239}