Skip to content

Commit

Permalink
Feature: PIE example + run bootloader helper
Browse files Browse the repository at this point in the history
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.
  • Loading branch information
odesenfans committed Jun 17, 2024
1 parent 9b3715c commit 5b78320
Show file tree
Hide file tree
Showing 6 changed files with 99 additions and 63 deletions.
4 changes: 4 additions & 0 deletions .github/workflows/check.yml
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
22 changes: 22 additions & 0 deletions examples/run_cairo_pie.rs
Original file line number Diff line number Diff line change
@@ -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<dyn Error>> {
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(())
}
61 changes: 2 additions & 59 deletions examples/run_program.rs
Original file line number Diff line number Diff line change
@@ -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<TaskSpec>,
) -> Result<CairoRunner, CairoRunError> {
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<dyn Error>> {
let bootloader_program = load_bootloader()?;
Expand All @@ -69,7 +12,7 @@ fn main() -> Result<(), Box<dyn Error>> {

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}");

Expand Down
4 changes: 2 additions & 2 deletions src/hints/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,12 +9,12 @@ 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};
pub use types::{
BootloaderConfig, BootloaderInput, PackedOutput, SimpleBootloaderInput, Task, TaskSpec,
};

pub use vars::BOOTLOADER_INPUT;
pub use vars::{BOOTLOADER_INPUT, BOOTLOADER_PROGRAM_IDENTIFIERS};
18 changes: 18 additions & 0 deletions src/hints/types.rs
Original file line number Diff line number Diff line change
Expand Up @@ -78,3 +78,21 @@ pub struct BootloaderInput {
pub bootloader_config: BootloaderConfig,
pub packed_outputs: Vec<PackedOutput>,
}

impl BootloaderInput {
pub fn from_tasks(tasks: Vec<TaskSpec>) -> 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],
}
}
}
53 changes: 51 additions & 2 deletions src/lib.rs
Original file line number Diff line number Diff line change
@@ -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;
Expand All @@ -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<TaskSpec>,
) -> Result<CairoRunner, CairoRunError> {
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,
)
}

0 comments on commit 5b78320

Please sign in to comment.