1#![no_std]
2#![cfg_attr(test, allow(clippy::needless_range_loop))]
5
6#[macro_use]
7extern crate alloc;
8
9#[cfg(feature = "std")]
10extern crate std;
11
12use alloc::vec::Vec;
13use core::{
14 fmt::{self, Display, LowerHex},
15 ops::ControlFlow,
16};
17
18mod continuation_stack;
19mod debug;
20mod errors;
21mod execution;
22mod execution_options;
23mod fast;
24mod host;
25mod processor;
26mod tracer;
27
28use crate::{
29 advice::{AdviceInputs, AdviceProvider},
30 continuation_stack::ContinuationStack,
31 errors::MapExecErr,
32 processor::{Processor, SystemInterface},
33 trace::RowIndex,
34};
35
36#[cfg(any(test, feature = "testing"))]
37mod test_utils;
38#[cfg(any(test, feature = "testing"))]
39pub use test_utils::{ProcessorStateSnapshot, TestHost, TraceCollector};
40
41#[cfg(test)]
42mod tests;
43
44pub use continuation_stack::Continuation;
48pub use errors::{AceError, ExecutionError, HostError, MemoryError};
49pub use execution_options::{ExecutionOptions, ExecutionOptionsError};
50pub use fast::{BreakReason, ExecutionOutput, FastProcessor, ResumeContext};
51pub use host::{
52 BaseHost, FutureMaybeSend, Host, MastForestStore, MemMastForestStore, SyncHost,
53 debug::DefaultDebugHandler,
54 default::{DefaultHost, HostLibrary},
55 handlers::{DebugError, DebugHandler, TraceError},
56};
57pub use miden_core::{
58 EMPTY_WORD, Felt, ONE, WORD_SIZE, Word, ZERO, crypto, field, mast, precompile,
59 program::{
60 InputError, Kernel, MIN_STACK_DEPTH, Program, ProgramInfo, StackInputs, StackOutputs,
61 },
62 serde, utils,
63};
64pub use trace::{TraceBuildInputs, TraceGenerationContext};
65
66pub mod advice {
67 pub use miden_core::advice::{AdviceInputs, AdviceMap, AdviceStackBuilder};
68
69 pub use super::host::{
70 AdviceMutation,
71 advice::{AdviceError, AdviceProvider},
72 };
73}
74
75pub mod event {
76 pub use miden_core::events::*;
77
78 pub use crate::host::handlers::{
79 EventError, EventHandler, EventHandlerRegistry, NoopEventHandler,
80 };
81}
82
83pub mod operation {
84 pub use miden_core::operations::*;
85
86 pub use crate::errors::OperationError;
87}
88
89pub mod trace;
90
91#[tracing::instrument("execute_program", skip_all)]
103pub async fn execute(
104 program: &Program,
105 stack_inputs: StackInputs,
106 advice_inputs: AdviceInputs,
107 host: &mut impl Host,
108 options: ExecutionOptions,
109) -> Result<ExecutionOutput, ExecutionError> {
110 let processor = FastProcessor::new_with_options(stack_inputs, advice_inputs, options);
111 processor.execute(program, host).await
112}
113
114#[tracing::instrument("execute_program_sync", skip_all)]
116pub fn execute_sync(
117 program: &Program,
118 stack_inputs: StackInputs,
119 advice_inputs: AdviceInputs,
120 host: &mut impl SyncHost,
121 options: ExecutionOptions,
122) -> Result<ExecutionOutput, ExecutionError> {
123 let processor = FastProcessor::new_with_options(stack_inputs, advice_inputs, options);
124 processor.execute_sync(program, host)
125}
126
127#[derive(Debug)]
135pub struct ProcessorState<'a> {
136 processor: &'a FastProcessor,
137}
138
139impl<'a> ProcessorState<'a> {
140 #[inline(always)]
142 pub fn advice_provider(&self) -> &AdviceProvider {
143 self.processor.advice_provider()
144 }
145
146 #[inline(always)]
148 pub fn execution_options(&self) -> &ExecutionOptions {
149 self.processor.execution_options()
150 }
151
152 #[inline(always)]
154 pub fn clock(&self) -> RowIndex {
155 self.processor.clock()
156 }
157
158 #[inline(always)]
160 pub fn ctx(&self) -> ContextId {
161 self.processor.ctx()
162 }
163
164 #[inline(always)]
168 pub fn get_stack_item(&self, pos: usize) -> Felt {
169 self.processor.stack_get_safe(pos)
170 }
171
172 #[inline(always)]
184 pub fn get_stack_word(&self, start_idx: usize) -> Word {
185 self.processor.stack_get_word_safe(start_idx)
186 }
187
188 #[inline(always)]
191 pub fn get_stack_state(&self) -> Vec<Felt> {
192 self.processor.stack().iter().rev().copied().collect()
193 }
194
195 #[inline(always)]
198 pub fn get_mem_value(&self, ctx: ContextId, addr: u32) -> Option<Felt> {
199 self.processor.memory().read_element_impl(ctx, addr)
200 }
201
202 #[inline(always)]
207 pub fn get_mem_word(&self, ctx: ContextId, addr: u32) -> Result<Option<Word>, MemoryError> {
208 self.processor.memory().read_word_impl(ctx, addr)
209 }
210
211 pub fn get_mem_addr_range(
214 &self,
215 start_idx: usize,
216 end_idx: usize,
217 ) -> Result<core::ops::Range<u32>, MemoryError> {
218 let start_addr = self.get_stack_item(start_idx).as_canonical_u64();
219 let end_addr = self.get_stack_item(end_idx).as_canonical_u64();
220
221 if start_addr > u32::MAX as u64 {
222 return Err(MemoryError::AddressOutOfBounds { addr: start_addr });
223 }
224 if end_addr > u32::MAX as u64 {
225 return Err(MemoryError::AddressOutOfBounds { addr: end_addr });
226 }
227
228 if start_addr > end_addr {
229 return Err(MemoryError::InvalidMemoryRange { start_addr, end_addr });
230 }
231
232 Ok(start_addr as u32..end_addr as u32)
233 }
234
235 #[inline(always)]
241 pub fn get_mem_state(&self, ctx: ContextId) -> Vec<(MemoryAddress, Felt)> {
242 self.processor.memory().get_memory_state(ctx)
243 }
244}
245
246pub trait Stopper {
256 type Processor;
257
258 fn should_stop(
273 &self,
274 processor: &Self::Processor,
275 continuation_stack: &ContinuationStack,
276 continuation_after_stop: impl FnOnce() -> Option<continuation_stack::Continuation>,
277 ) -> ControlFlow<BreakReason>;
278}
279
280#[derive(Clone, Copy, Debug, Default, Eq, Ord, PartialEq, PartialOrd)]
285pub struct ContextId(u32);
286
287impl ContextId {
288 pub fn root() -> Self {
290 Self(0)
291 }
292
293 pub fn is_root(&self) -> bool {
295 self.0 == 0
296 }
297}
298
299impl From<RowIndex> for ContextId {
300 fn from(value: RowIndex) -> Self {
301 Self(value.as_u32())
302 }
303}
304
305impl From<u32> for ContextId {
306 fn from(value: u32) -> Self {
307 Self(value)
308 }
309}
310
311impl From<ContextId> for u32 {
312 fn from(context_id: ContextId) -> Self {
313 context_id.0
314 }
315}
316
317impl From<ContextId> for u64 {
318 fn from(context_id: ContextId) -> Self {
319 context_id.0.into()
320 }
321}
322
323impl From<ContextId> for Felt {
324 fn from(context_id: ContextId) -> Self {
325 Felt::from_u32(context_id.0)
326 }
327}
328
329impl Display for ContextId {
330 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
331 write!(f, "{}", self.0)
332 }
333}
334
335#[derive(Copy, Clone, Debug, Eq, PartialEq, Hash)]
339pub struct MemoryAddress(u32);
340
341impl From<u32> for MemoryAddress {
342 fn from(addr: u32) -> Self {
343 MemoryAddress(addr)
344 }
345}
346
347impl From<MemoryAddress> for u32 {
348 fn from(value: MemoryAddress) -> Self {
349 value.0
350 }
351}
352
353impl Display for MemoryAddress {
354 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
355 Display::fmt(&self.0, f)
356 }
357}
358
359impl LowerHex for MemoryAddress {
360 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
361 LowerHex::fmt(&self.0, f)
362 }
363}
364
365impl core::ops::Add<MemoryAddress> for MemoryAddress {
366 type Output = Self;
367
368 fn add(self, rhs: MemoryAddress) -> Self::Output {
369 MemoryAddress(self.0 + rhs.0)
370 }
371}
372
373impl core::ops::Add<u32> for MemoryAddress {
374 type Output = Self;
375
376 fn add(self, rhs: u32) -> Self::Output {
377 MemoryAddress(self.0 + rhs)
378 }
379}