Skip to content

Commit

Permalink
Merge pull request privacy-scaling-explorations#149 from input-output…
Browse files Browse the repository at this point in the history
…-hk/dev-benchmark/recursive-open-ipa

Add Goldenfile + Criterion benchmark for recursive IPA commitment opening
  • Loading branch information
b13decker committed Mar 20, 2024
2 parents 565e706 + 3bce37e commit bc3f00a
Show file tree
Hide file tree
Showing 6 changed files with 361 additions and 76 deletions.
4 changes: 4 additions & 0 deletions halo2_gadgets/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -92,3 +92,7 @@ harness = false
[[bench]]
name = "plonk"
harness = false

[[bench]]
name = "ipa_recursive_commitment"
harness = false
242 changes: 242 additions & 0 deletions halo2_gadgets/benches/ipa_recursive_commitment.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,242 @@
mod ecc_circuits;
mod utilities;

use std::{iter::repeat_with, marker::PhantomData, time::Duration};

use criterion::{criterion_group, criterion_main, Criterion};
use group::Curve;

use halo2_proofs::{
arithmetic::eval_polynomial,
circuit::{floor_planner::V1, Chip},
generate_default_duplex_domain,
plonk::Circuit,
poly::{
commitment::{Blind, ParamsProver},
ipa::commitment::{create_proof, ParamsIPA},
Coeff, EvaluationDomain, Polynomial,
},
transcript::{
poseidon::PoseidonWriteBaseFitsInScalarP128Pow5T3, EncodedChallenge, Transcript,
TranscriptWrite, TranscriptWriterBuffer,
},
};
use rand::thread_rng;

use halo2_proofs::{
circuit::{Layouter, Value},
plonk::{ConstraintSystem, Error},
poseidon::{duplex::DuplexDomain, P128Pow5T3},
};
use halo2curves::{pasta, CurveAffine};
use std::{fmt::Debug, io::Read};
use utilities::bench_circuit;

use halo2_gadgets::{
ecc::{
chip::{BaseFieldElem, FixedPoint, FullScalar, ShortScalar},
EccInstructions, FixedPoints,
},
recursive_chip::DefaultRecursiveChip as RecursiveChip,
recursive_circuits::ipa,
transcript::{TranscriptInstructions, TranscriptReadInstructions},
};

use ecc_circuits::fixed_points::TestFixedBases;

#[derive(Debug, Clone)]
struct MyCircuit<FP, D, const L: usize, R: Clone> {
params: ParamsIPA<C>,
proof: Value<R>,
evaluation: Value<<C as CurveAffine>::ScalarExt>,

_marker: PhantomData<(FP, D)>,
}

#[allow(deprecated)] // Allow final absorb in `duplex_pattern`
mod poseidon_patterns {
use super::*;

pub const K: u32 = 10;

// Generated using `commit_open_pattern(10)`
generate_default_duplex_domain!(
domain,
IpaCommitOpenDomain,
F::ZERO,
25,
DuplexPatternBuilder::new()
// Initialization: commitment and challenge
.absorb(2)
.squeeze(1)
// Open commitment
.absorb(2)
.squeeze(2)
.absorb(4)
.squeeze(1)
.absorb(4)
.squeeze(1)
.absorb(4)
.squeeze(1)
.absorb(4)
.squeeze(1)
.absorb(4)
.squeeze(1)
.absorb(4)
.squeeze(1)
.absorb(4)
.squeeze(1)
.absorb(4)
.squeeze(1)
.absorb(4)
.squeeze(1)
.absorb(4)
.squeeze(1)
.absorb(4)
.build()
);
}

use poseidon_patterns::{IpaCommitOpenDomain, K};

type C = pasta::pallas::Affine; // Limitation of `EccChip` (will be generalized later)

