-
Notifications
You must be signed in to change notification settings - Fork 146
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
base: main
Are you sure you want to change the base?
Conversation
I'm not sure the benefit of looking at MNT4 or BLS12-381 given that our main goal is on-chain verification on Ethereum, so we need to run Groth16 over BN254? We could just run both HyperKZG and Groth16 over BN254, but this would obviously mean that all the pairings and scalar multiplications the HyperKZG verifier does have to be done non-natively. That seems too expensive though? Here's my back-of-the-envelope calculation: The HyperKZG verifier does 2 pairings and 2 or 3 MSMs (not sure which, would have to check) of size n where n is the size of the committed polynomial (say, 2^24). The 2 pairings done non-natively would be about 6 million constraints. If the MSMs are implemented naively (i.e., no Pippenger's, as I'm not sure how much Pippenger's helps when implemented in constraints) that's 48 scalar multiplications. Each of those is about 1 million constraints if implemented non-natively (based on the current way people handle non-native arithmetic in constraints anyway). So that's over 50 million constraints. That seems like too many constraints to run Groth16 on without a beefy machine (maybe it's several minutes of proving time with 32 threads? It's also not that much lower than the 2^27 constraint count limit for Groth16 over BN254). Please correct me if my estimates here seem off. Another possibility would be to do a two-step composition to get Jolt proofs on-chain: Jolt-with-HyperKZG-over-BN254 proved by Spartan-with-Hyrax-over-Grumpin proved by Groth16-over-BN254. This would keep all arithmetic native. We would need both a Hyperkzg-over-BN254-verifier expressed as R1CS over Grumpkin, and a Hyrax-verifier-over-grumpkin-verifier expressed as an R1CS over BN254. |
@GUJustin the second two-step recursion system is actually how we've dealt with Nova + CycleFold proof compression to reach Ethereum verifiability. i.e., (modified)Spartan-with-Zeromorph-over-Grumpkin proved by Groth16-over-BN254. Still, we needed very beefy machines to run this process. This kind of complexity for doing proof compression for EC-based systems is likely a good reason to move out from them, is my gut feeling |
@GUJustin Definitely working towards on-chain verification, so yes, doing Groth16 over BN254. To clarify, the BLS12-381 port I'm mentioning above is for the non-native in-circuit pairing check for Jolt-with-HyperKZG-over-BLS12-381 verification proven by Groth16-over-BN254. Choosing BLS12-381 because it has an existing R1CS circuit implementation in arkworks. I'll update here on the non-native pairing costs when I'm done with a pairing circuit PoC. I do like the idea of keeping arithmetic native. I'm also curious if there are other ways to do this than the two step composition. |
@danielmarinq Hash-based proving systems use more layers to get to apply Groth16. I think most systems I’m aware of have three (or more?) layers of recursion to compress proofs and require beefy machines for those layers: (1) switch from “big” proof to “small” proof mode by altering rate of RS codes, (2) switch from “small” field to “big” field to match the scalar field of a curve, and (3) apply Groth16 or Plonk. I don’t think hash vs curve is affecting the complexity here and switching to hash based schemes doesn’t seem to magically solve the problem and the switch may make it somewhat harder. |
@danielmarinq how do you run zeromorph over Grumpkin? Doesn’t ZM need a pairing-friendly curve for succinct verification? |
Also, add PairingGadget trait.
We don't know how many constraints yet.
4fea9f3
to
d2f7171
Compare
Just pushed the PoC code for the pairing gadget in the non-native field (circuit is over BN254, the pairing is BLS12-381). The results are chilling: I haven't even got to the pairing itself yet, but just allocating a G1 element is more than 2M constraints. Allocating a G2 element is ~22M more. Here's the printout from the test run (the relevant part is in
|
# Conflicts: # jolt-core/src/poly/commitment/hyperkzg.rs
Hey folks, I understand this may not be a priority, but here's an implementation of HyperKZG verification in a SNARK. To make it work, I had to offload MSMs and multi-pairings to be performed by the SNARK verifier: this dramatically reduces the number of constraints in the circuit allows building the circuit over the pairing scalar field. Enjoy 😉 |
I did cheat a little: the transcript is implemented using a mock calling the native ProofTranscript. For actual production use, the transcript should either be implemented using a circuit-friendly hash (MiMC or Poseidon) or BSB22-style commitments (like in Gnark). |
btw, here's how you can see it in action (having checked out this PR's branch):
|
How did you offload the MSM's? |
@Forpee I've created a wrapper around Groth16 (other It's all in the code 😅 |
Just a note: for the FFA which occur in MSM there are tricks in SigmaBus that push FFA to the verifier circuit which can be accumulated in a Cyclefold instance. We will likely get all of this work into Cyclefold and then use the PSE tricks to get Cycefold on-chain. On L1 we pay for: |
@wyattbenno777 are you talking about this paper: https://eprint.iacr.org/2023/1406 ? Also, where can I learn more about "the PSE tricks to get Cyclefold on-chain" ? |
The PRs are good to review as well. privacy-scaling-explorations/sonobe#132 Also the newer Sigma-paper: |
@GUJustin @moodlezoup Are you guys still interested in this? |
Alas, our plans to get cheap on-chain verification (and folding) no longer involve implementing the HyperKZG verifier non-natively in constraints. |
@GUJustin if you think this is a dead end, I'll close this PR. But also, what would you suggest on how to move forward towards cheaper verification (and folding)? Also, to clarify, what's implemented here doesn't involve non-native arithmetic: MSM and pairing definitions are simply appended to public input to be checked by the verifier. The circuit only deals with the scalar field (natively). |
You're saying that you're taking the HyperKZG verifier (when the committed polynomial is defined over the BN254 scalar field), and expressing it as constraints over the BN254 base field, so that all of the scalar multiplications and pairings done by the HyperKZG verifier are natively defined over the field used by the constraint system? If there's no non-native arithmetic happening in the constraints, then the HyperKZG verifier should only require a few hundred thousand constraints at the most. Here's the math: The HyperKZG verifier does a couple of dozen scalar multiplications and two pairings. A scalar multiplication is ~400 group additions (actually, ~256 group additions, since we could use 128-bit scalars, but let's ignore that). Each group addition is like ~10 field multiplications. So the scalar multiplications should conservatively be about 30 \cdot 400 \cdot 30 = 120K constraints. And a pairing is equivalent to several thousand group additions, so the two pairings also should only be 2 \cdot 2,000 \cdot 10 constraints, which is way below 100K. So if you're seeing tens of millions of constraints, I have to think you're actually having the constraints non-natively implement the field operations done by the HyperKZG verifier. This would be needed, for example, if the constraint system is defined over the BN254 scalar field.
For some details, see https://jolt.a16zcrypto.com/future/groth-16.html#a-way-forward and https://github.com/a16z/jolt/blob/main/book/src/future/folding.md |
No. I'm taking the HyperKZG verifier (when the committed polynomial is defined over the BN254 scalar field), and express it as constraints over the BN254 scalar field. I also take
and append to the public input. The verifier must make sure the MSMs and multi-pairings evaluate to
Exactly right! When you run
on this branch, you get a circuit with 112136 constraints. |
This is a work in progress with the goal to build a complete Jolt verifier circuit and prove it with Groth16 or Polymath.
The ultimate goal is to implement #371.
HyperKZG verifier circuit
We can't rely (as arkworks' PairingVar does) on the circuit native field to be the base field of the pairing curve of the HyperKZG verifier. The verifier circuit's native field is the scalar field of BN254 or BLS12-381 (as the most widely available pairing curves). Unfortunately, there are no pairing-friendly curves with the base field being the scalar field of either BN254 or BLS12-381.