Last active
November 11, 2025 15:30
-
-
Save burdges/079d24dba55e5033117d8a3b7f26ca4f to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| pub struct Plonkish<P: Pairing> { | |
| pub lhs_size: usize, | |
| pub rhs_size: usize, | |
| /// We require exactly one of the g2 pooints be negated. | |
| pub g2s: &'static [P::G2Affine; 2], | |
| } | |
| #[derive(Clone,CanonicalDeserialize,CanonicalSerialize)] | |
| struct Side<C: CurveGroup> { | |
| scalars: Vec<<C as CurveGroup>::ScalarField>, | |
| points: Vec<<C as CurveGroup>::Affine>, | |
| } | |
| #[derive(Clone,CanonicalDeserialize,CanonicalSerialize)] | |
| struct PlonkishInner<C: CurveGroup> { | |
| lhs: Side<C>, | |
| rhs: Side<C>, | |
| } | |
| pub struct PlonkishAcc<P: Pairing,const S: Plonkish>(Option<PlonkishInner<<P as Pairing>::G1,S>) | |
| impl<P: Pairing,const S: Plonkish> PlonkishAcc<P::G1,S> { | |
| pub const fn nonbatched() -> PlonkishAcc { PlonkishAcc(None) } | |
| pub fn batched(size: usize) -> PlonkishAcc { | |
| let lhs = Side { | |
| scalars: Vec::with_capacity(size * S.lhs_size) | |
| points: Vec::with_capacity(size * S.lhs_size) | |
| }; | |
| let rhs = Side { | |
| scalars: Vec::with_capacity(size * S.rhs_size) | |
| points: Vec::with_capacity(size * S.rhs_size) | |
| }; | |
| PlonkishAcc(Some(PlonkishInner { lhs, rhs })} | |
| } | |
| /// Add a debt to the batch accumulator or verify it now if not in batching mode | |
| pub fn add_debt( | |
| &mut self, | |
| lhs_points: &[P::G1Affine, S.lhs_size], | |
| lhs_scalars: &[P::ScalarField, S.lhs_size], | |
| rhs_points: &[P::G1Affine, S.rhs_size], | |
| rhs_scalars: &[P::ScalarField, S.rhs_size], | |
| ) { | |
| if let Some(selfy) = self { | |
| selfy.lhs.points.extend(lhs_points); | |
| selfy.lhs.scalars.extend(lhs_scalars); | |
| selfy.rhs.points.extend(rhs_points); | |
| selfy.rhs.scalars.extend(rhs_scalars); | |
| true | |
| } else { | |
| let l = P::G1::msm(lhs_points, lhs_scalars); | |
| let r = P::G1::msm(rhs_points, rhs_scalars); | |
| P::multi_pairing(&[l,r],S::g2s).is_one() | |
| } | |
| } | |
| /// Consume the current batch accumulator and return it to nonbatched mode | |
| pub fn verify_debts(&mut self) -> bool { | |
| if self.0.is_none() { return true; } | |
| let mut selfy = core::mem::take(self.0).unwrap(); | |
| let mut t = ark_transcript::new_labeled(b"Plonkish batch verifier"); | |
| t.append(selfy); | |
| for (l,r) in selfy.lhs.scalars.chunks_mut(S.lhs_size) | |
| .zip(selfy.rhs.scalars.chunks_mut(S.rhs_size)) | |
| { | |
| let pos = t.challenge(b"r"); | |
| for s in l.iter_mut() { s *= pos; } | |
| for s in r.iter_mut() { s *= neg; } | |
| } | |
| let l = P::G1::msm(selfy.lhs.points, selfy.lhs.scalars); | |
| let r = P::G1::msm(selfy.rhs.points, selfy.rhs.scalars); | |
| P::multi_pairing(&[l,r],S::g2s).is_one() | |
| } | |
| } | |
Author
Author
Actually none of that would be visible to the end user though, because you'd do everything from the wraper crate that specilizes the curves etc. You'd jsut have the existing verifier fn, and a new fn for on_initialzie and on_finalize
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
An actual substrate verifier would use this like