From ebec8ad2c78632321bbff73bc302935c1519d7b0 Mon Sep 17 00:00:00 2001 From: Olivier Desenfans Date: Mon, 17 Jun 2024 11:45:36 +0200 Subject: [PATCH] Feature: PIE example + run bootloader helper Problems: 1. We do not have a working example for Cairo PIEs 2. It would be convenient for developers to have a helper function to run the bootloader in proof mode easily. Solutions: 1. Add an example for how to run a Cairo PIE 2. Move the `cairo_run_bootloader_in_proof_mode` from the Stone prover SDK to this repository. This helper is now implemented in a way that makes it easy to reimplement your own version if needed. --- .github/workflows/check.yml | 4 +++ examples/run_cairo_pie.rs | 22 +++++++++++++ examples/run_program.rs | 61 ++----------------------------------- src/hints/mod.rs | 4 +-- src/hints/types.rs | 18 +++++++++++ src/lib.rs | 53 ++++++++++++++++++++++++++++++-- 6 files changed, 99 insertions(+), 63 deletions(-) create mode 100644 examples/run_cairo_pie.rs diff --git a/.github/workflows/check.yml b/.github/workflows/check.yml index d1ffe66..cdfd9a2 100644 --- a/.github/workflows/check.yml +++ b/.github/workflows/check.yml @@ -39,6 +39,10 @@ jobs: - name: Run Rust tests run: | RUSTFLAGS="-D warnings" cargo test + - name: Run examples + run: | + RUSTFLAGS="-D warnings" cargo run --example run_cairo_pie + RUSTFLAGS="-D warnings" cargo run --example run_program udeps: runs-on: ubuntu-latest diff --git a/examples/run_cairo_pie.rs b/examples/run_cairo_pie.rs new file mode 100644 index 0000000..cce5aa2 --- /dev/null +++ b/examples/run_cairo_pie.rs @@ -0,0 +1,22 @@ +use std::error::Error; + +use cairo_bootloader::bootloaders::load_bootloader; +use cairo_bootloader::cairo_run_bootloader_in_proof_mode; +use cairo_bootloader::tasks::make_bootloader_tasks; + +fn main() -> Result<(), Box> { + let bootloader_program = load_bootloader()?; + let fibonacci_pie = include_bytes!( + "../dependencies/test-programs/bootloader/pies/fibonacci-stone-e2e/cairo_pie.zip" + ); + + let tasks = make_bootloader_tasks(&[], &[fibonacci_pie])?; + + let mut runner = cairo_run_bootloader_in_proof_mode(&bootloader_program, tasks)?; + + let mut output_buffer = "Bootloader output:\n".to_string(); + runner.vm.write_output(&mut output_buffer)?; + print!("{output_buffer}"); + + Ok(()) +} diff --git a/examples/run_program.rs b/examples/run_program.rs index f451c0a..fe6590e 100644 --- a/examples/run_program.rs +++ b/examples/run_program.rs @@ -1,65 +1,8 @@ use std::error::Error; -use cairo_vm::cairo_run::{cairo_run_program_with_initial_scope, CairoRunConfig}; -use cairo_vm::types::exec_scope::ExecutionScopes; -use cairo_vm::types::layout_name::LayoutName; -use cairo_vm::types::program::Program; -use cairo_vm::vm::errors::cairo_run_errors::CairoRunError; -use cairo_vm::vm::runners::cairo_runner::CairoRunner; -use cairo_vm::Felt252; - use cairo_bootloader::bootloaders::load_bootloader; +use cairo_bootloader::cairo_run_bootloader_in_proof_mode; use cairo_bootloader::tasks::make_bootloader_tasks; -use cairo_bootloader::{ - insert_bootloader_input, BootloaderConfig, BootloaderHintProcessor, BootloaderInput, - PackedOutput, SimpleBootloaderInput, TaskSpec, -}; - -fn cairo_run_bootloader_in_proof_mode( - bootloader_program: &Program, - tasks: Vec, -) -> Result { - let mut hint_processor = BootloaderHintProcessor::new(); - - let cairo_run_config = CairoRunConfig { - entrypoint: "main", - trace_enabled: false, - relocate_mem: false, - layout: LayoutName::starknet_with_keccak, - proof_mode: true, - secure_run: None, - disable_trace_padding: false, - allow_missing_builtins: None, - }; - - // Build the bootloader input - let n_tasks = tasks.len(); - let bootloader_input = BootloaderInput { - simple_bootloader_input: SimpleBootloaderInput { - fact_topologies_path: None, - single_page: false, - tasks, - }, - bootloader_config: BootloaderConfig { - simple_bootloader_program_hash: Felt252::from(0), - supported_cairo_verifier_program_hashes: vec![], - }, - packed_outputs: vec![PackedOutput::Plain(vec![]); n_tasks], - }; - - // Note: the method used to set the bootloader input depends on - // https://github.com/lambdaclass/cairo-vm/pull/1772 and may change depending on review. - let mut exec_scopes = ExecutionScopes::new(); - insert_bootloader_input(&mut exec_scopes, bootloader_input); - - // Run the bootloader - cairo_run_program_with_initial_scope( - &bootloader_program, - &cairo_run_config, - &mut hint_processor, - exec_scopes, - ) -} fn main() -> Result<(), Box> { let bootloader_program = load_bootloader()?; @@ -69,7 +12,7 @@ fn main() -> Result<(), Box> { let mut runner = cairo_run_bootloader_in_proof_mode(&bootloader_program, tasks)?; - let mut output_buffer = "Program Output:\n".to_string(); + let mut output_buffer = "Bootloader output:\n".to_string(); runner.vm.write_output(&mut output_buffer)?; print!("{output_buffer}"); diff --git a/src/hints/mod.rs b/src/hints/mod.rs index e0f3ebd..304f8e9 100644 --- a/src/hints/mod.rs +++ b/src/hints/mod.rs @@ -9,7 +9,7 @@ mod program_hash; mod program_loader; mod select_builtins; mod simple_bootloader_hints; -mod types; +pub(crate) mod types; mod vars; pub use hint_processors::{BootloaderHintProcessor, MinimalBootloaderHintProcessor}; @@ -17,4 +17,4 @@ pub use types::{ BootloaderConfig, BootloaderInput, PackedOutput, SimpleBootloaderInput, Task, TaskSpec, }; -pub use vars::BOOTLOADER_INPUT; +pub use vars::{BOOTLOADER_INPUT, BOOTLOADER_PROGRAM_IDENTIFIERS}; diff --git a/src/hints/types.rs b/src/hints/types.rs index 065d09a..4a0a91c 100644 --- a/src/hints/types.rs +++ b/src/hints/types.rs @@ -78,3 +78,21 @@ pub struct BootloaderInput { pub bootloader_config: BootloaderConfig, pub packed_outputs: Vec, } + +impl BootloaderInput { + pub fn from_tasks(tasks: Vec) -> Self { + let n_tasks = tasks.len(); + Self { + simple_bootloader_input: SimpleBootloaderInput { + fact_topologies_path: None, + single_page: false, + tasks, + }, + bootloader_config: BootloaderConfig { + simple_bootloader_program_hash: Felt252::from(0), + supported_cairo_verifier_program_hashes: vec![], + }, + packed_outputs: vec![PackedOutput::Plain(vec![]); n_tasks], + } + } +} diff --git a/src/lib.rs b/src/lib.rs index 11523f8..f4f999a 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,4 +1,10 @@ +use crate::hints::types::ProgramIdentifiers; +use cairo_vm::cairo_run::{cairo_run_program_with_initial_scope, CairoRunConfig}; use cairo_vm::types::exec_scope::ExecutionScopes; +use cairo_vm::types::layout_name::LayoutName; +use cairo_vm::types::program::Program; +use cairo_vm::vm::errors::cairo_run_errors::CairoRunError; +use cairo_vm::vm::runners::cairo_runner::CairoRunner; pub use hints::*; pub mod bootloaders; @@ -8,10 +14,53 @@ pub mod tasks; #[cfg(test)] pub mod macros; -/// Inserts the bootloader input in the execution scopes. -pub fn insert_bootloader_input( +/// Inserts the bootloader input and program identifiers in the execution scopes. +pub fn prepare_bootloader_exec_scopes( exec_scopes: &mut ExecutionScopes, bootloader_input: BootloaderInput, + bootloader_program: &Program, ) { exec_scopes.insert_value(BOOTLOADER_INPUT, bootloader_input); + let identifiers: ProgramIdentifiers = bootloader_program + .iter_identifiers() + .map(|(k, v)| (k.to_string(), v.clone())) + .collect(); + exec_scopes.insert_value(BOOTLOADER_PROGRAM_IDENTIFIERS, identifiers); +} + +/// A helper function to run the bootloader in proof mode. +/// +/// Reimplement your own version of this function if you wish to modify the Cairo run config +/// or other parameters. +pub fn cairo_run_bootloader_in_proof_mode( + bootloader_program: &Program, + tasks: Vec, +) -> Result { + let mut hint_processor = BootloaderHintProcessor::new(); + + let cairo_run_config = CairoRunConfig { + entrypoint: "main", + trace_enabled: false, + relocate_mem: false, + layout: LayoutName::starknet_with_keccak, + proof_mode: true, + secure_run: None, + disable_trace_padding: false, + allow_missing_builtins: None, + }; + + // Build the bootloader input + let bootloader_input = BootloaderInput::from_tasks(tasks); + + // Load initial variables in the exec scopes + let mut exec_scopes = ExecutionScopes::new(); + prepare_bootloader_exec_scopes(&mut exec_scopes, bootloader_input, bootloader_program); + + // Run the bootloader + cairo_run_program_with_initial_scope( + &bootloader_program, + &cairo_run_config, + &mut hint_processor, + exec_scopes, + ) }