zkSNARKs for knowledge of preimage of a Pedersen commitment using libsnark

Ian Goldberg 1aebe14522 If not in const mode, choose random (instead of fixed) points for the public keys P_i 4 лет назад
libsnark @ 477c9dfd07 cb8642b8df Add libsnark as a submodule 4 лет назад
sage 7ea1a3d913 Initial commit of pedersen-libsnark code 4 лет назад
.gitmodules cb8642b8df Add libsnark as a submodule 4 лет назад
Makefile e251c51f13 Add an example application of verifiable encryption 4 лет назад
README.md 95d946225b Update README 4 лет назад
ecgadget.hpp 088df43cd7 Choose a better generator A that is more clearly nothing-up-my-sleeve 4 лет назад
libsnark_headers.hpp 12c989ed60 Use precompiled headers for libsnark 4 лет назад
pedersen.cpp a145003c92 Add versions of the scalarmul gadget that don't take an accumulator 4 лет назад
pedersen.hpp 12c989ed60 Use precompiled headers for libsnark 4 лет назад
scalarmul.cpp a145003c92 Add versions of the scalarmul gadget that don't take an accumulator 4 лет назад
scalarmul.hpp 12c989ed60 Use precompiled headers for libsnark 4 лет назад
varscalarmul.cpp 12129895ac Improve the CLI for varscalarmul 4 лет назад
verifenc.cpp 1aebe14522 If not in const mode, choose random (instead of fixed) points for the public keys P_i 4 лет назад

README.md

zkSNARK for a Pedersen commitment

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:

  • Clone the repo
  • git submodule update --init --recursive
  • Ensure you have the build dependencies for libsnark installed.
  • cd libsnark
  • mkdir build && cd build && cmake -DCURVE=BN128 ..
  • make
  • cd ../..
  • make

Thanks to Christian Lundkvist and Sam Mayo for the very helpful libsnark tutorial.