Content-Length: 619787 | pFad | http://github.com/a16z/jolt/pull/431/commits/4ab444d56edb52cb2fac6d4387f42f65f41aff38

C7 WIP: HyperKZG verifier circuit by imikushin · Pull Request #431 · a16z/jolt · GitHub
Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

WIP: HyperKZG verifier circuit #431

Draft
wants to merge 46 commits into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
46 commits
Select commit Hold shift + click to select a range
610cac0
HyperKZG verifier circuit: get started
imikushin Jul 12, 2024
39c14de
WIP: HyperKZGVerifierGadget
imikushin Jul 25, 2024
d948df5
WIP: PairingGadget
imikushin Jul 28, 2024
2143514
WIP: PairingGadget: it compiles!
imikushin Jul 29, 2024
9931385
WIP: PairingGadget: test circuit compiles and runs (extremely slowly)
imikushin Jul 29, 2024
d2f7171
print out the number of constraints as they get synthesized
imikushin Jul 29, 2024
925c4ec
ignore the heavy test
imikushin Jul 29, 2024
a73c445
WIP: DelayedPairingCircuit
imikushin Aug 2, 2024
2f495c0
WIP: DelayedPairingCircuit
imikushin Aug 3, 2024
8e6b3d4
WIP: LoadedSNARK
imikushin Aug 3, 2024
5fa5e48
WIP: LoadedSNARK
imikushin Aug 3, 2024
f1ed212
WIP: LoadedSNARK trait
imikushin Aug 3, 2024
f1e7f39
WIP: LoadedSNARK trait
imikushin Aug 4, 2024
3f4313e
OffloadedSNARK trait
imikushin Aug 4, 2024
ab84dca
WIP: implement OffloadedSNARK trait for a demo circuit
imikushin Aug 4, 2024
3bd319f
Offloaded circuit successfully verifies
imikushin Aug 5, 2024
18b9886
Offloaded SNARK takes shape
imikushin Aug 7, 2024
6a5aa97
OffloadedSNARK: move to module `snark`
imikushin Aug 7, 2024
2020be1
OffloadedSNARK: cleanup
imikushin Aug 7, 2024
b940345
OffloadedSNARK: OffloadedMSM gadget
imikushin Aug 8, 2024
8d305c8
OffloadedSNARK: OffloadedMSM gadget works
imikushin Aug 9, 2024
517c865
WIP: HyperKZG gadget
imikushin Aug 10, 2024
9579c31
WIP: HyperKZG gadget
imikushin Aug 11, 2024
b045294
MockSponge
imikushin Aug 11, 2024
b64d33a
Fix point assignment
imikushin Aug 11, 2024
715349b
Return public input vector based on expected result
imikushin Aug 11, 2024
ee33022
WIP: HyperKZG gadget
imikushin Aug 14, 2024
e6b81ae
WIP: HyperKZG gadget
imikushin Aug 14, 2024
f988dde
WIP: HyperKZG gadget: adjust type parameters in OffloadedDataCircuit
imikushin Aug 14, 2024
23b474f
WIP: HyperKZG gadget: factor out MSMGadget trait
imikushin Aug 14, 2024
395c891
WIP: HyperKZG gadget: prep to use OffloadedMSMGadget
imikushin Aug 14, 2024
b475d84
WIP: HyperKZG verifier test: migrate to OffloadedSNARK
imikushin Aug 14, 2024
3433150
WIP: HyperKZG verifier: the only thing left is the pairing
imikushin Aug 15, 2024
f421225
WIP: HyperKZG verifier: remove some debugging statements
imikushin Aug 15, 2024
31e87a4
WIP: HyperKZG verifier: add G2 elements to OffloadSNARKVerifyingKey
imikushin Aug 16, 2024
4ab444d
WIP: HyperKZG verifier: make pairings work
imikushin Aug 18, 2024
b7e983a
WIP: HyperKZG verifier: offload pairings data
imikushin Aug 19, 2024
70a65c3
HyperKZG verifier works with offloaded data
imikushin Aug 20, 2024
678b04d
Remove unneeded code
imikushin Aug 20, 2024
ae0e9cf
Cleanup warnings
imikushin Aug 21, 2024
2cedc18
Merge branch 'main' into hyperkzg-circuit
imikushin Aug 21, 2024
486cd61
Merge branch 'main' into hyperkzg-circuit
imikushin Aug 21, 2024
6565391
Cleanup lints
imikushin Aug 21, 2024
2904552
Remove commented out code
imikushin Aug 21, 2024
c9aa0e9
Port transcript changes
imikushin Aug 21, 2024
8bb1a29
Port transcript changes: make it work
imikushin Aug 21, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
WIP: HyperKZG verifier: make pairings work
  • Loading branch information
