diff --git a/cairo-vm-cli/src/main.rs b/cairo-vm-cli/src/main.rs index 0b39884b2a..0292a4777f 100644 --- a/cairo-vm-cli/src/main.rs +++ b/cairo-vm-cli/src/main.rs @@ -250,8 +250,8 @@ fn run(args: impl Iterator) -> Result<(), Error> { eprintln!("{error}"); CairoRunError::Runner(error) })?; - let bytes = prover_input_info.serialize()?; - std::fs::write(path, bytes)?; + prover_input_info + .write_encoded_prover_input_info(&Path::new(&path)).expect(""); } if let Some(path) = args.prover_input_info_json { diff --git a/cairo1-run/cairo b/cairo1-run/cairo new file mode 160000 index 0000000000..879302d8ce --- /dev/null +++ b/cairo1-run/cairo @@ -0,0 +1 @@ +Subproject commit 879302d8cea7206ed6349bcc2bff2b3bfa0c7521 diff --git a/vm/hola b/vm/hola new file mode 100644 index 0000000000..9048b37041 Binary files /dev/null and b/vm/hola differ diff --git a/vm/src/cairo_run.rs b/vm/src/cairo_run.rs index 63c40f19d1..0b3dd85235 100644 --- a/vm/src/cairo_run.rs +++ b/vm/src/cairo_run.rs @@ -540,4 +540,29 @@ mod tests { CairoRunError::Runner(RunnerError::PieNStepsVsRunResourcesNStepsMismatch) ))); } + + use crate::vm::runners::cairo_runner::ProverInputInfo; + #[test] + fn stav() { + let program_content = + include_bytes!("/home/stav/Stwo-Cairo/stwo-cairo/stwo_cairo_prover/test_data/test_big_program/compiled.json"); + let runner = crate::cairo_run::cairo_run( + program_content, + &CairoRunConfig { + trace_enabled: true, + layout: LayoutName::all_cairo_stwo, + allow_missing_builtins: Some(true), + ..Default::default() + }, + &mut BuiltinHintProcessor::new_empty(), + ) + .unwrap(); + let prover_info = runner.get_prover_input_info().unwrap(); + + prover_info.write_encoded_prover_input_info(std::path::Path::new("hola")).expect(""); + + let prover_input_info = + ProverInputInfo::read_encoded_prover_input_info(std::path::Path::new("hola")).unwrap(); + assert!(prover_input_info == prover_info); + } } diff --git a/vm/src/vm/runners/cairo_runner.rs b/vm/src/vm/runners/cairo_runner.rs index 1990cd8329..b133f163c5 100644 --- a/vm/src/vm/runners/cairo_runner.rs +++ b/vm/src/vm/runners/cairo_runner.rs @@ -1563,6 +1563,14 @@ pub struct ProverInputInfo { pub builtins_segments: BTreeMap, } +use bincode::decode_from_slice; +use std::fs::File; +use std::io; +use std::io::Read; +use std::io::Write; +use std::path::Path; + + impl ProverInputInfo { pub fn serialize_json(&self) -> Result { serde_json::to_string_pretty(&self).map_err(ProverInputInfoError::from) @@ -1571,6 +1579,176 @@ impl ProverInputInfo { bincode::serde::encode_to_vec(self, bincode::config::standard()) .map_err(ProverInputInfoError::from) } + + pub fn write_encoded_prover_input_info( + &self, + path: &std::path::Path, + ) -> std::io::Result<()> { + let mut dest = File::create(path)?; + // Header + // let trace_len = data.relocatable_trace.len() as u32; + dest.write_all(&(self.relocatable_trace.len() as u32).to_le_bytes()) + .expect(""); + // let memory_len = data.relocatable_memory.iter().map(|seg| seg.len()).sum::() as u32; + dest.write_all(&(self.relocatable_memory.len() as u32).to_le_bytes()) + .expect(""); + + // let public_offset_count = data.public_memory_offsets.values().map(|v| v.len()).sum::() as u32; + // let builtin_count = data.builtins_segments.len() as u32; + + // write_memory + for segment in self.relocatable_memory.iter() { + + dest.write_all(&(segment.len() as u32).to_le_bytes()) + .expect(""); + for memory_cell in segment.iter() { + match memory_cell { + None => { + dest.write_all(&[0u8]).expect(""); + dest.write_all(&[0u8; 32]).expect(""); + } + Some(unwrapped_memory_cell) => match unwrapped_memory_cell { + MaybeRelocatable::Int(int) => { + dest.write_all(&[0u8]).expect(""); + dest.write_all(&int.to_bytes_le()).expect(""); + } + MaybeRelocatable::RelocatableValue(relocatable) => { + dest.write_all(&[1u8]).expect(""); + dest.write_all(&(relocatable.segment_index as u32).to_le_bytes()) + .expect(""); + dest.write_all(&(relocatable.offset as u32).to_le_bytes()) + .expect(""); + } + }, + } + } + } + + // write_trace + for entry in &self.relocatable_trace { + dest.write_all(&(entry.pc.segment_index as u32).to_le_bytes()) + .expect(""); + dest.write_all(&(entry.pc.offset as u32).to_le_bytes()) + .expect(""); + dest.write_all(&(entry.fp as u32).to_le_bytes()).expect(""); + dest.write_all(&(entry.ap as u32).to_le_bytes()).expect(""); + } + + //write builtins segments + dest.write_all( + &bincode::serde::encode_to_vec(&self.builtins_segments, bincode::config::standard()) + .unwrap(), + ) + .expect(""); + + //write pa addresses + dest.write_all( + &bincode::serde::encode_to_vec( + &self.public_memory_offsets, + bincode::config::standard(), + ) + .unwrap(), + ) + .expect(""); + + Ok(()) + } + + pub fn read_encoded_prover_input_info(path: &Path) -> io::Result { + let mut file = File::open(path)?; + let mut buf = [0u8; 4]; + + // --- Read Header --- + file.read_exact(&mut buf)?; + let trace_len = u32::from_le_bytes(buf); + + file.read_exact(&mut buf)?; + let num_memory_segments = u32::from_le_bytes(buf); + + // --- Read Memory --- + let mut relocatable_memory = Vec::new(); + + for _ in 0..num_memory_segments { + // Read segment length + file.read_exact(&mut buf)?; + let segment_len = u32::from_le_bytes(buf); + + let mut segment = Vec::with_capacity(segment_len as usize); + for _ in 0..segment_len { + let mut tag = [0u8; 1]; + file.read_exact(&mut tag)?; + + match tag[0] { + 0u8 => { + let mut felt_bytes = [0u8; 32]; + file.read_exact(&mut felt_bytes)?; + segment.push(Some(MaybeRelocatable::Int(Felt252::from_bytes_le( + &felt_bytes, + )))); + } + 1u8 => { + let mut seg_buf = [0u8; 4]; + let mut off_buf = [0u8; 4]; + + file.read_exact(&mut seg_buf)?; + file.read_exact(&mut off_buf)?; + segment.push(Some(MaybeRelocatable::RelocatableValue(Relocatable { + segment_index: u32::from_le_bytes(seg_buf) as isize, + offset: u32::from_le_bytes(off_buf) as usize, + }))) + } + _ => panic!("invalid tag: {}", tag[0]), + }; + } + relocatable_memory.push(segment); + } + + // --- Read Trace --- + let mut relocatable_trace = Vec::with_capacity(trace_len as usize); + for _ in 0..trace_len { + let mut seg_buf = [0u8; 4]; + let mut off_buf = [0u8; 4]; + let mut fp_buf = [0u8; 4]; + let mut ap_buf = [0u8; 4]; + + file.read_exact(&mut seg_buf)?; + file.read_exact(&mut off_buf)?; + file.read_exact(&mut fp_buf)?; + file.read_exact(&mut ap_buf)?; + + relocatable_trace.push(TraceEntry { + pc: Relocatable { + segment_index: u32::from_le_bytes(seg_buf) as isize, + offset: u32::from_le_bytes(off_buf) as usize, + }, + fp: u32::from_le_bytes(fp_buf) as usize, + ap: u32::from_le_bytes(ap_buf) as usize, + }); + } + + // --- Read Remaining as Bincode Maps --- + let mut remaining_bytes = Vec::new(); + file.read_to_end(&mut remaining_bytes)?; + + let config = bincode::config::standard(); + + let (builtins_segments, bytes_read) = + bincode::serde::decode_from_slice(&remaining_bytes, config.clone()).map_err(|e| { + io::Error::new(io::ErrorKind::InvalidData, format!("bincode error: {e}")) + })?; + + let (public_memory_offsets, _) = decode_from_slice(&remaining_bytes[bytes_read..], config) + .map_err(|e| { + io::Error::new(io::ErrorKind::InvalidData, format!("bincode error: {e}")) + })?; + + Ok(Self { + relocatable_trace, + relocatable_memory, + public_memory_offsets, + builtins_segments, + }) + } } // TODO(Stav): add TraceNotEnabled error.