Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implement CairoRunner.get_cairo_pie #1375

Merged
merged 40 commits into from
Aug 22, 2023
Merged
Show file tree
Hide file tree
Changes from 39 commits
Commits
Show all changes
40 commits
Select commit Hold shift + click to select a range
36f7404
Add skeletons
fmoletta Aug 14, 2023
fa0a380
Move func + progress
fmoletta Aug 14, 2023
3222cc0
Add CairoPieMetadata
fmoletta Aug 14, 2023
72a714a
Improve stripped program representation
fmoletta Aug 14, 2023
5d9ac19
Use stripped program in cairo pie
fmoletta Aug 14, 2023
3bb2723
Add Pie representation of memory
fmoletta Aug 14, 2023
49482f1
Add execution resources
fmoletta Aug 14, 2023
a186e28
Add BuiltinAdditionalInfo struct
fmoletta Aug 15, 2023
ab6e560
Add get_additional_info for output & signature
fmoletta Aug 16, 2023
20220cb
Add get_additional info for hash builtin
fmoletta Aug 16, 2023
58c1c49
Add get_additional_data for builtin enum + rename
fmoletta Aug 16, 2023
b1781f9
Add additional_data to pie
fmoletta Aug 16, 2023
f9bdb59
Fixex
fmoletta Aug 16, 2023
41c457d
fmt
fmoletta Aug 16, 2023
399350b
Clippy + remove unused impl
fmoletta Aug 16, 2023
7856710
Fix hash additional data format
fmoletta Aug 16, 2023
c1a6c2c
Fix logic
fmoletta Aug 16, 2023
9e08a9e
Fix hash additional data
fmoletta Aug 16, 2023
5b0fe95
Add wip test
fmoletta Aug 16, 2023
ce77126
Use struct for SegmentInfo
fmoletta Aug 16, 2023
1731848
Strip _builtin suffix
fmoletta Aug 16, 2023
aea245d
Complete test
fmoletta Aug 16, 2023
d4b66b1
Undo change
fmoletta Aug 16, 2023
79feadd
Add test
fmoletta Aug 16, 2023
1f3773d
Add test
fmoletta Aug 16, 2023
7f8d2ca
Add test
fmoletta Aug 16, 2023
114a9b2
Derive relevant traits for public structures
fmoletta Aug 16, 2023
4d1e811
Add tests
fmoletta Aug 16, 2023
bbf8ac2
More tests
fmoletta Aug 16, 2023
055d4e5
Add tests
fmoletta Aug 16, 2023
69014eb
Add test
fmoletta Aug 16, 2023
872b0a8
Merge branch 'main' of github.com:lambdaclass/cairo-rs into runner-ge…
fmoletta Aug 16, 2023
d9a496b
Add changelog entry
fmoletta Aug 16, 2023
e0979a9
Add tests
fmoletta Aug 16, 2023
5b0eb9d
Add tests
fmoletta Aug 16, 2023
883fca8
Fix imports
fmoletta Aug 16, 2023
f0ae7a9
Fix imports
fmoletta Aug 16, 2023
1db1796
Add wasm imports
fmoletta Aug 16, 2023
8fc0d6f
Merge branch 'main' into runner-get-cairo-pie
fmoletta Aug 17, 2023
64b04cd
Merge branch 'main' into runner-get-cairo-pie
pefontana Aug 22, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@

#### [0.8.6] - 2023-8-11

