zkSNARKs for knowledge of preimage of a Pedersen commitment using libsnark
Ian Goldberg 2dce3ad890 Remove accidentally duplicated code | vor 5 Jahren | |
---|---|---|
libsnark @ 477c9dfd07 | vor 5 Jahren | |
sage | vor 5 Jahren | |
.gitmodules | vor 5 Jahren | |
Makefile | vor 5 Jahren | |
README.md | vor 5 Jahren | |
ecgadget.hpp | vor 5 Jahren | |
libsnark_headers.hpp | vor 5 Jahren | |
pedersen.cpp | vor 5 Jahren | |
pedersen.hpp | vor 5 Jahren | |
scalarmul.cpp | vor 5 Jahren | |
scalarmul.hpp | vor 5 Jahren | |
varscalarmul.cpp | vor 5 Jahren | |
verifenc.cpp | vor 5 Jahren |
Ian Goldberg (iang@uwaterloo.ca), updated November 2019
I spent a day learning how to use libsnark, and thought an interesting first project would be to create a zkSNARK for knowledge of a preimage for a Pedersen commitment. I spent another day reimplementing it with a better scalar multiplication algorithm. A few months later, I did a little more work on the algorithm, further reducing the cost of scalar multiplication (with a constant base point) to 3 constraints per bit, and implementing new features like scalar multiplication of non-constant points.
This circuit ends up with 1531 constraints for a Pedersen commitment over a 254-bit elliptic curve.
It uses libsnark's BN128 implementation, which has an order (not modulus) of r=21888242871839275222246405745257275088548364400416034343698204186575808495617. Then using Sage, the findcurve script in this repo searches for an elliptic curve with modulus r, and with both prime order and whose twist has prime order. (You do not need to run the findcurve script yourself.) The resulting curve (over F_r) is E: y^2 = x^3 - 3*x + b, where b=7950939520449436327800262930799465135910802758673292356620796789196167463969. The order of this curve is the prime 21888242871839275222246405745257275088760161411100494528458776273921456643749.
The code uses four generators of this curve, which must not have a known DL representation among them. They are G(0,11977228949870389393715360594190192321220966033310912010610740966317727761886), H(1,21803877843449984883423225223478944275188924769286999517937427649571474907279), C(2,4950745124018817972378217179409499695353526031437053848725554590521829916331), and A(4,1929778687269876629657252589535788315400602403700102541701561325064015752665).
If you switch to a different underlying curve for the zkSNARKs than BN128, you will need to find a new E and new generators, and change the precomputed values in ecgadget.hpp to match.
The code produces a zkSNARK for the statment "I know values a and b such that a*G + b*H equals the given Pedersen commitment P."
Also supported: scalar multiplication by a constant point (768 constraints), scalar multiplication by a public point (3048 constraints with a private precomputation table, or 1530 with a public one, but the public version is considerably slower to verify).
Building:
Thanks to Christian Lundkvist and Sam Mayo for the very helpful libsnark tutorial.