From d0f88508b0aebe8b86e5ba05b2247a75983adf9b Mon Sep 17 00:00:00 2001 From: Po Date: Thu, 4 Jan 2024 18:27:14 +0100 Subject: [PATCH 1/2] feat: add `proof-from-trace` cli --- .gitignore | 2 ++ crates/cli/src/app_builder.rs | 23 +++++++++++++++ crates/cli/src/args.rs | 6 ++++ crates/cli/src/command.rs | 8 ++++++ crates/cli/src/exec.rs | 36 +++++++++++++++++++++++ crates/cli/test_cli.sh | 2 ++ crates/specs/src/lib.rs | 51 ++++++++++++++++++++++----------- crates/zkwasm/src/loader/mod.rs | 2 +- crates/zkwasm/src/test/mod.rs | 2 +- 9 files changed, 113 insertions(+), 19 deletions(-) diff --git a/.gitignore b/.gitignore index 5f38836d9..08a51c08f 100644 --- a/.gitignore +++ b/.gitignore @@ -4,3 +4,5 @@ /output crates/playground/wasm crates/playground/target +params/ +output/ diff --git a/crates/cli/src/app_builder.rs b/crates/cli/src/app_builder.rs index 02dc3a073..d3101da65 100644 --- a/crates/cli/src/app_builder.rs +++ b/crates/cli/src/app_builder.rs @@ -18,6 +18,7 @@ use super::exec::exec_create_proof; use super::exec::exec_image_checksum; use super::exec::exec_setup; use super::exec::exec_verify_proof; +use super::exec::exec_create_proof_from_trace; fn load_or_generate_output_path( wasm_md5: &String, @@ -74,6 +75,7 @@ pub trait AppBuilder: CommandBuilder { let app = Self::append_setup_subcommand(app); let app = Self::append_dry_run_subcommand(app); let app = Self::append_create_single_proof_subcommand(app); + let app = Self::append_create_proof_from_trace_subcommand(app); let app = Self::append_verify_single_proof_subcommand(app); let app = Self::append_image_checksum_subcommand(app); @@ -185,6 +187,27 @@ pub trait AppBuilder: CommandBuilder { Ok(()) } + Some(("proof-from-trace", sub_matches)) => { + let tables_dir = sub_matches.get_one::("tables").unwrap(); + let proof_dir = sub_matches.get_one::("proof").unwrap(); + + let context_out_path: Option = + Self::parse_context_out_path_arg(&sub_matches); + + let context_out = Arc::new(Mutex::new(vec![])); + + exec_create_proof_from_trace( + Self::NAME, + zkwasm_k, + tables_dir, + &proof_dir, + ¶m_dir, + )?; + + write_context_output(&context_out.lock().unwrap(), context_out_path)?; + + Ok(()) + } Some(("single-verify", _)) => exec_verify_proof(Self::NAME, &output_dir, ¶m_dir), Some((_, _)) => todo!(), None => todo!(), diff --git a/crates/cli/src/args.rs b/crates/cli/src/args.rs index e933070f0..34d421dc3 100644 --- a/crates/cli/src/args.rs +++ b/crates/cli/src/args.rs @@ -71,6 +71,12 @@ pub trait ArgBuilder { ).value_parser(value_parser!(PathBuf)) } + fn tables_path_arg<'a>() -> Arg<'a> { + arg!( + -t --tables [TABLES_PATH] "Path of the tables files.\nMust be provided." + ).value_parser(value_parser!(PathBuf)) + } + fn proof_path_arg<'a>() -> Arg<'a> { arg!( -p --proof "Path of proof." diff --git a/crates/cli/src/command.rs b/crates/cli/src/command.rs index 9f0d0c30a..02aba7321 100644 --- a/crates/cli/src/command.rs +++ b/crates/cli/src/command.rs @@ -36,6 +36,14 @@ pub trait CommandBuilder: ArgBuilder { app.subcommand(command) } + fn append_create_proof_from_trace_subcommand(app: App) -> App { + let command = Command::new("proof-from-trace") + .arg(Self::proof_path_arg()) + .arg(Self::tables_path_arg()); + + app.subcommand(command) + } + fn append_verify_single_proof_subcommand(app: App) -> App { let command = Command::new("single-verify"); app.subcommand(command) diff --git a/crates/cli/src/exec.rs b/crates/cli/src/exec.rs index f8db80654..28d7cea5e 100644 --- a/crates/cli/src/exec.rs +++ b/crates/cli/src/exec.rs @@ -3,6 +3,7 @@ use circuits_batcher::proof::CircuitInfo; use circuits_batcher::proof::ProofInfo; use circuits_batcher::proof::ProofLoadInfo; use delphinus_zkwasm::circuits::TestCircuit; +use delphinus_zkwasm::circuits::ZkWasmCircuitBuilder; use delphinus_zkwasm::loader::ZkWasmLoader; use delphinus_zkwasm::runtime::host::HostEnvBuilder; use halo2_proofs::pairing::bn256::Bn256; @@ -12,6 +13,7 @@ use halo2aggregator_s::circuits::utils::load_or_build_unsafe_params; use halo2aggregator_s::circuits::utils::TranscriptHash; use halo2aggregator_s::native_verifier; use log::info; +use specs::Tables; use std::io::Write; use std::path::PathBuf; @@ -145,6 +147,40 @@ pub fn exec_create_proof>( Ok(()) } +pub fn exec_create_proof_from_trace( + prefix: &'static str, + zkwasm_k: u32, + tables_dir: &PathBuf, + proof_dir: &PathBuf, + param_dir: &PathBuf, +) -> Result<()> { + let (tables, public_inputs_and_outputs) = Tables::load_table(tables_dir.clone()); + let builder = ZkWasmCircuitBuilder { + tables, + public_inputs_and_outputs: public_inputs_and_outputs.clone(), + }; + let circuit = builder.build_circuit(); + + let instances = public_inputs_and_outputs + .iter() + .map(|v| (*v).into()) + .collect(); + + let circuit: CircuitInfo> = CircuitInfo::new( + circuit, + prefix.to_string(), + vec![instances], + zkwasm_k as usize, + circuits_batcher::args::HashType::Poseidon, + ); + circuit.proofloadinfo.save(proof_dir); + circuit.exec_create_proof(proof_dir, param_dir, 0); + + info!("Proof has been created."); + + Ok(()) +} + pub fn exec_verify_proof( prefix: &'static str, output_dir: &PathBuf, diff --git a/crates/cli/test_cli.sh b/crates/cli/test_cli.sh index bdf25a072..fcf57f39d 100755 --- a/crates/cli/test_cli.sh +++ b/crates/cli/test_cli.sh @@ -11,3 +11,5 @@ RUST_LOG=info cargo run --release --features cuda -- -k 18 --function zkmain --p RUST_LOG=info cargo run --release --features cuda -- -k 18 --function zkmain --param ./params --output ./output --wasm ../zkwasm/wasm/wasm_output.wasm single-prove --public 133:i64 --public 2:i64 RUST_LOG=info cargo run --release --features cuda -- -k 18 --function zkmain --param ./params --output ./output --wasm ../zkwasm/wasm/wasm_output.wasm single-verify + +RUST_LOG=info cargo run --release --features cuda -- -k 18 --function zkmain --param ./params --output ./output --wasm ../zkwasm/wasm/wasm_output.wasm proof-from-trace --tables ./ --proof ./output \ No newline at end of file diff --git a/crates/specs/src/lib.rs b/crates/specs/src/lib.rs index 3add81166..45bfc6058 100644 --- a/crates/specs/src/lib.rs +++ b/crates/specs/src/lib.rs @@ -3,6 +3,7 @@ #![deny(dead_code)] use std::env; +use std::io::BufReader; use std::io::Write; use std::path::PathBuf; @@ -16,6 +17,7 @@ use jtable::StaticFrameEntry; use mtable::MTable; use serde::Deserialize; use serde::Serialize; +use serde::de::DeserializeOwned; #[macro_use] extern crate lazy_static; @@ -51,15 +53,20 @@ pub struct ExecutionTable { pub jtable: JumpTable, } +pub enum FileType { + JSON, + FLEXBUFFERS, +} + #[derive(Default, Clone)] pub struct Tables { pub compilation_tables: CompilationTable, - pub execution_tables: ExecutionTable, + pub execution_tables: ExecutionTable } impl Tables { - pub fn write_json(&self, dir: Option) { - fn write_file(folder: &PathBuf, filename: &str, buf: &String) { + pub fn write_json(&self, dir: Option, public_inputs_and_outputs: &Vec) { + fn write_file(folder: &PathBuf, filename: &str, buf: String) { let mut folder = folder.clone(); folder.push(filename); let mut fd = std::fs::File::create(folder.as_path()).unwrap(); @@ -68,25 +75,35 @@ impl Tables { fd.write(buf.as_bytes()).unwrap(); } - let itable = serde_json::to_string_pretty(&self.compilation_tables.itable).unwrap(); - let imtable = serde_json::to_string_pretty(&self.compilation_tables.imtable).unwrap(); - let etable = serde_json::to_string_pretty(&self.execution_tables.etable).unwrap(); + let dir = dir.unwrap_or(env::current_dir().unwrap()); + + let compilation_table = + serde_json::to_string_pretty(&self.compilation_tables).unwrap(); + let execution_table = serde_json::to_string_pretty(&self.execution_tables).unwrap(); let external_host_call_table = serde_json::to_string_pretty( &self .execution_tables .etable .filter_external_host_call_table(), - ) - .unwrap(); - let mtable = serde_json::to_string_pretty(&self.execution_tables.mtable).unwrap(); - let jtable = serde_json::to_string_pretty(&self.execution_tables.jtable).unwrap(); + ).unwrap(); + let instances = serde_json::to_string_pretty(&public_inputs_and_outputs).unwrap(); + write_file(&dir, "compilation.json", compilation_table); + write_file(&dir, "execution.json", execution_table); + write_file(&dir, "instance.json", instances); + write_file(&dir, "external_host_table.json", external_host_call_table); + } - let dir = dir.unwrap_or(env::current_dir().unwrap()); - write_file(&dir, "itable.json", &itable); - write_file(&dir, "imtable.json", &imtable); - write_file(&dir, "etable.json", &etable); - write_file(&dir, "mtable.json", &mtable); - write_file(&dir, "jtable.json", &jtable); - write_file(&dir, "external_host_table.json", &external_host_call_table); + pub fn load_table(dir: PathBuf) -> (Tables, Vec) { + fn load_file(folder: &PathBuf, filename: &str) -> T { + let mut folder = folder.clone(); + folder.push(filename); + let file = std::fs::File::open(folder.as_path()).unwrap(); + let reader = BufReader::new(file); + serde_json::from_reader(reader).unwrap() + } + let compilation_tables: CompilationTable = load_file(&dir, "compilation.json"); + let execution_tables: ExecutionTable = load_file(&dir, "execution.json"); + let public_inputs_and_outputs: Vec = load_file(&dir, "instance.json"); + (Tables { compilation_tables, execution_tables}, public_inputs_and_outputs) } } diff --git a/crates/zkwasm/src/loader/mod.rs b/crates/zkwasm/src/loader/mod.rs index e84364b06..339f1f372 100644 --- a/crates/zkwasm/src/loader/mod.rs +++ b/crates/zkwasm/src/loader/mod.rs @@ -180,7 +180,7 @@ impl> ZkWasmLoader( v }; - execution_result.tables.write_json(None); + execution_result.tables.write_json(None, &execution_result.public_inputs_and_outputs); let memory_writing_table: MemoryWritingTable = execution_result .tables .execution_tables From 9b135e13ba40caec168231f86fcffd43c9ced1b0 Mon Sep 17 00:00:00 2001 From: Po Date: Mon, 8 Jan 2024 03:43:46 +0100 Subject: [PATCH 2/2] fmt & keep all tables --- crates/cli/src/app_builder.rs | 2 +- crates/cli/src/args.rs | 3 +- crates/cli/test_cli.sh | 2 +- crates/specs/src/lib.rs | 65 +++++++++++++++++++++++++++------ crates/zkwasm/src/loader/mod.rs | 4 +- crates/zkwasm/src/test/mod.rs | 4 +- 6 files changed, 63 insertions(+), 17 deletions(-) diff --git a/crates/cli/src/app_builder.rs b/crates/cli/src/app_builder.rs index d3101da65..b3358c7c6 100644 --- a/crates/cli/src/app_builder.rs +++ b/crates/cli/src/app_builder.rs @@ -15,10 +15,10 @@ use crate::exec::exec_dry_run; use super::command::CommandBuilder; use super::exec::exec_create_proof; +use super::exec::exec_create_proof_from_trace; use super::exec::exec_image_checksum; use super::exec::exec_setup; use super::exec::exec_verify_proof; -use super::exec::exec_create_proof_from_trace; fn load_or_generate_output_path( wasm_md5: &String, diff --git a/crates/cli/src/args.rs b/crates/cli/src/args.rs index 34d421dc3..019ee82a6 100644 --- a/crates/cli/src/args.rs +++ b/crates/cli/src/args.rs @@ -74,7 +74,8 @@ pub trait ArgBuilder { fn tables_path_arg<'a>() -> Arg<'a> { arg!( -t --tables [TABLES_PATH] "Path of the tables files.\nMust be provided." - ).value_parser(value_parser!(PathBuf)) + ) + .value_parser(value_parser!(PathBuf)) } fn proof_path_arg<'a>() -> Arg<'a> { diff --git a/crates/cli/test_cli.sh b/crates/cli/test_cli.sh index fcf57f39d..bf236970a 100755 --- a/crates/cli/test_cli.sh +++ b/crates/cli/test_cli.sh @@ -12,4 +12,4 @@ RUST_LOG=info cargo run --release --features cuda -- -k 18 --function zkmain --p RUST_LOG=info cargo run --release --features cuda -- -k 18 --function zkmain --param ./params --output ./output --wasm ../zkwasm/wasm/wasm_output.wasm single-prove --public 133:i64 --public 2:i64 RUST_LOG=info cargo run --release --features cuda -- -k 18 --function zkmain --param ./params --output ./output --wasm ../zkwasm/wasm/wasm_output.wasm single-verify -RUST_LOG=info cargo run --release --features cuda -- -k 18 --function zkmain --param ./params --output ./output --wasm ../zkwasm/wasm/wasm_output.wasm proof-from-trace --tables ./ --proof ./output \ No newline at end of file +RUST_LOG=info cargo run --release -- -k 18 --function zkmain --param ./params --output ./output --wasm ../zkwasm/wasm/wasm_output.wasm proof-from-trace --tables ./ --proof ./output \ No newline at end of file diff --git a/crates/specs/src/lib.rs b/crates/specs/src/lib.rs index 45bfc6058..5b010c680 100644 --- a/crates/specs/src/lib.rs +++ b/crates/specs/src/lib.rs @@ -15,9 +15,9 @@ use itable::InstructionTable; use jtable::JumpTable; use jtable::StaticFrameEntry; use mtable::MTable; +use serde::de::DeserializeOwned; use serde::Deserialize; use serde::Serialize; -use serde::de::DeserializeOwned; #[macro_use] extern crate lazy_static; @@ -61,7 +61,7 @@ pub enum FileType { #[derive(Default, Clone)] pub struct Tables { pub compilation_tables: CompilationTable, - pub execution_tables: ExecutionTable + pub execution_tables: ExecutionTable, } impl Tables { @@ -77,33 +77,74 @@ impl Tables { let dir = dir.unwrap_or(env::current_dir().unwrap()); - let compilation_table = - serde_json::to_string_pretty(&self.compilation_tables).unwrap(); - let execution_table = serde_json::to_string_pretty(&self.execution_tables).unwrap(); + macro_rules! serialize { + ($t:ident, $name:ident) => { + let table = serde_json::to_string_pretty(&self.$t.$name).unwrap(); + write_file(&dir, &format!("{}.json", stringify!($name)), table); + }; + } + + serialize!(compilation_tables, itable); + serialize!(compilation_tables, imtable); + serialize!(compilation_tables, elem_table); + serialize!(compilation_tables, configure_table); + serialize!(compilation_tables, static_jtable); + serialize!(compilation_tables, fid_of_entry); + + serialize!(execution_tables, etable); + serialize!(execution_tables, mtable); + serialize!(execution_tables, jtable); + let external_host_call_table = serde_json::to_string_pretty( &self .execution_tables .etable .filter_external_host_call_table(), - ).unwrap(); + ) + .unwrap(); let instances = serde_json::to_string_pretty(&public_inputs_and_outputs).unwrap(); - write_file(&dir, "compilation.json", compilation_table); - write_file(&dir, "execution.json", execution_table); + write_file(&dir, "instance.json", instances); write_file(&dir, "external_host_table.json", external_host_call_table); } pub fn load_table(dir: PathBuf) -> (Tables, Vec) { - fn load_file(folder: &PathBuf, filename: &str) -> T { + fn load_file(folder: &PathBuf, filename: &str) -> T { let mut folder = folder.clone(); folder.push(filename); let file = std::fs::File::open(folder.as_path()).unwrap(); let reader = BufReader::new(file); serde_json::from_reader(reader).unwrap() } - let compilation_tables: CompilationTable = load_file(&dir, "compilation.json"); - let execution_tables: ExecutionTable = load_file(&dir, "execution.json"); + let itable = load_file(&dir, "itable.json"); + let imtable = load_file(&dir, "imtable.json"); + let elem_table = load_file(&dir, "elem_table.json"); + let configure_table = load_file(&dir, "configure_table.json"); + let static_jtable = load_file(&dir, "static_jtable.json"); + let fid_of_entry = load_file(&dir, "fid_of_entry.json"); + + let etable = load_file(&dir, "etable.json"); + let mtable = load_file(&dir, "mtable.json"); + let jtable = load_file(&dir, "jtable.json"); + let public_inputs_and_outputs: Vec = load_file(&dir, "instance.json"); - (Tables { compilation_tables, execution_tables}, public_inputs_and_outputs) + ( + Tables { + compilation_tables: CompilationTable { + itable, + imtable, + elem_table, + configure_table, + static_jtable, + fid_of_entry, + }, + execution_tables: ExecutionTable { + etable, + mtable, + jtable, + }, + }, + public_inputs_and_outputs, + ) } } diff --git a/crates/zkwasm/src/loader/mod.rs b/crates/zkwasm/src/loader/mod.rs index 339f1f372..040237190 100644 --- a/crates/zkwasm/src/loader/mod.rs +++ b/crates/zkwasm/src/loader/mod.rs @@ -180,7 +180,9 @@ impl> ZkWasmLoader( v }; - execution_result.tables.write_json(None, &execution_result.public_inputs_and_outputs); + execution_result + .tables + .write_json(None, &execution_result.public_inputs_and_outputs); let memory_writing_table: MemoryWritingTable = execution_result .tables .execution_tables