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

Complete Curdleproof migration to generic group backend #5

Merged
merged 11 commits into from
Sep 25, 2023

Conversation

jsign
Copy link
Owner

@jsign jsign commented Sep 24, 2023

This PR completes migrating to the generic backend that can run G1 and GT (or any group with order Fr field size).

TL;DR - Show me the numbers

Here’s the benchmark for a complete curdleproofs run in various setups:

Prover:

Group #shuffled-elements Time
G1 60 97.5ms
G1 124 152.0ms
G1 252 244.2ms
G1 508 402.7ms
Gt 60 636.6ms
Gt 124 1.287s
Gt 252 2.647s
Gt 508 5.185s

Verifier (please see the "Notes and caveats" section):

Group #shuffled-elements Time (~ms)
G1 60 26ms
G1 124 55ms
G1 252 153ms
G1 508 499ms
Gt 60 147ms
Gt 124 265ms
Gt 252 503ms
Gt 508 1.067s

Internal arguments:

grandproductargument - Prove G1 took 77.4983ms
grandproductargument - Verify G1 took 8.366892ms (7.448892ms+918.221µs)
grandproductargument - Prove Gt took 586.559942ms
grandproductargument - Verify Gt took 57.07462ms (12.578833ms+44.496148ms)
innerproductargument - Prove for G1 took 49.86483ms
innerproductargument - Verify for G1 took 7.927519ms (7.029877ms+897.882µs)
innerproductargument - Prove for Gt took 354.415074ms
innerproductargument - Verify for Gt took 57.240236ms (12.255743ms+44.984734ms)
samemultiscalarargument - Prove G1 took 70.720219ms
samemultiscalarargument - Verify G1 took 58.747055ms (56.867424ms+1.879911ms)
samemultiscalarargument - Prove Gt took 530.828468ms
samemultiscalarargument - Verify Gt took 599.394585ms (462.330541ms+137.064274ms)
samepermutationargument - Prove G1 took 74.015994ms
samepermutationargument - Verify G1 took 11.901557ms (10.702348ms+1.199429ms)
samepermutationargument - Prove Gt took 636.043765ms
samepermutationargument - Verify Gt took 58.511259ms (13.575038ms+44.936401ms)
samescalarargument - Prove G1: 870.113µs
samescalarargument - Verify G1: 1.426788ms
samescalarargument - Prove Gt: 2.791413ms
samescalarargument - Verify Gt: 3.622894ms

Note: the (Ams+Bms) refers to Ams for the verifier logic, and Bms for the accumulated MSM check.
Note: the setups for these are scaled down; IIRC length is usually 128. We could do "more serious" benchmarks for different sizes if needed.

Notes and caveats

The implementation for G1 is the same as the original implementation, so nothing is interesting to say here. There're some inefficiencies due to the generic group abstraction layer. In any case, if G1 is decided to be used we can remove that an probably avoid those inefficiencies (i.e: the original impl).

The implementation for GT is fine but naive/optimizable. The most naive and inefficient implementation is doing MSMs in GT. Mostly because this is implemented now as a sum of scalar multiplications, which could be better. This was done now since the plan was to have this working for a generic group so that we can improve on that. We could use a Pippenger variant over GT, apply any trick for the GT algebraic structure (if any?), or any other idea. This means that the "GT verifier" numbers should be taken with a grain of salt, so adjust your interpretation accordingly.

I'm using a version of gnark-crypto that has a patch I did some days ago to improve the performance of G1 equality checks, which became relevant for the new way the MSM accumulator works. The gnark team still has to review that, but I'm taking that out of the way so it doesn't interfere with the results. When (and if) gets merged, I'll switch back to gnark-crypto@master, just to avoid pointing to a my fork.

Correctness

I also migrated all existing tests, which exist for completeness and soundness. I mostly did this to gain some confidence that things were working as expected; like, the chance of all this working with all that passing and having a mistake is quite low. (And actually, I got into some bug-fixing rabbit holes “thanks” to that).