imikushin committed Aug 18, 2024
commit 4ab444d56edb52cb2fac6d4387f42f65f41aff38
13 changes: 3 additions & 10 deletions jolt-core/src/circuits/groups/curves/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -121,16 +121,9 @@ mod tests {
{
type Circuit = DelayedOpsCircuit<E, G1Var>;

fn offloaded_setup(
circuit: Self::Circuit,
snark_vk: S::ProcessedVerifyingKey,
) -> Result<OffloadedSNARKVerifyingKey<E, S>, OffloadedSNARKError<S::Error>> {
Ok(OffloadedSNARKVerifyingKey {
snark_pvk: snark_vk,
delayed_pairings: vec![], // TODO none yet
g2_elements: vec![],
})
}
// fn pairing_setup(circuit: Self::Circuit) -> Vec<Vec<E::G2Affine>> {
// vec![]
// }
}

#[test]
Expand Down
138 changes: 129 additions & 9 deletions jolt-core/src/circuits/offloaded/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,15 +3,32 @@ use ark_ec::pairing::Pairing;
use ark_ec::{CurveGroup, VariableBaseMSM};
use ark_ff::{One, PrimeField};
use ark_r1cs_std::alloc::AllocVar;
use ark_r1cs_std::boolean::Boolean;
use ark_r1cs_std::eq::EqGadget;
use ark_r1cs_std::fields::fp::FpVar;
use ark_r1cs_std::fields::FieldVar;
use ark_r1cs_std::groups::CurveVar;
use ark_r1cs_std::{R1CSVar, ToConstraintFieldGadget};
use ark_relations::ns;
use ark_relations::r1cs::{ConstraintSystemRef, Namespace, SynthesisError};
use ark_serialize::Valid;
use ark_std::Zero;
use std::marker::PhantomData;

pub trait MSMGadget<FVar, G, GVar>
where
FVar: FieldVar<G::ScalarField, G::ScalarField> + ToConstraintFieldGadget<G::ScalarField>,
G: CurveGroup,
GVar: CurveVar<G, G::ScalarField> + ToConstraintFieldGadget<G::ScalarField>,
{
fn msm(
&self,
cs: impl Into<Namespace<G::ScalarField>>,
g1s: &[GVar],
scalars: &[FVar],
) -> Result<GVar, SynthesisError>;
}

pub struct OffloadedMSMGadget<'a, FVar, G, GVar, Circuit>
where
Circuit: OffloadedDataCircuit<G>,
Expand Down Expand Up @@ -98,10 +115,13 @@ where
scalar_input.enforce_equal(&x)?;
}

let mut offsets = vec![];

// write g1s to public_input
for g1 in g1s {
let f_vec = g1.to_constraint_field()?;

offsets.push(cs.num_instance_variables() - 1);
for f in f_vec.iter() {
let f_input = FpVar::new_input(ns!(cs, "g1s"), || f.value())?;
f_input.enforce_equal(f)?;
Expand All @@ -110,8 +130,10 @@ where

// write msm_g1 to public_input
{
dbg!(cs.num_instance_variables() - 1);
let f_vec = msm_g1_var.to_constraint_field()?;

offsets.push(cs.num_instance_variables() - 1);
for f in f_vec.iter() {
let f_input = FpVar::new_input(ns!(cs, "msm_g1"), || f.value())?;
f_input.enforce_equal(f)?;
Expand All @@ -120,7 +142,7 @@ where
dbg!(cs.num_constraints());
dbg!(cs.num_instance_variables());

Ok(full_msm_value)
Ok((full_msm_value, offsets))
})
};
dbg!(cs.num_constraints());
Expand All @@ -129,16 +151,114 @@ where
}
}

