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::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/// A hint processor that can only execute the hints defined in this library.
73/// For large projects, you may want to compose a hint processor from multiple parts
74/// (ex: Starknet OS, bootloader and Cairo VM). This hint processor is as minimal as possible
75/// to enable this modularity.
76///
77/// However, this processor is not sufficient to execute the bootloader. For this,
78/// use `StandaloneBootloaderHintProcessor`.
79#[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
354/// A hint processor for use cases where we only care about the bootloader hints.
355///
356/// When executing a hint, this hint processor will first check the hints defined in this library,
357/// then the ones defined in Cairo VM.
358pub 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    /// Push new subtask state onto the stacks.
390    /// Pass an an optional Cairo hint processor.
391    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    /// Pop the current subtask state off the stacks.
397    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        // This method will never be called, but must be defined for `HintProcessorLogic`.
410
411        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        // In case the subtask_cairo_hint_processor is a Some variant, we try matching the hint
423        // using it first, for efficiency, since it is assumed to only be Some if we're inside
424        // an execution of a cairo1 program subtask.
425        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                // For cairo1 hint processors, we also ignore HintError::WrongHintData, since it
430                // if we reach a cairo1 hint procesor with a cairo0 hint, downcasting the hint data
431                // will fail and we will return the HintError::WrongHintData.
432                Err(HintError::UnknownHint(_)) | Err(HintError::WrongHintData) => {}
433                result => {
434                    return result;
435                }
436            }
437        }
438
439        // Since we don't want to ignore HintError::WrongHintData from the cairo0 hint processors,
440        // we assume all possbile cairo1 hint processors are matched first and since the extra
441        // hint processor might contain a cairo1 hint processor, we need to match it straight after
442        // the cairo1 hint processors.
443        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<'_> {}