miden_processor/fast/
sys_ops.rs

1use vm_core::{Felt, ZERO, mast::MastForest, sys_events::SystemEvent};
2
3use super::{ExecutionError, FastProcessor, ONE};
4use crate::{
5    FMP_MIN, Host, ProcessState,
6    errors::ErrorContext,
7    operations::sys_ops::sys_event_handlers::{
8        HDWORD_TO_MAP_WITH_DOMAIN_DOMAIN_OFFSET, copy_map_value_to_adv_stack,
9        copy_merkle_node_to_adv_stack, insert_hdword_into_adv_map, insert_hperm_into_adv_map,
10        insert_mem_values_into_adv_map, merge_merkle_nodes, push_ext2_intt_result,
11        push_ext2_inv_result, push_falcon_mod_result, push_ilog2, push_leading_ones,
12        push_leading_zeros, push_smtpeek_result, push_trailing_ones, push_trailing_zeros,
13        push_u64_div_result,
14    },
15    system::FMP_MAX,
16};
17
18impl FastProcessor {
19    /// Analogous to `Process::op_assert`.
20    pub fn op_assert(
21        &mut self,
22        err_code: Felt,
23        op_idx: usize,
24        host: &mut impl Host,
25        program: &MastForest,
26    ) -> Result<(), ExecutionError> {
27        if self.stack_get(0) != ONE {
28            host.on_assert_failed(ProcessState::new_fast(self, op_idx), err_code);
29            let err_msg = program.resolve_error_message(err_code);
30            return Err(ExecutionError::failed_assertion(
31                self.clk,
32                err_code,
33                err_msg,
34                &ErrorContext::default(),
35            ));
36        }
37        self.decrement_stack_size();
38        Ok(())
39    }
40
41    /// Analogous to `Process::op_fmpadd`.
42    pub fn op_fmpadd(&mut self) {
43        let fmp = self.fmp;
44        let top = self.stack_get_mut(0);
45
46        *top += fmp;
47    }
48
49    /// Analogous to `Process::op_fmpupdate`.
50    pub fn op_fmpupdate(&mut self) -> Result<(), ExecutionError> {
51        let top = self.stack_get(0);
52
53        let new_fmp = self.fmp + top;
54        let new_fmp_int = new_fmp.as_int();
55        if !(FMP_MIN..=FMP_MAX).contains(&new_fmp_int) {
56            return Err(ExecutionError::InvalidFmpValue(self.fmp, new_fmp));
57        }
58
59        self.fmp = new_fmp;
60        self.decrement_stack_size();
61        Ok(())
62    }
63
64    /// Analogous to `Process::op_sdepth`.
65    pub fn op_sdepth(&mut self) {
66        let depth = self.stack_depth();
67        self.increment_stack_size();
68        self.stack_write(0, depth.into());
69    }
70
71    /// Analogous to `Process::op_caller`.
72    pub fn op_caller(&mut self) -> Result<(), ExecutionError> {
73        if !self.in_syscall {
74            return Err(ExecutionError::CallerNotInSyscall);
75        }
76
77        let caller_hash = self.caller_hash;
78        self.stack_write_word(0, &caller_hash);
79
80        Ok(())
81    }
82
83    /// Analogous to `Process::op_clk`.
84    pub fn op_clk(&mut self, op_idx: usize) -> Result<(), ExecutionError> {
85        self.increment_stack_size();
86        self.stack_write(0, (self.clk + op_idx).into());
87        Ok(())
88    }
89
90    /// Analogous to `Process::op_emit`.
91    pub fn op_emit(
92        &mut self,
93        event_id: u32,
94        op_idx: usize,
95        host: &mut impl Host,
96    ) -> Result<(), ExecutionError> {
97        // If it's a system event, handle it directly. Otherwise, forward it to the host.
98        if let Some(system_event) = SystemEvent::from_event_id(event_id) {
99            self.handle_system_event(system_event, op_idx, host)
100        } else {
101            host.on_event(ProcessState::new_fast(self, op_idx), event_id, &ErrorContext::default())
102        }
103    }
104
105    // HELPERS
106    // ------------------------------------------------------------------------------------------
107
108    pub(super) fn handle_system_event(
109        &self,
110        system_event: SystemEvent,
111        op_idx: usize,
112        host: &mut impl Host,
113    ) -> Result<(), ExecutionError> {
114        let advice_provider = host.advice_provider_mut();
115        let process_state = ProcessState::new_fast(self, op_idx);
116        match system_event {
117            SystemEvent::MerkleNodeMerge => {
118                merge_merkle_nodes(advice_provider, process_state, &ErrorContext::default())
119            },
120            SystemEvent::MerkleNodeToStack => copy_merkle_node_to_adv_stack(
121                advice_provider,
122                process_state,
123                &ErrorContext::default(),
124            ),
125            SystemEvent::MapValueToStack => copy_map_value_to_adv_stack(
126                advice_provider,
127                process_state,
128                false,
129                &ErrorContext::default(),
130            ),
131            SystemEvent::MapValueToStackN => copy_map_value_to_adv_stack(
132                advice_provider,
133                process_state,
134                true,
135                &ErrorContext::default(),
136            ),
137            SystemEvent::U64Div => {
138                push_u64_div_result(advice_provider, process_state, &ErrorContext::default())
139            },
140            SystemEvent::FalconDiv => {
141                push_falcon_mod_result(advice_provider, process_state, &ErrorContext::default())
142            },
143            SystemEvent::Ext2Inv => {
144                push_ext2_inv_result(advice_provider, process_state, &ErrorContext::default())
145            },
146            SystemEvent::Ext2Intt => {
147                push_ext2_intt_result(advice_provider, process_state, &ErrorContext::default())
148            },
149            SystemEvent::SmtPeek => {
150                push_smtpeek_result(advice_provider, process_state, &ErrorContext::default())
151            },
152            SystemEvent::U32Clz => {
153                push_leading_zeros(advice_provider, process_state, &ErrorContext::default())
154            },
155            SystemEvent::U32Ctz => {
156                push_trailing_zeros(advice_provider, process_state, &ErrorContext::default())
157            },
158            SystemEvent::U32Clo => {
159                push_leading_ones(advice_provider, process_state, &ErrorContext::default())
160            },
161            SystemEvent::U32Cto => {
162                push_trailing_ones(advice_provider, process_state, &ErrorContext::default())
163            },
164            SystemEvent::ILog2 => {
165                push_ilog2(advice_provider, process_state, &ErrorContext::default())
166            },
167
168            SystemEvent::MemToMap => insert_mem_values_into_adv_map(advice_provider, process_state),
169            SystemEvent::HdwordToMap => {
170                insert_hdword_into_adv_map(advice_provider, process_state, ZERO)
171            },
172            SystemEvent::HdwordToMapWithDomain => {
173                let domain = self.stack_get(HDWORD_TO_MAP_WITH_DOMAIN_DOMAIN_OFFSET);
174                insert_hdword_into_adv_map(advice_provider, process_state, domain)
175            },
176            SystemEvent::HpermToMap => insert_hperm_into_adv_map(advice_provider, process_state),
177        }
178    }
179}