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