Add IPA commitment scheme and the respective circuit verifier gadget (#72)

* Add IPA commitment native implementation

* Add IPA Gadget verifier

* polish Pedersen & IPA, add blind bool param to IPA

* Optimize IPA gadget constraints (and native):

- optimize <s,b> computation from linear to log time
- optimize s computation from k*2^k to k*(2^k)/2

* add small optimization: delegate u_i^-1 to prover and just check u_i*u_i^-1==1 in verifier circuit

* IPA polish and document

* Add 'BLIND' parameter to CommitmentProver trait (and to Pedersen and KZG impls). Fit IPA into CommitmentProver trait.

* rename 'BLIND' to 'H' (hiding) in commitment

* IPA: rm u_invs from Proof and compute them incircuit

* Update IPA's build_s & gadget to use Halo2 approach following @han0110 's suggestion.

This reduced further the amount of constraints needed.
- for k=4: -9k constraints (-7%)
- for k=8: -473k constr (-31%)
- for k=9: -1123k constr (-35%)
- for k=10: -2578k constr (-39%)
And now IPA verification (without amortizing) is very close to Pedersen
verification (in-circuits).

* rm dbg!(cs.num_constraints()) from multiple tests

* IPA::prove remove intermediate v_lo,v_hi vectors, add doc to build_s_gadget

* move powers_of into utils/mod.rs, update iters to cfg_iter
This commit is contained in:
2024-03-01 09:52:07 +01:00
committed by GitHub
parent 9159c5c84c
commit b25037e34c
18 changed files with 796 additions and 96 deletions

View File

@@ -46,7 +46,7 @@ impl<C: CurveGroup> CCS<C> {
) -> Result<(LCCCS<C>, Witness<C::ScalarField>), Error> {
let w: Vec<C::ScalarField> = z[(1 + self.l)..].to_vec();
let r_w = C::ScalarField::rand(rng);
let C = Pedersen::commit(pedersen_params, &w, &r_w)?;
let C = Pedersen::<C>::commit(pedersen_params, &w, &r_w)?;
let r_x: Vec<C::ScalarField> = (0..self.s).map(|_| C::ScalarField::rand(rng)).collect();
let v = self.compute_v_j(z, &r_x);
@@ -96,8 +96,8 @@ impl<C: CurveGroup> LCCCS<C> {
w: &Witness<C::ScalarField>,
) -> Result<(), Error> {
// check that C is the commitment of w. Notice that this is not verifying a Pedersen
// opening, but checking that the commitment comes from committing to the witness.
if self.C != Pedersen::commit(pedersen_params, &w.w, &w.r_w)? {
// opening, but checking that the Commmitment comes from committing to the witness.
if self.C != Pedersen::<C>::commit(pedersen_params, &w.w, &w.r_w)? {
return Err(Error::NotSatisfied);
}