Skip to content

Publish aggregator_program_hash_function as a hint scope variable#393

Open
YairVaknin-starkware wants to merge 1 commit into
mainfrom
yairv/aggregator_program_hash_scope_var
Open

Publish aggregator_program_hash_function as a hint scope variable#393
YairVaknin-starkware wants to merge 1 commit into
mainfrom
yairv/aggregator_program_hash_scope_var

Conversation

@YairVaknin-starkware

@YairVaknin-starkware YairVaknin-starkware commented Jul 16, 2026

Copy link
Copy Markdown
Contributor

The applicative bootloader's input-loading hint now inserts the aggregator task's program hash function into the execution scope, and the nondet %{ aggregator_program_hash_function %} hint becomes a plain scope read instead of re-deriving the value from the input object. This also lets other applicative-flow bootloaders (the circuit-unpacking one, added later in this stack) share the nondet hint by simply setting the same scope variable in their own input-loading hints.

Stack (1/3): this ← mock circuit verifier hint ← circuit applicative BL hints.

🤖 Generated with Claude Code


This change is Reviewable

@cursor

cursor Bot commented Jul 16, 2026

Copy link
Copy Markdown

PR Summary

Low Risk
Localized hint wiring with equivalent behavior when the scope is set; new tests lock in the contract.

Overview
The nondet %{ aggregator_program_hash_function %} hint no longer reads program_hash_function from ApplicativeBootloaderInput; it only loads aggregator_program_hash_function from the execution scope and writes it to ap.

prepare_aggregator_simple_bootloader_output_segment now sets that scope value from the aggregator task when applicative input is prepared, so later nondet hints do not depend on which bootloader loaded the input. A new vars::AGGREGATOR_PROGRAM_HASH_FUNCTION constant names the scope key for reuse (e.g. circuit-unpacking applicative bootloader in a follow-up stack).

Unit tests cover the scope read, missing-scope failure, and that prepare inserts the hash function and related bootloader/output state.

Reviewed by Cursor Bugbot for commit efc698e. Bugbot is set up for automated code reviews on this repo. Configure here.

@codecov

codecov Bot commented Jul 16, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 67.80%. Comparing base (56b4a3a) to head (efc698e).

Additional details and impacted files
@@            Coverage Diff             @@
##             main     #393      +/-   ##
==========================================
+ Coverage   66.52%   67.80%   +1.28%     
==========================================
  Files          41       41              
  Lines        5807     5892      +85     
==========================================
+ Hits         3863     3995     +132     
+ Misses       1944     1897      -47     
Files with missing lines Coverage Δ
...nner-lib/src/hints/applicative_bootloader_hints.rs 55.00% <100.00%> (+55.00%) ⬆️
🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@YairVaknin-starkware
YairVaknin-starkware force-pushed the yairv/aggregator_program_hash_scope_var branch from 70a5b9a to 840f112 Compare July 16, 2026 12:32

@OmriEshhar1 OmriEshhar1 left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

:lgtm:

@OmriEshhar1 reviewed 2 files and all commit messages, and made 1 comment.
Reviewable status: :shipit: complete! all files reviewed, all discussions resolved (waiting on Gali-StarkWare).

The applicative bootloader's input-loading hint now inserts the aggregator
task's program hash function into the execution scope, and the
`nondet %{ aggregator_program_hash_function %}` hint becomes a plain scope
read instead of re-deriving the value from the input object. This also lets
other applicative-flow bootloaders (the circuit-unpacking one, added
separately) share the nondet hint by simply setting the same scope variable
in their own input-loading hints.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@YairVaknin-starkware
YairVaknin-starkware force-pushed the yairv/aggregator_program_hash_scope_var branch from 840f112 to efc698e Compare July 16, 2026 21:20

@Gali-StarkWare Gali-StarkWare left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@Gali-StarkWare reviewed 2 files and all commit messages, and made 1 comment.
Reviewable status: all files reviewed, 1 unresolved discussion (waiting on YairVaknin-starkware).


crates/cairo-program-runner-lib/src/hints/applicative_bootloader_hints.rs line 475 at r1 (raw file):

        );
    }
}

Move to a different test file

Code quote:

#[cfg(test)]
mod tests {
    use cairo_vm::Felt252;
    use cairo_vm::hint_processor::builtin_hint_processor::hint_utils::get_ptr_from_var_name;
    use cairo_vm::types::relocatable::Relocatable;
    use cairo_vm::vm::runners::builtin_runner::OutputBuiltinRunner;

    use super::*;
    use crate::test_utils::fill_ids_data_for_test;
    use crate::{PROGRAM_INPUT, ProgramInput};

