Browse Source

Update exposed methods, update README.md, add godoc & goreport cards

ed255-patch-1
arnaucube 4 years ago
parent
commit
d5c971e59a
9 changed files with 113 additions and 82 deletions
  1. +24
    -3
      README.md
  2. +17
    -17
      arithmetic.go
  3. +2
    -4
      go.mod
  4. +10
    -5
      go.sum
  5. +10
    -12
      ifft.go
  6. +4
    -0
      parsers.go
  7. +26
    -26
      parsers_test.go
  8. +18
    -13
      prover.go
  9. +2
    -2
      prover_test.go

+ 24
- 3
README.md

@ -1,5 +1,26 @@
# go-circom-prover
Experimental Go zkSNARK prover compatible with [circom](https://github.com/iden3/circom).
# go-circom-prover [![GoDoc](https://godoc.org/github.com/iden3/go-circom-prover?status.svg)](https://godoc.org/github.com/iden3/go-circom-prover) [![Go Report Card](https://goreportcard.com/badge/github.com/iden3/go-circom-prover)](https://goreportcard.com/report/github.com/iden3/go-circom-prover)
Experimental Go implementation of the [Groth16 protocol](https://eprint.iacr.org/2016/260.pdf) zkSNARK prover compatible with [circom](https://github.com/iden3/circom).
Using [bn256](https://github.com/ethereum/go-ethereum/tree/master/crypto/bn256/cloudflare) (used by [go-ethereum](https://github.com/ethereum/go-ethereum)) for the Pairing.
Using [bn256](https://github.com/ethereum/go-ethereum/tree/master/crypto/bn256/cloudflare) (used by [go-ethereum](https://github.com/ethereum/go-ethereum)) for the Pairing curve operations.
### Example
```go
// read ProvingKey & Witness files
provingKeyJson, _ := ioutil.ReadFile("testdata/provingkey.json")
witnessJson, _ := ioutil.ReadFile("testdata/witness.json")
// parse Proving Key
pk, _ := circomprover.ParseProvingKey(provingKeyJson)
// parse Witness
w, _ := circomprover.ParseWitness(witnessJson)
// generate the proof
proof, pubSignals, err := circomprover.GenerateProof(pk, w)
assert.Nil(t, err)
fmt.Println(pubSignals)
fmt.Println(proof)
```

+ 17
- 17
arithmetic.go

@ -13,35 +13,35 @@ func arrayOfZeroes(n int) []*big.Int {
return r return r
} }
func FAdd(a, b *big.Int) *big.Int {
func fAdd(a, b *big.Int) *big.Int {
ab := new(big.Int).Add(a, b) ab := new(big.Int).Add(a, b)
return new(big.Int).Mod(ab, R) return new(big.Int).Mod(ab, R)
} }
func FSub(a, b *big.Int) *big.Int {
func fSub(a, b *big.Int) *big.Int {
ab := new(big.Int).Sub(a, b) ab := new(big.Int).Sub(a, b)
return new(big.Int).Mod(ab, R) return new(big.Int).Mod(ab, R)
} }
func FMul(a, b *big.Int) *big.Int {
func fMul(a, b *big.Int) *big.Int {
ab := new(big.Int).Mul(a, b) ab := new(big.Int).Mul(a, b)
return new(big.Int).Mod(ab, R) return new(big.Int).Mod(ab, R)
} }
func FDiv(a, b *big.Int) *big.Int {
func fDiv(a, b *big.Int) *big.Int {
ab := new(big.Int).Mul(a, new(big.Int).ModInverse(b, R)) ab := new(big.Int).Mul(a, new(big.Int).ModInverse(b, R))
return new(big.Int).Mod(ab, R) return new(big.Int).Mod(ab, R)
} }
func FNeg(a *big.Int) *big.Int {
func fNeg(a *big.Int) *big.Int {
return new(big.Int).Mod(new(big.Int).Neg(a), R) return new(big.Int).Mod(new(big.Int).Neg(a), R)
} }
func FInv(a *big.Int) *big.Int {
func fInv(a *big.Int) *big.Int {
return new(big.Int).ModInverse(a, R) return new(big.Int).ModInverse(a, R)
} }
func FExp(base *big.Int, e *big.Int) *big.Int {
func fExp(base *big.Int, e *big.Int) *big.Int {
res := big.NewInt(1) res := big.NewInt(1)
rem := new(big.Int).Set(e) rem := new(big.Int).Set(e)
exp := base exp := base
@ -49,9 +49,9 @@ func FExp(base *big.Int, e *big.Int) *big.Int {
for !bytes.Equal(rem.Bytes(), big.NewInt(int64(0)).Bytes()) { for !bytes.Equal(rem.Bytes(), big.NewInt(int64(0)).Bytes()) {
// if BigIsOdd(rem) { // if BigIsOdd(rem) {
if rem.Bit(0) == 1 { // .Bit(0) returns 1 when is odd if rem.Bit(0) == 1 { // .Bit(0) returns 1 when is odd
res = FMul(res, exp)
res = fMul(res, exp)
} }
exp = FMul(exp, exp)
exp = fMul(exp, exp)
rem = new(big.Int).Rsh(rem, 1) rem = new(big.Int).Rsh(rem, 1)
} }
return res return res
@ -64,38 +64,38 @@ func max(a, b int) int {
return b return b
} }
func PolynomialSub(a, b []*big.Int) []*big.Int {
func polynomialSub(a, b []*big.Int) []*big.Int {
r := arrayOfZeroes(max(len(a), len(b))) r := arrayOfZeroes(max(len(a), len(b)))
for i := 0; i < len(a); i++ { for i := 0; i < len(a); i++ {
r[i] = FAdd(r[i], a[i])
r[i] = fAdd(r[i], a[i])
} }
for i := 0; i < len(b); i++ { for i := 0; i < len(b); i++ {
r[i] = FSub(r[i], b[i])
r[i] = fSub(r[i], b[i])
} }
return r return r
} }
func PolynomialMul(a, b []*big.Int) []*big.Int {
func polynomialMul(a, b []*big.Int) []*big.Int {
r := arrayOfZeroes(len(a) + len(b) - 1) r := arrayOfZeroes(len(a) + len(b) - 1)
for i := 0; i < len(a); i++ { for i := 0; i < len(a); i++ {
for j := 0; j < len(b); j++ { for j := 0; j < len(b); j++ {
r[i+j] = FAdd(r[i+j], FMul(a[i], b[j]))
r[i+j] = fAdd(r[i+j], fMul(a[i], b[j]))
} }
} }
return r return r
} }
func PolynomialDiv(a, b []*big.Int) ([]*big.Int, []*big.Int) {
func polynomialDiv(a, b []*big.Int) ([]*big.Int, []*big.Int) {
// https://en.wikipedia.org/wiki/Division_algorithm // https://en.wikipedia.org/wiki/Division_algorithm
r := arrayOfZeroes(len(a) - len(b) + 1) r := arrayOfZeroes(len(a) - len(b) + 1)
rem := a rem := a
for len(rem) >= len(b) { for len(rem) >= len(b) {
l := FDiv(rem[len(rem)-1], b[len(b)-1])
l := fDiv(rem[len(rem)-1], b[len(b)-1])
pos := len(rem) - len(b) pos := len(rem) - len(b)
r[pos] = l r[pos] = l
aux := arrayOfZeroes(pos) aux := arrayOfZeroes(pos)
aux1 := append(aux, l) aux1 := append(aux, l)
aux2 := PolynomialSub(rem, PolynomialMul(b, aux1))
aux2 := polynomialSub(rem, polynomialMul(b, aux1))
rem = aux2[:len(aux2)-1] rem = aux2[:len(aux2)-1]
} }
return r, rem return r, rem

+ 2
- 4
go.mod

@ -1,10 +1,8 @@
module gocircom
module gocircomprover
go 1.13 go 1.13
replace github.com/ethereum/go-ethereum => ../go-ethereum
require ( require (
github.com/ethereum/go-ethereum v1.9.12 github.com/ethereum/go-ethereum v1.9.12
github.com/stretchr/testify v1.4.0
github.com/stretchr/testify v1.5.1
) )

+ 10
- 5
go.sum

@ -40,6 +40,8 @@ github.com/docker/docker v1.4.2-0.20180625184442-8e610b2b55bf/go.mod h1:eEKB0N0r
github.com/dop251/goja v0.0.0-20200219165308-d1232e640a87/go.mod h1:Mw6PkjjMXWbTj+nnj4s3QPXq1jaT0s5pC0iFD4+BOAA= github.com/dop251/goja v0.0.0-20200219165308-d1232e640a87/go.mod h1:Mw6PkjjMXWbTj+nnj4s3QPXq1jaT0s5pC0iFD4+BOAA=
github.com/edsrzf/mmap-go v0.0.0-20160512033002-935e0e8a636c/go.mod h1:YO35OhQPt3KJa3ryjFM5Bs14WD66h8eGKpfaBNrHW5M= github.com/edsrzf/mmap-go v0.0.0-20160512033002-935e0e8a636c/go.mod h1:YO35OhQPt3KJa3ryjFM5Bs14WD66h8eGKpfaBNrHW5M=
github.com/elastic/gosigar v0.8.1-0.20180330100440-37f05ff46ffa/go.mod h1:cdorVVzy1fhmEqmtgqkoE3bYtCfSCkVyjTyCIo22xvs= github.com/elastic/gosigar v0.8.1-0.20180330100440-37f05ff46ffa/go.mod h1:cdorVVzy1fhmEqmtgqkoE3bYtCfSCkVyjTyCIo22xvs=
github.com/ethereum/go-ethereum v1.9.12 h1:EPtimwsp/KGDSiXcNunzsI4kefdsMHZGJntKx3fvbaI=
github.com/ethereum/go-ethereum v1.9.12/go.mod h1:PvsVkQmhZFx92Y+h2ylythYlheEDt/uBgFbl61Js/jo=
github.com/fatih/color v1.3.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4= github.com/fatih/color v1.3.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4=
github.com/fjl/memsize v0.0.0-20180418122429-ca190fb6ffbc/go.mod h1:VvhXpOYNQvB+uIk2RvXzuaQtkQJzzIx6lSBe1xv7hi0= github.com/fjl/memsize v0.0.0-20180418122429-ca190fb6ffbc/go.mod h1:VvhXpOYNQvB+uIk2RvXzuaQtkQJzzIx6lSBe1xv7hi0=
github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
@ -109,22 +111,26 @@ github.com/steakknife/hamming v0.0.0-20180906055917-c99c65617cd3/go.mod h1:hpGUW
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
github.com/stretchr/testify v1.4.0 h1:2E4SXV/wtOkTonXsotYi4li6zVWxYlZuYNCXe9XRJyk=
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
github.com/stretchr/testify v1.5.1 h1:nOGnQDM7FYENwehXlg/kFVnos3rEvtKTjRvOWSzb6H4=
github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA=
github.com/syndtr/goleveldb v1.0.1-0.20190923125748-758128399b1d/go.mod h1:9OrXJhf154huy1nPWmuSrkgjPUtUNhA+Zmy+6AESzuA= github.com/syndtr/goleveldb v1.0.1-0.20190923125748-758128399b1d/go.mod h1:9OrXJhf154huy1nPWmuSrkgjPUtUNhA+Zmy+6AESzuA=
github.com/tyler-smith/go-bip39 v1.0.1-0.20181017060643-dbb3b84ba2ef/go.mod h1:sJ5fKU0s6JVwZjjcUEX2zFOnvq0ASQ2K9Zr6cf67kNs= github.com/tyler-smith/go-bip39 v1.0.1-0.20181017060643-dbb3b84ba2ef/go.mod h1:sJ5fKU0s6JVwZjjcUEX2zFOnvq0ASQ2K9Zr6cf67kNs=
github.com/urfave/cli v1.22.1/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0= github.com/urfave/cli v1.22.1/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0=
github.com/wsddn/go-ecdh v0.0.0-20161211032359-48726bab9208/go.mod h1:IotVbo4F+mw0EzQ08zFqg7pK3FebNXpaMsRy2RT+Ees= github.com/wsddn/go-ecdh v0.0.0-20161211032359-48726bab9208/go.mod h1:IotVbo4F+mw0EzQ08zFqg7pK3FebNXpaMsRy2RT+Ees=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/crypto v0.0.0-20200311171314-f7b00557c8c4/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20190628185345-da137c7871d7/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20200301022130-244492dfa37a/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20181107165924-66b7b1311ac8/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20181107165924-66b7b1311ac8/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190712062909-fae7ac547cb7 h1:LepdCS8Gf/MVejFIt8lsiexZATdoGVyp5bcyS+rYoUI=
golang.org/x/sys v0.0.0-20190712062909-fae7ac547cb7/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200302150141-5c8b2ff67527 h1:uYVVQ9WP/Ds2ROhcaGPeIdVq0RIXVLwsHlnvJ+cT1So=
golang.org/x/sys v0.0.0-20200302150141-5c8b2ff67527/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
@ -135,7 +141,6 @@ gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8
gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys= gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys=
gopkg.in/natefinch/npipe.v2 v2.0.0-20160621034901-c1b8fa8bdcce/go.mod h1:5AcXVHNjg+BDxry382+8OKon8SEWiKktQR07RKPsv1c= gopkg.in/natefinch/npipe.v2 v2.0.0-20160621034901-c1b8fa8bdcce/go.mod h1:5AcXVHNjg+BDxry382+8OKon8SEWiKktQR07RKPsv1c=
gopkg.in/olebedev/go-duktape.v3 v3.0.0-20190213234257-ec84240a7772/go.mod h1:uAJfkITjFhyEEuUfm7bsmCZRbW5WRq8s9EY8HZ6hCns= gopkg.in/olebedev/go-duktape.v3 v3.0.0-20190213234257-ec84240a7772/go.mod h1:uAJfkITjFhyEEuUfm7bsmCZRbW5WRq8s9EY8HZ6hCns=
gopkg.in/sourcemap.v1 v1.0.5/go.mod h1:2RlvNNSMglmRrcvhfuzp4hQHwOtjxlbjX7UPY/GXb78=
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw= gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw=
gopkg.in/urfave/cli.v1 v1.20.0/go.mod h1:vuBzUtMdQeixQj8LVd+/98pzhxNGQoyuPBlsXHOQNO0= gopkg.in/urfave/cli.v1 v1.20.0/go.mod h1:vuBzUtMdQeixQj8LVd+/98pzhxNGQoyuPBlsXHOQNO0=
gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=

+ 10
- 12
ifft.go

@ -21,30 +21,28 @@ func newRootsT() rootsT {
rem = new(big.Int).Rsh(rem, 1) rem = new(big.Int).Rsh(rem, 1)
} }
roots.w = make([]*big.Int, s+1) roots.w = make([]*big.Int, s+1)
roots.w[s] = FExp(big.NewInt(5), rem)
roots.w[s] = fExp(big.NewInt(5), rem)
n := s - 1 n := s - 1
for n >= 0 { for n >= 0 {
roots.w[n] = FMul(roots.w[n+1], roots.w[n+1])
roots.w[n] = fMul(roots.w[n+1], roots.w[n+1])
n-- n--
} }
roots.roots = make([][]*big.Int, 50)
roots.roots = make([][]*big.Int, 50) // TODO WIP
roots.setRoots(15) roots.setRoots(15)
return roots return roots
} }
func (roots rootsT) setRoots(n int) { func (roots rootsT) setRoots(n int) {
// var roots []bool
for i := n; i >= 0 && nil == roots.roots[i]; i-- { // TODO tmp i<=len(r) for i := n; i >= 0 && nil == roots.roots[i]; i-- { // TODO tmp i<=len(r)
r := big.NewInt(1) r := big.NewInt(1)
nroots := 1 << i nroots := 1 << i
var rootsi []*big.Int var rootsi []*big.Int
for j := 0; j < nroots; j++ { for j := 0; j < nroots; j++ {
rootsi = append(rootsi, r) rootsi = append(rootsi, r)
r = FMul(r, roots.w[i])
r = fMul(r, roots.w[i])
} }
// fmt.Println("rootsi", rootsi)
roots.roots[i] = rootsi roots.roots[i] = rootsi
} }
} }
@ -55,8 +53,8 @@ func fft(roots rootsT, pall []*big.Int, bits, offset, step int) []*big.Int {
return []*big.Int{pall[offset]} return []*big.Int{pall[offset]}
} else if n == 2 { } else if n == 2 {
return []*big.Int{ return []*big.Int{
FAdd(pall[offset], pall[offset+step]), // TODO tmp
FSub(pall[offset], pall[offset+step]),
fAdd(pall[offset], pall[offset+step]), // TODO tmp
fSub(pall[offset], pall[offset+step]),
} }
} }
@ -68,8 +66,8 @@ func fft(roots rootsT, pall []*big.Int, bits, offset, step int) []*big.Int {
out := make([]*big.Int, n) out := make([]*big.Int, n)
for i := 0; i < ndiv2; i++ { for i := 0; i < ndiv2; i++ {
fmt.Println(i, len(roots.roots)) fmt.Println(i, len(roots.roots))
out[i] = FAdd(p1[i], FMul(roots.roots[bits][i], p2[i]))
out[i+ndiv2] = FSub(p1[i], FMul(roots.roots[bits][i], p2[i]))
out[i] = fAdd(p1[i], fMul(roots.roots[bits][i], p2[i]))
out[i+ndiv2] = fSub(p1[i], fMul(roots.roots[bits][i], p2[i]))
} }
return out return out
} }
@ -85,11 +83,11 @@ func ifft(p []*big.Int) []*big.Int {
ep := extend(p, m) ep := extend(p, m)
res := fft(roots, ep, int(bits), 0, 1) res := fft(roots, ep, int(bits), 0, 1)
twoinvm := FInv(FMul(big.NewInt(1), big.NewInt(int64(m))))
twoinvm := fInv(fMul(big.NewInt(1), big.NewInt(int64(m))))
var resn []*big.Int var resn []*big.Int
for i := 0; i < m; i++ { for i := 0; i < m; i++ {
resn = append(resn, FMul(res[(m-i)%m], twoinvm))
resn = append(resn, fMul(res[(m-i)%m], twoinvm))
} }
return resn return resn

+ 4
- 0
parsers.go

@ -12,6 +12,7 @@ import (
bn256 "github.com/ethereum/go-ethereum/crypto/bn256/cloudflare" bn256 "github.com/ethereum/go-ethereum/crypto/bn256/cloudflare"
) )
// ProvingKeyString is the equivalent to the ProvingKey struct in string representation
type ProvingKeyString struct { type ProvingKeyString struct {
A [][]string `json:"A"` A [][]string `json:"A"`
B2 [][][]string `json:"B2"` B2 [][][]string `json:"B2"`
@ -31,8 +32,10 @@ type ProvingKeyString struct {
PolsC []map[string]string `json:"polsC"` PolsC []map[string]string `json:"polsC"`
} }
// WitnessString contains the Witness in string representation
type WitnessString []string type WitnessString []string
// ParseWitness parses the json []byte data into the Witness struct
func ParseWitness(wJson []byte) (Witness, error) { func ParseWitness(wJson []byte) (Witness, error) {
var ws WitnessString var ws WitnessString
err := json.Unmarshal(wJson, &ws) err := json.Unmarshal(wJson, &ws)
@ -51,6 +54,7 @@ func ParseWitness(wJson []byte) (Witness, error) {
return w, nil return w, nil
} }
// ParseProvingKey parses the json []byte data into the ProvingKey struct
func ParseProvingKey(pkJson []byte) (*ProvingKey, error) { func ParseProvingKey(pkJson []byte) (*ProvingKey, error) {
var pkStr ProvingKeyString var pkStr ProvingKeyString
err := json.Unmarshal(pkJson, &pkStr) err := json.Unmarshal(pkJson, &pkStr)

+ 26
- 26
parsers_test.go

@ -8,22 +8,22 @@ import (
func TestParseArrayG1(t *testing.T) { func TestParseArrayG1(t *testing.T) {
aS := [][]string{ aS := [][]string{
[]string{
{
"16145916318196730299582072104388453231952213805668281741813587224450782397538", "16145916318196730299582072104388453231952213805668281741813587224450782397538",
"4434505318477484327659527264104806919103674231447634885054368605283938696207", "4434505318477484327659527264104806919103674231447634885054368605283938696207",
"1", "1",
}, },
[]string{
{
"10618406967550056457559358662746625591602641004174976323307214433994084907915", "10618406967550056457559358662746625591602641004174976323307214433994084907915",
"1843236360452735081347085412539192450068665510574800388201121698908391533923", "1843236360452735081347085412539192450068665510574800388201121698908391533923",
"1", "1",
}, },
[]string{
{
"1208972877970123411566574123860641832032384890981476033353526096830198333194", "1208972877970123411566574123860641832032384890981476033353526096830198333194",
"777503551507025252294438107100944741641946695980350712141258191590862204805", "777503551507025252294438107100944741641946695980350712141258191590862204805",
"1", "1",
}, },
[]string{
{
"0", "0",
"1", "1",
"0", "0",
@ -40,15 +40,15 @@ func TestParseArrayG1(t *testing.T) {
func TestParseG2(t *testing.T) { func TestParseG2(t *testing.T) {
aS := [][]string{ aS := [][]string{
[]string{
{
"9283666785342556550467669770956850930982548182701254051508520248901282197973", "9283666785342556550467669770956850930982548182701254051508520248901282197973",
"11369378229277445316894458966429873744779877313900506577160370623273013178252", "11369378229277445316894458966429873744779877313900506577160370623273013178252",
}, },
[]string{
{
"10625777544326349817513295021482494426101347915428005055375725845993157551870", "10625777544326349817513295021482494426101347915428005055375725845993157551870",
"21401790227434807639472120486932615400751346915707967674912972446672152512583", "21401790227434807639472120486932615400751346915707967674912972446672152512583",
}, },
[]string{
{
"1", "1",
"0", "0",
}, },
@ -59,15 +59,15 @@ func TestParseG2(t *testing.T) {
assert.Equal(t, "bn256.G2((1922d70c934543aa655ec3277f7fa10a25ec973a4f001a7c54ce4954b4916f8c, 14865e836947c42cf35b47d30e06535fff9dab319c4296e28afde368960671d5), (2f50fbe77925b0a9d718c9ab38638bafa7c65f43f0d09035e518df97ad294847, 177dfa1a3b8627faf0425d9511bcb4c6ca986ea05e3803b5c643c35b94a7e6fe))", a.String()) assert.Equal(t, "bn256.G2((1922d70c934543aa655ec3277f7fa10a25ec973a4f001a7c54ce4954b4916f8c, 14865e836947c42cf35b47d30e06535fff9dab319c4296e28afde368960671d5), (2f50fbe77925b0a9d718c9ab38638bafa7c65f43f0d09035e518df97ad294847, 177dfa1a3b8627faf0425d9511bcb4c6ca986ea05e3803b5c643c35b94a7e6fe))", a.String())
aS = [][]string{ aS = [][]string{
[]string{
{
"13973091636763944887728510851169742544309374663995476311690518173988838518856", "13973091636763944887728510851169742544309374663995476311690518173988838518856",
"12903946180439304546475897520537621821375470264150438270817301786763517825250", "12903946180439304546475897520537621821375470264150438270817301786763517825250",
}, },
[]string{
{
"370374369234123593044872519351942112043402224488849374153134091815693350697", "370374369234123593044872519351942112043402224488849374153134091815693350697",
"17423079115073430837335625309232513526393852743032331213038909731579295753224", "17423079115073430837335625309232513526393852743032331213038909731579295753224",
}, },
[]string{
{
"1", "1",
"0", "0",
}, },
@ -79,58 +79,58 @@ func TestParseG2(t *testing.T) {
func TestParseArrayG2(t *testing.T) { func TestParseArrayG2(t *testing.T) {
aS := [][][]string{ aS := [][][]string{
[][]string{
[]string{
{
{
"0", "0",
"0", "0",
}, },
[]string{
{
"1", "1",
"0", "0",
}, },
[]string{
{
"0", "0",
"0", "0",
}, },
}, },
[][]string{
[]string{
{
{
"0", "0",
"0", "0",
}, },
[]string{
{
"1", "1",
"0", "0",
}, },
[]string{
{
"0", "0",
"0", "0",
}, },
}, },
[][]string{
[]string{
{
{
"0", "0",
"0", "0",
}, },
[]string{
{
"1", "1",
"0", "0",
}, },
[]string{
{
"0", "0",
"0", "0",
}, },
}, },
[][]string{
[]string{
{
{
"9283666785342556550467669770956850930982548182701254051508520248901282197973", "9283666785342556550467669770956850930982548182701254051508520248901282197973",
"11369378229277445316894458966429873744779877313900506577160370623273013178252", "11369378229277445316894458966429873744779877313900506577160370623273013178252",
}, },
[]string{
{
"10625777544326349817513295021482494426101347915428005055375725845993157551870", "10625777544326349817513295021482494426101347915428005055375725845993157551870",
"21401790227434807639472120486932615400751346915707967674912972446672152512583", "21401790227434807639472120486932615400751346915707967674912972446672152512583",
}, },
[]string{
{
"1", "1",
"0", "0",
}, },

+ 18
- 13
prover.go

@ -8,12 +8,14 @@ import (
bn256 "github.com/ethereum/go-ethereum/crypto/bn256/cloudflare" bn256 "github.com/ethereum/go-ethereum/crypto/bn256/cloudflare"
) )
// Proof is the data structure of the Groth16 zkSNARK proof
type Proof struct { type Proof struct {
A *bn256.G1 A *bn256.G1
B *bn256.G2 B *bn256.G2
C *bn256.G1 C *bn256.G1
} }
// ProvingKey holds the data structure of the provingKey
type ProvingKey struct { type ProvingKey struct {
A []*bn256.G1 A []*bn256.G1
B2 []*bn256.G2 B2 []*bn256.G2
@ -33,11 +35,13 @@ type ProvingKey struct {
PolsC []map[int]*big.Int PolsC []map[int]*big.Int
} }
// Witness contains the witness
type Witness []*big.Int type Witness []*big.Int
// R is the mod of the finite field
var R, _ = new(big.Int).SetString("21888242871839275222246405745257275088548364400416034343698204186575808495617", 10) var R, _ = new(big.Int).SetString("21888242871839275222246405745257275088548364400416034343698204186575808495617", 10)
func RandBigInt() (*big.Int, error) {
func randBigInt() (*big.Int, error) {
maxbits := R.BitLen() maxbits := R.BitLen()
b := make([]byte, (maxbits/8)-1) b := make([]byte, (maxbits/8)-1)
_, err := rand.Read(b) _, err := rand.Read(b)
@ -50,14 +54,15 @@ func RandBigInt() (*big.Int, error) {
return rq, nil return rq, nil
} }
func Prove(pk *ProvingKey, w Witness) (*Proof, []*big.Int, error) {
// GenerateProof generates the Groth16 zkSNARK proof
func GenerateProof(pk *ProvingKey, w Witness) (*Proof, []*big.Int, error) {
var proof Proof var proof Proof
r, err := RandBigInt()
r, err := randBigInt()
if err != nil { if err != nil {
return nil, nil, err return nil, nil, err
} }
s, err := RandBigInt()
s, err := randBigInt()
if err != nil { if err != nil {
return nil, nil, err return nil, nil, err
} }
@ -95,7 +100,7 @@ func Prove(pk *ProvingKey, w Witness) (*Proof, []*big.Int, error) {
} }
proof.C = new(bn256.G1).Add(proof.C, new(bn256.G1).ScalarMult(proof.A, s)) proof.C = new(bn256.G1).Add(proof.C, new(bn256.G1).ScalarMult(proof.A, s))
proof.C = new(bn256.G1).Add(proof.C, new(bn256.G1).ScalarMult(proofBG1, r)) proof.C = new(bn256.G1).Add(proof.C, new(bn256.G1).ScalarMult(proofBG1, r))
rsneg := new(big.Int).Mod(new(big.Int).Neg(new(big.Int).Mul(r, s)), R) // FAdd & FMul
rsneg := new(big.Int).Mod(new(big.Int).Neg(new(big.Int).Mul(r, s)), R) // fAdd & fMul
proof.C = new(bn256.G1).Add(proof.C, new(bn256.G1).ScalarMult(pk.VkDelta1, rsneg)) proof.C = new(bn256.G1).Add(proof.C, new(bn256.G1).ScalarMult(pk.VkDelta1, rsneg))
pubSignals := w[1 : pk.NPublic+1] pubSignals := w[1 : pk.NPublic+1]
@ -110,23 +115,23 @@ func calculateH(pk *ProvingKey, w Witness) []*big.Int {
polCT := arrayOfZeroes(m) polCT := arrayOfZeroes(m)
for i := 0; i < pk.NVars; i++ { for i := 0; i < pk.NVars; i++ {
for j, _ := range pk.PolsA[i] {
polAT[j] = FAdd(polAT[j], FMul(w[i], pk.PolsA[i][j]))
for j := range pk.PolsA[i] {
polAT[j] = fAdd(polAT[j], fMul(w[i], pk.PolsA[i][j]))
fmt.Println(polAT[j]) fmt.Println(polAT[j])
} }
for j, _ := range pk.PolsB[i] {
polBT[j] = FAdd(polBT[j], FMul(w[i], pk.PolsB[i][j]))
for j := range pk.PolsB[i] {
polBT[j] = fAdd(polBT[j], fMul(w[i], pk.PolsB[i][j]))
} }
for j, _ := range pk.PolsC[i] {
polCT[j] = FAdd(polCT[j], FMul(w[i], pk.PolsC[i][j]))
for j := range pk.PolsC[i] {
polCT[j] = fAdd(polCT[j], fMul(w[i], pk.PolsC[i][j]))
} }
} }
polAS := ifft(polAT) polAS := ifft(polAT)
polBS := ifft(polBT) polBS := ifft(polBT)
polABS := PolynomialMul(polAS, polBS)
polABS := polynomialMul(polAS, polBS)
polCS := ifft(polCT) polCS := ifft(polCT)
polABCS := PolynomialSub(polABS, polCS)
polABCS := polynomialSub(polABS, polCS)
hS := polABCS[m:] hS := polABCS[m:]
return hS return hS

+ 2
- 2
prover_test.go

@ -10,7 +10,7 @@ import (
"github.com/stretchr/testify/require" "github.com/stretchr/testify/require"
) )
func TestProve(t *testing.T) {
func TestGenerateProf(t *testing.T) {
provingKeyJson, err := ioutil.ReadFile("testdata/provingkey.json") provingKeyJson, err := ioutil.ReadFile("testdata/provingkey.json")
require.Nil(t, err) require.Nil(t, err)
pk, err := ParseProvingKey(provingKeyJson) pk, err := ParseProvingKey(provingKeyJson)
@ -28,7 +28,7 @@ func TestProve(t *testing.T) {
fmt.Println("w", w) fmt.Println("w", w)
assert.Equal(t, Witness{big.NewInt(1), big.NewInt(33), big.NewInt(3), big.NewInt(11)}, w) assert.Equal(t, Witness{big.NewInt(1), big.NewInt(33), big.NewInt(3), big.NewInt(11)}, w)
proof, pubSignals, err := Prove(pk, w)
proof, pubSignals, err := GenerateProof(pk, w)
assert.Nil(t, err) assert.Nil(t, err)
fmt.Println("proof", proof) fmt.Println("proof", proof)
fmt.Println("pubSignals", pubSignals) fmt.Println("pubSignals", pubSignals)

Loading…
Cancel
Save