1use std::any::Any;
2use std::rc::Rc;
3
4use cairo_lang_runner::CairoHintProcessor;
5use cairo_vm::hint_processor::builtin_hint_processor::builtin_hint_processor_definition::{
6 BuiltinHintProcessor, HintFunc, HintProcessorData,
7};
8use cairo_vm::hint_processor::hint_processor_definition::{
9 HintExtension, HintProcessor, HintProcessorLogic,
10};
11use cairo_vm::types::exec_scope::ExecutionScopes;
12use cairo_vm::vm::errors::hint_errors::HintError;
13use cairo_vm::vm::runners::cairo_runner::ResourceTracker;
14use cairo_vm::vm::vm_core::VirtualMachine;
15
16use crate::hints::bootloader_hints::{
17 assert_is_composite_packed_output, assert_program_address,
18 compute_and_configure_fact_topologies, compute_and_configure_fact_topologies_simple,
19 enter_packed_output_scope, guess_pre_image_of_subtasks_output_hash,
20 import_packed_output_schemas, is_plain_packed_output, load_bootloader_config,
21 load_simple_bootloader_input, prepare_simple_bootloader_input,
22 prepare_simple_bootloader_output_segment, restore_bootloader_output, save_output_pointer,
23 save_packed_outputs, set_packed_output_to_subtasks,
24};
25use crate::hints::codes::*;
26use crate::hints::execute_task_hints::{
27 append_fact_topologies, bootloader_validate_hash, determine_use_prev_hash,
28 execute_task_exit_scope, load_program_hint, setup_subtask_for_execution, validate_hash,
29 write_return_builtins_hint,
30};
31use crate::hints::inner_select_builtins::select_builtin;
32use crate::hints::select_builtins::select_builtins_enter_scope;
33use crate::hints::simple_bootloader_hints::{
34 divide_num_by_2, program_hash_function_to_ap, set_ap_to_zero, set_current_task,
35 setup_run_simple_bootloader_before_task_execution,
36};
37use crate::hints::utils::output_builtin_set_pages_by_size_and_fact_topology;
38use crate::hints::verifier_hints::load_and_parse_proof;
39
40use super::applicative_bootloader_hints::{
41 finalize_fact_topologies_and_pages, prepare_aggregator_simple_bootloader_output_segment,
42 prepare_root_task_unpacker_bootloader_output_segment, restore_applicative_output_state,
43};
44use super::bootloader_hints::load_unpacker_bootloader_input;
45use super::builtin_usage_hints::{
46 builtin_usage_5_to_ap, builtin_usage_add_other_segment, builtin_usage_add_signature,
47 builtin_usage_set_pages_and_fact_topology, flexible_builtin_usage_from_input,
48};
49use super::concat_aggregator_hints::{
50 concat_aggregator_get_handle_task_output, concat_aggregator_parse_task,
51};
52use super::fibonacci_hints::{fibonacci_load_claim_idx, fibonacci_load_second_element};
53use super::fri_layer::divide_queries_ind_by_coset_size_to_fp_offset;
54use super::mock_cairo_verifier_hints::{
55 load_mock_cairo_verifier_input, mock_cairo_verifier_hash_to_fp,
56 mock_cairo_verifier_len_output_to_fp, mock_cairo_verifier_n_steps_to_ap,
57};
58use super::pedersen_merkle_hints::{
59 pedersen_merkle_idx_parity_to_ap, pedersen_merkle_load_input, pedersen_merkle_update,
60 pedersen_merkle_verify_auth_path_len,
61};
62use super::simple_bootloader_hints::{
63 simple_bootloader_simulate_ec_op, simple_bootloader_simulate_ecdsa,
64 simple_bootloader_simulate_keccak, simulate_ec_op_assert_false,
65 simulate_ec_op_fill_mem_with_bits_of_m, simulate_ecdsa_compute_w_wr_wz,
66 simulate_ecdsa_fill_mem_with_felt_96_bit_limbs, simulate_ecdsa_get_r_and_s,
67 simulate_keccak_calc_high_low, simulate_keccak_fill_mem_with_state,
68};
69use super::simple_output_hints::{len_output_to_ap, load_simple_output_input, write_simple_output};
70use super::vector_commitment::set_bit_from_index;
71
72#[derive(Default)]
80pub struct MinimalBootloaderHintProcessor;
81
82impl MinimalBootloaderHintProcessor {
83 pub fn new() -> Self {
84 Self {}
85 }
86}
87
88impl HintProcessorLogic for MinimalBootloaderHintProcessor {
89 fn execute_hint(
90 &mut self,
91 vm: &mut VirtualMachine,
92 exec_scopes: &mut ExecutionScopes,
93 hint_data: &Box<dyn Any>,
94 ) -> Result<(), HintError> {
95 let hint_data = hint_data
96 .downcast_ref::<HintProcessorData>()
97 .ok_or(HintError::WrongHintData)?;
98
99 let ids_data = &hint_data.ids_data;
100 let ap_tracking = &hint_data.ap_tracking;
101 let constants = &hint_data.constants;
102
103 match hint_data.code.as_str() {
104 BOOTLOADER_RESTORE_BOOTLOADER_OUTPUT => restore_bootloader_output(vm, exec_scopes),
105 BOOTLOADER_PREPARE_SIMPLE_BOOTLOADER_INPUT => {
106 prepare_simple_bootloader_input(exec_scopes)
107 }
108 BOOTLOADER_READ_SIMPLE_BOOTLOADER_INPUT => load_simple_bootloader_input(exec_scopes),
109 BOOTLOADER_READ_UNPACKER_BOOTLOADER_INPUT => {
110 load_unpacker_bootloader_input(exec_scopes)
111 }
112 BOOTLOADER_LOAD_BOOTLOADER_CONFIG => {
113 load_bootloader_config(vm, exec_scopes, ids_data, ap_tracking)
114 }
115 BOOTLOADER_ENTER_PACKED_OUTPUT_SCOPE => {
116 enter_packed_output_scope(vm, exec_scopes, ids_data, ap_tracking)
117 }
118 BOOTLOADER_SAVE_OUTPUT_POINTER => {
119 save_output_pointer(vm, exec_scopes, ids_data, ap_tracking)
120 }
121 BOOTLOADER_SAVE_PACKED_OUTPUTS => save_packed_outputs(exec_scopes),
122 BOOTLOADER_GUESS_PRE_IMAGE_OF_SUBTASKS_OUTPUT_HASH => {
123 guess_pre_image_of_subtasks_output_hash(vm, exec_scopes, ids_data, ap_tracking)
124 }
125 BOOTLOADER_PREPARE_SIMPLE_BOOTLOADER_OUTPUT_SEGMENT => {
126 prepare_simple_bootloader_output_segment(vm, exec_scopes, ids_data, ap_tracking)
127 }
128 BOOTLOADER_COMPUTE_FACT_TOPOLOGIES => {
129 compute_and_configure_fact_topologies(vm, exec_scopes)
130 }
131 BOOTLOADER_SIMPLE_BOOTLOADER_COMPUTE_FACT_TOPOLOGIES => {
132 compute_and_configure_fact_topologies_simple(vm, exec_scopes)
133 }
134 BOOTLOADER_SET_PACKED_OUTPUT_TO_SUBTASKS => set_packed_output_to_subtasks(exec_scopes),
135 BOOTLOADER_IMPORT_PACKED_OUTPUT_SCHEMAS => import_packed_output_schemas(),
136 BOOTLOADER_IS_PLAIN_PACKED_OUTPUT => is_plain_packed_output(vm, exec_scopes),
137 BOOTLOADER_PROGRAM_HASH => program_hash_function_to_ap(vm, exec_scopes),
138 BOOTLOADER_VALIDATE_HASH => bootloader_validate_hash(
139 vm,
140 exec_scopes,
141 &hint_data.ids_data,
142 &hint_data.ap_tracking,
143 ),
144 BOOTLOADER_ASSERT_IS_COMPOSITE_PACKED_OUTPUT => {
145 assert_is_composite_packed_output(exec_scopes)
146 }
147 SETUP_RUN_SIMPLE_BOOTLOADER_BEFORE_TASK_EXECUTION => {
148 setup_run_simple_bootloader_before_task_execution(
149 vm,
150 exec_scopes,
151 ids_data,
152 ap_tracking,
153 )
154 }
155 SIMPLE_BOOTLOADER_DIVIDE_NUM_BY_2 => divide_num_by_2(vm, ids_data, ap_tracking),
156 SIMPLE_BOOTLOADER_SET_CURRENT_TASK => {
157 set_current_task(vm, exec_scopes, ids_data, ap_tracking)
158 }
159 DETERMINE_USE_PREV_HASH => {
160 determine_use_prev_hash(vm, exec_scopes, ids_data, ap_tracking)
161 }
162 SIMPLE_BOOTLOADER_ZERO => set_ap_to_zero(vm),
163 LOAD_PROGRAM_SEGMENT => load_program_hint(vm, exec_scopes, ids_data, ap_tracking),
164 EXECUTE_TASK_VALIDATE_HASH => validate_hash(vm, exec_scopes, ids_data, ap_tracking),
165 EXECUTE_TASK_ASSERT_PROGRAM_ADDRESS => {
166 assert_program_address(vm, exec_scopes, ids_data, ap_tracking)
167 }
168 EXECUTE_TASK_WRITE_RETURN_BUILTINS => {
169 write_return_builtins_hint(vm, exec_scopes, ids_data, ap_tracking)
170 }
171 EXECUTE_TASK_APPEND_FACT_TOPOLOGIES => {
172 append_fact_topologies(vm, exec_scopes, ids_data, ap_tracking)
173 }
174 SELECT_BUILTINS_ENTER_SCOPE => {
175 select_builtins_enter_scope(vm, exec_scopes, ids_data, ap_tracking)
176 }
177 INNER_SELECT_BUILTINS_SELECT_BUILTIN => {
178 select_builtin(vm, exec_scopes, ids_data, ap_tracking)
179 }
180 VERIFIER_LOAD_AND_PARSE_PROOF => {
181 load_and_parse_proof(vm, exec_scopes, ids_data, ap_tracking)
182 }
183 VERIFIER_GET_INDEX_LAST_BIT => set_bit_from_index(vm, ids_data, ap_tracking),
184 VERIFIER_DIVIDE_QUERIES_IND_BY_COSET_SIZE_TO_FP_OFFSET => {
185 divide_queries_ind_by_coset_size_to_fp_offset(vm, ids_data, ap_tracking)
186 }
187 APPLICATIVE_LOAD_INPUTS => prepare_aggregator_simple_bootloader_output_segment(
188 vm,
189 exec_scopes,
190 ids_data,
191 ap_tracking,
192 ),
193 APPLICATIVE_SET_UP_UNPACKER_INPUTS => {
194 prepare_root_task_unpacker_bootloader_output_segment(
195 vm,
196 exec_scopes,
197 ids_data,
198 ap_tracking,
199 )
200 }
201 APPLICATIVE_RESTORE_OUTPUT_BUILTIN_STATE => {
202 restore_applicative_output_state(vm, exec_scopes)
203 }
204 APPLICATIVE_FINALIZE_FACT_TOPOLOGIES_AND_PAGES => {
205 finalize_fact_topologies_and_pages(vm, exec_scopes, ids_data, ap_tracking)
206 }
207 SIMPLE_BOOTLOADER_SIMULATE_EC_OP => {
208 simple_bootloader_simulate_ec_op(vm, ids_data, ap_tracking)
209 }
210 SIMULATE_EC_OP_FILL_MEM_WITH_BITS_OF_M => {
211 simulate_ec_op_fill_mem_with_bits_of_m(vm, ids_data, ap_tracking, constants)
212 }
213 SIMULATE_EC_OP_ASSERT_FALSE => simulate_ec_op_assert_false(),
214 SIMPLE_BOOTLOADER_SIMULATE_KECCAK => {
215 simple_bootloader_simulate_keccak(vm, ids_data, ap_tracking)
216 }
217 SIMULATE_KECCAK_FILL_MEM_WITH_STATE => {
218 simulate_keccak_fill_mem_with_state(vm, ids_data, ap_tracking)
219 }
220 SIMULATE_KECCAK_CALC_HIGH3_LOW3 => {
221 simulate_keccak_calc_high_low(vm, ids_data, ap_tracking, 3)
222 }
223 SIMULATE_KECCAK_CALC_HIGH6_LOW6 => {
224 simulate_keccak_calc_high_low(vm, ids_data, ap_tracking, 6)
225 }
226 SIMULATE_KECCAK_CALC_HIGH9_LOW9 => {
227 simulate_keccak_calc_high_low(vm, ids_data, ap_tracking, 9)
228 }
229 SIMULATE_KECCAK_CALC_HIGH12_LOW12 => {
230 simulate_keccak_calc_high_low(vm, ids_data, ap_tracking, 12)
231 }
232 SIMULATE_KECCAK_CALC_HIGH15_LOW15 => {
233 simulate_keccak_calc_high_low(vm, ids_data, ap_tracking, 15)
234 }
235 SIMULATE_KECCAK_CALC_HIGH18_LOW18 => {
236 simulate_keccak_calc_high_low(vm, ids_data, ap_tracking, 18)
237 }
238 SIMULATE_KECCAK_CALC_HIGH21_LOW21 => {
239 simulate_keccak_calc_high_low(vm, ids_data, ap_tracking, 21)
240 }
241 SIMPLE_BOOTLOADER_SIMULATE_ECDSA => {
242 simple_bootloader_simulate_ecdsa(vm, ids_data, ap_tracking)
243 }
244 SIMULATE_ECDSA_GET_R_AND_S => simulate_ecdsa_get_r_and_s(vm, ids_data, ap_tracking),
245 SIMULATE_ECDSA_COMPUTE_W_WR_WZ => {
246 simulate_ecdsa_compute_w_wr_wz(vm, ids_data, ap_tracking, constants)
247 }
248 SIMULATE_ECDSA_FILL_MEM_WITH_FELT_96_BIT_LIMBS => {
249 simulate_ecdsa_fill_mem_with_felt_96_bit_limbs(vm, ids_data, ap_tracking)
250 }
251 unknown_hint_code => Err(HintError::UnknownHint(
252 unknown_hint_code.to_string().into_boxed_str(),
253 )),
254 }
255 }
256}
257
258impl ResourceTracker for MinimalBootloaderHintProcessor {}
259
260#[derive(Default)]
261pub struct MinimalTestProgramsHintProcessor;
262
263impl MinimalTestProgramsHintProcessor {
264 pub fn new() -> Self {
265 Self {}
266 }
267}
268
269impl HintProcessorLogic for MinimalTestProgramsHintProcessor {
270 fn execute_hint(
271 &mut self,
272 vm: &mut VirtualMachine,
273 exec_scopes: &mut ExecutionScopes,
274 hint_data: &Box<dyn Any>,
275 ) -> Result<(), HintError> {
276 let hint_data = hint_data
277 .downcast_ref::<HintProcessorData>()
278 .ok_or(HintError::WrongHintData)?;
279
280 let ids_data = &hint_data.ids_data;
281 let ap_tracking = &hint_data.ap_tracking;
282
283 match hint_data.code.as_str() {
284 SIMPLE_OUTPUT_LOAD_PROGRAM_INPUT => load_simple_output_input(exec_scopes),
285 SIMPLE_OUTPUT_WRITE_OUTPUT => {
286 write_simple_output(vm, exec_scopes, ids_data, ap_tracking)
287 }
288 SIMPLE_OUTPUT_LEN_OUTPUT_TO_AP => len_output_to_ap(vm, exec_scopes),
289 MOCK_CAIRO_VERIFIER_LOAD_INPUT => {
290 load_mock_cairo_verifier_input(vm, exec_scopes, ids_data, ap_tracking)
291 }
292 MOCK_CAIRO_VERIFIER_OUTPUT_LEN_TO_FP => {
293 mock_cairo_verifier_len_output_to_fp(vm, exec_scopes)
294 }
295 MOCK_CAIRO_VERIFIER_HASH_TO_FP => mock_cairo_verifier_hash_to_fp(vm, exec_scopes),
296 MOCK_CAIRO_VERIFIER_GET_N_STEPS => Ok(()),
297 MOCK_CAIRO_VERIFIER_N_STEPS_TO_AP => mock_cairo_verifier_n_steps_to_ap(vm, exec_scopes),
298 CONCAT_AGGREGATOR_PARSE_TASKS_OUTPUTS => {
299 concat_aggregator_parse_task(vm, exec_scopes, ids_data, ap_tracking)
300 }
301 CONCAT_AGGREGATOR_GET_TASK_OUTPUT_WITH_SIZE => {
302 concat_aggregator_get_handle_task_output(vm, exec_scopes, ids_data, ap_tracking, 1)
303 }
304 CONCAT_AGGREGATOR_GET_TASK_OUTPUT_WITHOUT_SIZE => {
305 concat_aggregator_get_handle_task_output(vm, exec_scopes, ids_data, ap_tracking, 0)
306 }
307 CONCAT_AGGREGATOR_SET_PAGES_AND_FACT_TOPOLOGY => {
308 output_builtin_set_pages_by_size_and_fact_topology(vm, ids_data, ap_tracking, 10)
309 }
310 BUILTIN_USAGE_SET_MAX_SIZE_PAGES_AND_FACT_TOPOLOGY => {
311 output_builtin_set_pages_by_size_and_fact_topology(vm, ids_data, ap_tracking, 3800)
312 }
313 BUILTIN_USAGE_ADD_OTHER_SEGMENT => {
314 builtin_usage_add_other_segment(vm, ids_data, ap_tracking, true)
315 }
316 BUILTIN_USAGE_ADD_OTHER_SEGMENT_FINALIZE => {
317 builtin_usage_add_other_segment(vm, ids_data, ap_tracking, true)
318 }
319 BUILTIN_USAGE_ADD_SIGNATURE
320 | BUILTIN_USAGE_ADD_SIGNATURE_FROM_SIGNATURE_BUILTIN_STRUCT => {
321 builtin_usage_add_signature(vm, ids_data, ap_tracking)
322 }
323 BUILTIN_USAGE_5_TO_AP => builtin_usage_5_to_ap(vm),
324 BUILTIN_USAGE_SET_PAGES_AND_FACT_TOPOLOGY => {
325 builtin_usage_set_pages_and_fact_topology(vm, ids_data, ap_tracking)
326 }
327 FLEXIBLE_BUILTIN_USAGE_FROM_INPUT => {
328 flexible_builtin_usage_from_input(vm, exec_scopes, ids_data, ap_tracking)
329 }
330 FIBONACCI_LOAD_SECOND_ELEMENT => fibonacci_load_second_element(vm, exec_scopes),
331 FIBONACCI_LOAD_CLAIM_IDX => fibonacci_load_claim_idx(vm, exec_scopes),
332 PEDERSEN_MERKLE_VERIFY_AUTH_PATH_LEN => {
333 pedersen_merkle_verify_auth_path_len(exec_scopes)
334 }
335 PEDERSEN_MERKLE_LOAD_INPUT => {
336 pedersen_merkle_load_input(vm, exec_scopes, ids_data, ap_tracking)
337 }
338 PEDERSEN_MERKLE_IDX_PARITY_TO_AP => {
339 pedersen_merkle_idx_parity_to_ap(vm, ids_data, ap_tracking)
340 }
341 PEDERSEN_MERKLE_UPDATE_LEFT => {
342 pedersen_merkle_update(vm, exec_scopes, ids_data, ap_tracking, true)
343 }
344 PEDERSEN_MERKLE_UPDATE_RIGHT => {
345 pedersen_merkle_update(vm, exec_scopes, ids_data, ap_tracking, false)
346 }
347 unknown_hint_code => Err(HintError::UnknownHint(
348 unknown_hint_code.to_string().into_boxed_str(),
349 )),
350 }
351 }
352}
353
354pub struct BootloaderHintProcessor<'a> {
359 bootloader_hint_processor: MinimalBootloaderHintProcessor,
360 builtin_hint_processor: BuiltinHintProcessor,
361 test_programs_hint_processor: MinimalTestProgramsHintProcessor,
362 pub subtask_cairo1_hint_processor_stack: Vec<Option<CairoHintProcessor<'a>>>,
363 extra_hint_processor: Option<&'a mut dyn HintProcessor>,
364}
365
366impl Default for BootloaderHintProcessor<'_> {
367 fn default() -> Self {
368 Self::new(None)
369 }
370}
371
372impl<'a> BootloaderHintProcessor<'a> {
373 pub fn new(extra_hint_processor: Option<&'a mut dyn HintProcessor>) -> Self {
374 Self {
375 bootloader_hint_processor: MinimalBootloaderHintProcessor::new(),
376 builtin_hint_processor: BuiltinHintProcessor::new_empty(),
377 subtask_cairo1_hint_processor_stack: Vec::new(),
378 test_programs_hint_processor: MinimalTestProgramsHintProcessor::new(),
379 extra_hint_processor,
380 }
381 }
382
383 pub fn add_hint(&mut self, hint_code: String, hint_func: Rc<HintFunc>) {
384 self.builtin_hint_processor
385 .extra_hints
386 .insert(hint_code, hint_func);
387 }
388
389 pub fn spawn_subtask(&mut self, cairo_hint_processor: Option<CairoHintProcessor<'a>>) {
392 self.subtask_cairo1_hint_processor_stack
393 .push(cairo_hint_processor);
394 }
395
396 pub fn despawn_subtask(&mut self) {
398 self.subtask_cairo1_hint_processor_stack.pop();
399 }
400}
401
402impl HintProcessorLogic for BootloaderHintProcessor<'_> {
403 fn execute_hint(
404 &mut self,
405 _vm: &mut VirtualMachine,
406 _exec_scopes: &mut ExecutionScopes,
407 hint_data: &Box<dyn Any>,
408 ) -> Result<(), HintError> {
409 let hint_data = hint_data.downcast_ref::<HintProcessorData>().unwrap();
412 let hint_code = &hint_data.code;
413 Err(HintError::UnknownHint(hint_code.clone().into_boxed_str()))
414 }
415
416 fn execute_hint_extensive(
417 &mut self,
418 vm: &mut VirtualMachine,
419 exec_scopes: &mut ExecutionScopes,
420 hint_data: &Box<dyn Any>,
421 ) -> Result<HintExtension, HintError> {
422 if let Some(Some(subtask_cairo_hint_processor)) =
426 self.subtask_cairo1_hint_processor_stack.last_mut()
427 {
428 match subtask_cairo_hint_processor.execute_hint_extensive(vm, exec_scopes, hint_data) {
429 Err(HintError::UnknownHint(_)) | Err(HintError::WrongHintData) => {}
433 result => {
434 return result;
435 }
436 }
437 }
438
439 if let Some(extra_hint_processor) = self.extra_hint_processor.as_mut() {
444 match extra_hint_processor.execute_hint_extensive(vm, exec_scopes, hint_data) {
445 Err(HintError::UnknownHint(_)) | Err(HintError::WrongHintData) => {}
446 result => {
447 return result;
448 }
449 }
450 }
451
452 match self
453 .bootloader_hint_processor
454 .execute_hint_extensive(vm, exec_scopes, hint_data)
455 {
456 Err(HintError::UnknownHint(_)) => {}
457 result => {
458 return result;
459 }
460 }
461
462 let hint_data_dc = hint_data
463 .downcast_ref::<HintProcessorData>()
464 .ok_or(HintError::WrongHintData)?;
465 match hint_data_dc.code.as_str() {
466 EXECUTE_TASK_CALL_TASK => {
467 return setup_subtask_for_execution(
468 self,
469 vm,
470 exec_scopes,
471 &hint_data_dc.ids_data,
472 &hint_data_dc.ap_tracking,
473 );
474 }
475 EXECUTE_TASK_EXIT_SCOPE => return execute_task_exit_scope(self, exec_scopes),
476 _ => {}
477 }
478
479 match self
480 .builtin_hint_processor
481 .execute_hint_extensive(vm, exec_scopes, hint_data)
482 {
483 Err(HintError::UnknownHint(_)) => {}
484 result => {
485 return result;
486 }
487 }
488
489 self.test_programs_hint_processor
490 .execute_hint_extensive(vm, exec_scopes, hint_data)
491 }
492}
493
494impl ResourceTracker for BootloaderHintProcessor<'_> {}