    #[test]
    fn test_aggregator_program_hash_function_to_ap() {
        let mut vm = VirtualMachine::new(false, false);
        vm.add_memory_segment();
        vm.add_memory_segment();
        let mut exec_scopes = ExecutionScopes::new();
        // Set by the input-loading hint of whichever applicative bootloader is running.
        exec_scopes.insert_value(vars::AGGREGATOR_PROGRAM_HASH_FUNCTION, 2usize);

        aggregator_program_hash_function_to_ap(&mut vm, &mut exec_scopes).unwrap();

        assert_eq!(
            *vm.get_integer(Relocatable::from((1, 0))).unwrap().as_ref(),
            Felt252::from(2)
        );
    }

    #[test]
    fn test_aggregator_program_hash_function_to_ap_requires_scope_variable() {
        let mut vm = VirtualMachine::new(false, false);
        vm.add_memory_segment();
        vm.add_memory_segment();
        let mut exec_scopes = ExecutionScopes::new();
        assert!(aggregator_program_hash_function_to_ap(&mut vm, &mut exec_scopes).is_err());
    }

    #[test]
    fn test_prepare_aggregator_simple_bootloader_output_segment() {
        let mut vm = VirtualMachine::new(false, false);
        vm.add_memory_segment();
        vm.add_memory_segment();
        vm.set_fp(1);
        vm.set_ap(1);
        let ids_data = fill_ids_data_for_test(&["aggregator_output_ptr"]);
        let ap_tracking = ApTracking::new();

        // An output builtin whose pre-hint state points at a fresh segment.
        let applicative_segment = vm.add_memory_segment();
        let mut output_builtin_runner = OutputBuiltinRunner::new(true);
        output_builtin_runner.set_state(OutputBuiltinState {
            base: applicative_segment.segment_index as usize,
            base_offset: 0,
            pages: Default::default(),
            attributes: Default::default(),
        });
        vm.builtin_runners = vec![output_builtin_runner.into()];

        let fibonacci = format!(
            "{}/resources/compiled_programs/test_programs/fibonacci_compiled.json",
            env!("CARGO_MANIFEST_DIR")
        );
        let task = serde_json::json!({
            "type": "RunProgramTask",
            "path": fibonacci,
            "program_hash_function": "blake",
        });
        let mut exec_scopes = ExecutionScopes::new();
        exec_scopes.insert_value(
            PROGRAM_INPUT,
            ProgramInput::Json(
                serde_json::json!({
                    "tasks": [task],
                    "fact_topologies_path": null,
                    "single_page": false,
                    "bootloader_config": {
                        "supported_simple_bootloader_hash_list": ["0x1", "0x2"],
                        "applicative_bootloader_program_hash": "0x3",
                        "supported_cairo_verifier_program_hashes": ["0x4"],
                    },
                    "packed_outputs": [],
                    "aggregator_task": task,
                })
                .to_string(),
            ),
        );

        prepare_aggregator_simple_bootloader_output_segment(
            &mut vm,
            &mut exec_scopes,
            &ids_data,
            &ap_tracking,
        )
        .unwrap();

        // The aggregator task's hash function is exposed for the nondet hint.
        let hash_function: usize = exec_scopes
            .get(vars::AGGREGATOR_PROGRAM_HASH_FUNCTION)
            .unwrap();
        let input: ApplicativeBootloaderInput =
            exec_scopes.get(APPLICATIVE_BOOTLOADER_INPUT).unwrap();
        assert_eq!(
            hash_function,
            input.aggregator_task.program_hash_function as usize
        );

        // The simple bootloader input holds only the aggregator task.
        let simple_bootloader_input: SimpleBootloaderInput =
            exec_scopes.get(vars::SIMPLE_BOOTLOADER_INPUT).unwrap();
        assert_eq!(simple_bootloader_input.tasks.len(), 1);

        // The applicative output builtin state was saved, and the builtin points at the fresh
        // aggregator segment.
        let saved_state: OutputBuiltinState = exec_scopes
            .get(vars::APPLICATIVE_OUTPUT_BUILTIN_STATE)
            .unwrap();
        assert_eq!(saved_state.base, applicative_segment.segment_index as usize);
        let aggregator_output_ptr =
            get_ptr_from_var_name("aggregator_output_ptr", &vm, &ids_data, &ap_tracking).unwrap();
        assert_eq!(
            vm.get_output_builtin_mut().unwrap().get_state().base,
            aggregator_output_ptr.segment_index as usize
        );
    }
}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants