diff --git a/stwo_cairo_prover/crates/prover/src/input/builtins_segments.rs b/stwo_cairo_prover/crates/prover/src/input/builtins_segments.rs new file mode 100644 index 00000000..ebcb70cf --- /dev/null +++ b/stwo_cairo_prover/crates/prover/src/input/builtins_segments.rs @@ -0,0 +1,79 @@ +use std::collections::HashMap; + +use cairo_vm::air_public_input::MemorySegmentAddresses; +use cairo_vm::types::builtin_name::BuiltinName; + +/// This struct holds the builtins used in a Cairo program. +#[derive(Debug, Default)] +pub struct BuiltinsSegments { + pub range_check_bits_128: Option, + pub range_check_bits_96: Option, + pub bitwise: Option, + pub add_mod: Option, + pub ec_op: Option, + pub ecdsa: Option, + pub keccak: Option, + pub mul_mod: Option, + pub pedersen: Option, + pub poseidon: Option, +} + +impl BuiltinsSegments { + /// Create a new `BuiltinsSegments` struct from a map of memory MemorySegmentAddressess. + pub fn from_memory_segments(memory_segments: &HashMap<&str, MemorySegmentAddresses>) -> Self { + let mut res = BuiltinsSegments::default(); + for (name, value) in memory_segments.iter() { + let value = Some((value.begin_addr, value.stop_ptr).into()); + if let Some(builtin) = BuiltinName::from_str(name) { + match builtin { + BuiltinName::range_check => res.range_check_bits_128 = value, + BuiltinName::range_check96 => res.range_check_bits_96 = value, + BuiltinName::bitwise => res.bitwise = value, + BuiltinName::add_mod => res.add_mod = value, + BuiltinName::ec_op => res.ec_op = value, + BuiltinName::ecdsa => res.ecdsa = value, + BuiltinName::keccak => res.keccak = value, + BuiltinName::mul_mod => res.mul_mod = value, + BuiltinName::pedersen => res.pedersen = value, + BuiltinName::poseidon => res.poseidon = value, + // Not builtins. + BuiltinName::output | BuiltinName::segment_arena => {} + } + }; + } + res + } +} + +#[cfg(test)] +mod test_builtins_segments { + use std::path::PathBuf; + + use cairo_vm::air_public_input::PublicInput; + + use crate::input::BuiltinsSegments; + + #[test] + fn test_builtins_segments() { + let mut d = PathBuf::from(env!("CARGO_MANIFEST_DIR")); + d.push("src/input/test_builtins_segments/air_pub.json"); + let pub_data_string = std::fs::read_to_string(&d) + .unwrap_or_else(|_| panic!("Unable to read file: {}", d.display())); + let pub_data: PublicInput<'_> = + sonic_rs::from_str(&pub_data_string).expect("Unable to parse JSON"); + let builtins_segments = BuiltinsSegments::from_memory_segments(&pub_data.memory_segments); + assert_eq!( + builtins_segments.range_check_bits_128, + Some((289, 289).into()) + ); + assert_eq!(builtins_segments.range_check_bits_96, None); + assert_eq!(builtins_segments.bitwise, None); + assert_eq!(builtins_segments.add_mod, None); + assert_eq!(builtins_segments.ec_op, None); + assert_eq!(builtins_segments.ecdsa, Some((353, 353).into())); + assert_eq!(builtins_segments.keccak, None); + assert_eq!(builtins_segments.mul_mod, None); + assert_eq!(builtins_segments.pedersen, Some((97, 97).into())); + assert_eq!(builtins_segments.poseidon, None); + } +} diff --git a/stwo_cairo_prover/crates/prover/src/input/mod.rs b/stwo_cairo_prover/crates/prover/src/input/mod.rs index be6994cf..36a35567 100644 --- a/stwo_cairo_prover/crates/prover/src/input/mod.rs +++ b/stwo_cairo_prover/crates/prover/src/input/mod.rs @@ -1,7 +1,8 @@ -use cairo_vm::air_public_input::MemorySegmentAddresses; +use builtins_segments::BuiltinsSegments; use mem::Memory; use state_transitions::StateTransitions; +pub mod builtins_segments; mod decode; pub mod mem; pub mod plain; @@ -19,5 +20,5 @@ pub struct CairoInput { pub public_mem_addresses: Vec, // Builtins. - pub range_check_builtin: MemorySegmentAddresses, + pub builtins_segments: BuiltinsSegments, } diff --git a/stwo_cairo_prover/crates/prover/src/input/plain.rs b/stwo_cairo_prover/crates/prover/src/input/plain.rs index 7f9b3d6e..8d13a6f8 100644 --- a/stwo_cairo_prover/crates/prover/src/input/plain.rs +++ b/stwo_cairo_prover/crates/prover/src/input/plain.rs @@ -9,8 +9,7 @@ use itertools::Itertools; use super::mem::{MemConfig, MemoryBuilder}; use super::state_transitions::StateTransitions; use super::vm_import::MemEntry; -use super::CairoInput; -use crate::input::MemorySegmentAddresses; +use super::{BuiltinsSegments, CairoInput}; // TODO(Ohad): remove dev_mode after adding the rest of the opcodes. /// Translates a plain casm into a CairoInput by running the program and extracting the memory and @@ -71,6 +70,13 @@ pub fn input_from_finished_runner(runner: CairoRunner, dev_mode: bool) -> CairoI val: bytemuck::cast(v.to_bytes_le()), }) }); + + let memory_segments = &runner + .get_air_public_input() + .expect("Unable to get public input from the runner") + .memory_segments; + let builtins_segments = BuiltinsSegments::from_memory_segments(memory_segments); + let trace = runner.relocated_trace.unwrap(); let trace = trace.iter().map(|t| t.clone().into()); @@ -84,9 +90,6 @@ pub fn input_from_finished_runner(runner: CairoRunner, dev_mode: bool) -> CairoI state_transitions, mem: mem.build(), public_mem_addresses, - range_check_builtin: MemorySegmentAddresses { - begin_addr: 24, - stop_ptr: 64, - }, + builtins_segments, } } diff --git a/stwo_cairo_prover/crates/prover/src/input/test_builtins_segments/air_pub.json b/stwo_cairo_prover/crates/prover/src/input/test_builtins_segments/air_pub.json new file mode 100644 index 00000000..d475928a --- /dev/null +++ b/stwo_cairo_prover/crates/prover/src/input/test_builtins_segments/air_pub.json @@ -0,0 +1,425 @@ +{ + "layout": "small", + "rc_min": 32762, + "rc_max": 32770, + "n_steps": 512, + "memory_segments": { + "range_check": { + "begin_addr": 289, + "stop_ptr": 289 + }, + "pedersen": { + "begin_addr": 97, + "stop_ptr": 97 + }, + "output": { + "begin_addr": 95, + "stop_ptr": 97 + }, + "program": { + "begin_addr": 1, + "stop_ptr": 5 + }, + "execution": { + "begin_addr": 75, + "stop_ptr": 95 + }, + "ecdsa": { + "begin_addr": 353, + "stop_ptr": 353 + } + }, + "public_memory": [ + { + "address": 1, + "value": "0x40780017fff7fff", + "page": 0 + }, + { + "address": 2, + "value": "0x1", + "page": 0 + }, + { + "address": 3, + "value": "0x1104800180018000", + "page": 0 + }, + { + "address": 4, + "value": "0x4", + "page": 0 + }, + { + "address": 5, + "value": "0x10780017fff7fff", + "page": 0 + }, + { + "address": 6, + "value": "0x0", + "page": 0 + }, + { + "address": 7, + "value": "0x482680017ffd8002", + "page": 0 + }, + { + "address": 8, + "value": "0x1", + "page": 0 + }, + { + "address": 9, + "value": "0x481280017fff8002", + "page": 0 + }, + { + "address": 10, + "value": "0x40780017fff7fff", + "page": 0 + }, + { + "address": 11, + "value": "0x2", + "page": 0 + }, + { + "address": 12, + "value": "0x1104800180018000", + "page": 0 + }, + { + "address": 13, + "value": "0xc", + "page": 0 + }, + { + "address": 14, + "value": "0xa0680017fff7ffd", + "page": 0 + }, + { + "address": 15, + "value": "0x5", + "page": 0 + }, + { + "address": 16, + "value": "0x40127ffe7fff7fff", + "page": 0 + }, + { + "address": 17, + "value": "0x10780017fff7fff", + "page": 0 + }, + { + "address": 18, + "value": "0x4", + "page": 0 + }, + { + "address": 19, + "value": "0x402680017ffd7fff", + "page": 0 + }, + { + "address": 20, + "value": "0x1", + "page": 0 + }, + { + "address": 21, + "value": "0x400280007ffd7ffc", + "page": 0 + }, + { + "address": 22, + "value": "0x48127fff7fff8000", + "page": 0 + }, + { + "address": 23, + "value": "0x208b7fff7fff7ffe", + "page": 0 + }, + { + "address": 24, + "value": "0x48297ffa80007ffb", + "page": 0 + }, + { + "address": 25, + "value": "0x20680017fff7fff", + "page": 0 + }, + { + "address": 26, + "value": "0x4", + "page": 0 + }, + { + "address": 27, + "value": "0x10780017fff7fff", + "page": 0 + }, + { + "address": 28, + "value": "0x20", + "page": 0 + }, + { + "address": 29, + "value": "0x482680017ffa8000", + "page": 0 + }, + { + "address": 30, + "value": "0x1", + "page": 0 + }, + { + "address": 31, + "value": "0x480a7ffb7fff8000", + "page": 0 + }, + { + "address": 32, + "value": "0x48307ffe80007fff", + "page": 0 + }, + { + "address": 33, + "value": "0x20680017fff7fff", + "page": 0 + }, + { + "address": 34, + "value": "0x4", + "page": 0 + }, + { + "address": 35, + "value": "0x10780017fff7fff", + "page": 0 + }, + { + "address": 36, + "value": "0xd", + "page": 0 + }, + { + "address": 37, + "value": "0x40780017fff7fff", + "page": 0 + }, + { + "address": 38, + "value": "0x1", + "page": 0 + }, + { + "address": 39, + "value": "0x480680017fff8000", + "page": 0 + }, + { + "address": 40, + "value": "0x496e70757420746f6f206c6f6e6720666f7220706172616d732e", + "page": 0 + }, + { + "address": 41, + "value": "0x400080007ffe7fff", + "page": 0 + }, + { + "address": 42, + "value": "0x480680017fff8000", + "page": 0 + }, + { + "address": 43, + "value": "0x1", + "page": 0 + }, + { + "address": 44, + "value": "0x48127ffd7fff8000", + "page": 0 + }, + { + "address": 45, + "value": "0x482480017ffc8000", + "page": 0 + }, + { + "address": 46, + "value": "0x1", + "page": 0 + }, + { + "address": 47, + "value": "0x208b7fff7fff7ffe", + "page": 0 + }, + { + "address": 48, + "value": "0x480680017fff8000", + "page": 0 + }, + { + "address": 49, + "value": "0x0", + "page": 0 + }, + { + "address": 50, + "value": "0x482480017fff8000", + "page": 0 + }, + { + "address": 51, + "value": "0x1", + "page": 0 + }, + { + "address": 52, + "value": "0x400280007ffd7fff", + "page": 0 + }, + { + "address": 53, + "value": "0x480680017fff8000", + "page": 0 + }, + { + "address": 54, + "value": "0x0", + "page": 0 + }, + { + "address": 55, + "value": "0x480a7ffc7fff8000", + "page": 0 + }, + { + "address": 56, + "value": "0x482680017ffd8000", + "page": 0 + }, + { + "address": 57, + "value": "0x1", + "page": 0 + }, + { + "address": 58, + "value": "0x208b7fff7fff7ffe", + "page": 0 + }, + { + "address": 59, + "value": "0x40780017fff7fff", + "page": 0 + }, + { + "address": 60, + "value": "0x3", + "page": 0 + }, + { + "address": 61, + "value": "0x40780017fff7fff", + "page": 0 + }, + { + "address": 62, + "value": "0x1", + "page": 0 + }, + { + "address": 63, + "value": "0x480680017fff8000", + "page": 0 + }, + { + "address": 64, + "value": "0x4661696c656420746f20646573657269616c697a6520706172616d202330", + "page": 0 + }, + { + "address": 65, + "value": "0x400080007ffe7fff", + "page": 0 + }, + { + "address": 66, + "value": "0x480680017fff8000", + "page": 0 + }, + { + "address": 67, + "value": "0x1", + "page": 0 + }, + { + "address": 68, + "value": "0x48127ffd7fff8000", + "page": 0 + }, + { + "address": 69, + "value": "0x482480017ffc8000", + "page": 0 + }, + { + "address": 70, + "value": "0x1", + "page": 0 + }, + { + "address": 71, + "value": "0x208b7fff7fff7ffe", + "page": 0 + }, + { + "address": 72, + "value": "0x208b7fff7fff7ffe", + "page": 0 + }, + { + "address": 73, + "value": "0x4b", + "page": 0 + }, + { + "address": 74, + "value": "0x0", + "page": 0 + }, + { + "address": 75, + "value": "0x5f", + "page": 0 + }, + { + "address": 94, + "value": "0x61", + "page": 0 + }, + { + "address": 95, + "value": "0x0", + "page": 0 + }, + { + "address": 96, + "value": "0x1", + "page": 0 + } + ], + "dynamic_params": null +} diff --git a/stwo_cairo_prover/crates/prover/src/input/vm_import/mod.rs b/stwo_cairo_prover/crates/prover/src/input/vm_import/mod.rs index dff25c1a..93544b56 100644 --- a/stwo_cairo_prover/crates/prover/src/input/vm_import/mod.rs +++ b/stwo_cairo_prover/crates/prover/src/input/vm_import/mod.rs @@ -14,7 +14,7 @@ use super::mem::MemConfig; use super::state_transitions::StateTransitions; use super::CairoInput; use crate::input::mem::MemoryBuilder; -use crate::input::MemorySegmentAddresses; +use crate::input::BuiltinsSegments; #[derive(Debug, Error)] pub enum VmImportError { @@ -61,14 +61,13 @@ pub fn import_from_vm_output( .map(|entry| entry.address as u32) .collect(); + let builtins_segments = BuiltinsSegments::from_memory_segments(&pub_data.memory_segments); + Ok(CairoInput { state_transitions, mem: mem.build(), public_mem_addresses, - range_check_builtin: MemorySegmentAddresses { - begin_addr: pub_data.memory_segments["range_check"].begin_addr as usize, - stop_ptr: pub_data.memory_segments["range_check"].stop_ptr as usize, - }, + builtins_segments, }) } @@ -168,6 +167,8 @@ pub mod tests { #[test] fn test_read_from_large_files() { let input = large_cairo_input(); + + // Test opcode components. let components = input.state_transitions.casm_states_by_opcode; assert_eq!(components.generic_opcode.len(), 0); assert_eq!(components.add_ap_opcode_is_imm_f_op_1_base_fp_f.len(), 0); @@ -228,12 +229,36 @@ pub mod tests { assert_eq!(components.mul_opcode_is_small_f_is_imm_f.len(), 4583); assert_eq!(components.mul_opcode_is_small_f_is_imm_t.len(), 9047); assert_eq!(components.ret_opcode.len(), 49472); + + // Test builtins. + let builtins_segments = input.builtins_segments; + assert_eq!( + builtins_segments.range_check_bits_128, + Some((1715768, 1757348).into()) + ); + assert_eq!( + builtins_segments.range_check_bits_96, + Some((17706552, 17706552).into()) + ); + assert_eq!(builtins_segments.bitwise, Some((5942840, 5942840).into())); + assert_eq!(builtins_segments.add_mod, Some((21900856, 21900856).into())); + assert_eq!(builtins_segments.ec_op, Some((16428600, 16428747).into())); + assert_eq!(builtins_segments.ecdsa, Some((5910072, 5910072).into())); + assert_eq!(builtins_segments.keccak, Some((16657976, 16657976).into())); + assert_eq!(builtins_segments.mul_mod, Some((23735864, 23735864).into())); + assert_eq!(builtins_segments.pedersen, Some((1322552, 1337489).into())); + assert_eq!( + builtins_segments.poseidon, + Some((16920120, 17444532).into()) + ); } #[ignore] #[test] fn test_read_from_small_files() { let input = small_cairo_input(); + + // Test opcode components. let components = input.state_transitions.casm_states_by_opcode; assert_eq!(components.generic_opcode.len(), 0); assert_eq!(components.add_ap_opcode_is_imm_f_op_1_base_fp_f.len(), 0); @@ -291,5 +316,24 @@ pub mod tests { assert_eq!(components.mul_opcode_is_small_f_is_imm_f.len(), 0); assert_eq!(components.mul_opcode_is_small_f_is_imm_t.len(), 0); assert_eq!(components.ret_opcode.len(), 462); + + // Test builtins. + let builtins_segments = input.builtins_segments; + assert_eq!( + builtins_segments.range_check_bits_128, + Some((6000, 6050).into()) + ); + assert_eq!( + builtins_segments.range_check_bits_96, + Some((68464, 68514).into()) + ); + assert_eq!(builtins_segments.bitwise, Some((22512, 22762).into())); + assert_eq!(builtins_segments.add_mod, Some((84848, 84848).into())); + assert_eq!(builtins_segments.ec_op, Some((63472, 63822).into())); + assert_eq!(builtins_segments.ecdsa, Some((22384, 22484).into())); + assert_eq!(builtins_segments.keccak, Some((64368, 65168).into())); + assert_eq!(builtins_segments.mul_mod, Some((92016, 92016).into())); + assert_eq!(builtins_segments.pedersen, Some((4464, 4614).into())); + assert_eq!(builtins_segments.poseidon, Some((65392, 65692).into())); } }