Run with go test ./... -v. (I won't paste the output; it's too long).

Reproduce in your machine

For curdleproofs:

$ go test ./... -run=none -bench=.
goos: linux
goarch: amd64
pkg: github.com/jsign/curdleproofs
cpu: AMD Ryzen 7 3800XT 8-Core Processor            
BenchmarkProver/G1/shuffled_elements=60-16                    12          97527276 ns/op
BenchmarkProver/G1/shuffled_elements=124-16                    7         152007257 ns/op
BenchmarkProver/G1/shuffled_elements=252-16                    5         244253410 ns/op
BenchmarkProver/G1/shuffled_elements=508-16                    3         402716944 ns/op
BenchmarkProver/Gt/shuffled_elements=60-16                     2         636605186 ns/op
BenchmarkProver/Gt/shuffled_elements=124-16                    1        1287265046 ns/op
BenchmarkProver/Gt/shuffled_elements=252-16                    1        2647623288 ns/op
BenchmarkProver/Gt/shuffled_elements=508-16                    1        5185130979 ns/op
BenchmarkVerifier/G1/shuffled_elements=60-16                  45          26223691 ns/op
BenchmarkVerifier/G1/shuffled_elements=124-16                 21          55208867 ns/op
BenchmarkVerifier/G1/shuffled_elements=252-16                  7         153371241 ns/op
BenchmarkVerifier/G1/shuffled_elements=508-16                  3         498918875 ns/op
BenchmarkVerifier/Gt/shuffled_elements=60-16                   8         147182755 ns/op
BenchmarkVerifier/Gt/shuffled_elements=124-16                  4         265008072 ns/op
BenchmarkVerifier/Gt/shuffled_elements=252-16                  2         503797160 ns/op
BenchmarkVerifier/Gt/shuffled_elements=508-16                  2        1066527438 ns/op

For tests and internal arguments ~benchs, run: go test ./... -v -parallel=1

Review notes

I'll leave this PR open for a day or two, and then I'll merge it into the base PR and copy this same PR description.

I'm not doing much commenting on the PR since I'm not expecting a review since it's quite massive... but I got into some rabbit holes catching bugs. It's not the nicest thing to see a proof verification failing; that's finding a needle in a haystack... in any case, this had a happy ending.

@jsign jsign marked this pull request as ready for review September 24, 2023 12:15
Signed-off-by: Ignacio Hagopian <[email protected]>
Comment on lines -56 to +70
z.inner = bls12381.GT{}
z.inner.SetOne()
Copy link
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The default bls12381.GT{} is the neutral element in the additive group. But we live in a multiplicative subgroup, so the correct neutral element is one, not zero.

@@ -45,15 +47,27 @@ func (z *GtElement) AddAssign(e Element) Element {
return z
}

func (z *GtElement) SubAssign(e Element) Element {
ee := e.(*GtElement).inner
z.inner.Div(&z.inner, &ee)
Copy link
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

SubAssign it's a new one needed. Prob a good idea to have in mind.

Comment on lines -14 to +15
return &GtElement{}
res := &GtElement{}
res.inner.SetOne()
Copy link
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Improved for correctness, because we're in a multiplicative subgroup of F_12.

Comment on lines +117 to +127
var byts [48 * 12]byte
for i := 0; i < 6; i++ {
a, err := r.GetG1Affine()
if err != nil {
return bls12381.GT{}, nil
}
abytes := a.RawBytes()
copy(byts[i*(48*2):], abytes[:])
}
var randElem bls12381.GT
if _, err := randElem.SetRandom(); err != nil {
if err := randElem.SetBytes(byts[:]); err != nil {
Copy link
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks to the test verifiers complaining... we were using SetRandom(), where we should use the randomness from r *Rand to get deterministic setup generation.

@jsign jsign merged commit 89152b8 into jsign-gt Sep 25, 2023
@jsign jsign deleted the jsign-gt-morearguments branch September 25, 2023 22:43
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

1 participant