From bf70bda2c9b386a0d48164843dbd3fbfc31f9625 Mon Sep 17 00:00:00 2001 From: sergerad Date: Thu, 14 Nov 2024 17:33:40 +1300 Subject: [PATCH 01/22] Move outdated code to separate module --- scripts/outdated.rs | 54 +++++++++++++++++++++++++++++++++++++++++++++ scripts/xtask.rs | 54 +++++---------------------------------------- 2 files changed, 59 insertions(+), 49 deletions(-) create mode 100644 scripts/outdated.rs diff --git a/scripts/outdated.rs b/scripts/outdated.rs new file mode 100644 index 000000000..8fd09f428 --- /dev/null +++ b/scripts/outdated.rs @@ -0,0 +1,54 @@ +use std::process::{Command, Stdio}; + +use anyhow::Result; +use anyhow::{ensure, Context as _}; +use serde::Deserialize; + +#[derive(Deserialize)] +struct Outdated<'a> { + crate_name: &'a str, + dependencies: Vec>, +} + +#[derive(Deserialize)] +struct Dependency<'a> { + name: &'a str, + project: &'a str, + latest: &'a str, +} + +pub fn list_outdated_deps() -> Result<()> { + let output = Command::new("cargo") + .args(["outdated", "--root-deps-only", "--format=json"]) + .stderr(Stdio::inherit()) + .stdout(Stdio::piped()) + .output() + .context("couldn't exec `cargo`")?; + ensure!( + output.status.success(), + "command failed with {}", + output.status + ); + + let outdated_items = serde_json::Deserializer::from_slice(&output.stdout) + .into_iter::>() + .collect::, _>>() + .context("failed to parse output from `cargo outdated`")?; + for Outdated { + crate_name, + dependencies, + } in outdated_items + { + for Dependency { + name, + project, + latest, + } in dependencies + { + // https://docs.github.com/en/actions/writing-workflows/choosing-what-your-workflow-does/workflow-commands-for-github-actions#setting-a-warning-message + println!("::warning title=outdated-dependency::dependency {name} of crate {crate_name} is at version {project}, but the latest is {latest}") + } + } + + Ok(()) +} diff --git a/scripts/xtask.rs b/scripts/xtask.rs index c60770e28..9218327f1 100644 --- a/scripts/xtask.rs +++ b/scripts/xtask.rs @@ -1,10 +1,10 @@ //! General purpose scripts for development -use std::process::{Command, Stdio}; +mod outdated; -use anyhow::{ensure, Context as _}; +use anyhow::Result; use clap::Parser; -use serde::Deserialize; +use outdated::list_outdated_deps; #[derive(Parser)] enum Args { @@ -18,52 +18,8 @@ enum Args { Outdated, } -#[derive(Deserialize)] -struct Outdated<'a> { - crate_name: &'a str, - dependencies: Vec>, -} - -#[derive(Deserialize)] -struct Dependency<'a> { - name: &'a str, - project: &'a str, - latest: &'a str, -} - -fn main() -> anyhow::Result<()> { +fn main() -> Result<()> { match Args::parse() { - Args::Outdated => { - let output = Command::new("cargo") - .args(["outdated", "--root-deps-only", "--format=json"]) - .stderr(Stdio::inherit()) - .stdout(Stdio::piped()) - .output() - .context("couldn't exec `cargo`")?; - ensure!( - output.status.success(), - "command failed with {}", - output.status - ); - for Outdated { - crate_name, - dependencies, - } in serde_json::Deserializer::from_slice(&output.stdout) - .into_iter::>() - .collect::, _>>() - .context("failed to parse output from `cargo outdated`")? - { - for Dependency { - name, - project, - latest, - } in dependencies - { - // https://docs.github.com/en/actions/writing-workflows/choosing-what-your-workflow-does/workflow-commands-for-github-actions#setting-a-warning-message - println!("::warning title=outdated-dependency::dependency {name} of crate {crate_name} is at version {project}, but the latest is {latest}") - } - } - } + Args::Outdated => list_outdated_deps(), } - Ok(()) } From bd775b06be5f575dd50c6b8afe729f76b4a51b2a Mon Sep 17 00:00:00 2001 From: sergerad Date: Thu, 14 Nov 2024 18:07:24 +1300 Subject: [PATCH 02/22] Begin prove_rpc.rs impl --- Cargo.lock | 1 + scripts/Cargo.toml | 1 + scripts/prove_rpc.rs | 52 ++++++++++++++++++++++++++++++++++++++++++++ scripts/xtask.rs | 5 +++++ 4 files changed, 59 insertions(+) create mode 100644 scripts/prove_rpc.rs diff --git a/Cargo.lock b/Cargo.lock index 2c78e2031..60ea5be75 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -5879,6 +5879,7 @@ dependencies = [ name = "xtask" version = "0.0.0" dependencies = [ + "alloy", "anyhow", "clap", "serde", diff --git a/scripts/Cargo.toml b/scripts/Cargo.toml index d4328f96c..3df7a88a6 100644 --- a/scripts/Cargo.toml +++ b/scripts/Cargo.toml @@ -10,6 +10,7 @@ categories.workspace = true publish = false [dependencies] +alloy.workspace = true anyhow.workspace = true clap = { workspace = true, features = ["derive"] } serde = { workspace = true, features = ["derive"] } diff --git a/scripts/prove_rpc.rs b/scripts/prove_rpc.rs new file mode 100644 index 000000000..3fa500462 --- /dev/null +++ b/scripts/prove_rpc.rs @@ -0,0 +1,52 @@ +use alloy::{eips::BlockId, transports::http::reqwest::Url}; +use anyhow::Result; +use clap::{arg, Args, ValueEnum, ValueHint}; + +#[derive(ValueEnum, Clone)] +enum RpcType { + Jerigon, + Native, +} + +#[derive(ValueEnum, Clone)] +enum RunMode { + /// Dummy proof is generated only. Useful for quickly testing decoding and + /// all other non-proving logic. + Test, + /// The proof generated but is not verified. + Prove, + /// The proof generated and verified. + Verify, +} + +#[derive(Args)] +pub struct ProveRpcArgs { + /// The node RPC URL. + #[arg(short = 'u', value_hint = ValueHint::Url)] + rpc_url: Url, + /// The RPC type (jerigon or native). + #[arg(short = 't', long)] + rpc_type: RpcType, + /// The start of the block range to prove (inclusive). + #[arg(short = 's', long)] + start_block: BlockId, + /// The end of the block range to prove. If None, start_block-1 is used. + #[arg(short = 'e', long)] + checkpoint_block: Option, + /// The end of the block range to prove (inclusive). + #[arg(short = 'e', long)] + end_block: Option, + /// Backoff in milliseconds for retry requests + #[arg(short = 'b', long, default_value_t = 0)] + backoff: u64, + /// The maximum number of retries + #[arg(short = 'r', long, default_value_t = 0)] + max_retries: u32, + /// Whether to generate a proof and verify it or not. + #[arg(short = 'm', long)] + mode: RunMode, +} + +pub fn prove_via_rpc(args: ProveRpcArgs) -> Result<()> { + todo!() +} diff --git a/scripts/xtask.rs b/scripts/xtask.rs index 9218327f1..0a28d5ef0 100644 --- a/scripts/xtask.rs +++ b/scripts/xtask.rs @@ -1,10 +1,12 @@ //! General purpose scripts for development mod outdated; +mod prove_rpc; use anyhow::Result; use clap::Parser; use outdated::list_outdated_deps; +use prove_rpc::{prove_via_rpc, ProveRpcArgs}; #[derive(Parser)] enum Args { @@ -16,10 +18,13 @@ enum Args { /// Note that we only warn on our _direct_ dependencies, /// not the entire supply chain. Outdated, + /// Execute proving via RPC endpoint. + ProveRpc(Box), } fn main() -> Result<()> { match Args::parse() { Args::Outdated => list_outdated_deps(), + Args::ProveRpc(args) => prove_via_rpc(*args), } } From ce812b04c707afb297f3fcbc5018a0e3d005d3aa Mon Sep 17 00:00:00 2001 From: sergerad Date: Thu, 14 Nov 2024 21:49:22 +1300 Subject: [PATCH 03/22] Add initial envs and block input logic --- scripts/prove_rpc.rs | 53 ++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 49 insertions(+), 4 deletions(-) diff --git a/scripts/prove_rpc.rs b/scripts/prove_rpc.rs index 3fa500462..7c5b75208 100644 --- a/scripts/prove_rpc.rs +++ b/scripts/prove_rpc.rs @@ -1,3 +1,9 @@ +use std::{ + env::set_var, + fs::create_dir_all, + path::{Path, PathBuf}, +}; + use alloy::{eips::BlockId, transports::http::reqwest::Url}; use anyhow::Result; use clap::{arg, Args, ValueEnum, ValueHint}; @@ -10,12 +16,12 @@ enum RpcType { #[derive(ValueEnum, Clone)] enum RunMode { - /// Dummy proof is generated only. Useful for quickly testing decoding and + /// Dummy proof is generated. Useful for quickly testing decoding and /// all other non-proving logic. Test, - /// The proof generated but is not verified. + /// The proof is generated but is not verified. Prove, - /// The proof generated and verified. + /// The proof is generated and verified. Verify, } @@ -31,7 +37,7 @@ pub struct ProveRpcArgs { #[arg(short = 's', long)] start_block: BlockId, /// The end of the block range to prove. If None, start_block-1 is used. - #[arg(short = 'e', long)] + #[arg(short = 'c', long)] checkpoint_block: Option, /// The end of the block range to prove (inclusive). #[arg(short = 'e', long)] @@ -45,8 +51,47 @@ pub struct ProveRpcArgs { /// Whether to generate a proof and verify it or not. #[arg(short = 'm', long)] mode: RunMode, + /// The batch size for block fetching. + #[arg(long, default_value_t = 8)] + block_batch_size: u32, + /// The directory to output the proof files. If it does not exist, it will + /// recursively be created. + #[arg(short = 'o', long, value_hint = ValueHint::DirPath, default_value = ".")] + output_dir: PathBuf, } pub fn prove_via_rpc(args: ProveRpcArgs) -> Result<()> { + // Set rustc environment variables. + set_var("RUST_MIN_STACK", "33554432"); + set_var("RUST_BACKTRACE", "1"); + set_var("RUST_LOG", "info"); + // Script users are running locally, and might benefit from extra perf. + // See also .cargo/config.toml. + set_var("RUSTFLAGS", "-C target-cpu=native -Zlinker-features=-lld"); + + // Handle optional block inputs. + let start_block = args.start_block; + let end_block = args.end_block.unwrap_or(start_block); + let checkpoint_block = match args.checkpoint_block { + Some(checkpoint_block) => checkpoint_block, + // No checkpoint block specified, infer from start block. + None => match start_block { + // Infer the checkpoint block from the start block. + BlockId::Number(start_block) => BlockId::from(start_block.as_number().unwrap() - 1u64), + // Cannot infer the checkpoint block from a hash. + BlockId::Hash(_) => { + anyhow::bail!("Must specify checkpoint block if start block is a hash.") + } + }, + }; + + // Create the output directory if it does not exist. + let proof_output_dirpath = Path::new(&args.output_dir); + if !proof_output_dirpath.exists() { + create_dir_all(proof_output_dirpath)?; + } + let output_log_path = + proof_output_dirpath.join(format!("b{}_{}.log", args.start_block, end_block)); + todo!() } From 7b1a6117201d27b5b734eca63b4ab78a291ea755 Mon Sep 17 00:00:00 2001 From: sergerad Date: Fri, 15 Nov 2024 21:55:09 +1300 Subject: [PATCH 04/22] Add most of prove_rpc.rs logic --- Cargo.lock | 81 +++++++++++++++++++++++++++++- scripts/Cargo.toml | 1 + scripts/prove_rpc.rs | 116 +++++++++++++++++++++++++++++++++++++++++-- 3 files changed, 193 insertions(+), 5 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 60ea5be75..268462b69 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3168,6 +3168,15 @@ dependencies = [ "minimal-lexical", ] +[[package]] +name = "ntapi" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e8a3895c6391c39d7fe7ebc444a87eb2991b2a0bc718fdabd071eec617fc68e4" +dependencies = [ + "winapi", +] + [[package]] name = "nu-ansi-term" version = "0.46.0" @@ -4849,6 +4858,20 @@ dependencies = [ "syn 2.0.77", ] +[[package]] +name = "sysinfo" +version = "0.32.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e3b5ae3f4f7d64646c46c4cae4e3f01d1c5d255c7406fdd7c7f999a94e488791" +dependencies = [ + "core-foundation-sys", + "libc", + "memchr", + "ntapi", + "rayon", + "windows", +] + [[package]] name = "tap" version = "1.0.1" @@ -5651,17 +5674,70 @@ version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" +[[package]] +name = "windows" +version = "0.57.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "12342cb4d8e3b046f3d80effd474a7a02447231330ef77d71daa6fbc40681143" +dependencies = [ + "windows-core", + "windows-targets 0.52.6", +] + +[[package]] +name = "windows-core" +version = "0.57.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d2ed2439a290666cd67ecce2b0ffaad89c2a56b976b736e6ece670297897832d" +dependencies = [ + "windows-implement", + "windows-interface", + "windows-result 0.1.2", + "windows-targets 0.52.6", +] + +[[package]] +name = "windows-implement" +version = "0.57.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9107ddc059d5b6fbfbffdfa7a7fe3e22a226def0b2608f72e9d552763d3e1ad7" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.77", +] + +[[package]] +name = "windows-interface" +version = "0.57.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "29bee4b38ea3cde66011baa44dba677c432a78593e202392d1e9070cf2a7fca7" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.77", +] + [[package]] name = "windows-registry" version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e400001bb720a623c1c69032f8e3e4cf09984deec740f007dd2b03ec864804b0" dependencies = [ - "windows-result", + "windows-result 0.2.0", "windows-strings", "windows-targets 0.52.6", ] +[[package]] +name = "windows-result" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5e383302e8ec8515204254685643de10811af0ed97ea37210dc26fb0032647f8" +dependencies = [ + "windows-targets 0.52.6", +] + [[package]] name = "windows-result" version = "0.2.0" @@ -5677,7 +5753,7 @@ version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4cd9b125c486025df0eabcb585e62173c6c9eddcec5d117d3b6e8c30e2ee4d10" dependencies = [ - "windows-result", + "windows-result 0.2.0", "windows-targets 0.52.6", ] @@ -5884,6 +5960,7 @@ dependencies = [ "clap", "serde", "serde_json", + "sysinfo", ] [[package]] diff --git a/scripts/Cargo.toml b/scripts/Cargo.toml index 3df7a88a6..75727776a 100644 --- a/scripts/Cargo.toml +++ b/scripts/Cargo.toml @@ -15,6 +15,7 @@ anyhow.workspace = true clap = { workspace = true, features = ["derive"] } serde = { workspace = true, features = ["derive"] } serde_json.workspace = true +sysinfo = "0.32.0" [lints] workspace = true diff --git a/scripts/prove_rpc.rs b/scripts/prove_rpc.rs index 7c5b75208..133fe12f8 100644 --- a/scripts/prove_rpc.rs +++ b/scripts/prove_rpc.rs @@ -1,11 +1,13 @@ use std::{ env::set_var, - fs::create_dir_all, + fmt::Display, + fs::{create_dir_all, File}, path::{Path, PathBuf}, + process::{Command, Stdio}, }; use alloy::{eips::BlockId, transports::http::reqwest::Url}; -use anyhow::Result; +use anyhow::{Context as _, Result}; use clap::{arg, Args, ValueEnum, ValueHint}; #[derive(ValueEnum, Clone)] @@ -14,6 +16,15 @@ enum RpcType { Native, } +impl Display for RpcType { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + match self { + RpcType::Jerigon => write!(f, "jerigon"), + RpcType::Native => write!(f, "native"), + } + } +} + #[derive(ValueEnum, Clone)] enum RunMode { /// Dummy proof is generated. Useful for quickly testing decoding and @@ -69,6 +80,19 @@ pub fn prove_via_rpc(args: ProveRpcArgs) -> Result<()> { // See also .cargo/config.toml. set_var("RUSTFLAGS", "-C target-cpu=native -Zlinker-features=-lld"); + // TODO: move this logic below when full match is done + if let RunMode::Test = args.mode { + set_var("ARITHMETIC_CIRCUIT_SIZE", "16..21"); + set_var("BYTE_PACKING_CIRCUIT_SIZE", "8..21"); + set_var("CPU_CIRCUIT_SIZE", "8..21"); + set_var("KECCAK_CIRCUIT_SIZE", "4..20"); + set_var("KECCAK_SPONGE_CIRCUIT_SIZE", "8..17"); + set_var("LOGIC_CIRCUIT_SIZE", "4..21"); + set_var("MEMORY_CIRCUIT_SIZE", "17..24"); + set_var("MEMORY_BEFORE_CIRCUIT_SIZE", "16..23"); + set_var("MEMORY_AFTER_CIRCUIT_SIZE", "7..23"); + } + // Handle optional block inputs. let start_block = args.start_block; let end_block = args.end_block.unwrap_or(start_block); @@ -92,6 +116,92 @@ pub fn prove_via_rpc(args: ProveRpcArgs) -> Result<()> { } let output_log_path = proof_output_dirpath.join(format!("b{}_{}.log", args.start_block, end_block)); + let log_out = File::create(&output_log_path).context("couldn't create log file")?; + let log_err = log_out.try_clone().context("couldn't clone log file")?; - todo!() + /// Set file handle limit. + const RECOMMENDED_FILE_LIMIT: isize = 8192; + if !sysinfo::set_open_files_limit(RECOMMENDED_FILE_LIMIT) { + eprintln!("WARNING: Unable to set file descriptor limit to recommended value: {RECOMMENDED_FILE_LIMIT}."); + } + + let runner = Runner::new("cargo") + .args(&[ + "run", + "--release", + "--package=zero", + "--bin=leader", + "--", + "--runtime=in-memory", + "--load-strategy=on-demand", + "--proof-output-dir", + proof_output_dirpath.to_str().unwrap(), + "--block-batch-size", + &args.block_batch_size.to_string(), + "rpc", + "--rpc-type", + &args.rpc_type.to_string(), + "--rpc-url", + args.rpc_url.as_ref(), + "--start-block", + &start_block.to_string(), + "--checkpoint-block", + &checkpoint_block.to_string(), + "--end-block", + &end_block.to_string(), + "--backoff", + &args.backoff.to_string(), + "--max-retries", + &args.max_retries.to_string(), + ]) + .out(log_out) + .err(log_err); + match args.mode { + RunMode::Test => runner.args(&["--use-test-config"]).run(), + RunMode::Prove => todo!(), + RunMode::Verify => todo!(), + } +} + +struct Runner { + cmd: String, + args: Vec, + out: Stdio, + err: Stdio, +} + +impl Runner { + fn new(cmd: impl Into) -> Self { + Self { + cmd: cmd.into(), + args: vec![], + out: Stdio::piped(), + err: Stdio::piped(), + } + } + + fn args(mut self, args: &[&str]) -> Self { + self.args.extend(args.iter().map(|s| s.to_string())); + self + } + + fn out(mut self, out: impl Into) -> Self { + self.out = out.into(); + self + } + + fn err(mut self, err: impl Into) -> Self { + self.err = err.into(); + self + } + + fn run(self) -> Result<()> { + let output = Command::new(&self.cmd) + .args(&self.args) + .stdout(self.out) + .stderr(self.err) + .output() + .context(format!("couldn't exec `{}`", &self.cmd))?; + todo!() + } } From 4abfbc0163e3ce3524362ad36445bc582d9031a6 Mon Sep 17 00:00:00 2001 From: sergerad Date: Sat, 16 Nov 2024 09:54:27 +1300 Subject: [PATCH 05/22] Split runner module and add verify path --- scripts/prove_rpc.rs | 110 ++++++++++++++++--------------------------- scripts/runner.rs | 53 +++++++++++++++++++++ scripts/xtask.rs | 1 + 3 files changed, 95 insertions(+), 69 deletions(-) create mode 100644 scripts/runner.rs diff --git a/scripts/prove_rpc.rs b/scripts/prove_rpc.rs index 133fe12f8..7603b7f95 100644 --- a/scripts/prove_rpc.rs +++ b/scripts/prove_rpc.rs @@ -1,15 +1,16 @@ use std::{ env::set_var, fmt::Display, - fs::{create_dir_all, File}, + fs::create_dir_all, path::{Path, PathBuf}, - process::{Command, Stdio}, }; use alloy::{eips::BlockId, transports::http::reqwest::Url}; -use anyhow::{Context as _, Result}; +use anyhow::Result; use clap::{arg, Args, ValueEnum, ValueHint}; +use crate::runner::Runner; + #[derive(ValueEnum, Clone)] enum RpcType { Jerigon, @@ -80,19 +81,6 @@ pub fn prove_via_rpc(args: ProveRpcArgs) -> Result<()> { // See also .cargo/config.toml. set_var("RUSTFLAGS", "-C target-cpu=native -Zlinker-features=-lld"); - // TODO: move this logic below when full match is done - if let RunMode::Test = args.mode { - set_var("ARITHMETIC_CIRCUIT_SIZE", "16..21"); - set_var("BYTE_PACKING_CIRCUIT_SIZE", "8..21"); - set_var("CPU_CIRCUIT_SIZE", "8..21"); - set_var("KECCAK_CIRCUIT_SIZE", "4..20"); - set_var("KECCAK_SPONGE_CIRCUIT_SIZE", "8..17"); - set_var("LOGIC_CIRCUIT_SIZE", "4..21"); - set_var("MEMORY_CIRCUIT_SIZE", "17..24"); - set_var("MEMORY_BEFORE_CIRCUIT_SIZE", "16..23"); - set_var("MEMORY_AFTER_CIRCUIT_SIZE", "7..23"); - } - // Handle optional block inputs. let start_block = args.start_block; let end_block = args.end_block.unwrap_or(start_block); @@ -114,18 +102,16 @@ pub fn prove_via_rpc(args: ProveRpcArgs) -> Result<()> { if !proof_output_dirpath.exists() { create_dir_all(proof_output_dirpath)?; } - let output_log_path = - proof_output_dirpath.join(format!("b{}_{}.log", args.start_block, end_block)); - let log_out = File::create(&output_log_path).context("couldn't create log file")?; - let log_err = log_out.try_clone().context("couldn't clone log file")?; - /// Set file handle limit. const RECOMMENDED_FILE_LIMIT: isize = 8192; if !sysinfo::set_open_files_limit(RECOMMENDED_FILE_LIMIT) { eprintln!("WARNING: Unable to set file descriptor limit to recommended value: {RECOMMENDED_FILE_LIMIT}."); } - let runner = Runner::new("cargo") + let log_output_filepath = + proof_output_dirpath.join(format!("b{}_{}.log", start_block, end_block)); + + let proof_runner = Runner::new("cargo") .args(&[ "run", "--release", @@ -154,54 +140,40 @@ pub fn prove_via_rpc(args: ProveRpcArgs) -> Result<()> { "--max-retries", &args.max_retries.to_string(), ]) - .out(log_out) - .err(log_err); + .out(log_output_filepath)?; match args.mode { - RunMode::Test => runner.args(&["--use-test-config"]).run(), - RunMode::Prove => todo!(), - RunMode::Verify => todo!(), - } -} - -struct Runner { - cmd: String, - args: Vec, - out: Stdio, - err: Stdio, -} - -impl Runner { - fn new(cmd: impl Into) -> Self { - Self { - cmd: cmd.into(), - args: vec![], - out: Stdio::piped(), - err: Stdio::piped(), + RunMode::Test => { + set_var("ARITHMETIC_CIRCUIT_SIZE", "16..21"); + set_var("BYTE_PACKING_CIRCUIT_SIZE", "8..21"); + set_var("CPU_CIRCUIT_SIZE", "8..21"); + set_var("KECCAK_CIRCUIT_SIZE", "4..20"); + set_var("KECCAK_SPONGE_CIRCUIT_SIZE", "8..17"); + set_var("LOGIC_CIRCUIT_SIZE", "4..21"); + set_var("MEMORY_CIRCUIT_SIZE", "17..24"); + set_var("MEMORY_BEFORE_CIRCUIT_SIZE", "16..23"); + set_var("MEMORY_AFTER_CIRCUIT_SIZE", "7..23"); + proof_runner.args(&["--test-only"]).run() + } + RunMode::Prove => proof_runner.args(&["--use-test-config"]).run(), + RunMode::Verify => { + // Generate the proof. + proof_runner.args(&["--use-test-config"]).run()?; + + // Verify the proof. + let proof_filepath = proof_output_dirpath.join(format!("b{end_block}.proof")); + let verify_output_filepath = proof_output_dirpath.join("verify.out"); + let verify_runner = Runner::new("cargo") + .args(&[ + "run", + "--release", + "--package=zero", + "--bin=verifier", + "--", + "-f", + proof_filepath.to_str().unwrap(), + ]) + .out(verify_output_filepath)?; + verify_runner.run() } - } - - fn args(mut self, args: &[&str]) -> Self { - self.args.extend(args.iter().map(|s| s.to_string())); - self - } - - fn out(mut self, out: impl Into) -> Self { - self.out = out.into(); - self - } - - fn err(mut self, err: impl Into) -> Self { - self.err = err.into(); - self - } - - fn run(self) -> Result<()> { - let output = Command::new(&self.cmd) - .args(&self.args) - .stdout(self.out) - .stderr(self.err) - .output() - .context(format!("couldn't exec `{}`", &self.cmd))?; - todo!() } } diff --git a/scripts/runner.rs b/scripts/runner.rs new file mode 100644 index 000000000..e10956bac --- /dev/null +++ b/scripts/runner.rs @@ -0,0 +1,53 @@ +use std::{ + fs::File, + path::PathBuf, + process::{Command, Stdio}, +}; + +use anyhow::{Context as _, Result}; + +pub struct Runner { + cmd: String, + args: Vec, + stdout: Stdio, + stderr: Stdio, +} + +impl Runner { + /// Create a new runner with the given command. + pub fn new(cmd: impl Into) -> Self { + Self { + cmd: cmd.into(), + args: vec![], + stdout: Stdio::piped(), + stderr: Stdio::piped(), + } + } + + /// Add arguments to the command. + pub fn args(mut self, args: &[&str]) -> Self { + self.args.extend(args.iter().map(|s| s.to_string())); + self + } + + /// Create the file specified by `output_filepath` and set it as the stdout + /// and stderr of the command. + pub fn out(mut self, output_filepath: impl Into) -> Result { + let out = File::create(output_filepath.into())?; + let err = out.try_clone()?; + self.stdout = Stdio::from(out); + self.stderr = Stdio::from(err); + Ok(self) + } + + /// Run the command. + pub fn run(self) -> Result<()> { + let output = Command::new(&self.cmd) + .args(&self.args) + .stdout(self.stdout) + .stderr(self.stderr) + .output() + .context(format!("couldn't exec `{}`", &self.cmd))?; + todo!() + } +} diff --git a/scripts/xtask.rs b/scripts/xtask.rs index 0a28d5ef0..9786becca 100644 --- a/scripts/xtask.rs +++ b/scripts/xtask.rs @@ -2,6 +2,7 @@ mod outdated; mod prove_rpc; +mod runner; use anyhow::Result; use clap::Parser; From 34db2923994c90d46292c333454fe969f0af09f4 Mon Sep 17 00:00:00 2001 From: sergerad Date: Sat, 16 Nov 2024 13:33:49 +1300 Subject: [PATCH 06/22] Update CI and docs --- .github/workflows/jerigon-native.yml | 6 +++--- .github/workflows/jerigon-zero.yml | 6 +++--- scripts/prove_rpc.rs | 10 +++++----- scripts/runner.rs | 12 +++++++++--- zero/README.md | 16 +++++----------- 5 files changed, 25 insertions(+), 25 deletions(-) diff --git a/.github/workflows/jerigon-native.yml b/.github/workflows/jerigon-native.yml index ccfbdc005..d01eb77fa 100644 --- a/.github/workflows/jerigon-native.yml +++ b/.github/workflows/jerigon-native.yml @@ -1,4 +1,4 @@ ---- # Run and populate blockchain with transactions and generate proofs using native tracer +--- # Run and populate blockchain with transactions and generate proofs using native tracer name: Jerigon Integration @@ -76,14 +76,14 @@ jobs: run: | ETH_RPC_URL="$(kurtosis port print cancun-testnet el-2-erigon-lighthouse ws-rpc)" ulimit -n 8192 - OUTPUT_TO_TERMINAL=true ./scripts/prove_rpc.sh 1 15 $ETH_RPC_URL native 0 3000 100 test_only + cargo xtask prove-rpc -u $ETH_RPC_URL -s 1 -e 15 -t native -c 0 -b 3000 -r 100 -m test echo "Proving blocks in test_only mode finished" - name: Run prove blocks with native tracer in real mode run: | ETH_RPC_URL="$(kurtosis port print cancun-testnet el-2-erigon-lighthouse ws-rpc)" rm -rf proofs/* circuits/* ./proofs.json test.out verify.out leader.out - OUTPUT_TO_TERMINAL=true RUN_VERIFICATION=true ./scripts/prove_rpc.sh 4 7 $ETH_RPC_URL native 3 3000 100 + cargo xtask prove-rpc -u $ETH_RPC_URL -s 4 -e 7 -t native -c 3 -b 3000 -r 100 -m verify echo "Proving blocks in real mode finished" - name: Shut down network diff --git a/.github/workflows/jerigon-zero.yml b/.github/workflows/jerigon-zero.yml index 01e580438..74946f2d5 100644 --- a/.github/workflows/jerigon-zero.yml +++ b/.github/workflows/jerigon-zero.yml @@ -1,4 +1,4 @@ ---- # Run and populate blockchain with transactions and generate proofs using zero tracer +--- # Run and populate blockchain with transactions and generate proofs using zero tracer name: Jerigon Integration @@ -76,14 +76,14 @@ jobs: run: | ETH_RPC_URL="$(kurtosis port print cancun-testnet el-2-erigon-lighthouse ws-rpc)" ulimit -n 8192 - OUTPUT_TO_TERMINAL=true ./scripts/prove_rpc.sh 1 15 $ETH_RPC_URL jerigon 0 3000 100 test_only + cargo xtask prove-rpc -u $ETH_RPC_URL -s 1 -e 15 -t jerigon -c 0 -b 3000 -r 100 -m test echo "Proving blocks in test_only mode finished" - name: Run prove blocks with zero tracer in real mode run: | ETH_RPC_URL="$(kurtosis port print cancun-testnet el-2-erigon-lighthouse ws-rpc)" rm -rf proofs/* circuits/* ./proofs.json test.out verify.out leader.out - OUTPUT_TO_TERMINAL=true RUN_VERIFICATION=true ./scripts/prove_rpc.sh 2 5 $ETH_RPC_URL jerigon 1 3000 100 + cargo xtask prove-rpc -u $ETH_RPC_URL -s 2 -e 5 -t jerigon -c 1 -b 3000 -r 100 -m verify echo "Proving blocks in real mode finished" - name: Shut down network diff --git a/scripts/prove_rpc.rs b/scripts/prove_rpc.rs index 7603b7f95..f1db6f3ad 100644 --- a/scripts/prove_rpc.rs +++ b/scripts/prove_rpc.rs @@ -54,11 +54,11 @@ pub struct ProveRpcArgs { /// The end of the block range to prove (inclusive). #[arg(short = 'e', long)] end_block: Option, - /// Backoff in milliseconds for retry requests + /// Backoff in milliseconds for retry requests. #[arg(short = 'b', long, default_value_t = 0)] backoff: u64, - /// The maximum number of retries - #[arg(short = 'r', long, default_value_t = 0)] + /// The maximum number of retries. + #[arg(short = 'r', long, default_value_t = 7)] max_retries: u32, /// Whether to generate a proof and verify it or not. #[arg(short = 'm', long)] @@ -140,7 +140,7 @@ pub fn prove_via_rpc(args: ProveRpcArgs) -> Result<()> { "--max-retries", &args.max_retries.to_string(), ]) - .out(log_output_filepath)?; + .pipe(log_output_filepath)?; match args.mode { RunMode::Test => { set_var("ARITHMETIC_CIRCUIT_SIZE", "16..21"); @@ -172,7 +172,7 @@ pub fn prove_via_rpc(args: ProveRpcArgs) -> Result<()> { "-f", proof_filepath.to_str().unwrap(), ]) - .out(verify_output_filepath)?; + .pipe(verify_output_filepath)?; verify_runner.run() } } diff --git a/scripts/runner.rs b/scripts/runner.rs index e10956bac..d2b14367e 100644 --- a/scripts/runner.rs +++ b/scripts/runner.rs @@ -4,8 +4,9 @@ use std::{ process::{Command, Stdio}, }; -use anyhow::{Context as _, Result}; +use anyhow::{ensure, Context as _, Result}; +/// A means of running a command as a subprocess. pub struct Runner { cmd: String, args: Vec, @@ -32,7 +33,7 @@ impl Runner { /// Create the file specified by `output_filepath` and set it as the stdout /// and stderr of the command. - pub fn out(mut self, output_filepath: impl Into) -> Result { + pub fn pipe(mut self, output_filepath: impl Into) -> Result { let out = File::create(output_filepath.into())?; let err = out.try_clone()?; self.stdout = Stdio::from(out); @@ -48,6 +49,11 @@ impl Runner { .stderr(self.stderr) .output() .context(format!("couldn't exec `{}`", &self.cmd))?; - todo!() + ensure!( + output.status.success(), + "command failed with {}", + output.status + ); + Ok(()) } } diff --git a/zero/README.md b/zero/README.md index ddf60de92..a8a717935 100644 --- a/zero/README.md +++ b/zero/README.md @@ -422,16 +422,16 @@ For testing proof generation for blocks, the `testing` branch should be used. ### Proving Blocks -If you want to generate a full block proof, you can use `tools/prove_rpc.sh`: +If you want to generate a full block proof, you can use `cargo xtask prove-rpc`: ```sh -./prove_rpc.sh +cargo xtask prove-rpc -s -e -u -t -c -m ``` Which may look like this: ```sh -./prove_rpc.sh 17 18 http://127.0.0.1:8545 jerigon +cargo xtask prove-rpc -u "$ETH_RPC_URL" -s 17 -e 18 -t jerigon -c 16 -b 3000 -r 100 -m verify ``` Which will attempt to generate proofs for blocks `17` & `18` consecutively and incorporate the previous block proof during generation. @@ -444,16 +444,10 @@ A few other notes: ### Generating Witnesses Only -If you want to test a block without the high CPU & memory requirements that come with creating a full proof, you can instead generate only the witness using `tools/prove_rpc.sh` in the `test_only` mode: +If you want to test a block without the high CPU & memory requirements that come with creating a full proof, you can instead generate only the witness using `cargo xtask prove-rpc` in the `test` mode: ```sh -./prove_rpc.sh test_only -``` - -Filled in: - -```sh -./prove_rpc.sh 18299898 18299899 http://34.89.57.138:8545 jerigon 18299897 0 0 test_only +cargo xtask prove-rpc -u "$ETH_RPC_URL" -s 17 -e 18 -t jerigon -c 16 -b 3000 -r 100 -m test ``` Finally, note that both of these testing scripts force proof generation to be sequential by allowing only one worker. Because of this, this is not a realistic representation of performance but makes the debugging logs much easier to follow. From 4a3c8d2f64dd96a9a088bddde071debf9cdfd43d Mon Sep 17 00:00:00 2001 From: sergerad Date: Sat, 16 Nov 2024 20:49:57 +1300 Subject: [PATCH 07/22] Test flow functional --- scripts/prove_rpc.rs | 87 +++++++++++++++++++++++++------------------- scripts/runner.rs | 4 +- 2 files changed, 52 insertions(+), 39 deletions(-) diff --git a/scripts/prove_rpc.rs b/scripts/prove_rpc.rs index f1db6f3ad..fdf14216a 100644 --- a/scripts/prove_rpc.rs +++ b/scripts/prove_rpc.rs @@ -108,39 +108,36 @@ pub fn prove_via_rpc(args: ProveRpcArgs) -> Result<()> { eprintln!("WARNING: Unable to set file descriptor limit to recommended value: {RECOMMENDED_FILE_LIMIT}."); } - let log_output_filepath = - proof_output_dirpath.join(format!("b{}_{}.log", start_block, end_block)); - - let proof_runner = Runner::new("cargo") - .args(&[ - "run", - "--release", - "--package=zero", - "--bin=leader", - "--", - "--runtime=in-memory", - "--load-strategy=on-demand", - "--proof-output-dir", - proof_output_dirpath.to_str().unwrap(), - "--block-batch-size", - &args.block_batch_size.to_string(), - "rpc", - "--rpc-type", - &args.rpc_type.to_string(), - "--rpc-url", - args.rpc_url.as_ref(), - "--start-block", - &start_block.to_string(), - "--checkpoint-block", - &checkpoint_block.to_string(), - "--end-block", - &end_block.to_string(), - "--backoff", - &args.backoff.to_string(), - "--max-retries", - &args.max_retries.to_string(), - ]) - .pipe(log_output_filepath)?; + let cmd_args = &[ + "run", + "--release", + "--package=zero", + "--bin=leader", + "--", + "--use-test-config", + "--runtime=in-memory", + "--load-strategy=on-demand", + "--proof-output-dir", + proof_output_dirpath.to_str().unwrap(), + "--block-batch-size", + &args.block_batch_size.to_string(), + "rpc", + "--rpc-type", + &args.rpc_type.to_string(), + "--rpc-url", + args.rpc_url.as_ref(), + "--start-block", + &block_string(start_block), + "--checkpoint-block", + &block_string(checkpoint_block), + "--end-block", + &block_string(end_block), + "--backoff", + &args.backoff.to_string(), + "--max-retries", + &args.max_retries.to_string(), + ]; + //.pipe(log_output_filepath)?; match args.mode { RunMode::Test => { set_var("ARITHMETIC_CIRCUIT_SIZE", "16..21"); @@ -152,15 +149,23 @@ pub fn prove_via_rpc(args: ProveRpcArgs) -> Result<()> { set_var("MEMORY_CIRCUIT_SIZE", "17..24"); set_var("MEMORY_BEFORE_CIRCUIT_SIZE", "16..23"); set_var("MEMORY_AFTER_CIRCUIT_SIZE", "7..23"); - proof_runner.args(&["--test-only"]).run() + let cmd_args = cmd_args.map(|arg| { + if arg == "--use-test-config" { + "--test-only" + } else { + arg + } + }); + Runner::new("cargo").args(&cmd_args).run() } - RunMode::Prove => proof_runner.args(&["--use-test-config"]).run(), + RunMode::Prove => Runner::new("cargo").args(cmd_args).run(), RunMode::Verify => { // Generate the proof. - proof_runner.args(&["--use-test-config"]).run()?; + Runner::new("cargo").args(cmd_args).run()?; // Verify the proof. - let proof_filepath = proof_output_dirpath.join(format!("b{end_block}.proof")); + let proof_filepath = + proof_output_dirpath.join(format!("b{}.proof", block_string(end_block))); let verify_output_filepath = proof_output_dirpath.join("verify.out"); let verify_runner = Runner::new("cargo") .args(&[ @@ -177,3 +182,11 @@ pub fn prove_via_rpc(args: ProveRpcArgs) -> Result<()> { } } } + +/// Converts a block ID to an appropriate string based on its variant. +fn block_string(block: BlockId) -> String { + match block { + BlockId::Number(number) => number.as_number().unwrap().to_string(), + BlockId::Hash(hash) => hash.to_string(), + } +} diff --git a/scripts/runner.rs b/scripts/runner.rs index d2b14367e..dc5aab081 100644 --- a/scripts/runner.rs +++ b/scripts/runner.rs @@ -20,8 +20,8 @@ impl Runner { Self { cmd: cmd.into(), args: vec![], - stdout: Stdio::piped(), - stderr: Stdio::piped(), + stdout: Stdio::inherit(), + stderr: Stdio::inherit(), } } From 814c33febc803730921e9e41c3dc874bdd5500ce Mon Sep 17 00:00:00 2001 From: sergerad Date: Tue, 19 Nov 2024 16:30:51 +1300 Subject: [PATCH 08/22] Refactor cmd logic and fix zkproof file name --- scripts/prove_rpc.rs | 61 ++++++++++++++++++++++++++++++-------------- 1 file changed, 42 insertions(+), 19 deletions(-) diff --git a/scripts/prove_rpc.rs b/scripts/prove_rpc.rs index fdf14216a..d9aee985a 100644 --- a/scripts/prove_rpc.rs +++ b/scripts/prove_rpc.rs @@ -108,13 +108,8 @@ pub fn prove_via_rpc(args: ProveRpcArgs) -> Result<()> { eprintln!("WARNING: Unable to set file descriptor limit to recommended value: {RECOMMENDED_FILE_LIMIT}."); } - let cmd_args = &[ - "run", - "--release", - "--package=zero", - "--bin=leader", - "--", - "--use-test-config", + // Construct common args used for all run modes. + let leader_args = &[ "--runtime=in-memory", "--load-strategy=on-demand", "--proof-output-dir", @@ -137,7 +132,8 @@ pub fn prove_via_rpc(args: ProveRpcArgs) -> Result<()> { "--max-retries", &args.max_retries.to_string(), ]; - //.pipe(log_output_filepath)?; + + // Run the appropriate command based on the run mode. match args.mode { RunMode::Test => { set_var("ARITHMETIC_CIRCUIT_SIZE", "16..21"); @@ -149,23 +145,21 @@ pub fn prove_via_rpc(args: ProveRpcArgs) -> Result<()> { set_var("MEMORY_CIRCUIT_SIZE", "17..24"); set_var("MEMORY_BEFORE_CIRCUIT_SIZE", "16..23"); set_var("MEMORY_AFTER_CIRCUIT_SIZE", "7..23"); - let cmd_args = cmd_args.map(|arg| { - if arg == "--use-test-config" { - "--test-only" - } else { - arg - } - }); - Runner::new("cargo").args(&cmd_args).run() + + Runner::new("cargo") + .args(&test_command_args(leader_args)) + .run() } - RunMode::Prove => Runner::new("cargo").args(cmd_args).run(), + RunMode::Prove => Runner::new("cargo").args(&command_args(leader_args)).run(), RunMode::Verify => { // Generate the proof. - Runner::new("cargo").args(cmd_args).run()?; + Runner::new("cargo") + .args(&command_args(leader_args)) + .run()?; // Verify the proof. let proof_filepath = - proof_output_dirpath.join(format!("b{}.proof", block_string(end_block))); + proof_output_dirpath.join(format!("b{}.zkproof", block_string(end_block))); let verify_output_filepath = proof_output_dirpath.join("verify.out"); let verify_runner = Runner::new("cargo") .args(&[ @@ -190,3 +184,32 @@ fn block_string(block: BlockId) -> String { BlockId::Hash(hash) => hash.to_string(), } } + +/// Returns the command arguments for running the leader binary in test mode. +fn test_command_args<'a>(leader_args: &'a [&str]) -> Vec<&'a str> { + let mut args = Vec::from(&[ + "run", + "--release", + "--package=zero", + "--bin=leader", + "--", + "--test-only", + ]); + args.extend_from_slice(leader_args); + args +} + +/// Returns the command arguments for running the leader binary in prove or +/// verify mode. +fn command_args<'a>(leader_args: &'a [&str]) -> Vec<&'a str> { + let mut args = Vec::from(&[ + "run", + "--release", + "--package=zero", + "--bin=leader", + "--", + "--use-test-config", + ]); + args.extend_from_slice(leader_args); + args +} From 5833ca7a8ebec8360529df2b4764ed6a5937fee7 Mon Sep 17 00:00:00 2001 From: sergerad Date: Tue, 19 Nov 2024 19:16:42 +1300 Subject: [PATCH 09/22] Verify output file --- scripts/prove_rpc.rs | 22 +++++++++++++++++++--- scripts/runner.rs | 6 +++--- 2 files changed, 22 insertions(+), 6 deletions(-) diff --git a/scripts/prove_rpc.rs b/scripts/prove_rpc.rs index d9aee985a..34b7abafc 100644 --- a/scripts/prove_rpc.rs +++ b/scripts/prove_rpc.rs @@ -1,7 +1,8 @@ use std::{ env::set_var, fmt::Display, - fs::create_dir_all, + fs::{create_dir_all, File}, + io::{BufRead, BufReader}, path::{Path, PathBuf}, }; @@ -171,8 +172,11 @@ pub fn prove_via_rpc(args: ProveRpcArgs) -> Result<()> { "-f", proof_filepath.to_str().unwrap(), ]) - .pipe(verify_output_filepath)?; - verify_runner.run() + .pipe(&verify_output_filepath)?; + verify_runner.run()?; + + // Validate the proof output file. + verify_proof_output(&verify_output_filepath) } } } @@ -213,3 +217,15 @@ fn command_args<'a>(leader_args: &'a [&str]) -> Vec<&'a str> { args.extend_from_slice(leader_args); args } + +/// Checks that the output file contains the expected success message. +fn verify_proof_output(verify_output_filepath: &Path) -> Result<()> { + let verify_output_file = File::open(verify_output_filepath)?; + let reader = BufReader::new(verify_output_file); + for line in reader.lines() { + if line? == "All proofs verified successfully!" { + return Ok(()); + } + } + anyhow::bail!("Proof verification failed!") +} diff --git a/scripts/runner.rs b/scripts/runner.rs index dc5aab081..0809a0abe 100644 --- a/scripts/runner.rs +++ b/scripts/runner.rs @@ -1,6 +1,6 @@ use std::{ fs::File, - path::PathBuf, + path::{Path, PathBuf}, process::{Command, Stdio}, }; @@ -33,8 +33,8 @@ impl Runner { /// Create the file specified by `output_filepath` and set it as the stdout /// and stderr of the command. - pub fn pipe(mut self, output_filepath: impl Into) -> Result { - let out = File::create(output_filepath.into())?; + pub fn pipe(mut self, output_filepath: &Path) -> Result { + let out = File::create(output_filepath)?; let err = out.try_clone()?; self.stdout = Stdio::from(out); self.stderr = Stdio::from(err); From 2220ddeafabd4ca5aa33c3380a157ef0698dbecc Mon Sep 17 00:00:00 2001 From: sergerad Date: Tue, 19 Nov 2024 19:28:21 +1300 Subject: [PATCH 10/22] Fix import --- scripts/runner.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/runner.rs b/scripts/runner.rs index 0809a0abe..6e3407305 100644 --- a/scripts/runner.rs +++ b/scripts/runner.rs @@ -1,6 +1,6 @@ use std::{ fs::File, - path::{Path, PathBuf}, + path::Path, process::{Command, Stdio}, }; From c3bc9f84ae9bcd97ce9dd83f56129c9e12dafe41 Mon Sep 17 00:00:00 2001 From: sergerad Date: Tue, 19 Nov 2024 19:43:18 +1300 Subject: [PATCH 11/22] RM superfluous check --- scripts/prove_rpc.rs | 20 ++------------------ 1 file changed, 2 insertions(+), 18 deletions(-) diff --git a/scripts/prove_rpc.rs b/scripts/prove_rpc.rs index 34b7abafc..489398898 100644 --- a/scripts/prove_rpc.rs +++ b/scripts/prove_rpc.rs @@ -1,8 +1,7 @@ use std::{ env::set_var, fmt::Display, - fs::{create_dir_all, File}, - io::{BufRead, BufReader}, + fs::create_dir_all, path::{Path, PathBuf}, }; @@ -173,10 +172,7 @@ pub fn prove_via_rpc(args: ProveRpcArgs) -> Result<()> { proof_filepath.to_str().unwrap(), ]) .pipe(&verify_output_filepath)?; - verify_runner.run()?; - - // Validate the proof output file. - verify_proof_output(&verify_output_filepath) + verify_runner.run() } } } @@ -217,15 +213,3 @@ fn command_args<'a>(leader_args: &'a [&str]) -> Vec<&'a str> { args.extend_from_slice(leader_args); args } - -/// Checks that the output file contains the expected success message. -fn verify_proof_output(verify_output_filepath: &Path) -> Result<()> { - let verify_output_file = File::open(verify_output_filepath)?; - let reader = BufReader::new(verify_output_file); - for line in reader.lines() { - if line? == "All proofs verified successfully!" { - return Ok(()); - } - } - anyhow::bail!("Proof verification failed!") -} From 8d1d3b26b885f29d605968bcb6503f3bafa0f764 Mon Sep 17 00:00:00 2001 From: sergerad Date: Tue, 19 Nov 2024 19:53:24 +1300 Subject: [PATCH 12/22] Rename runner to process --- scripts/{runner.rs => process.rs} | 4 ++-- scripts/prove_rpc.rs | 10 +++++----- scripts/xtask.rs | 2 +- 3 files changed, 8 insertions(+), 8 deletions(-) rename scripts/{runner.rs => process.rs} (97%) diff --git a/scripts/runner.rs b/scripts/process.rs similarity index 97% rename from scripts/runner.rs rename to scripts/process.rs index 6e3407305..525549361 100644 --- a/scripts/runner.rs +++ b/scripts/process.rs @@ -7,14 +7,14 @@ use std::{ use anyhow::{ensure, Context as _, Result}; /// A means of running a command as a subprocess. -pub struct Runner { +pub struct Process { cmd: String, args: Vec, stdout: Stdio, stderr: Stdio, } -impl Runner { +impl Process { /// Create a new runner with the given command. pub fn new(cmd: impl Into) -> Self { Self { diff --git a/scripts/prove_rpc.rs b/scripts/prove_rpc.rs index 489398898..d3d1fb86f 100644 --- a/scripts/prove_rpc.rs +++ b/scripts/prove_rpc.rs @@ -9,7 +9,7 @@ use alloy::{eips::BlockId, transports::http::reqwest::Url}; use anyhow::Result; use clap::{arg, Args, ValueEnum, ValueHint}; -use crate::runner::Runner; +use crate::process::Process; #[derive(ValueEnum, Clone)] enum RpcType { @@ -146,14 +146,14 @@ pub fn prove_via_rpc(args: ProveRpcArgs) -> Result<()> { set_var("MEMORY_BEFORE_CIRCUIT_SIZE", "16..23"); set_var("MEMORY_AFTER_CIRCUIT_SIZE", "7..23"); - Runner::new("cargo") + Process::new("cargo") .args(&test_command_args(leader_args)) .run() } - RunMode::Prove => Runner::new("cargo").args(&command_args(leader_args)).run(), + RunMode::Prove => Process::new("cargo").args(&command_args(leader_args)).run(), RunMode::Verify => { // Generate the proof. - Runner::new("cargo") + Process::new("cargo") .args(&command_args(leader_args)) .run()?; @@ -161,7 +161,7 @@ pub fn prove_via_rpc(args: ProveRpcArgs) -> Result<()> { let proof_filepath = proof_output_dirpath.join(format!("b{}.zkproof", block_string(end_block))); let verify_output_filepath = proof_output_dirpath.join("verify.out"); - let verify_runner = Runner::new("cargo") + let verify_runner = Process::new("cargo") .args(&[ "run", "--release", diff --git a/scripts/xtask.rs b/scripts/xtask.rs index 9786becca..02b21f809 100644 --- a/scripts/xtask.rs +++ b/scripts/xtask.rs @@ -2,7 +2,7 @@ mod outdated; mod prove_rpc; -mod runner; +mod process; use anyhow::Result; use clap::Parser; From 9f7dfb4bf0262a40d9517e06eedd8e0583c0b248 Mon Sep 17 00:00:00 2001 From: sergerad Date: Tue, 19 Nov 2024 20:09:31 +1300 Subject: [PATCH 13/22] Required flags to args --- .github/workflows/jerigon-native.yml | 4 ++-- .github/workflows/jerigon-zero.yml | 4 ++-- scripts/prove_rpc.rs | 12 ++++++------ 3 files changed, 10 insertions(+), 10 deletions(-) diff --git a/.github/workflows/jerigon-native.yml b/.github/workflows/jerigon-native.yml index d01eb77fa..c49e3b943 100644 --- a/.github/workflows/jerigon-native.yml +++ b/.github/workflows/jerigon-native.yml @@ -76,14 +76,14 @@ jobs: run: | ETH_RPC_URL="$(kurtosis port print cancun-testnet el-2-erigon-lighthouse ws-rpc)" ulimit -n 8192 - cargo xtask prove-rpc -u $ETH_RPC_URL -s 1 -e 15 -t native -c 0 -b 3000 -r 100 -m test + cargo xtask prove-rpc "$ETH_RPC_URL" native test 1 -e 15 -c 0 -b 3000 -r 100 echo "Proving blocks in test_only mode finished" - name: Run prove blocks with native tracer in real mode run: | ETH_RPC_URL="$(kurtosis port print cancun-testnet el-2-erigon-lighthouse ws-rpc)" rm -rf proofs/* circuits/* ./proofs.json test.out verify.out leader.out - cargo xtask prove-rpc -u $ETH_RPC_URL -s 4 -e 7 -t native -c 3 -b 3000 -r 100 -m verify + cargo xtask prove-rpc "$ETH_RPC_URL" native verify 4 -e 7 -c 3 -b 3000 -r 100 echo "Proving blocks in real mode finished" - name: Shut down network diff --git a/.github/workflows/jerigon-zero.yml b/.github/workflows/jerigon-zero.yml index 74946f2d5..3e075a934 100644 --- a/.github/workflows/jerigon-zero.yml +++ b/.github/workflows/jerigon-zero.yml @@ -76,14 +76,14 @@ jobs: run: | ETH_RPC_URL="$(kurtosis port print cancun-testnet el-2-erigon-lighthouse ws-rpc)" ulimit -n 8192 - cargo xtask prove-rpc -u $ETH_RPC_URL -s 1 -e 15 -t jerigon -c 0 -b 3000 -r 100 -m test + cargo xtask prove-rpc "$ETH_RPC_URL" jerigon test 1 -e 15 -c 0 -b 3000 -r 100 echo "Proving blocks in test_only mode finished" - name: Run prove blocks with zero tracer in real mode run: | ETH_RPC_URL="$(kurtosis port print cancun-testnet el-2-erigon-lighthouse ws-rpc)" rm -rf proofs/* circuits/* ./proofs.json test.out verify.out leader.out - cargo xtask prove-rpc -u $ETH_RPC_URL -s 2 -e 5 -t jerigon -c 1 -b 3000 -r 100 -m verify + cargo xtask prove-rpc "$ETH_RPC_URL" jerigon verify 2 -e 5 -c 1 -b 3000 -r 100 echo "Proving blocks in real mode finished" - name: Shut down network diff --git a/scripts/prove_rpc.rs b/scripts/prove_rpc.rs index d3d1fb86f..785f0c5fb 100644 --- a/scripts/prove_rpc.rs +++ b/scripts/prove_rpc.rs @@ -40,13 +40,16 @@ enum RunMode { #[derive(Args)] pub struct ProveRpcArgs { /// The node RPC URL. - #[arg(short = 'u', value_hint = ValueHint::Url)] + #[arg(value_hint = ValueHint::Url)] rpc_url: Url, /// The RPC type (jerigon or native). - #[arg(short = 't', long)] + #[arg()] rpc_type: RpcType, + /// Whether to generate a proof and verify it or not. + #[arg()] + mode: RunMode, /// The start of the block range to prove (inclusive). - #[arg(short = 's', long)] + #[arg()] start_block: BlockId, /// The end of the block range to prove. If None, start_block-1 is used. #[arg(short = 'c', long)] @@ -60,9 +63,6 @@ pub struct ProveRpcArgs { /// The maximum number of retries. #[arg(short = 'r', long, default_value_t = 7)] max_retries: u32, - /// Whether to generate a proof and verify it or not. - #[arg(short = 'm', long)] - mode: RunMode, /// The batch size for block fetching. #[arg(long, default_value_t = 8)] block_batch_size: u32, From a90e6ab56461985e5d3cd571d745be3a0ffa8d5d Mon Sep 17 00:00:00 2001 From: sergerad Date: Tue, 19 Nov 2024 20:13:13 +1300 Subject: [PATCH 14/22] Fix spacing in actions yaml --- .github/workflows/jerigon-native.yml | 2 +- .github/workflows/jerigon-zero.yml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/jerigon-native.yml b/.github/workflows/jerigon-native.yml index c49e3b943..f48648bd1 100644 --- a/.github/workflows/jerigon-native.yml +++ b/.github/workflows/jerigon-native.yml @@ -1,4 +1,4 @@ ---- # Run and populate blockchain with transactions and generate proofs using native tracer +--- # Run and populate blockchain with transactions and generate proofs using native tracer name: Jerigon Integration diff --git a/.github/workflows/jerigon-zero.yml b/.github/workflows/jerigon-zero.yml index 3e075a934..bf611a269 100644 --- a/.github/workflows/jerigon-zero.yml +++ b/.github/workflows/jerigon-zero.yml @@ -1,4 +1,4 @@ ---- # Run and populate blockchain with transactions and generate proofs using zero tracer +--- # Run and populate blockchain with transactions and generate proofs using zero tracer name: Jerigon Integration From 9f5e31a2d061bd3d8f5afa923984321d0226be58 Mon Sep 17 00:00:00 2001 From: sergerad Date: Tue, 19 Nov 2024 20:16:02 +1300 Subject: [PATCH 15/22] Lint fix --- scripts/xtask.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/xtask.rs b/scripts/xtask.rs index 02b21f809..edf853117 100644 --- a/scripts/xtask.rs +++ b/scripts/xtask.rs @@ -1,8 +1,8 @@ //! General purpose scripts for development mod outdated; -mod prove_rpc; mod process; +mod prove_rpc; use anyhow::Result; use clap::Parser; From 6b20299904cc755e004b8e21914a72a809131f1f Mon Sep 17 00:00:00 2001 From: sergerad Date: Tue, 19 Nov 2024 20:19:47 +1300 Subject: [PATCH 16/22] Fix comments and readme and remove old script --- scripts/prove_rpc.rs | 3 +- scripts/prove_rpc.sh | 192 ------------------------------------------- zero/README.md | 4 +- 3 files changed, 4 insertions(+), 195 deletions(-) delete mode 100755 scripts/prove_rpc.sh diff --git a/scripts/prove_rpc.rs b/scripts/prove_rpc.rs index 785f0c5fb..f8b1c57b0 100644 --- a/scripts/prove_rpc.rs +++ b/scripts/prove_rpc.rs @@ -72,6 +72,7 @@ pub struct ProveRpcArgs { output_dir: PathBuf, } +/// Run leader binary to prove a block range via RPC. pub fn prove_via_rpc(args: ProveRpcArgs) -> Result<()> { // Set rustc environment variables. set_var("RUST_MIN_STACK", "33554432"); @@ -102,7 +103,7 @@ pub fn prove_via_rpc(args: ProveRpcArgs) -> Result<()> { if !proof_output_dirpath.exists() { create_dir_all(proof_output_dirpath)?; } - /// Set file handle limit. + // Set file handle limit. const RECOMMENDED_FILE_LIMIT: isize = 8192; if !sysinfo::set_open_files_limit(RECOMMENDED_FILE_LIMIT) { eprintln!("WARNING: Unable to set file descriptor limit to recommended value: {RECOMMENDED_FILE_LIMIT}."); diff --git a/scripts/prove_rpc.sh b/scripts/prove_rpc.sh deleted file mode 100755 index d5c072c3e..000000000 --- a/scripts/prove_rpc.sh +++ /dev/null @@ -1,192 +0,0 @@ -#!/bin/bash - -# Args: -# 1 --> Start block (number in decimal or block hash with prefix 0x). E.g. `1234` or `0x1d5e7a08dd1f4ce7fa52afe7f4960d78e82e508c874838dee594d5300b8df625`. -# 2 --> End block (number or hash, inclusive). Same format as start block. -# 3 --> Rpc endpoint:port (eg. http://35.246.1.96:8545) -# 4 --> Rpc type (eg. jerigon / native) -# 5 --> Checkpoint block (number or hash). If argument is missing, start block predecessor will be used. -# 6 --> Backoff in milliseconds (optional [default: 0]) -# 7 --> Number of retries (optional [default: 0]) -# 8 --> Test run only flag `test_only` (optional) - -export RUST_MIN_STACK=33554432 -export RUST_BACKTRACE=1 -export RUST_LOG=info -# Script users are running locally, and might benefit from extra perf. -# See also .cargo/config.toml. -export RUSTFLAGS='-C target-cpu=native -Zlinker-features=-lld' - -BLOCK_BATCH_SIZE="${BLOCK_BATCH_SIZE:-8}" -echo "Block batch size: $BLOCK_BATCH_SIZE" - -# Circuit sizes only matter in non test_only mode. -if ! [[ $8 == "test_only" ]]; then - export ARITHMETIC_CIRCUIT_SIZE="16..21" - export BYTE_PACKING_CIRCUIT_SIZE="8..21" - export CPU_CIRCUIT_SIZE="8..21" - export KECCAK_CIRCUIT_SIZE="4..20" - export KECCAK_SPONGE_CIRCUIT_SIZE="8..17" - export LOGIC_CIRCUIT_SIZE="4..21" - export MEMORY_CIRCUIT_SIZE="17..24" - export MEMORY_BEFORE_CIRCUIT_SIZE="16..23" - export MEMORY_AFTER_CIRCUIT_SIZE="7..23" -fi - -REPO_ROOT=$(git rev-parse --show-toplevel) - -PROOF_OUTPUT_DIR="${REPO_ROOT}/proofs" -OUT_LOG_PATH="${PROOF_OUTPUT_DIR}/b$1_$2.log" -ALWAYS_WRITE_LOGS=0 # Change this to `1` if you always want logs to be written. - -START_BLOCK=$1 -END_BLOCK=$2 -NODE_RPC_URL=$3 -NODE_RPC_TYPE=$4 -CHECKPOINT_BLOCK=$5 -BACKOFF=${6:-0} -RETRIES=${7:-0} - -# Sometimes we need to override file logging, e.g. in the CI run -OUTPUT_TO_TERMINAL="${OUTPUT_TO_TERMINAL:-false}" -# Only generate proof by default -RUN_VERIFICATION="${RUN_VERIFICATION:-false}" - -# Recommended soft file handle limit. Will warn if it is set lower. -RECOMMENDED_FILE_HANDLE_LIMIT=8192 - -mkdir -p "$PROOF_OUTPUT_DIR" - -# Handle checkpoint block arg -if [ -n "$CHECKPOINT_BLOCK" ] ; then - # Checkpoint block provided, pass it to the prover as a flag - PREV_PROOF_EXTRA_ARG="--checkpoint-block $CHECKPOINT_BLOCK" -else - # Checkpoint block not provided, but is required for hash-based start block - if [[ $START_BLOCK == 0x* ]]; then - echo "Checkpoint block is required when specifying blocks by hash" - exit 1 - fi - - # Checkpoint block not provided, deduce proof starting point from the start block - if [[ $1 -gt 1 ]]; then - prev_proof_num=$(($1-1)) - PREV_PROOF_EXTRA_ARG="-f ${PROOF_OUTPUT_DIR}/b${prev_proof_num}.zkproof" - fi -fi - -# Print out a warning if the we're using `native` and our file descriptor limit is too low. Don't bother if we can't find `ulimit`. -if [ "$(command -v ulimit)" ] && [ "$NODE_RPC_TYPE" == "native" ] -then - file_desc_limit=$(ulimit -n) - - if [[ $file_desc_limit -lt $RECOMMENDED_FILE_HANDLE_LIMIT ]] - then - echo "WARNING: Maximum file descriptor limit may be too low to run native mode (current: $file_desc_limit, Recommended: ${RECOMMENDED_FILE_HANDLE_LIMIT}). - Consider increasing it with: - - ulimit -n ${RECOMMENDED_FILE_HANDLE_LIMIT}" - fi -fi - -# If we set test_only flag, we'll generate a dummy -# proof. This is useful for quickly testing decoding and all of the -# other non-proving code. -if [[ $8 == "test_only" ]]; then - # test only run - echo "Proving blocks from ($START_BLOCK) to ($END_BLOCK)" - command="cargo r --release --package zero --bin leader -- \ ---test-only \ ---runtime in-memory \ ---load-strategy on-demand \ ---proof-output-dir $PROOF_OUTPUT_DIR \ ---block-batch-size $BLOCK_BATCH_SIZE \ -rpc \ ---rpc-type $NODE_RPC_TYPE \ ---rpc-url $NODE_RPC_URL \ ---start-block $START_BLOCK \ ---end-block $END_BLOCK \ ---backoff $BACKOFF \ ---max-retries $RETRIES \ -$PREV_PROOF_EXTRA_ARG" - - if [ "$OUTPUT_TO_TERMINAL" = true ]; then - eval "$command" - retVal=$? - echo -e "Proof witness generation finished with result: $retVal" - exit $retVal - else - eval "$command" > "$OUT_LOG_PATH" 2>&1 - if grep -q 'All proof witnesses have been generated successfully.' "$OUT_LOG_PATH"; then - echo -e "Success - Note this was just a test, not a proof" - # Remove the log on success if we don't want to keep it. - if [ $ALWAYS_WRITE_LOGS -ne 1 ]; then - rm "$OUT_LOG_PATH" - fi - exit - else - echo "Failed to create proof witnesses. See $OUT_LOG_PATH for more details." - exit 1 - fi - fi -else - # normal run - echo "Proving blocks from ($START_BLOCK) to ($END_BLOCK)" - command="cargo r --release --package zero --bin leader -- \ ---runtime in-memory \ ---use-test-config \ ---load-strategy on-demand \ ---proof-output-dir $PROOF_OUTPUT_DIR \ ---block-batch-size $BLOCK_BATCH_SIZE \ -rpc \ ---rpc-type $NODE_RPC_TYPE \ ---rpc-url $3 \ ---start-block $START_BLOCK \ ---end-block $END_BLOCK \ ---backoff $BACKOFF \ ---max-retries $RETRIES \ -$PREV_PROOF_EXTRA_ARG " - - if [ "$OUTPUT_TO_TERMINAL" = true ]; then - eval "$command" - echo -e "Proof generation finished with result: $?" - else - eval "$command" > "$OUT_LOG_PATH" 2>&1 - retVal=$? - if [ $retVal -ne 0 ]; then - # Some error occurred, display the logs and exit. - cat "$OUT_LOG_PATH" - echo "Error occurred. See $OUT_LOG_PATH for more details." - exit $retVal - else - # Remove the log on success if we don't want to keep it. - if [ $ALWAYS_WRITE_LOGS -ne 1 ]; then - rm "$OUT_LOG_PATH" - fi - fi - proof_count=$(grep -c 'INFO zero::prover: Proving block \d' < "$OUT_LOG_PATH") - echo "Successfully generated $proof_count proofs!" - fi -fi - - -# If we're running the verification, we'll do it here. -if [ "$RUN_VERIFICATION" = true ]; then - echo "Running the verification for the last proof..." - - proof_file_name=$PROOF_OUTPUT_DIR/b$END_BLOCK.zkproof - echo "Verifying the proof of the latest block in the interval:" "$proof_file_name" - cargo r --release --package zero --bin verifier -- -f "$proof_file_name" > "$PROOF_OUTPUT_DIR/verify.out" 2>&1 - - if grep -q 'All proofs verified successfully!' "$PROOF_OUTPUT_DIR/verify.out"; then - echo "$proof_file_name verified successfully!"; - rm "$PROOF_OUTPUT_DIR/verify.out" - else - # Some error occurred with verification, display the logs and exit. - cat "$PROOF_OUTPUT_DIR/verify.out" - echo "There was an issue with proof verification. See $PROOF_OUTPUT_DIR/verify.out for more details."; - exit 1 - fi -else - echo "Skipping verification..." -fi diff --git a/zero/README.md b/zero/README.md index a8a717935..b5a38abdc 100644 --- a/zero/README.md +++ b/zero/README.md @@ -425,7 +425,7 @@ For testing proof generation for blocks, the `testing` branch should be used. If you want to generate a full block proof, you can use `cargo xtask prove-rpc`: ```sh -cargo xtask prove-rpc -s -e -u -t -c -m +cargo xtask prove-rpc -e -c ``` Which may look like this: @@ -447,7 +447,7 @@ A few other notes: If you want to test a block without the high CPU & memory requirements that come with creating a full proof, you can instead generate only the witness using `cargo xtask prove-rpc` in the `test` mode: ```sh -cargo xtask prove-rpc -u "$ETH_RPC_URL" -s 17 -e 18 -t jerigon -c 16 -b 3000 -r 100 -m test +cargo xtask prove-rpc "$ETH_RPC_URL" jerigon test 17 -e 18 -c 16 -b 3000 -r 100 ``` Finally, note that both of these testing scripts force proof generation to be sequential by allowing only one worker. Because of this, this is not a realistic representation of performance but makes the debugging logs much easier to follow. From 84d710f40a771ac6d575f9735010cd784e2695ba Mon Sep 17 00:00:00 2001 From: sergerad Date: Tue, 19 Nov 2024 21:36:22 +1300 Subject: [PATCH 17/22] Coalesce commands fns --- scripts/prove_rpc.rs | 46 +++++++++++++------------------------------- 1 file changed, 13 insertions(+), 33 deletions(-) diff --git a/scripts/prove_rpc.rs b/scripts/prove_rpc.rs index f8b1c57b0..e0c3427c5 100644 --- a/scripts/prove_rpc.rs +++ b/scripts/prove_rpc.rs @@ -26,7 +26,7 @@ impl Display for RpcType { } } -#[derive(ValueEnum, Clone)] +#[derive(ValueEnum, Copy, Clone)] enum RunMode { /// Dummy proof is generated. Useful for quickly testing decoding and /// all other non-proving logic. @@ -133,6 +133,7 @@ pub fn prove_via_rpc(args: ProveRpcArgs) -> Result<()> { "--max-retries", &args.max_retries.to_string(), ]; + let cmd_args = command_args(args.mode, leader_args); // Run the appropriate command based on the run mode. match args.mode { @@ -147,16 +148,12 @@ pub fn prove_via_rpc(args: ProveRpcArgs) -> Result<()> { set_var("MEMORY_BEFORE_CIRCUIT_SIZE", "16..23"); set_var("MEMORY_AFTER_CIRCUIT_SIZE", "7..23"); - Process::new("cargo") - .args(&test_command_args(leader_args)) - .run() + Process::new("cargo").args(&cmd_args).run() } - RunMode::Prove => Process::new("cargo").args(&command_args(leader_args)).run(), + RunMode::Prove => Process::new("cargo").args(&cmd_args).run(), RunMode::Verify => { // Generate the proof. - Process::new("cargo") - .args(&command_args(leader_args)) - .run()?; + Process::new("cargo").args(&cmd_args).run()?; // Verify the proof. let proof_filepath = @@ -186,31 +183,14 @@ fn block_string(block: BlockId) -> String { } } -/// Returns the command arguments for running the leader binary in test mode. -fn test_command_args<'a>(leader_args: &'a [&str]) -> Vec<&'a str> { - let mut args = Vec::from(&[ - "run", - "--release", - "--package=zero", - "--bin=leader", - "--", - "--test-only", - ]); - args.extend_from_slice(leader_args); - args -} - -/// Returns the command arguments for running the leader binary in prove or -/// verify mode. -fn command_args<'a>(leader_args: &'a [&str]) -> Vec<&'a str> { - let mut args = Vec::from(&[ - "run", - "--release", - "--package=zero", - "--bin=leader", - "--", - "--use-test-config", - ]); +/// Constructs the full command arguments for running the leader binary with +/// cargo. +fn command_args<'a>(mode: RunMode, leader_args: &'a [&str]) -> Vec<&'a str> { + let mut args = Vec::from(&["run", "--release", "--package=zero", "--bin=leader", "--"]); + match mode { + RunMode::Prove | RunMode::Verify => args.push("--use-test-config"), + RunMode::Test => args.push("--test-only"), + } args.extend_from_slice(leader_args); args } From 598f3a17e8b4f13ec93196dc6967ddca5a0bba8c Mon Sep 17 00:00:00 2001 From: sergerad Date: Wed, 20 Nov 2024 19:24:36 +1300 Subject: [PATCH 18/22] Initial PR fixes before arg and process refactor --- scripts/process.rs | 6 +++--- scripts/prove_rpc.rs | 43 +++++++++++++++++-------------------------- 2 files changed, 20 insertions(+), 29 deletions(-) diff --git a/scripts/process.rs b/scripts/process.rs index 525549361..a2739d76a 100644 --- a/scripts/process.rs +++ b/scripts/process.rs @@ -4,7 +4,7 @@ use std::{ process::{Command, Stdio}, }; -use anyhow::{ensure, Context as _, Result}; +use anyhow::{ensure, Context as _}; /// A means of running a command as a subprocess. pub struct Process { @@ -33,7 +33,7 @@ impl Process { /// Create the file specified by `output_filepath` and set it as the stdout /// and stderr of the command. - pub fn pipe(mut self, output_filepath: &Path) -> Result { + pub fn pipe(mut self, output_filepath: &Path) -> anyhow::Result { let out = File::create(output_filepath)?; let err = out.try_clone()?; self.stdout = Stdio::from(out); @@ -42,7 +42,7 @@ impl Process { } /// Run the command. - pub fn run(self) -> Result<()> { + pub fn run(self) -> anyhow::Result<()> { let output = Command::new(&self.cmd) .args(&self.args) .stdout(self.stdout) diff --git a/scripts/prove_rpc.rs b/scripts/prove_rpc.rs index e0c3427c5..81eaab9b9 100644 --- a/scripts/prove_rpc.rs +++ b/scripts/prove_rpc.rs @@ -1,12 +1,6 @@ -use std::{ - env::set_var, - fmt::Display, - fs::create_dir_all, - path::{Path, PathBuf}, -}; +use std::{env::set_var, fmt::Display, fs::create_dir_all, path::PathBuf}; use alloy::{eips::BlockId, transports::http::reqwest::Url}; -use anyhow::Result; use clap::{arg, Args, ValueEnum, ValueHint}; use crate::process::Process; @@ -42,14 +36,10 @@ pub struct ProveRpcArgs { /// The node RPC URL. #[arg(value_hint = ValueHint::Url)] rpc_url: Url, - /// The RPC type (jerigon or native). - #[arg()] rpc_type: RpcType, /// Whether to generate a proof and verify it or not. - #[arg()] mode: RunMode, /// The start of the block range to prove (inclusive). - #[arg()] start_block: BlockId, /// The end of the block range to prove. If None, start_block-1 is used. #[arg(short = 'c', long)] @@ -73,7 +63,7 @@ pub struct ProveRpcArgs { } /// Run leader binary to prove a block range via RPC. -pub fn prove_via_rpc(args: ProveRpcArgs) -> Result<()> { +pub fn prove_via_rpc(args: ProveRpcArgs) -> anyhow::Result<()> { // Set rustc environment variables. set_var("RUST_MIN_STACK", "33554432"); set_var("RUST_BACKTRACE", "1"); @@ -99,10 +89,7 @@ pub fn prove_via_rpc(args: ProveRpcArgs) -> Result<()> { }; // Create the output directory if it does not exist. - let proof_output_dirpath = Path::new(&args.output_dir); - if !proof_output_dirpath.exists() { - create_dir_all(proof_output_dirpath)?; - } + create_dir_all(args.output_dir.clone())?; // Set file handle limit. const RECOMMENDED_FILE_LIMIT: isize = 8192; if !sysinfo::set_open_files_limit(RECOMMENDED_FILE_LIMIT) { @@ -114,7 +101,7 @@ pub fn prove_via_rpc(args: ProveRpcArgs) -> Result<()> { "--runtime=in-memory", "--load-strategy=on-demand", "--proof-output-dir", - proof_output_dirpath.to_str().unwrap(), + args.output_dir.to_str().unwrap(), "--block-batch-size", &args.block_batch_size.to_string(), "rpc", @@ -123,11 +110,11 @@ pub fn prove_via_rpc(args: ProveRpcArgs) -> Result<()> { "--rpc-url", args.rpc_url.as_ref(), "--start-block", - &block_string(start_block), + &block_string(start_block)?, "--checkpoint-block", - &block_string(checkpoint_block), + &block_string(checkpoint_block)?, "--end-block", - &block_string(end_block), + &block_string(end_block)?, "--backoff", &args.backoff.to_string(), "--max-retries", @@ -156,9 +143,10 @@ pub fn prove_via_rpc(args: ProveRpcArgs) -> Result<()> { Process::new("cargo").args(&cmd_args).run()?; // Verify the proof. - let proof_filepath = - proof_output_dirpath.join(format!("b{}.zkproof", block_string(end_block))); - let verify_output_filepath = proof_output_dirpath.join("verify.out"); + let proof_filepath = args + .output_dir + .join(format!("b{}.zkproof", block_string(end_block)?)); + let verify_output_filepath = args.output_dir.join("verify.out"); let verify_runner = Process::new("cargo") .args(&[ "run", @@ -176,10 +164,13 @@ pub fn prove_via_rpc(args: ProveRpcArgs) -> Result<()> { } /// Converts a block ID to an appropriate string based on its variant. -fn block_string(block: BlockId) -> String { +fn block_string(block: BlockId) -> anyhow::Result { match block { - BlockId::Number(number) => number.as_number().unwrap().to_string(), - BlockId::Hash(hash) => hash.to_string(), + BlockId::Number(number) => Ok(number + .as_number() + .ok_or(anyhow::anyhow!("BlockId must be a number"))? + .to_string()), + BlockId::Hash(hash) => Ok(hash.to_string()), } } From 1e9c06fc2e88beef77906e8bf5c2d2723c6a8499 Mon Sep 17 00:00:00 2001 From: sergerad Date: Wed, 20 Nov 2024 20:17:34 +1300 Subject: [PATCH 19/22] Remove process.rs and use Command directly --- scripts/process.rs | 59 ----------------------- scripts/prove_rpc.rs | 112 +++++++++++++++++++++++++------------------ scripts/xtask.rs | 1 - 3 files changed, 65 insertions(+), 107 deletions(-) delete mode 100644 scripts/process.rs diff --git a/scripts/process.rs b/scripts/process.rs deleted file mode 100644 index a2739d76a..000000000 --- a/scripts/process.rs +++ /dev/null @@ -1,59 +0,0 @@ -use std::{ - fs::File, - path::Path, - process::{Command, Stdio}, -}; - -use anyhow::{ensure, Context as _}; - -/// A means of running a command as a subprocess. -pub struct Process { - cmd: String, - args: Vec, - stdout: Stdio, - stderr: Stdio, -} - -impl Process { - /// Create a new runner with the given command. - pub fn new(cmd: impl Into) -> Self { - Self { - cmd: cmd.into(), - args: vec![], - stdout: Stdio::inherit(), - stderr: Stdio::inherit(), - } - } - - /// Add arguments to the command. - pub fn args(mut self, args: &[&str]) -> Self { - self.args.extend(args.iter().map(|s| s.to_string())); - self - } - - /// Create the file specified by `output_filepath` and set it as the stdout - /// and stderr of the command. - pub fn pipe(mut self, output_filepath: &Path) -> anyhow::Result { - let out = File::create(output_filepath)?; - let err = out.try_clone()?; - self.stdout = Stdio::from(out); - self.stderr = Stdio::from(err); - Ok(self) - } - - /// Run the command. - pub fn run(self) -> anyhow::Result<()> { - let output = Command::new(&self.cmd) - .args(&self.args) - .stdout(self.stdout) - .stderr(self.stderr) - .output() - .context(format!("couldn't exec `{}`", &self.cmd))?; - ensure!( - output.status.success(), - "command failed with {}", - output.status - ); - Ok(()) - } -} diff --git a/scripts/prove_rpc.rs b/scripts/prove_rpc.rs index 81eaab9b9..27aa6a074 100644 --- a/scripts/prove_rpc.rs +++ b/scripts/prove_rpc.rs @@ -1,10 +1,9 @@ -use std::{env::set_var, fmt::Display, fs::create_dir_all, path::PathBuf}; +use std::{env::set_var, fmt::Display, fs::create_dir_all, path::PathBuf, process::Command}; use alloy::{eips::BlockId, transports::http::reqwest::Url}; +use anyhow::ensure; use clap::{arg, Args, ValueEnum, ValueHint}; -use crate::process::Process; - #[derive(ValueEnum, Clone)] enum RpcType { Jerigon, @@ -97,6 +96,7 @@ pub fn prove_via_rpc(args: ProveRpcArgs) -> anyhow::Result<()> { } // Construct common args used for all run modes. + let cargo_args = &["run", "--release", "--package=zero", "--bin=leader", "--"]; let leader_args = &[ "--runtime=in-memory", "--load-strategy=on-demand", @@ -120,45 +120,75 @@ pub fn prove_via_rpc(args: ProveRpcArgs) -> anyhow::Result<()> { "--max-retries", &args.max_retries.to_string(), ]; - let cmd_args = command_args(args.mode, leader_args); // Run the appropriate command based on the run mode. match args.mode { RunMode::Test => { - set_var("ARITHMETIC_CIRCUIT_SIZE", "16..21"); - set_var("BYTE_PACKING_CIRCUIT_SIZE", "8..21"); - set_var("CPU_CIRCUIT_SIZE", "8..21"); - set_var("KECCAK_CIRCUIT_SIZE", "4..20"); - set_var("KECCAK_SPONGE_CIRCUIT_SIZE", "8..17"); - set_var("LOGIC_CIRCUIT_SIZE", "4..21"); - set_var("MEMORY_CIRCUIT_SIZE", "17..24"); - set_var("MEMORY_BEFORE_CIRCUIT_SIZE", "16..23"); - set_var("MEMORY_AFTER_CIRCUIT_SIZE", "7..23"); + // Update the command args for test mode. + let mut cmd_args = Vec::from(cargo_args); + cmd_args.push("--test-only"); + cmd_args.extend_from_slice(leader_args); - Process::new("cargo").args(&cmd_args).run() + // Run the leader command. + let output = Command::new("cargo") + .args(&cmd_args) + .env("ARITHMETIC_CIRCUIT_SIZE", "16..21") + .env("BYTE_PACKING_CIRCUIT_SIZE", "8..21") + .env("CPU_CIRCUIT_SIZE", "8..21") + .env("KECCAK_CIRCUIT_SIZE", "4..20") + .env("KECCAK_SPONGE_CIRCUIT_SIZE", "8..17") + .env("LOGIC_CIRCUIT_SIZE", "4..21") + .env("MEMORY_CIRCUIT_SIZE", "17..24") + .env("MEMORY_BEFORE_CIRCUIT_SIZE", "16..23") + .env("MEMORY_AFTER_CIRCUIT_SIZE", "7..23") + .output()?; + ensure!( + output.status.success(), + "command failed with {}", + output.status + ); + Ok(()) } - RunMode::Prove => Process::new("cargo").args(&cmd_args).run(), - RunMode::Verify => { - // Generate the proof. - Process::new("cargo").args(&cmd_args).run()?; + RunMode::Prove | RunMode::Verify => { + // Update the command args for prove mode. + let mut cmd_args = Vec::from(cargo_args); + cmd_args.push("--use-test-config"); + cmd_args.extend_from_slice(leader_args); + + // Run the leader command. + let output = Command::new("cargo").args(&cmd_args).output()?; + ensure!( + output.status.success(), + "command failed with {}", + output.status + ); - // Verify the proof. - let proof_filepath = args - .output_dir - .join(format!("b{}.zkproof", block_string(end_block)?)); - let verify_output_filepath = args.output_dir.join("verify.out"); - let verify_runner = Process::new("cargo") - .args(&[ - "run", - "--release", - "--package=zero", - "--bin=verifier", - "--", - "-f", - proof_filepath.to_str().unwrap(), - ]) - .pipe(&verify_output_filepath)?; - verify_runner.run() + // Verify proof if in verify mode. + if let RunMode::Verify = args.mode { + // Construct the proof file path. + let proof_filepath = args + .output_dir + .join(format!("b{}.zkproof", block_string(end_block)?)); + + // Run the verifier command. + let output = Command::new("cargo") + .args([ + "run", + "--release", + "--package=zero", + "--bin=verifier", + "--", + "-f", + proof_filepath.to_str().unwrap(), + ]) + .output()?; + ensure!( + output.status.success(), + "command failed with {}", + output.status + ); + } + Ok(()) } } } @@ -173,15 +203,3 @@ fn block_string(block: BlockId) -> anyhow::Result { BlockId::Hash(hash) => Ok(hash.to_string()), } } - -/// Constructs the full command arguments for running the leader binary with -/// cargo. -fn command_args<'a>(mode: RunMode, leader_args: &'a [&str]) -> Vec<&'a str> { - let mut args = Vec::from(&["run", "--release", "--package=zero", "--bin=leader", "--"]); - match mode { - RunMode::Prove | RunMode::Verify => args.push("--use-test-config"), - RunMode::Test => args.push("--test-only"), - } - args.extend_from_slice(leader_args); - args -} diff --git a/scripts/xtask.rs b/scripts/xtask.rs index edf853117..0a28d5ef0 100644 --- a/scripts/xtask.rs +++ b/scripts/xtask.rs @@ -1,7 +1,6 @@ //! General purpose scripts for development mod outdated; -mod process; mod prove_rpc; use anyhow::Result; From 831b68de47fa33cf54f829997725c726060bc4ea Mon Sep 17 00:00:00 2001 From: sergerad Date: Wed, 20 Nov 2024 20:43:17 +1300 Subject: [PATCH 20/22] Inherit stdout/err --- scripts/prove_rpc.rs | 30 ++++++++++-------------------- 1 file changed, 10 insertions(+), 20 deletions(-) diff --git a/scripts/prove_rpc.rs b/scripts/prove_rpc.rs index 27aa6a074..b5708fd41 100644 --- a/scripts/prove_rpc.rs +++ b/scripts/prove_rpc.rs @@ -130,7 +130,7 @@ pub fn prove_via_rpc(args: ProveRpcArgs) -> anyhow::Result<()> { cmd_args.extend_from_slice(leader_args); // Run the leader command. - let output = Command::new("cargo") + let status = Command::new("cargo") .args(&cmd_args) .env("ARITHMETIC_CIRCUIT_SIZE", "16..21") .env("BYTE_PACKING_CIRCUIT_SIZE", "8..21") @@ -141,12 +141,9 @@ pub fn prove_via_rpc(args: ProveRpcArgs) -> anyhow::Result<()> { .env("MEMORY_CIRCUIT_SIZE", "17..24") .env("MEMORY_BEFORE_CIRCUIT_SIZE", "16..23") .env("MEMORY_AFTER_CIRCUIT_SIZE", "7..23") - .output()?; - ensure!( - output.status.success(), - "command failed with {}", - output.status - ); + .spawn()? + .wait()?; + ensure!(status.success(), "command failed with {}", status); Ok(()) } RunMode::Prove | RunMode::Verify => { @@ -156,12 +153,8 @@ pub fn prove_via_rpc(args: ProveRpcArgs) -> anyhow::Result<()> { cmd_args.extend_from_slice(leader_args); // Run the leader command. - let output = Command::new("cargo").args(&cmd_args).output()?; - ensure!( - output.status.success(), - "command failed with {}", - output.status - ); + let status = Command::new("cargo").args(&cmd_args).spawn()?.wait()?; + ensure!(status.success(), "command failed with {}", status); // Verify proof if in verify mode. if let RunMode::Verify = args.mode { @@ -171,7 +164,7 @@ pub fn prove_via_rpc(args: ProveRpcArgs) -> anyhow::Result<()> { .join(format!("b{}.zkproof", block_string(end_block)?)); // Run the verifier command. - let output = Command::new("cargo") + let status = Command::new("cargo") .args([ "run", "--release", @@ -181,12 +174,9 @@ pub fn prove_via_rpc(args: ProveRpcArgs) -> anyhow::Result<()> { "-f", proof_filepath.to_str().unwrap(), ]) - .output()?; - ensure!( - output.status.success(), - "command failed with {}", - output.status - ); + .spawn()? + .wait()?; + ensure!(status.success(), "command failed with {}", status); } Ok(()) } From 19d3591384b7c522c77a99856ab40e5ed73f9765 Mon Sep 17 00:00:00 2001 From: sergerad Date: Thu, 21 Nov 2024 09:09:45 +1300 Subject: [PATCH 21/22] Undo whitespace rm in yamls --- .github/workflows/jerigon-native.yml | 2 +- .github/workflows/jerigon-zero.yml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/jerigon-native.yml b/.github/workflows/jerigon-native.yml index f48648bd1..935cf166a 100644 --- a/.github/workflows/jerigon-native.yml +++ b/.github/workflows/jerigon-native.yml @@ -1,4 +1,4 @@ ---- # Run and populate blockchain with transactions and generate proofs using native tracer +--- # Run and populate blockchain with transactions and generate proofs using native tracer name: Jerigon Integration diff --git a/.github/workflows/jerigon-zero.yml b/.github/workflows/jerigon-zero.yml index bf611a269..6d8017a6e 100644 --- a/.github/workflows/jerigon-zero.yml +++ b/.github/workflows/jerigon-zero.yml @@ -1,4 +1,4 @@ ---- # Run and populate blockchain with transactions and generate proofs using zero tracer +--- # Run and populate blockchain with transactions and generate proofs using zero tracer name: Jerigon Integration From 3fb1ea21a9364ec1091bfd38f28f5db121c1b293 Mon Sep 17 00:00:00 2001 From: sergerad Date: Thu, 21 Nov 2024 09:12:09 +1300 Subject: [PATCH 22/22] Fix readme --- zero/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/zero/README.md b/zero/README.md index b5a38abdc..545cf6708 100644 --- a/zero/README.md +++ b/zero/README.md @@ -431,7 +431,7 @@ cargo xtask prove-rpc -e - Which may look like this: ```sh -cargo xtask prove-rpc -u "$ETH_RPC_URL" -s 17 -e 18 -t jerigon -c 16 -b 3000 -r 100 -m verify +cargo xtask prove-rpc "$ETH_RPC_URL" jerigon verify 17 -e 18 -c 16 -b 3000 -r 100 ``` Which will attempt to generate proofs for blocks `17` & `18` consecutively and incorporate the previous block proof during generation.