From dcf70b78aa04effea48bbb426d2bb3e573055c4d Mon Sep 17 00:00:00 2001 From: Alexander Camuto Date: Wed, 14 Dec 2022 13:29:41 +0000 Subject: [PATCH 01/20] feat: KZG commitments with single strategy for proving --- src/bin/ezkl.rs | 196 +++++++++++++++++++++++++---------- src/pfsys/kzg/aggregation.rs | 181 +++++++++++++++++++++++++++++++- src/pfsys/kzg/mod.rs | 186 +-------------------------------- src/pfsys/kzg/single.rs | 125 ++++++++++++++++++++++ 4 files changed, 449 insertions(+), 239 deletions(-) create mode 100644 src/pfsys/kzg/single.rs diff --git a/src/bin/ezkl.rs b/src/bin/ezkl.rs index 6cddd2c78..33b15e9e4 100644 --- a/src/bin/ezkl.rs +++ b/src/bin/ezkl.rs @@ -5,26 +5,31 @@ use ezkl::fieldutils::i32_to_felt; use ezkl::graph::Model; use ezkl::pfsys::ipa::{create_ipa_proof, verify_ipa_proof}; #[cfg(feature = "evm")] -use ezkl::pfsys::kzg::{ +use ezkl::pfsys::kzg::aggregation::{ aggregation::AggregationCircuit, evm_verify, gen_aggregation_evm_verifier, gen_application_snark, gen_kzg_proof, gen_pk, gen_srs, }; +#[cfg(not(feature = "evm"))] +use ezkl::pfsys::kzg::single::{create_kzg_proof, verify_kzg_proof}; use ezkl::pfsys::Proof; use ezkl::pfsys::{parse_prover_errors, prepare_circuit_and_public_input, prepare_data}; #[cfg(feature = "evm")] use halo2_proofs::poly::commitment::Params; +#[cfg(not(feature = "evm"))] +use halo2_proofs::poly::kzg::{ + commitment::ParamsKZG, multiopen::VerifierGWC, strategy::SingleStrategy as KZGSingleStrategy, +}; use halo2_proofs::{ dev::MockProver, plonk::verify_proof, poly::{ commitment::ParamsProver, - ipa::{commitment::ParamsIPA, strategy::SingleStrategy}, + ipa::{commitment::ParamsIPA, strategy::SingleStrategy as IPASingleStrategy}, VerificationStrategy, }, transcript::{Blake2bRead, Challenge255, TranscriptReadBuffer}, }; -#[cfg(feature = "evm")] -use halo2curves::bn256::G1Affine; +use halo2curves::bn256::{Bn256, Fr}; use halo2curves::pasta::vesta; use halo2curves::pasta::Fp; use log::{error, info, trace}; @@ -81,14 +86,14 @@ pub fn main() { model: _, pfsys, } => { + // A direct proof let args = Cli::parse(); let data = prepare_data(data); - let (circuit, public_inputs) = prepare_circuit_and_public_input(&data); - info!("full proof with {}", pfsys); - match pfsys { ProofSystem::IPA => { - // A direct proof + let (circuit, public_inputs) = prepare_circuit_and_public_input(&data); + info!("full proof with {}", pfsys); + let params: ParamsIPA = ParamsIPA::new(args.logrows); trace!("params computed"); @@ -103,7 +108,7 @@ pub fn main() { let pi_for_real_prover: &[&[&[Fp]]] = &[&pi_inner]; let now = Instant::now(); - let strategy = SingleStrategy::new(¶ms); + let strategy = IPASingleStrategy::new(¶ms); let mut transcript = Blake2bRead::<_, _, Challenge255<_>>::init(&proof[..]); assert!(verify_proof( ¶ms, @@ -116,11 +121,40 @@ pub fn main() { info!("verify took {}", now.elapsed().as_secs()); } #[cfg(not(feature = "evm"))] - ProofSystem::KZG => todo!(), + ProofSystem::KZG => { + // A direct proof + let (circuit, public_inputs) = prepare_circuit_and_public_input(&data); + let params: ParamsKZG = ParamsKZG::new(args.logrows); + trace!("params computed"); + + let (pk, proof, _dims) = + create_kzg_proof(circuit, public_inputs.clone(), ¶ms); + + let pi_inner: Vec> = public_inputs + .iter() + .map(|i| i.iter().map(|e| i32_to_felt::(*e)).collect::>()) + .collect::>>(); + let pi_inner = pi_inner.iter().map(|e| e.deref()).collect::>(); + let pi_for_real_prover: &[&[&[Fr]]] = &[&pi_inner]; + + let now = Instant::now(); + let strategy = KZGSingleStrategy::new(¶ms); + let mut transcript = Blake2bRead::<_, _, Challenge255<_>>::init(&proof[..]); + assert!(verify_proof::<_, VerifierGWC<_>, _, _, _>( + ¶ms, + pk.get_vk(), + strategy, + pi_for_real_prover, + &mut transcript + ) + .is_ok()); + info!("verify took {}", now.elapsed().as_secs()); + } #[cfg(feature = "evm")] ProofSystem::KZG => { // We will need aggregator k > application k > bits // let application_logrows = args.logrows; //bits + 1; + let (circuit, public_inputs) = prepare_circuit_and_public_input(&data); let aggregation_logrows = args.logrows + 6; let params = gen_srs(aggregation_logrows); @@ -164,59 +198,117 @@ pub fn main() { } => { let args = Cli::parse(); let data = prepare_data(data); - let (circuit, public_inputs) = prepare_circuit_and_public_input(&data); - info!("proof with {}", pfsys); - let params: ParamsIPA = ParamsIPA::new(args.logrows); - trace!("params computed"); + match pfsys { + ProofSystem::IPA => { + let (circuit, public_inputs) = prepare_circuit_and_public_input(&data); + info!("proof with {}", pfsys); + let params: ParamsIPA = ParamsIPA::new(args.logrows); + trace!("params computed"); - let (_pk, proof, _input_dims) = - create_ipa_proof(circuit.clone(), public_inputs.clone(), ¶ms); + let (_pk, proof, _input_dims) = + create_ipa_proof(circuit.clone(), public_inputs.clone(), ¶ms); - let pi: Vec<_> = public_inputs - .into_iter() - .map(|i| i.into_iter().collect()) - .collect(); + let pi: Vec<_> = public_inputs + .into_iter() + .map(|i| i.into_iter().collect()) + .collect(); - let checkable_pf = Proof { - input_shapes: circuit.inputs.iter().map(|i| i.dims().to_vec()).collect(), - public_inputs: pi, - proof, - }; + let checkable_pf = Proof { + input_shapes: circuit.inputs.iter().map(|i| i.dims().to_vec()).collect(), + public_inputs: pi, + proof, + }; - let serialized = match serde_json::to_string(&checkable_pf) { - Ok(s) => s, - Err(e) => { - abort!("failed to convert proof json to string {:?}", e); + let serialized = match serde_json::to_string(&checkable_pf) { + Ok(s) => s, + Err(e) => { + abort!("failed to convert proof json to string {:?}", e); + } + }; + + let mut file = std::fs::File::create(output).expect("create failed"); + file.write_all(serialized.as_bytes()).expect("write failed"); } - }; + ProofSystem::KZG => { + let (circuit, public_inputs) = prepare_circuit_and_public_input(&data); + info!("proof with {}", pfsys); + let params: ParamsKZG = ParamsKZG::new(args.logrows); + trace!("params computed"); - let mut file = std::fs::File::create(output).expect("create failed"); - file.write_all(serialized.as_bytes()).expect("write failed"); + let (_pk, proof, _input_dims) = + create_kzg_proof(circuit.clone(), public_inputs.clone(), ¶ms); + + let pi: Vec<_> = public_inputs + .into_iter() + .map(|i| i.into_iter().collect()) + .collect(); + + let checkable_pf = Proof { + input_shapes: circuit.inputs.iter().map(|i| i.dims().to_vec()).collect(), + public_inputs: pi, + proof, + }; + + let serialized = match serde_json::to_string(&checkable_pf) { + Ok(s) => s, + Err(e) => { + abort!("failed to convert proof json to string {:?}", e); + } + }; + + let mut file = std::fs::File::create(output).expect("create failed"); + file.write_all(serialized.as_bytes()).expect("write failed"); + } + } } Commands::Verify { model: _, proof, - pfsys: _, - } => { - let mut file = match File::open(proof) { - Ok(f) => f, - Err(e) => { - abort!("failed to open proof file {:?}", e); - } - }; - let mut data = String::new(); - match file.read_to_string(&mut data) { - Ok(_) => {} - Err(e) => { - abort!("failed to read file {:?}", e); - } - }; - let proof: Proof = serde_json::from_str(&data).expect("JSON was not well-formatted"); + pfsys, + } => match pfsys { + ProofSystem::IPA => { + let mut file = match File::open(proof) { + Ok(f) => f, + Err(e) => { + abort!("failed to open proof file {:?}", e); + } + }; + let mut data = String::new(); + match file.read_to_string(&mut data) { + Ok(_) => {} + Err(e) => { + abort!("failed to read file {:?}", e); + } + }; + let proof: Proof = + serde_json::from_str(&data).expect("JSON was not well-formatted"); - let result = verify_ipa_proof(proof); - info!("verified: {}", result); - assert!(result); - } + let result = verify_ipa_proof(proof); + info!("verified: {}", result); + assert!(result); + } + ProofSystem::KZG => { + let mut file = match File::open(proof) { + Ok(f) => f, + Err(e) => { + abort!("failed to open proof file {:?}", e); + } + }; + let mut data = String::new(); + match file.read_to_string(&mut data) { + Ok(_) => {} + Err(e) => { + abort!("failed to read file {:?}", e); + } + }; + let proof: Proof = + serde_json::from_str(&data).expect("JSON was not well-formatted"); + + let result = verify_kzg_proof(proof); + info!("verified: {}", result); + assert!(result); + } + }, } } diff --git a/src/pfsys/kzg/aggregation.rs b/src/pfsys/kzg/aggregation.rs index 350f5cf52..6133c27f2 100644 --- a/src/pfsys/kzg/aggregation.rs +++ b/src/pfsys/kzg/aggregation.rs @@ -1,7 +1,29 @@ +use super::super::prepare_circuit_and_public_input; +use super::super::ModelInput; +use crate::fieldutils::i32_to_felt; +#[cfg(feature = "evm")] +use ethereum_types::Address; +#[cfg(feature = "evm")] +use foundry_evm::executor::{fork::MultiFork, Backend, ExecutorBuilder}; +#[cfg(feature = "evm")] +use halo2_proofs::plonk::VerifyingKey; use halo2_proofs::{ circuit::{Layouter, SimpleFloorPlanner, Value}, - plonk::{self, Circuit, ConstraintSystem}, - poly::{commitment::ParamsProver, kzg::commitment::ParamsKZG}, + dev::MockProver, + plonk::{ + self, create_proof, keygen_pk, keygen_vk, verify_proof, Circuit, ConstraintSystem, + ProvingKey, + }, + poly::{ + commitment::{Params, ParamsProver}, + kzg::{ + commitment::{KZGCommitmentScheme, ParamsKZG}, + multiopen::{ProverGWC, VerifierGWC}, + strategy::AccumulatorStrategy, + }, + VerificationStrategy, + }, + transcript::{EncodedChallenge, TranscriptReadBuffer, TranscriptWriterBuffer}, }; use halo2_wrong_ecc::{ integer::rns::Rns, @@ -11,11 +33,23 @@ use halo2_wrong_ecc::{ }, EccConfig, }; +#[cfg(feature = "evm")] +use halo2curves::bn256::Fq; use halo2curves::bn256::{Bn256, Fq, Fr, G1Affine}; use itertools::Itertools; use log::trace; +#[cfg(feature = "evm")] +use plonk_verifier::{ + loader::evm::{encode_calldata, EvmLoader}, + system::halo2::transcript::evm::EvmTranscript, + verifier::PlonkVerifier, +}; use plonk_verifier::{ - loader::{self, native::NativeLoader}, + loader::native::NativeLoader, + system::halo2::{compile, Config}, +}; +use plonk_verifier::{ + loader::{self}, pcs::{ kzg::{Gwc19, Kzg, KzgAccumulator, KzgAs, KzgSuccinctVerifyingKey, LimbsEncoding}, AccumulationScheme, AccumulationSchemeProver, @@ -26,6 +60,9 @@ use plonk_verifier::{ Protocol, }; use rand::rngs::OsRng; +use std::io::Cursor; +#[cfg(feature = "evm")] +use std::rc::Rc; use std::{iter, rc::Rc}; const LIMBS: usize = 4; @@ -304,3 +341,141 @@ impl Circuit for AggregationCircuit { Ok(()) } } + +pub fn gen_application_snark(params: &ParamsKZG, data: &ModelInput) -> Snark { + let (circuit, public_inputs) = prepare_circuit_and_public_input::(data); + + let pk = gen_pk(params, &circuit); + let number_instance = public_inputs[0].len(); + trace!("number_instance {:?}", number_instance); + let protocol = compile( + params, + pk.get_vk(), + Config::kzg().with_num_instance(vec![number_instance]), + ); + let pi_inner: Vec> = public_inputs + .iter() + .map(|i| i.iter().map(|e| i32_to_felt::(*e)).collect::>()) + .collect::>>(); + // let pi_inner = pi_inner.iter().map(|e| e.deref()).collect::>(); + trace!("pi_inner {:?}", pi_inner); + let proof = gen_kzg_proof::< + _, + _, + PoseidonTranscript, + PoseidonTranscript, + >(params, &pk, circuit, pi_inner.clone()); + Snark::new(protocol, pi_inner, proof) +} + +#[cfg(feature = "evm")] +pub fn gen_aggregation_evm_verifier( + params: &ParamsKZG, + vk: &VerifyingKey, + num_instance: Vec, + accumulator_indices: Vec<(usize, usize)>, +) -> Vec { + let svk = params.get_g()[0].into(); + let dk = (params.g2(), params.s_g2()).into(); + let protocol = compile( + params, + vk, + Config::kzg() + .with_num_instance(num_instance.clone()) + .with_accumulator_indices(accumulator_indices), + ); + + let loader = EvmLoader::new::(); + let mut transcript = EvmTranscript::<_, Rc, _, _>::new(loader.clone()); + + let instances = transcript.load_instances(num_instance); + let proof = Plonk::read_proof(&svk, &protocol, &instances, &mut transcript).unwrap(); + Plonk::verify(&svk, &dk, &protocol, &instances, &proof).unwrap(); + + loader.deployment_code() +} + +#[cfg(feature = "evm")] +pub fn evm_verify(deployment_code: Vec, instances: Vec>, proof: Vec) { + let calldata = encode_calldata(&instances, &proof); + let success = { + let mut evm = ExecutorBuilder::default() + .with_gas_limit(u64::MAX.into()) + .build(Backend::new(MultiFork::new().0, None)); + + let caller = Address::from_low_u64_be(0xfe); + let verifier = evm + .deploy(caller, deployment_code.into(), 0.into(), None) + .unwrap() + .address; + let result = evm + .call_raw(caller, verifier, calldata.into(), 0.into()) + .unwrap(); + + dbg!(result.gas_used); + + !result.reverted + }; + assert!(success); +} + +pub fn gen_srs(k: u32) -> ParamsKZG { + ParamsKZG::::setup(k, OsRng) +} + +pub fn gen_pk>(params: &ParamsKZG, circuit: &C) -> ProvingKey { + let vk = keygen_vk(params, circuit).unwrap(); + keygen_pk(params, vk, circuit).unwrap() +} + +/// Generates proof for either application circuit (model) or aggregation circuit. +pub fn gen_kzg_proof< + C: Circuit, + E: EncodedChallenge, + TR: TranscriptReadBuffer>, G1Affine, E>, + TW: TranscriptWriterBuffer, G1Affine, E>, +>( + params: &ParamsKZG, + pk: &ProvingKey, + circuit: C, + instances: Vec>, +) -> Vec { + MockProver::run(params.k(), &circuit, instances.clone()) + .unwrap() + .assert_satisfied(); + + let instances = instances + .iter() + .map(|instances| instances.as_slice()) + .collect_vec(); + let proof = { + let mut transcript = TW::init(Vec::new()); + create_proof::, ProverGWC<_>, _, _, TW, _>( + params, + pk, + &[circuit], + &[instances.as_slice()], + OsRng, + &mut transcript, + ) + .unwrap(); + transcript.finalize() + }; + + let accept = { + let mut transcript = TR::init(Cursor::new(proof.clone())); + VerificationStrategy::<_, VerifierGWC<_>>::finalize( + verify_proof::<_, VerifierGWC<_>, _, TR, _>( + params.verifier_params(), + pk.get_vk(), + AccumulatorStrategy::new(params.verifier_params()), + &[instances.as_slice()], + &mut transcript, + ) + .unwrap(), + ) + }; + assert!(accept); + + proof +} diff --git a/src/pfsys/kzg/mod.rs b/src/pfsys/kzg/mod.rs index 483c16397..7a3e8ccfb 100644 --- a/src/pfsys/kzg/mod.rs +++ b/src/pfsys/kzg/mod.rs @@ -1,187 +1,5 @@ /// Aggregation circuit -pub mod aggregation; - -use super::prepare_circuit_and_public_input; -use super::ModelInput; -use crate::fieldutils::i32_to_felt; -#[cfg(feature = "evm")] -use aggregation::Plonk; -use aggregation::{PoseidonTranscript, Snark}; -#[cfg(feature = "evm")] -use ethereum_types::Address; -#[cfg(feature = "evm")] -use foundry_evm::executor::{fork::MultiFork, Backend, ExecutorBuilder}; -#[cfg(feature = "evm")] -use halo2_proofs::plonk::VerifyingKey; -use halo2_proofs::{ - dev::MockProver, - plonk::{create_proof, keygen_pk, keygen_vk, verify_proof, Circuit, ProvingKey}, - poly::{ - commitment::{Params, ParamsProver}, - kzg::{ - commitment::{KZGCommitmentScheme, ParamsKZG}, - multiopen::{ProverGWC, VerifierGWC}, - strategy::AccumulatorStrategy, - }, - VerificationStrategy, - }, - transcript::{EncodedChallenge, TranscriptReadBuffer, TranscriptWriterBuffer}, -}; -#[cfg(feature = "evm")] -use halo2curves::bn256::Fq; -use halo2curves::bn256::{Bn256, Fr, G1Affine}; -use itertools::Itertools; -use log::trace; #[cfg(feature = "evm")] -use plonk_verifier::{ - loader::evm::{encode_calldata, EvmLoader}, - system::halo2::transcript::evm::EvmTranscript, - verifier::PlonkVerifier, -}; -use plonk_verifier::{ - loader::native::NativeLoader, - system::halo2::{compile, Config}, -}; - -use rand::rngs::OsRng; -use std::io::Cursor; -#[cfg(feature = "evm")] -use std::rc::Rc; - -pub fn gen_application_snark(params: &ParamsKZG, data: &ModelInput) -> Snark { - let (circuit, public_inputs) = prepare_circuit_and_public_input::(data); - - let pk = gen_pk(params, &circuit); - let number_instance = public_inputs[0].len(); - trace!("number_instance {:?}", number_instance); - let protocol = compile( - params, - pk.get_vk(), - Config::kzg().with_num_instance(vec![number_instance]), - ); - let pi_inner: Vec> = public_inputs - .iter() - .map(|i| i.iter().map(|e| i32_to_felt::(*e)).collect::>()) - .collect::>>(); - // let pi_inner = pi_inner.iter().map(|e| e.deref()).collect::>(); - trace!("pi_inner {:?}", pi_inner); - let proof = gen_kzg_proof::< - _, - _, - PoseidonTranscript, - PoseidonTranscript, - >(params, &pk, circuit, pi_inner.clone()); - Snark::new(protocol, pi_inner, proof) -} - -#[cfg(feature = "evm")] -pub fn gen_aggregation_evm_verifier( - params: &ParamsKZG, - vk: &VerifyingKey, - num_instance: Vec, - accumulator_indices: Vec<(usize, usize)>, -) -> Vec { - let svk = params.get_g()[0].into(); - let dk = (params.g2(), params.s_g2()).into(); - let protocol = compile( - params, - vk, - Config::kzg() - .with_num_instance(num_instance.clone()) - .with_accumulator_indices(accumulator_indices), - ); - - let loader = EvmLoader::new::(); - let mut transcript = EvmTranscript::<_, Rc, _, _>::new(loader.clone()); - - let instances = transcript.load_instances(num_instance); - let proof = Plonk::read_proof(&svk, &protocol, &instances, &mut transcript).unwrap(); - Plonk::verify(&svk, &dk, &protocol, &instances, &proof).unwrap(); - - loader.deployment_code() -} - -#[cfg(feature = "evm")] -pub fn evm_verify(deployment_code: Vec, instances: Vec>, proof: Vec) { - let calldata = encode_calldata(&instances, &proof); - let success = { - let mut evm = ExecutorBuilder::default() - .with_gas_limit(u64::MAX.into()) - .build(Backend::new(MultiFork::new().0, None)); - - let caller = Address::from_low_u64_be(0xfe); - let verifier = evm - .deploy(caller, deployment_code.into(), 0.into(), None) - .unwrap() - .address; - let result = evm - .call_raw(caller, verifier, calldata.into(), 0.into()) - .unwrap(); - - dbg!(result.gas_used); - - !result.reverted - }; - assert!(success); -} - -pub fn gen_srs(k: u32) -> ParamsKZG { - ParamsKZG::::setup(k, OsRng) -} - -pub fn gen_pk>(params: &ParamsKZG, circuit: &C) -> ProvingKey { - let vk = keygen_vk(params, circuit).unwrap(); - keygen_pk(params, vk, circuit).unwrap() -} - -/// Generates proof for either application circuit (model) or aggregation circuit. -pub fn gen_kzg_proof< - C: Circuit, - E: EncodedChallenge, - TR: TranscriptReadBuffer>, G1Affine, E>, - TW: TranscriptWriterBuffer, G1Affine, E>, ->( - params: &ParamsKZG, - pk: &ProvingKey, - circuit: C, - instances: Vec>, -) -> Vec { - MockProver::run(params.k(), &circuit, instances.clone()) - .unwrap() - .assert_satisfied(); - - let instances = instances - .iter() - .map(|instances| instances.as_slice()) - .collect_vec(); - let proof = { - let mut transcript = TW::init(Vec::new()); - create_proof::, ProverGWC<_>, _, _, TW, _>( - params, - pk, - &[circuit], - &[instances.as_slice()], - OsRng, - &mut transcript, - ) - .unwrap(); - transcript.finalize() - }; - - let accept = { - let mut transcript = TR::init(Cursor::new(proof.clone())); - VerificationStrategy::<_, VerifierGWC<_>>::finalize( - verify_proof::<_, VerifierGWC<_>, _, TR, _>( - params.verifier_params(), - pk.get_vk(), - AccumulatorStrategy::new(params.verifier_params()), - &[instances.as_slice()], - &mut transcript, - ) - .unwrap(), - ) - }; - assert!(accept); +pub mod aggregation; - proof -} +pub mod single; diff --git a/src/pfsys/kzg/single.rs b/src/pfsys/kzg/single.rs new file mode 100644 index 000000000..a4ea9eee4 --- /dev/null +++ b/src/pfsys/kzg/single.rs @@ -0,0 +1,125 @@ +use super::super::Proof; +use crate::abort; +use crate::commands::Cli; +use crate::fieldutils::i32_to_felt; +use crate::graph::ModelCircuit; +use crate::tensor::Tensor; +use clap::Parser; +use halo2_proofs::{ + // arithmetic::FieldExt, + // dev::{MockProver, VerifyFailure}, + plonk::{create_proof, keygen_pk, keygen_vk, verify_proof, Circuit, ProvingKey}, + poly::{ + commitment::ParamsProver, + kzg::{ + commitment::{KZGCommitmentScheme, ParamsKZG}, + multiopen::{ProverGWC, VerifierGWC}, + strategy::SingleStrategy, + }, + }, + transcript::{ + Blake2bRead, Blake2bWrite, Challenge255, TranscriptReadBuffer, TranscriptWriterBuffer, + }, +}; +use halo2curves::bn256::{Bn256, Fr as F, G1Affine}; +use log::{error, info, trace}; +use rand::rngs::OsRng; +use std::marker::PhantomData; +use std::ops::Deref; +use std::time::Instant; + +pub fn create_kzg_proof( + circuit: ModelCircuit, + public_inputs: Vec>, + params: &ParamsKZG, +) -> (ProvingKey, Vec, Vec>) { + // Real proof + let empty_circuit = circuit.without_witnesses(); + + // Initialize the proving key + let now = Instant::now(); + trace!("preparing VK"); + let vk = keygen_vk(params, &empty_circuit).expect("keygen_vk should not fail"); + info!("VK took {}", now.elapsed().as_secs()); + let now = Instant::now(); + let pk = keygen_pk(params, vk, &empty_circuit).expect("keygen_pk should not fail"); + info!("PK took {}", now.elapsed().as_secs()); + let now = Instant::now(); + let mut transcript = Blake2bWrite::<_, _, Challenge255<_>>::init(vec![]); + let mut rng = OsRng; + + let pi_inner: Vec> = public_inputs + .iter() + .map(|i| i.iter().map(|e| i32_to_felt::(*e)).collect::>()) + .collect::>>(); + let pi_inner = pi_inner.iter().map(|e| e.deref()).collect::>(); + let pi_for_real_prover: &[&[&[F]]] = &[&pi_inner]; + trace!("pi for real prover {:?}", pi_for_real_prover); + + let dims = circuit.inputs.iter().map(|i| i.dims().to_vec()).collect(); + + create_proof::, ProverGWC<_>, _, _, _, _>( + params, + &pk, + &[circuit], + pi_for_real_prover, + &mut rng, + &mut transcript, + ) + .expect("proof generation should not fail"); + let proof = transcript.finalize(); + info!("Proof took {}", now.elapsed().as_secs()); + + (pk, proof, dims) +} + +pub fn verify_kzg_proof(proof: Proof) -> bool { + let args = Cli::parse(); + let params: ParamsKZG = ParamsKZG::new(args.logrows); + + let inputs = proof + .input_shapes + .iter() + .map( + |s| match Tensor::new(Some(&vec![0; s.iter().product()]), s) { + Ok(t) => t, + Err(e) => { + abort!("failed to initialize tensor {:?}", e); + } + }, + ) + .collect(); + let circuit = ModelCircuit:: { + inputs, + _marker: PhantomData, + }; + let empty_circuit = circuit.without_witnesses(); + let vk = keygen_vk(¶ms, &empty_circuit).expect("keygen_vk should not fail"); + let pk = keygen_pk(¶ms, vk, &empty_circuit).expect("keygen_pk should not fail"); + + let pi_inner: Vec> = proof + .public_inputs + .iter() + .map(|i| i.iter().map(|e| i32_to_felt::(*e)).collect::>()) + .collect::>>(); + let pi_inner = pi_inner.iter().map(|e| e.deref()).collect::>(); + let pi_for_real_prover: &[&[&[F]]] = &[&pi_inner]; + trace!("pi for real prover {:?}", pi_for_real_prover); + + let now = Instant::now(); + let strategy = SingleStrategy::new(¶ms); + let mut transcript = Blake2bRead::<_, _, Challenge255<_>>::init(&proof.proof[..]); + + trace!("params computed"); + + let result = verify_proof::<_, VerifierGWC<_>, _, _, _>( + ¶ms, + pk.get_vk(), + strategy, + pi_for_real_prover, + &mut transcript, + ) + .is_ok(); + info!("verify took {}", now.elapsed().as_secs()); + result +} From e3d8e23e7760acc7e49fe37e4aaa382a48e444d2 Mon Sep 17 00:00:00 2001 From: Alexander Camuto Date: Wed, 14 Dec 2022 17:09:39 +0000 Subject: [PATCH 02/20] simplify tests --- Cargo.toml | 1 + src/pfsys/ipa.rs | 10 +- tests/integration_tests.rs | 189 ++++++++++++++++++++++--------------- 3 files changed, 114 insertions(+), 86 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index b218c6302..cd5860ebd 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -35,6 +35,7 @@ plonk_verifier = { git = "https://github.com/privacy-scaling-explorations/plonk criterion = {version = "0.3", features = ["html_reports"]} seq-macro = "0.3.1" test-case = "2.2.2" +ctor = "0.1.26" [[bench]] name = "affine" diff --git a/src/pfsys/ipa.rs b/src/pfsys/ipa.rs index 302531668..37875ce4e 100644 --- a/src/pfsys/ipa.rs +++ b/src/pfsys/ipa.rs @@ -98,7 +98,6 @@ pub fn verify_ipa_proof(proof: Proof) -> bool { }; let empty_circuit = circuit.without_witnesses(); let vk = keygen_vk(¶ms, &empty_circuit).expect("keygen_vk should not fail"); - let pk = keygen_pk(¶ms, vk, &empty_circuit).expect("keygen_pk should not fail"); let pi_inner: Vec> = proof .public_inputs @@ -115,14 +114,7 @@ pub fn verify_ipa_proof(proof: Proof) -> bool { trace!("params computed"); - let result = verify_proof( - ¶ms, - pk.get_vk(), - strategy, - pi_for_real_prover, - &mut transcript, - ) - .is_ok(); + let result = verify_proof(¶ms, &vk, strategy, pi_for_real_prover, &mut transcript).is_ok(); info!("verify took {}", now.elapsed().as_secs()); result } diff --git a/tests/integration_tests.rs b/tests/integration_tests.rs index 7951528f6..d15e1ce6f 100644 --- a/tests/integration_tests.rs +++ b/tests/integration_tests.rs @@ -1,5 +1,11 @@ use std::process::Command; +#[cfg(test)] +#[ctor::ctor] +fn init() { + build_ezkl(); +} + const TESTS: [&str; 12] = [ "1l_mlp", "1l_flatten", @@ -25,9 +31,11 @@ macro_rules! test_func { use crate::mock; use crate::mock_public_inputs; use crate::mock_public_params; - use crate::fullprove; - use crate::prove_and_verify; + use crate::ipa_fullprove; + use crate::ipa_prove_and_verify; use crate::kzg_fullprove; + use crate::kzg_prove_and_verify; + use crate::kzg_evm_fullprove; seq!(N in 0..=11 { #(#[test_case(TESTS[N])])* @@ -46,21 +54,32 @@ macro_rules! test_func { } #(#[test_case(TESTS[N])])* - fn fullprove_(test: &str) { - fullprove(test.to_string()); + fn ipa_fullprove_(test: &str) { + ipa_fullprove(test.to_string()); } #(#[test_case(TESTS[N])])* - fn prove_and_verify_(test: &str) { - prove_and_verify(test.to_string()); + fn ipa_prove_and_verify_(test: &str) { + ipa_prove_and_verify(test.to_string()); } - // these take a particularly long time to run #(#[test_case(TESTS[N])])* - #[ignore] fn kzg_fullprove_(test: &str) { kzg_fullprove(test.to_string()); } + + #(#[test_case(TESTS[N])])* + #[ignore] + fn kzg_prove_and_verify_(test: &str) { + kzg_prove_and_verify(test.to_string()); + } + + // these take a particularly long time to run + #(#[test_case(TESTS[N])])* + #[ignore] + fn kzg_evm_fullprove_(test: &str) { + kzg_evm_fullprove(test.to_string()); + } }); } }; @@ -70,17 +89,10 @@ test_func!(); // Mock prove (fast, but does not cover some potential issues) fn mock(example_name: String) { - let status = Command::new("cargo") + let status = Command::new("target/release/ezkl") .args([ - "run", - "--release", - "--bin", - "ezkl", - "--", - "--bits", - "16", - "-K", - "17", + "--bits=16", + "-K=17", "mock", "-D", format!("./examples/onnx/examples/{}/input.json", example_name).as_str(), @@ -96,18 +108,11 @@ fn mock(example_name: String) { // Mock prove (fast, but does not cover some potential issues) fn mock_public_inputs(example_name: String) { - let status = Command::new("cargo") + let status = Command::new("target/release/ezkl") .args([ - "run", - "--release", - "--bin", - "ezkl", - "--", "--public-inputs", - "--bits", - "16", - "-K", - "17", + "--bits=16", + "-K=17", "mock", "-D", format!("./examples/onnx/examples/{}/input.json", example_name).as_str(), @@ -123,18 +128,11 @@ fn mock_public_inputs(example_name: String) { // Mock prove (fast, but does not cover some potential issues) fn mock_public_params(example_name: String) { - let status = Command::new("cargo") + let status = Command::new("target/release/ezkl") .args([ - "run", - "--release", - "--bin", - "ezkl", - "--", "--public-params", - "--bits", - "16", - "-K", - "17", + "--bits=16", + "-K=17", "mock", "-D", format!("./examples/onnx/examples/{}/input.json", example_name).as_str(), @@ -149,18 +147,11 @@ fn mock_public_params(example_name: String) { } // full prove (slower, covers more, but still reuses the pk) -fn fullprove(example_name: String) { - let status = Command::new("cargo") +fn ipa_fullprove(example_name: String) { + let status = Command::new("target/release/ezkl") .args([ - "run", - "--release", - "--bin", - "ezkl", - "--", - "--bits", - "16", - "-K", - "17", + "--bits=16", + "-K=17", "fullprove", "-D", format!("./examples/onnx/examples/{}/input.json", example_name).as_str(), @@ -175,18 +166,11 @@ fn fullprove(example_name: String) { } // prove-serialize-verify, the usual full path -fn prove_and_verify(example_name: String) { - let status = Command::new("cargo") +fn ipa_prove_and_verify(example_name: String) { + let status = Command::new("target/release/ezkl") .args([ - "run", - "--release", - "--bin", - "ezkl", - "--", - "--bits", - "16", - "-K", - "17", + "--bits=16", + "-K=17", "prove", "-D", format!("./examples/onnx/examples/{}/input.json", example_name).as_str(), @@ -198,17 +182,10 @@ fn prove_and_verify(example_name: String) { .status() .expect("failed to execute process"); assert!(status.success()); - let status = Command::new("cargo") + let status = Command::new("target/release/ezkl") .args([ - "run", - "--release", - "--bin", - "ezkl", - "--", - "--bits", - "16", - "-K", - "17", + "--bits=16", + "-K=17", "verify", "-M", format!("./examples/onnx/examples/{}/network.onnx", example_name).as_str(), @@ -220,9 +197,62 @@ fn prove_and_verify(example_name: String) { assert!(status.success()); } -// KZG / EVM tests +// prove-serialize-verify, the usual full path +fn kzg_prove_and_verify(example_name: String) { + let status = Command::new("target/release/ezkl") + .args([ + "--bits=16", + "-K=17", + "prove", + "-D", + format!("./examples/onnx/examples/{}/input.json", example_name).as_str(), + "-M", + format!("./examples/onnx/examples/{}/network.onnx", example_name).as_str(), + "-O", + format!("pav_{}.pf", example_name).as_str(), + "--pfsys=kzg", + ]) + .status() + .expect("failed to execute process"); + assert!(status.success()); + let status = Command::new("target/release/ezkl") + .args([ + "--bits=16", + "-K=17", + "verify", + "--pfsys=kzg", + "-M", + format!("./examples/onnx/examples/{}/network.onnx", example_name).as_str(), + "-P", + format!("pav_{}.pf", example_name).as_str(), + ]) + .status() + .expect("failed to execute process"); + assert!(status.success()); +} + +// KZG tests // full prove (slower, covers more, but still reuses the pk) fn kzg_fullprove(example_name: String) { + let status = Command::new("target/release/ezkl") + .args([ + "--bits=16", + "-K=17", + "fullprove", + "--pfsys=kzg", + "-D", + format!("./examples/onnx/examples/{}/input.json", example_name).as_str(), + "-M", + format!("./examples/onnx/examples/{}/network.onnx", example_name).as_str(), + ]) + .status() + .expect("failed to execute process"); + assert!(status.success()); +} + +// KZG / EVM tests +// full prove (slower, covers more, but still reuses the pk) +fn kzg_evm_fullprove(example_name: String) { let status = Command::new("cargo") .args([ "run", @@ -232,19 +262,24 @@ fn kzg_fullprove(example_name: String) { "--bin", "ezkl", "--", - "--bits", - "16", - "-K", - "17", + "--bits=16", + "-K=17", "fullprove", + "--pfsys=kzg", "-D", format!("./examples/onnx/examples/{}/input.json", example_name).as_str(), "-M", format!("./examples/onnx/examples/{}/network.onnx", example_name).as_str(), - "--pfsys", - "kzg", ]) .status() .expect("failed to execute process"); assert!(status.success()); } + +fn build_ezkl() { + let status = Command::new("cargo") + .args(["build", "--release", "--bin", "ezkl"]) + .status() + .expect("failed to execute process"); + assert!(status.success()); +} From a14623ded984ed6b2d6bab8cd72bae4f7d0d94e8 Mon Sep 17 00:00:00 2001 From: Alexander Camuto Date: Wed, 14 Dec 2022 17:39:26 +0000 Subject: [PATCH 03/20] cleanup --- src/bin/ezkl.rs | 111 ++++++++++++++++++------------------------------ 1 file changed, 42 insertions(+), 69 deletions(-) diff --git a/src/bin/ezkl.rs b/src/bin/ezkl.rs index 33b15e9e4..603763098 100644 --- a/src/bin/ezkl.rs +++ b/src/bin/ezkl.rs @@ -198,7 +198,7 @@ pub fn main() { } => { let args = Cli::parse(); let data = prepare_data(data); - match pfsys { + let checkable_pf = match pfsys { ProofSystem::IPA => { let (circuit, public_inputs) = prepare_circuit_and_public_input(&data); info!("proof with {}", pfsys); @@ -213,21 +213,11 @@ pub fn main() { .map(|i| i.into_iter().collect()) .collect(); - let checkable_pf = Proof { + Proof { input_shapes: circuit.inputs.iter().map(|i| i.dims().to_vec()).collect(), public_inputs: pi, proof, - }; - - let serialized = match serde_json::to_string(&checkable_pf) { - Ok(s) => s, - Err(e) => { - abort!("failed to convert proof json to string {:?}", e); - } - }; - - let mut file = std::fs::File::create(output).expect("create failed"); - file.write_all(serialized.as_bytes()).expect("write failed"); + } } ProofSystem::KZG => { let (circuit, public_inputs) = prepare_circuit_and_public_input(&data); @@ -243,72 +233,55 @@ pub fn main() { .map(|i| i.into_iter().collect()) .collect(); - let checkable_pf = Proof { + Proof { input_shapes: circuit.inputs.iter().map(|i| i.dims().to_vec()).collect(), public_inputs: pi, proof, - }; - - let serialized = match serde_json::to_string(&checkable_pf) { - Ok(s) => s, - Err(e) => { - abort!("failed to convert proof json to string {:?}", e); - } - }; - - let mut file = std::fs::File::create(output).expect("create failed"); - file.write_all(serialized.as_bytes()).expect("write failed"); + } } - } + }; + let serialized = match serde_json::to_string(&checkable_pf) { + Ok(s) => s, + Err(e) => { + abort!("failed to convert proof json to string {:?}", e); + } + }; + + let mut file = std::fs::File::create(output).expect("create failed"); + file.write_all(serialized.as_bytes()).expect("write failed"); } Commands::Verify { model: _, proof, pfsys, - } => match pfsys { - ProofSystem::IPA => { - let mut file = match File::open(proof) { - Ok(f) => f, - Err(e) => { - abort!("failed to open proof file {:?}", e); - } - }; - let mut data = String::new(); - match file.read_to_string(&mut data) { - Ok(_) => {} - Err(e) => { - abort!("failed to read file {:?}", e); - } - }; - let proof: Proof = - serde_json::from_str(&data).expect("JSON was not well-formatted"); - - let result = verify_ipa_proof(proof); - info!("verified: {}", result); - assert!(result); - } - ProofSystem::KZG => { - let mut file = match File::open(proof) { - Ok(f) => f, - Err(e) => { - abort!("failed to open proof file {:?}", e); - } - }; - let mut data = String::new(); - match file.read_to_string(&mut data) { - Ok(_) => {} - Err(e) => { - abort!("failed to read file {:?}", e); - } - }; - let proof: Proof = - serde_json::from_str(&data).expect("JSON was not well-formatted"); - - let result = verify_kzg_proof(proof); - info!("verified: {}", result); - assert!(result); + } => { + let mut file = match File::open(proof) { + Ok(f) => f, + Err(e) => { + abort!("failed to open proof file {:?}", e); + } + }; + let mut data = String::new(); + match file.read_to_string(&mut data) { + Ok(_) => {} + Err(e) => { + abort!("failed to read file {:?}", e); + } + }; + let proof: Proof = serde_json::from_str(&data).expect("JSON was not well-formatted"); + match pfsys { + ProofSystem::IPA => { + let result = verify_ipa_proof(proof); + info!("verified: {}", result); + assert!(result); + } + ProofSystem::KZG => { + let result = verify_kzg_proof(proof); + info!("verified: {}", result); + assert!(result); + } } - }, + } } } From aff807035960eb92ce1e8203735bd918a9008883 Mon Sep 17 00:00:00 2001 From: Alexander Camuto Date: Wed, 14 Dec 2022 17:49:26 +0000 Subject: [PATCH 04/20] rm kzg verify --- src/bin/ezkl.rs | 27 +++----------- src/pfsys/kzg/single.rs | 76 +++----------------------------------- tests/integration_tests.rs | 41 -------------------- 3 files changed, 11 insertions(+), 133 deletions(-) diff --git a/src/bin/ezkl.rs b/src/bin/ezkl.rs index 603763098..9f965c47e 100644 --- a/src/bin/ezkl.rs +++ b/src/bin/ezkl.rs @@ -10,7 +10,7 @@ use ezkl::pfsys::kzg::aggregation::{ gen_application_snark, gen_kzg_proof, gen_pk, gen_srs, }; #[cfg(not(feature = "evm"))] -use ezkl::pfsys::kzg::single::{create_kzg_proof, verify_kzg_proof}; +use ezkl::pfsys::kzg::single::create_kzg_proof; use ezkl::pfsys::Proof; use ezkl::pfsys::{parse_prover_errors, prepare_circuit_and_public_input, prepare_data}; #[cfg(feature = "evm")] @@ -220,24 +220,8 @@ pub fn main() { } } ProofSystem::KZG => { - let (circuit, public_inputs) = prepare_circuit_and_public_input(&data); - info!("proof with {}", pfsys); - let params: ParamsKZG = ParamsKZG::new(args.logrows); - trace!("params computed"); - - let (_pk, proof, _input_dims) = - create_kzg_proof(circuit.clone(), public_inputs.clone(), ¶ms); - - let pi: Vec<_> = public_inputs - .into_iter() - .map(|i| i.into_iter().collect()) - .collect(); - - Proof { - input_shapes: circuit.inputs.iter().map(|i| i.dims().to_vec()).collect(), - public_inputs: pi, - proof, - } + // https://github.com/zcash/halo2/pull/661 + todo!("we need verification key serialization to be implemented"); } }; let serialized = match serde_json::to_string(&checkable_pf) { @@ -276,9 +260,8 @@ pub fn main() { assert!(result); } ProofSystem::KZG => { - let result = verify_kzg_proof(proof); - info!("verified: {}", result); - assert!(result); + // https://github.com/zcash/halo2/pull/661 + todo!("we need verification key serialization to be implemented"); } } } diff --git a/src/pfsys/kzg/single.rs b/src/pfsys/kzg/single.rs index a4ea9eee4..64383ee90 100644 --- a/src/pfsys/kzg/single.rs +++ b/src/pfsys/kzg/single.rs @@ -1,30 +1,17 @@ -use super::super::Proof; -use crate::abort; -use crate::commands::Cli; use crate::fieldutils::i32_to_felt; use crate::graph::ModelCircuit; use crate::tensor::Tensor; -use clap::Parser; use halo2_proofs::{ - // arithmetic::FieldExt, - // dev::{MockProver, VerifyFailure}, - plonk::{create_proof, keygen_pk, keygen_vk, verify_proof, Circuit, ProvingKey}, - poly::{ - commitment::ParamsProver, - kzg::{ - commitment::{KZGCommitmentScheme, ParamsKZG}, - multiopen::{ProverGWC, VerifierGWC}, - strategy::SingleStrategy, - }, - }, - transcript::{ - Blake2bRead, Blake2bWrite, Challenge255, TranscriptReadBuffer, TranscriptWriterBuffer, + plonk::{create_proof, keygen_pk, keygen_vk, Circuit, ProvingKey}, + poly::kzg::{ + commitment::{KZGCommitmentScheme, ParamsKZG}, + multiopen::ProverGWC, }, + transcript::{Blake2bWrite, Challenge255, TranscriptWriterBuffer}, }; use halo2curves::bn256::{Bn256, Fr as F, G1Affine}; -use log::{error, info, trace}; +use log::{info, trace}; use rand::rngs::OsRng; -use std::marker::PhantomData; use std::ops::Deref; use std::time::Instant; @@ -72,54 +59,3 @@ pub fn create_kzg_proof( (pk, proof, dims) } - -pub fn verify_kzg_proof(proof: Proof) -> bool { - let args = Cli::parse(); - let params: ParamsKZG = ParamsKZG::new(args.logrows); - - let inputs = proof - .input_shapes - .iter() - .map( - |s| match Tensor::new(Some(&vec![0; s.iter().product()]), s) { - Ok(t) => t, - Err(e) => { - abort!("failed to initialize tensor {:?}", e); - } - }, - ) - .collect(); - let circuit = ModelCircuit:: { - inputs, - _marker: PhantomData, - }; - let empty_circuit = circuit.without_witnesses(); - let vk = keygen_vk(¶ms, &empty_circuit).expect("keygen_vk should not fail"); - let pk = keygen_pk(¶ms, vk, &empty_circuit).expect("keygen_pk should not fail"); - - let pi_inner: Vec> = proof - .public_inputs - .iter() - .map(|i| i.iter().map(|e| i32_to_felt::(*e)).collect::>()) - .collect::>>(); - let pi_inner = pi_inner.iter().map(|e| e.deref()).collect::>(); - let pi_for_real_prover: &[&[&[F]]] = &[&pi_inner]; - trace!("pi for real prover {:?}", pi_for_real_prover); - - let now = Instant::now(); - let strategy = SingleStrategy::new(¶ms); - let mut transcript = Blake2bRead::<_, _, Challenge255<_>>::init(&proof.proof[..]); - - trace!("params computed"); - - let result = verify_proof::<_, VerifierGWC<_>, _, _, _>( - ¶ms, - pk.get_vk(), - strategy, - pi_for_real_prover, - &mut transcript, - ) - .is_ok(); - info!("verify took {}", now.elapsed().as_secs()); - result -} diff --git a/tests/integration_tests.rs b/tests/integration_tests.rs index d15e1ce6f..8f643b5ed 100644 --- a/tests/integration_tests.rs +++ b/tests/integration_tests.rs @@ -34,7 +34,6 @@ macro_rules! test_func { use crate::ipa_fullprove; use crate::ipa_prove_and_verify; use crate::kzg_fullprove; - use crate::kzg_prove_and_verify; use crate::kzg_evm_fullprove; seq!(N in 0..=11 { @@ -68,12 +67,6 @@ macro_rules! test_func { kzg_fullprove(test.to_string()); } - #(#[test_case(TESTS[N])])* - #[ignore] - fn kzg_prove_and_verify_(test: &str) { - kzg_prove_and_verify(test.to_string()); - } - // these take a particularly long time to run #(#[test_case(TESTS[N])])* #[ignore] @@ -197,40 +190,6 @@ fn ipa_prove_and_verify(example_name: String) { assert!(status.success()); } -// prove-serialize-verify, the usual full path -fn kzg_prove_and_verify(example_name: String) { - let status = Command::new("target/release/ezkl") - .args([ - "--bits=16", - "-K=17", - "prove", - "-D", - format!("./examples/onnx/examples/{}/input.json", example_name).as_str(), - "-M", - format!("./examples/onnx/examples/{}/network.onnx", example_name).as_str(), - "-O", - format!("pav_{}.pf", example_name).as_str(), - "--pfsys=kzg", - ]) - .status() - .expect("failed to execute process"); - assert!(status.success()); - let status = Command::new("target/release/ezkl") - .args([ - "--bits=16", - "-K=17", - "verify", - "--pfsys=kzg", - "-M", - format!("./examples/onnx/examples/{}/network.onnx", example_name).as_str(), - "-P", - format!("pav_{}.pf", example_name).as_str(), - ]) - .status() - .expect("failed to execute process"); - assert!(status.success()); -} - // KZG tests // full prove (slower, covers more, but still reuses the pk) fn kzg_fullprove(example_name: String) { From 3e21e8a0d673595349bb7cbcfc86c5a6781dec90 Mon Sep 17 00:00:00 2001 From: Alexander Camuto Date: Thu, 15 Dec 2022 13:07:44 +0000 Subject: [PATCH 05/20] Revert "rm kzg verify" This reverts commit aff807035960eb92ce1e8203735bd918a9008883. --- src/bin/ezkl.rs | 27 +++++++++++--- src/pfsys/kzg/single.rs | 76 +++++++++++++++++++++++++++++++++++--- tests/integration_tests.rs | 41 ++++++++++++++++++++ 3 files changed, 133 insertions(+), 11 deletions(-) diff --git a/src/bin/ezkl.rs b/src/bin/ezkl.rs index 9f965c47e..603763098 100644 --- a/src/bin/ezkl.rs +++ b/src/bin/ezkl.rs @@ -10,7 +10,7 @@ use ezkl::pfsys::kzg::aggregation::{ gen_application_snark, gen_kzg_proof, gen_pk, gen_srs, }; #[cfg(not(feature = "evm"))] -use ezkl::pfsys::kzg::single::create_kzg_proof; +use ezkl::pfsys::kzg::single::{create_kzg_proof, verify_kzg_proof}; use ezkl::pfsys::Proof; use ezkl::pfsys::{parse_prover_errors, prepare_circuit_and_public_input, prepare_data}; #[cfg(feature = "evm")] @@ -220,8 +220,24 @@ pub fn main() { } } ProofSystem::KZG => { - // https://github.com/zcash/halo2/pull/661 - todo!("we need verification key serialization to be implemented"); + let (circuit, public_inputs) = prepare_circuit_and_public_input(&data); + info!("proof with {}", pfsys); + let params: ParamsKZG = ParamsKZG::new(args.logrows); + trace!("params computed"); + + let (_pk, proof, _input_dims) = + create_kzg_proof(circuit.clone(), public_inputs.clone(), ¶ms); + + let pi: Vec<_> = public_inputs + .into_iter() + .map(|i| i.into_iter().collect()) + .collect(); + + Proof { + input_shapes: circuit.inputs.iter().map(|i| i.dims().to_vec()).collect(), + public_inputs: pi, + proof, + } } }; let serialized = match serde_json::to_string(&checkable_pf) { @@ -260,8 +276,9 @@ pub fn main() { assert!(result); } ProofSystem::KZG => { - // https://github.com/zcash/halo2/pull/661 - todo!("we need verification key serialization to be implemented"); + let result = verify_kzg_proof(proof); + info!("verified: {}", result); + assert!(result); } } } diff --git a/src/pfsys/kzg/single.rs b/src/pfsys/kzg/single.rs index 64383ee90..a4ea9eee4 100644 --- a/src/pfsys/kzg/single.rs +++ b/src/pfsys/kzg/single.rs @@ -1,17 +1,30 @@ +use super::super::Proof; +use crate::abort; +use crate::commands::Cli; use crate::fieldutils::i32_to_felt; use crate::graph::ModelCircuit; use crate::tensor::Tensor; +use clap::Parser; use halo2_proofs::{ - plonk::{create_proof, keygen_pk, keygen_vk, Circuit, ProvingKey}, - poly::kzg::{ - commitment::{KZGCommitmentScheme, ParamsKZG}, - multiopen::ProverGWC, + // arithmetic::FieldExt, + // dev::{MockProver, VerifyFailure}, + plonk::{create_proof, keygen_pk, keygen_vk, verify_proof, Circuit, ProvingKey}, + poly::{ + commitment::ParamsProver, + kzg::{ + commitment::{KZGCommitmentScheme, ParamsKZG}, + multiopen::{ProverGWC, VerifierGWC}, + strategy::SingleStrategy, + }, + }, + transcript::{ + Blake2bRead, Blake2bWrite, Challenge255, TranscriptReadBuffer, TranscriptWriterBuffer, }, - transcript::{Blake2bWrite, Challenge255, TranscriptWriterBuffer}, }; use halo2curves::bn256::{Bn256, Fr as F, G1Affine}; -use log::{info, trace}; +use log::{error, info, trace}; use rand::rngs::OsRng; +use std::marker::PhantomData; use std::ops::Deref; use std::time::Instant; @@ -59,3 +72,54 @@ pub fn create_kzg_proof( (pk, proof, dims) } + +pub fn verify_kzg_proof(proof: Proof) -> bool { + let args = Cli::parse(); + let params: ParamsKZG = ParamsKZG::new(args.logrows); + + let inputs = proof + .input_shapes + .iter() + .map( + |s| match Tensor::new(Some(&vec![0; s.iter().product()]), s) { + Ok(t) => t, + Err(e) => { + abort!("failed to initialize tensor {:?}", e); + } + }, + ) + .collect(); + let circuit = ModelCircuit:: { + inputs, + _marker: PhantomData, + }; + let empty_circuit = circuit.without_witnesses(); + let vk = keygen_vk(¶ms, &empty_circuit).expect("keygen_vk should not fail"); + let pk = keygen_pk(¶ms, vk, &empty_circuit).expect("keygen_pk should not fail"); + + let pi_inner: Vec> = proof + .public_inputs + .iter() + .map(|i| i.iter().map(|e| i32_to_felt::(*e)).collect::>()) + .collect::>>(); + let pi_inner = pi_inner.iter().map(|e| e.deref()).collect::>(); + let pi_for_real_prover: &[&[&[F]]] = &[&pi_inner]; + trace!("pi for real prover {:?}", pi_for_real_prover); + + let now = Instant::now(); + let strategy = SingleStrategy::new(¶ms); + let mut transcript = Blake2bRead::<_, _, Challenge255<_>>::init(&proof.proof[..]); + + trace!("params computed"); + + let result = verify_proof::<_, VerifierGWC<_>, _, _, _>( + ¶ms, + pk.get_vk(), + strategy, + pi_for_real_prover, + &mut transcript, + ) + .is_ok(); + info!("verify took {}", now.elapsed().as_secs()); + result +} diff --git a/tests/integration_tests.rs b/tests/integration_tests.rs index 8f643b5ed..d15e1ce6f 100644 --- a/tests/integration_tests.rs +++ b/tests/integration_tests.rs @@ -34,6 +34,7 @@ macro_rules! test_func { use crate::ipa_fullprove; use crate::ipa_prove_and_verify; use crate::kzg_fullprove; + use crate::kzg_prove_and_verify; use crate::kzg_evm_fullprove; seq!(N in 0..=11 { @@ -67,6 +68,12 @@ macro_rules! test_func { kzg_fullprove(test.to_string()); } + #(#[test_case(TESTS[N])])* + #[ignore] + fn kzg_prove_and_verify_(test: &str) { + kzg_prove_and_verify(test.to_string()); + } + // these take a particularly long time to run #(#[test_case(TESTS[N])])* #[ignore] @@ -190,6 +197,40 @@ fn ipa_prove_and_verify(example_name: String) { assert!(status.success()); } +// prove-serialize-verify, the usual full path +fn kzg_prove_and_verify(example_name: String) { + let status = Command::new("target/release/ezkl") + .args([ + "--bits=16", + "-K=17", + "prove", + "-D", + format!("./examples/onnx/examples/{}/input.json", example_name).as_str(), + "-M", + format!("./examples/onnx/examples/{}/network.onnx", example_name).as_str(), + "-O", + format!("pav_{}.pf", example_name).as_str(), + "--pfsys=kzg", + ]) + .status() + .expect("failed to execute process"); + assert!(status.success()); + let status = Command::new("target/release/ezkl") + .args([ + "--bits=16", + "-K=17", + "verify", + "--pfsys=kzg", + "-M", + format!("./examples/onnx/examples/{}/network.onnx", example_name).as_str(), + "-P", + format!("pav_{}.pf", example_name).as_str(), + ]) + .status() + .expect("failed to execute process"); + assert!(status.success()); +} + // KZG tests // full prove (slower, covers more, but still reuses the pk) fn kzg_fullprove(example_name: String) { From d26d43eeb63f41653bad39c67feef1ccbef23595 Mon Sep 17 00:00:00 2001 From: Alexander Camuto Date: Thu, 15 Dec 2022 15:28:14 +0000 Subject: [PATCH 06/20] vk serialization --- .gitignore | 1 + Cargo.toml | 2 +- src/bin/ezkl.rs | 89 +++++++++++++++++++++++--------------- src/commands.rs | 85 ++++-------------------------------- src/graph/mod.rs | 11 +++-- src/graph/model.rs | 33 ++++---------- src/pfsys/ipa.rs | 51 +++++++++++++--------- src/pfsys/kzg/single.rs | 37 ++++++---------- tests/integration_tests.rs | 10 ++++- 9 files changed, 132 insertions(+), 187 deletions(-) diff --git a/.gitignore b/.gitignore index 1120eafc9..da6ab73f7 100644 --- a/.gitignore +++ b/.gitignore @@ -2,5 +2,6 @@ target Cargo.lock data *.pf +*.vk *~ \#*\# diff --git a/Cargo.toml b/Cargo.toml index cd5860ebd..7332d8254 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -6,7 +6,7 @@ edition = "2021" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] -halo2_proofs = { git = "https://github.com/privacy-scaling-explorations/halo2", tag = "v2022_10_22"} +halo2_proofs = { git = "https://github.com/privacy-scaling-explorations/halo2", rev = "50ee8ad"} halo2curves = { git = 'https://github.com/privacy-scaling-explorations/halo2curves', tag = "0.3.0" } # nalgebra = "0.31" rand = "0.8" diff --git a/src/bin/ezkl.rs b/src/bin/ezkl.rs index 603763098..eb9e98348 100644 --- a/src/bin/ezkl.rs +++ b/src/bin/ezkl.rs @@ -2,7 +2,7 @@ use clap::Parser; use ezkl::abort; use ezkl::commands::{Cli, Commands, ProofSystem}; use ezkl::fieldutils::i32_to_felt; -use ezkl::graph::Model; +use ezkl::graph::{Model, ModelCircuit}; use ezkl::pfsys::ipa::{create_ipa_proof, verify_ipa_proof}; #[cfg(feature = "evm")] use ezkl::pfsys::kzg::aggregation::{ @@ -13,6 +13,8 @@ use ezkl::pfsys::kzg::aggregation::{ use ezkl::pfsys::kzg::single::{create_kzg_proof, verify_kzg_proof}; use ezkl::pfsys::Proof; use ezkl::pfsys::{parse_prover_errors, prepare_circuit_and_public_input, prepare_data}; +use ezkl::tensor::Tensor; +use halo2_proofs::plonk::ProvingKey; #[cfg(feature = "evm")] use halo2_proofs::poly::commitment::Params; #[cfg(not(feature = "evm"))] @@ -32,13 +34,15 @@ use halo2_proofs::{ use halo2curves::bn256::{Bn256, Fr}; use halo2curves::pasta::vesta; use halo2curves::pasta::Fp; +use halo2curves::{CurveAffine, FieldExt}; use log::{error, info, trace}; #[cfg(feature = "evm")] use plonk_verifier::system::halo2::transcript::evm::EvmTranscript; use rand::seq::SliceRandom; use std::fs::File; -use std::io::{Read, Write}; +use std::io::{BufWriter, Read, Write}; use std::ops::Deref; +use std::path::PathBuf; use std::time::Instant; use tabled::Table; @@ -194,30 +198,22 @@ pub fn main() { data, model: _, output, + vk_path, pfsys, } => { let args = Cli::parse(); let data = prepare_data(data); - let checkable_pf = match pfsys { + match pfsys { ProofSystem::IPA => { let (circuit, public_inputs) = prepare_circuit_and_public_input(&data); info!("proof with {}", pfsys); let params: ParamsIPA = ParamsIPA::new(args.logrows); trace!("params computed"); - let (_pk, proof, _input_dims) = + let (pk, proof, _) = create_ipa_proof(circuit.clone(), public_inputs.clone(), ¶ms); - let pi: Vec<_> = public_inputs - .into_iter() - .map(|i| i.into_iter().collect()) - .collect(); - - Proof { - input_shapes: circuit.inputs.iter().map(|i| i.dims().to_vec()).collect(), - public_inputs: pi, - proof, - } + save_proof(circuit, vk_path, output, pk, proof, public_inputs); } ProofSystem::KZG => { let (circuit, public_inputs) = prepare_circuit_and_public_input(&data); @@ -225,34 +221,17 @@ pub fn main() { let params: ParamsKZG = ParamsKZG::new(args.logrows); trace!("params computed"); - let (_pk, proof, _input_dims) = + let (pk, proof, _input_dims) = create_kzg_proof(circuit.clone(), public_inputs.clone(), ¶ms); - let pi: Vec<_> = public_inputs - .into_iter() - .map(|i| i.into_iter().collect()) - .collect(); - - Proof { - input_shapes: circuit.inputs.iter().map(|i| i.dims().to_vec()).collect(), - public_inputs: pi, - proof, - } + save_proof(circuit, vk_path, output, pk, proof, public_inputs); } }; - let serialized = match serde_json::to_string(&checkable_pf) { - Ok(s) => s, - Err(e) => { - abort!("failed to convert proof json to string {:?}", e); - } - }; - - let mut file = std::fs::File::create(output).expect("create failed"); - file.write_all(serialized.as_bytes()).expect("write failed"); } Commands::Verify { model: _, proof, + vk_path, pfsys, } => { let mut file = match File::open(proof) { @@ -271,12 +250,12 @@ pub fn main() { let proof: Proof = serde_json::from_str(&data).expect("JSON was not well-formatted"); match pfsys { ProofSystem::IPA => { - let result = verify_ipa_proof(proof); + let result = verify_ipa_proof(proof, vk_path); info!("verified: {}", result); assert!(result); } ProofSystem::KZG => { - let result = verify_kzg_proof(proof); + let result = verify_kzg_proof(proof, vk_path); info!("verified: {}", result); assert!(result); } @@ -285,6 +264,44 @@ pub fn main() { } } +fn save_proof( + circuit: ModelCircuit, + vk_path: Option, + output: PathBuf, + pk: ProvingKey, + proof: Vec, + public_inputs: Vec>, +) { + if let Some(path) = &vk_path { + info!("saving verification key 💾"); + let f = File::create(path).unwrap(); + let mut writer = BufWriter::new(f); + pk.get_vk().write(&mut writer).unwrap(); + writer.flush().unwrap(); + } + + let pi: Vec<_> = public_inputs + .into_iter() + .map(|i| i.into_iter().collect()) + .collect(); + + let checkable_pf = Proof { + input_shapes: circuit.inputs.iter().map(|i| i.dims().to_vec()).collect(), + public_inputs: pi, + proof, + }; + + let serialized = match serde_json::to_string(&checkable_pf) { + Ok(s) => s, + Err(e) => { + abort!("failed to convert proof json to string {:?}", e); + } + }; + + let mut file = std::fs::File::create(output).expect("create failed"); + file.write_all(serialized.as_bytes()).expect("write failed"); +} + fn banner() { let ell: Vec<&str> = vec![ "for Neural Networks", diff --git a/src/commands.rs b/src/commands.rs index 3715e25a4..94ee2179a 100644 --- a/src/commands.rs +++ b/src/commands.rs @@ -2,7 +2,7 @@ use clap::{Parser, Subcommand, ValueEnum}; use log::info; use std::io::{stdin, stdout, Write}; -use std::path::{Path, PathBuf}; +use std::path::PathBuf; #[derive(Parser, Debug)] #[command(author, version, about, long_about = None)] @@ -95,10 +95,13 @@ pub enum Commands { /// The path to the .onnx model file #[arg(short = 'M', long, default_value = "")] - model: String, + model: PathBuf, /// The path to the desired output file #[arg(short = 'O', long, default_value = "")] output: PathBuf, + /// The path to output to the desired verfication key file (optional) + #[arg(long, default_value = "")] + vk_path: Option, // /// The path to the Params for the proof system // #[arg(short = 'P', long, default_value = "")] @@ -119,11 +122,14 @@ pub enum Commands { Verify { /// The path to the .onnx model file #[arg(short = 'M', long, default_value = "")] - model: String, + model: PathBuf, /// The path to the proof file #[arg(short = 'P', long, default_value = "")] proof: PathBuf, + /// The path to output to the desired verfication key file (optional) + #[arg(long, default_value = "")] + vk_path: Option, // /// The path to the Params for the proof system // #[arg(short = 'P', long, default_value = "")] @@ -138,80 +144,7 @@ pub enum Commands { value_enum )] pfsys: ProofSystem, - // todo, allow optional vkey and params when applicable }, - // Awaiting PR to stabilize VK and PK formats - // /// Loads model and prepares verification key, saving in --output - // Vkey { - // /// The path to the .onnx model file - // #[arg(short = 'M', long, default_value = "")] - // model: String, - // /// The path to the desired output file - // #[arg(short = 'O', long, default_value = "")] - // output: PathBuf, - - // /// The path to the Params for the proof system - // #[arg(short = 'P', long, default_value = "")] - // params: PathBuf, - - // #[arg( - // long, - // short = 'B', - // require_equals = true, - // num_args = 0..=1, - // default_value_t = ProofSystem::IPA, - // default_missing_value = "always", - // value_enum - // )] - // pfsys: ProofSystem, - // }, - - // /// Loads model and prepares verification and proving key, saving proving key in --output - // Pkey { - // /// The path to the .onnx model file - // #[arg(short = 'M', long, default_value = "")] - // model: String, - // /// The path to the desired output file - // #[arg(short = 'O', long, default_value = "")] - // output: PathBuf, - - // /// The path to the Params for the proof system - // #[arg(short = 'P', long, default_value = "")] - // params: PathBuf, - - // #[arg( - // long, - // short = 'B', - // require_equals = true, - // num_args = 0..=1, - // default_value_t = ProofSystem::IPA, - // default_missing_value = "always", - // value_enum - // )] - // pfsys: ProofSystem, - // // todo, optionally allow supplying verification key - // }, -} - -pub fn model_path(model: String) -> PathBuf { - let mut s = String::new(); - let model_path = match model.is_empty() { - false => { - info!("loading model from {}", model.clone()); - Path::new(&model) - } - true => { - info!("please enter a path to a .onnx file containing a model: "); - let _ = stdout().flush(); - let _ = &stdin() - .read_line(&mut s) - .expect("did not enter a correct string"); - s.truncate(s.len() - 1); - Path::new(&s) - } - }; - assert!(model_path.exists()); - model_path.into() } pub fn data_path(data: String) -> PathBuf { diff --git a/src/graph/mod.rs b/src/graph/mod.rs index 4dbe3d91d..cf9de7dcb 100644 --- a/src/graph/mod.rs +++ b/src/graph/mod.rs @@ -34,23 +34,22 @@ impl Circuit for ModelCircuit { fn configure(cs: &mut ConstraintSystem) -> Self::Config { let model = Model::from_arg(); - let num_advice: usize; let mut num_fixed = 0; let row_cap = model.max_node_size(); // TODO: extract max number of params in a given fused layer - if model.visibility.params.is_public() { + let num_advice: usize = if model.visibility.params.is_public() { num_fixed += model.max_node_params(); // this is the maximum of variables in non-fused layer, and the maximum of variables (non-params) in fused layers - num_advice = max(model.max_node_vars_non_fused(), model.max_node_vars_fused()); + max(model.max_node_vars_non_fused(), model.max_node_vars_fused()) } else { // this is the maximum of variables in non-fused layer, and the maximum of variables (non-params) in fused layers // + the max number of params in a fused layer - num_advice = max( + max( model.max_node_vars_non_fused(), model.max_node_params() + model.max_node_vars_fused(), - ); - } + ) + }; // for now the number of instances corresponds to the number of graph / model outputs let mut num_instances = 0; let mut instance_shapes = vec![]; diff --git a/src/graph/model.rs b/src/graph/model.rs index 11f71b2d3..8f3dd63d3 100644 --- a/src/graph/model.rs +++ b/src/graph/model.rs @@ -4,7 +4,7 @@ use super::vars::*; use crate::circuit::eltwise::{DivideBy, EltwiseConfig, ReLu, Sigmoid}; use crate::circuit::fused::*; use crate::circuit::range::*; -use crate::commands::{model_path, Cli, Commands}; +use crate::commands::{Cli, Commands}; use crate::tensor::TensorType; use crate::tensor::{Tensor, ValTensor, VarTensor}; use anyhow::{Context, Result}; @@ -108,7 +108,7 @@ impl Model { let visibility = VarVisibility::from_args(); match args.command { Commands::Table { model } => Model::new( - model_path(model), + model, args.scale, args.bits, args.logrows, @@ -116,8 +116,8 @@ impl Model { Mode::Table, visibility, ), - Commands::Mock { data: _, model } => Model::new( - model_path(model), + Commands::Mock { model, .. } => Model::new( + model, args.scale, args.bits, args.logrows, @@ -125,12 +125,8 @@ impl Model { Mode::Mock, visibility, ), - Commands::Fullprove { - data: _, + Commands::Fullprove { model, .. } => Model::new( model, - pfsys: _, - } => Model::new( - model_path(model), args.scale, args.bits, args.logrows, @@ -138,13 +134,8 @@ impl Model { Mode::FullProve, visibility, ), - Commands::Prove { - data: _, + Commands::Prove { model, .. } => Model::new( model, - output: _, - pfsys: _, - } => Model::new( - model_path(model), args.scale, args.bits, args.logrows, @@ -152,12 +143,8 @@ impl Model { Mode::Prove, visibility, ), - Commands::Verify { + Commands::Verify { model, .. } => Model::new( model, - proof: _, - pfsys: _, - } => Model::new( - model_path(model), args.scale, args.bits, args.logrows, @@ -309,7 +296,7 @@ impl Model { .filter(|i| !nodes.contains_key(&i.idx) && seen.insert(i.idx)) .map(|f| { let s = f.out_dims.clone(); - let a = if f.opkind.is_const() && self.visibility.params.is_public() { + if f.opkind.is_const() && self.visibility.params.is_public() { let vars = (f.idx, vars.fixed[fixed_idx].reshape(&s)); fixed_idx += 1; vars @@ -317,9 +304,7 @@ impl Model { let vars = (f.idx, vars.advices[advice_idx].reshape(&s)); advice_idx += 1; vars - }; - - a + } }) .collect_vec() }) diff --git a/src/pfsys/ipa.rs b/src/pfsys/ipa.rs index 37875ce4e..359ac0a20 100644 --- a/src/pfsys/ipa.rs +++ b/src/pfsys/ipa.rs @@ -8,7 +8,7 @@ use clap::Parser; use halo2_proofs::{ // arithmetic::FieldExt, // dev::{MockProver, VerifyFailure}, - plonk::{create_proof, keygen_pk, keygen_vk, verify_proof, Circuit, ProvingKey}, + plonk::{create_proof, keygen_pk, keygen_vk, verify_proof, Circuit, ProvingKey, VerifyingKey}, poly::{ commitment::ParamsProver, ipa::{ @@ -28,8 +28,9 @@ use halo2curves::pasta::{EqAffine, Fp as F}; use log::{error, info, trace}; use rand::rngs::OsRng; use std::marker::PhantomData; -use std::ops::Deref; use std::time::Instant; +use std::{fs::File, path::PathBuf}; +use std::{io::BufReader, ops::Deref}; pub fn create_ipa_proof( circuit: ModelCircuit, @@ -76,28 +77,38 @@ pub fn create_ipa_proof( (pk, proof, dims) } -pub fn verify_ipa_proof(proof: Proof) -> bool { +pub fn verify_ipa_proof(proof: Proof, vk_path: Option) -> bool { let args = Cli::parse(); let params: ParamsIPA = ParamsIPA::new(args.logrows); - let inputs = proof - .input_shapes - .iter() - .map( - |s| match Tensor::new(Some(&vec![0; s.iter().product()]), s) { - Ok(t) => t, - Err(e) => { - abort!("failed to initialize tensor {:?}", e); - } - }, - ) - .collect(); - let circuit = ModelCircuit:: { - inputs, - _marker: PhantomData, + let vk = match vk_path { + None => { + let inputs = proof + .input_shapes + .iter() + .map( + |s| match Tensor::new(Some(&vec![0; s.iter().product()]), s) { + Ok(t) => t, + Err(e) => { + abort!("failed to initialize tensor {:?}", e); + } + }, + ) + .collect(); + let circuit = ModelCircuit:: { + inputs, + _marker: PhantomData, + }; + let empty_circuit = circuit.without_witnesses(); + keygen_vk(¶ms, &empty_circuit).expect("keygen_vk should not fail") + } + Some(path) => { + info!("loading verification key from {:?}", path); + let f = File::open(path).unwrap(); + let mut reader = BufReader::new(f); + VerifyingKey::::read::<_, ModelCircuit>(&mut reader, ¶ms).unwrap() + } }; - let empty_circuit = circuit.without_witnesses(); - let vk = keygen_vk(¶ms, &empty_circuit).expect("keygen_vk should not fail"); let pi_inner: Vec> = proof .public_inputs diff --git a/src/pfsys/kzg/single.rs b/src/pfsys/kzg/single.rs index a4ea9eee4..1654ace11 100644 --- a/src/pfsys/kzg/single.rs +++ b/src/pfsys/kzg/single.rs @@ -8,7 +8,7 @@ use clap::Parser; use halo2_proofs::{ // arithmetic::FieldExt, // dev::{MockProver, VerifyFailure}, - plonk::{create_proof, keygen_pk, keygen_vk, verify_proof, Circuit, ProvingKey}, + plonk::{create_proof, keygen_pk, keygen_vk, verify_proof, Circuit, ProvingKey, VerifyingKey}, poly::{ commitment::ParamsProver, kzg::{ @@ -24,9 +24,9 @@ use halo2_proofs::{ use halo2curves::bn256::{Bn256, Fr as F, G1Affine}; use log::{error, info, trace}; use rand::rngs::OsRng; -use std::marker::PhantomData; -use std::ops::Deref; use std::time::Instant; +use std::{fs::File, path::PathBuf}; +use std::{io::BufReader, ops::Deref}; pub fn create_kzg_proof( circuit: ModelCircuit, @@ -73,29 +73,20 @@ pub fn create_kzg_proof( (pk, proof, dims) } -pub fn verify_kzg_proof(proof: Proof) -> bool { +pub fn verify_kzg_proof(proof: Proof, vk_path: Option) -> bool { let args = Cli::parse(); let params: ParamsKZG = ParamsKZG::new(args.logrows); - let inputs = proof - .input_shapes - .iter() - .map( - |s| match Tensor::new(Some(&vec![0; s.iter().product()]), s) { - Ok(t) => t, - Err(e) => { - abort!("failed to initialize tensor {:?}", e); - } - }, - ) - .collect(); - let circuit = ModelCircuit:: { - inputs, - _marker: PhantomData, + let vk = match vk_path { + None => { + abort!("kzg verify requires a path to a verification key"); + } + Some(path) => { + let f = File::open(path).unwrap(); + let mut reader = BufReader::new(f); + VerifyingKey::::read::<_, ModelCircuit>(&mut reader, ¶ms).unwrap() + } }; - let empty_circuit = circuit.without_witnesses(); - let vk = keygen_vk(¶ms, &empty_circuit).expect("keygen_vk should not fail"); - let pk = keygen_pk(¶ms, vk, &empty_circuit).expect("keygen_pk should not fail"); let pi_inner: Vec> = proof .public_inputs @@ -114,7 +105,7 @@ pub fn verify_kzg_proof(proof: Proof) -> bool { let result = verify_proof::<_, VerifierGWC<_>, _, _, _>( ¶ms, - pk.get_vk(), + &vk, strategy, pi_for_real_prover, &mut transcript, diff --git a/tests/integration_tests.rs b/tests/integration_tests.rs index d15e1ce6f..c0e63726a 100644 --- a/tests/integration_tests.rs +++ b/tests/integration_tests.rs @@ -178,6 +178,8 @@ fn ipa_prove_and_verify(example_name: String) { format!("./examples/onnx/examples/{}/network.onnx", example_name).as_str(), "-O", format!("pav_{}.pf", example_name).as_str(), + "--vk-path", + format!("pav_{}.vk", example_name).as_str(), ]) .status() .expect("failed to execute process"); @@ -191,6 +193,8 @@ fn ipa_prove_and_verify(example_name: String) { format!("./examples/onnx/examples/{}/network.onnx", example_name).as_str(), "-P", format!("pav_{}.pf", example_name).as_str(), + "--vk-path", + format!("pav_{}.vk", example_name).as_str(), ]) .status() .expect("failed to execute process"); @@ -204,13 +208,15 @@ fn kzg_prove_and_verify(example_name: String) { "--bits=16", "-K=17", "prove", + "--pfsys=kzg", "-D", format!("./examples/onnx/examples/{}/input.json", example_name).as_str(), "-M", format!("./examples/onnx/examples/{}/network.onnx", example_name).as_str(), "-O", format!("pav_{}.pf", example_name).as_str(), - "--pfsys=kzg", + "--vk-path", + format!("pav_{}.vk", example_name).as_str(), ]) .status() .expect("failed to execute process"); @@ -225,6 +231,8 @@ fn kzg_prove_and_verify(example_name: String) { format!("./examples/onnx/examples/{}/network.onnx", example_name).as_str(), "-P", format!("pav_{}.pf", example_name).as_str(), + "--vk-path", + format!("pav_{}.vk", example_name).as_str(), ]) .status() .expect("failed to execute process"); From 04cedd1f6bf45ae545ac3090e6f42eb698813e2e Mon Sep 17 00:00:00 2001 From: Alexander Camuto Date: Thu, 15 Dec 2022 17:43:23 +0000 Subject: [PATCH 07/20] cleanup --- src/bin/ezkl.rs | 156 +++++++++---------------- src/commands.rs | 2 +- src/pfsys/{kzg => }/aggregation.rs | 0 src/pfsys/ipa.rs | 131 --------------------- src/pfsys/kzg/mod.rs | 5 - src/pfsys/kzg/single.rs | 116 ------------------- src/pfsys/mod.rs | 178 ++++++++++++++++++++++++++++- tests/integration_tests.rs | 18 +-- 8 files changed, 239 insertions(+), 367 deletions(-) rename src/pfsys/{kzg => }/aggregation.rs (100%) delete mode 100644 src/pfsys/ipa.rs delete mode 100644 src/pfsys/kzg/mod.rs delete mode 100644 src/pfsys/kzg/single.rs diff --git a/src/bin/ezkl.rs b/src/bin/ezkl.rs index eb9e98348..9f13aa361 100644 --- a/src/bin/ezkl.rs +++ b/src/bin/ezkl.rs @@ -2,48 +2,45 @@ use clap::Parser; use ezkl::abort; use ezkl::commands::{Cli, Commands, ProofSystem}; use ezkl::fieldutils::i32_to_felt; -use ezkl::graph::{Model, ModelCircuit}; -use ezkl::pfsys::ipa::{create_ipa_proof, verify_ipa_proof}; +use ezkl::graph::Model; #[cfg(feature = "evm")] use ezkl::pfsys::kzg::aggregation::{ aggregation::AggregationCircuit, evm_verify, gen_aggregation_evm_verifier, gen_application_snark, gen_kzg_proof, gen_pk, gen_srs, }; #[cfg(not(feature = "evm"))] -use ezkl::pfsys::kzg::single::{create_kzg_proof, verify_kzg_proof}; -use ezkl::pfsys::Proof; -use ezkl::pfsys::{parse_prover_errors, prepare_circuit_and_public_input, prepare_data}; -use ezkl::tensor::Tensor; -use halo2_proofs::plonk::ProvingKey; +use ezkl::pfsys::{ + create_proof_model, parse_prover_errors, prepare_circuit_and_public_input, prepare_data, + save_proof, verify_proof_model, +}; +use ezkl::pfsys::{load_vk, Proof}; #[cfg(feature = "evm")] use halo2_proofs::poly::commitment::Params; +use halo2_proofs::poly::ipa::commitment::IPACommitmentScheme; +use halo2_proofs::poly::ipa::multiopen::ProverIPA; +use halo2_proofs::poly::kzg::commitment::KZGCommitmentScheme; +use halo2_proofs::poly::kzg::multiopen::ProverGWC; #[cfg(not(feature = "evm"))] use halo2_proofs::poly::kzg::{ commitment::ParamsKZG, multiopen::VerifierGWC, strategy::SingleStrategy as KZGSingleStrategy, }; use halo2_proofs::{ dev::MockProver, - plonk::verify_proof, poly::{ commitment::ParamsProver, ipa::{commitment::ParamsIPA, strategy::SingleStrategy as IPASingleStrategy}, VerificationStrategy, }, - transcript::{Blake2bRead, Challenge255, TranscriptReadBuffer}, }; use halo2curves::bn256::{Bn256, Fr}; use halo2curves::pasta::vesta; use halo2curves::pasta::Fp; -use halo2curves::{CurveAffine, FieldExt}; use log::{error, info, trace}; #[cfg(feature = "evm")] use plonk_verifier::system::halo2::transcript::evm::EvmTranscript; use rand::seq::SliceRandom; use std::fs::File; -use std::io::{BufWriter, Read, Write}; -use std::ops::Deref; -use std::path::PathBuf; -use std::time::Instant; +use std::io::Read; use tabled::Table; pub fn main() { @@ -93,66 +90,46 @@ pub fn main() { // A direct proof let args = Cli::parse(); let data = prepare_data(data); + match pfsys { ProofSystem::IPA => { - let (circuit, public_inputs) = prepare_circuit_and_public_input(&data); + let (circuit, public_inputs) = prepare_circuit_and_public_input::(&data); info!("full proof with {}", pfsys); let params: ParamsIPA = ParamsIPA::new(args.logrows); + let strategy = IPASingleStrategy::new(¶ms); trace!("params computed"); let (pk, proof, _dims) = - create_ipa_proof(circuit, public_inputs.clone(), ¶ms); - - let pi_inner: Vec> = public_inputs - .iter() - .map(|i| i.iter().map(|e| i32_to_felt::(*e)).collect::>()) - .collect::>>(); - let pi_inner = pi_inner.iter().map(|e| e.deref()).collect::>(); - let pi_for_real_prover: &[&[&[Fp]]] = &[&pi_inner]; + create_proof_model::, Fp, ProverIPA<_>>( + circuit, + public_inputs.clone(), + ¶ms, + ); - let now = Instant::now(); - let strategy = IPASingleStrategy::new(¶ms); - let mut transcript = Blake2bRead::<_, _, Challenge255<_>>::init(&proof[..]); - assert!(verify_proof( - ¶ms, - pk.get_vk(), - strategy, - pi_for_real_prover, - &mut transcript - ) - .is_ok()); - info!("verify took {}", now.elapsed().as_secs()); + assert!(verify_proof_model(proof, ¶ms, pk.get_vk(), strategy)); } #[cfg(not(feature = "evm"))] ProofSystem::KZG => { // A direct proof - let (circuit, public_inputs) = prepare_circuit_and_public_input(&data); + let (circuit, public_inputs) = prepare_circuit_and_public_input::(&data); let params: ParamsKZG = ParamsKZG::new(args.logrows); + let strategy = KZGSingleStrategy::new(¶ms); trace!("params computed"); let (pk, proof, _dims) = - create_kzg_proof(circuit, public_inputs.clone(), ¶ms); - - let pi_inner: Vec> = public_inputs - .iter() - .map(|i| i.iter().map(|e| i32_to_felt::(*e)).collect::>()) - .collect::>>(); - let pi_inner = pi_inner.iter().map(|e| e.deref()).collect::>(); - let pi_for_real_prover: &[&[&[Fr]]] = &[&pi_inner]; + create_proof_model::, Fr, ProverGWC<_>>( + circuit, + public_inputs.clone(), + ¶ms, + ); - let now = Instant::now(); - let strategy = KZGSingleStrategy::new(¶ms); - let mut transcript = Blake2bRead::<_, _, Challenge255<_>>::init(&proof[..]); - assert!(verify_proof::<_, VerifierGWC<_>, _, _, _>( + assert!(verify_proof_model::<_, VerifierGWC<'_, Bn256>, _, _>( + proof, ¶ms, pk.get_vk(), - strategy, - pi_for_real_prover, - &mut transcript - ) - .is_ok()); - info!("verify took {}", now.elapsed().as_secs()); + strategy + )); } #[cfg(feature = "evm")] ProofSystem::KZG => { @@ -203,28 +180,37 @@ pub fn main() { } => { let args = Cli::parse(); let data = prepare_data(data); + match pfsys { ProofSystem::IPA => { - let (circuit, public_inputs) = prepare_circuit_and_public_input(&data); info!("proof with {}", pfsys); + let (circuit, public_inputs) = prepare_circuit_and_public_input::(&data); let params: ParamsIPA = ParamsIPA::new(args.logrows); trace!("params computed"); let (pk, proof, _) = - create_ipa_proof(circuit.clone(), public_inputs.clone(), ¶ms); + create_proof_model::, Fp, ProverIPA<_>>( + circuit.clone(), + public_inputs.clone(), + ¶ms, + ); - save_proof(circuit, vk_path, output, pk, proof, public_inputs); + save_proof::<_, Fp>(vk_path, output, pk, proof); } ProofSystem::KZG => { - let (circuit, public_inputs) = prepare_circuit_and_public_input(&data); info!("proof with {}", pfsys); + let (circuit, public_inputs) = prepare_circuit_and_public_input(&data); let params: ParamsKZG = ParamsKZG::new(args.logrows); trace!("params computed"); let (pk, proof, _input_dims) = - create_kzg_proof(circuit.clone(), public_inputs.clone(), ¶ms); + create_proof_model::, Fr, ProverGWC<_>>( + circuit.clone(), + public_inputs.clone(), + ¶ms, + ); - save_proof(circuit, vk_path, output, pk, proof, public_inputs); + save_proof::<_, Fr>(vk_path, output, pk, proof); } }; } @@ -250,12 +236,20 @@ pub fn main() { let proof: Proof = serde_json::from_str(&data).expect("JSON was not well-formatted"); match pfsys { ProofSystem::IPA => { - let result = verify_ipa_proof(proof, vk_path); + let params: ParamsIPA = ParamsIPA::new(args.logrows); + let strategy = IPASingleStrategy::new(¶ms); + let vk = load_vk::, Fp>(vk_path, ¶ms); + let result = verify_proof_model(proof, ¶ms, &vk, strategy); info!("verified: {}", result); assert!(result); } ProofSystem::KZG => { - let result = verify_kzg_proof(proof, vk_path); + let params: ParamsKZG = ParamsKZG::new(args.logrows); + let strategy = KZGSingleStrategy::new(¶ms); + let vk = load_vk::, Fr>(vk_path, ¶ms); + let result = verify_proof_model::<_, VerifierGWC<'_, Bn256>, _, _>( + proof, ¶ms, &vk, strategy, + ); info!("verified: {}", result); assert!(result); } @@ -264,44 +258,6 @@ pub fn main() { } } -fn save_proof( - circuit: ModelCircuit, - vk_path: Option, - output: PathBuf, - pk: ProvingKey, - proof: Vec, - public_inputs: Vec>, -) { - if let Some(path) = &vk_path { - info!("saving verification key 💾"); - let f = File::create(path).unwrap(); - let mut writer = BufWriter::new(f); - pk.get_vk().write(&mut writer).unwrap(); - writer.flush().unwrap(); - } - - let pi: Vec<_> = public_inputs - .into_iter() - .map(|i| i.into_iter().collect()) - .collect(); - - let checkable_pf = Proof { - input_shapes: circuit.inputs.iter().map(|i| i.dims().to_vec()).collect(), - public_inputs: pi, - proof, - }; - - let serialized = match serde_json::to_string(&checkable_pf) { - Ok(s) => s, - Err(e) => { - abort!("failed to convert proof json to string {:?}", e); - } - }; - - let mut file = std::fs::File::create(output).expect("create failed"); - file.write_all(serialized.as_bytes()).expect("write failed"); -} - fn banner() { let ell: Vec<&str> = vec![ "for Neural Networks", diff --git a/src/commands.rs b/src/commands.rs index 94ee2179a..9a91fa123 100644 --- a/src/commands.rs +++ b/src/commands.rs @@ -129,7 +129,7 @@ pub enum Commands { proof: PathBuf, /// The path to output to the desired verfication key file (optional) #[arg(long, default_value = "")] - vk_path: Option, + vk_path: PathBuf, // /// The path to the Params for the proof system // #[arg(short = 'P', long, default_value = "")] diff --git a/src/pfsys/kzg/aggregation.rs b/src/pfsys/aggregation.rs similarity index 100% rename from src/pfsys/kzg/aggregation.rs rename to src/pfsys/aggregation.rs diff --git a/src/pfsys/ipa.rs b/src/pfsys/ipa.rs deleted file mode 100644 index 359ac0a20..000000000 --- a/src/pfsys/ipa.rs +++ /dev/null @@ -1,131 +0,0 @@ -use super::Proof; -use crate::abort; -use crate::commands::Cli; -use crate::fieldutils::i32_to_felt; -use crate::graph::ModelCircuit; -use crate::tensor::Tensor; -use clap::Parser; -use halo2_proofs::{ - // arithmetic::FieldExt, - // dev::{MockProver, VerifyFailure}, - plonk::{create_proof, keygen_pk, keygen_vk, verify_proof, Circuit, ProvingKey, VerifyingKey}, - poly::{ - commitment::ParamsProver, - ipa::{ - commitment::{IPACommitmentScheme, ParamsIPA}, - multiopen::ProverIPA, - strategy::SingleStrategy, - }, - VerificationStrategy, - }, - transcript::{ - Blake2bRead, Blake2bWrite, Challenge255, TranscriptReadBuffer, TranscriptWriterBuffer, - }, -}; -use halo2curves::pasta::vesta; -use halo2curves::pasta::Fp; -use halo2curves::pasta::{EqAffine, Fp as F}; -use log::{error, info, trace}; -use rand::rngs::OsRng; -use std::marker::PhantomData; -use std::time::Instant; -use std::{fs::File, path::PathBuf}; -use std::{io::BufReader, ops::Deref}; - -pub fn create_ipa_proof( - circuit: ModelCircuit, - public_inputs: Vec>, - params: &ParamsIPA, -) -> (ProvingKey, Vec, Vec>) { - // Real proof - let empty_circuit = circuit.without_witnesses(); - - // Initialize the proving key - let now = Instant::now(); - trace!("preparing VK"); - let vk = keygen_vk(params, &empty_circuit).expect("keygen_vk should not fail"); - info!("VK took {}", now.elapsed().as_secs()); - let now = Instant::now(); - let pk = keygen_pk(params, vk, &empty_circuit).expect("keygen_pk should not fail"); - info!("PK took {}", now.elapsed().as_secs()); - let now = Instant::now(); - let mut transcript = Blake2bWrite::<_, _, Challenge255<_>>::init(vec![]); - let mut rng = OsRng; - - let pi_inner: Vec> = public_inputs - .iter() - .map(|i| i.iter().map(|e| i32_to_felt::(*e)).collect::>()) - .collect::>>(); - let pi_inner = pi_inner.iter().map(|e| e.deref()).collect::>(); - let pi_for_real_prover: &[&[&[F]]] = &[&pi_inner]; - trace!("pi for real prover {:?}", pi_for_real_prover); - - let dims = circuit.inputs.iter().map(|i| i.dims().to_vec()).collect(); - - create_proof::, ProverIPA<_>, _, _, _, _>( - params, - &pk, - &[circuit], - pi_for_real_prover, - &mut rng, - &mut transcript, - ) - .expect("proof generation should not fail"); - let proof = transcript.finalize(); - info!("Proof took {}", now.elapsed().as_secs()); - - (pk, proof, dims) -} - -pub fn verify_ipa_proof(proof: Proof, vk_path: Option) -> bool { - let args = Cli::parse(); - let params: ParamsIPA = ParamsIPA::new(args.logrows); - - let vk = match vk_path { - None => { - let inputs = proof - .input_shapes - .iter() - .map( - |s| match Tensor::new(Some(&vec![0; s.iter().product()]), s) { - Ok(t) => t, - Err(e) => { - abort!("failed to initialize tensor {:?}", e); - } - }, - ) - .collect(); - let circuit = ModelCircuit:: { - inputs, - _marker: PhantomData, - }; - let empty_circuit = circuit.without_witnesses(); - keygen_vk(¶ms, &empty_circuit).expect("keygen_vk should not fail") - } - Some(path) => { - info!("loading verification key from {:?}", path); - let f = File::open(path).unwrap(); - let mut reader = BufReader::new(f); - VerifyingKey::::read::<_, ModelCircuit>(&mut reader, ¶ms).unwrap() - } - }; - - let pi_inner: Vec> = proof - .public_inputs - .iter() - .map(|i| i.iter().map(|e| i32_to_felt::(*e)).collect::>()) - .collect::>>(); - let pi_inner = pi_inner.iter().map(|e| e.deref()).collect::>(); - let pi_for_real_prover: &[&[&[F]]] = &[&pi_inner]; - trace!("pi for real prover {:?}", pi_for_real_prover); - - let now = Instant::now(); - let strategy = SingleStrategy::new(¶ms); - let mut transcript = Blake2bRead::<_, _, Challenge255<_>>::init(&proof.proof[..]); - - trace!("params computed"); - - let result = verify_proof(¶ms, &vk, strategy, pi_for_real_prover, &mut transcript).is_ok(); - info!("verify took {}", now.elapsed().as_secs()); - result -} diff --git a/src/pfsys/kzg/mod.rs b/src/pfsys/kzg/mod.rs deleted file mode 100644 index 7a3e8ccfb..000000000 --- a/src/pfsys/kzg/mod.rs +++ /dev/null @@ -1,5 +0,0 @@ -/// Aggregation circuit -#[cfg(feature = "evm")] -pub mod aggregation; - -pub mod single; diff --git a/src/pfsys/kzg/single.rs b/src/pfsys/kzg/single.rs deleted file mode 100644 index 1654ace11..000000000 --- a/src/pfsys/kzg/single.rs +++ /dev/null @@ -1,116 +0,0 @@ -use super::super::Proof; -use crate::abort; -use crate::commands::Cli; -use crate::fieldutils::i32_to_felt; -use crate::graph::ModelCircuit; -use crate::tensor::Tensor; -use clap::Parser; -use halo2_proofs::{ - // arithmetic::FieldExt, - // dev::{MockProver, VerifyFailure}, - plonk::{create_proof, keygen_pk, keygen_vk, verify_proof, Circuit, ProvingKey, VerifyingKey}, - poly::{ - commitment::ParamsProver, - kzg::{ - commitment::{KZGCommitmentScheme, ParamsKZG}, - multiopen::{ProverGWC, VerifierGWC}, - strategy::SingleStrategy, - }, - }, - transcript::{ - Blake2bRead, Blake2bWrite, Challenge255, TranscriptReadBuffer, TranscriptWriterBuffer, - }, -}; -use halo2curves::bn256::{Bn256, Fr as F, G1Affine}; -use log::{error, info, trace}; -use rand::rngs::OsRng; -use std::time::Instant; -use std::{fs::File, path::PathBuf}; -use std::{io::BufReader, ops::Deref}; - -pub fn create_kzg_proof( - circuit: ModelCircuit, - public_inputs: Vec>, - params: &ParamsKZG, -) -> (ProvingKey, Vec, Vec>) { - // Real proof - let empty_circuit = circuit.without_witnesses(); - - // Initialize the proving key - let now = Instant::now(); - trace!("preparing VK"); - let vk = keygen_vk(params, &empty_circuit).expect("keygen_vk should not fail"); - info!("VK took {}", now.elapsed().as_secs()); - let now = Instant::now(); - let pk = keygen_pk(params, vk, &empty_circuit).expect("keygen_pk should not fail"); - info!("PK took {}", now.elapsed().as_secs()); - let now = Instant::now(); - let mut transcript = Blake2bWrite::<_, _, Challenge255<_>>::init(vec![]); - let mut rng = OsRng; - - let pi_inner: Vec> = public_inputs - .iter() - .map(|i| i.iter().map(|e| i32_to_felt::(*e)).collect::>()) - .collect::>>(); - let pi_inner = pi_inner.iter().map(|e| e.deref()).collect::>(); - let pi_for_real_prover: &[&[&[F]]] = &[&pi_inner]; - trace!("pi for real prover {:?}", pi_for_real_prover); - - let dims = circuit.inputs.iter().map(|i| i.dims().to_vec()).collect(); - - create_proof::, ProverGWC<_>, _, _, _, _>( - params, - &pk, - &[circuit], - pi_for_real_prover, - &mut rng, - &mut transcript, - ) - .expect("proof generation should not fail"); - let proof = transcript.finalize(); - info!("Proof took {}", now.elapsed().as_secs()); - - (pk, proof, dims) -} - -pub fn verify_kzg_proof(proof: Proof, vk_path: Option) -> bool { - let args = Cli::parse(); - let params: ParamsKZG = ParamsKZG::new(args.logrows); - - let vk = match vk_path { - None => { - abort!("kzg verify requires a path to a verification key"); - } - Some(path) => { - let f = File::open(path).unwrap(); - let mut reader = BufReader::new(f); - VerifyingKey::::read::<_, ModelCircuit>(&mut reader, ¶ms).unwrap() - } - }; - - let pi_inner: Vec> = proof - .public_inputs - .iter() - .map(|i| i.iter().map(|e| i32_to_felt::(*e)).collect::>()) - .collect::>>(); - let pi_inner = pi_inner.iter().map(|e| e.deref()).collect::>(); - let pi_for_real_prover: &[&[&[F]]] = &[&pi_inner]; - trace!("pi for real prover {:?}", pi_for_real_prover); - - let now = Instant::now(); - let strategy = SingleStrategy::new(¶ms); - let mut transcript = Blake2bRead::<_, _, Challenge255<_>>::init(&proof.proof[..]); - - trace!("params computed"); - - let result = verify_proof::<_, VerifierGWC<_>, _, _, _>( - ¶ms, - &vk, - strategy, - pi_for_real_prover, - &mut transcript, - ) - .is_ok(); - info!("verify took {}", now.elapsed().as_secs()); - result -} diff --git a/src/pfsys/mod.rs b/src/pfsys/mod.rs index 0c0f9c700..497082a4b 100644 --- a/src/pfsys/mod.rs +++ b/src/pfsys/mod.rs @@ -1,18 +1,32 @@ -// Really these are halo2 plonkish IOP + commitment scheme, but we only support Plonkish IOP so far, so there is no ambiguity -pub mod ipa; -pub mod kzg; +/// Aggregation circuit +#[cfg(feature = "evm")] +pub mod aggregation; use crate::abort; use crate::commands::{data_path, Cli}; +use crate::fieldutils::i32_to_felt; use crate::graph::{utilities::vector_to_quantized, Model, ModelCircuit}; -use crate::tensor::Tensor; +use crate::tensor::{Tensor, TensorType}; use clap::Parser; +use halo2_proofs::plonk::{ + create_proof, keygen_pk, keygen_vk, verify_proof, Circuit, ProvingKey, VerifyingKey, +}; +use halo2_proofs::poly::commitment::{CommitmentScheme, Prover, Verifier}; +use halo2_proofs::poly::VerificationStrategy; +use halo2_proofs::transcript::{ + Blake2bRead, Blake2bWrite, Challenge255, TranscriptReadBuffer, TranscriptWriterBuffer, +}; use halo2_proofs::{arithmetic::FieldExt, dev::VerifyFailure}; +use halo2curves::CurveAffine; use log::{error, info, trace}; +use rand::rngs::OsRng; use serde::{Deserialize, Serialize}; use std::fs::File; -use std::io::Read; +use std::io::{BufReader, BufWriter, Read, Write}; use std::marker::PhantomData; +use std::ops::Deref; +use std::path::PathBuf; +use std::time::Instant; #[derive(Clone, Debug, Deserialize, Serialize)] pub struct ModelInput { @@ -164,3 +178,157 @@ pub fn prepare_data(datapath: String) -> ModelInput { data } + +// a wrapper around halo2's create proof +pub fn create_proof_model< + 'params, + Scheme: CommitmentScheme, + F: FieldExt + TensorType, + P: Prover<'params, Scheme>, +>( + circuit: ModelCircuit, + public_inputs: Vec>, + params: &'params Scheme::ParamsProver, +) -> (ProvingKey, Proof, Vec>) +where + ModelCircuit: Circuit, +{ + // Real proof + let empty_circuit = circuit.without_witnesses(); + + // Initialize the proving key + let now = Instant::now(); + trace!("preparing VK"); + let vk = keygen_vk(params, &empty_circuit).expect("keygen_vk should not fail"); + info!("VK took {}", now.elapsed().as_secs()); + let now = Instant::now(); + let pk = keygen_pk(params, vk, &empty_circuit).expect("keygen_pk should not fail"); + info!("PK took {}", now.elapsed().as_secs()); + let now = Instant::now(); + let mut transcript = Blake2bWrite::<_, Scheme::Curve, Challenge255<_>>::init(vec![]); + let mut rng = OsRng; + + let pi_inner: Vec> = public_inputs + .iter() + .map(|i| { + i.iter() + .map(|e| i32_to_felt::(*e)) + .collect::>() + }) + .collect::>>(); + let pi_inner = pi_inner + .iter() + .map(|e| e.deref()) + .collect::>(); + let instances: &[&[&[Scheme::Scalar]]] = &[&pi_inner]; + trace!("instances {:?}", instances); + + let dims = circuit.inputs.iter().map(|i| i.dims().to_vec()).collect(); + + create_proof::( + ¶ms, + &pk, + &[circuit.clone()], + instances, + &mut rng, + &mut transcript, + ) + .expect("proof generation should not fail"); + let proof = transcript.finalize(); + info!("Proof took {}", now.elapsed().as_secs()); + + let checkable_pf = Proof { + input_shapes: circuit.inputs.iter().map(|i| i.dims().to_vec()).collect(), + public_inputs: public_inputs + .into_iter() + .map(|i| i.into_iter().collect()) + .collect(), + proof, + }; + + (pk, checkable_pf, dims) +} + +pub fn verify_proof_model< + 'params, + F: FieldExt, + V: Verifier<'params, Scheme>, + Scheme: CommitmentScheme, + Strategy: VerificationStrategy<'params, Scheme, V>, +>( + proof: Proof, + params: &'params Scheme::ParamsVerifier, + vk: &VerifyingKey, + strategy: Strategy, +) -> bool +where + ModelCircuit: Circuit, +{ + let pi_inner: Vec> = proof + .public_inputs + .iter() + .map(|i| { + i.iter() + .map(|e| i32_to_felt::(*e)) + .collect::>() + }) + .collect::>>(); + let pi_inner = pi_inner + .iter() + .map(|e| e.deref()) + .collect::>(); + let instances: &[&[&[Scheme::Scalar]]] = &[&pi_inner]; + trace!("instances {:?}", instances); + + let now = Instant::now(); + let mut transcript = Blake2bRead::<_, _, Challenge255<_>>::init(&proof.proof[..]); + + let result = + verify_proof::(¶ms, &vk, strategy, instances, &mut transcript) + .is_ok(); + info!("verify took {}", now.elapsed().as_secs()); + result +} + +pub fn load_vk<'params, Scheme: CommitmentScheme, F: FieldExt + TensorType>( + path: PathBuf, + params: &'params Scheme::ParamsVerifier, +) -> VerifyingKey +where + ModelCircuit: Circuit, +{ + info!("loading verification key from {:?}", path); + let f = match File::open(path) { + Ok(f) => f, + Err(e) => { + abort!("failed to load vk {}", e); + } + }; + let mut reader = BufReader::new(f); + VerifyingKey::::read::<_, ModelCircuit>(&mut reader, params).unwrap() +} + +pub fn save_proof( + vk_path: Option, + output: PathBuf, + pk: ProvingKey, + proof: Proof, +) { + if let Some(path) = &vk_path { + info!("saving verification key 💾"); + let f = File::create(path).unwrap(); + let mut writer = BufWriter::new(f); + pk.get_vk().write(&mut writer).unwrap(); + writer.flush().unwrap(); + } + + let serialized = match serde_json::to_string(&proof) { + Ok(s) => s, + Err(e) => { + abort!("failed to convert proof json to string {:?}", e); + } + }; + + let mut file = std::fs::File::create(output).expect("create failed"); + file.write_all(serialized.as_bytes()).expect("write failed"); +} diff --git a/tests/integration_tests.rs b/tests/integration_tests.rs index c0e63726a..50b4bfd11 100644 --- a/tests/integration_tests.rs +++ b/tests/integration_tests.rs @@ -69,7 +69,7 @@ macro_rules! test_func { } #(#[test_case(TESTS[N])])* - #[ignore] + // #[ignore] fn kzg_prove_and_verify_(test: &str) { kzg_prove_and_verify(test.to_string()); } @@ -177,9 +177,9 @@ fn ipa_prove_and_verify(example_name: String) { "-M", format!("./examples/onnx/examples/{}/network.onnx", example_name).as_str(), "-O", - format!("pav_{}.pf", example_name).as_str(), + format!("ipa_{}.pf", example_name).as_str(), "--vk-path", - format!("pav_{}.vk", example_name).as_str(), + format!("ipa_{}.vk", example_name).as_str(), ]) .status() .expect("failed to execute process"); @@ -192,9 +192,9 @@ fn ipa_prove_and_verify(example_name: String) { "-M", format!("./examples/onnx/examples/{}/network.onnx", example_name).as_str(), "-P", - format!("pav_{}.pf", example_name).as_str(), + format!("ipa_{}.pf", example_name).as_str(), "--vk-path", - format!("pav_{}.vk", example_name).as_str(), + format!("ipa_{}.vk", example_name).as_str(), ]) .status() .expect("failed to execute process"); @@ -214,9 +214,9 @@ fn kzg_prove_and_verify(example_name: String) { "-M", format!("./examples/onnx/examples/{}/network.onnx", example_name).as_str(), "-O", - format!("pav_{}.pf", example_name).as_str(), + format!("kzg_{}.pf", example_name).as_str(), "--vk-path", - format!("pav_{}.vk", example_name).as_str(), + format!("kzg_{}.vk", example_name).as_str(), ]) .status() .expect("failed to execute process"); @@ -230,9 +230,9 @@ fn kzg_prove_and_verify(example_name: String) { "-M", format!("./examples/onnx/examples/{}/network.onnx", example_name).as_str(), "-P", - format!("pav_{}.pf", example_name).as_str(), + format!("kzg_{}.pf", example_name).as_str(), "--vk-path", - format!("pav_{}.vk", example_name).as_str(), + format!("kzg_{}.vk", example_name).as_str(), ]) .status() .expect("failed to execute process"); From 0dc42ed0a553e2236e240d9a146ca7ec4b1a67fd Mon Sep 17 00:00:00 2001 From: Alexander Camuto Date: Thu, 15 Dec 2022 18:01:32 +0000 Subject: [PATCH 08/20] hard types --- src/bin/ezkl.rs | 8 ++++---- src/pfsys/mod.rs | 5 ++--- 2 files changed, 6 insertions(+), 7 deletions(-) diff --git a/src/bin/ezkl.rs b/src/bin/ezkl.rs index 9f13aa361..d68ae2e72 100644 --- a/src/bin/ezkl.rs +++ b/src/bin/ezkl.rs @@ -195,7 +195,7 @@ pub fn main() { ¶ms, ); - save_proof::<_, Fp>(vk_path, output, pk, proof); + save_proof::, Fp>(vk_path, output, pk, proof); } ProofSystem::KZG => { info!("proof with {}", pfsys); @@ -204,13 +204,13 @@ pub fn main() { trace!("params computed"); let (pk, proof, _input_dims) = - create_proof_model::, Fr, ProverGWC<_>>( + create_proof_model::, Fr, ProverGWC<'_, Bn256>>( circuit.clone(), public_inputs.clone(), ¶ms, ); - save_proof::<_, Fr>(vk_path, output, pk, proof); + save_proof::, Fr>(vk_path, output, pk, proof); } }; } @@ -246,7 +246,7 @@ pub fn main() { ProofSystem::KZG => { let params: ParamsKZG = ParamsKZG::new(args.logrows); let strategy = KZGSingleStrategy::new(¶ms); - let vk = load_vk::, Fr>(vk_path, ¶ms); + let vk = load_vk::, Fr>(vk_path, ¶ms); let result = verify_proof_model::<_, VerifierGWC<'_, Bn256>, _, _>( proof, ¶ms, &vk, strategy, ); diff --git a/src/pfsys/mod.rs b/src/pfsys/mod.rs index 497082a4b..0749852cf 100644 --- a/src/pfsys/mod.rs +++ b/src/pfsys/mod.rs @@ -17,7 +17,6 @@ use halo2_proofs::transcript::{ Blake2bRead, Blake2bWrite, Challenge255, TranscriptReadBuffer, TranscriptWriterBuffer, }; use halo2_proofs::{arithmetic::FieldExt, dev::VerifyFailure}; -use halo2curves::CurveAffine; use log::{error, info, trace}; use rand::rngs::OsRng; use serde::{Deserialize, Serialize}; @@ -308,10 +307,10 @@ where VerifyingKey::::read::<_, ModelCircuit>(&mut reader, params).unwrap() } -pub fn save_proof( +pub fn save_proof( vk_path: Option, output: PathBuf, - pk: ProvingKey, + pk: ProvingKey, proof: Proof, ) { if let Some(path) = &vk_path { From 9bd4788cc50fd6a76452a4eaa40a0682ae6e12ad Mon Sep 17 00:00:00 2001 From: Alexander Camuto Date: Thu, 15 Dec 2022 18:47:25 +0000 Subject: [PATCH 09/20] params serialization for kzg prove and verify --- .gitignore | 1 + src/bin/ezkl.rs | 28 +++++++++++++++++++++----- src/commands.rs | 8 +++++++- src/pfsys/mod.rs | 40 ++++++++++++++++++++++++++++---------- tests/integration_tests.rs | 8 ++++++++ 5 files changed, 69 insertions(+), 16 deletions(-) diff --git a/.gitignore b/.gitignore index da6ab73f7..3e58434eb 100644 --- a/.gitignore +++ b/.gitignore @@ -3,5 +3,6 @@ Cargo.lock data *.pf *.vk +*.params *~ \#*\# diff --git a/src/bin/ezkl.rs b/src/bin/ezkl.rs index d68ae2e72..6370a5fad 100644 --- a/src/bin/ezkl.rs +++ b/src/bin/ezkl.rs @@ -13,7 +13,7 @@ use ezkl::pfsys::{ create_proof_model, parse_prover_errors, prepare_circuit_and_public_input, prepare_data, save_proof, verify_proof_model, }; -use ezkl::pfsys::{load_vk, Proof}; +use ezkl::pfsys::{load_params, load_vk, Proof}; #[cfg(feature = "evm")] use halo2_proofs::poly::commitment::Params; use halo2_proofs::poly::ipa::commitment::IPACommitmentScheme; @@ -176,6 +176,7 @@ pub fn main() { model: _, output, vk_path, + params_path, pfsys, } => { let args = Cli::parse(); @@ -195,7 +196,14 @@ pub fn main() { ¶ms, ); - save_proof::, Fp>(vk_path, output, pk, proof); + save_proof::, Fp>( + vk_path, + params_path, + output, + pk, + proof, + ¶ms, + ); } ProofSystem::KZG => { info!("proof with {}", pfsys); @@ -210,7 +218,14 @@ pub fn main() { ¶ms, ); - save_proof::, Fr>(vk_path, output, pk, proof); + save_proof::, Fr>( + vk_path, + params_path, + output, + pk, + proof, + ¶ms, + ); } }; } @@ -218,6 +233,7 @@ pub fn main() { model: _, proof, vk_path, + params_path, pfsys, } => { let mut file = match File::open(proof) { @@ -236,7 +252,8 @@ pub fn main() { let proof: Proof = serde_json::from_str(&data).expect("JSON was not well-formatted"); match pfsys { ProofSystem::IPA => { - let params: ParamsIPA = ParamsIPA::new(args.logrows); + let params: ParamsIPA = + load_params::, Fp>(params_path); let strategy = IPASingleStrategy::new(¶ms); let vk = load_vk::, Fp>(vk_path, ¶ms); let result = verify_proof_model(proof, ¶ms, &vk, strategy); @@ -244,7 +261,8 @@ pub fn main() { assert!(result); } ProofSystem::KZG => { - let params: ParamsKZG = ParamsKZG::new(args.logrows); + let params: ParamsKZG = + load_params::, Fr>(params_path); let strategy = KZGSingleStrategy::new(¶ms); let vk = load_vk::, Fr>(vk_path, ¶ms); let result = verify_proof_model::<_, VerifierGWC<'_, Bn256>, _, _>( diff --git a/src/commands.rs b/src/commands.rs index 9a91fa123..b5efe6d86 100644 --- a/src/commands.rs +++ b/src/commands.rs @@ -101,7 +101,10 @@ pub enum Commands { output: PathBuf, /// The path to output to the desired verfication key file (optional) #[arg(long, default_value = "")] - vk_path: Option, + vk_path: PathBuf, + /// The path to output to the desired verfication key file (optional) + #[arg(long, default_value = "")] + params_path: PathBuf, // /// The path to the Params for the proof system // #[arg(short = 'P', long, default_value = "")] @@ -130,6 +133,9 @@ pub enum Commands { /// The path to output to the desired verfication key file (optional) #[arg(long, default_value = "")] vk_path: PathBuf, + /// The path to output to the desired verfication key file (optional) + #[arg(long, default_value = "")] + params_path: PathBuf, // /// The path to the Params for the proof system // #[arg(short = 'P', long, default_value = "")] diff --git a/src/pfsys/mod.rs b/src/pfsys/mod.rs index 0749852cf..39b586e31 100644 --- a/src/pfsys/mod.rs +++ b/src/pfsys/mod.rs @@ -11,7 +11,7 @@ use clap::Parser; use halo2_proofs::plonk::{ create_proof, keygen_pk, keygen_vk, verify_proof, Circuit, ProvingKey, VerifyingKey, }; -use halo2_proofs::poly::commitment::{CommitmentScheme, Prover, Verifier}; +use halo2_proofs::poly::commitment::{CommitmentScheme, Params, Prover, Verifier}; use halo2_proofs::poly::VerificationStrategy; use halo2_proofs::transcript::{ Blake2bRead, Blake2bWrite, Challenge255, TranscriptReadBuffer, TranscriptWriterBuffer, @@ -307,19 +307,39 @@ where VerifyingKey::::read::<_, ModelCircuit>(&mut reader, params).unwrap() } -pub fn save_proof( - vk_path: Option, +pub fn load_params<'params, Scheme: CommitmentScheme, F: FieldExt + TensorType>( + path: PathBuf, +) -> Scheme::ParamsVerifier { + info!("loading params from {:?}", path); + let f = match File::open(path) { + Ok(f) => f, + Err(e) => { + abort!("failed to load params {}", e); + } + }; + let mut reader = BufReader::new(f); + Params::<'_, Scheme::Curve>::read(&mut reader).unwrap() +} + +pub fn save_proof<'params, Scheme: CommitmentScheme, F: FieldExt>( + vk_path: PathBuf, + params_path: PathBuf, output: PathBuf, pk: ProvingKey, proof: Proof, + params: &'params Scheme::ParamsVerifier, ) { - if let Some(path) = &vk_path { - info!("saving verification key 💾"); - let f = File::create(path).unwrap(); - let mut writer = BufWriter::new(f); - pk.get_vk().write(&mut writer).unwrap(); - writer.flush().unwrap(); - } + info!("saving verification key 💾"); + let f = File::create(vk_path).unwrap(); + let mut writer = BufWriter::new(f); + pk.get_vk().write(&mut writer).unwrap(); + writer.flush().unwrap(); + + info!("saving parameters 💾"); + let f = File::create(params_path).unwrap(); + let mut writer = BufWriter::new(f); + params.write(&mut writer).unwrap(); + writer.flush().unwrap(); let serialized = match serde_json::to_string(&proof) { Ok(s) => s, diff --git a/tests/integration_tests.rs b/tests/integration_tests.rs index 50b4bfd11..321037a48 100644 --- a/tests/integration_tests.rs +++ b/tests/integration_tests.rs @@ -180,6 +180,8 @@ fn ipa_prove_and_verify(example_name: String) { format!("ipa_{}.pf", example_name).as_str(), "--vk-path", format!("ipa_{}.vk", example_name).as_str(), + "--params-path", + format!("ipa_{}.params", example_name).as_str(), ]) .status() .expect("failed to execute process"); @@ -195,6 +197,8 @@ fn ipa_prove_and_verify(example_name: String) { format!("ipa_{}.pf", example_name).as_str(), "--vk-path", format!("ipa_{}.vk", example_name).as_str(), + "--params-path", + format!("ipa_{}.params", example_name).as_str(), ]) .status() .expect("failed to execute process"); @@ -217,6 +221,8 @@ fn kzg_prove_and_verify(example_name: String) { format!("kzg_{}.pf", example_name).as_str(), "--vk-path", format!("kzg_{}.vk", example_name).as_str(), + "--params-path", + format!("kzg_{}.params", example_name).as_str(), ]) .status() .expect("failed to execute process"); @@ -233,6 +239,8 @@ fn kzg_prove_and_verify(example_name: String) { format!("kzg_{}.pf", example_name).as_str(), "--vk-path", format!("kzg_{}.vk", example_name).as_str(), + "--params-path", + format!("kzg_{}.params", example_name).as_str(), ]) .status() .expect("failed to execute process"); From 7b9db8c0a362a47309656414f621f69058808c2d Mon Sep 17 00:00:00 2001 From: Alexander Camuto Date: Thu, 15 Dec 2022 18:53:43 +0000 Subject: [PATCH 10/20] docs --- src/pfsys/mod.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/pfsys/mod.rs b/src/pfsys/mod.rs index 39b586e31..c76970410 100644 --- a/src/pfsys/mod.rs +++ b/src/pfsys/mod.rs @@ -178,7 +178,7 @@ pub fn prepare_data(datapath: String) -> ModelInput { data } -// a wrapper around halo2's create proof +/// a wrapper around halo2's create_proof pub fn create_proof_model< 'params, Scheme: CommitmentScheme, @@ -248,6 +248,7 @@ where (pk, checkable_pf, dims) } +/// a wrapper around halo2's verify_proof pub fn verify_proof_model< 'params, F: FieldExt, From 32b1a18b46a96b017e05b2a4d588feeecbfb189e Mon Sep 17 00:00:00 2001 From: Alexander Camuto Date: Thu, 15 Dec 2022 20:09:38 +0000 Subject: [PATCH 11/20] divide functions more clearly --- src/bin/ezkl.rs | 100 +++++++++++++++++++---------------------------- src/commands.rs | 4 +- src/pfsys/mod.rs | 94 +++++++++++++++++++++++++++++--------------- 3 files changed, 106 insertions(+), 92 deletions(-) diff --git a/src/bin/ezkl.rs b/src/bin/ezkl.rs index 6370a5fad..e03581d23 100644 --- a/src/bin/ezkl.rs +++ b/src/bin/ezkl.rs @@ -8,12 +8,12 @@ use ezkl::pfsys::kzg::aggregation::{ aggregation::AggregationCircuit, evm_verify, gen_aggregation_evm_verifier, gen_application_snark, gen_kzg_proof, gen_pk, gen_srs, }; +use ezkl::pfsys::{create_keys, load_params, load_vk, Proof}; #[cfg(not(feature = "evm"))] use ezkl::pfsys::{ create_proof_model, parse_prover_errors, prepare_circuit_and_public_input, prepare_data, - save_proof, verify_proof_model, + save_params, save_vk, verify_proof_model, }; -use ezkl::pfsys::{load_params, load_vk, Proof}; #[cfg(feature = "evm")] use halo2_proofs::poly::commitment::Params; use halo2_proofs::poly::ipa::commitment::IPACommitmentScheme; @@ -39,8 +39,6 @@ use log::{error, info, trace}; #[cfg(feature = "evm")] use plonk_verifier::system::halo2::transcript::evm::EvmTranscript; use rand::seq::SliceRandom; -use std::fs::File; -use std::io::Read; use tabled::Table; pub fn main() { @@ -97,15 +95,17 @@ pub fn main() { info!("full proof with {}", pfsys); let params: ParamsIPA = ParamsIPA::new(args.logrows); + let pk = create_keys::, Fp>(&circuit, ¶ms); let strategy = IPASingleStrategy::new(¶ms); trace!("params computed"); - let (pk, proof, _dims) = - create_proof_model::, Fp, ProverIPA<_>>( - circuit, - public_inputs.clone(), - ¶ms, - ); + let (proof, _dims) = create_proof_model::< + IPACommitmentScheme<_>, + Fp, + ProverIPA<_>, + >( + &circuit, &public_inputs, ¶ms, &pk + ); assert!(verify_proof_model(proof, ¶ms, pk.get_vk(), strategy)); } @@ -114,15 +114,17 @@ pub fn main() { // A direct proof let (circuit, public_inputs) = prepare_circuit_and_public_input::(&data); let params: ParamsKZG = ParamsKZG::new(args.logrows); + let pk = create_keys::, Fr>(&circuit, ¶ms); let strategy = KZGSingleStrategy::new(¶ms); trace!("params computed"); - let (pk, proof, _dims) = - create_proof_model::, Fr, ProverGWC<_>>( - circuit, - public_inputs.clone(), - ¶ms, - ); + let (proof, _dims) = create_proof_model::< + KZGCommitmentScheme<_>, + Fr, + ProverGWC<_>, + >( + &circuit, &public_inputs, ¶ms, &pk + ); assert!(verify_proof_model::<_, VerifierGWC<'_, Bn256>, _, _>( proof, @@ -174,7 +176,7 @@ pub fn main() { Commands::Prove { data, model: _, - output, + proof_path, vk_path, params_path, pfsys, @@ -187,69 +189,49 @@ pub fn main() { info!("proof with {}", pfsys); let (circuit, public_inputs) = prepare_circuit_and_public_input::(&data); let params: ParamsIPA = ParamsIPA::new(args.logrows); + let pk = create_keys::, Fp>(&circuit, ¶ms); trace!("params computed"); - let (pk, proof, _) = - create_proof_model::, Fp, ProverIPA<_>>( - circuit.clone(), - public_inputs.clone(), - ¶ms, - ); - - save_proof::, Fp>( - vk_path, - params_path, - output, - pk, - proof, + let (proof, _) = create_proof_model::, Fp, ProverIPA<_>>( + &circuit, + &public_inputs, ¶ms, + &pk, ); + + proof.save(&proof_path); + save_params::, Fp>(¶ms_path, ¶ms); + save_vk::, Fp>(&vk_path, &pk.get_vk()); } ProofSystem::KZG => { info!("proof with {}", pfsys); let (circuit, public_inputs) = prepare_circuit_and_public_input(&data); let params: ParamsKZG = ParamsKZG::new(args.logrows); + let pk = create_keys::, Fr>(&circuit, ¶ms); trace!("params computed"); - let (pk, proof, _input_dims) = - create_proof_model::, Fr, ProverGWC<'_, Bn256>>( - circuit.clone(), - public_inputs.clone(), - ¶ms, - ); - - save_proof::, Fr>( - vk_path, - params_path, - output, - pk, - proof, - ¶ms, + let (proof, _input_dims) = create_proof_model::< + KZGCommitmentScheme, + Fr, + ProverGWC<'_, Bn256>, + >( + &circuit, &public_inputs, ¶ms, &pk ); + + proof.save(&proof_path); + save_params::, Fr>(¶ms_path, ¶ms); + save_vk::, Fr>(&vk_path, &pk.get_vk()); } }; } Commands::Verify { model: _, - proof, + proof_path, vk_path, params_path, pfsys, } => { - let mut file = match File::open(proof) { - Ok(f) => f, - Err(e) => { - abort!("failed to open proof file {:?}", e); - } - }; - let mut data = String::new(); - match file.read_to_string(&mut data) { - Ok(_) => {} - Err(e) => { - abort!("failed to read file {:?}", e); - } - }; - let proof: Proof = serde_json::from_str(&data).expect("JSON was not well-formatted"); + let proof = Proof::load(&proof_path); match pfsys { ProofSystem::IPA => { let params: ParamsIPA = diff --git a/src/commands.rs b/src/commands.rs index b5efe6d86..c221f5e7d 100644 --- a/src/commands.rs +++ b/src/commands.rs @@ -98,7 +98,7 @@ pub enum Commands { model: PathBuf, /// The path to the desired output file #[arg(short = 'O', long, default_value = "")] - output: PathBuf, + proof_path: PathBuf, /// The path to output to the desired verfication key file (optional) #[arg(long, default_value = "")] vk_path: PathBuf, @@ -129,7 +129,7 @@ pub enum Commands { /// The path to the proof file #[arg(short = 'P', long, default_value = "")] - proof: PathBuf, + proof_path: PathBuf, /// The path to output to the desired verfication key file (optional) #[arg(long, default_value = "")] vk_path: PathBuf, diff --git a/src/pfsys/mod.rs b/src/pfsys/mod.rs index c76970410..9fb6892b7 100644 --- a/src/pfsys/mod.rs +++ b/src/pfsys/mod.rs @@ -41,6 +41,37 @@ pub struct Proof { pub proof: Vec, } +impl Proof { + pub fn save(&self, proof_path: &PathBuf) { + let serialized = match serde_json::to_string(&self) { + Ok(s) => s, + Err(e) => { + abort!("failed to convert proof json to string {:?}", e); + } + }; + + let mut file = std::fs::File::create(proof_path).expect("create failed"); + file.write_all(serialized.as_bytes()).expect("write failed"); + } + + pub fn load(proof_path: &PathBuf) -> Self { + let mut file = match File::open(proof_path) { + Ok(f) => f, + Err(e) => { + abort!("failed to open proof file {:?}", e); + } + }; + let mut data = String::new(); + match file.read_to_string(&mut data) { + Ok(_) => {} + Err(e) => { + abort!("failed to read file {:?}", e); + } + }; + serde_json::from_str(&data).expect("JSON was not well-formatted") + } +} + /// Helper function to print helpful error messages after verification has failed. pub fn parse_prover_errors(f: &VerifyFailure) { match f { @@ -178,17 +209,10 @@ pub fn prepare_data(datapath: String) -> ModelInput { data } -/// a wrapper around halo2's create_proof -pub fn create_proof_model< - 'params, - Scheme: CommitmentScheme, - F: FieldExt + TensorType, - P: Prover<'params, Scheme>, ->( - circuit: ModelCircuit, - public_inputs: Vec>, +pub fn create_keys<'params, Scheme: CommitmentScheme, F: FieldExt + TensorType>( + circuit: &ModelCircuit, params: &'params Scheme::ParamsProver, -) -> (ProvingKey, Proof, Vec>) +) -> ProvingKey where ModelCircuit: Circuit, { @@ -203,10 +227,27 @@ where let now = Instant::now(); let pk = keygen_pk(params, vk, &empty_circuit).expect("keygen_pk should not fail"); info!("PK took {}", now.elapsed().as_secs()); + pk +} + +/// a wrapper around halo2's create_proof +pub fn create_proof_model< + 'params, + Scheme: CommitmentScheme, + F: FieldExt + TensorType, + P: Prover<'params, Scheme>, +>( + circuit: &ModelCircuit, + public_inputs: &Vec>, + params: &'params Scheme::ParamsProver, + pk: &ProvingKey, +) -> (Proof, Vec>) +where + ModelCircuit: Circuit, +{ let now = Instant::now(); let mut transcript = Blake2bWrite::<_, Scheme::Curve, Challenge255<_>>::init(vec![]); let mut rng = OsRng; - let pi_inner: Vec> = public_inputs .iter() .map(|i| { @@ -240,12 +281,12 @@ where input_shapes: circuit.inputs.iter().map(|i| i.dims().to_vec()).collect(), public_inputs: public_inputs .into_iter() - .map(|i| i.into_iter().collect()) + .map(|i| i.clone().into_iter().collect()) .collect(), proof, }; - (pk, checkable_pf, dims) + (checkable_pf, dims) } /// a wrapper around halo2's verify_proof @@ -322,33 +363,24 @@ pub fn load_params<'params, Scheme: CommitmentScheme, F: FieldExt + TensorType>( Params::<'_, Scheme::Curve>::read(&mut reader).unwrap() } -pub fn save_proof<'params, Scheme: CommitmentScheme, F: FieldExt>( - vk_path: PathBuf, - params_path: PathBuf, - output: PathBuf, - pk: ProvingKey, - proof: Proof, - params: &'params Scheme::ParamsVerifier, +pub fn save_vk<'params, Scheme: CommitmentScheme, F: FieldExt>( + vk_path: &PathBuf, + vk: &VerifyingKey, ) { info!("saving verification key 💾"); let f = File::create(vk_path).unwrap(); let mut writer = BufWriter::new(f); - pk.get_vk().write(&mut writer).unwrap(); + vk.write(&mut writer).unwrap(); writer.flush().unwrap(); +} +pub fn save_params<'params, Scheme: CommitmentScheme, F: FieldExt>( + params_path: &PathBuf, + params: &'params Scheme::ParamsVerifier, +) { info!("saving parameters 💾"); let f = File::create(params_path).unwrap(); let mut writer = BufWriter::new(f); params.write(&mut writer).unwrap(); writer.flush().unwrap(); - - let serialized = match serde_json::to_string(&proof) { - Ok(s) => s, - Err(e) => { - abort!("failed to convert proof json to string {:?}", e); - } - }; - - let mut file = std::fs::File::create(output).expect("create failed"); - file.write_all(serialized.as_bytes()).expect("write failed"); } From 1c74a9e6f4bb9a4a94d766a4f5f134e30aa6cd02 Mon Sep 17 00:00:00 2001 From: Alexander Camuto Date: Thu, 15 Dec 2022 20:13:24 +0000 Subject: [PATCH 12/20] cleanup traits --- src/bin/ezkl.rs | 12 ++++++------ src/pfsys/mod.rs | 8 +++----- 2 files changed, 9 insertions(+), 11 deletions(-) diff --git a/src/bin/ezkl.rs b/src/bin/ezkl.rs index e03581d23..c39be4126 100644 --- a/src/bin/ezkl.rs +++ b/src/bin/ezkl.rs @@ -200,8 +200,8 @@ pub fn main() { ); proof.save(&proof_path); - save_params::, Fp>(¶ms_path, ¶ms); - save_vk::, Fp>(&vk_path, &pk.get_vk()); + save_params::>(¶ms_path, ¶ms); + save_vk::>(&vk_path, &pk.get_vk()); } ProofSystem::KZG => { info!("proof with {}", pfsys); @@ -219,8 +219,8 @@ pub fn main() { ); proof.save(&proof_path); - save_params::, Fr>(¶ms_path, ¶ms); - save_vk::, Fr>(&vk_path, &pk.get_vk()); + save_params::>(¶ms_path, ¶ms); + save_vk::>(&vk_path, &pk.get_vk()); } }; } @@ -235,7 +235,7 @@ pub fn main() { match pfsys { ProofSystem::IPA => { let params: ParamsIPA = - load_params::, Fp>(params_path); + load_params::>(params_path); let strategy = IPASingleStrategy::new(¶ms); let vk = load_vk::, Fp>(vk_path, ¶ms); let result = verify_proof_model(proof, ¶ms, &vk, strategy); @@ -244,7 +244,7 @@ pub fn main() { } ProofSystem::KZG => { let params: ParamsKZG = - load_params::, Fr>(params_path); + load_params::>(params_path); let strategy = KZGSingleStrategy::new(¶ms); let vk = load_vk::, Fr>(vk_path, ¶ms); let result = verify_proof_model::<_, VerifierGWC<'_, Bn256>, _, _>( diff --git a/src/pfsys/mod.rs b/src/pfsys/mod.rs index 9fb6892b7..327c67262 100644 --- a/src/pfsys/mod.rs +++ b/src/pfsys/mod.rs @@ -349,9 +349,7 @@ where VerifyingKey::::read::<_, ModelCircuit>(&mut reader, params).unwrap() } -pub fn load_params<'params, Scheme: CommitmentScheme, F: FieldExt + TensorType>( - path: PathBuf, -) -> Scheme::ParamsVerifier { +pub fn load_params<'params, Scheme: CommitmentScheme>(path: PathBuf) -> Scheme::ParamsVerifier { info!("loading params from {:?}", path); let f = match File::open(path) { Ok(f) => f, @@ -363,7 +361,7 @@ pub fn load_params<'params, Scheme: CommitmentScheme, F: FieldExt + TensorType>( Params::<'_, Scheme::Curve>::read(&mut reader).unwrap() } -pub fn save_vk<'params, Scheme: CommitmentScheme, F: FieldExt>( +pub fn save_vk<'params, Scheme: CommitmentScheme>( vk_path: &PathBuf, vk: &VerifyingKey, ) { @@ -374,7 +372,7 @@ pub fn save_vk<'params, Scheme: CommitmentScheme, F: FieldExt>( writer.flush().unwrap(); } -pub fn save_params<'params, Scheme: CommitmentScheme, F: FieldExt>( +pub fn save_params<'params, Scheme: CommitmentScheme>( params_path: &PathBuf, params: &'params Scheme::ParamsVerifier, ) { From 33dd1ceeb84b14bf156d7385a0dd50ec7fd0eb84 Mon Sep 17 00:00:00 2001 From: Alexander Camuto Date: Fri, 16 Dec 2022 10:52:12 +0000 Subject: [PATCH 13/20] split workflow into separate files --- .github/workflows/rust.yml | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-) diff --git a/.github/workflows/rust.yml b/.github/workflows/rust.yml index 9746b93b3..601144061 100644 --- a/.github/workflows/rust.yml +++ b/.github/workflows/rust.yml @@ -25,5 +25,19 @@ jobs: components: rustfmt, clippy - name: Build run: cargo build --verbose - - name: Run tests - run: cargo test --verbose + - name: Doc tests + run: cargo test --doc --verbose + - name: Doc tests + run: cargo test --doc --verbose + - name: Library tests + run: cargo test --lib --verbose + - name: Mock proving tests + run: cargo test tests::mock_ --verbose + - name: IPA full-prove tests + run: cargo test tests::ipa_fullprove_ --verbose + - name: KZG full-prove tests + run: cargo test tests::kzg_fullprove_ --verbose + - name: IPA prove and verify tests + run: cargo test tests::ipa_prove_and_verify_ --verbose + - name: KZG prove and verify tests + run: cargo test tests::kzg_prove_and_verify_ --verbose From 2d012dab3b228d1b8b17595103c7453e80f51426 Mon Sep 17 00:00:00 2001 From: Alexander Camuto Date: Fri, 16 Dec 2022 10:56:30 +0000 Subject: [PATCH 14/20] increase timeout time --- .github/workflows/rust.yml | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/.github/workflows/rust.yml b/.github/workflows/rust.yml index 601144061..bd258d69e 100644 --- a/.github/workflows/rust.yml +++ b/.github/workflows/rust.yml @@ -13,6 +13,7 @@ jobs: build: runs-on: self-hosted + timeout-minutes: 720 steps: - uses: actions/checkout@v3 @@ -27,12 +28,14 @@ jobs: run: cargo build --verbose - name: Doc tests run: cargo test --doc --verbose - - name: Doc tests - run: cargo test --doc --verbose - name: Library tests run: cargo test --lib --verbose - name: Mock proving tests - run: cargo test tests::mock_ --verbose + run: cargo test tests::mock_:: --verbose + - name: Mock proving tests (public inputs) + run: cargo test tests::mock_public_inputs_ --verbose + - name: Mock proving tests (public params) + run: cargo test tests::mock_public_params_ --verbose - name: IPA full-prove tests run: cargo test tests::ipa_fullprove_ --verbose - name: KZG full-prove tests From 31ef234a542ca3036bc213ba778ad8aa5b1f26f7 Mon Sep 17 00:00:00 2001 From: Alexander Camuto Date: Fri, 16 Dec 2022 10:58:53 +0000 Subject: [PATCH 15/20] more descriptive naming --- .github/workflows/rust.yml | 2 +- tests/integration_tests.rs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/rust.yml b/.github/workflows/rust.yml index bd258d69e..e93b901d2 100644 --- a/.github/workflows/rust.yml +++ b/.github/workflows/rust.yml @@ -31,7 +31,7 @@ jobs: - name: Library tests run: cargo test --lib --verbose - name: Mock proving tests - run: cargo test tests::mock_:: --verbose + run: cargo test tests::mock_public_outputs_ --verbose - name: Mock proving tests (public inputs) run: cargo test tests::mock_public_inputs_ --verbose - name: Mock proving tests (public params) diff --git a/tests/integration_tests.rs b/tests/integration_tests.rs index 321037a48..cfde190f9 100644 --- a/tests/integration_tests.rs +++ b/tests/integration_tests.rs @@ -39,7 +39,7 @@ macro_rules! test_func { seq!(N in 0..=11 { #(#[test_case(TESTS[N])])* - fn mock_(test: &str) { + fn mock_public_outputs_(test: &str) { mock(test.to_string()); } From 80ae33ffbb950a9a700864db46b8a27f8600522a Mon Sep 17 00:00:00 2001 From: Alexander Camuto Date: Fri, 16 Dec 2022 11:07:06 +0000 Subject: [PATCH 16/20] split up yaml further --- .github/workflows/rust.yml | 71 ++++++++++++++++++++++++++++++++------ 1 file changed, 61 insertions(+), 10 deletions(-) diff --git a/.github/workflows/rust.yml b/.github/workflows/rust.yml index e93b901d2..213fbc79f 100644 --- a/.github/workflows/rust.yml +++ b/.github/workflows/rust.yml @@ -13,12 +13,9 @@ jobs: build: runs-on: self-hosted - timeout-minutes: 720 steps: - uses: actions/checkout@v3 - with: - submodules: recursive - uses: actions-rs/toolchain@v1 with: toolchain: nightly @@ -26,21 +23,75 @@ jobs: components: rustfmt, clippy - name: Build run: cargo build --verbose + + library_tests: + + runs-on: self-hosted + + steps: + - uses: actions/checkout@v3 + - uses: actions-rs/toolchain@v1 + with: + toolchain: nightly + override: true + components: rustfmt, clippy - name: Doc tests run: cargo test --doc --verbose - name: Library tests run: cargo test --lib --verbose + + mock_proving_tests: + + runs-on: self-hosted + steps: + - uses: actions/checkout@v3 + with: + submodules: recursive + - uses: actions-rs/toolchain@v1 + with: + toolchain: nightly + override: true + components: rustfmt, clippy + - name: Mock proving tests - run: cargo test tests::mock_public_outputs_ --verbose + run: cargo test --release --verbose tests::mock_public_outputs_ - name: Mock proving tests (public inputs) - run: cargo test tests::mock_public_inputs_ --verbose + run: cargo test --release --verbose tests::mock_public_inputs_ - name: Mock proving tests (public params) - run: cargo test tests::mock_public_params_ --verbose + run: cargo test --release --verbose tests::mock_public_params_ + + full_proving_tests: + + runs-on: self-hosted + steps: + - uses: actions/checkout@v3 + with: + submodules: recursive + - uses: actions-rs/toolchain@v1 + with: + toolchain: nightly + override: true + components: rustfmt, clippy + - name: IPA full-prove tests - run: cargo test tests::ipa_fullprove_ --verbose + run: cargo test --release --verbose tests::ipa_fullprove_ - name: KZG full-prove tests - run: cargo test tests::kzg_fullprove_ --verbose + run: cargo test --release --verbose tests::kzg_fullprove_ + + prove_and_verify_tests: + + runs-on: self-hosted + steps: + - uses: actions/checkout@v3 + with: + submodules: recursive + - uses: actions-rs/toolchain@v1 + with: + toolchain: nightly + override: true + components: rustfmt, clippy + - name: IPA prove and verify tests - run: cargo test tests::ipa_prove_and_verify_ --verbose + run: cargo test --release --verbose tests::ipa_prove_and_verify_ - name: KZG prove and verify tests - run: cargo test tests::kzg_prove_and_verify_ --verbose + run: cargo test --release --verbose tests::kzg_prove_and_verify_ From f722eab858534bc6c97f55a627e1beacc3b04f3a Mon Sep 17 00:00:00 2001 From: Alexander Camuto Date: Fri, 16 Dec 2022 11:14:37 +0000 Subject: [PATCH 17/20] clippy errors --- .github/workflows/rust.yml | 8 ++++---- src/bin/ezkl.rs | 4 ++-- src/circuit/eltwise.rs | 6 +++--- src/pfsys/mod.rs | 29 +++++++++++++---------------- 4 files changed, 22 insertions(+), 25 deletions(-) diff --git a/.github/workflows/rust.yml b/.github/workflows/rust.yml index 213fbc79f..329b3f4eb 100644 --- a/.github/workflows/rust.yml +++ b/.github/workflows/rust.yml @@ -24,7 +24,7 @@ jobs: - name: Build run: cargo build --verbose - library_tests: + library tests: runs-on: self-hosted @@ -40,7 +40,7 @@ jobs: - name: Library tests run: cargo test --lib --verbose - mock_proving_tests: + mock proving tests: runs-on: self-hosted steps: @@ -60,7 +60,7 @@ jobs: - name: Mock proving tests (public params) run: cargo test --release --verbose tests::mock_public_params_ - full_proving_tests: + full proving tests: runs-on: self-hosted steps: @@ -78,7 +78,7 @@ jobs: - name: KZG full-prove tests run: cargo test --release --verbose tests::kzg_fullprove_ - prove_and_verify_tests: + prove and verify tests: runs-on: self-hosted steps: diff --git a/src/bin/ezkl.rs b/src/bin/ezkl.rs index c39be4126..074c7bc1a 100644 --- a/src/bin/ezkl.rs +++ b/src/bin/ezkl.rs @@ -201,7 +201,7 @@ pub fn main() { proof.save(&proof_path); save_params::>(¶ms_path, ¶ms); - save_vk::>(&vk_path, &pk.get_vk()); + save_vk::>(&vk_path, pk.get_vk()); } ProofSystem::KZG => { info!("proof with {}", pfsys); @@ -220,7 +220,7 @@ pub fn main() { proof.save(&proof_path); save_params::>(¶ms_path, ¶ms); - save_vk::>(&vk_path, &pk.get_vk()); + save_vk::>(&vk_path, pk.get_vk()); } }; } diff --git a/src/circuit/eltwise.rs b/src/circuit/eltwise.rs index b85c28bd5..5f566c7de 100644 --- a/src/circuit/eltwise.rs +++ b/src/circuit/eltwise.rs @@ -358,7 +358,7 @@ mod tests { for i in -127..127 { let r = as Nonlinearity>::nonlinearity(i, &[1]); if i <= 0 { - assert!(r == F::from(0 as u64)) + assert!(r == F::from(0_u64)) } else { assert!(r == F::from(i as u64)) } @@ -390,7 +390,7 @@ mod tests { #[test] fn relucircuit() { let input: Tensor> = - Tensor::new(Some(&[Value::::known(F::from(1 as u64))]), &[1]).unwrap(); + Tensor::new(Some(&[Value::::known(F::from(1_u64))]), &[1]).unwrap(); let assigned: Nonlin1d> = Nonlin1d { input: ValTensor::from(input.clone()), output: ValTensor::from(input), @@ -402,7 +402,7 @@ mod tests { _marker: PhantomData, }; - let prover = MockProver::run(4 as u32, &circuit, vec![]).unwrap(); + let prover = MockProver::run(4_u32, &circuit, vec![]).unwrap(); prover.assert_satisfied(); } } diff --git a/src/pfsys/mod.rs b/src/pfsys/mod.rs index 327c67262..1c55f5b1d 100644 --- a/src/pfsys/mod.rs +++ b/src/pfsys/mod.rs @@ -209,9 +209,9 @@ pub fn prepare_data(datapath: String) -> ModelInput { data } -pub fn create_keys<'params, Scheme: CommitmentScheme, F: FieldExt + TensorType>( +pub fn create_keys( circuit: &ModelCircuit, - params: &'params Scheme::ParamsProver, + params: &'_ Scheme::ParamsProver, ) -> ProvingKey where ModelCircuit: Circuit, @@ -238,7 +238,7 @@ pub fn create_proof_model< P: Prover<'params, Scheme>, >( circuit: &ModelCircuit, - public_inputs: &Vec>, + public_inputs: &[Tensor], params: &'params Scheme::ParamsProver, pk: &ProvingKey, ) -> (Proof, Vec>) @@ -266,8 +266,8 @@ where let dims = circuit.inputs.iter().map(|i| i.dims().to_vec()).collect(); create_proof::( - ¶ms, - &pk, + params, + pk, &[circuit.clone()], instances, &mut rng, @@ -280,7 +280,7 @@ where let checkable_pf = Proof { input_shapes: circuit.inputs.iter().map(|i| i.dims().to_vec()).collect(), public_inputs: public_inputs - .into_iter() + .iter() .map(|i| i.clone().into_iter().collect()) .collect(), proof, @@ -325,15 +325,15 @@ where let mut transcript = Blake2bRead::<_, _, Challenge255<_>>::init(&proof.proof[..]); let result = - verify_proof::(¶ms, &vk, strategy, instances, &mut transcript) + verify_proof::(params, vk, strategy, instances, &mut transcript) .is_ok(); info!("verify took {}", now.elapsed().as_secs()); result } -pub fn load_vk<'params, Scheme: CommitmentScheme, F: FieldExt + TensorType>( +pub fn load_vk( path: PathBuf, - params: &'params Scheme::ParamsVerifier, + params: &'_ Scheme::ParamsVerifier, ) -> VerifyingKey where ModelCircuit: Circuit, @@ -349,7 +349,7 @@ where VerifyingKey::::read::<_, ModelCircuit>(&mut reader, params).unwrap() } -pub fn load_params<'params, Scheme: CommitmentScheme>(path: PathBuf) -> Scheme::ParamsVerifier { +pub fn load_params(path: PathBuf) -> Scheme::ParamsVerifier { info!("loading params from {:?}", path); let f = match File::open(path) { Ok(f) => f, @@ -361,10 +361,7 @@ pub fn load_params<'params, Scheme: CommitmentScheme>(path: PathBuf) -> Scheme:: Params::<'_, Scheme::Curve>::read(&mut reader).unwrap() } -pub fn save_vk<'params, Scheme: CommitmentScheme>( - vk_path: &PathBuf, - vk: &VerifyingKey, -) { +pub fn save_vk(vk_path: &PathBuf, vk: &VerifyingKey) { info!("saving verification key 💾"); let f = File::create(vk_path).unwrap(); let mut writer = BufWriter::new(f); @@ -372,9 +369,9 @@ pub fn save_vk<'params, Scheme: CommitmentScheme>( writer.flush().unwrap(); } -pub fn save_params<'params, Scheme: CommitmentScheme>( +pub fn save_params( params_path: &PathBuf, - params: &'params Scheme::ParamsVerifier, + params: &'_ Scheme::ParamsVerifier, ) { info!("saving parameters 💾"); let f = File::create(params_path).unwrap(); From 52248d1ab6a06d76a824f7f02970149f1fa761b2 Mon Sep 17 00:00:00 2001 From: Alexander Camuto Date: Fri, 16 Dec 2022 11:15:42 +0000 Subject: [PATCH 18/20] Update rust.yml --- .github/workflows/rust.yml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/rust.yml b/.github/workflows/rust.yml index 329b3f4eb..83b10c79c 100644 --- a/.github/workflows/rust.yml +++ b/.github/workflows/rust.yml @@ -24,7 +24,7 @@ jobs: - name: Build run: cargo build --verbose - library tests: + library-tests: runs-on: self-hosted @@ -40,7 +40,7 @@ jobs: - name: Library tests run: cargo test --lib --verbose - mock proving tests: + mock-proving-tests: runs-on: self-hosted steps: @@ -60,7 +60,7 @@ jobs: - name: Mock proving tests (public params) run: cargo test --release --verbose tests::mock_public_params_ - full proving tests: + full-proving-tests: runs-on: self-hosted steps: @@ -78,7 +78,7 @@ jobs: - name: KZG full-prove tests run: cargo test --release --verbose tests::kzg_fullprove_ - prove and verify tests: + prove-and-verify-tests: runs-on: self-hosted steps: From e99678480e424517a8d5307e0abd136fe2b4eef3 Mon Sep 17 00:00:00 2001 From: Alexander Camuto Date: Fri, 16 Dec 2022 20:06:59 +0000 Subject: [PATCH 19/20] reduce test threads for KZG prove and verify --- .github/workflows/rust.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/rust.yml b/.github/workflows/rust.yml index 83b10c79c..0feae2064 100644 --- a/.github/workflows/rust.yml +++ b/.github/workflows/rust.yml @@ -94,4 +94,4 @@ jobs: - name: IPA prove and verify tests run: cargo test --release --verbose tests::ipa_prove_and_verify_ - name: KZG prove and verify tests - run: cargo test --release --verbose tests::kzg_prove_and_verify_ + run: cargo test --release --verbose tests::kzg_prove_and_verify_ -- --test-threads 1 From 4982ce166cbc71ad4084b8e4794e6eed2095fa32 Mon Sep 17 00:00:00 2001 From: Alexander Camuto Date: Sat, 17 Dec 2022 12:40:50 +0000 Subject: [PATCH 20/20] single thread tests --- .github/workflows/rust.yml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/rust.yml b/.github/workflows/rust.yml index 0feae2064..eea63e505 100644 --- a/.github/workflows/rust.yml +++ b/.github/workflows/rust.yml @@ -53,7 +53,7 @@ jobs: override: true components: rustfmt, clippy - - name: Mock proving tests + - name: Mock proving tests (public outputs) run: cargo test --release --verbose tests::mock_public_outputs_ - name: Mock proving tests (public inputs) run: cargo test --release --verbose tests::mock_public_inputs_ @@ -74,9 +74,9 @@ jobs: components: rustfmt, clippy - name: IPA full-prove tests - run: cargo test --release --verbose tests::ipa_fullprove_ + run: cargo test --release --verbose tests::ipa_fullprove_ -- --test-threads 1 - name: KZG full-prove tests - run: cargo test --release --verbose tests::kzg_fullprove_ + run: cargo test --release --verbose tests::kzg_fullprove_ -- --test-threads 1 prove-and-verify-tests: @@ -92,6 +92,6 @@ jobs: components: rustfmt, clippy - name: IPA prove and verify tests - run: cargo test --release --verbose tests::ipa_prove_and_verify_ + run: cargo test --release --verbose tests::ipa_prove_and_verify_ -- --test-threads 1 - name: KZG prove and verify tests run: cargo test --release --verbose tests::kzg_prove_and_verify_ -- --test-threads 1