Skip to main content

cairo_program_runner_lib/hints/
hint_processors.rs

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::applicative_bootloader_hints::aggregator_program_hash_function_to_ap;
17use crate::hints::bootloader_hints::{
18    assert_is_composite_packed_output, assert_program_address,
19    compute_and_configure_fact_topologies, compute_and_configure_fact_topologies_simple,
20    enter_packed_output_scope, guess_pre_image_of_subtasks_output_hash,
21    import_packed_output_schemas, is_plain_packed_output, load_bootloader_config,
22    load_simple_bootloader_input, prepare_simple_bootloader_input,
23    prepare_simple_bootloader_output_segment, restore_bootloader_output, save_output_pointer,
24    save_packed_outputs, set_packed_output_to_subtasks,
25};
26use crate::hints::codes::*;
27use crate::hints::execute_task_hints::{
28    append_fact_topologies, bootloader_validate_hash, determine_use_prev_hash,
29    execute_task_exit_scope, load_program_hint, setup_subtask_for_execution, validate_hash,
30    write_return_builtins_hint,
31};
32use crate::hints::inner_select_builtins::select_builtin;
33use crate::hints::select_builtins::select_builtins_enter_scope;
34use crate::hints::simple_bootloader_hints::{
35    divide_num_by_2, program_hash_function_to_ap, set_ap_to_zero, set_current_task,
36    setup_run_simple_bootloader_before_task_execution,
37};
38use crate::hints::utils::output_builtin_set_pages_by_size_and_fact_topology;
39use crate::hints::verifier_hints::load_and_parse_proof;
40
41use super::applicative_bootloader_hints::{
42    finalize_fact_topologies_and_pages, prepare_aggregator_simple_bootloader_output_segment,
43    prepare_root_task_unpacker_bootloader_output_segment, restore_applicative_output_state,
44};
45use super::bootloader_hints::load_unpacker_bootloader_input;
46use super::builtin_usage_hints::{
47    builtin_usage_5_to_ap, builtin_usage_add_other_segment, builtin_usage_add_signature,
48    builtin_usage_set_pages_and_fact_topology, flexible_builtin_usage_from_input,
49};
50use super::concat_aggregator_hints::{
51    concat_aggregator_get_handle_task_output, concat_aggregator_parse_task,
52};
53use super::fibonacci_hints::{fibonacci_load_claim_idx, fibonacci_load_second_element};
54use super::fri_layer::divide_queries_ind_by_coset_size_to_fp_offset;
55use super::mock_cairo_verifier_hints::{
56    load_mock_cairo_verifier_input, mock_cairo_verifier_hash_to_fp,
57    mock_cairo_verifier_len_output_to_fp, mock_cairo_verifier_n_steps_to_ap,
58};
59use super::pedersen_merkle_hints::{
60    pedersen_merkle_idx_parity_to_ap, pedersen_merkle_load_input, pedersen_merkle_update,
61    pedersen_merkle_verify_auth_path_len,
62};
63use super::privacy_simple_bootloader_hints::{
64    dump_privacy_simple_bootloader_output_preimage, load_privacy_simple_bootloader_input,
65};
66use super::simple_bootloader_hints::{
67    simple_bootloader_simulate_ec_op, simple_bootloader_simulate_ecdsa,
68    simple_bootloader_simulate_keccak, simulate_ec_op_assert_false,
69    simulate_ec_op_fill_mem_with_bits_of_m, simulate_ecdsa_compute_w_wr_wz,
70    simulate_ecdsa_fill_mem_with_felt_96_bit_limbs, simulate_ecdsa_get_r_and_s,
71    simulate_keccak_calc_high_low, simulate_keccak_fill_mem_with_state,
72};
73use super::simple_output_hints::{len_output_to_ap, load_simple_output_input, write_simple_output};
74use super::vector_commitment::set_bit_from_index;
75
76/// A hint processor that can only execute the hints defined in this library.
77/// For large projects, you may want to compose a hint processor from multiple parts
78/// (ex: Starknet OS, bootloader and Cairo VM). This hint processor is as minimal as possible
79/// to enable this modularity.
80///
81/// However, this processor is not sufficient to execute the bootloader. For this,
82/// use `StandaloneBootloaderHintProcessor`.
83#[derive(Default)]
84pub struct MinimalBootloaderHintProcessor;
85
86impl MinimalBootloaderHintProcessor {
87    pub fn new() -> Self {
88        Self {}
89    }
90}
91
92impl HintProcessorLogic for MinimalBootloaderHintProcessor {
93    fn execute_hint(
94        &mut self,
95        vm: &mut VirtualMachine,
96        exec_scopes: &mut ExecutionScopes,
97        hint_data: &Box<dyn Any>,
98    ) -> Result<(), HintError> {
99        let hint_data = hint_data
100            .downcast_ref::<HintProcessorData>()
101            .ok_or(HintError::WrongHintData)?;
102
103        let ids_data = &hint_data.ids_data;
104        let ap_tracking = &hint_data.ap_tracking;
105        let constants = &hint_data.constants;
106
107        match hint_data.code.as_str() {
108            BOOTLOADER_RESTORE_BOOTLOADER_OUTPUT => restore_bootloader_output(vm, exec_scopes),
109            BOOTLOADER_PREPARE_SIMPLE_BOOTLOADER_INPUT => {
110                prepare_simple_bootloader_input(exec_scopes)
111            }
112            BOOTLOADER_READ_SIMPLE_BOOTLOADER_INPUT => load_simple_bootloader_input(exec_scopes),
113            LOAD_PRIVACY_SIMPLE_BOOTLOADER_INPUT => {
114                load_privacy_simple_bootloader_input(exec_scopes)
115            }
116            DUMP_PRIVACY_SIMPLE_BOOTLOADER_OUTPUT_PREIMAGE => {
117                dump_privacy_simple_bootloader_output_preimage(
118                    vm,
119                    exec_scopes,
120                    ids_data,
121                    ap_tracking,
122                )
123            }
124            BOOTLOADER_READ_UNPACKER_BOOTLOADER_INPUT => {
125                load_unpacker_bootloader_input(exec_scopes)
126            }
127            BOOTLOADER_LOAD_BOOTLOADER_CONFIG => {
128                load_bootloader_config(vm, exec_scopes, ids_data, ap_tracking)
129            }
130            BOOTLOADER_ENTER_PACKED_OUTPUT_SCOPE => {
131                enter_packed_output_scope(vm, exec_scopes, ids_data, ap_tracking)
132            }
133            BOOTLOADER_SAVE_OUTPUT_POINTER => {
134                save_output_pointer(vm, exec_scopes, ids_data, ap_tracking)
135            }
136            BOOTLOADER_SAVE_PACKED_OUTPUTS => save_packed_outputs(exec_scopes),
137            BOOTLOADER_GUESS_PRE_IMAGE_OF_SUBTASKS_OUTPUT_HASH => {
138                guess_pre_image_of_subtasks_output_hash(vm, exec_scopes, ids_data, ap_tracking)
139            }
140            BOOTLOADER_PREPARE_SIMPLE_BOOTLOADER_OUTPUT_SEGMENT => {
141                prepare_simple_bootloader_output_segment(vm, exec_scopes, ids_data, ap_tracking)
142            }
143            BOOTLOADER_COMPUTE_FACT_TOPOLOGIES => {
144                compute_and_configure_fact_topologies(vm, exec_scopes)
145            }
146            BOOTLOADER_SIMPLE_BOOTLOADER_COMPUTE_FACT_TOPOLOGIES => {
147                compute_and_configure_fact_topologies_simple(vm, exec_scopes)
148            }
149            BOOTLOADER_SET_PACKED_OUTPUT_TO_SUBTASKS => set_packed_output_to_subtasks(exec_scopes),
150            BOOTLOADER_IMPORT_PACKED_OUTPUT_SCHEMAS => import_packed_output_schemas(),
151            BOOTLOADER_IS_PLAIN_PACKED_OUTPUT => is_plain_packed_output(vm, exec_scopes),
152            BOOTLOADER_PROGRAM_HASH => program_hash_function_to_ap(vm, exec_scopes),
153            BOOTLOADER_VALIDATE_HASH => bootloader_validate_hash(
154                vm,
155                exec_scopes,
156                &hint_data.ids_data,
157                &hint_data.ap_tracking,
158            ),
159            BOOTLOADER_ASSERT_IS_COMPOSITE_PACKED_OUTPUT => {
160                assert_is_composite_packed_output(exec_scopes)
161            }
162            SETUP_RUN_SIMPLE_BOOTLOADER_BEFORE_TASK_EXECUTION => {
163                setup_run_simple_bootloader_before_task_execution(
164                    vm,
165                    exec_scopes,
166                    ids_data,
167                    ap_tracking,
168                )
169            }
170            SIMPLE_BOOTLOADER_DIVIDE_NUM_BY_2 => divide_num_by_2(vm, ids_data, ap_tracking),
171            SIMPLE_BOOTLOADER_SET_CURRENT_TASK => {
172                set_current_task(vm, exec_scopes, ids_data, ap_tracking)
173            }
174            DETERMINE_USE_PREV_HASH => {
175                determine_use_prev_hash(vm, exec_scopes, ids_data, ap_tracking)
176            }
177            SIMPLE_BOOTLOADER_ZERO => set_ap_to_zero(vm),
178            LOAD_PROGRAM_SEGMENT => load_program_hint(vm, exec_scopes, ids_data, ap_tracking),
179            EXECUTE_TASK_VALIDATE_HASH => validate_hash(vm, exec_scopes, ids_data, ap_tracking),
180            EXECUTE_TASK_ASSERT_PROGRAM_ADDRESS => {
181                assert_program_address(vm, exec_scopes, ids_data, ap_tracking)
182            }
183            EXECUTE_TASK_WRITE_RETURN_BUILTINS => {
184                write_return_builtins_hint(vm, exec_scopes, ids_data, ap_tracking)
185            }
186            EXECUTE_TASK_APPEND_FACT_TOPOLOGIES => {
187                append_fact_topologies(vm, exec_scopes, ids_data, ap_tracking)
188            }
189            SELECT_BUILTINS_ENTER_SCOPE => {
190                select_builtins_enter_scope(vm, exec_scopes, ids_data, ap_tracking)
191            }
192            INNER_SELECT_BUILTINS_SELECT_BUILTIN => {
193                select_builtin(vm, exec_scopes, ids_data, ap_tracking)
194            }
195            VERIFIER_LOAD_AND_PARSE_PROOF => {
196                load_and_parse_proof(vm, exec_scopes, ids_data, ap_tracking)
197            }
198            VERIFIER_GET_INDEX_LAST_BIT => set_bit_from_index(vm, ids_data, ap_tracking),
199            VERIFIER_DIVIDE_QUERIES_IND_BY_COSET_SIZE_TO_FP_OFFSET => {
200                divide_queries_ind_by_coset_size_to_fp_offset(vm, ids_data, ap_tracking)
201            }
202            AGGREGATOR_PROGRAM_HASH_FUNCTION_TO_AP => {
203                aggregator_program_hash_function_to_ap(vm, exec_scopes)
204            }
205            APPLICATIVE_LOAD_INPUTS => prepare_aggregator_simple_bootloader_output_segment(
206                vm,
207                exec_scopes,
208                ids_data,
209                ap_tracking,
210            ),
211            APPLICATIVE_SET_UP_UNPACKER_INPUTS => {
212                prepare_root_task_unpacker_bootloader_output_segment(
213                    vm,
214                    exec_scopes,
215                    ids_data,
216                    ap_tracking,
217                )
218            }
219            APPLICATIVE_RESTORE_OUTPUT_BUILTIN_STATE => {
220                restore_applicative_output_state(vm, exec_scopes)
221            }
222            APPLICATIVE_FINALIZE_FACT_TOPOLOGIES_AND_PAGES => {
223                finalize_fact_topologies_and_pages(vm, exec_scopes, ids_data, ap_tracking)
224            }
225            SIMPLE_BOOTLOADER_SIMULATE_EC_OP => {
226                simple_bootloader_simulate_ec_op(vm, ids_data, ap_tracking)
227            }
228            SIMULATE_EC_OP_FILL_MEM_WITH_BITS_OF_M => {
229                simulate_ec_op_fill_mem_with_bits_of_m(vm, ids_data, ap_tracking, constants)
230            }
231            SIMULATE_EC_OP_ASSERT_FALSE => simulate_ec_op_assert_false(),
232            SIMPLE_BOOTLOADER_SIMULATE_KECCAK => {
233                simple_bootloader_simulate_keccak(vm, ids_data, ap_tracking)
234            }
235            SIMULATE_KECCAK_FILL_MEM_WITH_STATE => {
236                simulate_keccak_fill_mem_with_state(vm, ids_data, ap_tracking)
237            }
238            SIMULATE_KECCAK_CALC_HIGH3_LOW3 => {
239                simulate_keccak_calc_high_low(vm, ids_data, ap_tracking, 3)
240            }
241            SIMULATE_KECCAK_CALC_HIGH6_LOW6 => {
242                simulate_keccak_calc_high_low(vm, ids_data, ap_tracking, 6)
243            }
244            SIMULATE_KECCAK_CALC_HIGH9_LOW9 => {
245                simulate_keccak_calc_high_low(vm, ids_data, ap_tracking, 9)
246            }
247            SIMULATE_KECCAK_CALC_HIGH12_LOW12 => {
248                simulate_keccak_calc_high_low(vm, ids_data, ap_tracking, 12)
249            }
250            SIMULATE_KECCAK_CALC_HIGH15_LOW15 => {
251                simulate_keccak_calc_high_low(vm, ids_data, ap_tracking, 15)
252            }
253            SIMULATE_KECCAK_CALC_HIGH18_LOW18 => {
254                simulate_keccak_calc_high_low(vm, ids_data, ap_tracking, 18)
255            }
256            SIMULATE_KECCAK_CALC_HIGH21_LOW21 => {
257                simulate_keccak_calc_high_low(vm, ids_data, ap_tracking, 21)
258            }
259            SIMPLE_BOOTLOADER_SIMULATE_ECDSA => {
260                simple_bootloader_simulate_ecdsa(vm, ids_data, ap_tracking)
261            }
262            SIMULATE_ECDSA_GET_R_AND_S => simulate_ecdsa_get_r_and_s(vm, ids_data, ap_tracking),
263            SIMULATE_ECDSA_COMPUTE_W_WR_WZ => {
264                simulate_ecdsa_compute_w_wr_wz(vm, ids_data, ap_tracking, constants)
265            }
266            SIMULATE_ECDSA_FILL_MEM_WITH_FELT_96_BIT_LIMBS => {
267                simulate_ecdsa_fill_mem_with_felt_96_bit_limbs(vm, ids_data, ap_tracking)
268            }
269            unknown_hint_code => Err(HintError::UnknownHint(
270                unknown_hint_code.to_string().into_boxed_str(),
271            )),
272        }
273    }
274}
275
276impl ResourceTracker for MinimalBootloaderHintProcessor {}
277
278#[derive(Default)]
279pub struct MinimalTestProgramsHintProcessor;
280
281impl MinimalTestProgramsHintProcessor {
282    pub fn new() -> Self {
283        Self {}
284    }
285}
286
287impl HintProcessorLogic for MinimalTestProgramsHintProcessor {
288    fn execute_hint(
289        &mut self,
290        vm: &mut VirtualMachine,
291        exec_scopes: &mut ExecutionScopes,
292        hint_data: &Box<dyn Any>,
293    ) -> Result<(), HintError> {
294        let hint_data = hint_data
295            .downcast_ref::<HintProcessorData>()
296            .ok_or(HintError::WrongHintData)?;
297
298        let ids_data = &hint_data.ids_data;
299        let ap_tracking = &hint_data.ap_tracking;
300
301        match hint_data.code.as_str() {
302            SIMPLE_OUTPUT_LOAD_PROGRAM_INPUT => load_simple_output_input(exec_scopes),
303            SIMPLE_OUTPUT_WRITE_OUTPUT => {
304                write_simple_output(vm, exec_scopes, ids_data, ap_tracking)
305            }
306            SIMPLE_OUTPUT_LEN_OUTPUT_TO_AP => len_output_to_ap(vm, exec_scopes),
307            MOCK_CAIRO_VERIFIER_LOAD_INPUT => {
308                load_mock_cairo_verifier_input(vm, exec_scopes, ids_data, ap_tracking)
309            }
310            MOCK_CAIRO_VERIFIER_OUTPUT_LEN_TO_FP => {
311                mock_cairo_verifier_len_output_to_fp(vm, exec_scopes)
312            }
313            MOCK_CAIRO_VERIFIER_HASH_TO_FP => mock_cairo_verifier_hash_to_fp(vm, exec_scopes),
314            MOCK_CAIRO_VERIFIER_GET_N_STEPS => Ok(()),
315            MOCK_CAIRO_VERIFIER_N_STEPS_TO_AP => mock_cairo_verifier_n_steps_to_ap(vm, exec_scopes),
316            CONCAT_AGGREGATOR_PARSE_TASKS_OUTPUTS => {
317                concat_aggregator_parse_task(vm, exec_scopes, ids_data, ap_tracking)
318            }
319            CONCAT_AGGREGATOR_GET_TASK_OUTPUT_WITH_SIZE => {
320                concat_aggregator_get_handle_task_output(vm, exec_scopes, ids_data, ap_tracking, 1)
321            }
322            CONCAT_AGGREGATOR_GET_TASK_OUTPUT_WITHOUT_SIZE => {
323                concat_aggregator_get_handle_task_output(vm, exec_scopes, ids_data, ap_tracking, 0)
324            }
325            CONCAT_AGGREGATOR_SET_PAGES_AND_FACT_TOPOLOGY => {
326                output_builtin_set_pages_by_size_and_fact_topology(vm, ids_data, ap_tracking, 10)
327            }
328            BUILTIN_USAGE_SET_MAX_SIZE_PAGES_AND_FACT_TOPOLOGY => {
329                output_builtin_set_pages_by_size_and_fact_topology(vm, ids_data, ap_tracking, 3800)
330            }
331            BUILTIN_USAGE_ADD_OTHER_SEGMENT => {
332                builtin_usage_add_other_segment(vm, ids_data, ap_tracking, true)
333            }
334            BUILTIN_USAGE_ADD_OTHER_SEGMENT_FINALIZE => {
335                builtin_usage_add_other_segment(vm, ids_data, ap_tracking, true)
336            }
337            BUILTIN_USAGE_ADD_SIGNATURE
338            | BUILTIN_USAGE_ADD_SIGNATURE_FROM_SIGNATURE_BUILTIN_STRUCT => {
339                builtin_usage_add_signature(vm, ids_data, ap_tracking)
340            }
341            BUILTIN_USAGE_5_TO_AP => builtin_usage_5_to_ap(vm),
342            BUILTIN_USAGE_SET_PAGES_AND_FACT_TOPOLOGY => {
343                builtin_usage_set_pages_and_fact_topology(vm, ids_data, ap_tracking)
344            }
345            FLEXIBLE_BUILTIN_USAGE_FROM_INPUT => {
346                flexible_builtin_usage_from_input(vm, exec_scopes, ids_data, ap_tracking)
347            }
348            FIBONACCI_LOAD_SECOND_ELEMENT => fibonacci_load_second_element(vm, exec_scopes),
349            FIBONACCI_LOAD_CLAIM_IDX => fibonacci_load_claim_idx(vm, exec_scopes),
350            PEDERSEN_MERKLE_VERIFY_AUTH_PATH_LEN => {
351                pedersen_merkle_verify_auth_path_len(exec_scopes)
352            }
353            PEDERSEN_MERKLE_LOAD_INPUT => {
354                pedersen_merkle_load_input(vm, exec_scopes, ids_data, ap_tracking)
355            }
356            PEDERSEN_MERKLE_IDX_PARITY_TO_AP => {
357                pedersen_merkle_idx_parity_to_ap(vm, ids_data, ap_tracking)
358            }
359            PEDERSEN_MERKLE_UPDATE_LEFT => {
360                pedersen_merkle_update(vm, exec_scopes, ids_data, ap_tracking, true)
361            }
362            PEDERSEN_MERKLE_UPDATE_RIGHT => {
363                pedersen_merkle_update(vm, exec_scopes, ids_data, ap_tracking, false)
364            }
365            unknown_hint_code => Err(HintError::UnknownHint(
366                unknown_hint_code.to_string().into_boxed_str(),
367            )),
368        }
369    }
370}
371
372/// A hint processor for use cases where we only care about the bootloader hints.
373///
374/// When executing a hint, this hint processor will first check the hints defined in this library,
375/// then the ones defined in Cairo VM.
376pub struct BootloaderHintProcessor<'a> {
377    bootloader_hint_processor: MinimalBootloaderHintProcessor,
378    builtin_hint_processor: BuiltinHintProcessor,
379    test_programs_hint_processor: MinimalTestProgramsHintProcessor,
380    pub subtask_cairo1_hint_processor_stack: Vec<Option<CairoHintProcessor<'a>>>,
381    extra_hint_processor: Option<&'a mut dyn HintProcessor>,
382}
383
384impl Default for BootloaderHintProcessor<'_> {
385    fn default() -> Self {
386        Self::new(None)
387    }
388}
389
390impl<'a> BootloaderHintProcessor<'a> {
391    pub fn new(extra_hint_processor: Option<&'a mut dyn HintProcessor>) -> Self {
392        Self {
393            bootloader_hint_processor: MinimalBootloaderHintProcessor::new(),
394            builtin_hint_processor: BuiltinHintProcessor::new_empty(),
395            subtask_cairo1_hint_processor_stack: Vec::new(),
396            test_programs_hint_processor: MinimalTestProgramsHintProcessor::new(),
397            extra_hint_processor,
398        }
399    }
400
401    pub fn add_hint(&mut self, hint_code: String, hint_func: Rc<HintFunc>) {
402        self.builtin_hint_processor
403            .extra_hints
404            .insert(hint_code, hint_func);
405    }
406
407    /// Push new subtask state onto the stacks.
408    /// Pass an an optional Cairo hint processor.
409    pub fn spawn_subtask(&mut self, cairo_hint_processor: Option<CairoHintProcessor<'a>>) {
410        self.subtask_cairo1_hint_processor_stack
411            .push(cairo_hint_processor);
412    }
413
414    /// Pop the current subtask state off the stacks.
415    pub fn despawn_subtask(&mut self) {
416        self.subtask_cairo1_hint_processor_stack.pop();
417    }
418}
419
420impl HintProcessorLogic for BootloaderHintProcessor<'_> {
421    fn execute_hint(
422        &mut self,
423        _vm: &mut VirtualMachine,
424        _exec_scopes: &mut ExecutionScopes,
425        hint_data: &Box<dyn Any>,
426    ) -> Result<(), HintError> {
427        // This method will never be called, but must be defined for `HintProcessorLogic`.
428
429        let hint_data = hint_data.downcast_ref::<HintProcessorData>().unwrap();
430        let hint_code = &hint_data.code;
431        Err(HintError::UnknownHint(hint_code.clone().into_boxed_str()))
432    }
433
434    fn execute_hint_extensive(
435        &mut self,
436        vm: &mut VirtualMachine,
437        exec_scopes: &mut ExecutionScopes,
438        hint_data: &Box<dyn Any>,
439    ) -> Result<HintExtension, HintError> {
440        // In case the subtask_cairo_hint_processor is a Some variant, we try matching the hint
441        // using it first, for efficiency, since it is assumed to only be Some if we're inside
442        // an execution of a cairo1 program subtask.
443        if let Some(Some(subtask_cairo_hint_processor)) =
444            self.subtask_cairo1_hint_processor_stack.last_mut()
445        {
446            match subtask_cairo_hint_processor.execute_hint_extensive(vm, exec_scopes, hint_data) {
447                // For cairo1 hint processors, we also ignore HintError::WrongHintData, since it
448                // if we reach a cairo1 hint procesor with a cairo0 hint, downcasting the hint data
449                // will fail and we will return the HintError::WrongHintData.
450                Err(HintError::UnknownHint(_)) | Err(HintError::WrongHintData) => {}
451                result => {
452                    return result;
453                }
454            }
455        }
456
457        // Since we don't want to ignore HintError::WrongHintData from the cairo0 hint processors,
458        // we assume all possbile cairo1 hint processors are matched first and since the extra
459        // hint processor might contain a cairo1 hint processor, we need to match it straight after
460        // the cairo1 hint processors.
461        if let Some(extra_hint_processor) = self.extra_hint_processor.as_mut() {
462            match extra_hint_processor.execute_hint_extensive(vm, exec_scopes, hint_data) {
463                Err(HintError::UnknownHint(_)) | Err(HintError::WrongHintData) => {}
464                result => {
465                    return result;
466                }
467            }
468        }
469
470        match self
471            .bootloader_hint_processor
472            .execute_hint_extensive(vm, exec_scopes, hint_data)
473        {
474            Err(HintError::UnknownHint(_)) => {}
475            result => {
476                return result;
477            }
478        }
479
480        let hint_data_dc = hint_data
481            .downcast_ref::<HintProcessorData>()
482            .ok_or(HintError::WrongHintData)?;
483        match hint_data_dc.code.as_str() {
484            EXECUTE_TASK_CALL_TASK => {
485                return setup_subtask_for_execution(
486                    self,
487                    vm,
488                    exec_scopes,
489                    &hint_data_dc.ids_data,
490                    &hint_data_dc.ap_tracking,
491                );
492            }
493            EXECUTE_TASK_EXIT_SCOPE => return execute_task_exit_scope(self, exec_scopes),
494            _ => {}
495        }
496
497        match self
498            .builtin_hint_processor
499            .execute_hint_extensive(vm, exec_scopes, hint_data)
500        {
501            Err(HintError::UnknownHint(_)) => {}
502            result => {
503                return result;
504            }
505        }
506
507        self.test_programs_hint_processor
508            .execute_hint_extensive(vm, exec_scopes, hint_data)
509    }
510}
511
512impl ResourceTracker for BootloaderHintProcessor<'_> {}