* feat: Implement `CairoRunner.get_cairo_pie`[#1375](https://github.com/lambdaclass/cairo-vm/pull/1375/files)

* fix: Fix div_mod [#1383](https://github.com/lambdaclass/cairo-vm/pull/1383)

* Fixes `div_mod` function so that it behaves like the cairo-lang version
Expand Down
247 changes: 247 additions & 0 deletions vm/src/tests/get_cairo_pie_tests.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,247 @@
use crate::stdlib::{collections::HashMap, prelude::*};

use felt::felt_str;

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

#[cfg(all(not(feature = "std"), feature = "alloc"))]
use alloc::{
string::{String, ToString},
vec::Vec,
};

use crate::{
cairo_run::{cairo_run, CairoRunConfig},
hint_processor::builtin_hint_processor::builtin_hint_processor_definition::BuiltinHintProcessor,
types::relocatable::Relocatable,
vm::runners::{
builtin_runner::{
HASH_BUILTIN_NAME, OUTPUT_BUILTIN_NAME, RANGE_CHECK_BUILTIN_NAME,
SIGNATURE_BUILTIN_NAME,
},
cairo_pie::{
BuiltinAdditionalData, CairoPieMemory, OutputBuiltinAdditionalData, SegmentInfo,
},
cairo_runner::ExecutionResources,
},
};

#[test]
#[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
fn pedersen_test() {
// Run the program
let program_content = include_bytes!("../../../cairo_programs/pedersen_test.json");
let mut hint_processor = BuiltinHintProcessor::new_empty();
let result = cairo_run(
program_content,
&CairoRunConfig {
layout: "all_cairo",
..Default::default()
},
&mut hint_processor,
);
assert!(result.is_ok());
let (runner, vm) = result.unwrap();
// Obtain the pie
let result = runner.get_cairo_pie(&vm);
assert!(result.is_ok());
let cairo_pie = result.unwrap();
// Check pie values
// CairoPieMedatada
let pie_metadata = cairo_pie.metadata;
// ret_pc_segment
assert_eq!(pie_metadata.ret_pc_segment, SegmentInfo::from((6, 0)));
// builtin_segments
let expected_builtin_segments = HashMap::from([
(String::from("output"), SegmentInfo::from((2, 1))),
(String::from("pedersen"), SegmentInfo::from((3, 3))),
(String::from("range_check"), SegmentInfo::from((4, 0))),
]);
assert_eq!(pie_metadata.builtin_segments, expected_builtin_segments);
// program_segment
assert_eq!(pie_metadata.program_segment, SegmentInfo::from((0, 19)));
// ret_fp_segment
assert_eq!(pie_metadata.ret_fp_segment, SegmentInfo::from((5, 0)));
//program
assert_eq!(pie_metadata.program.main, 6);
assert_eq!(pie_metadata.program.builtins, runner.program.builtins);
assert_eq!(
pie_metadata.program.data,
runner.program.shared_program_data.data
);
// execution_segment
assert_eq!(pie_metadata.execution_segment, SegmentInfo::from((1, 15)));
// extra_segments
assert!(pie_metadata.extra_segments.is_empty());

// execution_resources
let expected_execution_resources = ExecutionResources {
n_steps: 14,
n_memory_holes: 0,
builtin_instance_counter: HashMap::from([
(RANGE_CHECK_BUILTIN_NAME.to_string(), 0),
(OUTPUT_BUILTIN_NAME.to_string(), 1),
(HASH_BUILTIN_NAME.to_string(), 1),
]),
};
assert_eq!(cairo_pie.execution_resources, expected_execution_resources);
// additional_data
let expected_additional_data = HashMap::from([
(
OUTPUT_BUILTIN_NAME.to_string(),
BuiltinAdditionalData::Output(OutputBuiltinAdditionalData {
pages: HashMap::new(),
attributes: HashMap::new(),
}),
),
(
HASH_BUILTIN_NAME.to_string(),
BuiltinAdditionalData::Hash(vec![Relocatable::from((3, 2))]),
),
(
RANGE_CHECK_BUILTIN_NAME.to_string(),
BuiltinAdditionalData::None,
),
]);
assert_eq!(cairo_pie.additional_data, expected_additional_data);
// memory
assert_eq!(
cairo_pie.memory,
Into::<CairoPieMemory>::into(&vm.segments.memory)
);
}

#[test]
#[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
fn common_signature() {
// Run the program
let program_content = include_bytes!("../../../cairo_programs/common_signature.json");
let mut hint_processor = BuiltinHintProcessor::new_empty();
let result = cairo_run(
program_content,
&CairoRunConfig {
layout: "all_cairo",
..Default::default()
},
&mut hint_processor,
);
assert!(result.is_ok());
let (runner, vm) = result.unwrap();
// Obtain the pie
let result = runner.get_cairo_pie(&vm);
assert!(result.is_ok());
let cairo_pie = result.unwrap();
// Check pie values
// CairoPieMedatada
let pie_metadata = cairo_pie.metadata;
// ret_pc_segment
assert_eq!(pie_metadata.ret_pc_segment, SegmentInfo::from((4, 0)));
// builtin_segments
let expected_builtin_segments =
HashMap::from([(String::from("ecdsa"), SegmentInfo::from((2, 2)))]);
assert_eq!(pie_metadata.builtin_segments, expected_builtin_segments);
// program_segment
assert_eq!(pie_metadata.program_segment, SegmentInfo::from((0, 21)));
// ret_fp_segment
assert_eq!(pie_metadata.ret_fp_segment, SegmentInfo::from((3, 0)));
//program
assert_eq!(pie_metadata.program.main, 9);
assert_eq!(pie_metadata.program.builtins, runner.program.builtins);
assert_eq!(
pie_metadata.program.data,
runner.program.shared_program_data.data
);
// execution_segment
assert_eq!(pie_metadata.execution_segment, SegmentInfo::from((1, 11)));
// extra_segments
assert!(pie_metadata.extra_segments.is_empty());

// execution_resources
let expected_execution_resources = ExecutionResources {
n_steps: 11,
n_memory_holes: 0,
builtin_instance_counter: HashMap::from([(SIGNATURE_BUILTIN_NAME.to_string(), 1)]),
};
assert_eq!(cairo_pie.execution_resources, expected_execution_resources);
// additional_data
let expected_additional_data = HashMap::from([(
SIGNATURE_BUILTIN_NAME.to_string(),
BuiltinAdditionalData::Signature(HashMap::from([(
Relocatable::from((2, 0)),
(
felt_str!(
"3086480810278599376317923499561306189851900463386393948998357832163236918254"
),
felt_str!(
"598673427589502599949712887611119751108407514580626464031881322743364689811"
),
),
)])),
)]);
assert_eq!(cairo_pie.additional_data, expected_additional_data);
// memory
assert_eq!(
cairo_pie.memory,
Into::<CairoPieMemory>::into(&vm.segments.memory)
);
}

#[test]
#[cfg_attr(target_arch = "wasm32", wasm_bindgen_test)]
fn relocate_segments() {
// Run the program
let program_content = include_bytes!("../../../cairo_programs/relocate_segments.json");
let mut hint_processor = BuiltinHintProcessor::new_empty();
let result = cairo_run(
program_content,
&CairoRunConfig {
layout: "all_cairo",
..Default::default()
},
&mut hint_processor,
);
assert!(result.is_ok());
let (runner, vm) = result.unwrap();
// Obtain the pie
let result = runner.get_cairo_pie(&vm);
assert!(result.is_ok());
let cairo_pie = result.unwrap();
// Check pie values
// CairoPieMedatada
let pie_metadata = cairo_pie.metadata;
// ret_pc_segment
assert_eq!(pie_metadata.ret_pc_segment, SegmentInfo::from((3, 0)));
// builtin_segments
assert!(pie_metadata.builtin_segments.is_empty());
// program_segment
assert_eq!(pie_metadata.program_segment, SegmentInfo::from((0, 32)));
// ret_fp_segment
assert_eq!(pie_metadata.ret_fp_segment, SegmentInfo::from((2, 0)));
//program
assert_eq!(pie_metadata.program.main, 5);
assert!(pie_metadata.program.builtins.is_empty());
assert_eq!(
pie_metadata.program.data,
runner.program.shared_program_data.data
);
// execution_segment
assert_eq!(pie_metadata.execution_segment, SegmentInfo::from((1, 16)));
// extra_segments
assert_eq!(pie_metadata.extra_segments, vec![SegmentInfo::from((4, 3))]);

// execution_resources
let expected_execution_resources = ExecutionResources {
n_steps: 22,
n_memory_holes: 0,
builtin_instance_counter: HashMap::default(),
};
assert_eq!(cairo_pie.execution_resources, expected_execution_resources);
// additional_data
assert!(cairo_pie.additional_data.is_empty());
// memory
assert_eq!(
cairo_pie.memory,
Into::<CairoPieMemory>::into(&vm.segments.memory)
);
}
1 change: 1 addition & 0 deletions vm/src/tests/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ mod cairo_run_test;
mod pedersen_test;
mod struct_test;

mod get_cairo_pie_tests;
#[cfg(feature = "skip_next_instruction_hint")]
mod skip_instruction_test;

Expand Down
2 changes: 2 additions & 0 deletions vm/src/types/errors/program_errors.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@ pub enum ProgramError {
ConstWithoutValue(String),
#[error("Expected prime {PRIME_STR}, got {0}")]
PrimeDiffers(String),
#[error("Can't build a StrippedProgram from a Program without main")]
StrippedProgramNoMain,
#[error("Hint PC ({0}) is greater or equal to program length ({1})")]
InvalidHintPc(usize, usize),
}
Expand Down
47 changes: 47 additions & 0 deletions vm/src/types/program.rs
Original file line number Diff line number Diff line change
Expand Up @@ -111,6 +111,13 @@
pub(crate) builtins: Vec<BuiltinName>,
}

#[derive(Clone, Debug, PartialEq, Eq)]

Check warning on line 114 in vm/src/types/program.rs

View check run for this annotation

Codecov / codecov/patch

vm/src/types/program.rs#L114

Added line #L114 was not covered by tests
pub struct StrippedProgram {
pub data: Vec<MaybeRelocatable>,
pub builtins: Vec<BuiltinName>,
pub main: usize,
}

impl Program {
#[allow(clippy::too_many_arguments)]
pub fn new(
Expand Down Expand Up @@ -252,6 +259,20 @@
})
.collect()
}

