Skip to content

Commit

Permalink
Implement running from CairoPie (#1720)
Browse files Browse the repository at this point in the history
* Implement CairoPieMetadata validity checks

* Save progres

* Progress

* Progress

* Clippy

* Impl generic serialization for suffixed ver

* Implement custom generic deserialization

* Rename module

* Complete API

* Add docs & examples

* Fix docs

* Remove reference from method

* Add clippy allow

* Add changelog entry

* Add no-std import

* Fix

* fmt

* Use a wrapper for CairoPie additional data

* Update changelog

* Fix tests + fmt

* Add test for validity checks

* Start implementing cairo_run_pie

* Implement extend_additional_data for hash

* Handle check

* Simplify

* Simplify

* Implement extend_additional_data for ecdsa

* Add test

* Implement extend_additional_data for output

* Implement extend_additional_data for enum

* Add changelog entry

* Add doc comments to get_additional_data & extend_additional_data

* Check n_steps

* Fail if proof mode

* wip

* Finalize segments by cairo pie

* Add integration test for fibonacci

* Impl check_pie_compatibility

* Simplify code

* Generalize test

* Extend additional data

* Improve test

* Fix bug + add more test cases

* Add more test cases

* Add doc

* Add test

* Add docs

* Add changelog entry

* clippy

* changelog

* fmt
  • Loading branch information
fmoletta authored Apr 25, 2024
1 parent 3f1f9ec commit bc276ce
Show file tree
Hide file tree
Showing 12 changed files with 408 additions and 31 deletions.
5 changes: 5 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,11 @@

* feat: Implement `CairoPie::read_zip_file`[#1729](https://github.com/lambdaclass/cairo-vm/pull/1729)

* feat: Implement running from `CairoPie`[#1720](https://github.com/lambdaclass/cairo-vm/pull/1720)
* Add function `cairo_run_pie`
* Add `CairoPie` methods `run_validity_checks` & `check_pie_compatibility`
* Add `Program` method `from_stripped_program`

* feat: Implement `extend_additional_data` for `BuiltinRunner`[#1726](https://github.com/lambdaclass/cairo-vm/pull/1726)

* BREAKING: Set dynamic params as null by default on air public input [#1716](https://github.com/lambdaclass/cairo-vm/pull/1716)
Expand Down
52 changes: 25 additions & 27 deletions fuzzer/Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

135 changes: 131 additions & 4 deletions vm/src/cairo_run.rs
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
use crate::{
hint_processor::hint_processor_definition::HintProcessor,
types::layout_name::LayoutName,
types::program::Program,
types::{builtin_name::BuiltinName, layout_name::LayoutName, program::Program},
vm::{
errors::{cairo_run_errors::CairoRunError, vm_exception::VmException},
runners::cairo_runner::CairoRunner,
errors::{
cairo_run_errors::CairoRunError, runner_errors::RunnerError, vm_exception::VmException,
},
runners::{cairo_pie::CairoPie, cairo_runner::CairoRunner},
security::verify_secure_runner,
vm_core::VirtualMachine,
},
Expand Down Expand Up @@ -105,6 +106,76 @@ pub fn cairo_run(

cairo_run_program(&program, cairo_run_config, hint_executor)
}
/// Runs a Cairo PIE generated by a previous cairo execution
/// To generate a cairo pie use the runner's method `get_cairo_pie`
/// Note: Cairo PIEs cannot be ran in proof_mode
/// WARNING: As the RunResources are part of the HintProcessor trait, the caller should make sure that
/// the number of steps in the `RunResources` matches that of the `ExecutionResources` in the `CairoPie`.
/// An error will be returned if this doesn't hold.
pub fn cairo_run_pie(
pie: &CairoPie,
cairo_run_config: &CairoRunConfig,
hint_processor: &mut dyn HintProcessor,
) -> Result<(CairoRunner, VirtualMachine), CairoRunError> {
if cairo_run_config.proof_mode {
return Err(RunnerError::CairoPieProofMode.into());
}
if !hint_processor
.get_n_steps()
.is_some_and(|steps| steps == pie.execution_resources.n_steps)
{
return Err(RunnerError::PieNStepsVsRunResourcesNStepsMismatch.into());
}
pie.run_validity_checks()?;
let secure_run = cairo_run_config.secure_run.unwrap_or(true);

let allow_missing_builtins = cairo_run_config.allow_missing_builtins.unwrap_or_default();

let program = Program::from_stripped_program(&pie.metadata.program);
let mut cairo_runner = CairoRunner::new(&program, cairo_run_config.layout, false)?;

let mut vm = VirtualMachine::new(cairo_run_config.trace_enabled);
let end = cairo_runner.initialize(&mut vm, allow_missing_builtins)?;
vm.finalize_segments_by_cairo_pie(pie);
// Load builtin additional data
for (name, data) in pie.additional_data.0.iter() {
// Data is not trusted in secure_run, therefore we skip extending the hash builtin's data
if matches!(name, BuiltinName::pedersen) && secure_run {
continue;
}
if let Some(builtin) = vm.builtin_runners.iter_mut().find(|b| b.name() == *name) {
builtin.extend_additional_data(data)?;
}
}
// Load previous execution memory
let n_extra_segments = pie.metadata.extra_segments.len();
vm.segments.load_pie_memory(&pie.memory, n_extra_segments)?;

cairo_runner
.run_until_pc(end, &mut vm, hint_processor)
.map_err(|err| VmException::from_vm_error(&cairo_runner, &vm, err))?;

cairo_runner.end_run(
cairo_run_config.disable_trace_padding,
false,
&mut vm,
hint_processor,
)?;

vm.verify_auto_deductions()?;
cairo_runner.read_return_values(&mut vm, allow_missing_builtins)?;

if secure_run {
verify_secure_runner(&cairo_runner, true, None, &mut vm)?;
// Check that the Cairo PIE produced by this run is compatible with the Cairo PIE received
cairo_runner
.get_cairo_pie(&vm)?
.check_pie_compatibility(pie)?;
}
cairo_runner.relocate(&mut vm, cairo_run_config.relocate_mem)?;

Ok((cairo_runner, vm))
}

#[cfg(feature = "arbitrary")]
pub fn cairo_run_fuzzed_program(
Expand Down Expand Up @@ -207,6 +278,7 @@ pub fn write_encoded_memory(
mod tests {
use super::*;
use crate::stdlib::prelude::*;
use crate::vm::runners::cairo_runner::RunResources;
use crate::Felt252;
use crate::{
hint_processor::{
Expand All @@ -217,6 +289,7 @@ mod tests {
};
use bincode::enc::write::SliceWriter;

use rstest::rstest;
#[cfg(target_arch = "wasm32")]
use wasm_bindgen_test::*;

Expand Down Expand Up @@ -377,4 +450,58 @@ mod tests {
assert!(cairo_runner.relocate(&mut vm, false).is_ok());
assert!(cairo_runner.relocated_trace.is_none());
}

#[rstest]
#[case(include_bytes!("../../cairo_programs/fibonacci.json"))]
#[case(include_bytes!("../../cairo_programs/integration.json"))]
#[case(include_bytes!("../../cairo_programs/common_signature.json"))]
#[case(include_bytes!("../../cairo_programs/relocate_segments.json"))]
#[case(include_bytes!("../../cairo_programs/ec_op.json"))]
#[case(include_bytes!("../../cairo_programs/bitwise_output.json"))]
fn get_and_run_cairo_pie(#[case] program_content: &[u8]) {
let cairo_run_config = CairoRunConfig {
layout: LayoutName::starknet_with_keccak,
..Default::default()
};
// First run program to get Cairo PIE
let cairo_pie = {
let (runner, vm) = cairo_run(
program_content,
&cairo_run_config,
&mut BuiltinHintProcessor::new_empty(),
)
.unwrap();
runner.get_cairo_pie(&vm).unwrap()
};
let mut hint_processor = BuiltinHintProcessor::new(
Default::default(),
RunResources::new(cairo_pie.execution_resources.n_steps),
);
// Default config runs with secure_run, which checks that the Cairo PIE produced by this run is compatible with the one received
assert!(cairo_run_pie(&cairo_pie, &cairo_run_config, &mut hint_processor).is_ok());
}

#[test]
fn cairo_run_pie_n_steps_not_set() {
// First run program to get Cairo PIE
let cairo_pie = {
let (runner, vm) = cairo_run(
include_bytes!("../../cairo_programs/fibonacci.json"),
&CairoRunConfig::default(),
&mut BuiltinHintProcessor::new_empty(),
)
.unwrap();
runner.get_cairo_pie(&vm).unwrap()
};
// Run Cairo PIE
let res = cairo_run_pie(
&cairo_pie,
&CairoRunConfig::default(),
&mut BuiltinHintProcessor::new_empty(),
);
assert!(res.is_err_and(|err| matches!(
err,
CairoRunError::Runner(RunnerError::PieNStepsVsRunResourcesNStepsMismatch)
)));
}
}
20 changes: 20 additions & 0 deletions vm/src/tests/cairo_pie_test.rs
Original file line number Diff line number Diff line change
Expand Up @@ -274,3 +274,23 @@ fn serialize_cairo_pie() {
.unwrap(),
);
}

#[test]
#[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
fn run_pie_validity_checks_integration() {
// Run the program
let program_content = include_bytes!("../../../cairo_programs/integration.json");
let mut hint_processor = BuiltinHintProcessor::new_empty();
let (runner, vm) = cairo_run(
program_content,
&CairoRunConfig {
layout: LayoutName::all_cairo,
..Default::default()
},
&mut hint_processor,
)
.expect("cairo_run failure");
// Obtain the pie
let cairo_pie = runner.get_cairo_pie(&vm).expect("Failed to get pie");
assert!(cairo_pie.run_validity_checks().is_ok())
}
12 changes: 12 additions & 0 deletions vm/src/types/program.rs
Original file line number Diff line number Diff line change
Expand Up @@ -386,6 +386,18 @@ impl Program {
})
}

pub fn from_stripped_program(stripped: &StrippedProgram) -> Program {
Program {
shared_program_data: Arc::new(SharedProgramData {
data: stripped.data.clone(),
main: Some(stripped.main),
..Default::default()
}),
constants: Default::default(),
builtins: stripped.builtins.clone(),
}
}

pub fn serialize(&self) -> Result<Vec<u8>, ProgramError> {
let program_serializer: ProgramSerializer = ProgramSerializer::from(self);
let bytes: Vec<u8> = serde_json::to_vec(&program_serializer)?;
Expand Down
Loading

0 comments on commit bc276ce

Please sign in to comment.