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

feat: introduce constraint blueprints. improve memory usage, enables custom gates and group of constraints #641

Merged
merged 20 commits into from
Apr 20, 2023

Conversation

gbotrel
Copy link
Collaborator

@gbotrel gbotrel commented Apr 13, 2023

Warning: fat PR. See #602 for context.

Breaking changes

For circuit builders / developers: none.

constraint package is impacted; in particular, since ConstraintSystem object is now the same for R1CS / Plonkish, methods AddConstraint and GetConstraints are now AddR1C (resp AddSparseR1C) and GetR1Cs. Signature is slightly modified (see Example in _test.go files in constraint/).

TLDR

Essentially the goal of this PR is to minimize the memory footprint of compiled constraint systems (for both R1CS and Plonkish). The core idea is instead of storing a flat list of constraint, to store a list of Instruction which points to some calldata enabling a Blueprint to "compress" (during compile time) a constraint into calldata and to "decompress" it during solving (or setup for zk backends).
So for a (simple) example a plonk gate doing qL * xa + qR * xb + qO * xc == 0 will just store these coefficients / wire ids (and not the unused one like qM or qC).

Additionally did refactor the SparseR1C structure to follow qLxa... notation.

The blueprint solving arithmetic is done using the same mechanism than in the frontend; we allocate (on the stack) a [6]uint64 and do field ops on that. I had a shot at generic again but it's just too ugly / adds barrier / performance & memory issues.

TODO

  • Serialization of blueprint is just a mvp, might be the right path, might be not. (ie we could have a registry like hints or something else).
  • Unplugged CheckUnconstrainedWires
  • Future PR: add "blocks of constraints" to further minimize memory footprint (see feat: lazify the constraints repeatable used; added poseidon for test #549 )
  • perf: investigate, if needed could have "specialized blueprints" for some frequent hints like binary decomposition & such to store coefficient references once.

Perf Status;

comparing the emulated bn254 pairing on develop vs on this branch:
regression on R1CS solver (+11% slower). all the rest (compile / solving time for both types) is faster / less greedy.

-56% for memory r1cs
-36% for memory scs 

(this is without block of constraints / optimized blueprints for hints, etc)

impacts on perf of the compiler & solver:

benchmark                            old ns/op       new ns/op       delta
BenchmarkPairing/compile_scs-10      23655591709     17436404667     -26.29%
BenchmarkPairing/solve_scs-10        2588727583      2285032250      -11.73%
BenchmarkPairing/compile_r1cs-10     20717499042     9739011416      -52.99%
BenchmarkPairing/solve_r1cs-10       1199609958      1333357208      +11.15%

benchmark                            old allocs     new allocs     delta
BenchmarkPairing/compile_scs-10      307815721      206326052      -32.97%
BenchmarkPairing/solve_scs-10        19024494       9639805        -49.33%
BenchmarkPairing/compile_r1cs-10     194413859      118428787      -39.08%
BenchmarkPairing/solve_r1cs-10       19024495       9643794        -49.31%

benchmark                            old bytes       new bytes       delta
BenchmarkPairing/compile_scs-10      29156295160     17976918504     -38.34%
BenchmarkPairing/solve_scs-10        2885155400      2522378920      -12.57%
BenchmarkPairing/compile_r1cs-10     34127280208     27831332584     -18.45%
BenchmarkPairing/solve_r1cs-10       1337235808      979406728       -26.76%

@gbotrel gbotrel added this to the v0.9.0 milestone Apr 13, 2023
@gbotrel gbotrel marked this pull request as draft April 13, 2023 21:11
@gbotrel gbotrel marked this pull request as ready for review April 14, 2023 21:54
@gbotrel
Copy link
Collaborator Author

gbotrel commented Apr 19, 2023

note: trying to have R1C and Hint blueprint implement solve to recover from solver perf regression.

Copy link
Collaborator

@ivokub ivokub left a comment

Choose a reason for hiding this comment

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

It is a big PR and I tried to find something, but imo the implementation is very straightforward. Everything makes sense.

I tried to find any typos or problems, but couldn't find any. But in any case I would still let it settle one develop for a bit just to edge off any potential bugs.

go.mod Outdated Show resolved Hide resolved
constraint/blueprint_r1cs.go Outdated Show resolved Hide resolved
constraint/blueprint_scs.go Outdated Show resolved Hide resolved
Comment on lines +127 to +129
func (system *System) AddBlueprint(b Blueprint) BlueprintID {
system.Blueprints = append(system.Blueprints, b)
return BlueprintID(len(system.Blueprints) - 1)
Copy link
Collaborator

Choose a reason for hiding this comment

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

Should check no duplicate blueprints?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

probably... but do you compare the object type or the object itself? so far our blueprint are stateless, but I'm thinking a specialized hint blueprint that store in the struct list of powers of 2 coeff IDs would be interesting.
Or a blue print that stores the params for MiMC permutation. (ie no need to store these in the constraint related to that).

@gbotrel gbotrel merged commit a48a8d1 into develop Apr 20, 2023
@gbotrel gbotrel deleted the feat/blueprint branch April 20, 2023 19:39
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants