mirror of
https://github.com/arnaucube/go-circom-prover-verifier.git
synced 2026-02-06 19:06:43 +01:00
Update exposed methods, update README.md, add godoc & goreport cards
This commit is contained in:
27
README.md
27
README.md
@@ -1,5 +1,26 @@
|
||||
# go-circom-prover
|
||||
Experimental Go zkSNARK prover compatible with [circom](https://github.com/iden3/circom).
|
||||
# go-circom-prover [](https://godoc.org/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)
|
||||
```
|
||||
|
||||
@@ -13,35 +13,35 @@ func arrayOfZeroes(n int) []*big.Int {
|
||||
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)
|
||||
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)
|
||||
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)
|
||||
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))
|
||||
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)
|
||||
}
|
||||
|
||||
func FInv(a *big.Int) *big.Int {
|
||||
func fInv(a *big.Int) *big.Int {
|
||||
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)
|
||||
rem := new(big.Int).Set(e)
|
||||
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()) {
|
||||
// if BigIsOdd(rem) {
|
||||
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)
|
||||
}
|
||||
return res
|
||||
@@ -64,38 +64,38 @@ func max(a, b int) int {
|
||||
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)))
|
||||
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++ {
|
||||
r[i] = FSub(r[i], b[i])
|
||||
r[i] = fSub(r[i], b[i])
|
||||
}
|
||||
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)
|
||||
for i := 0; i < len(a); i++ {
|
||||
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
|
||||
}
|
||||
|
||||
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
|
||||
r := arrayOfZeroes(len(a) - len(b) + 1)
|
||||
rem := a
|
||||
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)
|
||||
r[pos] = l
|
||||
aux := arrayOfZeroes(pos)
|
||||
aux1 := append(aux, l)
|
||||
aux2 := PolynomialSub(rem, PolynomialMul(b, aux1))
|
||||
aux2 := polynomialSub(rem, polynomialMul(b, aux1))
|
||||
rem = aux2[:len(aux2)-1]
|
||||
}
|
||||
return r, rem
|
||||
|
||||
6
go.mod
6
go.mod
@@ -1,10 +1,8 @@
|
||||
module gocircom
|
||||
module gocircomprover
|
||||
|
||||
go 1.13
|
||||
|
||||
replace github.com/ethereum/go-ethereum => ../go-ethereum
|
||||
|
||||
require (
|
||||
github.com/ethereum/go-ethereum v1.9.12
|
||||
github.com/stretchr/testify v1.4.0
|
||||
github.com/stretchr/testify v1.5.1
|
||||
)
|
||||
|
||||
15
go.sum
15
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/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/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/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=
|
||||
@@ -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/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.4.0 h1:2E4SXV/wtOkTonXsotYi4li6zVWxYlZuYNCXe9XRJyk=
|
||||
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/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/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-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-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-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-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-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.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
|
||||
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/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/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/urfave/cli.v1 v1.20.0/go.mod h1:vuBzUtMdQeixQj8LVd+/98pzhxNGQoyuPBlsXHOQNO0=
|
||||
gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
|
||||
22
ifft.go
22
ifft.go
@@ -21,30 +21,28 @@ func newRootsT() rootsT {
|
||||
rem = new(big.Int).Rsh(rem, 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
|
||||
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--
|
||||
}
|
||||
roots.roots = make([][]*big.Int, 50)
|
||||
roots.roots = make([][]*big.Int, 50) // TODO WIP
|
||||
|
||||
roots.setRoots(15)
|
||||
return roots
|
||||
}
|
||||
|
||||
func (roots rootsT) setRoots(n int) {
|
||||
// var roots []bool
|
||||
for i := n; i >= 0 && nil == roots.roots[i]; i-- { // TODO tmp i<=len(r)
|
||||
r := big.NewInt(1)
|
||||
nroots := 1 << i
|
||||
var rootsi []*big.Int
|
||||
for j := 0; j < nroots; j++ {
|
||||
rootsi = append(rootsi, r)
|
||||
r = FMul(r, roots.w[i])
|
||||
r = fMul(r, roots.w[i])
|
||||
}
|
||||
// fmt.Println("rootsi", 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]}
|
||||
} else if n == 2 {
|
||||
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)
|
||||
for i := 0; i < ndiv2; i++ {
|
||||
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
|
||||
}
|
||||
@@ -85,11 +83,11 @@ func ifft(p []*big.Int) []*big.Int {
|
||||
ep := extend(p, m)
|
||||
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
|
||||
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
|
||||
|
||||
@@ -12,6 +12,7 @@ import (
|
||||
bn256 "github.com/ethereum/go-ethereum/crypto/bn256/cloudflare"
|
||||
)
|
||||
|
||||
// ProvingKeyString is the equivalent to the ProvingKey struct in string representation
|
||||
type ProvingKeyString struct {
|
||||
A [][]string `json:"A"`
|
||||
B2 [][][]string `json:"B2"`
|
||||
@@ -31,8 +32,10 @@ type ProvingKeyString struct {
|
||||
PolsC []map[string]string `json:"polsC"`
|
||||
}
|
||||
|
||||
// WitnessString contains the Witness in string representation
|
||||
type WitnessString []string
|
||||
|
||||
// ParseWitness parses the json []byte data into the Witness struct
|
||||
func ParseWitness(wJson []byte) (Witness, error) {
|
||||
var ws WitnessString
|
||||
err := json.Unmarshal(wJson, &ws)
|
||||
@@ -51,6 +54,7 @@ func ParseWitness(wJson []byte) (Witness, error) {
|
||||
return w, nil
|
||||
}
|
||||
|
||||
// ParseProvingKey parses the json []byte data into the ProvingKey struct
|
||||
func ParseProvingKey(pkJson []byte) (*ProvingKey, error) {
|
||||
var pkStr ProvingKeyString
|
||||
err := json.Unmarshal(pkJson, &pkStr)
|
||||
|
||||
@@ -8,22 +8,22 @@ import (
|
||||
|
||||
func TestParseArrayG1(t *testing.T) {
|
||||
aS := [][]string{
|
||||
[]string{
|
||||
{
|
||||
"16145916318196730299582072104388453231952213805668281741813587224450782397538",
|
||||
"4434505318477484327659527264104806919103674231447634885054368605283938696207",
|
||||
"1",
|
||||
},
|
||||
[]string{
|
||||
{
|
||||
"10618406967550056457559358662746625591602641004174976323307214433994084907915",
|
||||
"1843236360452735081347085412539192450068665510574800388201121698908391533923",
|
||||
"1",
|
||||
},
|
||||
[]string{
|
||||
{
|
||||
"1208972877970123411566574123860641832032384890981476033353526096830198333194",
|
||||
"777503551507025252294438107100944741641946695980350712141258191590862204805",
|
||||
"1",
|
||||
},
|
||||
[]string{
|
||||
{
|
||||
"0",
|
||||
"1",
|
||||
"0",
|
||||
@@ -40,15 +40,15 @@ func TestParseArrayG1(t *testing.T) {
|
||||
|
||||
func TestParseG2(t *testing.T) {
|
||||
aS := [][]string{
|
||||
[]string{
|
||||
{
|
||||
"9283666785342556550467669770956850930982548182701254051508520248901282197973",
|
||||
"11369378229277445316894458966429873744779877313900506577160370623273013178252",
|
||||
},
|
||||
[]string{
|
||||
{
|
||||
"10625777544326349817513295021482494426101347915428005055375725845993157551870",
|
||||
"21401790227434807639472120486932615400751346915707967674912972446672152512583",
|
||||
},
|
||||
[]string{
|
||||
{
|
||||
"1",
|
||||
"0",
|
||||
},
|
||||
@@ -59,15 +59,15 @@ func TestParseG2(t *testing.T) {
|
||||
assert.Equal(t, "bn256.G2((1922d70c934543aa655ec3277f7fa10a25ec973a4f001a7c54ce4954b4916f8c, 14865e836947c42cf35b47d30e06535fff9dab319c4296e28afde368960671d5), (2f50fbe77925b0a9d718c9ab38638bafa7c65f43f0d09035e518df97ad294847, 177dfa1a3b8627faf0425d9511bcb4c6ca986ea05e3803b5c643c35b94a7e6fe))", a.String())
|
||||
|
||||
aS = [][]string{
|
||||
[]string{
|
||||
{
|
||||
"13973091636763944887728510851169742544309374663995476311690518173988838518856",
|
||||
"12903946180439304546475897520537621821375470264150438270817301786763517825250",
|
||||
},
|
||||
[]string{
|
||||
{
|
||||
"370374369234123593044872519351942112043402224488849374153134091815693350697",
|
||||
"17423079115073430837335625309232513526393852743032331213038909731579295753224",
|
||||
},
|
||||
[]string{
|
||||
{
|
||||
"1",
|
||||
"0",
|
||||
},
|
||||
@@ -79,58 +79,58 @@ func TestParseG2(t *testing.T) {
|
||||
|
||||
func TestParseArrayG2(t *testing.T) {
|
||||
aS := [][][]string{
|
||||
[][]string{
|
||||
[]string{
|
||||
{
|
||||
{
|
||||
"0",
|
||||
"0",
|
||||
},
|
||||
[]string{
|
||||
{
|
||||
"1",
|
||||
"0",
|
||||
},
|
||||
[]string{
|
||||
{
|
||||
"0",
|
||||
"0",
|
||||
},
|
||||
},
|
||||
[][]string{
|
||||
[]string{
|
||||
{
|
||||
{
|
||||
"0",
|
||||
"0",
|
||||
},
|
||||
[]string{
|
||||
{
|
||||
"1",
|
||||
"0",
|
||||
},
|
||||
[]string{
|
||||
{
|
||||
"0",
|
||||
"0",
|
||||
},
|
||||
},
|
||||
[][]string{
|
||||
[]string{
|
||||
{
|
||||
{
|
||||
"0",
|
||||
"0",
|
||||
},
|
||||
[]string{
|
||||
{
|
||||
"1",
|
||||
"0",
|
||||
},
|
||||
[]string{
|
||||
{
|
||||
"0",
|
||||
"0",
|
||||
},
|
||||
},
|
||||
[][]string{
|
||||
[]string{
|
||||
{
|
||||
{
|
||||
"9283666785342556550467669770956850930982548182701254051508520248901282197973",
|
||||
"11369378229277445316894458966429873744779877313900506577160370623273013178252",
|
||||
},
|
||||
[]string{
|
||||
{
|
||||
"10625777544326349817513295021482494426101347915428005055375725845993157551870",
|
||||
"21401790227434807639472120486932615400751346915707967674912972446672152512583",
|
||||
},
|
||||
[]string{
|
||||
{
|
||||
"1",
|
||||
"0",
|
||||
},
|
||||
|
||||
31
prover.go
31
prover.go
@@ -8,12 +8,14 @@ import (
|
||||
bn256 "github.com/ethereum/go-ethereum/crypto/bn256/cloudflare"
|
||||
)
|
||||
|
||||
// Proof is the data structure of the Groth16 zkSNARK proof
|
||||
type Proof struct {
|
||||
A *bn256.G1
|
||||
B *bn256.G2
|
||||
C *bn256.G1
|
||||
}
|
||||
|
||||
// ProvingKey holds the data structure of the provingKey
|
||||
type ProvingKey struct {
|
||||
A []*bn256.G1
|
||||
B2 []*bn256.G2
|
||||
@@ -33,11 +35,13 @@ type ProvingKey struct {
|
||||
PolsC []map[int]*big.Int
|
||||
}
|
||||
|
||||
// Witness contains the witness
|
||||
type Witness []*big.Int
|
||||
|
||||
// R is the mod of the finite field
|
||||
var R, _ = new(big.Int).SetString("21888242871839275222246405745257275088548364400416034343698204186575808495617", 10)
|
||||
|
||||
func RandBigInt() (*big.Int, error) {
|
||||
func randBigInt() (*big.Int, error) {
|
||||
maxbits := R.BitLen()
|
||||
b := make([]byte, (maxbits/8)-1)
|
||||
_, err := rand.Read(b)
|
||||
@@ -50,14 +54,15 @@ func RandBigInt() (*big.Int, error) {
|
||||
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
|
||||
|
||||
r, err := RandBigInt()
|
||||
r, err := randBigInt()
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
s, err := RandBigInt()
|
||||
s, err := randBigInt()
|
||||
if err != nil {
|
||||
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(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))
|
||||
|
||||
pubSignals := w[1 : pk.NPublic+1]
|
||||
@@ -110,23 +115,23 @@ func calculateH(pk *ProvingKey, w Witness) []*big.Int {
|
||||
polCT := arrayOfZeroes(m)
|
||||
|
||||
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])
|
||||
}
|
||||
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)
|
||||
polBS := ifft(polBT)
|
||||
|
||||
polABS := PolynomialMul(polAS, polBS)
|
||||
polABS := polynomialMul(polAS, polBS)
|
||||
polCS := ifft(polCT)
|
||||
polABCS := PolynomialSub(polABS, polCS)
|
||||
polABCS := polynomialSub(polABS, polCS)
|
||||
|
||||
hS := polABCS[m:]
|
||||
return hS
|
||||
|
||||
@@ -10,7 +10,7 @@ import (
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
func TestProve(t *testing.T) {
|
||||
func TestGenerateProf(t *testing.T) {
|
||||
provingKeyJson, err := ioutil.ReadFile("testdata/provingkey.json")
|
||||
require.Nil(t, err)
|
||||
pk, err := ParseProvingKey(provingKeyJson)
|
||||
@@ -28,7 +28,7 @@ func TestProve(t *testing.T) {
|
||||
fmt.Println("w", 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)
|
||||
fmt.Println("proof", proof)
|
||||
fmt.Println("pubSignals", pubSignals)
|
||||
|
||||
Reference in New Issue
Block a user