impl<FP, D, const L: usize, R> Circuit<<C as CurveAffine>::Base> for MyCircuit<FP, D, L, R>
where
FP: FixedPoints<C>,
<FP as FixedPoints<C>>::FullScalar: FixedPoint<C>,
<FP as FixedPoints<C>>::Base: FixedPoint<C, FixedScalarKind = BaseFieldElem>,
<FP as FixedPoints<C>>::FullScalar: FixedPoint<C, FixedScalarKind = FullScalar>,
<FP as FixedPoints<C>>::ShortScalar: FixedPoint<C, FixedScalarKind = ShortScalar>,
D: DuplexDomain<<C as CurveAffine>::Base, { P128Pow5T3::RATE }, L>,
R: Read + Debug + Clone,
{
type Config = <RecursiveChip<FP, D, R, L> as Chip<<C as CurveAffine>::Base>>::Config;
type FloorPlanner = V1;
#[cfg(feature = "circuit-params")]
type Params = ();

fn without_witnesses(&self) -> Self {
Self {
params: self.params.clone(),
_marker: PhantomData,
proof: Value::unknown(),
evaluation: Value::unknown(),
}
}

fn configure(meta: &mut ConstraintSystem<<C as CurveAffine>::Base>) -> Self::Config {
let advice: [_; 10] = repeat_with(|| meta.advice_column())
.take(10)
.collect::<Vec<_>>()
.try_into()
.unwrap();
let fixed: [_; 8] = repeat_with(|| meta.fixed_column())
.take(8)
.collect::<Vec<_>>()
.try_into()
.unwrap();
let instance = [meta.instance_column()];
let lookup = meta.lookup_table_column();

RecursiveChip::configure(meta, advice, fixed, instance, lookup)
}

fn synthesize(
&self,
config: Self::Config,
mut layouter: impl Layouter<<C as CurveAffine>::Base>,
) -> Result<(), Error> {
let mut chip = RecursiveChip::init(
layouter.namespace(|| "init recursive chip"),
config,
self.proof.clone(),
)?;

let commitment = chip.read_point(layouter.namespace(|| "commitment"))?;
let x = chip.squeeze_challenge(layouter.namespace(|| "challenge"))?;

// `v` is the evaluation you expect: depends on the challenge but we pre-computed out
// of circuit and can just pass it in
let v = chip.witness_scalar_var(&mut layouter, self.evaluation)?;

ipa::commitment::verify(chip, layouter, &self.params, commitment, x, v)?;
Ok(())
}
}

fn random_polynomial<F: ff::WithSmallOrderMulGroup<3>, R: rand::Rng>(
domain: &EvaluationDomain<F>,
mut rng: R,
) -> Polynomial<F, Coeff> {
domain.coeff_from_vec(
std::iter::repeat_with(|| F::random(&mut rng))
.take(1 << domain.k() as usize)
.collect(),
)
}

fn bench_recursive_ipa_commit(c: &mut Criterion) {
let params = ParamsIPA::new(K);
let mut rng = thread_rng();

let domain = EvaluationDomain::<<C as CurveAffine>::ScalarExt>::new(1, K);

// Randomly choose a polynomial to commit to/open
let polynomial = random_polynomial(&domain, &mut rng);
let blind = Blind::new(&mut rng);

let commitment: <C as CurveAffine>::CurveExt = params.commit(&polynomial, blind);
// Create commitment opening proof to verify
let (proof, evaluation) = {
let mut transcript_write = PoseidonWriteBaseFitsInScalarP128Pow5T3::<
_,
_,
IpaCommitOpenDomain<_>,
{ IpaCommitOpenDomain::<<C as CurveAffine>::Base>::L },
>::init(vec![]);

transcript_write
.write_point(commitment.to_affine())
.expect("transcript write failed");
let challenge_scalar = transcript_write.squeeze_challenge().get_scalar();

let evaluation = eval_polynomial(&polynomial, challenge_scalar);

create_proof(
&params,
rng,
&mut transcript_write,
&polynomial,
blind,
challenge_scalar,
)
.expect("proof generation failed");

let proof = transcript_write.finalize();
(std::io::Cursor::new(proof), evaluation)
};

let circuit = MyCircuit {
params,
proof: Value::known(proof),
evaluation: Value::known(evaluation),
_marker: PhantomData::<(TestFixedBases<C>, IpaCommitOpenDomain<_>)>,
};

bench_circuit::<pasta::vesta::Affine>(
c,
13,
"IPA recursive commitment opening: degree 2^10",
&[&[]],
circuit,
);
}

criterion_group! {
name = benches;
config = Criterion::default().sample_size(10).measurement_time(Duration::from_secs(20));
targets = bench_recursive_ipa_commit,
}

criterion_main!(benches);
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
max_deg,advice_columns,lookups,permutations,column_queries,point_sets,proof_size
16,10,3,15,85,5,6464
2 changes: 1 addition & 1 deletion halo2_gadgets/src/recursive_circuits.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
//! Implementation of recrusive verification circuit subroutines

mod ipa;
pub mod ipa;
mod plonk;
mod recursive_gadgets;
mod utils;
Expand Down
Loading

0 comments on commit bc3f00a

Please sign in to comment.