miden_processor/fast/
sys_ops.rs

1use miden_core::{Felt, mast::MastForest, sys_events::SystemEvent};
2
3use super::{ExecutionError, FastProcessor, ONE};
4use crate::{
5    AsyncHost, BaseHost, ErrorContext, FMP_MIN,
6    operations::sys_ops::sys_event_handlers::handle_system_event, system::FMP_MAX,
7};
8
9impl FastProcessor {
10    /// Analogous to `Process::op_assert`.
11    #[inline(always)]
12    pub fn op_assert(
13        &mut self,
14        err_code: Felt,
15        host: &mut impl BaseHost,
16        program: &MastForest,
17        err_ctx: &impl ErrorContext,
18    ) -> Result<(), ExecutionError> {
19        if self.stack_get(0) != ONE {
20            let process = &mut self.state();
21            host.on_assert_failed(process, err_code);
22            let err_msg = program.resolve_error_message(err_code);
23            return Err(ExecutionError::failed_assertion(
24                process.clk(),
25                err_code,
26                err_msg,
27                err_ctx,
28            ));
29        }
30        self.decrement_stack_size();
31        Ok(())
32    }
33
34    /// Analogous to `Process::op_fmpadd`.
35    pub fn op_fmpadd(&mut self) {
36        let fmp = self.fmp;
37        let top = self.stack_get_mut(0);
38
39        *top += fmp;
40    }
41
42    /// Analogous to `Process::op_fmpupdate`.
43    pub fn op_fmpupdate(&mut self) -> Result<(), ExecutionError> {
44        let top = self.stack_get(0);
45
46        let new_fmp = self.fmp + top;
47        let new_fmp_int = new_fmp.as_int();
48        if !(FMP_MIN..=FMP_MAX).contains(&new_fmp_int) {
49            return Err(ExecutionError::InvalidFmpValue(self.fmp, new_fmp));
50        }
51
52        self.fmp = new_fmp;
53        self.decrement_stack_size();
54        Ok(())
55    }
56
57    /// Analogous to `Process::op_sdepth`.
58    pub fn op_sdepth(&mut self) {
59        let depth = self.stack_depth();
60        self.increment_stack_size();
61        self.stack_write(0, depth.into());
62    }
63
64    /// Analogous to `Process::op_caller`.
65    pub fn op_caller(&mut self) -> Result<(), ExecutionError> {
66        if !self.in_syscall {
67            return Err(ExecutionError::CallerNotInSyscall);
68        }
69
70        let caller_hash = self.caller_hash;
71        self.stack_write_word(0, &caller_hash);
72
73        Ok(())
74    }
75
76    /// Analogous to `Process::op_clk`.
77    pub fn op_clk(&mut self) -> Result<(), ExecutionError> {
78        self.increment_stack_size();
79        self.stack_write(0, self.clk.into());
80        Ok(())
81    }
82
83    /// Analogous to `Process::op_emit`.
84    #[inline(always)]
85    pub async fn op_emit(
86        &mut self,
87        event_id: u32,
88        host: &mut impl AsyncHost,
89        err_ctx: &impl ErrorContext,
90    ) -> Result<(), ExecutionError> {
91        let mut process = self.state();
92        // If it's a system event, handle it directly. Otherwise, forward it to the host.
93        if let Some(system_event) = SystemEvent::from_event_id(event_id) {
94            handle_system_event(&mut process, system_event, err_ctx)
95        } else {
96            let clk = process.clk();
97            let mutations = host
98                .on_event(&process, event_id)
99                .await
100                .map_err(|err| ExecutionError::event_error(err, event_id, err_ctx))?;
101            self.advice
102                .apply_mutations(mutations)
103                .map_err(|err| ExecutionError::advice_error(err, clk, err_ctx))?;
104            Ok(())
105        }
106    }
107}