From a5bf64b1a244734002765a78dcd99a674de42065 Mon Sep 17 00:00:00 2001 From: dante <45801863+alexander-camuto@users.noreply.github.com> Date: Sat, 16 Mar 2024 16:31:01 +0000 Subject: [PATCH] feat!: ipa commitments (#740) BREAKING CHANGE: commitment is now an added flag --- .github/workflows/rust.yml | 38 +- benches/accum_conv.rs | 34 +- benches/accum_dot.rs | 29 +- benches/accum_einsum_matmul.rs | 29 +- benches/accum_matmul_relu.rs | 29 +- benches/accum_matmul_relu_overflow.rs | 29 +- benches/accum_sum.rs | 29 +- benches/accum_sumpool.rs | 34 +- benches/pairwise_add.rs | 29 +- benches/pairwise_pow.rs | 29 +- benches/poseidon.rs | 30 +- benches/relu.rs | 28 +- examples/notebooks/generalized_inverse.ipynb | 6 +- examples/notebooks/hashed_vis.ipynb | 4 +- examples/notebooks/kzg_vis.ipynb | 12 +- .../notebooks/mnist_gan_proof_splitting.ipynb | 10 +- examples/notebooks/proof_splitting.ipynb | 12 +- .../simple_demo_aggregated_proofs.ipynb | 3 +- examples/notebooks/solvency.ipynb | 12 +- src/circuit/modules/mod.rs | 2 +- src/circuit/modules/{kzg.rs => polycommit.rs} | 57 +- src/circuit/ops/layouts.rs | 2 +- src/circuit/tests.rs | 211 +-- src/commands.rs | 47 +- src/execute.rs | 1195 ++++++++++------- src/graph/mod.rs | 63 +- src/graph/model.rs | 4 +- src/graph/modules.rs | 69 +- src/graph/vars.rs | 16 +- src/lib.rs | 75 ++ .../{aggregation.rs => aggregation_kzg.rs} | 0 src/pfsys/evm/mod.rs | 4 +- src/pfsys/mod.rs | 268 +--- src/pfsys/srs.rs | 13 +- src/python.rs | 145 +- src/wasm.rs | 166 ++- test_snark_serialization_roundtrip.json | 1 - tests/integration_tests.rs | 175 +-- tests/py_integration_tests.rs | 1 + tests/python/binding_tests.py | 2 +- tests/wasm/model.compiled | Bin 1720 -> 1724 bytes tests/wasm/proof.json | 2 +- tests/wasm/settings.json | 5 +- 43 files changed, 1754 insertions(+), 1195 deletions(-) rename src/circuit/modules/{kzg.rs => polycommit.rs} (79%) rename src/pfsys/evm/{aggregation.rs => aggregation_kzg.rs} (100%) delete mode 100644 test_snark_serialization_roundtrip.json diff --git a/.github/workflows/rust.yml b/.github/workflows/rust.yml index 78c642d0e..1315efaff 100644 --- a/.github/workflows/rust.yml +++ b/.github/workflows/rust.yml @@ -392,6 +392,10 @@ jobs: - name: Replace memory definition in nodejs run: | sed -i "3s|.*|imports['env'] = {memory: new WebAssembly.Memory({initial:20,maximum:65536,shared:true})}|" tests/wasm/nodejs/ezkl.js + - name: IPA prove and verify tests + run: cargo nextest run --release --verbose tests::ipa_prove_and_verify_::t --test-threads 1 + - name: IPA prove and verify tests (ipa outputs) + run: cargo nextest run --release --verbose tests::ipa_prove_and_verify_ipa_output - name: KZG prove and verify tests (public outputs + column overflow) run: cargo nextest run --release --verbose tests::kzg_prove_and_verify_with_overflow_::w - name: KZG prove and verify tests single inner col @@ -452,28 +456,6 @@ jobs: - name: KZG prove and verify tests (hashed outputs) run: cargo nextest run --release --verbose tests::kzg_prove_and_verify_hashed --features icicle --test-threads 1 - fuzz-tests: - runs-on: ubuntu-latest-32-cores - needs: [build, library-tests, python-tests] - steps: - - uses: actions/checkout@v4 - - uses: actions-rs/toolchain@v1 - with: - toolchain: nightly-2024-01-04 - override: true - components: rustfmt, clippy - - uses: baptiste0928/cargo-install@v1 - with: - crate: cargo-nextest - locked: true - - name: Install solc - run: (hash svm 2>/dev/null || cargo install svm-rs) && svm install 0.8.20 && solc --version - - name: Install Anvil - run: cargo install --git https://github.com/foundry-rs/foundry --rev b320f350156a0fb15c2eb13dc380deb2367c4474 --profile local --locked anvil --force - - name: fuzz tests (EVM) - run: cargo nextest run --release --verbose tests_evm::kzg_evm_fuzz_ --test-threads 2 - # - name: fuzz tests - # run: cargo nextest run --release --verbose tests::kzg_fuzz_ --test-threads 6 prove-and-verify-mock-aggr-tests: runs-on: self-hosted @@ -489,7 +471,7 @@ jobs: with: crate: cargo-nextest locked: true - - name: Mock aggr tests + - name: Mock aggr tests (KZG) run: cargo nextest run --release --verbose tests_aggr::kzg_aggr_mock_prove_and_verify_ --test-threads 8 prove-and-verify-aggr-tests-gpu: @@ -524,9 +506,11 @@ jobs: with: crate: cargo-nextest locked: true - - name: KZG )tests + - name: KZG tests run: cargo nextest run --release --verbose tests_aggr::kzg_aggr_prove_and_verify_ --test-threads 4 -- --include-ignored + + prove-and-verify-aggr-evm-tests: runs-on: large-self-hosted needs: [build, library-tests] @@ -629,7 +613,7 @@ jobs: - uses: actions/checkout@v4 - uses: actions/setup-python@v4 with: - python-version: "3.9" + python-version: "3.10" - uses: actions-rs/toolchain@v1 with: toolchain: nightly-2024-01-04 @@ -657,12 +641,12 @@ jobs: # echo $KAGGLE_API_KEY > /home/ubuntu/.kaggle/kaggle.json # chmod 600 /home/ubuntu/.kaggle/kaggle.json - name: All notebooks - run: source .env/bin/activate; cargo nextest run py_tests::tests::run_notebook_ --no-capture + run: source .env/bin/activate; cargo nextest run py_tests::tests::run_notebook_ --test-threads 1 - name: Voice tutorial run: source .env/bin/activate; cargo nextest run py_tests::tests::voice_ - name: NBEATS tutorial run: source .env/bin/activate; cargo nextest run py_tests::tests::nbeats_ - name: Tictactoe tutorials - run: source .env/bin/activate; cargo nextest run py_tests::tests::tictactoe_ --no-capture + run: source .env/bin/activate; cargo nextest run py_tests::tests::tictactoe_ # - name: Postgres tutorials # run: source .env/bin/activate; cargo nextest run py_tests::tests::postgres_ --test-threads 1 diff --git a/benches/accum_conv.rs b/benches/accum_conv.rs index 508eeea5e..c70331d59 100644 --- a/benches/accum_conv.rs +++ b/benches/accum_conv.rs @@ -2,11 +2,13 @@ use criterion::{criterion_group, criterion_main, BenchmarkId, Criterion, Through use ezkl::circuit::poly::PolyOp; use ezkl::circuit::*; use ezkl::pfsys::create_keys; -use ezkl::pfsys::create_proof_circuit_kzg; +use ezkl::pfsys::create_proof_circuit; use ezkl::pfsys::srs::gen_srs; use ezkl::pfsys::TranscriptType; use ezkl::tensor::*; use halo2_proofs::poly::kzg::commitment::KZGCommitmentScheme; +use halo2_proofs::poly::kzg::multiopen::ProverSHPLONK; +use halo2_proofs::poly::kzg::multiopen::VerifierSHPLONK; use halo2_proofs::poly::kzg::strategy::SingleStrategy; use halo2_proofs::{ arithmetic::Field, @@ -15,6 +17,7 @@ use halo2_proofs::{ }; use halo2curves::bn256::{Bn256, Fr}; use rand::rngs::OsRng; +use snark_verifier::system::halo2::transcript::evm::EvmTranscript; static mut KERNEL_HEIGHT: usize = 2; static mut KERNEL_WIDTH: usize = 2; @@ -121,28 +124,35 @@ fn runcnvrl(c: &mut Criterion) { group.throughput(Throughput::Elements(*size as u64)); group.bench_with_input(BenchmarkId::new("pk", size), &size, |b, &_| { b.iter(|| { - create_keys::, Fr, MyCircuit>( - &circuit, ¶ms, true, - ) - .unwrap(); + create_keys::, MyCircuit>(&circuit, ¶ms, true) + .unwrap(); }); }); - let pk = - create_keys::, Fr, MyCircuit>(&circuit, ¶ms, true) - .unwrap(); + let pk = create_keys::, MyCircuit>(&circuit, ¶ms, true) + .unwrap(); group.throughput(Throughput::Elements(*size as u64)); group.bench_with_input(BenchmarkId::new("prove", size), &size, |b, &_| { b.iter(|| { - let prover = create_proof_circuit_kzg( + let prover = create_proof_circuit::< + KZGCommitmentScheme<_>, + MyCircuit, + ProverSHPLONK<_>, + VerifierSHPLONK<_>, + SingleStrategy<_>, + _, + EvmTranscript<_, _, _, _>, + EvmTranscript<_, _, _, _>, + >( circuit.clone(), + vec![], ¶ms, - None, &pk, - TranscriptType::EVM, - SingleStrategy::new(¶ms), CheckMode::UNSAFE, + ezkl::Commitments::KZG, + TranscriptType::EVM, + None, None, ); prover.unwrap(); diff --git a/benches/accum_dot.rs b/benches/accum_dot.rs index 2d9bd9b90..2bf98446d 100644 --- a/benches/accum_dot.rs +++ b/benches/accum_dot.rs @@ -1,11 +1,13 @@ use criterion::{criterion_group, criterion_main, BenchmarkId, Criterion, Throughput}; use ezkl::circuit::poly::PolyOp; use ezkl::circuit::*; -use ezkl::pfsys::create_proof_circuit_kzg; +use ezkl::pfsys::create_proof_circuit; use ezkl::pfsys::TranscriptType; use ezkl::pfsys::{create_keys, srs::gen_srs}; use ezkl::tensor::*; use halo2_proofs::poly::kzg::commitment::KZGCommitmentScheme; +use halo2_proofs::poly::kzg::multiopen::ProverSHPLONK; +use halo2_proofs::poly::kzg::multiopen::VerifierSHPLONK; use halo2_proofs::poly::kzg::strategy::SingleStrategy; use halo2_proofs::{ arithmetic::Field, @@ -14,6 +16,7 @@ use halo2_proofs::{ }; use halo2curves::bn256::{Bn256, Fr}; use rand::rngs::OsRng; +use snark_verifier::system::halo2::transcript::evm::EvmTranscript; use std::marker::PhantomData; static mut LEN: usize = 4; @@ -90,25 +93,35 @@ fn rundot(c: &mut Criterion) { group.throughput(Throughput::Elements(len as u64)); group.bench_with_input(BenchmarkId::new("pk", len), &len, |b, &_| { b.iter(|| { - create_keys::, Fr, MyCircuit>(&circuit, ¶ms, true) + create_keys::, MyCircuit>(&circuit, ¶ms, true) .unwrap(); }); }); - let pk = create_keys::, Fr, MyCircuit>(&circuit, ¶ms, true) - .unwrap(); + let pk = + create_keys::, MyCircuit>(&circuit, ¶ms, true).unwrap(); group.throughput(Throughput::Elements(len as u64)); group.bench_with_input(BenchmarkId::new("prove", len), &len, |b, &_| { b.iter(|| { - let prover = create_proof_circuit_kzg( + let prover = create_proof_circuit::< + KZGCommitmentScheme<_>, + MyCircuit, + ProverSHPLONK<_>, + VerifierSHPLONK<_>, + SingleStrategy<_>, + _, + EvmTranscript<_, _, _, _>, + EvmTranscript<_, _, _, _>, + >( circuit.clone(), + vec![], ¶ms, - None, &pk, - TranscriptType::EVM, - SingleStrategy::new(¶ms), CheckMode::UNSAFE, + ezkl::Commitments::KZG, + TranscriptType::EVM, + None, None, ); prover.unwrap(); diff --git a/benches/accum_einsum_matmul.rs b/benches/accum_einsum_matmul.rs index 10cc8af95..cba1e0947 100644 --- a/benches/accum_einsum_matmul.rs +++ b/benches/accum_einsum_matmul.rs @@ -1,11 +1,13 @@ use criterion::{criterion_group, criterion_main, BenchmarkId, Criterion, Throughput}; use ezkl::circuit::poly::PolyOp; use ezkl::circuit::*; -use ezkl::pfsys::create_proof_circuit_kzg; +use ezkl::pfsys::create_proof_circuit; use ezkl::pfsys::TranscriptType; use ezkl::pfsys::{create_keys, srs::gen_srs}; use ezkl::tensor::*; use halo2_proofs::poly::kzg::commitment::KZGCommitmentScheme; +use halo2_proofs::poly::kzg::multiopen::ProverSHPLONK; +use halo2_proofs::poly::kzg::multiopen::VerifierSHPLONK; use halo2_proofs::poly::kzg::strategy::SingleStrategy; use halo2_proofs::{ arithmetic::Field, @@ -14,6 +16,7 @@ use halo2_proofs::{ }; use halo2curves::bn256::{Bn256, Fr}; use rand::rngs::OsRng; +use snark_verifier::system::halo2::transcript::evm::EvmTranscript; use std::marker::PhantomData; static mut LEN: usize = 4; @@ -94,25 +97,35 @@ fn runmatmul(c: &mut Criterion) { group.throughput(Throughput::Elements(len as u64)); group.bench_with_input(BenchmarkId::new("pk", len), &len, |b, &_| { b.iter(|| { - create_keys::, Fr, MyCircuit>(&circuit, ¶ms, true) + create_keys::, MyCircuit>(&circuit, ¶ms, true) .unwrap(); }); }); - let pk = create_keys::, Fr, MyCircuit>(&circuit, ¶ms, true) - .unwrap(); + let pk = + create_keys::, MyCircuit>(&circuit, ¶ms, true).unwrap(); group.throughput(Throughput::Elements(len as u64)); group.bench_with_input(BenchmarkId::new("prove", len), &len, |b, &_| { b.iter(|| { - let prover = create_proof_circuit_kzg( + let prover = create_proof_circuit::< + KZGCommitmentScheme<_>, + MyCircuit, + ProverSHPLONK<_>, + VerifierSHPLONK<_>, + SingleStrategy<_>, + _, + EvmTranscript<_, _, _, _>, + EvmTranscript<_, _, _, _>, + >( circuit.clone(), + vec![], ¶ms, - None, &pk, - TranscriptType::EVM, - SingleStrategy::new(¶ms), CheckMode::UNSAFE, + ezkl::Commitments::KZG, + TranscriptType::EVM, + None, None, ); prover.unwrap(); diff --git a/benches/accum_matmul_relu.rs b/benches/accum_matmul_relu.rs index c080434af..0aa8901ef 100644 --- a/benches/accum_matmul_relu.rs +++ b/benches/accum_matmul_relu.rs @@ -4,17 +4,20 @@ use ezkl::circuit::*; use ezkl::circuit::lookup::LookupOp; use ezkl::circuit::poly::PolyOp; -use ezkl::pfsys::create_proof_circuit_kzg; +use ezkl::pfsys::create_proof_circuit; use ezkl::pfsys::TranscriptType; use ezkl::pfsys::{create_keys, srs::gen_srs}; use ezkl::tensor::*; use halo2_proofs::poly::kzg::commitment::KZGCommitmentScheme; +use halo2_proofs::poly::kzg::multiopen::ProverSHPLONK; +use halo2_proofs::poly::kzg::multiopen::VerifierSHPLONK; use halo2_proofs::poly::kzg::strategy::SingleStrategy; use halo2_proofs::{ circuit::{Layouter, SimpleFloorPlanner, Value}, plonk::{Circuit, ConstraintSystem, Error}, }; use halo2curves::bn256::{Bn256, Fr}; +use snark_verifier::system::halo2::transcript::evm::EvmTranscript; use std::marker::PhantomData; const BITS: Range = (-32768, 32768); @@ -112,25 +115,35 @@ fn runmatmul(c: &mut Criterion) { group.throughput(Throughput::Elements(len as u64)); group.bench_with_input(BenchmarkId::new("pk", len), &len, |b, &_| { b.iter(|| { - create_keys::, Fr, MyCircuit>(&circuit, ¶ms, true) + create_keys::, MyCircuit>(&circuit, ¶ms, true) .unwrap(); }); }); - let pk = create_keys::, Fr, MyCircuit>(&circuit, ¶ms, true) - .unwrap(); + let pk = + create_keys::, MyCircuit>(&circuit, ¶ms, true).unwrap(); group.throughput(Throughput::Elements(len as u64)); group.bench_with_input(BenchmarkId::new("prove", len), &len, |b, &_| { b.iter(|| { - let prover = create_proof_circuit_kzg( + let prover = create_proof_circuit::< + KZGCommitmentScheme<_>, + MyCircuit, + ProverSHPLONK<_>, + VerifierSHPLONK<_>, + SingleStrategy<_>, + _, + EvmTranscript<_, _, _, _>, + EvmTranscript<_, _, _, _>, + >( circuit.clone(), + vec![], ¶ms, - None, &pk, + CheckMode::UNSAFE, + ezkl::Commitments::KZG, TranscriptType::EVM, - SingleStrategy::new(¶ms), - CheckMode::SAFE, + None, None, ); prover.unwrap(); diff --git a/benches/accum_matmul_relu_overflow.rs b/benches/accum_matmul_relu_overflow.rs index 549eb79de..b69ae7068 100644 --- a/benches/accum_matmul_relu_overflow.rs +++ b/benches/accum_matmul_relu_overflow.rs @@ -4,17 +4,20 @@ use ezkl::circuit::*; use ezkl::circuit::lookup::LookupOp; use ezkl::circuit::poly::PolyOp; use ezkl::circuit::table::Range; -use ezkl::pfsys::create_proof_circuit_kzg; +use ezkl::pfsys::create_proof_circuit; use ezkl::pfsys::TranscriptType; use ezkl::pfsys::{create_keys, srs::gen_srs}; use ezkl::tensor::*; use halo2_proofs::poly::kzg::commitment::KZGCommitmentScheme; +use halo2_proofs::poly::kzg::multiopen::ProverSHPLONK; +use halo2_proofs::poly::kzg::multiopen::VerifierSHPLONK; use halo2_proofs::poly::kzg::strategy::SingleStrategy; use halo2_proofs::{ circuit::{Layouter, SimpleFloorPlanner, Value}, plonk::{Circuit, ConstraintSystem, Error}, }; use halo2curves::bn256::{Bn256, Fr}; +use snark_verifier::system::halo2::transcript::evm::EvmTranscript; use std::marker::PhantomData; const BITS: Range = (-8180, 8180); @@ -115,25 +118,35 @@ fn runmatmul(c: &mut Criterion) { group.throughput(Throughput::Elements(k as u64)); group.bench_with_input(BenchmarkId::new("pk", k), &k, |b, &_| { b.iter(|| { - create_keys::, Fr, MyCircuit>(&circuit, ¶ms, true) + create_keys::, MyCircuit>(&circuit, ¶ms, true) .unwrap(); }); }); - let pk = create_keys::, Fr, MyCircuit>(&circuit, ¶ms, true) - .unwrap(); + let pk = + create_keys::, MyCircuit>(&circuit, ¶ms, true).unwrap(); group.throughput(Throughput::Elements(k as u64)); group.bench_with_input(BenchmarkId::new("prove", k), &k, |b, &_| { b.iter(|| { - let prover = create_proof_circuit_kzg( + let prover = create_proof_circuit::< + KZGCommitmentScheme<_>, + MyCircuit, + ProverSHPLONK<_>, + VerifierSHPLONK<_>, + SingleStrategy<_>, + _, + EvmTranscript<_, _, _, _>, + EvmTranscript<_, _, _, _>, + >( circuit.clone(), + vec![], ¶ms, - None, &pk, + CheckMode::UNSAFE, + ezkl::Commitments::KZG, TranscriptType::EVM, - SingleStrategy::new(¶ms), - CheckMode::SAFE, + None, None, ); prover.unwrap(); diff --git a/benches/accum_sum.rs b/benches/accum_sum.rs index 46b5df514..eb1caf6fa 100644 --- a/benches/accum_sum.rs +++ b/benches/accum_sum.rs @@ -1,11 +1,13 @@ use criterion::{criterion_group, criterion_main, BenchmarkId, Criterion, Throughput}; use ezkl::circuit::poly::PolyOp; use ezkl::circuit::*; -use ezkl::pfsys::create_proof_circuit_kzg; +use ezkl::pfsys::create_proof_circuit; use ezkl::pfsys::TranscriptType; use ezkl::pfsys::{create_keys, srs::gen_srs}; use ezkl::tensor::*; use halo2_proofs::poly::kzg::commitment::KZGCommitmentScheme; +use halo2_proofs::poly::kzg::multiopen::ProverSHPLONK; +use halo2_proofs::poly::kzg::multiopen::VerifierSHPLONK; use halo2_proofs::poly::kzg::strategy::SingleStrategy; use halo2_proofs::{ arithmetic::Field, @@ -14,6 +16,7 @@ use halo2_proofs::{ }; use halo2curves::bn256::{Bn256, Fr}; use rand::rngs::OsRng; +use snark_verifier::system::halo2::transcript::evm::EvmTranscript; use std::marker::PhantomData; static mut LEN: usize = 4; @@ -86,25 +89,35 @@ fn runsum(c: &mut Criterion) { group.throughput(Throughput::Elements(len as u64)); group.bench_with_input(BenchmarkId::new("pk", len), &len, |b, &_| { b.iter(|| { - create_keys::, Fr, MyCircuit>(&circuit, ¶ms, true) + create_keys::, MyCircuit>(&circuit, ¶ms, true) .unwrap(); }); }); - let pk = create_keys::, Fr, MyCircuit>(&circuit, ¶ms, true) - .unwrap(); + let pk = + create_keys::, MyCircuit>(&circuit, ¶ms, true).unwrap(); group.throughput(Throughput::Elements(len as u64)); group.bench_with_input(BenchmarkId::new("prove", len), &len, |b, &_| { b.iter(|| { - let prover = create_proof_circuit_kzg( + let prover = create_proof_circuit::< + KZGCommitmentScheme<_>, + MyCircuit, + ProverSHPLONK<_>, + VerifierSHPLONK<_>, + SingleStrategy<_>, + _, + EvmTranscript<_, _, _, _>, + EvmTranscript<_, _, _, _>, + >( circuit.clone(), + vec![], ¶ms, - None, &pk, - TranscriptType::EVM, - SingleStrategy::new(¶ms), CheckMode::UNSAFE, + ezkl::Commitments::KZG, + TranscriptType::EVM, + None, None, ); prover.unwrap(); diff --git a/benches/accum_sumpool.rs b/benches/accum_sumpool.rs index 9d324f20c..a1c9c5bc8 100644 --- a/benches/accum_sumpool.rs +++ b/benches/accum_sumpool.rs @@ -2,11 +2,13 @@ use criterion::{criterion_group, criterion_main, BenchmarkId, Criterion, Through use ezkl::circuit::hybrid::HybridOp; use ezkl::circuit::*; use ezkl::pfsys::create_keys; -use ezkl::pfsys::create_proof_circuit_kzg; +use ezkl::pfsys::create_proof_circuit; use ezkl::pfsys::srs::gen_srs; use ezkl::pfsys::TranscriptType; use ezkl::tensor::*; use halo2_proofs::poly::kzg::commitment::KZGCommitmentScheme; +use halo2_proofs::poly::kzg::multiopen::ProverSHPLONK; +use halo2_proofs::poly::kzg::multiopen::VerifierSHPLONK; use halo2_proofs::poly::kzg::strategy::SingleStrategy; use halo2_proofs::{ arithmetic::Field, @@ -15,6 +17,7 @@ use halo2_proofs::{ }; use halo2curves::bn256::{Bn256, Fr}; use rand::rngs::OsRng; +use snark_verifier::system::halo2::transcript::evm::EvmTranscript; static mut IMAGE_HEIGHT: usize = 2; static mut IMAGE_WIDTH: usize = 2; @@ -101,28 +104,35 @@ fn runsumpool(c: &mut Criterion) { group.throughput(Throughput::Elements(*size as u64)); group.bench_with_input(BenchmarkId::new("pk", size), &size, |b, &_| { b.iter(|| { - create_keys::, Fr, MyCircuit>( - &circuit, ¶ms, true, - ) - .unwrap(); + create_keys::, MyCircuit>(&circuit, ¶ms, true) + .unwrap(); }); }); - let pk = - create_keys::, Fr, MyCircuit>(&circuit, ¶ms, true) - .unwrap(); + let pk = create_keys::, MyCircuit>(&circuit, ¶ms, true) + .unwrap(); group.throughput(Throughput::Elements(*size as u64)); group.bench_with_input(BenchmarkId::new("prove", size), &size, |b, &_| { b.iter(|| { - let prover = create_proof_circuit_kzg( + let prover = create_proof_circuit::< + KZGCommitmentScheme<_>, + MyCircuit, + ProverSHPLONK<_>, + VerifierSHPLONK<_>, + SingleStrategy<_>, + _, + EvmTranscript<_, _, _, _>, + EvmTranscript<_, _, _, _>, + >( circuit.clone(), + vec![], ¶ms, - None, &pk, - TranscriptType::EVM, - SingleStrategy::new(¶ms), CheckMode::UNSAFE, + ezkl::Commitments::KZG, + TranscriptType::EVM, + None, None, ); prover.unwrap(); diff --git a/benches/pairwise_add.rs b/benches/pairwise_add.rs index f2b048c2e..0dfbc85ce 100644 --- a/benches/pairwise_add.rs +++ b/benches/pairwise_add.rs @@ -1,11 +1,13 @@ use criterion::{criterion_group, criterion_main, BenchmarkId, Criterion, Throughput}; use ezkl::circuit::poly::PolyOp; use ezkl::circuit::*; -use ezkl::pfsys::create_proof_circuit_kzg; +use ezkl::pfsys::create_proof_circuit; use ezkl::pfsys::TranscriptType; use ezkl::pfsys::{create_keys, srs::gen_srs}; use ezkl::tensor::*; use halo2_proofs::poly::kzg::commitment::KZGCommitmentScheme; +use halo2_proofs::poly::kzg::multiopen::ProverSHPLONK; +use halo2_proofs::poly::kzg::multiopen::VerifierSHPLONK; use halo2_proofs::poly::kzg::strategy::SingleStrategy; use halo2_proofs::{ arithmetic::Field, @@ -14,6 +16,7 @@ use halo2_proofs::{ }; use halo2curves::bn256::{Bn256, Fr}; use rand::rngs::OsRng; +use snark_verifier::system::halo2::transcript::evm::EvmTranscript; use std::marker::PhantomData; static mut LEN: usize = 4; @@ -84,25 +87,35 @@ fn runadd(c: &mut Criterion) { group.throughput(Throughput::Elements(len as u64)); group.bench_with_input(BenchmarkId::new("pk", len), &len, |b, &_| { b.iter(|| { - create_keys::, Fr, MyCircuit>(&circuit, ¶ms, true) + create_keys::, MyCircuit>(&circuit, ¶ms, true) .unwrap(); }); }); - let pk = create_keys::, Fr, MyCircuit>(&circuit, ¶ms, true) - .unwrap(); + let pk = + create_keys::, MyCircuit>(&circuit, ¶ms, true).unwrap(); group.throughput(Throughput::Elements(len as u64)); group.bench_with_input(BenchmarkId::new("prove", len), &len, |b, &_| { b.iter(|| { - let prover = create_proof_circuit_kzg( + let prover = create_proof_circuit::< + KZGCommitmentScheme<_>, + MyCircuit, + ProverSHPLONK<_>, + VerifierSHPLONK<_>, + SingleStrategy<_>, + _, + EvmTranscript<_, _, _, _>, + EvmTranscript<_, _, _, _>, + >( circuit.clone(), + vec![], ¶ms, - None, &pk, + CheckMode::UNSAFE, + ezkl::Commitments::KZG, TranscriptType::EVM, - SingleStrategy::new(¶ms), - CheckMode::SAFE, + None, None, ); prover.unwrap(); diff --git a/benches/pairwise_pow.rs b/benches/pairwise_pow.rs index 1af5376b0..d4e41680e 100644 --- a/benches/pairwise_pow.rs +++ b/benches/pairwise_pow.rs @@ -2,11 +2,13 @@ use criterion::{criterion_group, criterion_main, BenchmarkId, Criterion, Through use ezkl::circuit::poly::PolyOp; use ezkl::circuit::region::RegionCtx; use ezkl::circuit::*; -use ezkl::pfsys::create_proof_circuit_kzg; +use ezkl::pfsys::create_proof_circuit; use ezkl::pfsys::TranscriptType; use ezkl::pfsys::{create_keys, srs::gen_srs}; use ezkl::tensor::*; use halo2_proofs::poly::kzg::commitment::KZGCommitmentScheme; +use halo2_proofs::poly::kzg::multiopen::ProverSHPLONK; +use halo2_proofs::poly::kzg::multiopen::VerifierSHPLONK; use halo2_proofs::poly::kzg::strategy::SingleStrategy; use halo2_proofs::{ arithmetic::Field, @@ -15,6 +17,7 @@ use halo2_proofs::{ }; use halo2curves::bn256::{Bn256, Fr}; use rand::rngs::OsRng; +use snark_verifier::system::halo2::transcript::evm::EvmTranscript; use std::marker::PhantomData; static mut LEN: usize = 4; @@ -83,25 +86,35 @@ fn runpow(c: &mut Criterion) { group.throughput(Throughput::Elements(len as u64)); group.bench_with_input(BenchmarkId::new("pk", len), &len, |b, &_| { b.iter(|| { - create_keys::, Fr, MyCircuit>(&circuit, ¶ms, true) + create_keys::, MyCircuit>(&circuit, ¶ms, true) .unwrap(); }); }); - let pk = create_keys::, Fr, MyCircuit>(&circuit, ¶ms, true) - .unwrap(); + let pk = + create_keys::, MyCircuit>(&circuit, ¶ms, true).unwrap(); group.throughput(Throughput::Elements(len as u64)); group.bench_with_input(BenchmarkId::new("prove", len), &len, |b, &_| { b.iter(|| { - let prover = create_proof_circuit_kzg( + let prover = create_proof_circuit::< + KZGCommitmentScheme<_>, + MyCircuit, + ProverSHPLONK<_>, + VerifierSHPLONK<_>, + SingleStrategy<_>, + _, + EvmTranscript<_, _, _, _>, + EvmTranscript<_, _, _, _>, + >( circuit.clone(), + vec![], ¶ms, - None, &pk, + CheckMode::UNSAFE, + ezkl::Commitments::KZG, TranscriptType::EVM, - SingleStrategy::new(¶ms), - CheckMode::SAFE, + None, None, ); prover.unwrap(); diff --git a/benches/poseidon.rs b/benches/poseidon.rs index d16b63ff5..2229e29fd 100644 --- a/benches/poseidon.rs +++ b/benches/poseidon.rs @@ -4,12 +4,13 @@ use ezkl::circuit::modules::poseidon::{PoseidonChip, PoseidonConfig}; use ezkl::circuit::modules::Module; use ezkl::circuit::*; use ezkl::pfsys::create_keys; -use ezkl::pfsys::create_proof_circuit_kzg; +use ezkl::pfsys::create_proof_circuit; use ezkl::pfsys::srs::gen_srs; use ezkl::pfsys::TranscriptType; use ezkl::tensor::*; use halo2_proofs::circuit::Value; use halo2_proofs::poly::kzg::commitment::KZGCommitmentScheme; +use halo2_proofs::poly::kzg::multiopen::{ProverSHPLONK, VerifierSHPLONK}; use halo2_proofs::poly::kzg::strategy::SingleStrategy; use halo2_proofs::{ arithmetic::Field, @@ -18,6 +19,7 @@ use halo2_proofs::{ }; use halo2curves::bn256::{Bn256, Fr}; use rand::rngs::OsRng; +use snark_verifier::system::halo2::transcript::evm::EvmTranscript; const L: usize = 10; @@ -62,7 +64,7 @@ fn runposeidon(c: &mut Criterion) { let params = gen_srs::>(k); let message = (0..*size).map(|_| Fr::random(OsRng)).collect::>(); - let output = + let _output = PoseidonChip::::run(message.to_vec()) .unwrap(); @@ -76,25 +78,35 @@ fn runposeidon(c: &mut Criterion) { group.throughput(Throughput::Elements(*size as u64)); group.bench_with_input(BenchmarkId::new("pk", size), &size, |b, &_| { b.iter(|| { - create_keys::, Fr, MyCircuit>(&circuit, ¶ms, true) + create_keys::, MyCircuit>(&circuit, ¶ms, true) .unwrap(); }); }); - let pk = create_keys::, Fr, MyCircuit>(&circuit, ¶ms, true) - .unwrap(); + let pk = + create_keys::, MyCircuit>(&circuit, ¶ms, true).unwrap(); group.throughput(Throughput::Elements(*size as u64)); group.bench_with_input(BenchmarkId::new("prove", size), &size, |b, &_| { b.iter(|| { - let prover = create_proof_circuit_kzg( + let prover = create_proof_circuit::< + KZGCommitmentScheme<_>, + MyCircuit, + ProverSHPLONK<_>, + VerifierSHPLONK<_>, + SingleStrategy<_>, + _, + EvmTranscript<_, _, _, _>, + EvmTranscript<_, _, _, _>, + >( circuit.clone(), + vec![], ¶ms, - Some(output[0].clone()), &pk, - TranscriptType::EVM, - SingleStrategy::new(¶ms), CheckMode::UNSAFE, + ezkl::Commitments::KZG, + TranscriptType::EVM, + None, None, ); prover.unwrap(); diff --git a/benches/relu.rs b/benches/relu.rs index 0142e9667..061ac2e39 100644 --- a/benches/relu.rs +++ b/benches/relu.rs @@ -2,11 +2,12 @@ use criterion::{criterion_group, criterion_main, BenchmarkId, Criterion, Through use ezkl::circuit::region::RegionCtx; use ezkl::circuit::table::Range; use ezkl::circuit::{ops::lookup::LookupOp, BaseConfig as Config, CheckMode}; -use ezkl::pfsys::create_proof_circuit_kzg; +use ezkl::pfsys::create_proof_circuit; use ezkl::pfsys::TranscriptType; use ezkl::pfsys::{create_keys, srs::gen_srs}; use ezkl::tensor::*; use halo2_proofs::poly::kzg::commitment::KZGCommitmentScheme; +use halo2_proofs::poly::kzg::multiopen::{ProverSHPLONK, VerifierSHPLONK}; use halo2_proofs::poly::kzg::strategy::SingleStrategy; use halo2_proofs::{ circuit::{Layouter, SimpleFloorPlanner, Value}, @@ -14,6 +15,7 @@ use halo2_proofs::{ }; use halo2curves::bn256::{Bn256, Fr}; use rand::Rng; +use snark_verifier::system::halo2::transcript::evm::EvmTranscript; const BITS: Range = (-32768, 32768); static mut LEN: usize = 4; @@ -91,25 +93,35 @@ fn runrelu(c: &mut Criterion) { group.throughput(Throughput::Elements(len as u64)); group.bench_with_input(BenchmarkId::new("pk", len), &len, |b, &_| { b.iter(|| { - create_keys::, Fr, NLCircuit>(&circuit, ¶ms, true) + create_keys::, NLCircuit>(&circuit, ¶ms, true) .unwrap(); }); }); - let pk = create_keys::, Fr, NLCircuit>(&circuit, ¶ms, true) - .unwrap(); + let pk = + create_keys::, NLCircuit>(&circuit, ¶ms, true).unwrap(); group.throughput(Throughput::Elements(len as u64)); group.bench_with_input(BenchmarkId::new("prove", len), &len, |b, &_| { b.iter(|| { - let prover = create_proof_circuit_kzg( + let prover = create_proof_circuit::< + KZGCommitmentScheme<_>, + NLCircuit, + ProverSHPLONK<_>, + VerifierSHPLONK<_>, + SingleStrategy<_>, + _, + EvmTranscript<_, _, _, _>, + EvmTranscript<_, _, _, _>, + >( circuit.clone(), + vec![], ¶ms, - None, &pk, + CheckMode::UNSAFE, + ezkl::Commitments::KZG, TranscriptType::EVM, - SingleStrategy::new(¶ms), - CheckMode::SAFE, + None, None, ); prover.unwrap(); diff --git a/examples/notebooks/generalized_inverse.ipynb b/examples/notebooks/generalized_inverse.ipynb index 583b0038f..a71555ba4 100644 --- a/examples/notebooks/generalized_inverse.ipynb +++ b/examples/notebooks/generalized_inverse.ipynb @@ -10,7 +10,7 @@ "\n", "## Generalized Inverse\n", "\n", - "We show how to use EZKL to prove that we know matrices $A$ and its generalized inverse $B$. Since these are large we deal with the KZG commitments, with $a$ the kzgcommit of $A$, $b$ the kzgcommit of $B$, and $ABA = A$.\n" + "We show how to use EZKL to prove that we know matrices $A$ and its generalized inverse $B$. Since these are large we deal with the KZG commitments, with $a$ the polycommit of $A$, $b$ the polycommit of $B$, and $ABA = A$.\n" ] }, { @@ -77,7 +77,7 @@ "outputs": [], "source": [ "gip_run_args = ezkl.PyRunArgs()\n", - "gip_run_args.input_visibility = \"kzgcommit\" # matrix and generalized inverse commitments\n", + "gip_run_args.input_visibility = \"polycommit\" # matrix and generalized inverse commitments\n", "gip_run_args.output_visibility = \"fixed\" # no parameters used\n", "gip_run_args.param_visibility = \"fixed\" # should be Tensor(True)" ] @@ -340,4 +340,4 @@ }, "nbformat": 4, "nbformat_minor": 5 -} +} \ No newline at end of file diff --git a/examples/notebooks/hashed_vis.ipynb b/examples/notebooks/hashed_vis.ipynb index 439c2ea86..e41cd0eb0 100644 --- a/examples/notebooks/hashed_vis.ipynb +++ b/examples/notebooks/hashed_vis.ipynb @@ -161,7 +161,7 @@ "- `fixed`: known to the prover and verifier (as a commit), but not modifiable by the prover.\n", "- `hashed`: the hash pre-image is known to the prover, the prover and verifier know the hash. The prover proves that the they know the pre-image to the hash. \n", "- `encrypted`: the non-encrypted element and the secret key used for decryption are known to the prover. The prover and the verifier know the encrypted element, the public key used to encrypt, and the hash of the decryption hey. The prover proves that they know the pre-image of the hashed decryption key and that this key can in fact decrypt the encrypted message.\n", - "- `kzgcommit`: unblinded advice column which generates a kzg commitment. This doesn't appear in the instances of the circuit and must instead be inserted directly within the proof bytes. \n", + "- `polycommit`: unblinded advice column which generates a kzg commitment. This doesn't appear in the instances of the circuit and must instead be inserted directly within the proof bytes. \n", "\n", "\n", "Here we create the following setup:\n", @@ -510,4 +510,4 @@ }, "nbformat": 4, "nbformat_minor": 2 -} +} \ No newline at end of file diff --git a/examples/notebooks/kzg_vis.ipynb b/examples/notebooks/kzg_vis.ipynb index 1a2f38f3a..7d298c11a 100644 --- a/examples/notebooks/kzg_vis.ipynb +++ b/examples/notebooks/kzg_vis.ipynb @@ -154,11 +154,11 @@ "- `fixed`: known to the prover and verifier (as a commit), but not modifiable by the prover.\n", "- `hashed`: the hash pre-image is known to the prover, the prover and verifier know the hash. The prover proves that the they know the pre-image to the hash. \n", "- `encrypted`: the non-encrypted element and the secret key used for decryption are known to the prover. The prover and the verifier know the encrypted element, the public key used to encrypt, and the hash of the decryption hey. The prover proves that they know the pre-image of the hashed decryption key and that this key can in fact decrypt the encrypted message.\n", - "- `kzgcommit`: unblinded advice column which generates a kzg commitment. This doesn't appear in the instances of the circuit and must instead be modified directly within the proof bytes. \n", + "- `polycommit`: unblinded advice column which generates a kzg commitment. This doesn't appear in the instances of the circuit and must instead be modified directly within the proof bytes. \n", "\n", "Here we create the following setup:\n", - "- `input_visibility`: \"kzgcommit\"\n", - "- `param_visibility`: \"kzgcommit\"\n", + "- `input_visibility`: \"polycommit\"\n", + "- `param_visibility`: \"polycommit\"\n", "- `output_visibility`: public\n", "\n", "We encourage you to play around with other setups :) \n", @@ -186,8 +186,8 @@ "data_path = os.path.join('input.json')\n", "\n", "run_args = ezkl.PyRunArgs()\n", - "run_args.input_visibility = \"kzgcommit\"\n", - "run_args.param_visibility = \"kzgcommit\"\n", + "run_args.input_visibility = \"polycommit\"\n", + "run_args.param_visibility = \"polycommit\"\n", "run_args.output_visibility = \"public\"\n", "run_args.variables = [(\"batch_size\", 1)]\n", "\n", @@ -512,4 +512,4 @@ }, "nbformat": 4, "nbformat_minor": 2 -} +} \ No newline at end of file diff --git a/examples/notebooks/mnist_gan_proof_splitting.ipynb b/examples/notebooks/mnist_gan_proof_splitting.ipynb index 9e8abbcad..217058673 100644 --- a/examples/notebooks/mnist_gan_proof_splitting.ipynb +++ b/examples/notebooks/mnist_gan_proof_splitting.ipynb @@ -264,9 +264,9 @@ "### KZG commitment intermediate calculations\n", "\n", "the visibility parameters are:\n", - "- `input_visibility`: \"kzgcommit\"\n", + "- `input_visibility`: \"polycommit\"\n", "- `param_visibility`: \"public\"\n", - "- `output_visibility`: kzgcommit" + "- `output_visibility`: polycommit" ] }, { @@ -280,15 +280,15 @@ "srs_path = os.path.join('kzg.srs')\n", "\n", "run_args = ezkl.PyRunArgs()\n", - "run_args.input_visibility = \"kzgcommit\"\n", + "run_args.input_visibility = \"polycommit\"\n", "run_args.param_visibility = \"fixed\"\n", - "run_args.output_visibility = \"kzgcommit\"\n", + "run_args.output_visibility = \"polycommit\"\n", "run_args.variables = [(\"batch_size\", 1)]\n", "run_args.input_scale = 0\n", "run_args.param_scale = 0\n", "run_args.logrows = 18\n", "\n", - "ezkl.get_srs(logrows=run_args.logrows)\n" + "ezkl.get_srs(logrows=run_args.logrows, commitment=ezkl.PyCommitments.KZG)\n" ] }, { diff --git a/examples/notebooks/proof_splitting.ipynb b/examples/notebooks/proof_splitting.ipynb index 82a513509..99075fbf7 100644 --- a/examples/notebooks/proof_splitting.ipynb +++ b/examples/notebooks/proof_splitting.ipynb @@ -208,7 +208,7 @@ "- `private`: known only to the prover\n", "- `hashed`: the hash pre-image is known to the prover, the prover and verifier know the hash. The prover proves that the they know the pre-image to the hash. \n", "- `encrypted`: the non-encrypted element and the secret key used for decryption are known to the prover. The prover and the verifier know the encrypted element, the public key used to encrypt, and the hash of the decryption hey. The prover proves that they know the pre-image of the hashed decryption key and that this key can in fact decrypt the encrypted message.\n", - "- `kzgcommit`: unblinded advice column which generates a kzg commitment. This doesn't appear in the instances of the circuit and must instead be modified directly within the proof bytes. \n", + "- `polycommit`: unblinded advice column which generates a kzg commitment. This doesn't appear in the instances of the circuit and must instead be modified directly within the proof bytes. \n", "\n", "Here we create the following setup:\n", "- `input_visibility`: \"public\"\n", @@ -234,7 +234,7 @@ "run_args.input_scale = 2\n", "run_args.logrows = 8\n", "\n", - "ezkl.get_srs(logrows=run_args.logrows)" + "ezkl.get_srs(logrows=run_args.logrows, commitment=ezkl.PyCommitments.KZG)" ] }, { @@ -385,9 +385,9 @@ "### KZG commitment intermediate calculations\n", "\n", "This time the visibility parameters are:\n", - "- `input_visibility`: \"kzgcommit\"\n", + "- `input_visibility`: \"polycommit\"\n", "- `param_visibility`: \"public\"\n", - "- `output_visibility`: kzgcommit" + "- `output_visibility`: polycommit" ] }, { @@ -399,9 +399,9 @@ "import ezkl\n", "\n", "run_args = ezkl.PyRunArgs()\n", - "run_args.input_visibility = \"kzgcommit\"\n", + "run_args.input_visibility = \"polycommit\"\n", "run_args.param_visibility = \"fixed\"\n", - "run_args.output_visibility = \"kzgcommit\"\n", + "run_args.output_visibility = \"polycommit\"\n", "run_args.variables = [(\"batch_size\", 1)]\n", "run_args.input_scale = 2\n", "run_args.logrows = 8\n" diff --git a/examples/notebooks/simple_demo_aggregated_proofs.ipynb b/examples/notebooks/simple_demo_aggregated_proofs.ipynb index f2dbb1cb9..75ac50ffd 100644 --- a/examples/notebooks/simple_demo_aggregated_proofs.ipynb +++ b/examples/notebooks/simple_demo_aggregated_proofs.ipynb @@ -275,7 +275,6 @@ " proof_path,\n", " settings_path,\n", " vk_path,\n", - " \n", " )\n", "\n", "assert res == True\n", @@ -291,7 +290,7 @@ "source": [ "# Generate a larger SRS. This is needed for the aggregated proof\n", "\n", - "res = ezkl.get_srs(settings_path=None, logrows=21)" + "res = ezkl.get_srs(settings_path=None, logrows=21, commitment=ezkl.PyCommitments.KZG)" ] }, { diff --git a/examples/notebooks/solvency.ipynb b/examples/notebooks/solvency.ipynb index 6ab560d09..e1e2755db 100644 --- a/examples/notebooks/solvency.ipynb +++ b/examples/notebooks/solvency.ipynb @@ -9,7 +9,7 @@ "source": [ "## Solvency demo\n", "\n", - "Here we create a demo of a solvency calculation in the manner of [summa-solvency](https://github.com/summa-dev/summa-solvency). The aim here is to demonstrate the use of the new kzgcommit method detailed [here](https://blog.ezkl.xyz/post/commits/). \n", + "Here we create a demo of a solvency calculation in the manner of [summa-solvency](https://github.com/summa-dev/summa-solvency). The aim here is to demonstrate the use of the new polycommit method detailed [here](https://blog.ezkl.xyz/post/commits/). \n", "\n", "In this setup:\n", "- the commitments to users, respective balances, and total balance are known are publicly known to the prover and verifier. \n", @@ -177,10 +177,10 @@ "- `private`: known only to the prover\n", "- `hashed`: the hash pre-image is known to the prover, the prover and verifier know the hash. The prover proves that the they know the pre-image to the hash. \n", "- `encrypted`: the non-encrypted element and the secret key used for decryption are known to the prover. The prover and the verifier know the encrypted element, the public key used to encrypt, and the hash of the decryption hey. The prover proves that they know the pre-image of the hashed decryption key and that this key can in fact decrypt the encrypted message.\n", - "- `kzgcommit`: unblinded advice column which generates a kzg commitment. This doesn't appear in the instances of the circuit and must instead be modified directly within the proof bytes. \n", + "- `polycommit`: unblinded advice column which generates a kzg commitment. This doesn't appear in the instances of the circuit and must instead be modified directly within the proof bytes. \n", "\n", "Here we create the following setup:\n", - "- `input_visibility`: \"kzgcommit\"\n", + "- `input_visibility`: \"polycommit\"\n", "- `param_visibility`: \"public\"\n", "- `output_visibility`: public\n", "\n", @@ -202,8 +202,8 @@ "outputs": [], "source": [ "run_args = ezkl.PyRunArgs()\n", - "# \"kzgcommit\" means that the output of the hashing is not visible to the verifier and is instead fed into the computational graph\n", - "run_args.input_visibility = \"kzgcommit\"\n", + "# \"polycommit\" means that the output of the hashing is not visible to the verifier and is instead fed into the computational graph\n", + "run_args.input_visibility = \"polycommit\"\n", "# the parameters are public\n", "run_args.param_visibility = \"fixed\"\n", "# the output is public (this is the inequality test)\n", @@ -515,4 +515,4 @@ }, "nbformat": 4, "nbformat_minor": 5 -} +} \ No newline at end of file diff --git a/src/circuit/modules/mod.rs b/src/circuit/modules/mod.rs index bb957bdb5..385a24789 100644 --- a/src/circuit/modules/mod.rs +++ b/src/circuit/modules/mod.rs @@ -2,7 +2,7 @@ pub mod poseidon; /// -pub mod kzg; +pub mod polycommit; /// pub mod planner; diff --git a/src/circuit/modules/kzg.rs b/src/circuit/modules/polycommit.rs similarity index 79% rename from src/circuit/modules/kzg.rs rename to src/circuit/modules/polycommit.rs index 371946dee..2e63b44eb 100644 --- a/src/circuit/modules/kzg.rs +++ b/src/circuit/modules/polycommit.rs @@ -6,10 +6,9 @@ Thanks to https://github.com/summa-dev/summa-solvency/blob/master/src/chips/pose // This chip adds a set of advice columns to the gadget Chip to store the inputs of the hash use halo2_proofs::halo2curves::bn256::Fr as Fp; -use halo2_proofs::poly::commitment::{Blind, Params}; -use halo2_proofs::poly::kzg::commitment::ParamsKZG; +use halo2_proofs::poly::commitment::{Blind, CommitmentScheme, Params}; use halo2_proofs::{circuit::*, plonk::*}; -use halo2curves::bn256::{Bn256, G1Affine}; +use halo2curves::bn256::G1Affine; use halo2curves::group::prime::PrimeCurveAffine; use halo2curves::group::Curve; use halo2curves::CurveAffine; @@ -18,35 +17,33 @@ use crate::tensor::{Tensor, ValTensor, ValType, VarTensor}; use super::Module; -/// The number of instance columns used by the KZG hash function +/// The number of instance columns used by the PolyCommit hash function pub const NUM_INSTANCE_COLUMNS: usize = 0; -/// The number of advice columns used by the KZG hash function +/// The number of advice columns used by the PolyCommit hash function pub const NUM_INNER_COLS: usize = 1; #[derive(Debug, Clone)] -/// WIDTH, RATE and L are const generics for the struct, which represent the width, rate, and number of inputs for the Poseidon hash function, respectively. -/// This means they are values that are known at compile time and can be used to specialize the implementation of the struct. -/// The actual chip provided by halo2_gadgets is added to the parent Chip. -pub struct KZGConfig { +/// Configuration for the PolyCommit chip +pub struct PolyCommitConfig { /// - pub hash_inputs: VarTensor, + pub inputs: VarTensor, } type InputAssignments = (); -/// PoseidonChip is a wrapper around the Pow5Chip that adds a set of advice columns to the gadget Chip to store the inputs of the hash +/// #[derive(Debug)] -pub struct KZGChip { - config: KZGConfig, +pub struct PolyCommitChip { + config: PolyCommitConfig, } -impl KZGChip { +impl PolyCommitChip { /// Commit to the message using the KZG commitment scheme - pub fn commit( - message: Vec, + pub fn commit>( + message: Vec, degree: u32, num_unusable_rows: u32, - params: &ParamsKZG, + params: &Scheme::ParamsProver, ) -> Vec { let k = params.k(); let domain = halo2_proofs::poly::EvaluationDomain::new(degree, k); @@ -81,14 +78,14 @@ impl KZGChip { } } -impl Module for KZGChip { - type Config = KZGConfig; +impl Module for PolyCommitChip { + type Config = PolyCommitConfig; type InputAssignments = InputAssignments; type RunInputs = Vec; type Params = (usize, usize); fn name(&self) -> &'static str { - "KZG" + "PolyCommit" } fn instance_increment_input(&self) -> Vec { @@ -102,8 +99,8 @@ impl Module for KZGChip { /// Configuration of the PoseidonChip fn configure(meta: &mut ConstraintSystem, params: Self::Params) -> Self::Config { - let hash_inputs = VarTensor::new_unblinded_advice(meta, params.0, NUM_INNER_COLS, params.1); - Self::Config { hash_inputs } + let inputs = VarTensor::new_unblinded_advice(meta, params.0, NUM_INNER_COLS, params.1); + Self::Config { inputs } } fn layout_inputs( @@ -125,8 +122,8 @@ impl Module for KZGChip { ) -> Result, Error> { assert_eq!(input.len(), 1); layouter.assign_region( - || "kzg commit", - |mut region| self.config.hash_inputs.assign(&mut region, 0, &input[0]), + || "PolyCommit", + |mut region| self.config.inputs.assign(&mut region, 0, &input[0]), ) } @@ -163,7 +160,7 @@ mod tests { } impl Circuit for HashCircuit { - type Config = KZGConfig; + type Config = PolyCommitConfig; type FloorPlanner = ModulePlanner; type Params = (); @@ -178,7 +175,7 @@ mod tests { fn configure(meta: &mut ConstraintSystem) -> Self::Config { let params = (K, R); - KZGChip::configure(meta, params) + PolyCommitChip::configure(meta, params) } fn synthesize( @@ -186,8 +183,8 @@ mod tests { config: Self::Config, mut layouter: impl Layouter, ) -> Result<(), Error> { - let kzg_chip = KZGChip::new(config); - kzg_chip.layout(&mut layouter, &[self.message.clone()], 0); + let polycommit_chip = PolyCommitChip::new(config); + polycommit_chip.layout(&mut layouter, &[self.message.clone()], 0); Ok(()) } @@ -195,7 +192,7 @@ mod tests { #[test] #[ignore] - fn kzg_for_a_range_of_input_sizes() { + fn polycommit_chip_for_a_range_of_input_sizes() { let rng = rand::rngs::OsRng; #[cfg(not(target_arch = "wasm32"))] @@ -225,7 +222,7 @@ mod tests { #[test] #[ignore] - fn kzg_commit_much_longer_input() { + fn polycommit_chip_much_longer_input() { #[cfg(not(target_arch = "wasm32"))] env_logger::init(); diff --git a/src/circuit/ops/layouts.rs b/src/circuit/ops/layouts.rs index bbba353fe..e8649111f 100644 --- a/src/circuit/ops/layouts.rs +++ b/src/circuit/ops/layouts.rs @@ -1222,7 +1222,7 @@ pub(crate) fn linearize_nd_index( .iter() .map(|x| { let slice = x.iter().map(|x| *x..*x + 1).collect::>(); - Ok(index_slice.get_slice(&slice)?) + index_slice.get_slice(&slice) }) .collect::, Box>>()? }; diff --git a/src/circuit/tests.rs b/src/circuit/tests.rs index ff1c6fd88..7a8b68fca 100644 --- a/src/circuit/tests.rs +++ b/src/circuit/tests.rs @@ -245,7 +245,13 @@ mod matmul_col_overflow { #[cfg(test)] #[cfg(not(all(target_arch = "wasm32", target_os = "unknown")))] mod matmul_col_ultra_overflow_double_col { - use halo2_proofs::poly::commitment::{Params, ParamsProver}; + + use halo2_proofs::poly::kzg::{ + commitment::KZGCommitmentScheme, + multiopen::{ProverSHPLONK, VerifierSHPLONK}, + strategy::SingleStrategy, + }; + use snark_verifier::system::halo2::transcript::evm::EvmTranscript; use super::*; @@ -324,46 +330,46 @@ mod matmul_col_ultra_overflow_double_col { let pk = crate::pfsys::create_keys::< halo2_proofs::poly::kzg::commitment::KZGCommitmentScheme, - F, MatmulCircuit, >(&circuit, ¶ms, true) .unwrap(); - let prover = crate::pfsys::create_proof_circuit_kzg( + let prover = crate::pfsys::create_proof_circuit::< + KZGCommitmentScheme<_>, + _, + ProverSHPLONK<_>, + VerifierSHPLONK<_>, + SingleStrategy<_>, + _, + EvmTranscript<_, _, _, _>, + EvmTranscript<_, _, _, _>, + >( circuit.clone(), + vec![], ¶ms, - None, &pk, - crate::pfsys::TranscriptType::EVM, - halo2_proofs::poly::kzg::strategy::SingleStrategy::new(¶ms), // use safe mode to verify that the proof is correct CheckMode::SAFE, + crate::Commitments::KZG, + crate::pfsys::TranscriptType::EVM, + None, None, ); assert!(prover.is_ok()); - - let proof = prover.unwrap(); - - let strategy = - halo2_proofs::poly::kzg::strategy::SingleStrategy::new(params.verifier_params()); - let vk = pk.get_vk(); - let result = crate::pfsys::verify_proof_circuit_kzg( - params.verifier_params(), - proof, - vk, - strategy, - params.n(), - ); - - assert!(result.is_ok()); } } #[cfg(test)] #[cfg(not(all(target_arch = "wasm32", target_os = "unknown")))] mod matmul_col_ultra_overflow { - use halo2_proofs::poly::commitment::{Params, ParamsProver}; + + use halo2_proofs::poly::kzg::{ + commitment::KZGCommitmentScheme, + multiopen::{ProverSHPLONK, VerifierSHPLONK}, + strategy::SingleStrategy, + }; + use snark_verifier::system::halo2::transcript::evm::EvmTranscript; use super::*; @@ -441,39 +447,33 @@ mod matmul_col_ultra_overflow { let pk = crate::pfsys::create_keys::< halo2_proofs::poly::kzg::commitment::KZGCommitmentScheme, - F, MatmulCircuit, >(&circuit, ¶ms, true) .unwrap(); - let prover = crate::pfsys::create_proof_circuit_kzg( + let prover = crate::pfsys::create_proof_circuit::< + KZGCommitmentScheme<_>, + _, + ProverSHPLONK<_>, + VerifierSHPLONK<_>, + SingleStrategy<_>, + _, + EvmTranscript<_, _, _, _>, + EvmTranscript<_, _, _, _>, + >( circuit.clone(), + vec![], ¶ms, - None, &pk, - crate::pfsys::TranscriptType::EVM, - halo2_proofs::poly::kzg::strategy::SingleStrategy::new(¶ms), // use safe mode to verify that the proof is correct CheckMode::SAFE, + crate::Commitments::KZG, + crate::pfsys::TranscriptType::EVM, + None, None, ); assert!(prover.is_ok()); - - let proof = prover.unwrap(); - - let strategy = - halo2_proofs::poly::kzg::strategy::SingleStrategy::new(params.verifier_params()); - let vk = pk.get_vk(); - let result = crate::pfsys::verify_proof_circuit_kzg( - params.verifier_params(), - proof, - vk, - strategy, - params.n(), - ); - - assert!(result.is_ok()); } } @@ -1145,7 +1145,15 @@ mod conv { #[cfg(test)] #[cfg(not(all(target_arch = "wasm32", target_os = "unknown")))] mod conv_col_ultra_overflow { - use halo2_proofs::poly::commitment::{Params, ParamsProver}; + + use halo2_proofs::poly::{ + kzg::strategy::SingleStrategy, + kzg::{ + commitment::KZGCommitmentScheme, + multiopen::{ProverSHPLONK, VerifierSHPLONK}, + }, + }; + use snark_verifier::system::halo2::transcript::evm::EvmTranscript; use super::*; @@ -1243,39 +1251,33 @@ mod conv_col_ultra_overflow { let pk = crate::pfsys::create_keys::< halo2_proofs::poly::kzg::commitment::KZGCommitmentScheme, - F, ConvCircuit, >(&circuit, ¶ms, true) .unwrap(); - let prover = crate::pfsys::create_proof_circuit_kzg( + let prover = crate::pfsys::create_proof_circuit::< + KZGCommitmentScheme<_>, + _, + ProverSHPLONK<_>, + VerifierSHPLONK<_>, + SingleStrategy<_>, + _, + EvmTranscript<_, _, _, _>, + EvmTranscript<_, _, _, _>, + >( circuit.clone(), + vec![], ¶ms, - None, &pk, - crate::pfsys::TranscriptType::EVM, - halo2_proofs::poly::kzg::strategy::SingleStrategy::new(¶ms), // use safe mode to verify that the proof is correct CheckMode::SAFE, + crate::Commitments::KZG, + crate::pfsys::TranscriptType::EVM, + None, None, ); assert!(prover.is_ok()); - - let proof = prover.unwrap(); - - let strategy = - halo2_proofs::poly::kzg::strategy::SingleStrategy::new(params.verifier_params()); - let vk = pk.get_vk(); - let result = crate::pfsys::verify_proof_circuit_kzg( - params.verifier_params(), - proof, - vk, - strategy, - params.n(), - ); - - assert!(result.is_ok()); } } @@ -1283,7 +1285,13 @@ mod conv_col_ultra_overflow { // not wasm 32 unknown #[cfg(not(all(target_arch = "wasm32", target_os = "unknown")))] mod conv_relu_col_ultra_overflow { - use halo2_proofs::poly::commitment::{Params, ParamsProver}; + + use halo2_proofs::poly::kzg::{ + commitment::KZGCommitmentScheme, + multiopen::{ProverSHPLONK, VerifierSHPLONK}, + strategy::SingleStrategy, + }; + use snark_verifier::system::halo2::transcript::evm::EvmTranscript; use super::*; @@ -1396,39 +1404,33 @@ mod conv_relu_col_ultra_overflow { let pk = crate::pfsys::create_keys::< halo2_proofs::poly::kzg::commitment::KZGCommitmentScheme, - F, ConvCircuit, >(&circuit, ¶ms, true) .unwrap(); - let prover = crate::pfsys::create_proof_circuit_kzg( + let prover = crate::pfsys::create_proof_circuit::< + KZGCommitmentScheme<_>, + _, + ProverSHPLONK<_>, + VerifierSHPLONK<_>, + SingleStrategy<_>, + _, + EvmTranscript<_, _, _, _>, + EvmTranscript<_, _, _, _>, + >( circuit.clone(), + vec![], ¶ms, - None, &pk, + CheckMode::SAFE, + crate::Commitments::KZG, crate::pfsys::TranscriptType::EVM, - halo2_proofs::poly::kzg::strategy::SingleStrategy::new(¶ms), // use safe mode to verify that the proof is correct - CheckMode::SAFE, + None, None, ); assert!(prover.is_ok()); - - let proof = prover.unwrap(); - - let strategy = - halo2_proofs::poly::kzg::strategy::SingleStrategy::new(params.verifier_params()); - let vk = pk.get_vk(); - let result = crate::pfsys::verify_proof_circuit_kzg( - params.verifier_params(), - proof, - vk, - strategy, - params.n(), - ); - - assert!(result.is_ok()); } } @@ -2417,8 +2419,13 @@ mod lookup_ultra_overflow { use halo2_proofs::{ circuit::{Layouter, SimpleFloorPlanner, Value}, plonk::{Circuit, ConstraintSystem, Error}, - poly::commitment::{Params, ParamsProver}, + poly::kzg::{ + commitment::KZGCommitmentScheme, + multiopen::{ProverSHPLONK, VerifierSHPLONK}, + strategy::SingleStrategy, + }, }; + use snark_verifier::system::halo2::transcript::evm::EvmTranscript; #[derive(Clone)] struct ReLUCircuit { @@ -2497,38 +2504,32 @@ mod lookup_ultra_overflow { let pk = crate::pfsys::create_keys::< halo2_proofs::poly::kzg::commitment::KZGCommitmentScheme, - F, ReLUCircuit, >(&circuit, ¶ms, true) .unwrap(); - let prover = crate::pfsys::create_proof_circuit_kzg( + let prover = crate::pfsys::create_proof_circuit::< + KZGCommitmentScheme<_>, + _, + ProverSHPLONK<_>, + VerifierSHPLONK<_>, + SingleStrategy<_>, + _, + EvmTranscript<_, _, _, _>, + EvmTranscript<_, _, _, _>, + >( circuit.clone(), + vec![], ¶ms, - None, &pk, - crate::pfsys::TranscriptType::EVM, - halo2_proofs::poly::kzg::strategy::SingleStrategy::new(¶ms), // use safe mode to verify that the proof is correct CheckMode::SAFE, + crate::Commitments::KZG, + crate::pfsys::TranscriptType::EVM, + None, None, ); assert!(prover.is_ok()); - - let proof = prover.unwrap(); - - let strategy = - halo2_proofs::poly::kzg::strategy::SingleStrategy::new(params.verifier_params()); - let vk = pk.get_vk(); - let result = crate::pfsys::verify_proof_circuit_kzg( - params.verifier_params(), - proof, - vk, - strategy, - params.n(), - ); - - assert!(result.is_ok()); } } diff --git a/src/commands.rs b/src/commands.rs index d938b7661..5c7cb0f44 100644 --- a/src/commands.rs +++ b/src/commands.rs @@ -13,7 +13,7 @@ use std::path::PathBuf; use std::{error::Error, str::FromStr}; use tosubcommand::{ToFlags, ToSubcommand}; -use crate::{pfsys::ProofType, RunArgs}; +use crate::{pfsys::ProofType, Commitments, RunArgs}; use crate::circuit::CheckMode; #[cfg(not(target_arch = "wasm32"))] @@ -90,6 +90,8 @@ pub const DEFAULT_SCALE_REBASE_MULTIPLIERS: &str = "1,2,10"; pub const DEFAULT_USE_REDUCED_SRS_FOR_VERIFICATION: &str = "false"; /// Default only check for range check rebase pub const DEFAULT_ONLY_RANGE_CHECK_REBASE: &str = "false"; +/// Default commitment +pub const DEFAULT_COMMITMENT: &str = "kzg"; #[cfg(feature = "python-bindings")] /// Converts TranscriptType into a PyObject (Required for TranscriptType to be compatible with Python) @@ -372,6 +374,9 @@ pub enum Commands { /// number of logrows to use for srs #[arg(long)] logrows: usize, + /// commitment used + #[arg(long, default_value = DEFAULT_COMMITMENT)] + commitment: Commitments, }, #[cfg(not(target_arch = "wasm32"))] @@ -387,6 +392,9 @@ pub enum Commands { /// Number of logrows to use for srs. Overrides settings_path if specified. #[arg(long, default_value = None)] logrows: Option, + /// Commitment used + #[arg(long, default_value = None)] + commitment: Option, }, /// Loads model and input and runs mock prover (for testing) Mock { @@ -434,6 +442,9 @@ pub enum Commands { /// compress selectors #[arg(long, default_value = DEFAULT_DISABLE_SELECTOR_COMPRESSION)] disable_selector_compression: bool, + /// commitment used + #[arg(long, default_value = DEFAULT_COMMITMENT)] + commitment: Commitments, }, /// Aggregates proofs :) Aggregate { @@ -466,6 +477,9 @@ pub enum Commands { /// whether the accumulated proofs are segments of a larger circuit #[arg(long, default_value = DEFAULT_SPLIT)] split_proofs: bool, + /// commitment used + #[arg(long, default_value = DEFAULT_COMMITMENT)] + commitment: Commitments, }, /// Compiles a circuit from onnx to a simplified graph (einsum + other ops) and parameters as sets of field elements CompileCircuit { @@ -500,31 +514,6 @@ pub enum Commands { #[arg(long, default_value = DEFAULT_DISABLE_SELECTOR_COMPRESSION)] disable_selector_compression: bool, }, - - #[cfg(not(target_arch = "wasm32"))] - /// Fuzzes the proof pipeline with random inputs, random parameters, and random keys - Fuzz { - /// The path to the .json witness file (generated using the gen-witness command) - #[arg(short = 'W', long, default_value = DEFAULT_WITNESS)] - witness: PathBuf, - /// The path to the compiled model file (generated using the compile-circuit command) - #[arg(short = 'M', long)] - compiled_circuit: PathBuf, - #[arg( - long, - require_equals = true, - num_args = 0..=1, - default_value_t = TranscriptType::default(), - value_enum - )] - transcript: TranscriptType, - /// number of fuzz iterations - #[arg(long, default_value = DEFAULT_FUZZ_RUNS)] - num_runs: usize, - /// compress selectors - #[arg(long, default_value = DEFAULT_DISABLE_SELECTOR_COMPRESSION)] - disable_selector_compression: bool, - }, #[cfg(not(target_arch = "wasm32"))] /// Deploys a test contact that the data attester reads from and creates a data attestation formatted input.json file that contains call data information #[command(arg_required_else_help = true)] @@ -726,12 +715,18 @@ pub enum Commands { /// The path to the verification key file (generated using the setup-aggregate command) #[arg(long, default_value = DEFAULT_VK_AGGREGATED)] vk_path: PathBuf, + /// reduced srs + #[arg(long, default_value = DEFAULT_USE_REDUCED_SRS_FOR_VERIFICATION)] + reduced_srs: bool, /// The path to SRS, if None will use $EZKL_REPO_PATH/srs/kzg{logrows}.srs #[arg(long)] srs_path: Option, /// logrows used for aggregation circuit #[arg(long, default_value = DEFAULT_AGGREGATED_LOGROWS)] logrows: u32, + /// commitment + #[arg(long, default_value = DEFAULT_COMMITMENT)] + commitment: Commitments, }, #[cfg(not(target_arch = "wasm32"))] /// Deploys an evm verifier that is generated by ezkl diff --git a/src/execute.rs b/src/execute.rs index c67b6d75b..318ee1d53 100644 --- a/src/execute.rs +++ b/src/execute.rs @@ -13,31 +13,40 @@ use crate::graph::input::GraphData; use crate::graph::{GraphCircuit, GraphSettings, GraphWitness, Model}; #[cfg(not(target_arch = "wasm32"))] use crate::graph::{TestDataSource, TestSources}; -use crate::pfsys::evm::aggregation::AggregationCircuit; +use crate::pfsys::evm::aggregation_kzg::{AggregationCircuit, PoseidonTranscript}; #[cfg(not(target_arch = "wasm32"))] use crate::pfsys::{ - create_keys, load_pk, load_vk, save_params, save_pk, swap_proof_commitments_kzg, Snark, - StrategyType, TranscriptType, + create_keys, load_pk, load_vk, save_params, save_pk, Snark, StrategyType, TranscriptType, +}; +use crate::pfsys::{ + create_proof_circuit, swap_proof_commitments_polycommit, verify_proof_circuit, ProofSplitCommit, }; -use crate::pfsys::{create_proof_circuit_kzg, verify_proof_circuit_kzg}; use crate::pfsys::{save_vk, srs::*}; use crate::tensor::TensorError; -use crate::RunArgs; +use crate::{Commitments, RunArgs}; #[cfg(unix)] use gag::Gag; use halo2_proofs::dev::VerifyFailure; -use halo2_proofs::poly::commitment::Params; -use halo2_proofs::poly::commitment::ParamsProver; +use halo2_proofs::plonk::{self, Circuit}; +use halo2_proofs::poly::commitment::{CommitmentScheme, Params}; +use halo2_proofs::poly::commitment::{ParamsProver, Verifier}; +use halo2_proofs::poly::ipa::commitment::{IPACommitmentScheme, ParamsIPA}; +use halo2_proofs::poly::ipa::multiopen::{ProverIPA, VerifierIPA}; +use halo2_proofs::poly::ipa::strategy::AccumulatorStrategy as IPAAccumulatorStrategy; +use halo2_proofs::poly::ipa::strategy::SingleStrategy as IPASingleStrategy; use halo2_proofs::poly::kzg::commitment::KZGCommitmentScheme; -use halo2_proofs::poly::kzg::strategy::AccumulatorStrategy; +use halo2_proofs::poly::kzg::multiopen::{ProverSHPLONK, VerifierSHPLONK}; +use halo2_proofs::poly::kzg::strategy::AccumulatorStrategy as KZGAccumulatorStrategy; use halo2_proofs::poly::kzg::{ commitment::ParamsKZG, strategy::SingleStrategy as KZGSingleStrategy, }; +use halo2_proofs::poly::VerificationStrategy; +use halo2_proofs::transcript::{EncodedChallenge, TranscriptReadBuffer}; #[cfg(not(target_arch = "wasm32"))] use halo2_solidity_verifier; use halo2curves::bn256::{Bn256, Fr, G1Affine}; -#[cfg(not(target_arch = "wasm32"))] -use halo2curves::ff::Field; +use halo2curves::ff::{FromUniformBytes, WithSmallOrderMulGroup}; +use halo2curves::serde::SerdeObject; #[cfg(not(target_arch = "wasm32"))] use indicatif::{ProgressBar, ProgressStyle}; use instant::Instant; @@ -46,10 +55,12 @@ use itertools::Itertools; #[cfg(not(target_arch = "wasm32"))] use log::debug; use log::{info, trace, warn}; -#[cfg(not(target_arch = "wasm32"))] -use maybe_rayon::prelude::{IntoParallelIterator, ParallelIterator}; -#[cfg(not(target_arch = "wasm32"))] -use rand::Rng; +use serde::de::DeserializeOwned; +use serde::Serialize; +use snark_verifier::loader::native::NativeLoader; +use snark_verifier::system::halo2::compile; +use snark_verifier::system::halo2::transcript::evm::EvmTranscript; +use snark_verifier::system::halo2::Config; use std::error::Error; use std::fs::File; #[cfg(not(target_arch = "wasm32"))] @@ -59,8 +70,6 @@ use std::path::PathBuf; #[cfg(not(target_arch = "wasm32"))] use std::process::Command; #[cfg(not(target_arch = "wasm32"))] -use std::sync::atomic::{AtomicBool, AtomicI64, Ordering}; -#[cfg(not(target_arch = "wasm32"))] use std::sync::OnceLock; #[cfg(not(target_arch = "wasm32"))] @@ -137,27 +146,18 @@ pub async fn run(command: Commands) -> Result> { match command { #[cfg(feature = "empty-cmd")] Commands::Empty => Ok(String::new()), - #[cfg(not(target_arch = "wasm32"))] - Commands::Fuzz { - witness, - compiled_circuit, - transcript, - num_runs, - disable_selector_compression, - } => fuzz( - compiled_circuit, - witness, - transcript, - num_runs, - disable_selector_compression, - ), - Commands::GenSrs { srs_path, logrows } => gen_srs_cmd(srs_path, logrows as u32), + Commands::GenSrs { + srs_path, + logrows, + commitment, + } => gen_srs_cmd(srs_path, logrows as u32, commitment), #[cfg(not(target_arch = "wasm32"))] Commands::GetSrs { srs_path, settings_path, logrows, - } => get_srs_cmd(srs_path, settings_path, logrows).await, + commitment, + } => get_srs_cmd(srs_path, settings_path, logrows, commitment).await, Commands::Table { model, args } => table(model, args), Commands::GenSettings { model, @@ -294,7 +294,7 @@ pub async fn run(command: Commands) -> Result> { Commands::SwapProofCommitments { proof_path, witness_path, - } => swap_proof_commitments(proof_path, witness_path) + } => swap_proof_commitments_cmd(proof_path, witness_path) .map(|e| serde_json::to_string(&e).unwrap()), #[cfg(not(target_arch = "wasm32"))] Commands::Prove { @@ -328,6 +328,7 @@ pub async fn run(command: Commands) -> Result> { logrows, split_proofs, disable_selector_compression, + commitment, } => setup_aggregate( sample_snarks, vk_path, @@ -336,6 +337,7 @@ pub async fn run(command: Commands) -> Result> { logrows, split_proofs, disable_selector_compression, + commitment, ), Commands::Aggregate { proof_path, @@ -346,6 +348,7 @@ pub async fn run(command: Commands) -> Result> { logrows, check_mode, split_proofs, + commitment, } => aggregate( proof_path, aggregation_snarks, @@ -355,6 +358,7 @@ pub async fn run(command: Commands) -> Result> { logrows, check_mode, split_proofs, + commitment, ) .map(|e| serde_json::to_string(&e).unwrap()), Commands::Verify { @@ -369,9 +373,18 @@ pub async fn run(command: Commands) -> Result> { proof_path, vk_path, srs_path, + reduced_srs, logrows, - } => verify_aggr(proof_path, vk_path, srs_path, logrows) - .map(|e| serde_json::to_string(&e).unwrap()), + commitment, + } => verify_aggr( + proof_path, + vk_path, + srs_path, + logrows, + reduced_srs, + commitment, + ) + .map(|e| serde_json::to_string(&e).unwrap()), #[cfg(not(target_arch = "wasm32"))] Commands::DeployEvmVerifier { sol_code_path, @@ -441,24 +454,39 @@ pub async fn run(command: Commands) -> Result> { } /// Get the srs path -pub fn get_srs_path(logrows: u32, srs_path: Option) -> PathBuf { +pub fn get_srs_path(logrows: u32, srs_path: Option, commitment: Commitments) -> PathBuf { if let Some(srs_path) = srs_path { srs_path } else { if !Path::new(&*EZKL_SRS_REPO_PATH).exists() { std::fs::create_dir_all(&*EZKL_SRS_REPO_PATH).unwrap(); } - (EZKL_SRS_REPO_PATH.clone() + &format!("/kzg{}.srs", logrows)).into() + match commitment { + Commitments::KZG => Path::new(&*EZKL_SRS_REPO_PATH).join(format!("kzg{}.srs", logrows)), + Commitments::IPA => Path::new(&*EZKL_SRS_REPO_PATH).join(format!("ipa{}.srs", logrows)), + } } } -fn srs_exists_check(logrows: u32, srs_path: Option) -> bool { - Path::new(&get_srs_path(logrows, srs_path)).exists() +fn srs_exists_check(logrows: u32, srs_path: Option, commitment: Commitments) -> bool { + Path::new(&get_srs_path(logrows, srs_path, commitment)).exists() } -pub(crate) fn gen_srs_cmd(srs_path: PathBuf, logrows: u32) -> Result> { - let params = gen_srs::>(logrows); - save_params::>(&srs_path, ¶ms)?; +pub(crate) fn gen_srs_cmd( + srs_path: PathBuf, + logrows: u32, + commitment: Commitments, +) -> Result> { + match commitment { + Commitments::KZG => { + let params = gen_srs::>(logrows); + save_params::>(&srs_path, ¶ms)?; + } + Commitments::IPA => { + let params = gen_srs::>(logrows); + save_params::>(&srs_path, ¶ms)?; + } + } Ok(String::new()) } @@ -502,8 +530,12 @@ pub(crate) fn get_file_hash(path: &PathBuf) -> Result> { } #[cfg(not(target_arch = "wasm32"))] -fn check_srs_hash(logrows: u32, srs_path: Option) -> Result> { - let path = get_srs_path(logrows, srs_path); +fn check_srs_hash( + logrows: u32, + srs_path: Option, + commitment: Commitments, +) -> Result> { + let path = get_srs_path(logrows, srs_path, commitment); let hash = get_file_hash(&path)?; let predefined_hash = match { crate::srs_sha::PUBLIC_SRS_SHA256_HASHES.get(&logrows) } { @@ -528,54 +560,71 @@ pub(crate) async fn get_srs_cmd( srs_path: Option, settings_path: Option, logrows: Option, + commitment: Option, ) -> Result> { // logrows overrides settings + let err_string = "You will need to provide a valid settings file to use the settings option. You should run gen-settings to generate a settings file (and calibrate-settings to pick optimal logrows)."; + let k = if let Some(k) = logrows { k - } else if let Some(settings_p) = settings_path { + } else if let Some(settings_p) = &settings_path { if settings_p.exists() { - let settings = GraphSettings::load(&settings_p)?; + let settings = GraphSettings::load(settings_p)?; settings.run_args.logrows } else { - let err_string = format!( - "You will need to provide a valid settings file to use the settings option. You should run gen-settings to generate a settings file (and calibrate-settings to pick optimal logrows)." - ); return Err(err_string.into()); } } else { - let err_string = format!( - "You will need to provide a settings file or set the logrows. You should run gen-settings to generate a settings file (and calibrate-settings to pick optimal logrows)." - ); return Err(err_string.into()); }; - if !srs_exists_check(k, srs_path.clone()) { - info!("SRS does not exist, downloading..."); - let srs_uri = format!("{}{}", PUBLIC_SRS_URL, k); - let mut reader = Cursor::new(fetch_srs(&srs_uri).await?); - // check the SRS - #[cfg(not(target_arch = "wasm32"))] - let pb = init_spinner(); - #[cfg(not(target_arch = "wasm32"))] - pb.set_message("Validating SRS (this may take a while) ..."); - let params = ParamsKZG::::read(&mut reader)?; - #[cfg(not(target_arch = "wasm32"))] - pb.finish_with_message("SRS validated."); - - info!("Saving SRS to disk..."); - let mut file = std::fs::File::create(get_srs_path(k, srs_path.clone()))?; - let mut buffer = BufWriter::with_capacity(*EZKL_BUF_CAPACITY, &mut file); - params.write(&mut buffer)?; - - info!("Saved SRS to disk."); + let commitment = if let Some(c) = commitment { + c + } else if let Some(settings_p) = settings_path { + if settings_p.exists() { + let settings = GraphSettings::load(&settings_p)?; + settings.run_args.commitment + } else { + return Err(err_string.into()); + } + } else { + return Err(err_string.into()); + }; - info!("SRS downloaded"); + if !srs_exists_check(k, srs_path.clone(), commitment) { + if matches!(commitment, Commitments::KZG) { + info!("SRS does not exist, downloading..."); + let srs_uri = format!("{}{}", PUBLIC_SRS_URL, k); + let mut reader = Cursor::new(fetch_srs(&srs_uri).await?); + // check the SRS + #[cfg(not(target_arch = "wasm32"))] + let pb = init_spinner(); + #[cfg(not(target_arch = "wasm32"))] + pb.set_message("Validating SRS (this may take a while) ..."); + let params = ParamsKZG::::read(&mut reader)?; + #[cfg(not(target_arch = "wasm32"))] + pb.finish_with_message("SRS validated."); + + info!("Saving SRS to disk..."); + let mut file = std::fs::File::create(get_srs_path(k, srs_path.clone(), commitment))?; + let mut buffer = BufWriter::with_capacity(*EZKL_BUF_CAPACITY, &mut file); + params.write(&mut buffer)?; + + info!("Saved SRS to disk."); + + info!("SRS downloaded"); + } else { + let path = get_srs_path(k, srs_path.clone(), commitment); + gen_srs_cmd(path, k, commitment)?; + } } else { info!("SRS already exists at that path"); }; // check the hash - check_srs_hash(k, srs_path.clone())?; + if matches!(commitment, Commitments::KZG) { + check_srs_hash(k, srs_path.clone(), commitment)?; + } Ok(String::new()) } @@ -600,7 +649,7 @@ pub(crate) async fn gen_witness( let settings = circuit.settings().clone(); let vk = if let Some(vk) = vk_path { - Some(load_vk::, Fr, GraphCircuit>( + Some(load_vk::, GraphCircuit>( vk, settings.clone(), )?) @@ -608,27 +657,58 @@ pub(crate) async fn gen_witness( None }; - // if any of the settings have kzg visibility then we need to load the srs - - let srs = if settings.module_requires_kzg() { - if get_srs_path(settings.run_args.logrows, srs_path.clone()).exists() { - Some(load_params_cmd(srs_path, settings.run_args.logrows)?) - } else { - warn!("SRS for kzg commit does not exist (will be ignored)"); - None - } - } else { - None - }; - #[cfg(not(target_arch = "wasm32"))] let mut input = circuit.load_graph_input(&data).await?; #[cfg(target_arch = "wasm32")] let mut input = circuit.load_graph_input(&data)?; - let start_time = Instant::now(); + // if any of the settings have kzg visibility then we need to load the srs - let witness = circuit.forward(&mut input, vk.as_ref(), srs.as_ref(), false)?; + let start_time = Instant::now(); + let witness = if settings.module_requires_polycommit() { + if get_srs_path( + settings.run_args.logrows, + srs_path.clone(), + settings.run_args.commitment, + ) + .exists() + { + match settings.run_args.commitment { + Commitments::KZG => { + let srs: ParamsKZG = load_params_prover::>( + srs_path.clone(), + settings.run_args.logrows, + settings.run_args.commitment, + )?; + circuit.forward::>( + &mut input, + vk.as_ref(), + Some(&srs), + false, + )? + } + Commitments::IPA => { + let srs: ParamsIPA = + load_params_prover::>( + srs_path.clone(), + settings.run_args.logrows, + settings.run_args.commitment, + )?; + circuit.forward::>( + &mut input, + vk.as_ref(), + Some(&srs), + false, + )? + } + } + } else { + warn!("SRS for poly commit does not exist (will be ignored)"); + circuit.forward::>(&mut input, vk.as_ref(), None, false)? + } + } else { + circuit.forward::>(&mut input, vk.as_ref(), None, false)? + }; // print each variable tuple (symbol, value) as symbol=value trace!( @@ -942,7 +1022,7 @@ pub(crate) fn calibrate( .map_err(|e| format!("failed to load circuit inputs: {}", e))?; let forward_res = circuit - .forward(&mut data.clone(), None, None, true) + .forward::>(&mut data.clone(), None, None, true) .map_err(|e| format!("failed to forward: {}", e))?; // push result to the hashmap @@ -1199,12 +1279,16 @@ pub(crate) fn create_evm_verifier( ) -> Result> { check_solc_requirement(); let circuit_settings = GraphSettings::load(&settings_path)?; - let params = load_params_cmd(srs_path, circuit_settings.run_args.logrows)?; + let params = load_params_verifier::>( + srs_path, + circuit_settings.run_args.logrows, + circuit_settings.run_args.commitment, + )?; let num_instance = circuit_settings.total_instances(); let num_instance: usize = num_instance.iter().sum::(); - let vk = load_vk::, Fr, GraphCircuit>(vk_path, circuit_settings)?; + let vk = load_vk::, GraphCircuit>(vk_path, circuit_settings)?; trace!("params computed"); let generator = halo2_solidity_verifier::SolidityGenerator::new( @@ -1239,12 +1323,16 @@ pub(crate) fn create_evm_vk( ) -> Result> { check_solc_requirement(); let circuit_settings = GraphSettings::load(&settings_path)?; - let params = load_params_cmd(srs_path, circuit_settings.run_args.logrows)?; + let params = load_params_verifier::>( + srs_path, + circuit_settings.run_args.logrows, + circuit_settings.run_args.commitment, + )?; let num_instance = circuit_settings.total_instances(); let num_instance: usize = num_instance.iter().sum::(); - let vk = load_vk::, Fr, GraphCircuit>(vk_path, circuit_settings)?; + let vk = load_vk::, GraphCircuit>(vk_path, circuit_settings)?; trace!("params computed"); let generator = halo2_solidity_verifier::SolidityGenerator::new( @@ -1432,8 +1520,8 @@ pub(crate) fn create_evm_aggregate_verifier( render_vk_seperately: bool, ) -> Result> { check_solc_requirement(); - let srs_path = get_srs_path(logrows, srs_path); - let params: ParamsKZG = load_srs::>(srs_path)?; + let srs_path = get_srs_path(logrows, srs_path, Commitments::KZG); + let params: ParamsKZG = load_srs_verifier::>(srs_path)?; let mut settings: Vec = vec![]; @@ -1451,7 +1539,7 @@ pub(crate) fn create_evm_aggregate_verifier( assert_eq!(num_instance.len(), 1); let num_instance = num_instance[0]; - let agg_vk = load_vk::, Fr, AggregationCircuit>(vk_path, ())?; + let agg_vk = load_vk::, AggregationCircuit>(vk_path, ())?; let mut generator = halo2_solidity_verifier::SolidityGenerator::new( ¶ms, @@ -1504,23 +1592,44 @@ pub(crate) fn setup( disable_selector_compression: bool, ) -> Result> { // these aren't real values so the sanity checks are mostly meaningless + let mut circuit = GraphCircuit::load(compiled_circuit)?; + if let Some(witness) = witness { let data = GraphWitness::from_path(witness)?; circuit.load_graph_witness(&data)?; } - let params = load_params_cmd(srs_path, circuit.settings().run_args.logrows)?; - - let pk = create_keys::, Fr, GraphCircuit>( - &circuit, - ¶ms, - disable_selector_compression, - ) - .map_err(Box::::from)?; + let logrows = circuit.settings().run_args.logrows; - save_vk::>(&vk_path, pk.get_vk())?; - save_pk::>(&pk_path, &pk)?; + let pk = match circuit.settings().run_args.commitment { + Commitments::KZG => { + let params = load_params_prover::>( + srs_path, + logrows, + Commitments::KZG, + )?; + create_keys::, GraphCircuit>( + &circuit, + ¶ms, + disable_selector_compression, + )? + } + Commitments::IPA => { + let params = load_params_prover::>( + srs_path, + logrows, + Commitments::IPA, + )?; + create_keys::, GraphCircuit>( + &circuit, + ¶ms, + disable_selector_compression, + )? + } + }; + save_vk::(&vk_path, pk.get_vk())?; + save_pk::(&pk_path, &pk)?; Ok(String::new()) } @@ -1588,8 +1697,6 @@ pub(crate) fn prove( proof_type: ProofType, check_mode: CheckMode, ) -> Result, Box> { - use crate::pfsys::ProofSplitCommit; - let data = GraphWitness::from_path(data_path)?; let mut circuit = GraphCircuit::load(compiled_circuit_path)?; @@ -1600,46 +1707,133 @@ pub(crate) fn prove( let circuit_settings = circuit.settings().clone(); - let params = load_params_cmd(srs_path, circuit_settings.run_args.logrows)?; - - let pk = load_pk::, Fr, GraphCircuit>(pk_path, circuit_settings) - .map_err(Box::::from)?; - - trace!("params computed"); - let strategy: StrategyType = proof_type.into(); let transcript: TranscriptType = proof_type.into(); let proof_split_commits: Option = data.into(); + let commitment = circuit_settings.run_args.commitment; // creates and verifies the proof - let mut snark = match strategy { - StrategyType::Single => { - let strategy = KZGSingleStrategy::new(¶ms); - create_proof_circuit_kzg( - circuit, - ¶ms, - Some(public_inputs), - &pk, - transcript, - strategy, - check_mode, - proof_split_commits, - )? + let mut snark = match commitment { + Commitments::KZG => { + let pk = + load_pk::, GraphCircuit>(pk_path, circuit.params())?; + + let params = load_params_prover::>( + srs_path, + circuit_settings.run_args.logrows, + Commitments::KZG, + )?; + match strategy { + StrategyType::Single => create_proof_circuit::< + KZGCommitmentScheme, + _, + ProverSHPLONK<_>, + VerifierSHPLONK<_>, + KZGSingleStrategy<_>, + _, + EvmTranscript<_, _, _, _>, + EvmTranscript<_, _, _, _>, + >( + circuit, + vec![public_inputs], + ¶ms, + &pk, + check_mode, + commitment, + transcript, + proof_split_commits, + None, + ), + StrategyType::Accum => { + let protocol = Some(compile( + ¶ms, + pk.get_vk(), + Config::kzg().with_num_instance(vec![public_inputs.len()]), + )); + + create_proof_circuit::< + KZGCommitmentScheme, + _, + ProverSHPLONK<_>, + VerifierSHPLONK<_>, + KZGAccumulatorStrategy<_>, + _, + PoseidonTranscript, + PoseidonTranscript, + >( + circuit, + vec![public_inputs], + ¶ms, + &pk, + check_mode, + commitment, + transcript, + proof_split_commits, + protocol, + ) + } + } } - StrategyType::Accum => { - let strategy = AccumulatorStrategy::new(¶ms); - create_proof_circuit_kzg( - circuit, - ¶ms, - Some(public_inputs), - &pk, - transcript, - strategy, - check_mode, - proof_split_commits, - )? + Commitments::IPA => { + let pk = + load_pk::, GraphCircuit>(pk_path, circuit.params())?; + + let params = load_params_prover::>( + srs_path, + circuit_settings.run_args.logrows, + Commitments::IPA, + )?; + match strategy { + StrategyType::Single => create_proof_circuit::< + IPACommitmentScheme, + _, + ProverIPA<_>, + VerifierIPA<_>, + IPASingleStrategy<_>, + _, + EvmTranscript<_, _, _, _>, + EvmTranscript<_, _, _, _>, + >( + circuit, + vec![public_inputs], + ¶ms, + &pk, + check_mode, + commitment, + transcript, + proof_split_commits, + None, + ), + StrategyType::Accum => { + let protocol = Some(compile( + ¶ms, + pk.get_vk(), + Config::ipa().with_num_instance(vec![public_inputs.len()]), + )); + create_proof_circuit::< + IPACommitmentScheme, + _, + ProverIPA<_>, + VerifierIPA<_>, + IPAAccumulatorStrategy<_>, + _, + PoseidonTranscript, + PoseidonTranscript, + >( + circuit, + vec![public_inputs], + ¶ms, + &pk, + check_mode, + commitment, + transcript, + proof_split_commits, + protocol, + ) + } + } } - }; + }?; snark.pretty_public_inputs = pretty_public_inputs; @@ -1650,267 +1844,19 @@ pub(crate) fn prove( Ok(snark) } -#[cfg(not(target_arch = "wasm32"))] -pub(crate) fn fuzz( - compiled_circuit_path: PathBuf, - data_path: PathBuf, - transcript: TranscriptType, - num_runs: usize, - disable_selector_compression: bool, -) -> Result> { - check_solc_requirement(); - let passed = AtomicBool::new(true); - - // these aren't real values so the sanity checks are mostly meaningless - let mut circuit = GraphCircuit::load(compiled_circuit_path)?; - let logrows = circuit.settings().run_args.logrows; - - info!("setting up tests"); - #[cfg(unix)] - let _r = Gag::stdout()?; - let params = gen_srs::>(logrows); - - let data = GraphWitness::from_path(data_path)?; - - let pk = create_keys::, Fr, GraphCircuit>( - &circuit, - ¶ms, - disable_selector_compression, - ) - .map_err(Box::::from)?; - - circuit.load_graph_witness(&data)?; - - let public_inputs = circuit.prepare_public_inputs(&data)?; - - let strategy = KZGSingleStrategy::new(¶ms); - #[cfg(unix)] - std::mem::drop(_r); - - info!("starting fuzzing"); - - info!("fuzzing pk"); - - let fuzz_pk = || { - let new_params = gen_srs::>(logrows); - - let bad_pk = create_keys::, Fr, GraphCircuit>( - &circuit, - &new_params, - disable_selector_compression, - ) - .map_err(|_| ())?; - - let bad_proof = create_proof_circuit_kzg( - circuit.clone(), - ¶ms, - Some(public_inputs.clone()), - &bad_pk, - transcript, - strategy.clone(), - CheckMode::UNSAFE, - None, - ) - .map_err(|_| ())?; - - verify_proof_circuit_kzg( - params.verifier_params(), - bad_proof, - pk.get_vk(), - strategy.clone(), - params.n(), - ) - .map_err(|_| ()) - }; - - run_fuzz_fn(num_runs, fuzz_pk, &passed); - - info!("fuzzing public inputs"); - - let fuzz_public_inputs = || { - let bad_inputs: Vec = (0..public_inputs.len()) - .map(|_| Fr::random(rand::rngs::OsRng)) - .collect(); - - let bad_proof = create_proof_circuit_kzg( - circuit.clone(), - ¶ms, - Some(bad_inputs.clone()), - &pk, - transcript, - strategy.clone(), - CheckMode::UNSAFE, - None, - ) - .map_err(|_| ())?; - - verify_proof_circuit_kzg( - params.verifier_params(), - bad_proof, - pk.get_vk(), - strategy.clone(), - params.n(), - ) - .map_err(|_| ()) - }; - - run_fuzz_fn(num_runs, fuzz_public_inputs, &passed); - - info!("fuzzing vk"); - - let proof = create_proof_circuit_kzg( - circuit.clone(), - ¶ms, - Some(public_inputs.clone()), - &pk, - transcript, - strategy.clone(), - CheckMode::SAFE, - None, - )?; - - let fuzz_vk = || { - let new_params = gen_srs::>(logrows); - - let bad_pk = create_keys::, Fr, GraphCircuit>( - &circuit, - &new_params, - disable_selector_compression, - ) - .map_err(|_| ())?; - - let bad_vk = bad_pk.get_vk(); - - verify_proof_circuit_kzg( - params.verifier_params(), - proof.clone(), - bad_vk, - strategy.clone(), - params.n(), - ) - .map_err(|_| ()) - }; - - run_fuzz_fn(num_runs, fuzz_vk, &passed); - - info!("fuzzing proof bytes"); - - let fuzz_proof_bytes = || { - let mut rng = rand::thread_rng(); - - let bad_proof_bytes: Vec = (0..proof.proof.len()) - .map(|_| rng.gen_range(0..20)) - .collect(); - - let bad_proof = Snark::<_, _> { - instances: proof.instances.clone(), - proof: bad_proof_bytes, - protocol: proof.protocol.clone(), - transcript_type: transcript, - split: None, - pretty_public_inputs: None, - hex_proof: None, - timestamp: None, - }; - - verify_proof_circuit_kzg( - params.verifier_params(), - bad_proof, - pk.get_vk(), - strategy.clone(), - params.n(), - ) - .map_err(|_| ()) - }; - - run_fuzz_fn(num_runs, fuzz_proof_bytes, &passed); - - info!("fuzzing proof instances"); - - let fuzz_proof_instances = || { - let mut bad_inputs = vec![vec![]]; - - for l in &proof.instances { - bad_inputs.push( - (0..l.len()) - .map(|_| Fr::random(rand::rngs::OsRng)) - .collect(), - ); - } - - let bad_proof = Snark::<_, _> { - instances: bad_inputs.clone(), - proof: proof.proof.clone(), - protocol: proof.protocol.clone(), - transcript_type: transcript, - split: None, - hex_proof: None, - pretty_public_inputs: None, - timestamp: None, - }; - - verify_proof_circuit_kzg( - params.verifier_params(), - bad_proof, - pk.get_vk(), - strategy.clone(), - params.n(), - ) - .map_err(|_| ()) - }; - - run_fuzz_fn(num_runs, fuzz_proof_instances, &passed); - - if !passed.into_inner() { - Err("fuzzing failed".into()) - } else { - Ok(String::new()) - } -} - -#[cfg(not(target_arch = "wasm32"))] -pub(crate) fn run_fuzz_fn( - num_runs: usize, - f: impl Fn() -> Result<(), ()> + std::marker::Sync + std::marker::Send, - passed: &AtomicBool, -) { - let num_failures = AtomicI64::new(0); - #[cfg(unix)] - let _r = Gag::stdout().unwrap(); - - let pb = init_bar(num_runs as u64); - pb.set_message("fuzzing..."); - (0..num_runs).into_par_iter().for_each(|_| { - let result = f(); - if result.is_ok() { - passed.swap(false, Ordering::Relaxed); - num_failures.fetch_add(1, Ordering::Relaxed); - } - pb.inc(1); - }); - pb.finish_with_message("Done."); - #[cfg(unix)] - std::mem::drop(_r); - info!( - "num failures: {} out of {}", - num_failures.load(Ordering::Relaxed), - num_runs - ); -} - -pub(crate) fn swap_proof_commitments( +pub(crate) fn swap_proof_commitments_cmd( proof_path: PathBuf, witness: PathBuf, ) -> Result, Box> { let snark = Snark::load::>(&proof_path)?; let witness = GraphWitness::from_path(witness)?; - let commitments = witness.get_kzg_commitments(); + let commitments = witness.get_polycommitments(); if commitments.is_empty() { log::warn!("no commitments found in witness"); } - let snark_new = swap_proof_commitments_kzg(&snark, &commitments)?; + let snark_new = swap_proof_commitments_polycommit(&snark, &commitments)?; if snark_new.proof != *snark.proof { log::warn!("swap proof has created a different proof"); @@ -1927,7 +1873,16 @@ pub(crate) fn mock_aggregate( ) -> Result> { let mut snarks = vec![]; for proof_path in aggregation_snarks.iter() { - snarks.push(Snark::load::>(proof_path)?); + match Snark::load::>(proof_path) { + Ok(snark) => { + snarks.push(snark); + } + Err(_) => { + return Err( + format!("invalid sample commitment type for aggregation, must be KZG").into(), + ); + } + } } // proof aggregation #[cfg(not(target_arch = "wasm32"))] @@ -1957,27 +1912,54 @@ pub(crate) fn setup_aggregate( logrows: u32, split_proofs: bool, disable_selector_compression: bool, + commitment: Commitments, ) -> Result> { - // the K used for the aggregation circuit - let params = load_params_cmd(srs_path, logrows)?; - let mut snarks = vec![]; for proof_path in sample_snarks.iter() { - snarks.push(Snark::load::>(proof_path)?); + match Snark::load::>(proof_path) { + Ok(snark) => { + snarks.push(snark); + } + Err(_) => { + return Err( + format!("invalid sample commitment type for aggregation, must be KZG",).into(), + ); + } + } } - let agg_circuit = AggregationCircuit::new(¶ms.get_g()[0].into(), snarks, split_proofs)?; - let agg_pk = create_keys::, Fr, AggregationCircuit>( - &agg_circuit, - ¶ms, - disable_selector_compression, - )?; + let circuit = AggregationCircuit::new(&G1Affine::generator().into(), snarks, split_proofs)?; - let agg_vk = agg_pk.get_vk(); + let pk = match commitment { + Commitments::KZG => { + let params = load_params_prover::>( + srs_path, + logrows, + Commitments::KZG, + )?; + + create_keys::, AggregationCircuit>( + &circuit, + ¶ms, + disable_selector_compression, + )? + } + Commitments::IPA => { + let params = load_params_prover::>( + srs_path, + logrows, + Commitments::IPA, + )?; + create_keys::, AggregationCircuit>( + &circuit, + ¶ms, + disable_selector_compression, + )? + } + }; + save_vk::(&vk_path, pk.get_vk())?; + save_pk::(&pk_path, &pk)?; - // now save - save_vk::>(&vk_path, agg_vk)?; - save_pk::>(&pk_path, &agg_pk)?; Ok(String::new()) } @@ -1991,16 +1973,22 @@ pub(crate) fn aggregate( logrows: u32, check_mode: CheckMode, split_proofs: bool, + commitment: Commitments, ) -> Result, Box> { - // the K used for the aggregation circuit - let params = load_params_cmd(srs_path, logrows)?; - let mut snarks = vec![]; for proof_path in aggregation_snarks.iter() { - snarks.push(Snark::load::>(proof_path)?); + match Snark::load::>(proof_path) { + Ok(snark) => { + snarks.push(snark); + } + Err(_) => { + return Err( + format!("invalid sample commitment type for aggregation, must be KZG").into(), + ); + } + } } - let agg_pk = load_pk::, Fr, AggregationCircuit>(pk_path, ())?; // proof aggregation #[cfg(not(target_arch = "wasm32"))] let pb = { @@ -2009,19 +1997,140 @@ pub(crate) fn aggregate( pb }; - let agg_circuit = AggregationCircuit::new(¶ms.get_g()[0].into(), snarks, split_proofs)?; - let now = Instant::now(); - let snark = create_proof_circuit_kzg( - agg_circuit.clone(), - ¶ms, - Some(agg_circuit.instances()), - &agg_pk, - transcript, - AccumulatorStrategy::new(¶ms), - check_mode, - None, - )?; + + let snark = match commitment { + Commitments::KZG => { + let pk = load_pk::, AggregationCircuit>(pk_path, ())?; + let params: ParamsKZG = load_params_prover::>( + srs_path.clone(), + logrows, + Commitments::KZG, + )?; + let circuit = AggregationCircuit::new( + &ParamsProver::::get_g(¶ms)[0].into(), + snarks, + split_proofs, + )?; + let public_inputs = circuit.instances(); + match transcript { + TranscriptType::EVM => create_proof_circuit::< + KZGCommitmentScheme, + _, + ProverSHPLONK<_>, + VerifierSHPLONK<_>, + KZGSingleStrategy<_>, + _, + EvmTranscript<_, _, _, _>, + EvmTranscript<_, _, _, _>, + >( + circuit, + vec![public_inputs], + ¶ms, + &pk, + check_mode, + commitment, + transcript, + None, + None, + ), + TranscriptType::Poseidon => { + let protocol = Some(compile( + ¶ms, + pk.get_vk(), + Config::kzg().with_num_instance(vec![public_inputs.len()]), + )); + + create_proof_circuit::< + KZGCommitmentScheme, + _, + ProverSHPLONK<_>, + VerifierSHPLONK<_>, + KZGAccumulatorStrategy<_>, + _, + PoseidonTranscript, + PoseidonTranscript, + >( + circuit, + vec![public_inputs], + ¶ms, + &pk, + check_mode, + commitment, + transcript, + None, + protocol, + ) + } + } + } + Commitments::IPA => { + let pk = load_pk::, AggregationCircuit>(pk_path, ())?; + let params: ParamsIPA<_> = load_params_prover::>( + srs_path.clone(), + logrows, + Commitments::IPA, + )?; + let circuit = AggregationCircuit::new( + &ParamsProver::::get_g(¶ms)[0].into(), + snarks, + split_proofs, + )?; + let public_inputs = circuit.instances(); + + match transcript { + TranscriptType::EVM => create_proof_circuit::< + IPACommitmentScheme, + _, + ProverIPA<_>, + VerifierIPA<_>, + IPASingleStrategy<_>, + _, + EvmTranscript<_, _, _, _>, + EvmTranscript<_, _, _, _>, + >( + circuit, + vec![public_inputs], + ¶ms, + &pk, + check_mode, + commitment, + transcript, + None, + None, + ), + TranscriptType::Poseidon => { + let protocol = Some(compile( + ¶ms, + pk.get_vk(), + Config::ipa().with_num_instance(vec![public_inputs.len()]), + )); + + create_proof_circuit::< + IPACommitmentScheme, + _, + ProverIPA<_>, + VerifierIPA<_>, + IPAAccumulatorStrategy<_>, + _, + PoseidonTranscript, + PoseidonTranscript, + >( + circuit, + vec![public_inputs], + ¶ms, + &pk, + check_mode, + commitment, + transcript, + None, + protocol, + ) + } + } + } + }?; + // the K used for the aggregation circuit let elapsed = now.elapsed(); info!( @@ -2046,26 +2155,115 @@ pub(crate) fn verify( ) -> Result> { let circuit_settings = GraphSettings::load(&settings_path)?; - let params = if reduced_srs { - // only need G_0 for the verification with shplonk - load_params_cmd(srs_path, 1)? - } else { - load_params_cmd(srs_path, circuit_settings.run_args.logrows)? - }; - - let proof = Snark::load::>(&proof_path)?; + let logrows = circuit_settings.run_args.logrows; + + match circuit_settings.run_args.commitment { + Commitments::KZG => { + let proof = Snark::load::>(&proof_path)?; + let params: ParamsKZG = if reduced_srs { + // only need G_0 for the verification with shplonk + load_params_verifier::>(srs_path, 1, Commitments::KZG)? + } else { + load_params_verifier::>( + srs_path, + logrows, + Commitments::KZG, + )? + }; + match proof.transcript_type { + TranscriptType::EVM => { + verify_commitment::< + KZGCommitmentScheme, + VerifierSHPLONK<'_, Bn256>, + _, + KZGSingleStrategy<_>, + EvmTranscript, + GraphCircuit, + _, + >(proof_path, circuit_settings, vk_path, ¶ms, logrows) + } + TranscriptType::Poseidon => { + verify_commitment::< + KZGCommitmentScheme, + VerifierSHPLONK<'_, Bn256>, + _, + KZGSingleStrategy<_>, + PoseidonTranscript, + GraphCircuit, + _, + >(proof_path, circuit_settings, vk_path, ¶ms, logrows) + } + } + } + Commitments::IPA => { + let proof = Snark::load::>(&proof_path)?; + let params: ParamsIPA<_> = load_params_verifier::>( + srs_path, + logrows, + Commitments::IPA, + )?; + match proof.transcript_type { + TranscriptType::EVM => { + verify_commitment::< + IPACommitmentScheme, + VerifierIPA<_>, + _, + IPASingleStrategy<_>, + EvmTranscript, + GraphCircuit, + _, + >(proof_path, circuit_settings, vk_path, ¶ms, logrows) + } + TranscriptType::Poseidon => { + verify_commitment::< + IPACommitmentScheme, + VerifierIPA<_>, + _, + IPASingleStrategy<_>, + PoseidonTranscript, + GraphCircuit, + _, + >(proof_path, circuit_settings, vk_path, ¶ms, logrows) + } + } + } + } +} - let strategy = KZGSingleStrategy::new(params.verifier_params()); - let vk = - load_vk::, Fr, GraphCircuit>(vk_path, circuit_settings.clone())?; +fn verify_commitment< + 'a, + Scheme: CommitmentScheme, + V: Verifier<'a, Scheme>, + E: EncodedChallenge, + Strategy: VerificationStrategy<'a, Scheme, V>, + TR: TranscriptReadBuffer>, Scheme::Curve, E>, + C: Circuit<::Scalar, Params = Params>, + Params, +>( + proof_path: PathBuf, + settings: Params, + vk_path: PathBuf, + params: &'a Scheme::ParamsVerifier, + logrows: u32, +) -> Result> +where + Scheme::Scalar: FromUniformBytes<64> + + SerdeObject + + Serialize + + DeserializeOwned + + WithSmallOrderMulGroup<3>, + Scheme::Curve: SerdeObject + Serialize + DeserializeOwned, + Scheme::ParamsVerifier: 'a, +{ + let proof = Snark::load::(&proof_path)?; + + let strategy = Strategy::new(params); + let vk = load_vk::(vk_path, settings)?; let now = Instant::now(); - let result = verify_proof_circuit_kzg( - params.verifier_params(), - proof, - &vk, - strategy, - 1 << circuit_settings.run_args.logrows, - ); + + let result = + verify_proof_circuit::(&proof, params, &vk, strategy, 1 << logrows); + let elapsed = now.elapsed(); info!( "verify took {}.{}", @@ -2073,7 +2271,7 @@ pub(crate) fn verify( elapsed.subsec_millis() ); info!("verified: {}", result.is_ok()); - result.map_err(|e| e.into()).map(|_| true) + result.map_err(|e: plonk::Error| e.into()).map(|_| true) } pub(crate) fn verify_aggr( @@ -2081,34 +2279,101 @@ pub(crate) fn verify_aggr( vk_path: PathBuf, srs_path: Option, logrows: u32, + reduced_srs: bool, + commitment: Commitments, ) -> Result> { - let params = load_params_cmd(srs_path, logrows)?; - - let proof = Snark::load::>(&proof_path)?; - - let strategy = AccumulatorStrategy::new(params.verifier_params()); - let vk = load_vk::, Fr, AggregationCircuit>(vk_path, ())?; - let now = Instant::now(); - let result = verify_proof_circuit_kzg(¶ms, proof, &vk, strategy, 1 << logrows); + match commitment { + Commitments::KZG => { + let proof = Snark::load::>(&proof_path)?; + let params: ParamsKZG = if reduced_srs { + // only need G_0 for the verification with shplonk + load_params_verifier::>(srs_path, 1, Commitments::KZG)? + } else { + load_params_verifier::>( + srs_path, + logrows, + Commitments::KZG, + )? + }; + match proof.transcript_type { + TranscriptType::EVM => verify_commitment::< + KZGCommitmentScheme, + VerifierSHPLONK<'_, Bn256>, + _, + KZGSingleStrategy<_>, + EvmTranscript<_, _, _, _>, + AggregationCircuit, + _, + >(proof_path, (), vk_path, ¶ms, logrows), + TranscriptType::Poseidon => { + verify_commitment::< + KZGCommitmentScheme, + VerifierSHPLONK<'_, Bn256>, + _, + KZGAccumulatorStrategy<_>, + PoseidonTranscript, + AggregationCircuit, + _, + >(proof_path, (), vk_path, ¶ms, logrows) + } + } + } + Commitments::IPA => { + let proof = Snark::load::>(&proof_path)?; + let params: ParamsIPA<_> = load_params_verifier::>( + srs_path, + logrows, + Commitments::IPA, + )?; + match proof.transcript_type { + TranscriptType::EVM => verify_commitment::< + IPACommitmentScheme, + VerifierIPA<_>, + _, + IPASingleStrategy<_>, + EvmTranscript<_, _, _, _>, + AggregationCircuit, + _, + >(proof_path, (), vk_path, ¶ms, logrows), + TranscriptType::Poseidon => { + verify_commitment::< + IPACommitmentScheme, + VerifierIPA<_>, + _, + IPAAccumulatorStrategy<_>, + PoseidonTranscript, + AggregationCircuit, + _, + >(proof_path, (), vk_path, ¶ms, logrows) + } + } + } + } +} - let elapsed = now.elapsed(); - info!( - "verify took {}.{}", - elapsed.as_secs(), - elapsed.subsec_millis() - ); - info!("verified: {}", result.is_ok()); - result?; - Ok(true) +/// helper function for load_params +pub(crate) fn load_params_verifier( + srs_path: Option, + logrows: u32, + commitment: Commitments, +) -> Result> { + let srs_path = get_srs_path(logrows, srs_path, commitment); + let mut params = load_srs_verifier::(srs_path)?; + info!("downsizing params to {} logrows", logrows); + if logrows < params.k() { + params.downsize(logrows); + } + Ok(params) } /// helper function for load_params -pub(crate) fn load_params_cmd( +pub(crate) fn load_params_prover( srs_path: Option, logrows: u32, -) -> Result, Box> { - let srs_path = get_srs_path(logrows, srs_path); - let mut params: ParamsKZG = load_srs::>(srs_path)?; + commitment: Commitments, +) -> Result> { + let srs_path = get_srs_path(logrows, srs_path, commitment); + let mut params = load_srs_prover::(srs_path)?; info!("downsizing params to {} logrows", logrows); if logrows < params.k() { params.downsize(logrows); diff --git a/src/graph/mod.rs b/src/graph/mod.rs index ac3e56c17..405f5bcc2 100644 --- a/src/graph/mod.rs +++ b/src/graph/mod.rs @@ -15,7 +15,7 @@ use colored_json::ToColoredJson; #[cfg(unix)] use gag::Gag; use halo2_proofs::plonk::VerifyingKey; -use halo2_proofs::poly::kzg::commitment::ParamsKZG; +use halo2_proofs::poly::commitment::CommitmentScheme; pub use input::DataSource; use itertools::Itertools; use tosubcommand::ToFlags; @@ -37,7 +37,7 @@ use halo2_proofs::{ circuit::Layouter, plonk::{Circuit, ConstraintSystem, Error as PlonkError}, }; -use halo2curves::bn256::{self, Bn256, Fr as Fp, G1Affine}; +use halo2curves::bn256::{self, Fr as Fp, G1Affine}; use halo2curves::ff::PrimeField; #[cfg(not(target_arch = "wasm32"))] use lazy_static::lazy_static; @@ -126,7 +126,7 @@ pub enum GraphError { #[error("failed to rescale inputs for {0}")] RescalingError(String), /// Error when attempting to load a model - #[error("failed to load model")] + #[error("failed to load")] ModelLoad, /// Packing exponent is too large #[error("largest packing exponent exceeds max. try reducing the scale")] @@ -284,20 +284,20 @@ impl GraphWitness { } /// - pub fn get_kzg_commitments(&self) -> Vec { + pub fn get_polycommitments(&self) -> Vec { let mut commitments = vec![]; if let Some(processed_inputs) = &self.processed_inputs { - if let Some(commits) = &processed_inputs.kzg_commit { + if let Some(commits) = &processed_inputs.polycommit { commitments.extend(commits.iter().flatten()); } } if let Some(processed_params) = &self.processed_params { - if let Some(commits) = &processed_params.kzg_commit { + if let Some(commits) = &processed_params.polycommit { commitments.extend(commits.iter().flatten()); } } if let Some(processed_outputs) = &self.processed_outputs { - if let Some(commits) = &processed_outputs.kzg_commit { + if let Some(commits) = &processed_outputs.polycommit { commitments.extend(commits.iter().flatten()); } } @@ -318,7 +318,7 @@ impl GraphWitness { /// Load the model input from a file pub fn from_path(path: std::path::PathBuf) -> Result> { let file = std::fs::File::open(path.clone()) - .map_err(|_| format!("failed to load model at {}", path.display()))?; + .map_err(|_| format!("failed to load {}", path.display()))?; let reader = std::io::BufReader::with_capacity(*EZKL_BUF_CAPACITY, file); serde_json::from_reader(reader).map_err(|e| e.into()) @@ -387,8 +387,8 @@ impl ToPyObject for GraphWitness { if let Some(processed_inputs_poseidon_hash) = &processed_inputs.poseidon_hash { insert_poseidon_hash_pydict(dict_inputs, processed_inputs_poseidon_hash).unwrap(); } - if let Some(processed_inputs_kzg_commit) = &processed_inputs.kzg_commit { - insert_kzg_commit_pydict(dict_inputs, processed_inputs_kzg_commit).unwrap(); + if let Some(processed_inputs_polycommit) = &processed_inputs.polycommit { + insert_polycommit_pydict(dict_inputs, processed_inputs_polycommit).unwrap(); } dict.set_item("processed_inputs", dict_inputs).unwrap(); @@ -398,8 +398,8 @@ impl ToPyObject for GraphWitness { if let Some(processed_params_poseidon_hash) = &processed_params.poseidon_hash { insert_poseidon_hash_pydict(dict_params, processed_params_poseidon_hash).unwrap(); } - if let Some(processed_params_kzg_commit) = &processed_params.kzg_commit { - insert_kzg_commit_pydict(dict_inputs, processed_params_kzg_commit).unwrap(); + if let Some(processed_params_polycommit) = &processed_params.polycommit { + insert_polycommit_pydict(dict_inputs, processed_params_polycommit).unwrap(); } dict.set_item("processed_params", dict_params).unwrap(); @@ -409,8 +409,8 @@ impl ToPyObject for GraphWitness { if let Some(processed_outputs_poseidon_hash) = &processed_outputs.poseidon_hash { insert_poseidon_hash_pydict(dict_outputs, processed_outputs_poseidon_hash).unwrap(); } - if let Some(processed_outputs_kzg_commit) = &processed_outputs.kzg_commit { - insert_kzg_commit_pydict(dict_inputs, processed_outputs_kzg_commit).unwrap(); + if let Some(processed_outputs_polycommit) = &processed_outputs.polycommit { + insert_polycommit_pydict(dict_inputs, processed_outputs_polycommit).unwrap(); } dict.set_item("processed_outputs", dict_outputs).unwrap(); @@ -429,13 +429,13 @@ fn insert_poseidon_hash_pydict(pydict: &PyDict, poseidon_hash: &Vec) -> Resu } #[cfg(feature = "python-bindings")] -fn insert_kzg_commit_pydict(pydict: &PyDict, commits: &Vec>) -> Result<(), PyErr> { +fn insert_polycommit_pydict(pydict: &PyDict, commits: &Vec>) -> Result<(), PyErr> { use crate::python::PyG1Affine; let poseidon_hash: Vec> = commits .iter() .map(|c| c.iter().map(|x| PyG1Affine::from(*x)).collect()) .collect(); - pydict.set_item("kzg_commit", poseidon_hash)?; + pydict.set_item("polycommit", poseidon_hash)?; Ok(()) } @@ -590,7 +590,7 @@ impl GraphSettings { || self.run_args.param_visibility.is_hashed() } - /// requires dynamic lookup + /// requires dynamic lookup pub fn requires_dynamic_lookup(&self) -> bool { self.num_dynamic_lookups > 0 } @@ -601,10 +601,10 @@ impl GraphSettings { } /// any kzg visibility - pub fn module_requires_kzg(&self) -> bool { - self.run_args.input_visibility.is_kzgcommit() - || self.run_args.output_visibility.is_kzgcommit() - || self.run_args.param_visibility.is_kzgcommit() + pub fn module_requires_polycommit(&self) -> bool { + self.run_args.input_visibility.is_polycommit() + || self.run_args.output_visibility.is_polycommit() + || self.run_args.param_visibility.is_polycommit() } } @@ -1248,11 +1248,11 @@ impl GraphCircuit { } /// Runs the forward pass of the model / graph of computations and any associated hashing. - pub fn forward( + pub fn forward>( &self, inputs: &mut [Tensor], vk: Option<&VerifyingKey>, - srs: Option<&ParamsKZG>, + srs: Option<&Scheme::ParamsProver>, throw_range_check_error: bool, ) -> Result> { let original_inputs = inputs.to_vec(); @@ -1269,7 +1269,8 @@ impl GraphCircuit { for outlet in &module_outlets { module_inputs.push(inputs[*outlet].clone()); } - let res = GraphModules::forward(&module_inputs, &visibility.input, vk, srs)?; + let res = + GraphModules::forward::(&module_inputs, &visibility.input, vk, srs)?; processed_inputs = Some(res.clone()); let module_results = res.get_result(visibility.input.clone()); @@ -1277,7 +1278,12 @@ impl GraphCircuit { inputs[*outlet] = Tensor::from(module_results[i].clone().into_iter()); } } else { - processed_inputs = Some(GraphModules::forward(inputs, &visibility.input, vk, srs)?); + processed_inputs = Some(GraphModules::forward::( + inputs, + &visibility.input, + vk, + srs, + )?); } } @@ -1285,7 +1291,7 @@ impl GraphCircuit { let params = self.model().get_all_params(); if !params.is_empty() { let flattened_params = Tensor::new(Some(¶ms), &[params.len()])?.combine()?; - processed_params = Some(GraphModules::forward( + processed_params = Some(GraphModules::forward::( &[flattened_params], &visibility.params, vk, @@ -1305,7 +1311,8 @@ impl GraphCircuit { for outlet in &module_outlets { module_inputs.push(model_results.outputs[*outlet].clone()); } - let res = GraphModules::forward(&module_inputs, &visibility.output, vk, srs)?; + let res = + GraphModules::forward::(&module_inputs, &visibility.output, vk, srs)?; processed_outputs = Some(res.clone()); let module_results = res.get_result(visibility.output.clone()); @@ -1314,7 +1321,7 @@ impl GraphCircuit { Tensor::from(module_results[i].clone().into_iter()); } } else { - processed_outputs = Some(GraphModules::forward( + processed_outputs = Some(GraphModules::forward::( &model_results.outputs, &visibility.output, vk, diff --git a/src/graph/model.rs b/src/graph/model.rs index 857e87564..6f1de87e8 100644 --- a/src/graph/model.rs +++ b/src/graph/model.rs @@ -970,7 +970,7 @@ impl Model { let (model, _) = Model::load_onnx_using_tract( &mut std::fs::File::open(model_path) - .map_err(|_| format!("failed to load model at {}", model_path.display()))?, + .map_err(|_| format!("failed to load {}", model_path.display()))?, run_args, )?; @@ -1006,7 +1006,7 @@ impl Model { ) -> Result> { Model::new( &mut std::fs::File::open(model) - .map_err(|_| format!("failed to load model at {}", model.display()))?, + .map_err(|_| format!("failed to load {}", model.display()))?, run_args, ) } diff --git a/src/graph/modules.rs b/src/graph/modules.rs index 20905f015..71f867371 100644 --- a/src/graph/modules.rs +++ b/src/graph/modules.rs @@ -1,12 +1,12 @@ -use crate::circuit::modules::kzg::{KZGChip, KZGConfig}; +use crate::circuit::modules::polycommit::{PolyCommitChip, PolyCommitConfig}; use crate::circuit::modules::poseidon::spec::{PoseidonSpec, POSEIDON_RATE, POSEIDON_WIDTH}; use crate::circuit::modules::poseidon::{PoseidonChip, PoseidonConfig}; use crate::circuit::modules::Module; use crate::tensor::{Tensor, ValTensor}; use halo2_proofs::circuit::Layouter; use halo2_proofs::plonk::{Column, ConstraintSystem, Error, Instance, VerifyingKey}; -use halo2_proofs::poly::kzg::commitment::ParamsKZG; -use halo2curves::bn256::{Bn256, Fr as Fp, G1Affine}; +use halo2_proofs::poly::commitment::CommitmentScheme; +use halo2curves::bn256::{Fr as Fp, G1Affine}; use itertools::Itertools; use serde::{Deserialize, Serialize}; @@ -14,9 +14,6 @@ use super::{VarVisibility, Visibility}; /// poseidon len to hash in tree pub const POSEIDON_LEN_GRAPH: usize = 32; - -/// ElGamal number of instances -pub const ELGAMAL_INSTANCES: usize = 4; /// Poseidon number of instancess pub const POSEIDON_INSTANCES: usize = 1; @@ -29,8 +26,8 @@ pub type ModulePoseidonConfig = PoseidonConfig; /// #[derive(Clone, Debug, Default)] pub struct ModuleConfigs { - /// KZG - kzg: Vec, + /// PolyCommit + polycommit: Vec, /// Poseidon poseidon: Option, /// Instance @@ -46,8 +43,10 @@ impl ModuleConfigs { ) -> Self { let mut config = Self::default(); - for size in module_size.kzg { - config.kzg.push(KZGChip::configure(cs, (logrows, size))); + for size in module_size.polycommit { + config + .polycommit + .push(PolyCommitChip::configure(cs, (logrows, size))); } config @@ -94,8 +93,8 @@ impl ModuleConfigs { pub struct ModuleForwardResult { /// The inputs of the forward pass for poseidon pub poseidon_hash: Option>, - /// The outputs of the forward pass for KZG - pub kzg_commit: Option>>, + /// The outputs of the forward pass for PolyCommit + pub polycommit: Option>>, } impl ModuleForwardResult { @@ -126,7 +125,7 @@ impl ModuleForwardResult { #[derive(Clone, Debug, Default, Serialize, Deserialize, PartialEq)] /// pub struct ModuleSizes { - kzg: Vec, + polycommit: Vec, poseidon: (usize, Vec), } @@ -134,7 +133,7 @@ impl ModuleSizes { /// Create new module sizes pub fn new() -> Self { ModuleSizes { - kzg: vec![], + polycommit: vec![], poseidon: ( 0, vec![0; crate::circuit::modules::poseidon::NUM_INSTANCE_COLUMNS], @@ -156,17 +155,17 @@ impl ModuleSizes { /// Graph modules that can process inputs, params and outputs beyond the basic operations #[derive(Clone, Debug, Default, Serialize, Deserialize)] pub struct GraphModules { - kzg_idx: usize, + polycommit_idx: usize, } impl GraphModules { /// pub fn new() -> GraphModules { - GraphModules { kzg_idx: 0 } + GraphModules { polycommit_idx: 0 } } /// pub fn reset_index(&mut self) { - self.kzg_idx = 0; + self.polycommit_idx = 0; } } @@ -179,9 +178,9 @@ impl GraphModules { for shape in shapes { let total_len = shape.iter().product::(); if total_len > 0 { - if visibility.is_kzgcommit() { - // 1 constraint for each kzg commitment - sizes.kzg.push(total_len); + if visibility.is_polycommit() { + // 1 constraint for each polycommit commitment + sizes.polycommit.push(total_len); } else if visibility.is_hashed() { sizes.poseidon.0 += ModulePoseidon::num_rows(total_len); // 1 constraints for hash @@ -236,22 +235,22 @@ impl GraphModules { element_visibility: &Visibility, instance_offset: &mut usize, ) -> Result<(), Error> { - if element_visibility.is_kzgcommit() && !values.is_empty() { + if element_visibility.is_polycommit() && !values.is_empty() { // concat values and sk to get the inputs let mut inputs = values.iter_mut().map(|x| vec![x.clone()]).collect_vec(); // layout the module inputs.iter_mut().for_each(|x| { // create the module - let chip = KZGChip::new(configs.kzg[self.kzg_idx].clone()); - // reserve module 2 onwards for kzg modules - let module_offset = 3 + self.kzg_idx; + let chip = PolyCommitChip::new(configs.polycommit[self.polycommit_idx].clone()); + // reserve module 2 onwards for polycommit modules + let module_offset = 3 + self.polycommit_idx; layouter .assign_region(|| format!("_enter_module_{}", module_offset), |_| Ok(())) .unwrap(); Self::layout_module(&chip, layouter, x, instance_offset).unwrap(); // increment the current index - self.kzg_idx += 1; + self.polycommit_idx += 1; }); // replace the inputs with the outputs @@ -288,14 +287,14 @@ impl GraphModules { } /// Run forward pass - pub fn forward( - inputs: &[Tensor], + pub fn forward>( + inputs: &[Tensor], element_visibility: &Visibility, vk: Option<&VerifyingKey>, - srs: Option<&ParamsKZG>, + srs: Option<&Scheme::ParamsProver>, ) -> Result> { let mut poseidon_hash = None; - let mut kzg_commit = None; + let mut polycommit = None; if element_visibility.is_hashed() { let field_elements = inputs.iter().fold(vec![], |mut acc, x| { @@ -306,11 +305,11 @@ impl GraphModules { poseidon_hash = Some(field_elements); } - if element_visibility.is_kzgcommit() { + if element_visibility.is_polycommit() { if let Some(vk) = vk { if let Some(srs) = srs { let commitments = inputs.iter().fold(vec![], |mut acc, x| { - let res = KZGChip::commit( + let res = PolyCommitChip::commit::( x.to_vec(), vk.cs().degree() as u32, (vk.cs().blinding_factors() + 1) as u32, @@ -319,20 +318,20 @@ impl GraphModules { acc.push(res); acc }); - kzg_commit = Some(commitments); + polycommit = Some(commitments); } else { - log::warn!("no srs provided for kzgcommit. processed value will be none"); + log::warn!("no srs provided for polycommit. processed value will be none"); } } else { log::debug!( - "no verifying key provided for kzgcommit. processed value will be none" + "no verifying key provided for polycommit. processed value will be none" ); } } Ok(ModuleForwardResult { poseidon_hash, - kzg_commit, + polycommit, }) } } diff --git a/src/graph/vars.rs b/src/graph/vars.rs index 7324775ed..e8742c0b6 100644 --- a/src/graph/vars.rs +++ b/src/graph/vars.rs @@ -45,7 +45,7 @@ pub enum Visibility { impl Display for Visibility { fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { match self { - Visibility::KZGCommit => write!(f, "kzgcommit"), + Visibility::KZGCommit => write!(f, "polycommit"), Visibility::Private => write!(f, "private"), Visibility::Public => write!(f, "public"), Visibility::Fixed => write!(f, "fixed"), @@ -88,7 +88,7 @@ impl<'a> From<&'a str> for Visibility { match s { "private" => Visibility::Private, "public" => Visibility::Public, - "kzgcommit" => Visibility::KZGCommit, + "polycommit" => Visibility::KZGCommit, "fixed" => Visibility::Fixed, "hashed" | "hashed/public" => Visibility::Hashed { hash_is_public: true, @@ -111,7 +111,7 @@ impl IntoPy for Visibility { Visibility::Private => "private".to_object(py), Visibility::Public => "public".to_object(py), Visibility::Fixed => "fixed".to_object(py), - Visibility::KZGCommit => "kzgcommit".to_object(py), + Visibility::KZGCommit => "polycommit".to_object(py), Visibility::Hashed { hash_is_public, outlets, @@ -158,7 +158,7 @@ impl<'source> FromPyObject<'source> for Visibility { match strval.to_lowercase().as_str() { "private" => Ok(Visibility::Private), "public" => Ok(Visibility::Public), - "kzgcommit" => Ok(Visibility::KZGCommit), + "polycommit" => Ok(Visibility::KZGCommit), "hashed" => Ok(Visibility::Hashed { hash_is_public: true, outlets: vec![], @@ -192,7 +192,7 @@ impl Visibility { matches!(&self, Visibility::Hashed { .. }) } #[allow(missing_docs)] - pub fn is_kzgcommit(&self) -> bool { + pub fn is_polycommit(&self) -> bool { matches!(&self, Visibility::KZGCommit) } @@ -323,9 +323,9 @@ impl VarVisibility { & !output_vis.is_hashed() & !params_vis.is_hashed() & !input_vis.is_hashed() - & !output_vis.is_kzgcommit() - & !params_vis.is_kzgcommit() - & !input_vis.is_kzgcommit() + & !output_vis.is_polycommit() + & !params_vis.is_polycommit() + & !input_vis.is_polycommit() { return Err(Box::new(GraphError::Visibility)); } diff --git a/src/lib.rs b/src/lib.rs index 9715c2792..96f2a1377 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -28,9 +28,15 @@ //! A library for turning computational graphs, such as neural networks, into ZK-circuits. //! +use std::str::FromStr; + use circuit::{table::Range, CheckMode, Tolerance}; use clap::Args; use graph::Visibility; +use halo2_proofs::poly::{ + ipa::commitment::IPACommitmentScheme, kzg::commitment::KZGCommitmentScheme, +}; +use halo2curves::bn256::{Bn256, G1Affine}; use serde::{Deserialize, Serialize}; use tosubcommand::ToFlags; @@ -97,6 +103,71 @@ const EZKL_KEY_FORMAT: &str = "raw-bytes"; #[cfg(target_arch = "wasm32")] const EZKL_BUF_CAPACITY: &usize = &8000; +#[derive( + Clone, Debug, PartialEq, Eq, Hash, PartialOrd, Ord, Serialize, Deserialize, Default, Copy, +)] +/// Commitment scheme +pub enum Commitments { + #[default] + /// KZG + KZG, + /// IPA + IPA, +} + +impl FromStr for Commitments { + type Err = String; + fn from_str(s: &str) -> Result { + match s.to_lowercase().as_str() { + "kzg" => Ok(Commitments::KZG), + "ipa" => Ok(Commitments::IPA), + _ => Err("Invalid value for Commitments".to_string()), + } + } +} + +impl From> for Commitments { + fn from(_value: KZGCommitmentScheme) -> Self { + Commitments::KZG + } +} + +impl From> for Commitments { + fn from(_value: IPACommitmentScheme) -> Self { + Commitments::IPA + } +} + +impl std::fmt::Display for Commitments { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + match self { + Commitments::KZG => write!(f, "kzg"), + Commitments::IPA => write!(f, "ipa"), + } + } +} + +impl ToFlags for Commitments { + /// Convert the struct to a subcommand string + fn to_flags(&self) -> Vec { + vec![format!("{}", self)] + } +} + +impl From for Commitments { + fn from(value: String) -> Self { + match value.to_lowercase().as_str() { + "kzg" => Commitments::KZG, + "ipa" => Commitments::IPA, + _ => { + log::error!("Invalid value for Commitments"); + log::warn!("defaulting to KZG"); + Commitments::KZG + } + } + } +} + /// Parameters specific to a proving run #[derive(Debug, Args, Deserialize, Serialize, Clone, PartialEq, PartialOrd, ToFlags)] pub struct RunArgs { @@ -142,6 +213,9 @@ pub struct RunArgs { /// check mode (safe, unsafe, etc) #[arg(long, default_value = "unsafe")] pub check_mode: CheckMode, + /// commitment scheme + #[arg(long, default_value = "kzg")] + pub commitment: Commitments, } impl Default for RunArgs { @@ -161,6 +235,7 @@ impl Default for RunArgs { div_rebasing: false, rebase_frac_zero_constants: false, check_mode: CheckMode::UNSAFE, + commitment: Commitments::KZG, } } } diff --git a/src/pfsys/evm/aggregation.rs b/src/pfsys/evm/aggregation_kzg.rs similarity index 100% rename from src/pfsys/evm/aggregation.rs rename to src/pfsys/evm/aggregation_kzg.rs diff --git a/src/pfsys/evm/mod.rs b/src/pfsys/evm/mod.rs index 06da47759..3c8196e53 100644 --- a/src/pfsys/evm/mod.rs +++ b/src/pfsys/evm/mod.rs @@ -1,7 +1,7 @@ use thiserror::Error; -/// Aggregate proof generation for EVM -pub mod aggregation; +/// Aggregate proof generation for EVM using KZG +pub mod aggregation_kzg; #[derive(Error, Debug)] /// Errors related to evm verification diff --git a/src/pfsys/mod.rs b/src/pfsys/mod.rs index 29dfd2cc9..567ed708b 100644 --- a/src/pfsys/mod.rs +++ b/src/pfsys/mod.rs @@ -6,17 +6,16 @@ pub mod srs; use crate::circuit::CheckMode; use crate::graph::GraphWitness; -use crate::pfsys::evm::aggregation::PoseidonTranscript; -use crate::tensor::TensorType; -use crate::{EZKL_BUF_CAPACITY, EZKL_KEY_FORMAT}; +use crate::pfsys::evm::aggregation_kzg::PoseidonTranscript; +use crate::{Commitments, EZKL_BUF_CAPACITY, EZKL_KEY_FORMAT}; use clap::ValueEnum; use halo2_proofs::circuit::Value; use halo2_proofs::plonk::{ create_proof, keygen_pk, keygen_vk_custom, verify_proof, Circuit, ProvingKey, VerifyingKey, }; use halo2_proofs::poly::commitment::{CommitmentScheme, Params, ParamsProver, Prover, Verifier}; -use halo2_proofs::poly::kzg::commitment::{KZGCommitmentScheme, ParamsKZG}; -use halo2_proofs::poly::kzg::multiopen::{ProverSHPLONK, VerifierSHPLONK}; +use halo2_proofs::poly::ipa::commitment::IPACommitmentScheme; +use halo2_proofs::poly::kzg::commitment::KZGCommitmentScheme; use halo2_proofs::poly::VerificationStrategy; use halo2_proofs::transcript::{EncodedChallenge, TranscriptReadBuffer, TranscriptWriterBuffer}; use halo2curves::ff::{FromUniformBytes, PrimeField, WithSmallOrderMulGroup}; @@ -32,7 +31,6 @@ use serde::de::DeserializeOwned; use serde::{Deserialize, Serialize}; use snark_verifier::loader::native::NativeLoader; use snark_verifier::system::halo2::transcript::evm::EvmTranscript; -use snark_verifier::system::halo2::{compile, Config}; use snark_verifier::verifier::plonk::PlonkProtocol; use std::error::Error; use std::fs::File; @@ -293,6 +291,8 @@ where pub pretty_public_inputs: Option, /// timestamp pub timestamp: Option, + /// commitment + pub commitment: Option, } #[cfg(feature = "python-bindings")] @@ -336,6 +336,7 @@ where transcript_type: TranscriptType, split: Option, pretty_public_inputs: Option, + commitment: Option, ) -> Self { Self { protocol, @@ -352,6 +353,7 @@ where .unwrap() .as_millis(), ), + commitment, } } @@ -398,27 +400,36 @@ impl From for Option { let mut elem_offset = 0; if let Some(input) = witness.processed_inputs { - if let Some(kzg) = input.kzg_commit { + if let Some(polycommit) = input.polycommit { // flatten and count number of elements - let num_elements = kzg.iter().map(|kzg| kzg.len()).sum::(); + let num_elements = polycommit + .iter() + .map(|polycommit| polycommit.len()) + .sum::(); elem_offset += num_elements; } } if let Some(params) = witness.processed_params { - if let Some(kzg) = params.kzg_commit { + if let Some(polycommit) = params.polycommit { // flatten and count number of elements - let num_elements = kzg.iter().map(|kzg| kzg.len()).sum::(); + let num_elements = polycommit + .iter() + .map(|polycommit| polycommit.len()) + .sum::(); elem_offset += num_elements; } } if let Some(output) = witness.processed_outputs { - if let Some(kzg) = output.kzg_commit { + if let Some(polycommit) = output.polycommit { // flatten and count number of elements - let num_elements = kzg.iter().map(|kzg| kzg.len()).sum::(); + let num_elements = polycommit + .iter() + .map(|polycommit| polycommit.len()) + .sum::(); Some(ProofSplitCommit { start: elem_offset, @@ -481,7 +492,7 @@ where } /// Creates a [VerifyingKey] and [ProvingKey] for a [crate::graph::GraphCircuit] (`circuit`) with specific [CommitmentScheme] parameters (`params`). -pub fn create_keys>( +pub fn create_keys>( circuit: &C, params: &'_ Scheme::ParamsProver, disable_selector_compression: bool, @@ -491,7 +502,7 @@ where ::Scalar: FromUniformBytes<64>, { // Real proof - let empty_circuit = >::without_witnesses(circuit); + let empty_circuit = >::without_witnesses(circuit); // Initialize verifying key let now = Instant::now(); @@ -513,8 +524,7 @@ where pub fn create_proof_circuit< 'params, Scheme: CommitmentScheme, - F: PrimeField + TensorType, - C: Circuit, + C: Circuit, P: Prover<'params, Scheme>, V: Verifier<'params, Scheme>, Strategy: VerificationStrategy<'params, Scheme, V>, @@ -526,40 +536,28 @@ pub fn create_proof_circuit< instances: Vec>, params: &'params Scheme::ParamsProver, pk: &ProvingKey, - strategy: Strategy, check_mode: CheckMode, + commitment: Commitments, transcript_type: TranscriptType, split: Option, - set_protocol: bool, + protocol: Option>, ) -> Result, Box> where - C: Circuit, Scheme::ParamsVerifier: 'params, Scheme::Scalar: Serialize + DeserializeOwned + SerdeObject + PrimeField + FromUniformBytes<64> - + WithSmallOrderMulGroup<3> - + Ord, + + WithSmallOrderMulGroup<3>, Scheme::Curve: Serialize + DeserializeOwned, { + let strategy = Strategy::new(params.verifier_params()); let mut transcript = TranscriptWriterBuffer::<_, Scheme::Curve, _>::init(vec![]); #[cfg(feature = "det-prove")] let mut rng = ::from_seed([0u8; 32]); #[cfg(not(feature = "det-prove"))] let mut rng = OsRng; - let number_instance = instances.iter().map(|x| x.len()).collect(); - trace!("number_instance {:?}", number_instance); - let mut protocol = None; - - if set_protocol { - protocol = Some(compile( - params, - pk.get_vk(), - Config::kzg().with_num_instance(number_instance), - )) - } let pi_inner = instances .iter() @@ -595,13 +593,14 @@ where transcript_type, split, None, + Some(commitment), ); // sanity check that the generated proof is valid if check_mode == CheckMode::SAFE { debug!("verifying generated proof"); let verifier_params = params.verifier_params(); - verify_proof_circuit::( + verify_proof_circuit::( &checkable_pf, verifier_params, pk.get_vk(), @@ -621,7 +620,6 @@ where /// Swaps the proof commitments to a new set in the proof pub fn swap_proof_commitments< - F: PrimeField, Scheme: CommitmentScheme, E: EncodedChallenge, TW: TranscriptWriterBuffer, Scheme::Curve, E>, @@ -641,7 +639,7 @@ where { let mut transcript_new: TW = TranscriptWriterBuffer::<_, Scheme::Curve, _>::init(vec![]); - // kzg commitments are the first set of points in the proof, this we'll always be the first set of advice + // polycommit commitments are the first set of points in the proof, this we'll always be the first set of advice for commit in commitments { transcript_new .write_point(*commit) @@ -659,31 +657,46 @@ where } /// Swap the proof commitments to a new set in the proof for KZG -pub fn swap_proof_commitments_kzg( +pub fn swap_proof_commitments_polycommit( snark: &Snark, commitments: &[G1Affine], ) -> Result, Box> { - let proof = match snark.transcript_type { - TranscriptType::EVM => swap_proof_commitments::< - Fr, - KZGCommitmentScheme, - _, - EvmTranscript, - >(snark, commitments)?, - TranscriptType::Poseidon => swap_proof_commitments::< - Fr, - KZGCommitmentScheme, - _, - PoseidonTranscript, - >(snark, commitments)?, + let proof = match snark.commitment { + Some(Commitments::KZG) => match snark.transcript_type { + TranscriptType::EVM => swap_proof_commitments::< + KZGCommitmentScheme, + _, + EvmTranscript, + >(snark, commitments)?, + TranscriptType::Poseidon => swap_proof_commitments::< + KZGCommitmentScheme, + _, + PoseidonTranscript, + >(snark, commitments)?, + }, + Some(Commitments::IPA) => match snark.transcript_type { + TranscriptType::EVM => swap_proof_commitments::< + IPACommitmentScheme, + _, + EvmTranscript, + >(snark, commitments)?, + TranscriptType::Poseidon => swap_proof_commitments::< + IPACommitmentScheme, + _, + PoseidonTranscript, + >(snark, commitments)?, + }, + None => { + return Err("commitment scheme not found".into()); + } }; + Ok(proof) } /// A wrapper around halo2's verify_proof pub fn verify_proof_circuit< 'params, - F: PrimeField, V: Verifier<'params, Scheme>, Scheme: CommitmentScheme, Strategy: VerificationStrategy<'params, Scheme, V>, @@ -701,7 +714,6 @@ where + PrimeField + FromUniformBytes<64> + WithSmallOrderMulGroup<3> - + Ord + Serialize + DeserializeOwned, Scheme::Curve: Serialize + DeserializeOwned, @@ -719,7 +731,7 @@ where } /// Loads a [VerifyingKey] at `path`. -pub fn load_vk>( +pub fn load_vk>( path: PathBuf, params: >::Params, ) -> Result, Box> @@ -742,7 +754,7 @@ where } /// Loads a [ProvingKey] at `path`. -pub fn load_pk>( +pub fn load_pk>( path: PathBuf, params: >::Params, ) -> Result, Box> @@ -765,13 +777,12 @@ where } /// Saves a [ProvingKey] to `path`. -pub fn save_pk( +pub fn save_pk( path: &PathBuf, - pk: &ProvingKey, + pk: &ProvingKey, ) -> Result<(), io::Error> where - Scheme::Curve: SerdeObject + CurveAffine, - Scheme::Scalar: PrimeField + SerdeObject + FromUniformBytes<64>, + C::ScalarExt: FromUniformBytes<64> + SerdeObject, { info!("saving proving key 💾"); let f = File::create(path)?; @@ -783,13 +794,12 @@ where } /// Saves a [VerifyingKey] to `path`. -pub fn save_vk( +pub fn save_vk( path: &PathBuf, - vk: &VerifyingKey, + vk: &VerifyingKey, ) -> Result<(), io::Error> where - Scheme::Curve: SerdeObject + CurveAffine, - Scheme::Scalar: PrimeField + SerdeObject + FromUniformBytes<64>, + C::ScalarExt: FromUniformBytes<64> + SerdeObject, { info!("saving verification key 💾"); let f = File::create(path)?; @@ -813,156 +823,25 @@ pub fn save_params( Ok(()) } -/// helper function -#[allow(clippy::too_many_arguments)] -pub fn create_proof_circuit_kzg< - 'params, - C: Circuit, - Strategy: VerificationStrategy<'params, KZGCommitmentScheme, VerifierSHPLONK<'params, Bn256>>, ->( - circuit: C, - params: &'params ParamsKZG, - public_inputs: Option>, - pk: &ProvingKey, - transcript: TranscriptType, - strategy: Strategy, - check_mode: CheckMode, - split: Option, -) -> Result, Box> { - let public_inputs = if let Some(public_inputs) = public_inputs { - if !public_inputs.is_empty() { - vec![public_inputs] - } else { - vec![vec![]] - } - } else { - vec![] - }; - - match transcript { - TranscriptType::EVM => create_proof_circuit::< - KZGCommitmentScheme<_>, - Fr, - _, - ProverSHPLONK<_>, - VerifierSHPLONK<_>, - _, - _, - EvmTranscript, - EvmTranscript, - >( - circuit, - public_inputs, - params, - pk, - strategy, - check_mode, - transcript, - split, - false, - ) - .map_err(Box::::from), - TranscriptType::Poseidon => create_proof_circuit::< - KZGCommitmentScheme<_>, - Fr, - _, - ProverSHPLONK<_>, - VerifierSHPLONK<_>, - _, - _, - PoseidonTranscript, - PoseidonTranscript, - >( - circuit, - public_inputs, - params, - pk, - strategy, - check_mode, - transcript, - split, - true, - ) - .map_err(Box::::from), - } -} - -#[allow(unused)] -/// helper function -pub(crate) fn verify_proof_circuit_kzg< - 'params, - Strategy: VerificationStrategy<'params, KZGCommitmentScheme, VerifierSHPLONK<'params, Bn256>>, ->( - params: &'params ParamsKZG, - proof: Snark, - vk: &VerifyingKey, - strategy: Strategy, - orig_n: u64, -) -> Result { - match proof.transcript_type { - TranscriptType::EVM => verify_proof_circuit::< - Fr, - VerifierSHPLONK<'_, Bn256>, - _, - _, - _, - EvmTranscript, - >(&proof, params, vk, strategy, orig_n), - TranscriptType::Poseidon => verify_proof_circuit::< - Fr, - VerifierSHPLONK<'_, Bn256>, - _, - _, - _, - PoseidonTranscript, - >(&proof, params, vk, strategy, orig_n), - } -} - //////////////////////// #[cfg(test)] #[cfg(not(target_arch = "wasm32"))] mod tests { - use std::io::copy; use super::*; use halo2_proofs::poly::kzg::commitment::KZGCommitmentScheme; use halo2curves::bn256::{Bn256, Fr, G1Affine}; use tempfile::Builder; - #[tokio::test] - async fn test_can_load_pre_generated_srs() { - let tmp_dir = Builder::new().prefix("example").tempdir().unwrap(); - // lets hope this link never rots - let target = "https://trusted-setup-halo2kzg.s3.eu-central-1.amazonaws.com/hermez-raw-1"; - let response = reqwest::get(target).await.unwrap(); - - let fname = response - .url() - .path_segments() - .and_then(|segments| segments.last()) - .and_then(|name| if name.is_empty() { None } else { Some(name) }) - .unwrap_or("tmp.bin"); - - info!("file to download: '{}'", fname); - let fname = tmp_dir.path().join(fname); - info!("will be located under: '{:?}'", fname); - let mut dest = File::create(fname.clone()).unwrap(); - let content = response.bytes().await.unwrap(); - copy(&mut &content[..], &mut dest).unwrap(); - let res = srs::load_srs::>(fname); - assert!(res.is_ok()) - } - #[tokio::test] async fn test_can_load_saved_srs() { let tmp_dir = Builder::new().prefix("example").tempdir().unwrap(); - let fname = tmp_dir.path().join("kzg.params"); + let fname = tmp_dir.path().join("polycommit.params"); let srs = srs::gen_srs::>(1); let res = save_params::>(&fname, &srs); assert!(res.is_ok()); - let res = srs::load_srs::>(fname); + let res = srs::load_srs_prover::>(fname); assert!(res.is_ok()) } @@ -977,6 +856,7 @@ mod tests { split: None, pretty_public_inputs: None, timestamp: None, + commitment: None, }; snark diff --git a/src/pfsys/srs.rs b/src/pfsys/srs.rs index dc54a1aa0..60a8a9333 100644 --- a/src/pfsys/srs.rs +++ b/src/pfsys/srs.rs @@ -17,7 +17,7 @@ pub fn gen_srs(k: u32) -> Scheme::ParamsProver { } /// Loads the [CommitmentScheme::ParamsVerifier] at `path`. -pub fn load_srs( +pub fn load_srs_verifier( path: PathBuf, ) -> Result> { info!("loading srs from {:?}", path); @@ -26,3 +26,14 @@ pub fn load_srs( let mut reader = BufReader::new(f); Params::<'_, Scheme::Curve>::read(&mut reader).map_err(Box::::from) } + +/// Loads the [CommitmentScheme::ParamsVerifier] at `path`. +pub fn load_srs_prover( + path: PathBuf, +) -> Result> { + info!("loading srs from {:?}", path); + let f = File::open(path.clone()) + .map_err(|_| format!("failed to load srs at {}", path.display()))?; + let mut reader = BufReader::new(f); + Params::<'_, Scheme::Curve>::read(&mut reader).map_err(Box::::from) +} diff --git a/src/python.rs b/src/python.rs index 1600a5151..837fbdff9 100644 --- a/src/python.rs +++ b/src/python.rs @@ -1,4 +1,4 @@ -use crate::circuit::modules::kzg::KZGChip; +use crate::circuit::modules::polycommit::PolyCommitChip; use crate::circuit::modules::poseidon::{ spec::{PoseidonSpec, POSEIDON_RATE, POSEIDON_WIDTH}, PoseidonChip, @@ -12,12 +12,14 @@ use crate::graph::TestDataSource; use crate::graph::{ quantize_float, scale_to_multiplier, GraphCircuit, GraphSettings, Model, Visibility, }; -use crate::pfsys::evm::aggregation::AggregationCircuit; +use crate::pfsys::evm::aggregation_kzg::AggregationCircuit; use crate::pfsys::{ - load_pk, load_vk, save_params, save_vk, srs::gen_srs as ezkl_gen_srs, srs::load_srs, ProofType, - TranscriptType, + load_pk, load_vk, save_params, save_vk, srs::gen_srs as ezkl_gen_srs, srs::load_srs_prover, + ProofType, TranscriptType, }; +use crate::Commitments; use crate::RunArgs; +use halo2_proofs::poly::ipa::commitment::IPACommitmentScheme; use halo2_proofs::poly::kzg::commitment::KZGCommitmentScheme; use halo2curves::bn256::{Bn256, Fq, Fr, G1Affine, G1}; use pyo3::exceptions::{PyIOError, PyRuntimeError}; @@ -25,6 +27,7 @@ use pyo3::prelude::*; use pyo3::wrap_pyfunction; use pyo3_log; use snark_verifier::util::arithmetic::PrimeField; +use std::str::FromStr; use std::{fs::File, path::PathBuf}; use tokio::runtime::Runtime; @@ -163,6 +166,8 @@ struct PyRunArgs { pub rebase_frac_zero_constants: bool, #[pyo3(get, set)] pub check_mode: CheckMode, + #[pyo3(get, set)] + pub commitment: PyCommitments, } /// default instantiation of PyRunArgs @@ -192,6 +197,7 @@ impl From for RunArgs { div_rebasing: py_run_args.div_rebasing, rebase_frac_zero_constants: py_run_args.rebase_frac_zero_constants, check_mode: py_run_args.check_mode, + commitment: py_run_args.commitment.into(), } } } @@ -213,6 +219,46 @@ impl Into for RunArgs { div_rebasing: self.div_rebasing, rebase_frac_zero_constants: self.rebase_frac_zero_constants, check_mode: self.check_mode, + commitment: self.commitment.into(), + } + } +} + +#[pyclass] +#[derive(Debug, Clone)] +/// Pyclass marking the type of commitment +pub enum PyCommitments { + /// KZG commitment + KZG, + /// IPA commitment + IPA, +} + +impl From for Commitments { + fn from(py_commitments: PyCommitments) -> Self { + match py_commitments { + PyCommitments::KZG => Commitments::KZG, + PyCommitments::IPA => Commitments::IPA, + } + } +} + +impl Into for Commitments { + fn into(self) -> PyCommitments { + match self { + Commitments::KZG => PyCommitments::KZG, + Commitments::IPA => PyCommitments::IPA, + } + } +} + +impl FromStr for PyCommitments { + type Err = String; + fn from_str(s: &str) -> Result { + match s.to_lowercase().as_str() { + "kzg" => Ok(PyCommitments::KZG), + "ipa" => Ok(PyCommitments::IPA), + _ => Err("Invalid value for Commitments".to_string()), } } } @@ -366,15 +412,56 @@ fn kzg_commit( let settings = GraphSettings::load(&settings_path) .map_err(|_| PyIOError::new_err("Failed to load circuit settings"))?; - let srs_path = crate::execute::get_srs_path(settings.run_args.logrows, srs_path); + let srs_path = + crate::execute::get_srs_path(settings.run_args.logrows, srs_path, Commitments::KZG); + + let srs = load_srs_prover::>(srs_path) + .map_err(|_| PyIOError::new_err("Failed to load srs"))?; + + let vk = load_vk::, GraphCircuit>(vk_path, settings) + .map_err(|_| PyIOError::new_err("Failed to load vk"))?; + + let output = PolyCommitChip::commit::>( + message, + vk.cs().degree() as u32, + (vk.cs().blinding_factors() + 1) as u32, + &srs, + ); + + Ok(output.iter().map(|x| (*x).into()).collect::>()) +} + +/// Generate an ipa commitment. +#[pyfunction(signature = ( + message, + vk_path=PathBuf::from(DEFAULT_VK), + settings_path=PathBuf::from(DEFAULT_SETTINGS), + srs_path=None + ))] +fn ipa_commit( + message: Vec, + vk_path: PathBuf, + settings_path: PathBuf, + srs_path: Option, +) -> PyResult> { + let message: Vec = message + .iter() + .map(crate::pfsys::string_to_field::) + .collect::>(); + + let settings = GraphSettings::load(&settings_path) + .map_err(|_| PyIOError::new_err("Failed to load circuit settings"))?; + + let srs_path = + crate::execute::get_srs_path(settings.run_args.logrows, srs_path, Commitments::KZG); - let srs = load_srs::>(srs_path) + let srs = load_srs_prover::>(srs_path) .map_err(|_| PyIOError::new_err("Failed to load srs"))?; - let vk = load_vk::, Fr, GraphCircuit>(vk_path, settings) + let vk = load_vk::, GraphCircuit>(vk_path, settings) .map_err(|_| PyIOError::new_err("Failed to load vk"))?; - let output = KZGChip::commit( + let output = PolyCommitChip::commit::>( message, vk.cs().degree() as u32, (vk.cs().blinding_factors() + 1) as u32, @@ -390,7 +477,7 @@ fn kzg_commit( witness_path=PathBuf::from(DEFAULT_WITNESS), ))] fn swap_proof_commitments(proof_path: PathBuf, witness_path: PathBuf) -> PyResult<()> { - crate::execute::swap_proof_commitments(proof_path, witness_path) + crate::execute::swap_proof_commitments_cmd(proof_path, witness_path) .map_err(|_| PyIOError::new_err("Failed to swap commitments"))?; Ok(()) @@ -410,13 +497,13 @@ fn gen_vk_from_pk_single( let settings = GraphSettings::load(&circuit_settings_path) .map_err(|_| PyIOError::new_err("Failed to load circuit settings"))?; - let pk = load_pk::, Fr, GraphCircuit>(path_to_pk, settings) + let pk = load_pk::, GraphCircuit>(path_to_pk, settings) .map_err(|_| PyIOError::new_err("Failed to load pk"))?; let vk = pk.get_vk(); // now save - save_vk::>(&vk_output_path, vk) + save_vk::(&vk_output_path, vk) .map_err(|_| PyIOError::new_err("Failed to save vk"))?; Ok(true) @@ -428,13 +515,13 @@ fn gen_vk_from_pk_single( vk_output_path=PathBuf::from(DEFAULT_VK_AGGREGATED), ))] fn gen_vk_from_pk_aggr(path_to_pk: PathBuf, vk_output_path: PathBuf) -> PyResult { - let pk = load_pk::, Fr, AggregationCircuit>(path_to_pk, ()) + let pk = load_pk::, AggregationCircuit>(path_to_pk, ()) .map_err(|_| PyIOError::new_err("Failed to load pk"))?; let vk = pk.get_vk(); // now save - save_vk::>(&vk_output_path, vk) + save_vk::(&vk_output_path, vk) .map_err(|_| PyIOError::new_err("Failed to save vk"))?; Ok(true) @@ -471,19 +558,27 @@ fn gen_srs(srs_path: PathBuf, logrows: usize) -> PyResult<()> { #[pyfunction(signature = ( settings_path=PathBuf::from(DEFAULT_SETTINGS), logrows=None, - srs_path=None + srs_path=None, + commitment=None, ))] fn get_srs( settings_path: Option, logrows: Option, srs_path: Option, + commitment: Option, ) -> PyResult { + let commitment: Option = match commitment { + Some(c) => Some(c.into()), + None => None, + }; + Runtime::new() .unwrap() .block_on(crate::execute::get_srs_cmd( srs_path, settings_path, logrows, + commitment, )) .map_err(|e| { let err_str = format!("Failed to get srs: {}", e); @@ -719,6 +814,7 @@ fn verify( split_proofs = false, srs_path = None, disable_selector_compression=DEFAULT_DISABLE_SELECTOR_COMPRESSION.parse().unwrap(), + commitment=DEFAULT_COMMITMENT.parse().unwrap(), ))] fn setup_aggregate( sample_snarks: Vec, @@ -728,6 +824,7 @@ fn setup_aggregate( split_proofs: bool, srs_path: Option, disable_selector_compression: bool, + commitment: PyCommitments, ) -> Result { crate::execute::setup_aggregate( sample_snarks, @@ -737,6 +834,7 @@ fn setup_aggregate( logrows, split_proofs, disable_selector_compression, + commitment.into(), ) .map_err(|e| { let err_str = format!("Failed to setup aggregate: {}", e); @@ -774,6 +872,7 @@ fn compile_circuit( check_mode=CheckMode::UNSAFE, split_proofs = false, srs_path=None, + commitment=DEFAULT_COMMITMENT.parse().unwrap(), ))] fn aggregate( aggregation_snarks: Vec, @@ -784,6 +883,7 @@ fn aggregate( check_mode: CheckMode, split_proofs: bool, srs_path: Option, + commitment: PyCommitments, ) -> Result { // the K used for the aggregation circuit crate::execute::aggregate( @@ -795,6 +895,7 @@ fn aggregate( logrows, check_mode, split_proofs, + commitment.into(), ) .map_err(|e| { let err_str = format!("Failed to run aggregate: {}", e); @@ -809,15 +910,27 @@ fn aggregate( proof_path=PathBuf::from(DEFAULT_PROOF_AGGREGATED), vk_path=PathBuf::from(DEFAULT_VK), logrows=DEFAULT_AGGREGATED_LOGROWS.parse().unwrap(), + commitment=DEFAULT_COMMITMENT.parse().unwrap(), + reduced_srs=DEFAULT_USE_REDUCED_SRS_FOR_VERIFICATION.parse().unwrap(), srs_path=None, ))] fn verify_aggr( proof_path: PathBuf, vk_path: PathBuf, logrows: u32, + commitment: PyCommitments, + reduced_srs: bool, srs_path: Option, ) -> Result { - crate::execute::verify_aggr(proof_path, vk_path, srs_path, logrows).map_err(|e| { + crate::execute::verify_aggr( + proof_path, + vk_path, + srs_path, + logrows, + reduced_srs, + commitment.into(), + ) + .map_err(|e| { let err_str = format!("Failed to run verify_aggr: {}", e); PyRuntimeError::new_err(err_str) })?; @@ -1103,11 +1216,13 @@ fn ezkl(_py: Python<'_>, m: &PyModule) -> PyResult<()> { m.add_class::()?; m.add_class::()?; m.add_class::()?; + m.add_class::()?; m.add("__version__", env!("CARGO_PKG_VERSION"))?; m.add_function(wrap_pyfunction!(felt_to_big_endian, m)?)?; m.add_function(wrap_pyfunction!(felt_to_int, m)?)?; m.add_function(wrap_pyfunction!(felt_to_float, m)?)?; m.add_function(wrap_pyfunction!(kzg_commit, m)?)?; + m.add_function(wrap_pyfunction!(ipa_commit, m)?)?; m.add_function(wrap_pyfunction!(swap_proof_commitments, m)?)?; m.add_function(wrap_pyfunction!(poseidon_hash, m)?)?; m.add_function(wrap_pyfunction!(float_to_felt, m)?)?; diff --git a/src/wasm.rs b/src/wasm.rs index 80e4c5013..f7b178ff1 100644 --- a/src/wasm.rs +++ b/src/wasm.rs @@ -6,17 +6,33 @@ use crate::fieldutils::i128_to_felt; use crate::graph::modules::POSEIDON_LEN_GRAPH; use crate::graph::quantize_float; use crate::graph::scale_to_multiplier; +use crate::graph::{GraphCircuit, GraphSettings}; +use crate::pfsys::create_proof_circuit; +use crate::pfsys::evm::aggregation_kzg::PoseidonTranscript; +use crate::pfsys::verify_proof_circuit; +use crate::pfsys::TranscriptType; +use crate::tensor::TensorType; +use crate::CheckMode; +use crate::Commitments; use halo2_proofs::plonk::*; use halo2_proofs::poly::commitment::{CommitmentScheme, ParamsProver}; +use halo2_proofs::poly::ipa::multiopen::{ProverIPA, VerifierIPA}; +use halo2_proofs::poly::ipa::{ + commitment::{IPACommitmentScheme, ParamsIPA}, + strategy::SingleStrategy as IPASingleStrategy, +}; +use halo2_proofs::poly::kzg::multiopen::ProverSHPLONK; +use halo2_proofs::poly::kzg::multiopen::VerifierSHPLONK; use halo2_proofs::poly::kzg::{ commitment::{KZGCommitmentScheme, ParamsKZG}, strategy::SingleStrategy as KZGSingleStrategy, }; +use halo2_proofs::poly::VerificationStrategy; use halo2_solidity_verifier::encode_calldata; use halo2curves::bn256::{Bn256, Fr, G1Affine}; use halo2curves::ff::{FromUniformBytes, PrimeField}; - -use crate::tensor::TensorType; +use snark_verifier::loader::native::NativeLoader; +use snark_verifier::system::halo2::transcript::evm::EvmTranscript; use wasm_bindgen::prelude::*; use wasm_bindgen_console_logger::DEFAULT_LOGGER; @@ -37,9 +53,6 @@ pub fn init_panic_hook() { console_error_panic_hook::set_once(); } -use crate::graph::{GraphCircuit, GraphSettings}; -use crate::pfsys::{create_proof_circuit_kzg, verify_proof_circuit_kzg}; - /// Wrapper around the halo2 encode call data method #[wasm_bindgen] #[allow(non_snake_case)] @@ -222,7 +235,7 @@ pub fn genWitness( .map_err(|e| JsError::new(&format!("{}", e)))?; let witness = circuit - .forward(&mut input, None, None, false) + .forward::>(&mut input, None, None, false) .map_err(|e| JsError::new(&format!("{}", e)))?; serde_json::to_vec(&witness) @@ -307,15 +320,10 @@ pub fn verify( settings: wasm_bindgen::Clamped>, srs: wasm_bindgen::Clamped>, ) -> Result { - let mut reader = std::io::BufReader::new(&srs[..]); - let params: ParamsKZG = - halo2_proofs::poly::commitment::Params::<'_, G1Affine>::read(&mut reader) - .map_err(|e| JsError::new(&format!("Failed to deserialize params: {}", e)))?; - let circuit_settings: GraphSettings = serde_json::from_slice(&settings[..]) .map_err(|e| JsError::new(&format!("Failed to deserialize settings: {}", e)))?; - let snark: crate::pfsys::Snark = serde_json::from_slice(&proof_js[..]) + let proof: crate::pfsys::Snark = serde_json::from_slice(&proof_js[..]) .map_err(|e| JsError::new(&format!("Failed to deserialize proof: {}", e)))?; let mut reader = std::io::BufReader::new(&vk[..]); @@ -326,15 +334,60 @@ pub fn verify( ) .map_err(|e| JsError::new(&format!("Failed to deserialize vk: {}", e)))?; - let strategy = KZGSingleStrategy::new(params.verifier_params()); + let orig_n = 1 << circuit_settings.run_args.logrows; - let result = verify_proof_circuit_kzg( - params.verifier_params(), - snark, - &vk, - strategy, - 1 << circuit_settings.run_args.logrows, - ); + let mut reader = std::io::BufReader::new(&srs[..]); + let result = match circuit_settings.run_args.commitment { + Commitments::KZG => { + let params: ParamsKZG = + halo2_proofs::poly::commitment::Params::<'_, G1Affine>::read(&mut reader) + .map_err(|e| JsError::new(&format!("Failed to deserialize params: {}", e)))?; + let strategy = KZGSingleStrategy::new(params.verifier_params()); + match proof.transcript_type { + TranscriptType::EVM => verify_proof_circuit::< + VerifierSHPLONK<'_, Bn256>, + KZGCommitmentScheme, + KZGSingleStrategy<_>, + _, + EvmTranscript, + >(&proof, ¶ms, &vk, strategy, orig_n), + + TranscriptType::Poseidon => { + verify_proof_circuit::< + VerifierSHPLONK<'_, Bn256>, + KZGCommitmentScheme, + KZGSingleStrategy<_>, + _, + PoseidonTranscript, + >(&proof, ¶ms, &vk, strategy, orig_n) + } + } + } + Commitments::IPA => { + let params: ParamsIPA<_> = + halo2_proofs::poly::commitment::Params::<'_, G1Affine>::read(&mut reader) + .map_err(|e| JsError::new(&format!("Failed to deserialize params: {}", e)))?; + let strategy = IPASingleStrategy::new(params.verifier_params()); + match proof.transcript_type { + TranscriptType::EVM => verify_proof_circuit::< + VerifierIPA<_>, + IPACommitmentScheme, + IPASingleStrategy<_>, + _, + EvmTranscript, + >(&proof, ¶ms, &vk, strategy, orig_n), + TranscriptType::Poseidon => { + verify_proof_circuit::< + VerifierIPA<_>, + IPACommitmentScheme, + IPASingleStrategy<_>, + _, + PoseidonTranscript, + >(&proof, ¶ms, &vk, strategy, orig_n) + } + } + } + }; match result { Ok(_) => Ok(true), @@ -354,11 +407,6 @@ pub fn prove( log::set_max_level(log::LevelFilter::Debug); #[cfg(not(feature = "det-prove"))] log::set_max_level(log::LevelFilter::Info); - // read in kzg params - let mut reader = std::io::BufReader::new(&srs[..]); - let params: ParamsKZG = - halo2_proofs::poly::commitment::Params::<'_, G1Affine>::read(&mut reader) - .map_err(|e| JsError::new(&format!("Failed to deserialize srs: {}", e)))?; // read in circuit let mut circuit: crate::graph::GraphCircuit = bincode::deserialize(&compiled_circuit[..]) @@ -386,17 +434,63 @@ pub fn prove( .map_err(|e| JsError::new(&format!("{}", e)))?; let proof_split_commits: Option = data.into(); - let strategy = KZGSingleStrategy::new(¶ms); - let proof = create_proof_circuit_kzg( - circuit, - ¶ms, - Some(public_inputs), - &pk, - crate::pfsys::TranscriptType::EVM, - strategy, - crate::circuit::CheckMode::UNSAFE, - proof_split_commits, - ) + // read in kzg params + let mut reader = std::io::BufReader::new(&srs[..]); + // creates and verifies the proof + let proof = match circuit.settings().run_args.commitment { + Commitments::KZG => { + let params: ParamsKZG = + halo2_proofs::poly::commitment::Params::<'_, G1Affine>::read(&mut reader) + .map_err(|e| JsError::new(&format!("Failed to deserialize srs: {}", e)))?; + + create_proof_circuit::< + KZGCommitmentScheme, + _, + ProverSHPLONK<_>, + VerifierSHPLONK<_>, + KZGSingleStrategy<_>, + _, + EvmTranscript<_, _, _, _>, + EvmTranscript<_, _, _, _>, + >( + circuit, + vec![public_inputs], + ¶ms, + &pk, + CheckMode::UNSAFE, + crate::Commitments::KZG, + TranscriptType::EVM, + proof_split_commits, + None, + ) + } + Commitments::IPA => { + let params: ParamsIPA<_> = + halo2_proofs::poly::commitment::Params::<'_, G1Affine>::read(&mut reader) + .map_err(|e| JsError::new(&format!("Failed to deserialize srs: {}", e)))?; + + create_proof_circuit::< + IPACommitmentScheme, + _, + ProverIPA<_>, + VerifierIPA<_>, + IPASingleStrategy<_>, + _, + EvmTranscript<_, _, _, _>, + EvmTranscript<_, _, _, _>, + >( + circuit, + vec![public_inputs], + ¶ms, + &pk, + CheckMode::UNSAFE, + crate::Commitments::IPA, + TranscriptType::EVM, + proof_split_commits, + None, + ) + } + } .map_err(|e| JsError::new(&format!("{}", e)))?; Ok(serde_json::to_string(&proof) diff --git a/test_snark_serialization_roundtrip.json b/test_snark_serialization_roundtrip.json deleted file mode 100644 index 43af0afc6..000000000 --- a/test_snark_serialization_roundtrip.json +++ /dev/null @@ -1 +0,0 @@ -{"protocol":null,"instances":[[[12436184717236109307,3962172157175319849,7381016538464732718,1011752739694698287]],[[6425625360762666998,7924344314350639699,14762033076929465436,2023505479389396574]]],"proof":[1,2,3,4,5,6,7,8],"transcript_type":"EVM"} \ No newline at end of file diff --git a/tests/integration_tests.rs b/tests/integration_tests.rs index cef59b39f..04daf0d87 100644 --- a/tests/integration_tests.rs +++ b/tests/integration_tests.rs @@ -7,6 +7,7 @@ mod native_tests { // use ezkl::circuit::table::RESERVED_BLINDING_ROWS_PAD; use ezkl::graph::input::{FileSource, FileSourceInner, GraphData}; use ezkl::graph::{DataSource, GraphSettings, GraphWitness}; + use ezkl::Commitments; use lazy_static::lazy_static; use rand::Rng; use std::env::var; @@ -97,10 +98,16 @@ mod native_tests { }); } - fn download_srs(logrows: u32) { + fn download_srs(logrows: u32, commitment: Commitments) { // if does not exist, download it let status = Command::new(format!("{}/release/ezkl", *CARGO_TARGET_DIR)) - .args(["get-srs", "--logrows", &format!("{}", logrows)]) + .args([ + "get-srs", + "--logrows", + &format!("{}", logrows), + "--commitment", + &commitment.to_string(), + ]) .status() .expect("failed to execute process"); assert!(status.success()); @@ -115,7 +122,7 @@ mod native_tests { let settings: GraphSettings = serde_json::from_str(&settings).unwrap(); let logrows = settings.run_args.logrows; - download_srs(logrows) + download_srs(logrows, settings.run_args.commitment); } fn mv_test_(test_dir: &str, test: &str) { @@ -419,9 +426,10 @@ mod native_tests { use seq_macro::seq; use crate::native_tests::TESTS_AGGR; use test_case::test_case; - use crate::native_tests::kzg_aggr_prove_and_verify; + use crate::native_tests::aggr_prove_and_verify; use crate::native_tests::kzg_aggr_mock_prove_and_verify; use tempdir::TempDir; + use ezkl::Commitments; #[cfg(not(feature="icicle"))] seq!(N in 0..=20 { @@ -436,12 +444,22 @@ mod native_tests { } + #(#[test_case(TESTS_AGGR[N])])* fn kzg_aggr_prove_and_verify_(test: &str) { crate::native_tests::init_binary(); let test_dir = TempDir::new(test).unwrap(); let path = test_dir.path().to_str().unwrap(); crate::native_tests::mv_test_(path, test); - kzg_aggr_prove_and_verify(path, test.to_string(), "private", "private", "public"); + aggr_prove_and_verify(path, test.to_string(), "private", "private", "public", Commitments::KZG); + test_dir.close().unwrap(); + } + + #(#[test_case(TESTS_AGGR[N])])* + fn ipa_aggr_prove_and_verify_(test: &str) { + crate::native_tests::init_binary(); + let test_dir = TempDir::new(test).unwrap(); + let path = test_dir.path().to_str().unwrap(); crate::native_tests::mv_test_(path, test); + aggr_prove_and_verify(path, test.to_string(), "private", "private", "public", Commitments::IPA); test_dir.close().unwrap(); } @@ -450,11 +468,11 @@ mod native_tests { #[cfg(feature="icicle")] seq!(N in 0..=2 { #(#[test_case(TESTS_AGGR[N])])* - fn kzg_aggr_prove_and_verify_(test: &str) { + fn aggr_prove_and_verify_(test: &str) { crate::native_tests::init_binary(); let test_dir = TempDir::new(test).unwrap(); let path = test_dir.path().to_str().unwrap(); crate::native_tests::mv_test_(test_dir.path().to_str().unwrap(), test); - kzg_aggr_prove_and_verify(path, test.to_string(), "private", "private", "public"); + aggr_prove_and_verify(path, test.to_string(), "private", "private", "public", Commitments::KZG); test_dir.close().unwrap(); } }); @@ -474,13 +492,13 @@ mod native_tests { use test_case::test_case; use crate::native_tests::mock; use crate::native_tests::accuracy_measurement; - use crate::native_tests::kzg_prove_and_verify; + use crate::native_tests::prove_and_verify; use crate::native_tests::run_js_tests; - use crate::native_tests::kzg_fuzz; use crate::native_tests::render_circuit; use crate::native_tests::model_serialization_different_binaries; use rand::Rng; use tempdir::TempDir; + use ezkl::Commitments; #[test] fn model_serialization_different_binaries_() { @@ -653,7 +671,7 @@ mod native_tests { crate::native_tests::init_binary(); let test_dir = TempDir::new(test).unwrap(); let path = test_dir.path().to_str().unwrap(); crate::native_tests::mv_test_(path, test); - mock(path, test.to_string(), "kzgcommit", "private", "public", 1, "resources", None, 0.0); + mock(path, test.to_string(), "polycommit", "private", "public", 1, "resources", None, 0.0); test_dir.close().unwrap(); } @@ -673,7 +691,7 @@ mod native_tests { crate::native_tests::init_binary(); let test_dir = TempDir::new(test).unwrap(); let path = test_dir.path().to_str().unwrap(); crate::native_tests::mv_test_(path, test); - mock(path, test.to_string(), "private", "kzgcommit", "public", 1, "resources", None, 0.0); + mock(path, test.to_string(), "private", "polycommit", "public", 1, "resources", None, 0.0); test_dir.close().unwrap(); } @@ -692,7 +710,7 @@ mod native_tests { crate::native_tests::init_binary(); let test_dir = TempDir::new(test).unwrap(); let path = test_dir.path().to_str().unwrap(); crate::native_tests::mv_test_(path, test); - mock(path, test.to_string(), "public", "private", "kzgcommit", 1, "resources", None, 0.0); + mock(path, test.to_string(), "public", "private", "polycommit", 1, "resources", None, 0.0); test_dir.close().unwrap(); } @@ -711,7 +729,7 @@ mod native_tests { crate::native_tests::init_binary(); let test_dir = TempDir::new(test).unwrap(); let path = test_dir.path().to_str().unwrap(); crate::native_tests::mv_test_(path, test); - mock(path, test.to_string(), "public", "kzgcommit", "hashed", 1, "resources", None, 0.0); + mock(path, test.to_string(), "public", "polycommit", "hashed", 1, "resources", None, 0.0); test_dir.close().unwrap(); } @@ -721,7 +739,7 @@ mod native_tests { crate::native_tests::init_binary(); let test_dir = TempDir::new(test).unwrap(); let path = test_dir.path().to_str().unwrap(); crate::native_tests::mv_test_(path, test); - mock(path, test.to_string(), "kzgcommit", "kzgcommit", "kzgcommit", 1, "resources", None, 0.0); + mock(path, test.to_string(), "polycommit", "polycommit", "polycommit", 1, "resources", None, 0.0); test_dir.close().unwrap(); } @@ -760,7 +778,7 @@ mod native_tests { crate::native_tests::init_binary(); let test_dir = TempDir::new(test).unwrap(); let path = test_dir.path().to_str().unwrap(); crate::native_tests::mv_test_(path, test); - kzg_prove_and_verify(path, test.to_string(), "safe", "private", "private", "public", 1, None, false, "single"); + prove_and_verify(path, test.to_string(), "safe", "private", "private", "public", 1, None, false, "single", Commitments::KZG); test_dir.close().unwrap(); } @@ -769,7 +787,7 @@ mod native_tests { crate::native_tests::init_binary(); let test_dir = TempDir::new(test).unwrap(); let path = test_dir.path().to_str().unwrap(); crate::native_tests::mv_test_(path, test); - kzg_prove_and_verify(path, test.to_string(), "safe", "private", "private", "public", 3, None, false, "single"); + prove_and_verify(path, test.to_string(), "safe", "private", "private", "public", 3, None, false, "single", Commitments::KZG); test_dir.close().unwrap(); } @@ -778,7 +796,7 @@ mod native_tests { crate::native_tests::init_binary(); let test_dir = TempDir::new(test).unwrap(); let path = test_dir.path().to_str().unwrap(); crate::native_tests::mv_test_(path, test); - kzg_prove_and_verify(path, test.to_string(), "safe", "private", "private", "public", 4, None, false, "single"); + prove_and_verify(path, test.to_string(), "safe", "private", "private", "public", 4, None, false, "single", Commitments::KZG); test_dir.close().unwrap(); } @@ -787,7 +805,7 @@ mod native_tests { crate::native_tests::init_binary(); let test_dir = TempDir::new(test).unwrap(); let path = test_dir.path().to_str().unwrap(); crate::native_tests::mv_test_(path, test); - kzg_prove_and_verify(path, test.to_string(), "safe", "private", "private", "public", 8, None, false, "single"); + prove_and_verify(path, test.to_string(), "safe", "private", "private", "public", 8, None, false, "single", Commitments::KZG); test_dir.close().unwrap(); } @@ -796,7 +814,16 @@ mod native_tests { crate::native_tests::init_binary(); let test_dir = TempDir::new(test).unwrap(); let path = test_dir.path().to_str().unwrap(); crate::native_tests::mv_test_(path, test); - kzg_prove_and_verify(path, test.to_string(), "safe", "private", "private", "public", 1, None, false, "single"); + prove_and_verify(path, test.to_string(), "safe", "private", "private", "public", 1, None, false, "single", Commitments::KZG); + test_dir.close().unwrap(); + } + + #(#[test_case(TESTS[N])])* + fn ipa_prove_and_verify_(test: &str) { + crate::native_tests::init_binary(); + let test_dir = TempDir::new(test).unwrap(); + let path = test_dir.path().to_str().unwrap(); crate::native_tests::mv_test_(path, test); + prove_and_verify(path, test.to_string(), "safe", "private", "private", "public", 1, None, false, "single", Commitments::IPA); test_dir.close().unwrap(); } @@ -805,7 +832,7 @@ mod native_tests { crate::native_tests::init_binary(); let test_dir = TempDir::new(test).unwrap(); let path = test_dir.path().to_str().unwrap(); crate::native_tests::mv_test_(path, test); - kzg_prove_and_verify(path, test.to_string(), "safe", "public", "private", "public", 1, None, false, "single"); + prove_and_verify(path, test.to_string(), "safe", "public", "private", "public", 1, None, false, "single", Commitments::KZG); test_dir.close().unwrap(); } @@ -814,7 +841,7 @@ mod native_tests { crate::native_tests::init_binary(); let test_dir = TempDir::new(test).unwrap(); let path = test_dir.path().to_str().unwrap(); crate::native_tests::mv_test_(path, test); - kzg_prove_and_verify(path, test.to_string(), "safe", "private", "fixed", "public", 1, None, false, "single"); + prove_and_verify(path, test.to_string(), "safe", "private", "fixed", "public", 1, None, false, "single", Commitments::KZG); test_dir.close().unwrap(); } @@ -823,7 +850,7 @@ mod native_tests { crate::native_tests::init_binary(); let test_dir = TempDir::new(test).unwrap(); let path = test_dir.path().to_str().unwrap(); crate::native_tests::mv_test_(path, test); - kzg_prove_and_verify(path, test.to_string(), "safe", "private", "private", "hashed", 1, None, false, "single"); + prove_and_verify(path, test.to_string(), "safe", "private", "private", "hashed", 1, None, false, "single", Commitments::KZG); test_dir.close().unwrap(); } @@ -832,17 +859,17 @@ mod native_tests { crate::native_tests::init_binary(); let test_dir = TempDir::new(test).unwrap(); let path = test_dir.path().to_str().unwrap(); crate::native_tests::mv_test_(path, test); - kzg_prove_and_verify(path, test.to_string(), "safe", "private", "private", "kzgcommit", 1, None, false, "single"); + prove_and_verify(path, test.to_string(), "safe", "private", "private", "polycommit", 1, None, false, "single", Commitments::KZG); test_dir.close().unwrap(); } #(#[test_case(TESTS[N])])* - fn kzg_fuzz_(test: &str) { + fn ipa_prove_and_verify_ipa_output(test: &str) { crate::native_tests::init_binary(); let test_dir = TempDir::new(test).unwrap(); let path = test_dir.path().to_str().unwrap(); crate::native_tests::mv_test_(path, test); - kzg_fuzz(path, test.to_string(), "evm"); - test_dir.close().unwrap(); + prove_and_verify(path, test.to_string(), "safe", "private", "private", "polycommit", 1, None, false, "single", Commitments::IPA); + test_dir.close().unwrap(); } }); @@ -850,26 +877,26 @@ mod native_tests { seq!(N in 0..=45 { #(#[test_case(WASM_TESTS[N])])* - fn kzg_prove_and_verify_with_overflow_(test: &str) { + fn prove_and_verify_with_overflow_(test: &str) { crate::native_tests::init_binary(); // crate::native_tests::init_wasm(); let test_dir = TempDir::new(test).unwrap(); env_logger::init(); let path = test_dir.path().to_str().unwrap(); crate::native_tests::mv_test_(path, test); - kzg_prove_and_verify(path, test.to_string(), "safe", "private", "private", "public", 1, None, true, "single"); + prove_and_verify(path, test.to_string(), "safe", "private", "private", "public", 1, None, true, "single", Commitments::KZG); #[cfg(not(feature = "icicle"))] run_js_tests(path, test.to_string(), "testWasm", false); // test_dir.close().unwrap(); } #(#[test_case(WASM_TESTS[N])])* - fn kzg_prove_and_verify_with_overflow_fixed_params_(test: &str) { + fn prove_and_verify_with_overflow_fixed_params_(test: &str) { crate::native_tests::init_binary(); // crate::native_tests::init_wasm(); let test_dir = TempDir::new(test).unwrap(); env_logger::init(); let path = test_dir.path().to_str().unwrap(); crate::native_tests::mv_test_(path, test); - kzg_prove_and_verify(path, test.to_string(), "safe", "private", "fixed", "public", 1, None, true, "single"); + prove_and_verify(path, test.to_string(), "safe", "private", "fixed", "public", 1, None, true, "single", Commitments::KZG); #[cfg(not(feature = "icicle"))] run_js_tests(path, test.to_string(), "testWasm", false); test_dir.close().unwrap(); @@ -881,11 +908,11 @@ mod native_tests { #(#[test_case(LARGE_TESTS[N])])* #[ignore] - fn large_kzg_prove_and_verify_(test: &str) { + fn large_prove_and_verify_(test: &str) { crate::native_tests::init_binary(); let test_dir = TempDir::new(test).unwrap(); let path = test_dir.path().to_str().unwrap(); crate::native_tests::mv_test_(path, test); - kzg_prove_and_verify(path, test.to_string(), "unsafe", "private", "fixed", "public", 1, None, false, "single"); + prove_and_verify(path, test.to_string(), "unsafe", "private", "fixed", "public", 1, None, false, "single", Commitments::KZG); test_dir.close().unwrap(); } @@ -916,7 +943,6 @@ mod native_tests { use crate::native_tests::kzg_evm_on_chain_input_prove_and_verify; use crate::native_tests::kzg_evm_aggr_prove_and_verify; - use crate::native_tests::kzg_fuzz; use tempdir::TempDir; use crate::native_tests::Hardfork; use crate::native_tests::run_js_tests; @@ -1057,7 +1083,7 @@ mod native_tests { let test_dir = TempDir::new(test).unwrap(); let path = test_dir.path().to_str().unwrap(); crate::native_tests::mv_test_(path, test); let mut _anvil_child = crate::native_tests::start_anvil(false, hardfork); - kzg_evm_prove_and_verify(2, path, test.to_string(), "kzgcommit", "private", "public"); + kzg_evm_prove_and_verify(2, path, test.to_string(), "polycommit", "private", "public"); #[cfg(not(feature = "icicle"))] run_js_tests(path, test.to_string(), "testBrowserEvmVerify", false); test_dir.close().unwrap(); @@ -1096,7 +1122,7 @@ mod native_tests { let test_dir = TempDir::new(test).unwrap(); let path = test_dir.path().to_str().unwrap(); crate::native_tests::mv_test_(path, test); let _anvil_child = crate::native_tests::start_anvil(false, Hardfork::Latest); - kzg_evm_prove_and_verify(2, path, test.to_string(), "private", "kzgcommit", "public"); + kzg_evm_prove_and_verify(2, path, test.to_string(), "private", "polycommit", "public"); #[cfg(not(feature = "icicle"))] run_js_tests(path, test.to_string(), "testBrowserEvmVerify", false); test_dir.close().unwrap(); @@ -1109,7 +1135,7 @@ mod native_tests { let test_dir = TempDir::new(test).unwrap(); let path = test_dir.path().to_str().unwrap(); crate::native_tests::mv_test_(path, test); let _anvil_child = crate::native_tests::start_anvil(false, Hardfork::Latest); - kzg_evm_prove_and_verify(2, path, test.to_string(), "private", "private", "kzgcommit"); + kzg_evm_prove_and_verify(2, path, test.to_string(), "private", "private", "polycommit"); #[cfg(not(feature = "icicle"))] run_js_tests(path, test.to_string(), "testBrowserEvmVerify", false); test_dir.close().unwrap(); @@ -1121,7 +1147,7 @@ mod native_tests { let test_dir = TempDir::new(test).unwrap(); let path = test_dir.path().to_str().unwrap(); crate::native_tests::mv_test_(path, test); let _anvil_child = crate::native_tests::start_anvil(false, Hardfork::Latest); - kzg_evm_prove_and_verify(2, path, test.to_string(), "kzgcommit", "kzgcommit", "kzgcommit"); + kzg_evm_prove_and_verify(2, path, test.to_string(), "polycommit", "polycommit", "polycommit"); #[cfg(not(feature = "icicle"))] run_js_tests(path, test.to_string(), "testBrowserEvmVerify", false); test_dir.close().unwrap(); @@ -1129,16 +1155,7 @@ mod native_tests { - #(#[test_case(TESTS_EVM[N])])* - fn kzg_evm_fuzz_(test: &str) { - crate::native_tests::init_binary(); - let test_dir = TempDir::new(test).unwrap(); - let path = test_dir.path().to_str().unwrap(); crate::native_tests::mv_test_(path, test); - let _anvil_child = crate::native_tests::start_anvil(false, Hardfork::Latest); - kzg_fuzz(path, test.to_string(), "evm"); - test_dir.close().unwrap(); - } }); } }; @@ -1308,6 +1325,7 @@ mod native_tests { 2, false, &mut tolerance, + Commitments::KZG, ); if tolerance > 0.0 { @@ -1447,6 +1465,7 @@ mod native_tests { num_inner_columns: usize, div_rebasing: bool, tolerance: &mut f32, + commitment: Commitments, ) { let mut args = vec![ "gen-settings".to_string(), @@ -1462,6 +1481,7 @@ mod native_tests { format!("--output-visibility={}", output_visibility), format!("--num-inner-cols={}", num_inner_columns), format!("--tolerance={}", tolerance), + format!("--commitment={}", commitment), ]; if div_rebasing { @@ -1580,6 +1600,7 @@ mod native_tests { 2, div_rebasing, &mut 0.0, + Commitments::KZG, ); println!( @@ -1621,7 +1642,7 @@ mod native_tests { // prove-serialize-verify, the usual full path fn kzg_aggr_mock_prove_and_verify(test_dir: &str, example_name: String) { - kzg_prove_and_verify( + prove_and_verify( test_dir, example_name.clone(), "safe", @@ -1632,6 +1653,7 @@ mod native_tests { None, false, "for-aggr", + Commitments::KZG, ); let status = Command::new(format!("{}/release/ezkl", *CARGO_TARGET_DIR)) .args([ @@ -1646,14 +1668,15 @@ mod native_tests { } // prove-serialize-verify, the usual full path - fn kzg_aggr_prove_and_verify( + fn aggr_prove_and_verify( test_dir: &str, example_name: String, input_visibility: &str, param_visibility: &str, output_visibility: &str, + commitment: Commitments, ) { - kzg_prove_and_verify( + prove_and_verify( test_dir, example_name.clone(), "safe", @@ -1664,9 +1687,10 @@ mod native_tests { None, false, "for-aggr", + Commitments::KZG, ); - download_srs(23); + download_srs(23, commitment); // now setup-aggregate let status = Command::new(format!("{}/release/ezkl", *CARGO_TARGET_DIR)) .args([ @@ -1678,6 +1702,7 @@ mod native_tests { &format!("{}/{}/aggr.vk", test_dir, example_name), "--pk-path", &format!("{}/{}/aggr.pk", test_dir, example_name), + &format!("--commitment={}", commitment), ]) .status() .expect("failed to execute process"); @@ -1693,6 +1718,7 @@ mod native_tests { &format!("{}/{}/aggr.pf", test_dir, example_name), "--pk-path", &format!("{}/{}/aggr.pk", test_dir, example_name), + &format!("--commitment={}", commitment), ]) .status() .expect("failed to execute process"); @@ -1719,15 +1745,16 @@ mod native_tests { param_visibility: &str, output_visibility: &str, ) { - kzg_aggr_prove_and_verify( + aggr_prove_and_verify( test_dir, example_name.clone(), input_visibility, param_visibility, output_visibility, + Commitments::KZG, ); - download_srs(23); + download_srs(23, Commitments::KZG); let vk_arg = &format!("{}/{}/aggr.vk", test_dir, example_name); @@ -1810,7 +1837,7 @@ mod native_tests { // prove-serialize-verify, the usual full path #[allow(clippy::too_many_arguments)] - fn kzg_prove_and_verify( + fn prove_and_verify( test_dir: &str, example_name: String, checkmode: &str, @@ -1821,6 +1848,7 @@ mod native_tests { scales_to_use: Option>, overflow: bool, proof_type: &str, + commitment: Commitments, ) { let target_str = if overflow { "resources/col-overflow" @@ -1840,6 +1868,7 @@ mod native_tests { num_inner_columns, false, &mut 0.0, + commitment, ); let settings_path = format!("{}/{}/settings.json", test_dir, example_name); @@ -1912,7 +1941,7 @@ mod native_tests { .expect("failed to parse settings file"); // get_srs for the graph_settings_num_instances - download_srs(graph_settings.log2_total_instances()); + download_srs(1, graph_settings.run_args.commitment); let status = Command::new(format!("{}/release/ezkl", *CARGO_TARGET_DIR)) .args([ @@ -1929,37 +1958,6 @@ mod native_tests { assert!(status.success()); } - // prove-serialize-verify, the usual full path - fn kzg_fuzz(test_dir: &str, example_name: String, transcript: &str) { - gen_circuit_settings_and_witness( - test_dir, - example_name.clone(), - "private", - "fixed", - "public", - 1, - "resources", - None, - 2, - false, - &mut 0.0, - ); - - let status = Command::new(format!("{}/release/ezkl", *CARGO_TARGET_DIR)) - .args([ - "fuzz", - "-W", - format!("{}/{}/witness.json", test_dir, example_name).as_str(), - "-M", - format!("{}/{}/network.compiled", test_dir, example_name).as_str(), - &format!("--num-runs={}", 5), - &format!("--transcript={}", transcript), - ]) - .status() - .expect("failed to execute process"); - assert!(status.success()); - } - // prove-serialize-verify, the usual full path fn kzg_evm_prove_and_verify( num_inner_columns: usize, @@ -1971,7 +1969,7 @@ mod native_tests { ) { let anvil_url = ANVIL_URL.as_str(); - kzg_prove_and_verify( + prove_and_verify( test_dir, example_name.clone(), "safe", @@ -1982,6 +1980,7 @@ mod native_tests { None, false, "single", + Commitments::KZG, ); let settings_path = format!("{}/{}/settings.json", test_dir, example_name); @@ -2064,7 +2063,7 @@ mod native_tests { ) { let anvil_url = ANVIL_URL.as_str(); - kzg_prove_and_verify( + prove_and_verify( test_dir, example_name.clone(), "safe", @@ -2075,6 +2074,7 @@ mod native_tests { None, false, "single", + Commitments::KZG, ); let settings_path = format!("{}/{}/settings.json", test_dir, example_name); @@ -2222,6 +2222,7 @@ mod native_tests { 1, false, &mut 0.0, + Commitments::KZG, ); let model_path = format!("{}/{}/network.compiled", test_dir, example_name); diff --git a/tests/py_integration_tests.rs b/tests/py_integration_tests.rs index 0e481aa9a..4cd1b7ada 100644 --- a/tests/py_integration_tests.rs +++ b/tests/py_integration_tests.rs @@ -61,6 +61,7 @@ mod py_tests { let status = Command::new("pip") .args([ "install", + "torch-geometric==2.5.0", "torch==2.0.1", "torchvision==0.15.2", "pandas==2.0.3", diff --git a/tests/python/binding_tests.py b/tests/python/binding_tests.py index 2ab669d6c..902d5f210 100644 --- a/tests/python/binding_tests.py +++ b/tests/python/binding_tests.py @@ -242,7 +242,7 @@ def test_get_srs(): another_srs_path = os.path.join(folder_path, "kzg_test_k8.params") - res = ezkl.get_srs(logrows=8, srs_path=another_srs_path) + res = ezkl.get_srs(logrows=8, srs_path=another_srs_path, commitment=ezkl.PyCommitments.KZG) assert os.path.isfile(another_srs_path) diff --git a/tests/wasm/model.compiled b/tests/wasm/model.compiled index 3962b42bc5cb96dc82892d22fa81717f60a6ee51..40041e853be3a1089e68bbb5382d393e556cdff0 100644 GIT binary patch delta 14 VcmdnNyN7p!D=Q