diff --git a/Cargo.toml b/Cargo.toml index 62f3d27..9399fa6 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -28,8 +28,13 @@ criterion = "0.3" name = "arithmetic" harness = false +[[bench]] +name = "plonk" +harness = false + [dependencies] subtle = "2.2.1" crossbeam-utils = "0.7" +metrics = "0.13.0-alpha.8" num_cpus = "1.13" rand = "0.7" diff --git a/benches/plonk.rs b/benches/plonk.rs new file mode 100644 index 0000000..b92e398 --- /dev/null +++ b/benches/plonk.rs @@ -0,0 +1,281 @@ +#[macro_use] +extern crate criterion; + +extern crate halo2; +use halo2::arithmetic::Field; +use halo2::plonk::*; +use halo2::poly::commitment::Params; +use halo2::transcript::DummyHash; +use halo2::tweedle::{EqAffine, Fp, Fq}; + +use std::marker::PhantomData; + +use criterion::Criterion; + +fn bench_with_k(name: &str, k: u32, c: &mut Criterion) { + /// This represents an advice column at a certain row in the ConstraintSystem + #[derive(Copy, Clone, Debug)] + pub struct Variable(Column, usize); + + // Initialize the polynomial commitment parameters + let params: Params = Params::new::>(k); + + struct PLONKConfig { + a: Column, + b: Column, + c: Column, + + sa: Column, + sb: Column, + sc: Column, + sm: Column, + + perm: usize, + } + + trait StandardCS { + fn raw_multiply(&mut self, f: F) -> Result<(Variable, Variable, Variable), Error> + where + F: FnOnce() -> Result<(FF, FF, FF), Error>; + fn raw_add(&mut self, f: F) -> Result<(Variable, Variable, Variable), Error> + where + F: FnOnce() -> Result<(FF, FF, FF), Error>; + fn copy(&mut self, a: Variable, b: Variable) -> Result<(), Error>; + } + + struct MyCircuit { + a: Option, + k: u32, + } + + struct StandardPLONK<'a, F: Field, CS: Assignment + 'a> { + cs: &'a mut CS, + config: PLONKConfig, + current_gate: usize, + _marker: PhantomData, + } + + impl<'a, FF: Field, CS: Assignment> StandardPLONK<'a, FF, CS> { + fn new(cs: &'a mut CS, config: PLONKConfig) -> Self { + StandardPLONK { + cs, + config, + current_gate: 0, + _marker: PhantomData, + } + } + } + + impl<'a, FF: Field, CS: Assignment> StandardCS for StandardPLONK<'a, FF, CS> { + fn raw_multiply(&mut self, f: F) -> Result<(Variable, Variable, Variable), Error> + where + F: FnOnce() -> Result<(FF, FF, FF), Error>, + { + let index = self.current_gate; + self.current_gate += 1; + let mut value = None; + self.cs.assign_advice(self.config.a, index, || { + value = Some(f()?); + Ok(value.ok_or(Error::SynthesisError)?.0) + })?; + self.cs.assign_advice(self.config.b, index, || { + Ok(value.ok_or(Error::SynthesisError)?.1) + })?; + self.cs.assign_advice(self.config.c, index, || { + Ok(value.ok_or(Error::SynthesisError)?.2) + })?; + + self.cs + .assign_fixed(self.config.sa, index, || Ok(FF::zero()))?; + self.cs + .assign_fixed(self.config.sb, index, || Ok(FF::zero()))?; + self.cs + .assign_fixed(self.config.sc, index, || Ok(FF::one()))?; + self.cs + .assign_fixed(self.config.sm, index, || Ok(FF::one()))?; + Ok(( + Variable(self.config.a, index), + Variable(self.config.b, index), + Variable(self.config.c, index), + )) + } + fn raw_add(&mut self, f: F) -> Result<(Variable, Variable, Variable), Error> + where + F: FnOnce() -> Result<(FF, FF, FF), Error>, + { + let index = self.current_gate; + self.current_gate += 1; + let mut value = None; + self.cs.assign_advice(self.config.a, index, || { + value = Some(f()?); + Ok(value.ok_or(Error::SynthesisError)?.0) + })?; + self.cs.assign_advice(self.config.b, index, || { + Ok(value.ok_or(Error::SynthesisError)?.1) + })?; + self.cs.assign_advice(self.config.c, index, || { + Ok(value.ok_or(Error::SynthesisError)?.2) + })?; + + self.cs + .assign_fixed(self.config.sa, index, || Ok(FF::one()))?; + self.cs + .assign_fixed(self.config.sb, index, || Ok(FF::one()))?; + self.cs + .assign_fixed(self.config.sc, index, || Ok(FF::one()))?; + self.cs + .assign_fixed(self.config.sm, index, || Ok(FF::zero()))?; + Ok(( + Variable(self.config.a, index), + Variable(self.config.b, index), + Variable(self.config.c, index), + )) + } + fn copy(&mut self, left: Variable, right: Variable) -> Result<(), Error> { + let left_column = match left.0 { + x if x == self.config.a => 0, + x if x == self.config.b => 1, + x if x == self.config.c => 2, + _ => unreachable!(), + }; + let right_column = match right.0 { + x if x == self.config.a => 0, + x if x == self.config.b => 1, + x if x == self.config.c => 2, + _ => unreachable!(), + }; + + self.cs + .copy(self.config.perm, left_column, left.1, right_column, right.1) + } + } + + impl Circuit for MyCircuit { + type Config = PLONKConfig; + + fn configure(meta: &mut ConstraintSystem) -> PLONKConfig { + let a = meta.advice_column(); + let b = meta.advice_column(); + let c = meta.advice_column(); + + let perm = meta.permutation(&[a, b, c]); + + let sm = meta.fixed_column(); + let sa = meta.fixed_column(); + let sb = meta.fixed_column(); + let sc = meta.fixed_column(); + + meta.create_gate(|meta| { + let a = meta.query_advice(a, 0); + let b = meta.query_advice(b, 0); + let c = meta.query_advice(c, 0); + + let sa = meta.query_fixed(sa, 0); + let sb = meta.query_fixed(sb, 0); + let sc = meta.query_fixed(sc, 0); + let sm = meta.query_fixed(sm, 0); + + a.clone() * sa + b.clone() * sb + a * b * sm + (c * sc * (-F::one())) + }); + + PLONKConfig { + a, + b, + c, + sa, + sb, + sc, + sm, + perm, + } + } + + fn synthesize( + &self, + cs: &mut impl Assignment, + config: PLONKConfig, + ) -> Result<(), Error> { + let mut cs = StandardPLONK::new(cs, config); + + for _ in 0..(1 << (self.k - 1)) { + let mut a_squared = None; + let (a0, _, c0) = cs.raw_multiply(|| { + a_squared = self.a.map(|a| a.square()); + Ok(( + self.a.ok_or(Error::SynthesisError)?, + self.a.ok_or(Error::SynthesisError)?, + a_squared.ok_or(Error::SynthesisError)?, + )) + })?; + let (a1, b1, _) = cs.raw_add(|| { + let fin = a_squared.and_then(|a2| self.a.map(|a| a + a2)); + Ok(( + self.a.ok_or(Error::SynthesisError)?, + a_squared.ok_or(Error::SynthesisError)?, + fin.ok_or(Error::SynthesisError)?, + )) + })?; + cs.copy(a0, a1)?; + cs.copy(b1, c0)?; + } + + Ok(()) + } + } + + let empty_circuit: MyCircuit = MyCircuit { a: None, k }; + + // Initialize the proving key + let pk = keygen(¶ms, &empty_circuit).expect("keygen should not fail"); + + let prover_name = name.to_string() + "-prover"; + let verifier_name = name.to_string() + "-verifier"; + + c.bench_function(&prover_name, |b| { + b.iter(|| { + let circuit: MyCircuit = MyCircuit { + a: Some(Fp::random()), + k, + }; + + // Create a proof + Proof::create::, DummyHash, _>(¶ms, &pk, &circuit, &[]) + .expect("proof generation should not fail") + }); + }); + + let circuit: MyCircuit = MyCircuit { + a: Some(Fp::random()), + k, + }; + + // Create a proof + let proof = Proof::create::, DummyHash, _>(¶ms, &pk, &circuit, &[]) + .expect("proof generation should not fail"); + + c.bench_function(&verifier_name, |b| { + b.iter(|| { + let msm = params.empty_msm(); + let guard = proof + .verify::, DummyHash>(¶ms, pk.get_vk(), msm, &[]) + .unwrap(); + let msm = guard.clone().use_challenges(); + assert!(msm.eval()); + }); + }); +} + +fn criterion_benchmark(c: &mut Criterion) { + bench_with_k("plonk-k=8", 8, c); + bench_with_k("plonk-k=9", 9, c); + bench_with_k("plonk-k=10", 10, c); + bench_with_k("plonk-k=11", 11, c); + bench_with_k("plonk-k=12", 12, c); + bench_with_k("plonk-k=13", 13, c); + bench_with_k("plonk-k=14", 14, c); + bench_with_k("plonk-k=15", 15, c); + bench_with_k("plonk-k=16", 16, c); +} + +criterion_group!(benches, criterion_benchmark); +criterion_main!(benches); diff --git a/examples/performance_model.rs b/examples/performance_model.rs new file mode 100644 index 0000000..9da022e --- /dev/null +++ b/examples/performance_model.rs @@ -0,0 +1,292 @@ +use halo2::{ + arithmetic::{Curve, Field}, + model::ModelRecorder, + plonk::*, + poly::commitment::{Blind, Params}, + transcript::DummyHash, + tweedle::{EqAffine, Fp, Fq}, +}; + +use std::marker::PhantomData; + +/// This represents an advice column at a certain row in the ConstraintSystem +#[derive(Copy, Clone, Debug)] +pub struct Variable(Column, usize); + +struct PLONKConfig { + a: Column, + b: Column, + c: Column, + + sa: Column, + sb: Column, + sc: Column, + sm: Column, + sp: Column, + + perm: usize, +} + +trait StandardCS { + fn raw_multiply(&mut self, f: F) -> Result<(Variable, Variable, Variable), Error> + where + F: FnOnce() -> Result<(FF, FF, FF), Error>; + fn raw_add(&mut self, f: F) -> Result<(Variable, Variable, Variable), Error> + where + F: FnOnce() -> Result<(FF, FF, FF), Error>; + fn copy(&mut self, a: Variable, b: Variable) -> Result<(), Error>; + fn public_input(&mut self, f: F) -> Result + where + F: FnOnce() -> Result; +} + +struct MyCircuit { + a: Option, + k: u32, +} + +struct StandardPLONK<'a, F: Field, CS: Assignment + 'a> { + cs: &'a mut CS, + config: PLONKConfig, + current_gate: usize, + _marker: PhantomData, +} + +impl<'a, FF: Field, CS: Assignment> StandardPLONK<'a, FF, CS> { + fn new(cs: &'a mut CS, config: PLONKConfig) -> Self { + StandardPLONK { + cs, + config, + current_gate: 0, + _marker: PhantomData, + } + } +} + +impl<'a, FF: Field, CS: Assignment> StandardCS for StandardPLONK<'a, FF, CS> { + fn raw_multiply(&mut self, f: F) -> Result<(Variable, Variable, Variable), Error> + where + F: FnOnce() -> Result<(FF, FF, FF), Error>, + { + let index = self.current_gate; + self.current_gate += 1; + let mut value = None; + self.cs.assign_advice(self.config.a, index, || { + value = Some(f()?); + Ok(value.ok_or(Error::SynthesisError)?.0) + })?; + self.cs.assign_advice(self.config.b, index, || { + Ok(value.ok_or(Error::SynthesisError)?.1) + })?; + self.cs.assign_advice(self.config.c, index, || { + Ok(value.ok_or(Error::SynthesisError)?.2) + })?; + + self.cs + .assign_fixed(self.config.sa, index, || Ok(FF::zero()))?; + self.cs + .assign_fixed(self.config.sb, index, || Ok(FF::zero()))?; + self.cs + .assign_fixed(self.config.sc, index, || Ok(FF::one()))?; + self.cs + .assign_fixed(self.config.sm, index, || Ok(FF::one()))?; + Ok(( + Variable(self.config.a, index), + Variable(self.config.b, index), + Variable(self.config.c, index), + )) + } + fn raw_add(&mut self, f: F) -> Result<(Variable, Variable, Variable), Error> + where + F: FnOnce() -> Result<(FF, FF, FF), Error>, + { + let index = self.current_gate; + self.current_gate += 1; + let mut value = None; + self.cs.assign_advice(self.config.a, index, || { + value = Some(f()?); + Ok(value.ok_or(Error::SynthesisError)?.0) + })?; + self.cs.assign_advice(self.config.b, index, || { + Ok(value.ok_or(Error::SynthesisError)?.1) + })?; + self.cs.assign_advice(self.config.c, index, || { + Ok(value.ok_or(Error::SynthesisError)?.2) + })?; + + self.cs + .assign_fixed(self.config.sa, index, || Ok(FF::one()))?; + self.cs + .assign_fixed(self.config.sb, index, || Ok(FF::one()))?; + self.cs + .assign_fixed(self.config.sc, index, || Ok(FF::one()))?; + self.cs + .assign_fixed(self.config.sm, index, || Ok(FF::zero()))?; + Ok(( + Variable(self.config.a, index), + Variable(self.config.b, index), + Variable(self.config.c, index), + )) + } + fn copy(&mut self, left: Variable, right: Variable) -> Result<(), Error> { + let left_column = match left.0 { + x if x == self.config.a => 0, + x if x == self.config.b => 1, + x if x == self.config.c => 2, + _ => unreachable!(), + }; + let right_column = match right.0 { + x if x == self.config.a => 0, + x if x == self.config.b => 1, + x if x == self.config.c => 2, + _ => unreachable!(), + }; + + self.cs + .copy(self.config.perm, left_column, left.1, right_column, right.1) + } + fn public_input(&mut self, f: F) -> Result + where + F: FnOnce() -> Result, + { + let index = self.current_gate; + self.current_gate += 1; + self.cs.assign_advice(self.config.a, index, || f())?; + self.cs + .assign_fixed(self.config.sp, index, || Ok(FF::one()))?; + + Ok(Variable(self.config.a, index)) + } +} + +impl Circuit for MyCircuit { + type Config = PLONKConfig; + + fn configure(meta: &mut ConstraintSystem) -> PLONKConfig { + let a = meta.advice_column(); + let b = meta.advice_column(); + let c = meta.advice_column(); + let p = meta.aux_column(); + + let perm = meta.permutation(&[a, b, c]); + + let sm = meta.fixed_column(); + let sa = meta.fixed_column(); + let sb = meta.fixed_column(); + let sc = meta.fixed_column(); + let sp = meta.fixed_column(); + + meta.create_gate(|meta| { + let a = meta.query_advice(a, 0); + let b = meta.query_advice(b, 0); + let c = meta.query_advice(c, 0); + + let sa = meta.query_fixed(sa, 0); + let sb = meta.query_fixed(sb, 0); + let sc = meta.query_fixed(sc, 0); + let sm = meta.query_fixed(sm, 0); + + a.clone() * sa + b.clone() * sb + a * b * sm + (c * sc * (-F::one())) + }); + + meta.create_gate(|meta| { + let a = meta.query_advice(a, 0); + let p = meta.query_aux(p, 0); + let sp = meta.query_fixed(sp, 0); + + sp * (a + p * (-F::one())) + }); + + PLONKConfig { + a, + b, + c, + sa, + sb, + sc, + sm, + sp, + perm, + } + } + + fn synthesize(&self, cs: &mut impl Assignment, config: PLONKConfig) -> Result<(), Error> { + let mut cs = StandardPLONK::new(cs, config); + + let _ = cs.public_input(|| Ok(F::one() + F::one()))?; + + for _ in 0..((1 << (self.k - 1)) - 1) { + let mut a_squared = None; + let (a0, _, c0) = cs.raw_multiply(|| { + a_squared = self.a.map(|a| a.square()); + Ok(( + self.a.ok_or(Error::SynthesisError)?, + self.a.ok_or(Error::SynthesisError)?, + a_squared.ok_or(Error::SynthesisError)?, + )) + })?; + let (a1, b1, _) = cs.raw_add(|| { + let fin = a_squared.and_then(|a2| self.a.map(|a| a + a2)); + Ok(( + self.a.ok_or(Error::SynthesisError)?, + a_squared.ok_or(Error::SynthesisError)?, + fin.ok_or(Error::SynthesisError)?, + )) + })?; + cs.copy(a0, a1)?; + cs.copy(b1, c0)?; + } + + Ok(()) + } +} + +fn main() { + let recorder = Box::leak(Box::new(ModelRecorder::default())); + metrics::set_recorder(recorder).unwrap(); + + // TODO: Make dynamic. + let k = 11; + + // Initialize the polynomial commitment parameters + let params: Params = Params::new::>(k); + + let empty_circuit: MyCircuit = MyCircuit { a: None, k }; + + // Initialize the proving key + let pk = keygen(¶ms, &empty_circuit).expect("keygen should not fail"); + + println!("[Keygen] {}", recorder); + recorder.clear(); + + let mut pubinputs = pk.get_vk().get_domain().empty_lagrange(); + pubinputs[0] = Fp::one(); + pubinputs[0] += Fp::one(); + let pubinput = params + .commit_lagrange(&pubinputs, Blind::default()) + .to_affine(); + recorder.clear(); + + let circuit: MyCircuit = MyCircuit { + a: Some(Fp::random()), + k, + }; + + // Create a proof + let proof = + Proof::create::, DummyHash, _>(¶ms, &pk, &circuit, &[pubinputs]) + .expect("proof generation should not fail"); + + println!("[Prover] {}", recorder); + recorder.clear(); + + let pubinput_slice = &[pubinput]; + let msm = params.empty_msm(); + let guard = proof + .verify::, DummyHash>(¶ms, pk.get_vk(), msm, pubinput_slice) + .unwrap(); + let msm = guard.clone().use_challenges(); + assert!(msm.eval()); + + println!("[Verifier] {}", recorder); +} diff --git a/src/lib.rs b/src/lib.rs index 49441e8..c20d88d 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -18,3 +18,5 @@ pub mod plonk; pub mod poly; pub mod transcript; pub mod tweedle; + +pub mod model; diff --git a/src/model.rs b/src/model.rs new file mode 100644 index 0000000..1bbdc8c --- /dev/null +++ b/src/model.rs @@ -0,0 +1,111 @@ +//! Helpers for modelling halo2 circuit performance. + +use std::cell::RefCell; +use std::collections::HashMap; +use std::fmt; +use std::sync::Arc; + +use metrics::{Key, Recorder, Unit}; + +/// A [`metrics`] recorder for examining halo2 metrics. +/// +/// # Examples +/// +/// ``` +/// use halo2::model::ModelRecorder; +/// +/// let recorder = Box::leak(Box::new(ModelRecorder::default())); +/// metrics::set_recorder(recorder).unwrap(); +/// +/// // Create circuit, build and/or verify proof. +/// +/// println!("{}", recorder); +/// recorder.clear(); +/// +/// // Perform another operation to collect separate metrics. +/// ``` +#[derive(Debug)] +pub struct ModelRecorder { + counters: Arc>>, +} + +impl Default for ModelRecorder { + fn default() -> Self { + ModelRecorder { + counters: Default::default(), + } + } +} + +impl fmt::Display for ModelRecorder { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + let mut counters = self + .counters + .try_borrow() + .unwrap() + .iter() + .map(|(k, v)| (k.clone(), *v)) + .collect::>(); + + counters.sort_by(|(k1, _), (k2, _)| { + let key1 = ( + k1.name(), + k1.labels() + .map(|l| (l.key(), l.value())) + .collect::>(), + ); + let key2 = ( + k2.name(), + k2.labels() + .map(|l| (l.key(), l.value())) + .collect::>(), + ); + key1.cmp(&key2) + }); + + writeln!(f, "Recorded metrics:")?; + for (key, value) in counters.iter() { + writeln!(f, "- {}: {}", key, value)?; + } + Ok(()) + } +} + +impl Recorder for ModelRecorder { + fn register_counter(&self, _key: Key, _unit: Option, _description: Option<&'static str>) { + } + + fn register_gauge(&self, _key: Key, _unit: Option, _description: Option<&'static str>) {} + + fn register_histogram( + &self, + _key: Key, + _unit: Option, + _description: Option<&'static str>, + ) { + } + + fn increment_counter(&self, key: Key, value: u64) { + *self + .counters + .try_borrow_mut() + .unwrap() + .entry(key) + .or_default() += value; + } + + fn update_gauge(&self, _key: Key, _value: f64) { + unimplemented!() + } + + fn record_histogram(&self, _key: Key, _value: u64) { + unimplemented!() + } +} + +impl ModelRecorder { + /// Clear all recorded metrics. + pub fn clear(&self) { + self.counters.try_borrow_mut().unwrap().clear(); + } +} diff --git a/src/plonk/prover.rs b/src/plonk/prover.rs index 54c15f3..c3a291e 100644 --- a/src/plonk/prover.rs +++ b/src/plonk/prover.rs @@ -103,6 +103,7 @@ impl Proof { C::Projective::batch_to_affine(&aux_commitments_projective, &mut aux_commitments); let aux_commitments = aux_commitments; drop(aux_commitments_projective); + metrics::counter!("aux_commitments", aux_commitments.len() as u64); for commitment in &aux_commitments { transcript @@ -143,6 +144,7 @@ impl Proof { C::Projective::batch_to_affine(&advice_commitments_projective, &mut advice_commitments); let advice_commitments = advice_commitments; drop(advice_commitments_projective); + metrics::counter!("advice_commitments", advice_commitments.len() as u64); for commitment in &advice_commitments { transcript diff --git a/src/poly/commitment.rs b/src/poly/commitment.rs index cc30ee2..dec70c8 100644 --- a/src/poly/commitment.rs +++ b/src/poly/commitment.rs @@ -124,6 +124,7 @@ impl Params { poly: &Polynomial, r: Blind, ) -> C::Projective { + metrics::increment!("multiexp", "size" => format!("{}", poly.len() + 1), "fn" => "commit"); let mut tmp_scalars = Vec::with_capacity(poly.len() + 1); let mut tmp_bases = Vec::with_capacity(poly.len() + 1); @@ -144,6 +145,7 @@ impl Params { poly: &Polynomial, r: Blind, ) -> C::Projective { + metrics::increment!("multiexp", "size" => format!("{}", poly.len() + 1), "fn" => "commit_lagrange"); let mut tmp_scalars = Vec::with_capacity(poly.len() + 1); let mut tmp_bases = Vec::with_capacity(poly.len() + 1); diff --git a/src/poly/commitment/msm.rs b/src/poly/commitment/msm.rs index 42e6b87..08c0914 100644 --- a/src/poly/commitment/msm.rs +++ b/src/poly/commitment/msm.rs @@ -106,6 +106,7 @@ impl<'a, C: CurveAffine> MSM<'a, C> { assert_eq!(scalars.len(), len); + metrics::increment!("multiexp", "size" => format!("{}", len), "fn" => "MSM::eval"); bool::from(best_multiexp(&scalars, &bases).is_zero()) } } diff --git a/src/poly/commitment/prover.rs b/src/poly/commitment/prover.rs index 8b87e05..52847b9 100644 --- a/src/poly/commitment/prover.rs +++ b/src/poly/commitment/prover.rs @@ -78,12 +78,14 @@ impl Proof { // // TODO: If we modify multiexp to take "extra" bases, we could speed // this piece up a bit by combining the multiexps. + metrics::counter!("multiexp", 2, "val" => "l/r", "size" => format!("{}", half)); let l = best_multiexp(&a[0..half], &g[half..]); let r = best_multiexp(&a[half..], &g[0..half]); let value_l = compute_inner_product(&a[0..half], &b[half..]); let value_r = compute_inner_product(&a[half..], &b[0..half]); let mut l_randomness = C::Scalar::random(); let r_randomness = C::Scalar::random(); + metrics::counter!("multiexp", 2, "val" => "l/r", "size" => "2"); let l = l + &best_multiexp(&[value_l, l_randomness], &[u, params.h]); let r = r + &best_multiexp(&[value_r, r_randomness], &[u, params.h]); let mut l = l.to_affine(); @@ -173,6 +175,7 @@ impl Proof { let d = C::Scalar::random(); let s = C::Scalar::random(); + metrics::increment!("multiexp", "val" => "delta", "size" => "3"); let delta = best_multiexp(&[d, d * &b, s], &[g, u, params.h]).to_affine(); // Feed delta into the transcript @@ -204,6 +207,7 @@ fn parallel_generator_collapse( ) { let len = g.len() / 2; let (mut g_lo, g_hi) = g.split_at_mut(len); + metrics::counter!("multiexp", len as u64, "size" => "2", "fn" => "parallel_generator_collapse"); parallelize(&mut g_lo, |g_lo, start| { let g_hi = &g_hi[start..]; diff --git a/src/poly/commitment/verifier.rs b/src/poly/commitment/verifier.rs index e6552f1..02ed4d8 100644 --- a/src/poly/commitment/verifier.rs +++ b/src/poly/commitment/verifier.rs @@ -55,6 +55,7 @@ impl<'a, C: CurveAffine> Guard<'a, C> { pub fn compute_g(&self) -> C { let s = compute_s(&self.challenges_sq, self.allinv); + metrics::increment!("multiexp", "size" => format!("{}", s.len()), "fn" => "compute_g"); let mut tmp = best_multiexp(&s, &self.msm.params.g); tmp += self.msm.params.h; tmp.to_affine() diff --git a/src/poly/domain.rs b/src/poly/domain.rs index 6cc82f5..d336818 100644 --- a/src/poly/domain.rs +++ b/src/poly/domain.rs @@ -203,6 +203,7 @@ impl EvaluationDomain { assert_eq!(a.values.len(), 1 << self.k); // Perform inverse FFT to obtain the polynomial in coefficient form + metrics::increment!("ifft", "size" => format!("{}", a.len()), "fn" => "lagrange_to_coeff"); Self::ifft(&mut a.values, self.omega_inv, self.k, self.ifft_divisor); Polynomial { @@ -237,6 +238,7 @@ impl EvaluationDomain { Self::distribute_powers(&mut a.values, g); } a.values.resize(self.extended_len(), G::group_zero()); + metrics::increment!("fft", "size" => format!("{}", self.extended_len()), "fn" => "coeff_to_extended"); best_fft(&mut a.values, self.extended_omega, self.extended_k); Polynomial { @@ -255,6 +257,7 @@ impl EvaluationDomain { assert_eq!(a.values.len(), self.extended_len()); // Inverse FFT + metrics::increment!("ifft", "size" => format!("{}", a.len()), "fn" => "extended_to_coeff"); Self::ifft( &mut a.values, self.extended_omega_inv,