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 where
74 Self: Sized,
75 {
76 #[cfg(feature = "std")]
77 debug::print_debug_info(self, _process, _options);
78 Ok(())
79 }
80
81 fn on_trace(&mut self, _process: ProcessState, _trace_id: u32) -> Result<(), ExecutionError> {
83 #[cfg(feature = "std")]
84 std::println!(
85 "Trace with id {} emitted at step {} in context {}",
86 _trace_id,
87 _process.clk(),
88 _process.ctx()
89 );
90 Ok(())
91 }
92
93 fn on_assert_failed(&mut self, _process: ProcessState, _err_code: Felt) {}
95}
96
97impl<H> Host for &mut H
98where
99 H: Host,
100{
101 type AdviceProvider = H::AdviceProvider;
102
103 fn advice_provider(&self) -> &Self::AdviceProvider {
104 H::advice_provider(self)
105 }
106
107 fn advice_provider_mut(&mut self) -> &mut Self::AdviceProvider {
108 H::advice_provider_mut(self)
109 }
110
111 fn get_mast_forest(&self, node_digest: &RpoDigest) -> Option<Arc<MastForest>> {
112 H::get_mast_forest(self, node_digest)
113 }
114
115 fn on_debug(
116 &mut self,
117 process: ProcessState,
118 options: &DebugOptions,
119 ) -> Result<(), ExecutionError> {
120 H::on_debug(self, process, options)
121 }
122
123 fn on_event(
124 &mut self,
125 process: ProcessState,
126 event_id: u32,
127 err_ctx: &ErrorContext<'_, impl MastNodeExt>,
128 ) -> Result<(), ExecutionError> {
129 H::on_event(self, process, event_id, err_ctx)
130 }
131
132 fn on_trace(&mut self, process: ProcessState, trace_id: u32) -> Result<(), ExecutionError> {
133 H::on_trace(self, process, trace_id)
134 }
135
136 fn on_assert_failed(&mut self, process: ProcessState, err_code: Felt) {
137 H::on_assert_failed(self, process, err_code)
138 }
139}
140
141pub struct DefaultHost<A> {
146 adv_provider: A,
147 store: MemMastForestStore,
148}
149
150impl<A: Clone> Clone for DefaultHost<A> {
151 fn clone(&self) -> Self {
152 Self {
153 adv_provider: self.adv_provider.clone(),
154 store: self.store.clone(),
155 }
156 }
157}
158
159impl Default for DefaultHost<MemAdviceProvider> {
160 fn default() -> Self {
161 Self {
162 adv_provider: MemAdviceProvider::default(),
163 store: MemMastForestStore::default(),
164 }
165 }
166}
167
168impl<A: AdviceProvider> DefaultHost<A> {
169 pub fn new(adv_provider: A) -> Self {
170 Self {
171 adv_provider,
172 store: MemMastForestStore::default(),
173 }
174 }
175
176 pub fn load_mast_forest(&mut self, mast_forest: Arc<MastForest>) -> Result<(), ExecutionError> {
177 for (digest, values) in mast_forest.advice_map().iter() {
180 if let Some(stored_values) = self.advice_provider().get_mapped_values(digest) {
181 if stored_values != values {
182 return Err(ExecutionError::AdviceMapKeyAlreadyPresent {
183 key: digest.into(),
184 prev_values: stored_values.to_vec(),
185 new_values: values.clone(),
186 });
187 }
188 } else {
189 self.advice_provider_mut().insert_into_map(digest.into(), values.clone());
190 }
191 }
192
193 self.store.insert(mast_forest);
194 Ok(())
195 }
196
197 #[cfg(any(test, feature = "testing"))]
198 pub fn advice_provider(&self) -> &A {
199 &self.adv_provider
200 }
201
202 #[cfg(any(test, feature = "testing"))]
203 pub fn advice_provider_mut(&mut self) -> &mut A {
204 &mut self.adv_provider
205 }
206
207 pub fn into_inner(self) -> A {
208 self.adv_provider
209 }
210}
211
212impl<A: AdviceProvider> Host for DefaultHost<A> {
213 type AdviceProvider = A;
214
215 fn advice_provider(&self) -> &Self::AdviceProvider {
216 &self.adv_provider
217 }
218
219 fn advice_provider_mut(&mut self) -> &mut Self::AdviceProvider {
220 &mut self.adv_provider
221 }
222
223 fn get_mast_forest(&self, node_digest: &RpoDigest) -> Option<Arc<MastForest>> {
224 self.store.get(node_digest)
225 }
226
227 fn on_event(
228 &mut self,
229 _process: ProcessState,
230 _event_id: u32,
231 _err_ctx: &ErrorContext<'_, impl MastNodeExt>,
232 ) -> Result<(), ExecutionError> {
233 #[cfg(feature = "std")]
234 std::println!(
235 "Event with id {} emitted at step {} in context {}",
236 _event_id,
237 _process.clk(),
238 _process.ctx()
239 );
240 Ok(())
241 }
242}