pub trait MSMGadget<FVar, G, GVar>
pub trait PairingGadget<E, G1Var>
where
FVar: FieldVar<G::ScalarField, G::ScalarField> + ToConstraintFieldGadget<G::ScalarField>,
G: CurveGroup,
GVar: CurveVar<G, G::ScalarField> + ToConstraintFieldGadget<G::ScalarField>,
E: Pairing,
G1Var: CurveVar<E::G1, E::ScalarField> + ToConstraintFieldGadget<E::ScalarField>,
{
fn msm(
fn multi_pairing_is_zero(
&self,
cs: impl Into<Namespace<G::ScalarField>>,
cs: impl Into<Namespace<E::ScalarField>>,
g1s: &[G1Var],
g2s: &[E::G2Affine],
) -> Result<(), SynthesisError>;
}

pub struct OffloadedPairingGadget<'a, E, FVar, GVar, Circuit>
where
E: Pairing,
Circuit: OffloadedDataCircuit<E::G1>,
FVar: FieldVar<E::ScalarField, E::ScalarField> + ToConstraintFieldGadget<E::ScalarField>,
GVar: CurveVar<E::G1, E::ScalarField> + ToConstraintFieldGadget<E::ScalarField>,
{
_params: PhantomData<(E, FVar, GVar)>,
circuit: &'a Circuit,
}

impl<'a, E, FVar, GVar, Circuit> OffloadedPairingGadget<'a, E, FVar, GVar, Circuit>
where
E: Pairing,
Circuit: OffloadedDataCircuit<E::G1>,
FVar: FieldVar<E::ScalarField, E::ScalarField> + ToConstraintFieldGadget<E::ScalarField>,
GVar: CurveVar<E::G1, E::ScalarField> + ToConstraintFieldGadget<E::ScalarField>,
{
pub(crate) fn new(circuit: &'a Circuit) -> Self {
Self {
_params: PhantomData,
circuit,
}
}
}

impl<'a, E, FVar, GVar, Circuit> PairingGadget<E, GVar>
for OffloadedPairingGadget<'a, E, FVar, GVar, Circuit>
where
E: Pairing,
Circuit: OffloadedDataCircuit<E::G1>,
FVar: FieldVar<E::ScalarField, E::ScalarField> + ToConstraintFieldGadget<E::ScalarField>,
GVar: CurveVar<E::G1, E::ScalarField> + ToConstraintFieldGadget<E::ScalarField>,
{
fn multi_pairing_is_zero(
&self,
cs: impl Into<Namespace<E::ScalarField>>,
g1s: &[GVar],
scalars: &[FVar],
) -> Result<GVar, SynthesisError>;
g2s: &[E::G2Affine],
) -> Result<(), SynthesisError> {
let ns = cs.into();
let cs = ns.cs();

let g1_values_opt = g1s
.iter()
.map(|g1| g1.value().ok())
.collect::<Option<Vec<_>>>();

let g2_values = g2s;

let is_zero_opt =
g1_values_opt.map(|g1_values| E::multi_pairing(dbg!(&g1_values), g2_values).is_zero());
if let Some(false) = is_zero_opt {
dbg!("multi_pairing_is_zero: false");
return Err(SynthesisError::Unsatisfiable);
}

// {
// let g1s = g1s.to_vec();
// let ns = ns!(cs, "deferred_pairing");
// let cs = ns.cs();
//
// self.circuit.defer_msm(move || {
// let mut offsets = vec![];
//
// // write g1s to public_input
// for g1 in g1s {
// let f_vec = g1.to_constraint_field()?;
//
// offsets.push(cs.num_instance_variables() - 1);
// for f in f_vec.iter() {
// let f_input = FpVar::new_input(ns!(cs, "g1s"), || f.value())?;
// f_input.enforce_equal(f)?;
// }
// }
//
// // write g2s to public_input
// for g2 in g2s {
// let f_vec = g2.to_constraint_field()?;
//
// offsets.push(cs.num_instance_variables() - 1);
// for f in f_vec.iter() {
// let f_input = FpVar::new_input(ns!(cs, "g2s"), || f.value())?;
// f_input.enforce_equal(f)?;
// }
// }
//
// dbg!(cs.num_constraints());
// dbg!(cs.num_instance_variables());
//
// Ok(())
// })
// }

dbg!("multi_pairing_is_zero: success");
Ok(())
}
}
92 changes: 54 additions & 38 deletions jolt-core/src/circuits/poly/commitment/hyperkzg.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
use crate::circuits::offloaded::{MSMGadget, OffloadedMSMGadget};
use crate::circuits::offloaded::{
MSMGadget, OffloadedMSMGadget, OffloadedPairingGadget, PairingGadget,
};
use crate::circuits::poly::commitment::commitment_scheme::CommitmentVerifierGadget;
use crate::circuits::transcript::ImplAbsorb;
use crate::field::JoltField;
Expand Down Expand Up @@ -129,6 +131,7 @@ where
{
_params: PhantomData<(E, S, G1Var)>,
circuit: &'a Circuit,
g2_elements: Vec<E::G2Affine>,
}