// Obtains a reduced version of the program
// Doesn't contain hints
// Can be used for verifying execution.
pub fn get_stripped_program(&self) -> Result<StrippedProgram, ProgramError> {
Ok(StrippedProgram {
data: self.shared_program_data.data.clone(),
builtins: self.builtins.clone(),
main: self
.shared_program_data
.main
.ok_or(ProgramError::StrippedProgramNoMain)?,
})
}
}

impl Default for Program {
Expand Down Expand Up @@ -318,6 +339,8 @@
use felt::felt_str;
use num_traits::Zero;

use assert_matches::assert_matches;

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

Expand Down Expand Up @@ -1042,4 +1065,28 @@

assert_eq!(program, Program::default());
}

#[test]
fn get_stripped_program() {
let program_content = include_bytes!("../../../cairo_programs/pedersen_test.json");
let program = Program::from_bytes(program_content, Some("main")).unwrap();
let stripped_program = program.get_stripped_program().unwrap();
assert_eq!(stripped_program.builtins, program.builtins);
assert_eq!(stripped_program.data, program.shared_program_data.data);
assert_eq!(
stripped_program.main,
program.shared_program_data.main.unwrap()
);
}

#[test]
fn get_stripped_no_main() {
let program_content =
include_bytes!("../../../cairo_programs/proof_programs/fibonacci.json");
let program = Program::from_bytes(program_content, None).unwrap();
assert_matches!(

Check warning on line 1087 in vm/src/types/program.rs

View check run for this annotation

Codecov / codecov/patch

vm/src/types/program.rs#L1087

Added line #L1087 was not covered by tests
program.get_stripped_program(),
Err(ProgramError::StrippedProgramNoMain)
);
}
}
18 changes: 17 additions & 1 deletion vm/src/vm/errors/runner_errors.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ use crate::stdlib::{collections::HashSet, prelude::*};

use thiserror_no_std::Error;

use super::memory_errors::MemoryError;
use super::{memory_errors::MemoryError, trace_errors::TraceError};
use crate::types::{errors::math_errors::MathError, relocatable::Relocatable};
use felt::Felt252;

Expand Down Expand Up @@ -85,6 +85,22 @@ pub enum RunnerError {
BuiltinExpectedInteger(Box<(&'static str, Relocatable)>),
#[error("keccak_builtin: Failed to convert input cells to u64 values")]
KeccakInputCellsNotU64,
#[error("Unexpected ret_fp_segment size")]
UnexpectedRetFpSegmentSize,
#[error("Unexpected ret_pc_segment size")]
UnexpectedRetPcSegmentSize,
#[error("Expected program base offset to be zero")]
ProgramBaseOffsetNotZero,
#[error("Expected execution base offset to be zero")]
ExecBaseOffsetNotZero,
#[error("Expected ret_fp offset to be zero")]
RetFpOffsetNotZero,
#[error("Expected ret_pc offset to be zero")]
RetPcOffsetNotZero,
#[error("Can't build a StrippedProgram from a Program without main")]
StrippedProgramNoMain,
#[error(transparent)]
Trace(#[from] TraceError),
}

#[cfg(test)]
Expand Down