diff --git a/Cargo.lock b/Cargo.lock index b3ca7eb..14d8a45 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -5248,6 +5248,7 @@ dependencies = [ "reth-primitives", "rsp-client-executor", "rsp-host-executor", + "serde", "serde_json", "sp1-helper", "sp1-sdk", diff --git a/Cargo.toml b/Cargo.toml index 19883ad..e6eaf88 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -32,7 +32,7 @@ tokio = { version = "1.21", default-features = false, features = [ "rt-multi-thread", ] } serde_json = "1.0.94" -serde = { version = "1.0", default-features = false } +serde = { version = "1.0", default-features = false, features = ["derive"] } futures = "0.3" url = "2.3" thiserror = "1.0.61" diff --git a/bin/host/Cargo.toml b/bin/host/Cargo.toml index 427418b..b872196 100644 --- a/bin/host/Cargo.toml +++ b/bin/host/Cargo.toml @@ -11,6 +11,7 @@ tracing-subscriber = "0.3.18" dotenv = "0.15.0" clap = { version = "4.5.7", features = ["derive", "env"] } serde_json.workspace = true +serde.workspace = true bincode = "1.3.3" csv = "1.1" # workspace diff --git a/bin/host/src/execute.rs b/bin/host/src/execute.rs index 6ccad5d..0424dfd 100644 --- a/bin/host/src/execute.rs +++ b/bin/host/src/execute.rs @@ -1,8 +1,23 @@ -use csv::Writer; +use csv::WriterBuilder; use rsp_client_executor::{io::ClientExecutorInput, ChainVariant}; +use serde::{Deserialize, Serialize}; use sp1_sdk::ExecutionReport; use std::{fs::OpenOptions, path::PathBuf}; +#[derive(Serialize, Deserialize)] +struct ExecutionReportData { + chain_id: u64, + block_number: u64, + gas_used: u64, + tx_count: usize, + number_cycles: u64, + number_syscalls: u64, + bn_add_cycles: u64, + bn_mul_cycles: u64, + bn_pair_cycles: u64, + kzg_point_eval_cycles: u64, +} + /// Given an execution report, print it out and write it to a CSV specified by report_path. pub fn process_execution_report( variant: ChainVariant, @@ -20,54 +35,38 @@ pub fn process_execution_report( let number_cycles = execution_report.total_instruction_count(); let number_syscalls = execution_report.total_syscall_count(); - let bn_add_cycles = execution_report.cycle_tracker.get("precompile-bn-add").unwrap_or(&0); - let bn_mul_cycles = execution_report.cycle_tracker.get("precompile-bn-mul").unwrap_or(&0); - let bn_pair_cycles = execution_report.cycle_tracker.get("precompile-bn-pair").unwrap_or(&0); - let kzg_cyles = - execution_report.cycle_tracker.get("precompile-kzg-point-evaluation").unwrap_or(&0); + let bn_add_cycles = *execution_report.cycle_tracker.get("precompile-bn-add").unwrap_or(&0); + let bn_mul_cycles = *execution_report.cycle_tracker.get("precompile-bn-mul").unwrap_or(&0); + let bn_pair_cycles = *execution_report.cycle_tracker.get("precompile-bn-pair").unwrap_or(&0); + let kzg_point_eval_cycles = + *execution_report.cycle_tracker.get("precompile-kzg-point-evaluation").unwrap_or(&0); // TODO: we can track individual syscalls in our CSV once we have sp1-core as a dependency // let keccak_count = execution_report.syscall_counts.get(SyscallCode::KECCAK_PERMUTE); // let secp256k1_decompress_count = // execution_report.syscall_counts.get(SyscallCode::SECP256K1_DECOMPRESS); - let report_file_exists = report_path.exists(); + let report_data = ExecutionReportData { + chain_id, + block_number, + gas_used, + tx_count, + number_cycles, + number_syscalls, + bn_add_cycles, + bn_mul_cycles, + bn_pair_cycles, + kzg_point_eval_cycles, + }; // Open the file for appending or create it if it doesn't exist let file = OpenOptions::new().append(true).create(true).open(report_path)?; - let mut writer = Writer::from_writer(file); - - // Write the header if the file doesn't exist - if !report_file_exists { - writer.write_record([ - "chain_id", - "block_number", - "gas_used", - "tx_count", - "number_cycles", - "number_syscalls", - "bn_add_cycles", - "bn_mul_cycles", - "bn_pair_cycles", - "kzg_point_eval_cycles", - ])?; - } - - // Write the data - writer.write_record(&[ - chain_id.to_string(), - block_number.to_string(), - gas_used.to_string(), - tx_count.to_string(), - number_cycles.to_string(), - number_syscalls.to_string(), - bn_add_cycles.to_string(), - bn_mul_cycles.to_string(), - bn_pair_cycles.to_string(), - kzg_cyles.to_string(), - ])?; + // Check if the file is empty + let file_is_empty = file.metadata()?.len() == 0; + let mut writer = WriterBuilder::new().has_headers(file_is_empty).from_writer(file); + writer.serialize(report_data)?; writer.flush()?; Ok(())