impl<'a, E, S, G1Var, Circuit> HyperKZGVerifierGadget<'a, E, S, G1Var, Circuit>
Expand All @@ -138,10 +141,11 @@ where
G1Var: CurveVar<E::G1, E::ScalarField> + ToConstraintFieldGadget<E::ScalarField>,
Circuit: OffloadedDataCircuit<E::G1>,
{
pub fn new(circuit: &'a Circuit) -> Self {
pub fn new(circuit: &'a Circuit, g2_elements: Vec<E::G2Affine>) -> Self {
Self {
_params: PhantomData,
circuit,
g2_elements,
}
}
}
Expand Down Expand Up @@ -187,6 +191,8 @@ where
.next()
.unwrap();

dbg!(r.value());

let u = vec![r.clone(), r.negate()?, r.clone() * &r];

let com = [vec![c.clone()], com.clone()].concat();
Expand Down Expand Up @@ -215,22 +221,25 @@ where

// kzg_verify_batch

transcript.absorb(&v.iter().flatten().cloned().collect::<Vec<_>>())?;
let q_powers = q_powers::<E, S>(transcript, ell)?;

transcript.absorb(
&proof
.w
.iter()
.map(|g| ImplAbsorb::wrap(g))
&v.iter()
.flatten()
.map(|v_ij| ImplAbsorb::wrap(v_ij))
.collect::<Vec<_>>(),
)?;
let q_powers = q_powers::<E, S>(transcript, ell)?;

dbg!(q_powers.value());

transcript.absorb(&w.iter().map(|g| ImplAbsorb::wrap(g)).collect::<Vec<_>>())?;
let d = transcript
.squeeze_field_elements(1)?
.into_iter()
.next()
.unwrap();

dbg!(d.value());

let d_square = d.square()?;
let q_power_multiplier = one + &d + &d_square;
let q_powers_multiplied = q_powers
Expand All @@ -250,9 +259,11 @@ where
.collect::<Vec<_>>();

let msm_gadget = OffloadedMSMGadget::<FpVar<F>, E::G1, G1Var, Circuit>::new(self.circuit);
let pairing_gadget =
OffloadedPairingGadget::<E, FpVar<F>, G1Var, Circuit>::new(self.circuit);

let g1s = &[com.as_slice(), w.as_slice(), &[g1.clone()]].concat();
let scalars = &[
let l_g1s = &[com.as_slice(), w.as_slice(), &[g1.clone()]].concat();
let l_scalars = &[
q_powers_multiplied.as_slice(),
&[
u[0].clone(),
Expand All @@ -262,17 +273,29 @@ where
],
]
.concat();
debug_assert_eq!(l_g1s.len(), l_scalars.len());

let l_g1 = msm_gadget.msm(ns!(transcript.cs(), "l_g1"), g1s, scalars)?;
dbg!(transcript.cs().num_instance_variables() - 1);
let l_g1 = msm_gadget.msm(ns!(transcript.cs(), "l_g1"), l_g1s, l_scalars)?;

let g1s = w.as_slice();
let scalars = &[FpVar::one(), d, d_square];
debug_assert_eq!(g1s.len(), scalars.len());
dbg!(w.as_slice().value());

let r_g1 = msm_gadget.msm(ns!(transcript.cs(), "r_g1"), g1s, scalars)?;
let r_g1s = w.as_slice();
let r_scalars = &[FpVar::one().negate()?, d.negate()?, d_square.negate()?];
debug_assert_eq!(r_g1s.len(), r_scalars.len());

dbg!(transcript.cs().num_instance_variables() - 1);
let r_g1 = msm_gadget.msm(ns!(transcript.cs(), "r_g1"), r_g1s, r_scalars)?;

// (dbg!(l_g1.value()), dbg!(r_g1.value()));

pairing_gadget.multi_pairing_is_zero(
ns!(transcript.cs(), "multi_pairing"),
&[l_g1, r_g1],
self.g2_elements.as_slice(),
)?;
dbg!();

// TODO implement
Ok(Boolean::TRUE)
}
}
Expand Down Expand Up @@ -311,8 +334,8 @@ mod tests {
use crate::poly::commitment::kzg::KZGVerifierKey;
use crate::poly::dense_mlpoly::DensePolynomial;
use crate::snark::{
DeferredFnsRef, OffloadedDataCircuit, OffloadedSNARK, OffloadedSNARKError,
OffloadedSNARKVerifyingKey,
DeferredFnsRef, OffloadedDataCircuit, OffloadedPairingDef, OffloadedSNARK,
OffloadedSNARKError, OffloadedSNARKVerifyingKey,
};
use crate::utils::errors::ProofVerifyError;
use crate::utils::transcript::ProofTranscript;
Expand Down Expand Up @@ -409,14 +432,14 @@ mod tests {
let mut transcript_var =
MockSpongeVar::new(ns!(cs, "transcript").cs(), &(b"TestEval".as_slice()));

let h_kzg = HyperKZGVerifierGadget::<
E,
MockSponge<E::ScalarField>,
G1Var,
HyperKZGVerifierCircuit<E, G1Var>,
>::new(&self);
let kzg_vk = self.pcs_pk_vk.1.kzg_vk;
let hyper_kzg =
HyperKZGVerifierGadget::<E, MockSponge<E::ScalarField>, G1Var, Self>::new(
&self,
vec![kzg_vk.g2, kzg_vk.beta_g2],
);

let r = h_kzg.verify(
let r = hyper_kzg.verify(
&proof_var,
&vk_var,
&mut transcript_var,
Expand Down Expand Up @@ -455,18 +478,11 @@ mod tests {
{
type Circuit = HyperKZGVerifierCircuit<E, G1Var>;

fn offloaded_setup(
circuit: Self::Circuit,
snark_vk: S::ProcessedVerifyingKey,
) -> Result<OffloadedSNARKVerifyingKey<E, S>, OffloadedSNARKError<S::Error>> {
let KZGVerifierKey { g1, g2, beta_g2 } = circuit.pcs_pk_vk.1.kzg_vk;

Ok(OffloadedSNARKVerifyingKey {
snark_pvk: snark_vk,
delayed_pairings: vec![],
g2_elements: vec![vec![g2, beta_g2]],
})
}
// fn pairing_setup(circuit: Self::Circuit) -> Vec<Vec<E::G2Affine>> {
// let KZGVerifierKey { g1, g2, beta_g2 } = circuit.pcs_pk_vk.1.kzg_vk;
//
// vec![vec![g2, beta_g2]]
// }
}

#[test]
Expand Down
Loading








ApplySandwichStrip

pFad - (p)hone/(F)rame/(a)nonymizer/(d)eclutterfier!      Saves Data!


--- a PPN by Garber Painting Akron. With Image Size Reduction included!

Fetched URL: http://github.com/a16z/jolt/pull/431/commits/4ab444d56edb52cb2fac6d4387f42f65f41aff38

Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy