mirror of
https://github.com/arnaucube/go-circom-prover-verifier.git
synced 2026-02-06 19:06:43 +01:00
Compare commits
25 Commits
feature/pa
...
master
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
4349ce584f | ||
|
|
9555517797 | ||
|
|
ec6920aa11 | ||
|
|
6e31deb5b8 | ||
|
|
94dc934f62 | ||
|
|
9f2587151f | ||
|
|
e652f34753 | ||
|
|
42961f6b94 | ||
|
|
386758370e | ||
|
|
2b8a15ca1a | ||
|
|
d1b3979eb6 | ||
|
|
de95d7a3e4 | ||
|
|
5c2aaec1ca | ||
|
|
bedd64cc70 | ||
|
|
0d4e2581bd | ||
|
|
1aa316cbd2 | ||
|
|
0f48cfa2a5 | ||
|
|
6ec118d4e2 | ||
|
|
423d5f0ce7 | ||
|
|
a314ecc02f | ||
|
|
700f2a4503 | ||
|
|
02fc1ea6f7 | ||
|
|
16054cc679 | ||
|
|
296dc53736 | ||
|
|
0977fac08c |
10
.github/workflows/main.yml
vendored
10
.github/workflows/main.yml
vendored
@@ -17,16 +17,12 @@ jobs:
|
||||
- name: Install Nodejs
|
||||
uses: actions/setup-node@v1
|
||||
with:
|
||||
go-version: 10.x
|
||||
- name: Install circom
|
||||
run: npm install -g circom
|
||||
- name: Install snarkjs
|
||||
run: npm install -g snarkjs
|
||||
node-version: '10.x'
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v2
|
||||
- name: Compile circuits and execute Go tests
|
||||
run: |
|
||||
cd testdata && sh ./compile-circuits.sh && cd ..
|
||||
go run cli/cli.go -prove -provingkey=testdata/circuit1k/proving_key.json -witness=testdata/circuit1k/witness.json -proof=testdata/circuit1k/proof.json -public=testdata/circuit1k/public.json
|
||||
go run cli/cli.go -prove -provingkey=testdata/circuit5k/proving_key.json -witness=testdata/circuit5k/witness.json -proof=testdata/circuit5k/proof.json -public=testdata/circuit5k/public.json
|
||||
go run cli/cli.go -prove -pk=testdata/circuit1k/proving_key.json -witness=testdata/circuit1k/witness.json -proof=testdata/circuit1k/proof.json -public=testdata/circuit1k/public.json
|
||||
go run cli/cli.go -prove -pk=testdata/circuit5k/proving_key.json -witness=testdata/circuit5k/witness.json -proof=testdata/circuit5k/proof.json -public=testdata/circuit5k/public.json
|
||||
go test ./...
|
||||
|
||||
1
.gitignore
vendored
1
.gitignore
vendored
@@ -4,5 +4,6 @@ testdata/*/*.cpp
|
||||
testdata/*/*.sym
|
||||
testdata/*/*.r1cs
|
||||
testdata/*/*.sol
|
||||
testdata/*/*.bin
|
||||
!testdata/*/inputs.json
|
||||
cli/*.json
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
# go-circom-prover-verifier [](https://godoc.org/github.com/iden3/go-circom-prover-verifier) [](https://goreportcard.com/report/github.com/iden3/go-circom-prover-verifier) [](https://github.com/iden3/go-circom-prover-verifier/actions?query=workflow%3ATest)
|
||||
|
||||
Experimental Go implementation of the [Groth16 protocol](https://eprint.iacr.org/2016/260.pdf) zkSNARK prover & verifier compatible with [circom](https://github.com/iden3/circom).
|
||||
Go implementation of the [Groth16 protocol](https://eprint.iacr.org/2016/260.pdf) zkSNARK prover & verifier 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 curve operations.
|
||||
@@ -82,9 +82,9 @@ Usage of /tmp/go-build620318239/b001/exe/cli:
|
||||
|
||||
- Prove
|
||||
```
|
||||
> go run cli.go -prove -provingkey=../testdata/small/proving_key.json -witness=../testdata/small/witness.json
|
||||
> go run cli.go -prove -provingkey=../testdata/circuit5k/proving_key.json -witness=../testdata/circuit5k/witness.json
|
||||
```
|
||||
- Verify
|
||||
```
|
||||
> go run cli.go -verify -verificationkey=../testdata/small/verification_key.json
|
||||
> go run cli.go -verify -verificationkey=../testdata/circuit5k/verification_key.json
|
||||
```
|
||||
|
||||
1
cli/.gitignore
vendored
Normal file
1
cli/.gitignore
vendored
Normal file
@@ -0,0 +1 @@
|
||||
cli
|
||||
43
cli/cli.go
43
cli/cli.go
@@ -5,6 +5,7 @@ import (
|
||||
"flag"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"time"
|
||||
|
||||
"github.com/iden3/go-circom-prover-verifier/parsers"
|
||||
@@ -20,12 +21,14 @@ func main() {
|
||||
|
||||
prove := flag.Bool("prove", false, "prover mode")
|
||||
verify := flag.Bool("verify", false, "verifier mode")
|
||||
convert := flag.Bool("convert", false, "convert mode, to convert between proving_key.json to proving_key.go.bin")
|
||||
|
||||
provingKeyPath := flag.String("provingkey", "proving_key.json", "provingKey path")
|
||||
provingKeyPath := flag.String("pk", "proving_key.json", "provingKey path")
|
||||
witnessPath := flag.String("witness", "witness.json", "witness path")
|
||||
proofPath := flag.String("proof", "proof.json", "proof path")
|
||||
verificationKeyPath := flag.String("verificationkey", "verification_key.json", "verificationKey path")
|
||||
verificationKeyPath := flag.String("vk", "verification_key.json", "verificationKey path")
|
||||
publicPath := flag.String("public", "public.json", "public signals path")
|
||||
provingKeyBinPath := flag.String("pkbin", "proving_key.go.bin", "provingKey Bin path")
|
||||
|
||||
flag.Parse()
|
||||
|
||||
@@ -34,15 +37,21 @@ func main() {
|
||||
if err != nil {
|
||||
fmt.Println("Error:", err)
|
||||
}
|
||||
return
|
||||
os.Exit(0)
|
||||
} else if *verify {
|
||||
err := cmdVerify(*proofPath, *verificationKeyPath, *publicPath)
|
||||
if err != nil {
|
||||
fmt.Println("Error:", err)
|
||||
}
|
||||
return
|
||||
os.Exit(0)
|
||||
} else if *convert {
|
||||
err := cmdConvert(*provingKeyPath, *provingKeyBinPath)
|
||||
if err != nil {
|
||||
fmt.Println("Error:", err)
|
||||
}
|
||||
os.Exit(0)
|
||||
}
|
||||
fmt.Println("use -help for the list of commands")
|
||||
flag.PrintDefaults()
|
||||
}
|
||||
|
||||
func cmdProve(provingKeyPath, witnessPath, proofPath, publicPath string) error {
|
||||
@@ -132,3 +141,27 @@ func cmdVerify(proofPath, verificationKeyPath, publicPath string) error {
|
||||
fmt.Println("verification:", v)
|
||||
return nil
|
||||
}
|
||||
|
||||
func cmdConvert(provingKeyPath, provingKeyBinPath string) error {
|
||||
fmt.Println("Convertion tool")
|
||||
|
||||
provingKeyJson, err := ioutil.ReadFile(provingKeyPath)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
pk, err := parsers.ParsePk(provingKeyJson)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
fmt.Printf("Converting proving key json (%s)\nto go proving key binary (%s)\n", provingKeyPath, provingKeyBinPath)
|
||||
pkGBin, err := parsers.PkToGoBin(pk)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if err = ioutil.WriteFile(provingKeyBinPath, pkGBin, 0644); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
2
go.mod
2
go.mod
@@ -4,6 +4,6 @@ go 1.14
|
||||
|
||||
require (
|
||||
github.com/ethereum/go-ethereum v1.9.13
|
||||
github.com/iden3/go-iden3-crypto v0.0.5-0.20200421133134-14c3144613d4
|
||||
github.com/iden3/go-iden3-crypto v0.0.5
|
||||
github.com/stretchr/testify v1.4.0
|
||||
)
|
||||
|
||||
2
go.sum
2
go.sum
@@ -68,6 +68,8 @@ github.com/iden3/go-iden3-crypto v0.0.4 h1:rGQEFBvX6d4fDxqkQTizVq5UefB+xdZAg8j5F
|
||||
github.com/iden3/go-iden3-crypto v0.0.4/go.mod h1:LLcgB7DLWAUs+8eBSKne+ZHy5z7xtAmlYlEz0M9M8gE=
|
||||
github.com/iden3/go-iden3-crypto v0.0.5-0.20200421133134-14c3144613d4 h1:C+WGAJM9G5MxU62cAVrcwivFLk1muyENjGD5DGADk5o=
|
||||
github.com/iden3/go-iden3-crypto v0.0.5-0.20200421133134-14c3144613d4/go.mod h1:XKw1oDwYn2CIxKOtr7m/mL5jMn4mLOxAxtZBRxQBev8=
|
||||
github.com/iden3/go-iden3-crypto v0.0.5 h1:inCSm5a+ry+nbpVTL/9+m6UcIwSv6nhUm0tnIxEbcps=
|
||||
github.com/iden3/go-iden3-crypto v0.0.5/go.mod h1:XKw1oDwYn2CIxKOtr7m/mL5jMn4mLOxAxtZBRxQBev8=
|
||||
github.com/influxdata/influxdb v1.2.3-0.20180221223340-01288bdb0883/go.mod h1:qZna6X/4elxqT3yI9iZYdZrWWdeFOOprn86kgg4+IzY=
|
||||
github.com/jackpal/go-nat-pmp v1.0.2-0.20160603034137-1fa385a6f458/go.mod h1:QPH045xvCAeXUZOxsnwmrtiCoxIr9eob+4orBN1SBKc=
|
||||
github.com/jmespath/go-jmespath v0.0.0-20180206201540-c2b33e8439af/go.mod h1:Nht3zPeWKUH0NzdCt2Blrr5ys8VGpn0CEB0cQHVjt7k=
|
||||
|
||||
@@ -1,11 +1,16 @@
|
||||
package parsers
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"bytes"
|
||||
"encoding/binary"
|
||||
"encoding/hex"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io"
|
||||
"math/big"
|
||||
"os"
|
||||
"sort"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
@@ -30,7 +35,6 @@ type PkString struct {
|
||||
DomainSize int `json:"domainSize"`
|
||||
PolsA []map[string]string `json:"polsA"`
|
||||
PolsB []map[string]string `json:"polsB"`
|
||||
PolsC []map[string]string `json:"polsC"`
|
||||
}
|
||||
|
||||
// WitnessString contains the Witness in string representation
|
||||
@@ -145,10 +149,6 @@ func pkStringToPk(ps PkString) (*types.Pk, error) {
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
p.PolsC, err = polsStringToBigInt(ps.PolsC)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &p, nil
|
||||
}
|
||||
@@ -305,6 +305,13 @@ func stringToBigInt(s string) (*big.Int, error) {
|
||||
return n, nil
|
||||
}
|
||||
|
||||
func addPadding32(b []byte) []byte {
|
||||
if len(b) != 32 {
|
||||
b = addZPadding(b)
|
||||
}
|
||||
return b
|
||||
}
|
||||
|
||||
func addZPadding(b []byte) []byte {
|
||||
var z [32]byte
|
||||
var r []byte
|
||||
@@ -464,8 +471,35 @@ func stringToG2(h [][]string) (*bn256.G2, error) {
|
||||
return p, err
|
||||
}
|
||||
|
||||
// ProofToJson outputs the Proof i Json format
|
||||
func ProofToJson(p *types.Proof) ([]byte, error) {
|
||||
// ProofStringToSmartContractFormat converts the ProofString to a ProofString in the SmartContract format in a ProofString structure
|
||||
func ProofStringToSmartContractFormat(s ProofString) ProofString {
|
||||
var rs ProofString
|
||||
rs.A = make([]string, 2)
|
||||
rs.B = make([][]string, 2)
|
||||
rs.B[0] = make([]string, 2)
|
||||
rs.B[1] = make([]string, 2)
|
||||
rs.C = make([]string, 2)
|
||||
|
||||
rs.A[0] = s.A[0]
|
||||
rs.A[1] = s.A[1]
|
||||
rs.B[0][0] = s.B[0][1]
|
||||
rs.B[0][1] = s.B[0][0]
|
||||
rs.B[1][0] = s.B[1][1]
|
||||
rs.B[1][1] = s.B[1][0]
|
||||
rs.C[0] = s.C[0]
|
||||
rs.C[1] = s.C[1]
|
||||
rs.Protocol = s.Protocol
|
||||
return rs
|
||||
}
|
||||
|
||||
// ProofToSmartContractFormat converts the *types.Proof to a ProofString in the SmartContract format in a ProofString structure
|
||||
func ProofToSmartContractFormat(p *types.Proof) ProofString {
|
||||
s := ProofToString(p)
|
||||
return ProofStringToSmartContractFormat(s)
|
||||
}
|
||||
|
||||
// ProofToString converts the Proof to ProofString
|
||||
func ProofToString(p *types.Proof) ProofString {
|
||||
var ps ProofString
|
||||
ps.A = make([]string, 3)
|
||||
ps.B = make([][]string, 3)
|
||||
@@ -494,5 +528,801 @@ func ProofToJson(p *types.Proof) ([]byte, error) {
|
||||
|
||||
ps.Protocol = "groth"
|
||||
|
||||
return ps
|
||||
}
|
||||
|
||||
// ProofToJson outputs the Proof i Json format
|
||||
func ProofToJson(p *types.Proof) ([]byte, error) {
|
||||
ps := ProofToString(p)
|
||||
return json.Marshal(ps)
|
||||
}
|
||||
|
||||
// ProofToHex converts the Proof to ProofString with hexadecimal strings
|
||||
func ProofToHex(p *types.Proof) ProofString {
|
||||
var ps ProofString
|
||||
ps.A = make([]string, 3)
|
||||
ps.B = make([][]string, 3)
|
||||
ps.B[0] = make([]string, 2)
|
||||
ps.B[1] = make([]string, 2)
|
||||
ps.B[2] = make([]string, 2)
|
||||
ps.C = make([]string, 3)
|
||||
|
||||
a := p.A.Marshal()
|
||||
ps.A[0] = "0x" + hex.EncodeToString(new(big.Int).SetBytes(a[:32]).Bytes())
|
||||
ps.A[1] = "0x" + hex.EncodeToString(new(big.Int).SetBytes(a[32:64]).Bytes())
|
||||
ps.A[2] = "1"
|
||||
|
||||
b := p.B.Marshal()
|
||||
ps.B[0][1] = "0x" + hex.EncodeToString(new(big.Int).SetBytes(b[:32]).Bytes())
|
||||
ps.B[0][0] = "0x" + hex.EncodeToString(new(big.Int).SetBytes(b[32:64]).Bytes())
|
||||
ps.B[1][1] = "0x" + hex.EncodeToString(new(big.Int).SetBytes(b[64:96]).Bytes())
|
||||
ps.B[1][0] = "0x" + hex.EncodeToString(new(big.Int).SetBytes(b[96:128]).Bytes())
|
||||
ps.B[2][0] = "1"
|
||||
ps.B[2][1] = "0"
|
||||
|
||||
c := p.C.Marshal()
|
||||
ps.C[0] = "0x" + hex.EncodeToString(new(big.Int).SetBytes(c[:32]).Bytes())
|
||||
ps.C[1] = "0x" + hex.EncodeToString(new(big.Int).SetBytes(c[32:64]).Bytes())
|
||||
ps.C[2] = "1"
|
||||
|
||||
ps.Protocol = "groth"
|
||||
|
||||
return ps
|
||||
}
|
||||
|
||||
// ProofToJsonHex outputs the Proof i Json format with hexadecimal strings
|
||||
func ProofToJsonHex(p *types.Proof) ([]byte, error) {
|
||||
ps := ProofToHex(p)
|
||||
return json.Marshal(ps)
|
||||
}
|
||||
|
||||
// ParseWitnessBin parses binary file representation of the Witness into the Witness struct
|
||||
func ParseWitnessBin(f *os.File) (types.Witness, error) {
|
||||
var w types.Witness
|
||||
r := bufio.NewReader(f)
|
||||
for {
|
||||
b := make([]byte, 32)
|
||||
n, err := r.Read(b)
|
||||
if err == io.EOF {
|
||||
return w, nil
|
||||
} else if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if n != 32 {
|
||||
return nil, fmt.Errorf("error on value format, expected 32 bytes, got %v", n)
|
||||
}
|
||||
w = append(w, new(big.Int).SetBytes(swapEndianness(b[0:32])))
|
||||
}
|
||||
}
|
||||
|
||||
// swapEndianness swaps the order of the bytes in the slice.
|
||||
func swapEndianness(b []byte) []byte {
|
||||
o := make([]byte, len(b))
|
||||
for i := range b {
|
||||
o[len(b)-1-i] = b[i]
|
||||
}
|
||||
return o
|
||||
}
|
||||
|
||||
func readNBytes(r io.Reader, n int) ([]byte, error) {
|
||||
b := make([]byte, n)
|
||||
_, err := io.ReadFull(r, b)
|
||||
if err != nil {
|
||||
return b, err
|
||||
}
|
||||
return b, nil
|
||||
}
|
||||
|
||||
// ParsePkBin parses binary file representation of the ProvingKey into the ProvingKey struct
|
||||
func ParsePkBin(f *os.File) (*types.Pk, error) {
|
||||
o := 0
|
||||
var pk types.Pk
|
||||
r := bufio.NewReader(f)
|
||||
|
||||
b, err := readNBytes(r, 12)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
pk.NVars = int(binary.LittleEndian.Uint32(b[:4]))
|
||||
pk.NPublic = int(binary.LittleEndian.Uint32(b[4:8]))
|
||||
pk.DomainSize = int(binary.LittleEndian.Uint32(b[8:12]))
|
||||
o += 12
|
||||
|
||||
b, err = readNBytes(r, 8)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
pPolsA := int(binary.LittleEndian.Uint32(b[:4]))
|
||||
pPolsB := int(binary.LittleEndian.Uint32(b[4:8]))
|
||||
o += 8
|
||||
|
||||
b, err = readNBytes(r, 20)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
pPointsA := int(binary.LittleEndian.Uint32(b[:4]))
|
||||
pPointsB1 := int(binary.LittleEndian.Uint32(b[4:8]))
|
||||
pPointsB2 := int(binary.LittleEndian.Uint32(b[8:12]))
|
||||
pPointsC := int(binary.LittleEndian.Uint32(b[12:16]))
|
||||
pPointsHExps := int(binary.LittleEndian.Uint32(b[16:20]))
|
||||
o += 20
|
||||
|
||||
b, err = readNBytes(r, 64)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
pk.VkAlpha1 = new(bn256.G1)
|
||||
_, err = pk.VkAlpha1.Unmarshal(fromMont1Q(b))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
b, err = readNBytes(r, 64)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
pk.VkBeta1 = new(bn256.G1)
|
||||
_, err = pk.VkBeta1.Unmarshal(fromMont1Q(b))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
b, err = readNBytes(r, 64)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
pk.VkDelta1 = new(bn256.G1)
|
||||
_, err = pk.VkDelta1.Unmarshal(fromMont1Q(b))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
b, err = readNBytes(r, 128)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
pk.VkBeta2 = new(bn256.G2)
|
||||
_, err = pk.VkBeta2.Unmarshal(fromMont2Q(b))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
b, err = readNBytes(r, 128)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
pk.VkDelta2 = new(bn256.G2)
|
||||
_, err = pk.VkDelta2.Unmarshal(fromMont2Q(b))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
o += 448
|
||||
if o != pPolsA {
|
||||
return nil, fmt.Errorf("Unexpected offset, expected: %v, actual: %v", pPolsA, o)
|
||||
}
|
||||
|
||||
// PolsA
|
||||
for i := 0; i < pk.NVars; i++ {
|
||||
b, err = readNBytes(r, 4)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
keysLength := int(binary.LittleEndian.Uint32(b[:4]))
|
||||
o += 4
|
||||
polsMap := make(map[int]*big.Int)
|
||||
for j := 0; j < keysLength; j++ {
|
||||
bK, err := readNBytes(r, 4)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
key := int(binary.LittleEndian.Uint32(bK[:4]))
|
||||
o += 4
|
||||
|
||||
b, err := readNBytes(r, 32)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
polsMap[key] = new(big.Int).SetBytes(fromMont1R(b[:32]))
|
||||
o += 32
|
||||
}
|
||||
pk.PolsA = append(pk.PolsA, polsMap)
|
||||
}
|
||||
if o != pPolsB {
|
||||
return nil, fmt.Errorf("Unexpected offset, expected: %v, actual: %v", pPolsB, o)
|
||||
}
|
||||
// PolsB
|
||||
for i := 0; i < pk.NVars; i++ {
|
||||
b, err = readNBytes(r, 4)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
keysLength := int(binary.LittleEndian.Uint32(b[:4]))
|
||||
o += 4
|
||||
polsMap := make(map[int]*big.Int)
|
||||
for j := 0; j < keysLength; j++ {
|
||||
bK, err := readNBytes(r, 4)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
key := int(binary.LittleEndian.Uint32(bK[:4]))
|
||||
o += 4
|
||||
|
||||
b, err := readNBytes(r, 32)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
polsMap[key] = new(big.Int).SetBytes(fromMont1R(b[:32]))
|
||||
o += 32
|
||||
}
|
||||
pk.PolsB = append(pk.PolsB, polsMap)
|
||||
}
|
||||
if o != pPointsA {
|
||||
return nil, fmt.Errorf("Unexpected offset, expected: %v, actual: %v", pPointsA, o)
|
||||
}
|
||||
// A
|
||||
for i := 0; i < pk.NVars; i++ {
|
||||
b, err = readNBytes(r, 64)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
p1 := new(bn256.G1)
|
||||
_, err = p1.Unmarshal(fromMont1Q(b))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
pk.A = append(pk.A, p1)
|
||||
o += 64
|
||||
}
|
||||
if o != pPointsB1 {
|
||||
return nil, fmt.Errorf("Unexpected offset, expected: %v, actual: %v", pPointsB1, o)
|
||||
}
|
||||
// B1
|
||||
for i := 0; i < pk.NVars; i++ {
|
||||
b, err = readNBytes(r, 64)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
p1 := new(bn256.G1)
|
||||
_, err = p1.Unmarshal(fromMont1Q(b))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
pk.B1 = append(pk.B1, p1)
|
||||
o += 64
|
||||
}
|
||||
if o != pPointsB2 {
|
||||
return nil, fmt.Errorf("Unexpected offset, expected: %v, actual: %v", pPointsB2, o)
|
||||
}
|
||||
// B2
|
||||
for i := 0; i < pk.NVars; i++ {
|
||||
b, err = readNBytes(r, 128)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
p2 := new(bn256.G2)
|
||||
_, err = p2.Unmarshal(fromMont2Q(b))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
pk.B2 = append(pk.B2, p2)
|
||||
o += 128
|
||||
}
|
||||
if o != pPointsC {
|
||||
return nil, fmt.Errorf("Unexpected offset, expected: %v, actual: %v", pPointsC, o)
|
||||
}
|
||||
// C
|
||||
zb := make([]byte, 64)
|
||||
z := new(bn256.G1)
|
||||
_, err = z.Unmarshal(zb)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
for i := 0; i < pk.NPublic+1; i++ {
|
||||
pk.C = append(pk.C, z)
|
||||
}
|
||||
for i := pk.NPublic + 1; i < pk.NVars; i++ {
|
||||
b, err = readNBytes(r, 64)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
p1 := new(bn256.G1)
|
||||
_, err = p1.Unmarshal(fromMont1Q(b))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
pk.C = append(pk.C, p1)
|
||||
o += 64
|
||||
}
|
||||
if o != pPointsHExps {
|
||||
return nil, fmt.Errorf("Unexpected offset, expected: %v, actual: %v", pPointsHExps, o)
|
||||
}
|
||||
// HExps
|
||||
for i := 0; i < pk.DomainSize; i++ {
|
||||
b, err = readNBytes(r, 64)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
p1 := new(bn256.G1)
|
||||
_, err = p1.Unmarshal(fromMont1Q(b))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
pk.HExps = append(pk.HExps, p1)
|
||||
}
|
||||
return &pk, nil
|
||||
}
|
||||
|
||||
func fromMont1Q(m []byte) []byte {
|
||||
a := new(big.Int).SetBytes(swapEndianness(m[:32]))
|
||||
b := new(big.Int).SetBytes(swapEndianness(m[32:64]))
|
||||
|
||||
x := coordFromMont(a, types.Q)
|
||||
y := coordFromMont(b, types.Q)
|
||||
if bytes.Equal(x.Bytes(), big.NewInt(1).Bytes()) {
|
||||
x = big.NewInt(0)
|
||||
}
|
||||
if bytes.Equal(y.Bytes(), big.NewInt(1).Bytes()) {
|
||||
y = big.NewInt(0)
|
||||
}
|
||||
|
||||
xBytes := x.Bytes()
|
||||
yBytes := y.Bytes()
|
||||
if len(xBytes) != 32 {
|
||||
xBytes = addZPadding(xBytes)
|
||||
}
|
||||
if len(yBytes) != 32 {
|
||||
yBytes = addZPadding(yBytes)
|
||||
}
|
||||
|
||||
var p []byte
|
||||
p = append(p, xBytes...)
|
||||
p = append(p, yBytes...)
|
||||
|
||||
return p
|
||||
}
|
||||
|
||||
func fromMont2Q(m []byte) []byte {
|
||||
a := new(big.Int).SetBytes(swapEndianness(m[:32]))
|
||||
b := new(big.Int).SetBytes(swapEndianness(m[32:64]))
|
||||
c := new(big.Int).SetBytes(swapEndianness(m[64:96]))
|
||||
d := new(big.Int).SetBytes(swapEndianness(m[96:128]))
|
||||
|
||||
x := coordFromMont(a, types.Q)
|
||||
y := coordFromMont(b, types.Q)
|
||||
z := coordFromMont(c, types.Q)
|
||||
t := coordFromMont(d, types.Q)
|
||||
|
||||
if bytes.Equal(x.Bytes(), big.NewInt(1).Bytes()) {
|
||||
x = big.NewInt(0)
|
||||
}
|
||||
if bytes.Equal(y.Bytes(), big.NewInt(1).Bytes()) {
|
||||
y = big.NewInt(0)
|
||||
}
|
||||
if bytes.Equal(z.Bytes(), big.NewInt(1).Bytes()) {
|
||||
z = big.NewInt(0)
|
||||
}
|
||||
if bytes.Equal(t.Bytes(), big.NewInt(1).Bytes()) {
|
||||
t = big.NewInt(0)
|
||||
}
|
||||
|
||||
xBytes := x.Bytes()
|
||||
yBytes := y.Bytes()
|
||||
zBytes := z.Bytes()
|
||||
tBytes := t.Bytes()
|
||||
if len(xBytes) != 32 {
|
||||
xBytes = addZPadding(xBytes)
|
||||
}
|
||||
if len(yBytes) != 32 {
|
||||
yBytes = addZPadding(yBytes)
|
||||
}
|
||||
if len(zBytes) != 32 {
|
||||
zBytes = addZPadding(zBytes)
|
||||
}
|
||||
if len(tBytes) != 32 {
|
||||
tBytes = addZPadding(tBytes)
|
||||
}
|
||||
|
||||
var p []byte
|
||||
p = append(p, yBytes...) // swap
|
||||
p = append(p, xBytes...)
|
||||
p = append(p, tBytes...)
|
||||
p = append(p, zBytes...)
|
||||
|
||||
return p
|
||||
}
|
||||
|
||||
func fromMont1R(m []byte) []byte {
|
||||
a := new(big.Int).SetBytes(swapEndianness(m[:32]))
|
||||
|
||||
x := coordFromMont(a, types.R)
|
||||
|
||||
return x.Bytes()
|
||||
}
|
||||
|
||||
func fromMont2R(m []byte) []byte {
|
||||
a := new(big.Int).SetBytes(swapEndianness(m[:32]))
|
||||
b := new(big.Int).SetBytes(swapEndianness(m[32:64]))
|
||||
c := new(big.Int).SetBytes(swapEndianness(m[64:96]))
|
||||
d := new(big.Int).SetBytes(swapEndianness(m[96:128]))
|
||||
|
||||
x := coordFromMont(a, types.R)
|
||||
y := coordFromMont(b, types.R)
|
||||
z := coordFromMont(c, types.R)
|
||||
t := coordFromMont(d, types.R)
|
||||
|
||||
var p []byte
|
||||
p = append(p, y.Bytes()...) // swap
|
||||
p = append(p, x.Bytes()...)
|
||||
p = append(p, t.Bytes()...)
|
||||
p = append(p, z.Bytes()...)
|
||||
|
||||
return p
|
||||
}
|
||||
|
||||
func coordFromMont(u, q *big.Int) *big.Int {
|
||||
return new(big.Int).Mod(
|
||||
new(big.Int).Mul(
|
||||
u,
|
||||
new(big.Int).ModInverse(
|
||||
new(big.Int).Lsh(big.NewInt(1), 256),
|
||||
q,
|
||||
),
|
||||
),
|
||||
q,
|
||||
)
|
||||
}
|
||||
|
||||
func sortedKeys(m map[int]*big.Int) []int {
|
||||
keys := make([]int, 0, len(m))
|
||||
for k, _ := range m {
|
||||
keys = append(keys, k)
|
||||
}
|
||||
sort.Ints(keys)
|
||||
return keys
|
||||
}
|
||||
|
||||
// PkToGoBin converts the ProvingKey (*types.Pk) into binary format defined by
|
||||
// go-circom-prover-verifier. PkGoBin is a own go-circom-prover-verifier
|
||||
// binary format that allows to go faster when parsing.
|
||||
func PkToGoBin(pk *types.Pk) ([]byte, error) {
|
||||
var r []byte
|
||||
o := 0
|
||||
var b [4]byte
|
||||
binary.LittleEndian.PutUint32(b[:], uint32(pk.NVars))
|
||||
r = append(r, b[:]...)
|
||||
|
||||
binary.LittleEndian.PutUint32(b[:], uint32(pk.NPublic))
|
||||
r = append(r, b[:]...)
|
||||
|
||||
binary.LittleEndian.PutUint32(b[:], uint32(pk.DomainSize))
|
||||
r = append(r, b[:]...)
|
||||
o += 12
|
||||
|
||||
// reserve space for pols (A, B) pos
|
||||
b = [4]byte{}
|
||||
r = append(r, b[:]...) // 12:16
|
||||
r = append(r, b[:]...) // 16:20
|
||||
o += 8
|
||||
// reserve space for points (A, B1, B2, C, HExps) pos
|
||||
r = append(r, b[:]...) // 20:24
|
||||
r = append(r, b[:]...) // 24
|
||||
r = append(r, b[:]...) // 28
|
||||
r = append(r, b[:]...) // 32
|
||||
r = append(r, b[:]...) // 36:40
|
||||
o += 20
|
||||
|
||||
pb1 := pk.VkAlpha1.Marshal()
|
||||
r = append(r, pb1[:]...)
|
||||
pb1 = pk.VkBeta1.Marshal()
|
||||
r = append(r, pb1[:]...)
|
||||
pb1 = pk.VkDelta1.Marshal()
|
||||
r = append(r, pb1[:]...)
|
||||
pb2 := pk.VkBeta2.Marshal()
|
||||
r = append(r, pb2[:]...)
|
||||
pb2 = pk.VkDelta2.Marshal()
|
||||
r = append(r, pb2[:]...)
|
||||
o += 448
|
||||
|
||||
// polsA
|
||||
binary.LittleEndian.PutUint32(r[12:16], uint32(o))
|
||||
for i := 0; i < pk.NVars; i++ {
|
||||
binary.LittleEndian.PutUint32(b[:], uint32(len(pk.PolsA[i])))
|
||||
r = append(r, b[:]...)
|
||||
o += 4
|
||||
for _, j := range sortedKeys(pk.PolsA[i]) {
|
||||
v := pk.PolsA[i][j]
|
||||
binary.LittleEndian.PutUint32(b[:], uint32(j))
|
||||
r = append(r, b[:]...)
|
||||
r = append(r, addPadding32(v.Bytes())...)
|
||||
o += 32 + 4
|
||||
}
|
||||
}
|
||||
// polsB
|
||||
binary.LittleEndian.PutUint32(r[16:20], uint32(o))
|
||||
for i := 0; i < pk.NVars; i++ {
|
||||
binary.LittleEndian.PutUint32(b[:], uint32(len(pk.PolsB[i])))
|
||||
r = append(r, b[:]...)
|
||||
o += 4
|
||||
for _, j := range sortedKeys(pk.PolsB[i]) {
|
||||
v := pk.PolsB[i][j]
|
||||
binary.LittleEndian.PutUint32(b[:], uint32(j))
|
||||
r = append(r, b[:]...)
|
||||
r = append(r, addPadding32(v.Bytes())...)
|
||||
o += 32 + 4
|
||||
}
|
||||
}
|
||||
// A
|
||||
binary.LittleEndian.PutUint32(r[20:24], uint32(o))
|
||||
for i := 0; i < pk.NVars; i++ {
|
||||
pb1 = pk.A[i].Marshal()
|
||||
r = append(r, pb1[:]...)
|
||||
o += 64
|
||||
}
|
||||
// B1
|
||||
binary.LittleEndian.PutUint32(r[24:28], uint32(o))
|
||||
for i := 0; i < pk.NVars; i++ {
|
||||
pb1 = pk.B1[i].Marshal()
|
||||
r = append(r, pb1[:]...)
|
||||
o += 64
|
||||
}
|
||||
// B2
|
||||
binary.LittleEndian.PutUint32(r[28:32], uint32(o))
|
||||
for i := 0; i < pk.NVars; i++ {
|
||||
pb2 = pk.B2[i].Marshal()
|
||||
r = append(r, pb2[:]...)
|
||||
o += 128
|
||||
}
|
||||
// C
|
||||
binary.LittleEndian.PutUint32(r[32:36], uint32(o))
|
||||
for i := pk.NPublic + 1; i < pk.NVars; i++ {
|
||||
pb1 = pk.C[i].Marshal()
|
||||
r = append(r, pb1[:]...)
|
||||
o += 64
|
||||
}
|
||||
// HExps
|
||||
binary.LittleEndian.PutUint32(r[36:40], uint32(o))
|
||||
for i := 0; i < pk.DomainSize+1; i++ {
|
||||
pb1 = pk.HExps[i].Marshal()
|
||||
r = append(r, pb1[:]...)
|
||||
o += 64
|
||||
}
|
||||
|
||||
return r[:], nil
|
||||
}
|
||||
|
||||
// ParsePkGoBin parses go-circom-prover-verifier binary file representation of
|
||||
// the ProvingKey into ProvingKey struct (*types.Pk). PkGoBin is a own
|
||||
// go-circom-prover-verifier binary format that allows to go faster when
|
||||
// parsing.
|
||||
func ParsePkGoBin(f *os.File) (*types.Pk, error) {
|
||||
o := 0
|
||||
var pk types.Pk
|
||||
r := bufio.NewReader(f)
|
||||
|
||||
b, err := readNBytes(r, 12)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
pk.NVars = int(binary.LittleEndian.Uint32(b[:4]))
|
||||
pk.NPublic = int(binary.LittleEndian.Uint32(b[4:8]))
|
||||
pk.DomainSize = int(binary.LittleEndian.Uint32(b[8:12]))
|
||||
o += 12
|
||||
|
||||
b, err = readNBytes(r, 8)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
pPolsA := int(binary.LittleEndian.Uint32(b[:4]))
|
||||
pPolsB := int(binary.LittleEndian.Uint32(b[4:8]))
|
||||
o += 8
|
||||
|
||||
b, err = readNBytes(r, 20)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
pPointsA := int(binary.LittleEndian.Uint32(b[:4]))
|
||||
pPointsB1 := int(binary.LittleEndian.Uint32(b[4:8]))
|
||||
pPointsB2 := int(binary.LittleEndian.Uint32(b[8:12]))
|
||||
pPointsC := int(binary.LittleEndian.Uint32(b[12:16]))
|
||||
pPointsHExps := int(binary.LittleEndian.Uint32(b[16:20]))
|
||||
o += 20
|
||||
|
||||
b, err = readNBytes(r, 64)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
pk.VkAlpha1 = new(bn256.G1)
|
||||
_, err = pk.VkAlpha1.Unmarshal(b)
|
||||
if err != nil {
|
||||
return &pk, err
|
||||
}
|
||||
b, err = readNBytes(r, 64)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
pk.VkBeta1 = new(bn256.G1)
|
||||
_, err = pk.VkBeta1.Unmarshal(b)
|
||||
if err != nil {
|
||||
return &pk, err
|
||||
}
|
||||
b, err = readNBytes(r, 64)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
pk.VkDelta1 = new(bn256.G1)
|
||||
_, err = pk.VkDelta1.Unmarshal(b)
|
||||
if err != nil {
|
||||
return &pk, err
|
||||
}
|
||||
b, err = readNBytes(r, 128)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
pk.VkBeta2 = new(bn256.G2)
|
||||
_, err = pk.VkBeta2.Unmarshal(b)
|
||||
if err != nil {
|
||||
return &pk, err
|
||||
}
|
||||
b, err = readNBytes(r, 128)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
pk.VkDelta2 = new(bn256.G2)
|
||||
_, err = pk.VkDelta2.Unmarshal(b)
|
||||
if err != nil {
|
||||
return &pk, err
|
||||
}
|
||||
o += 448
|
||||
if o != pPolsA {
|
||||
return nil, fmt.Errorf("Unexpected offset, expected: %v, actual: %v", pPolsA, o)
|
||||
}
|
||||
|
||||
// PolsA
|
||||
for i := 0; i < pk.NVars; i++ {
|
||||
b, err = readNBytes(r, 4)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
keysLength := int(binary.LittleEndian.Uint32(b[:4]))
|
||||
o += 4
|
||||
polsMap := make(map[int]*big.Int)
|
||||
for j := 0; j < keysLength; j++ {
|
||||
bK, err := readNBytes(r, 4)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
key := int(binary.LittleEndian.Uint32(bK[:4]))
|
||||
o += 4
|
||||
|
||||
b, err := readNBytes(r, 32)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
polsMap[key] = new(big.Int).SetBytes(b[:32])
|
||||
o += 32
|
||||
}
|
||||
pk.PolsA = append(pk.PolsA, polsMap)
|
||||
}
|
||||
if o != pPolsB {
|
||||
return nil, fmt.Errorf("Unexpected offset, expected: %v, actual: %v", pPolsB, o)
|
||||
}
|
||||
// PolsB
|
||||
for i := 0; i < pk.NVars; i++ {
|
||||
b, err = readNBytes(r, 4)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
keysLength := int(binary.LittleEndian.Uint32(b[:4]))
|
||||
o += 4
|
||||
polsMap := make(map[int]*big.Int)
|
||||
for j := 0; j < keysLength; j++ {
|
||||
bK, err := readNBytes(r, 4)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
key := int(binary.LittleEndian.Uint32(bK[:4]))
|
||||
o += 4
|
||||
|
||||
b, err := readNBytes(r, 32)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
polsMap[key] = new(big.Int).SetBytes(b[:32])
|
||||
o += 32
|
||||
}
|
||||
pk.PolsB = append(pk.PolsB, polsMap)
|
||||
}
|
||||
if o != pPointsA {
|
||||
return nil, fmt.Errorf("Unexpected offset, expected: %v, actual: %v", pPointsA, o)
|
||||
}
|
||||
// A
|
||||
for i := 0; i < pk.NVars; i++ {
|
||||
b, err = readNBytes(r, 64)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
p1 := new(bn256.G1)
|
||||
_, err = p1.Unmarshal(b)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
pk.A = append(pk.A, p1)
|
||||
o += 64
|
||||
}
|
||||
if o != pPointsB1 {
|
||||
return nil, fmt.Errorf("Unexpected offset, expected: %v, actual: %v", pPointsB1, o)
|
||||
}
|
||||
// B1
|
||||
for i := 0; i < pk.NVars; i++ {
|
||||
b, err = readNBytes(r, 64)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
p1 := new(bn256.G1)
|
||||
_, err = p1.Unmarshal(b)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
pk.B1 = append(pk.B1, p1)
|
||||
o += 64
|
||||
}
|
||||
if o != pPointsB2 {
|
||||
return nil, fmt.Errorf("Unexpected offset, expected: %v, actual: %v", pPointsB2, o)
|
||||
}
|
||||
// B2
|
||||
for i := 0; i < pk.NVars; i++ {
|
||||
b, err = readNBytes(r, 128)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
p2 := new(bn256.G2)
|
||||
_, err = p2.Unmarshal(b)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
pk.B2 = append(pk.B2, p2)
|
||||
o += 128
|
||||
}
|
||||
if o != pPointsC {
|
||||
return nil, fmt.Errorf("Unexpected offset, expected: %v, actual: %v", pPointsC, o)
|
||||
}
|
||||
// C
|
||||
zb := make([]byte, 64)
|
||||
z := new(bn256.G1)
|
||||
_, err = z.Unmarshal(zb)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
for i := 0; i < pk.NPublic+1; i++ {
|
||||
pk.C = append(pk.C, z)
|
||||
}
|
||||
for i := pk.NPublic + 1; i < pk.NVars; i++ {
|
||||
b, err = readNBytes(r, 64)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
p1 := new(bn256.G1)
|
||||
_, err = p1.Unmarshal(b)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
pk.C = append(pk.C, p1)
|
||||
o += 64
|
||||
}
|
||||
if o != pPointsHExps {
|
||||
return nil, fmt.Errorf("Unexpected offset, expected: %v, actual: %v", pPointsHExps, o)
|
||||
}
|
||||
// HExps
|
||||
for i := 0; i < pk.DomainSize+1; i++ {
|
||||
b, err = readNBytes(r, 64)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
p1 := new(bn256.G1)
|
||||
_, err = p1.Unmarshal(b)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
pk.HExps = append(pk.HExps, p1)
|
||||
}
|
||||
|
||||
return &pk, nil
|
||||
}
|
||||
|
||||
@@ -1,9 +1,14 @@
|
||||
package parsers
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"testing"
|
||||
|
||||
"github.com/iden3/go-circom-prover-verifier/types"
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
func TestParseArrayG1(t *testing.T) {
|
||||
@@ -143,3 +148,186 @@ func TestParseArrayG2(t *testing.T) {
|
||||
assert.Equal(t, "bn256.G2((1922d70c934543aa655ec3277f7fa10a25ec973a4f001a7c54ce4954b4916f8c, 14865e836947c42cf35b47d30e06535fff9dab319c4296e28afde368960671d5), (2f50fbe77925b0a9d718c9ab38638bafa7c65f43f0d09035e518df97ad294847, 177dfa1a3b8627faf0425d9511bcb4c6ca986ea05e3803b5c643c35b94a7e6fe))", a[3].String())
|
||||
|
||||
}
|
||||
|
||||
func testCircuitParseWitnessBin(t *testing.T, circuit string) {
|
||||
witnessBinFile, err := os.Open("../testdata/" + circuit + "/witness.bin")
|
||||
require.Nil(t, err)
|
||||
defer witnessBinFile.Close()
|
||||
witness, err := ParseWitnessBin(witnessBinFile)
|
||||
require.Nil(t, err)
|
||||
|
||||
witnessJson, err := ioutil.ReadFile("../testdata/" + circuit + "/witness.json")
|
||||
require.Nil(t, err)
|
||||
w, err := ParseWitness(witnessJson)
|
||||
require.Nil(t, err)
|
||||
|
||||
assert.Equal(t, len(w), len(witness))
|
||||
assert.Equal(t, w[0], witness[0])
|
||||
assert.Equal(t, w[1], witness[1])
|
||||
assert.Equal(t, w[10], witness[10])
|
||||
assert.Equal(t, w[len(w)-3], witness[len(w)-3])
|
||||
assert.Equal(t, w[len(w)-2], witness[len(w)-2])
|
||||
assert.Equal(t, w[len(w)-1], witness[len(w)-1])
|
||||
}
|
||||
|
||||
func TestParseWitnessBin(t *testing.T) {
|
||||
testCircuitParseWitnessBin(t, "circuit1k")
|
||||
testCircuitParseWitnessBin(t, "circuit5k")
|
||||
}
|
||||
|
||||
func TestProofSmartContractFormat(t *testing.T) {
|
||||
proofJson, err := ioutil.ReadFile("../testdata/circuit1k/proof.json")
|
||||
require.Nil(t, err)
|
||||
proof, err := ParseProof(proofJson)
|
||||
require.Nil(t, err)
|
||||
pS := ProofToString(proof)
|
||||
|
||||
pSC := ProofToSmartContractFormat(proof)
|
||||
assert.Nil(t, err)
|
||||
assert.Equal(t, pS.A[0], pSC.A[0])
|
||||
assert.Equal(t, pS.A[1], pSC.A[1])
|
||||
assert.Equal(t, pS.B[0][0], pSC.B[0][1])
|
||||
assert.Equal(t, pS.B[0][1], pSC.B[0][0])
|
||||
assert.Equal(t, pS.B[1][0], pSC.B[1][1])
|
||||
assert.Equal(t, pS.B[1][1], pSC.B[1][0])
|
||||
assert.Equal(t, pS.C[0], pSC.C[0])
|
||||
assert.Equal(t, pS.C[1], pSC.C[1])
|
||||
assert.Equal(t, pS.Protocol, pSC.Protocol)
|
||||
|
||||
pSC2 := ProofStringToSmartContractFormat(pS)
|
||||
assert.Equal(t, pSC, pSC2)
|
||||
}
|
||||
|
||||
func TestProofJSON(t *testing.T) {
|
||||
proofJson, err := ioutil.ReadFile("../testdata/circuit1k/proof.json")
|
||||
require.Nil(t, err)
|
||||
proof, err := ParseProof(proofJson)
|
||||
require.Nil(t, err)
|
||||
|
||||
proof1JSON, err := json.Marshal(proof)
|
||||
require.Nil(t, err)
|
||||
var proof1 types.Proof
|
||||
err = json.Unmarshal(proof1JSON, &proof1)
|
||||
require.Nil(t, err)
|
||||
require.Equal(t, *proof, proof1)
|
||||
}
|
||||
|
||||
func testCircuitParsePkBin(t *testing.T, circuit string) {
|
||||
pkBinFile, err := os.Open("../testdata/" + circuit + "/proving_key.bin")
|
||||
require.Nil(t, err)
|
||||
defer pkBinFile.Close()
|
||||
pk, err := ParsePkBin(pkBinFile)
|
||||
require.Nil(t, err)
|
||||
|
||||
pkJson, err := ioutil.ReadFile("../testdata/" + circuit + "/proving_key.json")
|
||||
require.Nil(t, err)
|
||||
pkJ, err := ParsePk(pkJson)
|
||||
require.Nil(t, err)
|
||||
|
||||
assert.Equal(t, pkJ.NVars, pk.NVars)
|
||||
assert.Equal(t, pkJ.NPublic, pk.NPublic)
|
||||
assert.Equal(t, pkJ.DomainSize, pk.DomainSize)
|
||||
assert.Equal(t, pkJ.VkAlpha1, pk.VkAlpha1)
|
||||
assert.Equal(t, pkJ.VkBeta1, pk.VkBeta1)
|
||||
assert.Equal(t, pkJ.VkDelta1, pk.VkDelta1)
|
||||
assert.Equal(t, pkJ.VkDelta2, pk.VkDelta2)
|
||||
assert.Equal(t, pkJ.PolsA, pk.PolsA)
|
||||
assert.Equal(t, pkJ.PolsB, pk.PolsB)
|
||||
assert.Equal(t, pkJ.A, pk.A)
|
||||
assert.Equal(t, pkJ.B1, pk.B1)
|
||||
assert.Equal(t, pkJ.B2, pk.B2)
|
||||
assert.Equal(t, pkJ.C, pk.C)
|
||||
assert.Equal(t, pkJ.HExps[:pkJ.DomainSize], pk.HExps[:pk.DomainSize]) // circom behaviour
|
||||
|
||||
assert.Equal(t, pkJ.NVars, pk.NVars)
|
||||
assert.Equal(t, pkJ.NPublic, pk.NPublic)
|
||||
assert.Equal(t, pkJ.DomainSize, pk.DomainSize)
|
||||
}
|
||||
|
||||
func TestParsePkBin(t *testing.T) {
|
||||
testCircuitParsePkBin(t, "circuit1k")
|
||||
testCircuitParsePkBin(t, "circuit5k")
|
||||
}
|
||||
|
||||
func testGoCircomPkFormat(t *testing.T, circuit string) {
|
||||
pkJson, err := ioutil.ReadFile("../testdata/" + circuit + "/proving_key.json")
|
||||
require.Nil(t, err)
|
||||
pk, err := ParsePk(pkJson)
|
||||
require.Nil(t, err)
|
||||
|
||||
pkGBin, err := PkToGoBin(pk)
|
||||
require.Nil(t, err)
|
||||
err = ioutil.WriteFile("../testdata/"+circuit+"/proving_key.go.bin", pkGBin, 0644)
|
||||
assert.Nil(t, err)
|
||||
|
||||
// parse ProvingKeyGo
|
||||
pkGoBinFile, err := os.Open("../testdata/" + circuit + "/proving_key.go.bin")
|
||||
require.Nil(t, err)
|
||||
defer pkGoBinFile.Close()
|
||||
pkG, err := ParsePkGoBin(pkGoBinFile)
|
||||
require.Nil(t, err)
|
||||
assert.Equal(t, pk.VkAlpha1, pkG.VkAlpha1)
|
||||
assert.Equal(t, pk.VkBeta1, pkG.VkBeta1)
|
||||
assert.Equal(t, pk.VkDelta1, pkG.VkDelta1)
|
||||
assert.Equal(t, pk.VkBeta2, pkG.VkBeta2)
|
||||
assert.Equal(t, pk.VkDelta2, pkG.VkDelta2)
|
||||
assert.Equal(t, pk.A, pkG.A)
|
||||
assert.Equal(t, pk.B1, pkG.B1)
|
||||
assert.Equal(t, pk.B2, pkG.B2)
|
||||
assert.Equal(t, pk.C, pkG.C)
|
||||
assert.Equal(t, pk.HExps, pkG.HExps)
|
||||
assert.Equal(t, pk.PolsA, pkG.PolsA)
|
||||
assert.Equal(t, pk.PolsB, pkG.PolsB)
|
||||
|
||||
assert.Equal(t, pk.NVars, pkG.NVars)
|
||||
assert.Equal(t, pk.NPublic, pkG.NPublic)
|
||||
assert.Equal(t, pk.DomainSize, pkG.DomainSize)
|
||||
}
|
||||
|
||||
func TestGoCircomPkFormat(t *testing.T) {
|
||||
testGoCircomPkFormat(t, "circuit1k")
|
||||
testGoCircomPkFormat(t, "circuit5k")
|
||||
// testGoCircomPkFormat(t, "circuit10k")
|
||||
// testGoCircomPkFormat(t, "circuit20k")
|
||||
}
|
||||
|
||||
func benchmarkParsePk(b *testing.B, circuit string) {
|
||||
pkJson, err := ioutil.ReadFile("../testdata/" + circuit + "/proving_key.json")
|
||||
require.Nil(b, err)
|
||||
|
||||
pkBinFile, err := os.Open("../testdata/" + circuit + "/proving_key.bin")
|
||||
require.Nil(b, err)
|
||||
defer pkBinFile.Close()
|
||||
|
||||
pkGoBinFile, err := os.Open("../testdata/" + circuit + "/proving_key.go.bin")
|
||||
require.Nil(b, err)
|
||||
defer pkGoBinFile.Close()
|
||||
|
||||
b.Run("ParsePkJson "+circuit, func(b *testing.B) {
|
||||
for i := 0; i < b.N; i++ {
|
||||
_, err = ParsePk(pkJson)
|
||||
require.Nil(b, err)
|
||||
}
|
||||
})
|
||||
b.Run("ParsePkBin "+circuit, func(b *testing.B) {
|
||||
for i := 0; i < b.N; i++ {
|
||||
pkBinFile.Seek(0, 0)
|
||||
_, err = ParsePkBin(pkBinFile)
|
||||
require.Nil(b, err)
|
||||
}
|
||||
})
|
||||
b.Run("ParsePkGoBin "+circuit, func(b *testing.B) {
|
||||
for i := 0; i < b.N; i++ {
|
||||
pkGoBinFile.Seek(0, 0)
|
||||
_, err = ParsePkGoBin(pkGoBinFile)
|
||||
require.Nil(b, err)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
func BenchmarkParsePk(b *testing.B) {
|
||||
benchmarkParsePk(b, "circuit1k")
|
||||
benchmarkParsePk(b, "circuit5k")
|
||||
// benchmarkParsePk(b, "circuit10k")
|
||||
// benchmarkParsePk(b, "circuit20k")
|
||||
}
|
||||
|
||||
463
prover/gextra.go
Normal file
463
prover/gextra.go
Normal file
@@ -0,0 +1,463 @@
|
||||
package prover
|
||||
|
||||
import (
|
||||
"math/big"
|
||||
|
||||
bn256 "github.com/ethereum/go-ethereum/crypto/bn256/cloudflare"
|
||||
cryptoConstants "github.com/iden3/go-iden3-crypto/constants"
|
||||
)
|
||||
|
||||
type tableG1 struct {
|
||||
data []*bn256.G1
|
||||
}
|
||||
|
||||
func (t tableG1) getData() []*bn256.G1 {
|
||||
return t.data
|
||||
}
|
||||
|
||||
// Compute table of gsize elements as ::
|
||||
// Table[0] = Inf
|
||||
// Table[1] = a[0]
|
||||
// Table[2] = a[1]
|
||||
// Table[3] = a[0]+a[1]
|
||||
// .....
|
||||
// Table[(1<<gsize)-1] = a[0]+a[1]+...+a[gsize-1]
|
||||
func (t *tableG1) newTableG1(a []*bn256.G1, gsize int, toaffine bool) {
|
||||
// EC table
|
||||
table := make([]*bn256.G1, 0)
|
||||
|
||||
// We need at least gsize elements. If not enough, fill with 0
|
||||
aExt := make([]*bn256.G1, 0)
|
||||
aExt = append(aExt, a...)
|
||||
|
||||
for i := len(a); i < gsize; i++ {
|
||||
aExt = append(aExt, new(bn256.G1).ScalarBaseMult(big.NewInt(0)))
|
||||
}
|
||||
|
||||
elG1 := new(bn256.G1).ScalarBaseMult(big.NewInt(0))
|
||||
table = append(table, elG1)
|
||||
lastPow2 := 1
|
||||
nelems := 0
|
||||
for i := 1; i < 1<<gsize; i++ {
|
||||
elG1 := new(bn256.G1)
|
||||
// if power of 2
|
||||
if i&(i-1) == 0 {
|
||||
lastPow2 = i
|
||||
elG1.Set(aExt[nelems])
|
||||
nelems++
|
||||
} else {
|
||||
elG1.Add(table[lastPow2], table[i-lastPow2])
|
||||
// TODO bn256 doesn't export MakeAffine function. We need to fork repo
|
||||
//table[i].MakeAffine()
|
||||
}
|
||||
table = append(table, elG1)
|
||||
}
|
||||
if toaffine {
|
||||
for i := 0; i < len(table); i++ {
|
||||
info := table[i].Marshal()
|
||||
table[i].Unmarshal(info)
|
||||
}
|
||||
}
|
||||
t.data = table
|
||||
}
|
||||
|
||||
func (t tableG1) Marshal() []byte {
|
||||
info := make([]byte, 0)
|
||||
for _, el := range t.data {
|
||||
info = append(info, el.Marshal()...)
|
||||
}
|
||||
|
||||
return info
|
||||
}
|
||||
|
||||
// Multiply scalar by precomputed table of G1 elements
|
||||
func (t *tableG1) mulTableG1(k []*big.Int, qPrev *bn256.G1, gsize int) *bn256.G1 {
|
||||
// We need at least gsize elements. If not enough, fill with 0
|
||||
kExt := make([]*big.Int, 0)
|
||||
kExt = append(kExt, k...)
|
||||
|
||||
for i := len(k); i < gsize; i++ {
|
||||
kExt = append(kExt, new(big.Int).SetUint64(0))
|
||||
}
|
||||
|
||||
Q := new(bn256.G1).ScalarBaseMult(big.NewInt(0))
|
||||
|
||||
msb := getMsb(kExt)
|
||||
|
||||
for i := msb - 1; i >= 0; i-- {
|
||||
// TODO. bn256 doesn't export double operation. We will need to fork repo and export it
|
||||
Q = new(bn256.G1).Add(Q, Q)
|
||||
b := getBit(kExt, i)
|
||||
if b != 0 {
|
||||
// TODO. bn256 doesn't export mixed addition (Jacobian + Affine), which is more efficient.
|
||||
Q.Add(Q, t.data[b])
|
||||
}
|
||||
}
|
||||
if qPrev != nil {
|
||||
return Q.Add(Q, qPrev)
|
||||
}
|
||||
return Q
|
||||
}
|
||||
|
||||
// Multiply scalar by precomputed table of G1 elements without intermediate doubling
|
||||
func mulTableNoDoubleG1(t []tableG1, k []*big.Int, qPrev *bn256.G1, gsize int) *bn256.G1 {
|
||||
// We need at least gsize elements. If not enough, fill with 0
|
||||
minNElems := len(t) * gsize
|
||||
kExt := make([]*big.Int, 0)
|
||||
kExt = append(kExt, k...)
|
||||
for i := len(k); i < minNElems; i++ {
|
||||
kExt = append(kExt, new(big.Int).SetUint64(0))
|
||||
}
|
||||
// Init Adders
|
||||
nbitsQ := cryptoConstants.Q.BitLen()
|
||||
Q := make([]*bn256.G1, nbitsQ)
|
||||
|
||||
for i := 0; i < nbitsQ; i++ {
|
||||
Q[i] = new(bn256.G1).ScalarBaseMult(big.NewInt(0))
|
||||
}
|
||||
|
||||
// Perform bitwise addition
|
||||
for j := 0; j < len(t); j++ {
|
||||
msb := getMsb(kExt[j*gsize : (j+1)*gsize])
|
||||
|
||||
for i := msb - 1; i >= 0; i-- {
|
||||
b := getBit(kExt[j*gsize:(j+1)*gsize], i)
|
||||
if b != 0 {
|
||||
// TODO. bn256 doesn't export mixed addition (Jacobian + Affine), which is more efficient.
|
||||
Q[i].Add(Q[i], t[j].data[b])
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Consolidate Addition
|
||||
R := new(bn256.G1).Set(Q[nbitsQ-1])
|
||||
for i := nbitsQ - 1; i > 0; i-- {
|
||||
// TODO. bn256 doesn't export double operation. We will need to fork repo and export it
|
||||
R = new(bn256.G1).Add(R, R)
|
||||
R.Add(R, Q[i-1])
|
||||
}
|
||||
|
||||
if qPrev != nil {
|
||||
return R.Add(R, qPrev)
|
||||
}
|
||||
return R
|
||||
}
|
||||
|
||||
// Compute tables within function. This solution should still be faster than std multiplication
|
||||
// for gsize = 7
|
||||
func scalarMultG1(a []*bn256.G1, k []*big.Int, qPrev *bn256.G1, gsize int) *bn256.G1 {
|
||||
ntables := int((len(a) + gsize - 1) / gsize)
|
||||
table := tableG1{}
|
||||
Q := new(bn256.G1).ScalarBaseMult(new(big.Int))
|
||||
|
||||
for i := 0; i < ntables-1; i++ {
|
||||
table.newTableG1(a[i*gsize:(i+1)*gsize], gsize, false)
|
||||
Q = table.mulTableG1(k[i*gsize:(i+1)*gsize], Q, gsize)
|
||||
}
|
||||
table.newTableG1(a[(ntables-1)*gsize:], gsize, false)
|
||||
Q = table.mulTableG1(k[(ntables-1)*gsize:], Q, gsize)
|
||||
|
||||
if qPrev != nil {
|
||||
return Q.Add(Q, qPrev)
|
||||
}
|
||||
return Q
|
||||
}
|
||||
|
||||
// Multiply scalar by precomputed table of G1 elements without intermediate doubling
|
||||
func scalarMultNoDoubleG1(a []*bn256.G1, k []*big.Int, qPrev *bn256.G1, gsize int) *bn256.G1 {
|
||||
ntables := int((len(a) + gsize - 1) / gsize)
|
||||
table := tableG1{}
|
||||
|
||||
// We need at least gsize elements. If not enough, fill with 0
|
||||
minNElems := ntables * gsize
|
||||
kExt := make([]*big.Int, 0)
|
||||
kExt = append(kExt, k...)
|
||||
for i := len(k); i < minNElems; i++ {
|
||||
kExt = append(kExt, new(big.Int).SetUint64(0))
|
||||
}
|
||||
// Init Adders
|
||||
nbitsQ := cryptoConstants.Q.BitLen()
|
||||
Q := make([]*bn256.G1, nbitsQ)
|
||||
|
||||
for i := 0; i < nbitsQ; i++ {
|
||||
Q[i] = new(bn256.G1).ScalarBaseMult(big.NewInt(0))
|
||||
}
|
||||
|
||||
// Perform bitwise addition
|
||||
for j := 0; j < ntables-1; j++ {
|
||||
table.newTableG1(a[j*gsize:(j+1)*gsize], gsize, false)
|
||||
msb := getMsb(kExt[j*gsize : (j+1)*gsize])
|
||||
|
||||
for i := msb - 1; i >= 0; i-- {
|
||||
b := getBit(kExt[j*gsize:(j+1)*gsize], i)
|
||||
if b != 0 {
|
||||
// TODO. bn256 doesn't export mixed addition (Jacobian + Affine), which is more efficient.
|
||||
Q[i].Add(Q[i], table.data[b])
|
||||
}
|
||||
}
|
||||
}
|
||||
table.newTableG1(a[(ntables-1)*gsize:], gsize, false)
|
||||
msb := getMsb(kExt[(ntables-1)*gsize:])
|
||||
|
||||
for i := msb - 1; i >= 0; i-- {
|
||||
b := getBit(kExt[(ntables-1)*gsize:], i)
|
||||
if b != 0 {
|
||||
// TODO. bn256 doesn't export mixed addition (Jacobian + Affine), which is more efficient.
|
||||
Q[i].Add(Q[i], table.data[b])
|
||||
}
|
||||
}
|
||||
|
||||
// Consolidate Addition
|
||||
R := new(bn256.G1).Set(Q[nbitsQ-1])
|
||||
for i := nbitsQ - 1; i > 0; i-- {
|
||||
// TODO. bn256 doesn't export double operation. We will need to fork repo and export it
|
||||
R = new(bn256.G1).Add(R, R)
|
||||
R.Add(R, Q[i-1])
|
||||
}
|
||||
if qPrev != nil {
|
||||
return R.Add(R, qPrev)
|
||||
}
|
||||
return R
|
||||
}
|
||||
|
||||
/////
|
||||
|
||||
// TODO - How can avoid replicating code in G2?
|
||||
//G2
|
||||
|
||||
type tableG2 struct {
|
||||
data []*bn256.G2
|
||||
}
|
||||
|
||||
func (t tableG2) getData() []*bn256.G2 {
|
||||
return t.data
|
||||
}
|
||||
|
||||
// Compute table of gsize elements as ::
|
||||
// Table[0] = Inf
|
||||
// Table[1] = a[0]
|
||||
// Table[2] = a[1]
|
||||
// Table[3] = a[0]+a[1]
|
||||
// .....
|
||||
// Table[(1<<gsize)-1] = a[0]+a[1]+...+a[gsize-1]
|
||||
// TODO -> toaffine = True doesnt work. Problem with Marshal/Unmarshal
|
||||
func (t *tableG2) newTableG2(a []*bn256.G2, gsize int, toaffine bool) {
|
||||
// EC table
|
||||
table := make([]*bn256.G2, 0)
|
||||
|
||||
// We need at least gsize elements. If not enough, fill with 0
|
||||
aExt := make([]*bn256.G2, 0)
|
||||
aExt = append(aExt, a...)
|
||||
|
||||
for i := len(a); i < gsize; i++ {
|
||||
aExt = append(aExt, new(bn256.G2).ScalarBaseMult(big.NewInt(0)))
|
||||
}
|
||||
|
||||
elG2 := new(bn256.G2).ScalarBaseMult(big.NewInt(0))
|
||||
table = append(table, elG2)
|
||||
lastPow2 := 1
|
||||
nelems := 0
|
||||
for i := 1; i < 1<<gsize; i++ {
|
||||
elG2 := new(bn256.G2)
|
||||
// if power of 2
|
||||
if i&(i-1) == 0 {
|
||||
lastPow2 = i
|
||||
elG2.Set(aExt[nelems])
|
||||
nelems++
|
||||
} else {
|
||||
elG2.Add(table[lastPow2], table[i-lastPow2])
|
||||
// TODO bn256 doesn't export MakeAffine function. We need to fork repo
|
||||
//table[i].MakeAffine()
|
||||
}
|
||||
table = append(table, elG2)
|
||||
}
|
||||
if toaffine {
|
||||
for i := 0; i < len(table); i++ {
|
||||
info := table[i].Marshal()
|
||||
table[i].Unmarshal(info)
|
||||
}
|
||||
}
|
||||
t.data = table
|
||||
}
|
||||
|
||||
func (t tableG2) Marshal() []byte {
|
||||
info := make([]byte, 0)
|
||||
for _, el := range t.data {
|
||||
info = append(info, el.Marshal()...)
|
||||
}
|
||||
|
||||
return info
|
||||
}
|
||||
|
||||
// Multiply scalar by precomputed table of G2 elements
|
||||
func (t *tableG2) mulTableG2(k []*big.Int, qPrev *bn256.G2, gsize int) *bn256.G2 {
|
||||
// We need at least gsize elements. If not enough, fill with 0
|
||||
kExt := make([]*big.Int, 0)
|
||||
kExt = append(kExt, k...)
|
||||
|
||||
for i := len(k); i < gsize; i++ {
|
||||
kExt = append(kExt, new(big.Int).SetUint64(0))
|
||||
}
|
||||
|
||||
Q := new(bn256.G2).ScalarBaseMult(big.NewInt(0))
|
||||
|
||||
msb := getMsb(kExt)
|
||||
|
||||
for i := msb - 1; i >= 0; i-- {
|
||||
// TODO. bn256 doesn't export double operation. We will need to fork repo and export it
|
||||
Q = new(bn256.G2).Add(Q, Q)
|
||||
b := getBit(kExt, i)
|
||||
if b != 0 {
|
||||
// TODO. bn256 doesn't export mixed addition (Jacobian + Affine), which is more efficient.
|
||||
Q.Add(Q, t.data[b])
|
||||
}
|
||||
}
|
||||
if qPrev != nil {
|
||||
return Q.Add(Q, qPrev)
|
||||
}
|
||||
return Q
|
||||
}
|
||||
|
||||
// Multiply scalar by precomputed table of G2 elements without intermediate doubling
|
||||
func mulTableNoDoubleG2(t []tableG2, k []*big.Int, qPrev *bn256.G2, gsize int) *bn256.G2 {
|
||||
// We need at least gsize elements. If not enough, fill with 0
|
||||
minNElems := len(t) * gsize
|
||||
kExt := make([]*big.Int, 0)
|
||||
kExt = append(kExt, k...)
|
||||
for i := len(k); i < minNElems; i++ {
|
||||
kExt = append(kExt, new(big.Int).SetUint64(0))
|
||||
}
|
||||
// Init Adders
|
||||
nbitsQ := cryptoConstants.Q.BitLen()
|
||||
Q := make([]*bn256.G2, nbitsQ)
|
||||
|
||||
for i := 0; i < nbitsQ; i++ {
|
||||
Q[i] = new(bn256.G2).ScalarBaseMult(big.NewInt(0))
|
||||
}
|
||||
|
||||
// Perform bitwise addition
|
||||
for j := 0; j < len(t); j++ {
|
||||
msb := getMsb(kExt[j*gsize : (j+1)*gsize])
|
||||
|
||||
for i := msb - 1; i >= 0; i-- {
|
||||
b := getBit(kExt[j*gsize:(j+1)*gsize], i)
|
||||
if b != 0 {
|
||||
// TODO. bn256 doesn't export mixed addition (Jacobian + Affine), which is more efficient.
|
||||
Q[i].Add(Q[i], t[j].data[b])
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Consolidate Addition
|
||||
R := new(bn256.G2).Set(Q[nbitsQ-1])
|
||||
for i := nbitsQ - 1; i > 0; i-- {
|
||||
// TODO. bn256 doesn't export double operation. We will need to fork repo and export it
|
||||
R = new(bn256.G2).Add(R, R)
|
||||
R.Add(R, Q[i-1])
|
||||
}
|
||||
if qPrev != nil {
|
||||
return R.Add(R, qPrev)
|
||||
}
|
||||
return R
|
||||
}
|
||||
|
||||
// Compute tables within function. This solution should still be faster than std multiplication
|
||||
// for gsize = 7
|
||||
func scalarMultG2(a []*bn256.G2, k []*big.Int, qPrev *bn256.G2, gsize int) *bn256.G2 {
|
||||
ntables := int((len(a) + gsize - 1) / gsize)
|
||||
table := tableG2{}
|
||||
Q := new(bn256.G2).ScalarBaseMult(new(big.Int))
|
||||
|
||||
for i := 0; i < ntables-1; i++ {
|
||||
table.newTableG2(a[i*gsize:(i+1)*gsize], gsize, false)
|
||||
Q = table.mulTableG2(k[i*gsize:(i+1)*gsize], Q, gsize)
|
||||
}
|
||||
table.newTableG2(a[(ntables-1)*gsize:], gsize, false)
|
||||
Q = table.mulTableG2(k[(ntables-1)*gsize:], Q, gsize)
|
||||
|
||||
if qPrev != nil {
|
||||
return Q.Add(Q, qPrev)
|
||||
}
|
||||
return Q
|
||||
}
|
||||
|
||||
// Multiply scalar by precomputed table of G2 elements without intermediate doubling
|
||||
func scalarMultNoDoubleG2(a []*bn256.G2, k []*big.Int, qPrev *bn256.G2, gsize int) *bn256.G2 {
|
||||
ntables := int((len(a) + gsize - 1) / gsize)
|
||||
table := tableG2{}
|
||||
|
||||
// We need at least gsize elements. If not enough, fill with 0
|
||||
minNElems := ntables * gsize
|
||||
kExt := make([]*big.Int, 0)
|
||||
kExt = append(kExt, k...)
|
||||
for i := len(k); i < minNElems; i++ {
|
||||
kExt = append(kExt, new(big.Int).SetUint64(0))
|
||||
}
|
||||
// Init Adders
|
||||
nbitsQ := cryptoConstants.Q.BitLen()
|
||||
Q := make([]*bn256.G2, nbitsQ)
|
||||
|
||||
for i := 0; i < nbitsQ; i++ {
|
||||
Q[i] = new(bn256.G2).ScalarBaseMult(big.NewInt(0))
|
||||
}
|
||||
|
||||
// Perform bitwise addition
|
||||
for j := 0; j < ntables-1; j++ {
|
||||
table.newTableG2(a[j*gsize:(j+1)*gsize], gsize, false)
|
||||
msb := getMsb(kExt[j*gsize : (j+1)*gsize])
|
||||
|
||||
for i := msb - 1; i >= 0; i-- {
|
||||
b := getBit(kExt[j*gsize:(j+1)*gsize], i)
|
||||
if b != 0 {
|
||||
// TODO. bn256 doesn't export mixed addition (Jacobian + Affine), which is more efficient.
|
||||
Q[i].Add(Q[i], table.data[b])
|
||||
}
|
||||
}
|
||||
}
|
||||
table.newTableG2(a[(ntables-1)*gsize:], gsize, false)
|
||||
msb := getMsb(kExt[(ntables-1)*gsize:])
|
||||
|
||||
for i := msb - 1; i >= 0; i-- {
|
||||
b := getBit(kExt[(ntables-1)*gsize:], i)
|
||||
if b != 0 {
|
||||
// TODO. bn256 doesn't export mixed addition (Jacobian + Affine), which is more efficient.
|
||||
Q[i].Add(Q[i], table.data[b])
|
||||
}
|
||||
}
|
||||
|
||||
// Consolidate Addition
|
||||
R := new(bn256.G2).Set(Q[nbitsQ-1])
|
||||
for i := nbitsQ - 1; i > 0; i-- {
|
||||
// TODO. bn256 doesn't export double operation. We will need to fork repo and export it
|
||||
R = new(bn256.G2).Add(R, R)
|
||||
R.Add(R, Q[i-1])
|
||||
}
|
||||
if qPrev != nil {
|
||||
return R.Add(R, qPrev)
|
||||
}
|
||||
return R
|
||||
}
|
||||
|
||||
// Return most significant bit position in a group of Big Integers
|
||||
func getMsb(k []*big.Int) int {
|
||||
msb := 0
|
||||
|
||||
for _, el := range k {
|
||||
tmpMsb := el.BitLen()
|
||||
if tmpMsb > msb {
|
||||
msb = tmpMsb
|
||||
}
|
||||
}
|
||||
return msb
|
||||
}
|
||||
|
||||
// Return ith bit in group of Big Integers
|
||||
func getBit(k []*big.Int, i int) uint {
|
||||
tableIdx := uint(0)
|
||||
|
||||
for idx, el := range k {
|
||||
b := el.Bit(i)
|
||||
tableIdx += (b << idx)
|
||||
}
|
||||
return tableIdx
|
||||
}
|
||||
163
prover/gextra_test.go
Normal file
163
prover/gextra_test.go
Normal file
@@ -0,0 +1,163 @@
|
||||
package prover
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"crypto/rand"
|
||||
"fmt"
|
||||
"math/big"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
bn256 "github.com/ethereum/go-ethereum/crypto/bn256/cloudflare"
|
||||
)
|
||||
|
||||
const (
|
||||
N1 = 5000
|
||||
N2 = 5000
|
||||
)
|
||||
|
||||
func randomBigIntArray(n int) []*big.Int {
|
||||
var p []*big.Int
|
||||
for i := 0; i < n; i++ {
|
||||
pi := randBI()
|
||||
p = append(p, pi)
|
||||
}
|
||||
|
||||
return p
|
||||
}
|
||||
|
||||
func randomG1Array(n int) []*bn256.G1 {
|
||||
arrayG1 := make([]*bn256.G1, n)
|
||||
|
||||
for i := 0; i < n; i++ {
|
||||
_, arrayG1[i], _ = bn256.RandomG1(rand.Reader)
|
||||
}
|
||||
return arrayG1
|
||||
}
|
||||
|
||||
func randomG2Array(n int) []*bn256.G2 {
|
||||
arrayG2 := make([]*bn256.G2, n)
|
||||
|
||||
for i := 0; i < n; i++ {
|
||||
_, arrayG2[i], _ = bn256.RandomG2(rand.Reader)
|
||||
}
|
||||
return arrayG2
|
||||
}
|
||||
|
||||
func TestTableG1(t *testing.T) {
|
||||
n := N1
|
||||
|
||||
// init scalar
|
||||
var arrayW = randomBigIntArray(n)
|
||||
// init G1 array
|
||||
var arrayG1 = randomG1Array(n)
|
||||
|
||||
beforeT := time.Now()
|
||||
Q1 := new(bn256.G1).ScalarBaseMult(new(big.Int))
|
||||
for i := 0; i < n; i++ {
|
||||
Q1.Add(Q1, new(bn256.G1).ScalarMult(arrayG1[i], arrayW[i]))
|
||||
}
|
||||
fmt.Println("Std. Mult. time elapsed:", time.Since(beforeT))
|
||||
|
||||
for gsize := 2; gsize < 10; gsize++ {
|
||||
ntables := int((n + gsize - 1) / gsize)
|
||||
table := make([]tableG1, ntables)
|
||||
|
||||
for i := 0; i < ntables-1; i++ {
|
||||
table[i].newTableG1(arrayG1[i*gsize:(i+1)*gsize], gsize, true)
|
||||
}
|
||||
table[ntables-1].newTableG1(arrayG1[(ntables-1)*gsize:], gsize, true)
|
||||
|
||||
beforeT = time.Now()
|
||||
Q2 := new(bn256.G1).ScalarBaseMult(new(big.Int))
|
||||
for i := 0; i < ntables-1; i++ {
|
||||
Q2 = table[i].mulTableG1(arrayW[i*gsize:(i+1)*gsize], Q2, gsize)
|
||||
}
|
||||
Q2 = table[ntables-1].mulTableG1(arrayW[(ntables-1)*gsize:], Q2, gsize)
|
||||
fmt.Printf("Gsize : %d, TMult time elapsed: %s\n", gsize, time.Since(beforeT))
|
||||
|
||||
beforeT = time.Now()
|
||||
Q3 := scalarMultG1(arrayG1, arrayW, nil, gsize)
|
||||
fmt.Printf("Gsize : %d, TMult time elapsed (inc table comp): %s\n", gsize, time.Since(beforeT))
|
||||
|
||||
beforeT = time.Now()
|
||||
Q4 := mulTableNoDoubleG1(table, arrayW, nil, gsize)
|
||||
fmt.Printf("Gsize : %d, TMultNoDouble time elapsed: %s\n", gsize, time.Since(beforeT))
|
||||
|
||||
beforeT = time.Now()
|
||||
Q5 := scalarMultNoDoubleG1(arrayG1, arrayW, nil, gsize)
|
||||
fmt.Printf("Gsize : %d, TMultNoDouble time elapsed (inc table comp): %s\n", gsize, time.Since(beforeT))
|
||||
|
||||
if bytes.Compare(Q1.Marshal(), Q2.Marshal()) != 0 {
|
||||
t.Error("Error in TMult")
|
||||
}
|
||||
if bytes.Compare(Q1.Marshal(), Q3.Marshal()) != 0 {
|
||||
t.Error("Error in TMult with table comp")
|
||||
}
|
||||
if bytes.Compare(Q1.Marshal(), Q4.Marshal()) != 0 {
|
||||
t.Error("Error in TMultNoDouble")
|
||||
}
|
||||
if bytes.Compare(Q1.Marshal(), Q5.Marshal()) != 0 {
|
||||
t.Error("Error in TMultNoDoublee with table comp")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestTableG2(t *testing.T) {
|
||||
n := N2
|
||||
|
||||
// init scalar
|
||||
var arrayW = randomBigIntArray(n)
|
||||
// init G2 array
|
||||
var arrayG2 = randomG2Array(n)
|
||||
|
||||
beforeT := time.Now()
|
||||
Q1 := new(bn256.G2).ScalarBaseMult(new(big.Int))
|
||||
for i := 0; i < n; i++ {
|
||||
Q1.Add(Q1, new(bn256.G2).ScalarMult(arrayG2[i], arrayW[i]))
|
||||
}
|
||||
fmt.Println("Std. Mult. time elapsed:", time.Since(beforeT))
|
||||
|
||||
for gsize := 2; gsize < 10; gsize++ {
|
||||
ntables := int((n + gsize - 1) / gsize)
|
||||
table := make([]tableG2, ntables)
|
||||
|
||||
for i := 0; i < ntables-1; i++ {
|
||||
table[i].newTableG2(arrayG2[i*gsize:(i+1)*gsize], gsize, false)
|
||||
}
|
||||
table[ntables-1].newTableG2(arrayG2[(ntables-1)*gsize:], gsize, false)
|
||||
|
||||
beforeT = time.Now()
|
||||
Q2 := new(bn256.G2).ScalarBaseMult(new(big.Int))
|
||||
for i := 0; i < ntables-1; i++ {
|
||||
Q2 = table[i].mulTableG2(arrayW[i*gsize:(i+1)*gsize], Q2, gsize)
|
||||
}
|
||||
Q2 = table[ntables-1].mulTableG2(arrayW[(ntables-1)*gsize:], Q2, gsize)
|
||||
fmt.Printf("Gsize : %d, TMult time elapsed: %s\n", gsize, time.Since(beforeT))
|
||||
|
||||
beforeT = time.Now()
|
||||
Q3 := scalarMultG2(arrayG2, arrayW, nil, gsize)
|
||||
fmt.Printf("Gsize : %d, TMult time elapsed (inc table comp): %s\n", gsize, time.Since(beforeT))
|
||||
|
||||
beforeT = time.Now()
|
||||
Q4 := mulTableNoDoubleG2(table, arrayW, nil, gsize)
|
||||
fmt.Printf("Gsize : %d, TMultNoDouble time elapsed: %s\n", gsize, time.Since(beforeT))
|
||||
|
||||
beforeT = time.Now()
|
||||
Q5 := scalarMultNoDoubleG2(arrayG2, arrayW, nil, gsize)
|
||||
fmt.Printf("Gsize : %d, TMultNoDouble time elapsed (inc table comp): %s\n", gsize, time.Since(beforeT))
|
||||
|
||||
if bytes.Compare(Q1.Marshal(), Q2.Marshal()) != 0 {
|
||||
t.Error("Error in TMult")
|
||||
}
|
||||
if bytes.Compare(Q1.Marshal(), Q3.Marshal()) != 0 {
|
||||
t.Error("Error in TMult with table comp")
|
||||
}
|
||||
if bytes.Compare(Q1.Marshal(), Q4.Marshal()) != 0 {
|
||||
t.Error("Error in TMultNoDouble")
|
||||
}
|
||||
if bytes.Compare(Q1.Marshal(), Q5.Marshal()) != 0 {
|
||||
t.Error("Error in TMultNoDoublee with table comp")
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -10,37 +10,13 @@ import (
|
||||
bn256 "github.com/ethereum/go-ethereum/crypto/bn256/cloudflare"
|
||||
"github.com/iden3/go-circom-prover-verifier/types"
|
||||
"github.com/iden3/go-iden3-crypto/utils"
|
||||
//"fmt"
|
||||
)
|
||||
|
||||
// Proof is the data structure of the Groth16 zkSNARK proof
|
||||
type Proof struct {
|
||||
A *bn256.G1
|
||||
B *bn256.G2
|
||||
C *bn256.G1
|
||||
}
|
||||
|
||||
// Pk holds the data structure of the ProvingKey
|
||||
type Pk struct {
|
||||
A []*bn256.G1
|
||||
B2 []*bn256.G2
|
||||
B1 []*bn256.G1
|
||||
C []*bn256.G1
|
||||
NVars int
|
||||
NPublic int
|
||||
VkAlpha1 *bn256.G1
|
||||
VkDelta1 *bn256.G1
|
||||
VkBeta1 *bn256.G1
|
||||
VkBeta2 *bn256.G2
|
||||
VkDelta2 *bn256.G2
|
||||
HExps []*bn256.G1
|
||||
DomainSize int
|
||||
PolsA []map[int]*big.Int
|
||||
PolsB []map[int]*big.Int
|
||||
PolsC []map[int]*big.Int
|
||||
}
|
||||
|
||||
// Witness contains the witness
|
||||
type Witness []*big.Int
|
||||
// Group Size
|
||||
const (
|
||||
GSIZE = 6
|
||||
)
|
||||
|
||||
func randBigInt() (*big.Int, error) {
|
||||
maxbits := types.R.BitLen()
|
||||
@@ -69,25 +45,39 @@ func GenerateProof(pk *types.Pk, w types.Witness) (*types.Proof, []*big.Int, err
|
||||
}
|
||||
|
||||
// BEGIN PAR
|
||||
println("NVars", pk.NVars)
|
||||
numcpu := runtime.NumCPU()
|
||||
|
||||
proofA := arrayOfZeroesG1(numcpu)
|
||||
proofB := arrayOfZeroesG2(numcpu)
|
||||
proofC := arrayOfZeroesG1(numcpu)
|
||||
proofBG1 := arrayOfZeroesG1(numcpu)
|
||||
gsize := GSIZE
|
||||
var wg1 sync.WaitGroup
|
||||
wg1.Add(numcpu)
|
||||
for _cpu, _ranges := range ranges(pk.NVars, numcpu) {
|
||||
// split 1
|
||||
go func(cpu int, ranges [2]int) {
|
||||
for i := ranges[0]; i < ranges[1]; i++ {
|
||||
proofA[cpu].Add(proofA[cpu], new(bn256.G1).ScalarMult(pk.A[i], w[i]))
|
||||
proofB[cpu].Add(proofB[cpu], new(bn256.G2).ScalarMult(pk.B2[i], w[i]))
|
||||
proofBG1[cpu].Add(proofBG1[cpu], new(bn256.G1).ScalarMult(pk.B1[i], w[i]))
|
||||
if i >= pk.NPublic+1 {
|
||||
proofC[cpu].Add(proofC[cpu], new(bn256.G1).ScalarMult(pk.C[i], w[i]))
|
||||
}
|
||||
proofA[cpu] = scalarMultNoDoubleG1(pk.A[ranges[0]:ranges[1]],
|
||||
w[ranges[0]:ranges[1]],
|
||||
proofA[cpu],
|
||||
gsize)
|
||||
proofB[cpu] = scalarMultNoDoubleG2(pk.B2[ranges[0]:ranges[1]],
|
||||
w[ranges[0]:ranges[1]],
|
||||
proofB[cpu],
|
||||
gsize)
|
||||
proofBG1[cpu] = scalarMultNoDoubleG1(pk.B1[ranges[0]:ranges[1]],
|
||||
w[ranges[0]:ranges[1]],
|
||||
proofBG1[cpu],
|
||||
gsize)
|
||||
minLim := pk.NPublic + 1
|
||||
if ranges[0] > pk.NPublic+1 {
|
||||
minLim = ranges[0]
|
||||
}
|
||||
if ranges[1] > pk.NPublic+1 {
|
||||
proofC[cpu] = scalarMultNoDoubleG1(pk.C[minLim:ranges[1]],
|
||||
w[minLim:ranges[1]],
|
||||
proofC[cpu],
|
||||
gsize)
|
||||
}
|
||||
wg1.Done()
|
||||
}(_cpu, _ranges)
|
||||
@@ -107,8 +97,6 @@ func GenerateProof(pk *types.Pk, w types.Witness) (*types.Proof, []*big.Int, err
|
||||
|
||||
h := calculateH(pk, w)
|
||||
|
||||
println("len(h)", len(h))
|
||||
|
||||
proof.A.Add(proof.A, pk.VkAlpha1)
|
||||
proof.A.Add(proof.A, new(bn256.G1).ScalarMult(pk.VkDelta1, r))
|
||||
|
||||
@@ -124,9 +112,10 @@ func GenerateProof(pk *types.Pk, w types.Witness) (*types.Proof, []*big.Int, err
|
||||
for _cpu, _ranges := range ranges(len(h), numcpu) {
|
||||
// split 2
|
||||
go func(cpu int, ranges [2]int) {
|
||||
for i := ranges[0]; i < ranges[1]; i++ {
|
||||
proofC[cpu].Add(proofC[cpu], new(bn256.G1).ScalarMult(pk.HExps[i], h[i]))
|
||||
}
|
||||
proofC[cpu] = scalarMultNoDoubleG1(pk.HExps[ranges[0]:ranges[1]],
|
||||
h[ranges[0]:ranges[1]],
|
||||
proofC[cpu],
|
||||
gsize)
|
||||
wg2.Done()
|
||||
}(_cpu, _ranges)
|
||||
}
|
||||
@@ -139,7 +128,7 @@ func GenerateProof(pk *types.Pk, w types.Witness) (*types.Proof, []*big.Int, err
|
||||
|
||||
proof.C.Add(proof.C, new(bn256.G1).ScalarMult(proof.A, s))
|
||||
proof.C.Add(proof.C, new(bn256.G1).ScalarMult(proofBG1[0], r))
|
||||
rsneg := new(big.Int).Mod(new(big.Int).Neg(new(big.Int).Mul(r, s)), types.R) // fAdd & fMul
|
||||
rsneg := new(big.Int).Mod(new(big.Int).Neg(new(big.Int).Mul(r, s)), types.R)
|
||||
proof.C.Add(proof.C, new(bn256.G1).ScalarMult(pk.VkDelta1, rsneg))
|
||||
|
||||
pubSignals := w[1 : pk.NPublic+1]
|
||||
@@ -182,7 +171,6 @@ func calculateH(pk *types.Pk, w types.Witness) []*big.Int {
|
||||
r := int(math.Log2(float64(m))) + 1
|
||||
roots := newRootsT()
|
||||
roots.setRoots(r)
|
||||
println("len(polASe)", len(polASe))
|
||||
|
||||
var wg2 sync.WaitGroup
|
||||
wg2.Add(numcpu)
|
||||
|
||||
@@ -4,6 +4,7 @@ import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
@@ -21,20 +22,40 @@ func TestCircuitsGenerateProof(t *testing.T) {
|
||||
}
|
||||
|
||||
func testCircuitGenerateProof(t *testing.T, circuit string) {
|
||||
provingKeyJson, err := ioutil.ReadFile("../testdata/" + circuit + "/proving_key.json")
|
||||
// Using json provingKey file:
|
||||
// provingKeyJson, err := ioutil.ReadFile("../testdata/" + circuit + "/proving_key.json")
|
||||
// require.Nil(t, err)
|
||||
// pk, err := parsers.ParsePk(provingKeyJson)
|
||||
// require.Nil(t, err)
|
||||
// witnessJson, err := ioutil.ReadFile("../testdata/" + circuit + "/witness.json")
|
||||
// require.Nil(t, err)
|
||||
// w, err := parsers.ParseWitness(witnessJson)
|
||||
// require.Nil(t, err)
|
||||
|
||||
// Using bin provingKey file:
|
||||
// pkBinFile, err := os.Open("../testdata/" + circuit + "/proving_key.bin")
|
||||
// require.Nil(t, err)
|
||||
// defer pkBinFile.Close()
|
||||
// pk, err := parsers.ParsePkBin(pkBinFile)
|
||||
// require.Nil(t, err)
|
||||
|
||||
// Using go bin provingKey file:
|
||||
pkGoBinFile, err := os.Open("../testdata/" + circuit + "/proving_key.go.bin")
|
||||
require.Nil(t, err)
|
||||
pk, err := parsers.ParsePk(provingKeyJson)
|
||||
defer pkGoBinFile.Close()
|
||||
pk, err := parsers.ParsePkGoBin(pkGoBinFile)
|
||||
require.Nil(t, err)
|
||||
|
||||
witnessJson, err := ioutil.ReadFile("../testdata/" + circuit + "/witness.json")
|
||||
witnessBinFile, err := os.Open("../testdata/" + circuit + "/witness.bin")
|
||||
require.Nil(t, err)
|
||||
w, err := parsers.ParseWitness(witnessJson)
|
||||
defer witnessBinFile.Close()
|
||||
w, err := parsers.ParseWitnessBin(witnessBinFile)
|
||||
require.Nil(t, err)
|
||||
|
||||
beforeT := time.Now()
|
||||
proof, pubSignals, err := GenerateProof(pk, w)
|
||||
assert.Nil(t, err)
|
||||
fmt.Println("proof generation time elapsed:", time.Since(beforeT))
|
||||
fmt.Println("proof generation time for "+circuit+" elapsed:", time.Since(beforeT))
|
||||
|
||||
proofStr, err := parsers.ProofToJson(proof)
|
||||
assert.Nil(t, err)
|
||||
@@ -61,12 +82,12 @@ func testCircuitGenerateProof(t *testing.T, circuit string) {
|
||||
|
||||
func BenchmarkGenerateProof(b *testing.B) {
|
||||
// benchmark with a circuit of 10000 constraints
|
||||
provingKeyJson, err := ioutil.ReadFile("../testdata/circuit1/proving_key.json")
|
||||
provingKeyJson, err := ioutil.ReadFile("../testdata/circuit5k/proving_key.json")
|
||||
require.Nil(b, err)
|
||||
pk, err := parsers.ParsePk(provingKeyJson)
|
||||
require.Nil(b, err)
|
||||
|
||||
witnessJson, err := ioutil.ReadFile("../testdata/circuit1/witness.json")
|
||||
witnessJson, err := ioutil.ReadFile("../testdata/circuit5k/witness.json")
|
||||
require.Nil(b, err)
|
||||
w, err := parsers.ParseWitness(witnessJson)
|
||||
require.Nil(b, err)
|
||||
|
||||
49
prover/tables.md
Normal file
49
prover/tables.md
Normal file
@@ -0,0 +1,49 @@
|
||||
# Tables Pre-calculation
|
||||
The most time consuming part of a ZKSnark proof calculation is the scalar multiplication of elliptic curve points. Direct mechanism accumulates each multiplication. However, prover only needs the total accumulation.
|
||||
|
||||
There are two potential improvements to the naive approach:
|
||||
|
||||
1. Apply Strauss-Shamir method (https://stackoverflow.com/questions/50993471/ec-scalar-multiplication-with-strauss-shamir-method).
|
||||
2. Leave the doubling operation for the last step
|
||||
|
||||
Both options can be combined.
|
||||
|
||||
In the following table, we show the results of using the naive method, Srauss-Shamir and Strauss-Shamir + No doubling. These last two options are repeated for different table grouping order.
|
||||
|
||||
There are 50000 G1 Elliptical Curve Points, and the scalars are 254 bits (BN256 curve).
|
||||
|
||||
There may be some concern on the additional size of the tables since they need to be loaded into a smartphone during the proof, and the time required to load these tables may exceed the benefits. If this is a problem, another althernative is to compute the tables during the proof itself. Depending on the Group Size, timing may be better than the naive approach.
|
||||
|
||||
|
||||
| Algorithm (G1) | GS 2 | GS 3 | GS 4 | GS 5 | GS 6 | GS 7 | GS 8 | GS 9 |
|
||||
|---|---|---|--|---|---|---|---|---|
|
||||
| Naive | 6.63s | - | - | - | - | - | - | - |
|
||||
| Strauss | 13.16s | 9.03s | 6.95s | 5.61s | 4.91s | 4.26s | 3.88s | 3.54 s |
|
||||
| Strauss + Table Computation | 16.13s | 11.32s | 8.47s | 7.10s | 6.2s | 5.94s | 6.01s | 6.69s |
|
||||
| No Doubling | 3.74s | 3.00s | 2.38s | 1.96s | 1.79s | 1.54s | 1.50s | 1.44s|
|
||||
| No Doubling + Table Computation | 6.83s | 5.1s | 4.16s | 3.52s| 3.22s | 3.21s | 3.57s | 4.56s |
|
||||
|
||||
There are 5000 G2 Elliptical Curve Points, and the scalars are 254 bits (BN256 curve).
|
||||
|
||||
| Algorithm (G2) | GS 2 | GS 3 | GS 4 | GS 5 | GS 6 | GS 7 | GS 8 | GS 9 |
|
||||
|---|---|---|--|---|---|---|---|---|
|
||||
| Naive | 3.55s | | | | | | | |
|
||||
| Strauss | 3.55s | 2.54s | 1.96s | 1.58s | 1.38s | 1.20s | 1.03s | 937ms |
|
||||
| Strauss + Table Computation | 3.59s | 2.58s | 2.04s | 1.71s | 1.51s | 1.46s | 1.51s | 1.82s |
|
||||
| No Doubling | 1.49s | 1.16s | 952ms | 719ms | 661ms | 548ms | 506ms| 444ms |
|
||||
| No Doubling + Table Computation | 1.55s | 1.21s | 984ms | 841ms | 826ms | 847ms | 1.03s | 1.39s |
|
||||
|
||||
| GS | Extra Disk Space per Constraint (G1)|
|
||||
|----|--------|
|
||||
| 2 | 64 B |
|
||||
| 3 | 106 B |
|
||||
| 4 | 192 B |
|
||||
| 5 | 346 B |
|
||||
| 6 | 618 B |
|
||||
| 7 | 1106 B |
|
||||
| 8 | 1984 B |
|
||||
| 9 | 3577 B |
|
||||
| N | 2^(N+6)/N - 64 B |
|
||||
|
||||
Extra disk space per constraint in G2 is twice the requirements for G1
|
||||
|
||||
1
testdata/.gitignore
vendored
Normal file
1
testdata/.gitignore
vendored
Normal file
@@ -0,0 +1 @@
|
||||
node_modules
|
||||
1
testdata/clean-gereated-files.sh
vendored
1
testdata/clean-gereated-files.sh
vendored
@@ -7,3 +7,4 @@ rm */*.cpp
|
||||
rm */*.sym
|
||||
rm */*.r1cs
|
||||
rm */*.sol
|
||||
rm */*.bin
|
||||
|
||||
35
testdata/compile-circuits.sh
vendored
35
testdata/compile-circuits.sh
vendored
@@ -1,29 +1,31 @@
|
||||
#!/bin/sh
|
||||
|
||||
npm install
|
||||
|
||||
compile_and_ts_and_witness() {
|
||||
echo $(date +"%T") "circom circuit.circom --r1cs --wasm --sym"
|
||||
itime="$(date -u +%s)"
|
||||
circom circuit.circom --r1cs --wasm --sym
|
||||
../node_modules/.bin/circom circuit.circom --r1cs --wasm --sym
|
||||
ftime="$(date -u +%s)"
|
||||
echo " ($(($(date -u +%s)-$itime))s)"
|
||||
|
||||
echo $(date +"%T") "snarkjs info -r circuit.r1cs"
|
||||
snarkjs info -r circuit.r1cs
|
||||
../node_modules/.bin/snarkjs info -r circuit.r1cs
|
||||
|
||||
echo $(date +"%T") "snarkjs setup"
|
||||
itime="$(date -u +%s)"
|
||||
snarkjs setup
|
||||
../node_modules/.bin/snarkjs setup
|
||||
echo " ($(($(date -u +%s)-$itime))s)"
|
||||
echo $(date +"%T") "trusted setup generated"
|
||||
|
||||
sed -i 's/null/["0","0","0"]/g' proving_key.json
|
||||
|
||||
echo "calculating witness"
|
||||
snarkjs calculatewitness --wasm circuit.wasm --input inputs.json --witness witness.json
|
||||
../node_modules/.bin/snarkjs calculatewitness --wasm circuit.wasm --input inputs.json --witness witness.json
|
||||
|
||||
echo $(date +"%T") "snarkjs generateverifier"
|
||||
itime="$(date -u +%s)"
|
||||
snarkjs generateverifier
|
||||
../node_modules/.bin/snarkjs generateverifier
|
||||
echo " ($(($(date -u +%s)-$itime))s)"
|
||||
echo $(date +"%T") "generateverifier generated"
|
||||
}
|
||||
@@ -40,3 +42,26 @@ compile_and_ts_and_witness
|
||||
# echo "compile & trustesetup for circuit20k"
|
||||
# cd ../circuit20k
|
||||
# compile_and_ts_and_witness
|
||||
|
||||
cd ../
|
||||
|
||||
echo "convert witness & pk of circuit1k to bin & go bin"
|
||||
node node_modules/wasmsnark/tools/buildwitness.js -i circuit1k/witness.json -o circuit1k/witness.bin
|
||||
node node_modules/wasmsnark/tools/buildpkey.js -i circuit1k/proving_key.json -o circuit1k/proving_key.bin
|
||||
go run ../cli/cli.go -convert -pk circuit1k/proving_key.json -pkbin circuit1k/proving_key.go.bin
|
||||
|
||||
echo "convert witness & pk of circuit5k to bin & go bin"
|
||||
node node_modules/wasmsnark/tools/buildwitness.js -i circuit5k/witness.json -o circuit5k/witness.bin
|
||||
node node_modules/wasmsnark/tools/buildpkey.js -i circuit5k/proving_key.json -o circuit5k/proving_key.bin
|
||||
go run ../cli/cli.go -convert -pk circuit5k/proving_key.json -pkbin circuit5k/proving_key.go.bin
|
||||
|
||||
# echo "convert witness & pk of circuit10k to bin & go bin"
|
||||
# node node_modules/wasmsnark/tools/buildwitness.js -i circuit10k/witness.json -o circuit10k/witness.bin
|
||||
# node node_modules/wasmsnark/tools/buildpkey.js -i circuit10k/proving_key.json -o circuit10k/proving_key.bin
|
||||
# go run ../cli/cli.go -convert -pk circuit10k/proving_key.json -pkbin circuit10k/proving_key.go.bin
|
||||
#
|
||||
# echo "convert witness & pk of circuit20k to bin & go bin"
|
||||
# node node_modules/wasmsnark/tools/buildwitness.js -i circuit20k/witness.json -o circuit20k/witness.bin
|
||||
# node node_modules/wasmsnark/tools/buildpkey.js -i circuit20k/proving_key.json -o circuit20k/proving_key.bin
|
||||
# go run ../cli/cli.go -convert -pk circuit20k/proving_key.json -pkbin circuit20k/proving_key.go.bin
|
||||
|
||||
|
||||
923
testdata/package-lock.json
generated
vendored
Normal file
923
testdata/package-lock.json
generated
vendored
Normal file
@@ -0,0 +1,923 @@
|
||||
{
|
||||
"name": "binformat",
|
||||
"version": "0.0.1",
|
||||
"lockfileVersion": 1,
|
||||
"requires": true,
|
||||
"dependencies": {
|
||||
"@types/color-name": {
|
||||
"version": "1.1.1",
|
||||
"resolved": "https://registry.npmjs.org/@types/color-name/-/color-name-1.1.1.tgz",
|
||||
"integrity": "sha512-rr+OQyAjxze7GgWrSaJwydHStIhHq2lvY3BOC2Mj7KnzI7XK0Uw1TOOdI9lDoajEbSWLiYgoo4f1R51erQfhPQ=="
|
||||
},
|
||||
"ansi-regex": {
|
||||
"version": "5.0.0",
|
||||
"resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.0.tgz",
|
||||
"integrity": "sha512-bY6fj56OUQ0hU1KjFNDQuJFezqKdrAyFdIevADiqrWHwSlbmBNMHp5ak2f40Pm8JTFyM2mqxkG6ngkHO11f/lg=="
|
||||
},
|
||||
"ansi-styles": {
|
||||
"version": "3.2.1",
|
||||
"resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz",
|
||||
"integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==",
|
||||
"requires": {
|
||||
"color-convert": "^1.9.0"
|
||||
}
|
||||
},
|
||||
"assertion-error": {
|
||||
"version": "1.1.0",
|
||||
"resolved": "https://registry.npmjs.org/assertion-error/-/assertion-error-1.1.0.tgz",
|
||||
"integrity": "sha512-jgsaNduz+ndvGyFt3uSuWqvy4lCnIJiovtouQN5JZHOKCS2QuhEdbcQHFhVksz2N2U9hXJo8odG7ETyWlEeuDw=="
|
||||
},
|
||||
"async": {
|
||||
"version": "0.9.2",
|
||||
"resolved": "https://registry.npmjs.org/async/-/async-0.9.2.tgz",
|
||||
"integrity": "sha1-rqdNXmHB+JlhO/ZL2mbUx48v0X0="
|
||||
},
|
||||
"balanced-match": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz",
|
||||
"integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c="
|
||||
},
|
||||
"big-integer": {
|
||||
"version": "1.6.48",
|
||||
"resolved": "https://registry.npmjs.org/big-integer/-/big-integer-1.6.48.tgz",
|
||||
"integrity": "sha512-j51egjPa7/i+RdiRuJbPdJ2FIUYYPhvYLjzoYbcMMm62ooO6F94fETG4MTs46zPAF9Brs04OajboA/qTGuz78w=="
|
||||
},
|
||||
"blakejs": {
|
||||
"version": "1.1.0",
|
||||
"resolved": "https://registry.npmjs.org/blakejs/-/blakejs-1.1.0.tgz",
|
||||
"integrity": "sha1-ad+S75U6qIylGjLfarHFShVfx6U="
|
||||
},
|
||||
"brace-expansion": {
|
||||
"version": "1.1.11",
|
||||
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz",
|
||||
"integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==",
|
||||
"requires": {
|
||||
"balanced-match": "^1.0.0",
|
||||
"concat-map": "0.0.1"
|
||||
}
|
||||
},
|
||||
"camelcase": {
|
||||
"version": "5.3.1",
|
||||
"resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz",
|
||||
"integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg=="
|
||||
},
|
||||
"chai": {
|
||||
"version": "4.2.0",
|
||||
"resolved": "https://registry.npmjs.org/chai/-/chai-4.2.0.tgz",
|
||||
"integrity": "sha512-XQU3bhBukrOsQCuwZndwGcCVQHyZi53fQ6Ys1Fym7E4olpIqqZZhhoFJoaKVvV17lWQoXYwgWN2nF5crA8J2jw==",
|
||||
"requires": {
|
||||
"assertion-error": "^1.1.0",
|
||||
"check-error": "^1.0.2",
|
||||
"deep-eql": "^3.0.1",
|
||||
"get-func-name": "^2.0.0",
|
||||
"pathval": "^1.1.0",
|
||||
"type-detect": "^4.0.5"
|
||||
}
|
||||
},
|
||||
"chalk": {
|
||||
"version": "2.4.2",
|
||||
"resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz",
|
||||
"integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==",
|
||||
"requires": {
|
||||
"ansi-styles": "^3.2.1",
|
||||
"escape-string-regexp": "^1.0.5",
|
||||
"supports-color": "^5.3.0"
|
||||
}
|
||||
},
|
||||
"check-error": {
|
||||
"version": "1.0.2",
|
||||
"resolved": "https://registry.npmjs.org/check-error/-/check-error-1.0.2.tgz",
|
||||
"integrity": "sha1-V00xLt2Iu13YkS6Sht1sCu1KrII="
|
||||
},
|
||||
"circom": {
|
||||
"version": "0.5.11",
|
||||
"resolved": "https://registry.npmjs.org/circom/-/circom-0.5.11.tgz",
|
||||
"integrity": "sha512-rX56jFdLSZx7o9bhVIVQhe+AQYSKapMc9Lrbg27MVTPPSaCZi2T3gbR3wsAISPGp2aH50kZtTvIzvo5O7XcW1Q==",
|
||||
"requires": {
|
||||
"chai": "^4.2.0",
|
||||
"circom_runtime": "0.0.6",
|
||||
"fastfile": "0.0.1",
|
||||
"ffiasm": "0.0.2",
|
||||
"ffjavascript": "0.1.2",
|
||||
"ffwasm": "0.0.7",
|
||||
"fnv-plus": "^1.3.1",
|
||||
"r1csfile": "0.0.5",
|
||||
"tmp-promise": "^2.0.2",
|
||||
"wasmbuilder": "0.0.10"
|
||||
}
|
||||
},
|
||||
"circom_runtime": {
|
||||
"version": "0.0.6",
|
||||
"resolved": "https://registry.npmjs.org/circom_runtime/-/circom_runtime-0.0.6.tgz",
|
||||
"integrity": "sha512-o0T5MuWzxnxinWG3+CygS/kZouoP+z5ZrufUwqKJy3gsVFJhkbqMpfKmcBGjhExB3uatA7cKyOiRAOLOz5+t5w==",
|
||||
"requires": {
|
||||
"ffjavascript": "0.1.0",
|
||||
"fnv-plus": "^1.3.1"
|
||||
},
|
||||
"dependencies": {
|
||||
"ffjavascript": {
|
||||
"version": "0.1.0",
|
||||
"resolved": "https://registry.npmjs.org/ffjavascript/-/ffjavascript-0.1.0.tgz",
|
||||
"integrity": "sha512-dmKlUasSfvUcxBm8nCSKl2x7EFJsXA7OVP8XLFA03T2+6mAc3IiVLC2ambEVOcMOhyhl0vJfVZjM9f9d38D1rw==",
|
||||
"requires": {
|
||||
"big-integer": "^1.6.48"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"cliui": {
|
||||
"version": "6.0.0",
|
||||
"resolved": "https://registry.npmjs.org/cliui/-/cliui-6.0.0.tgz",
|
||||
"integrity": "sha512-t6wbgtoCXvAzst7QgXxJYqPt0usEfbgQdftEPbLL/cvv6HPE5VgvqCuAIDR0NgU52ds6rFwqrgakNLrHEjCbrQ==",
|
||||
"requires": {
|
||||
"string-width": "^4.2.0",
|
||||
"strip-ansi": "^6.0.0",
|
||||
"wrap-ansi": "^6.2.0"
|
||||
}
|
||||
},
|
||||
"code-point-at": {
|
||||
"version": "1.1.0",
|
||||
"resolved": "https://registry.npmjs.org/code-point-at/-/code-point-at-1.1.0.tgz",
|
||||
"integrity": "sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c="
|
||||
},
|
||||
"color-convert": {
|
||||
"version": "1.9.3",
|
||||
"resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz",
|
||||
"integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==",
|
||||
"requires": {
|
||||
"color-name": "1.1.3"
|
||||
}
|
||||
},
|
||||
"color-name": {
|
||||
"version": "1.1.3",
|
||||
"resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz",
|
||||
"integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU="
|
||||
},
|
||||
"concat-map": {
|
||||
"version": "0.0.1",
|
||||
"resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz",
|
||||
"integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s="
|
||||
},
|
||||
"cross-spawn": {
|
||||
"version": "6.0.5",
|
||||
"resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-6.0.5.tgz",
|
||||
"integrity": "sha512-eTVLrBSt7fjbDygz805pMnstIs2VTBNkRm0qxZd+M7A5XDdxVRWO5MxGBXZhjY4cqLYLdtrGqRf8mBPmzwSpWQ==",
|
||||
"requires": {
|
||||
"nice-try": "^1.0.4",
|
||||
"path-key": "^2.0.1",
|
||||
"semver": "^5.5.0",
|
||||
"shebang-command": "^1.2.0",
|
||||
"which": "^1.2.9"
|
||||
}
|
||||
},
|
||||
"decamelize": {
|
||||
"version": "1.2.0",
|
||||
"resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz",
|
||||
"integrity": "sha1-9lNNFRSCabIDUue+4m9QH5oZEpA="
|
||||
},
|
||||
"deep-eql": {
|
||||
"version": "3.0.1",
|
||||
"resolved": "https://registry.npmjs.org/deep-eql/-/deep-eql-3.0.1.tgz",
|
||||
"integrity": "sha512-+QeIQyN5ZuO+3Uk5DYh6/1eKO0m0YmJFGNmFHGACpf1ClL1nmlV/p4gNgbl2pJGxgXb4faqo6UE+M5ACEMyVcw==",
|
||||
"requires": {
|
||||
"type-detect": "^4.0.0"
|
||||
}
|
||||
},
|
||||
"ejs": {
|
||||
"version": "3.1.2",
|
||||
"resolved": "https://registry.npmjs.org/ejs/-/ejs-3.1.2.tgz",
|
||||
"integrity": "sha512-zFuywxrAWtX5Mk2KAuoJNkXXbfezpNA0v7i+YC971QORguPekpjpAgeOv99YWSdKXwj7JxI2QAWDeDkE8fWtXw==",
|
||||
"requires": {
|
||||
"jake": "^10.6.1"
|
||||
}
|
||||
},
|
||||
"emoji-regex": {
|
||||
"version": "8.0.0",
|
||||
"resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz",
|
||||
"integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A=="
|
||||
},
|
||||
"end-of-stream": {
|
||||
"version": "1.4.4",
|
||||
"resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz",
|
||||
"integrity": "sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==",
|
||||
"requires": {
|
||||
"once": "^1.4.0"
|
||||
}
|
||||
},
|
||||
"escape-string-regexp": {
|
||||
"version": "1.0.5",
|
||||
"resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz",
|
||||
"integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ="
|
||||
},
|
||||
"execa": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/execa/-/execa-1.0.0.tgz",
|
||||
"integrity": "sha512-adbxcyWV46qiHyvSp50TKt05tB4tK3HcmF7/nxfAdhnox83seTDbwnaqKO4sXRy7roHAIFqJP/Rw/AuEbX61LA==",
|
||||
"requires": {
|
||||
"cross-spawn": "^6.0.0",
|
||||
"get-stream": "^4.0.0",
|
||||
"is-stream": "^1.1.0",
|
||||
"npm-run-path": "^2.0.0",
|
||||
"p-finally": "^1.0.0",
|
||||
"signal-exit": "^3.0.0",
|
||||
"strip-eof": "^1.0.0"
|
||||
}
|
||||
},
|
||||
"fastfile": {
|
||||
"version": "0.0.1",
|
||||
"resolved": "https://registry.npmjs.org/fastfile/-/fastfile-0.0.1.tgz",
|
||||
"integrity": "sha512-Fk8PWafGWGEUw7oPq/dJen92ASxknCEy4ZC8n4VEvSwCp/jcReyEmVoWsRIWTf+IvAp2MzvFi54vOPeK2LQZtQ=="
|
||||
},
|
||||
"ffiasm": {
|
||||
"version": "0.0.2",
|
||||
"resolved": "https://registry.npmjs.org/ffiasm/-/ffiasm-0.0.2.tgz",
|
||||
"integrity": "sha512-o/CL7F4IodB7eRHCOQL1SrqN2DIPHrQbEwjPY7NIyeBRdnB3G0xo6b6Mj44SKiWFnvpQMb3n4N7acjD3vv4NVQ==",
|
||||
"requires": {
|
||||
"big-integer": "^1.6.48",
|
||||
"ejs": "^3.0.1",
|
||||
"yargs": "^15.3.1"
|
||||
}
|
||||
},
|
||||
"ffjavascript": {
|
||||
"version": "0.1.2",
|
||||
"resolved": "https://registry.npmjs.org/ffjavascript/-/ffjavascript-0.1.2.tgz",
|
||||
"integrity": "sha512-zB1dhgBjJlvyk2VQIQzFSpUJmanYQYDR/Fo1KhZnaNW5chMFJT55qz0dx1LMKrAklBbidKzz2/C7dgibxQF94g==",
|
||||
"requires": {
|
||||
"big-integer": "^1.6.48"
|
||||
}
|
||||
},
|
||||
"ffwasm": {
|
||||
"version": "0.0.7",
|
||||
"resolved": "https://registry.npmjs.org/ffwasm/-/ffwasm-0.0.7.tgz",
|
||||
"integrity": "sha512-17cTLzv7HHAKqZbX8MvHxjSrR0yDdn1sh4TVsTbAvO9e6klhFicnyoVXc/sCuViV/M8g65sCmVrAmoPCZp1YkQ==",
|
||||
"requires": {
|
||||
"big-integer": "^1.6.48",
|
||||
"wasmbuilder": "0.0.10"
|
||||
}
|
||||
},
|
||||
"filelist": {
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/filelist/-/filelist-1.0.1.tgz",
|
||||
"integrity": "sha512-8zSK6Nu0DQIC08mUC46sWGXi+q3GGpKydAG36k+JDba6VRpkevvOWUW5a/PhShij4+vHT9M+ghgG7eM+a9JDUQ==",
|
||||
"requires": {
|
||||
"minimatch": "^3.0.4"
|
||||
}
|
||||
},
|
||||
"find-up": {
|
||||
"version": "4.1.0",
|
||||
"resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz",
|
||||
"integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==",
|
||||
"requires": {
|
||||
"locate-path": "^5.0.0",
|
||||
"path-exists": "^4.0.0"
|
||||
}
|
||||
},
|
||||
"fnv-plus": {
|
||||
"version": "1.3.1",
|
||||
"resolved": "https://registry.npmjs.org/fnv-plus/-/fnv-plus-1.3.1.tgz",
|
||||
"integrity": "sha512-Gz1EvfOneuFfk4yG458dJ3TLJ7gV19q3OM/vVvvHf7eT02Hm1DleB4edsia6ahbKgAYxO9gvyQ1ioWZR+a00Yw=="
|
||||
},
|
||||
"fs.realpath": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz",
|
||||
"integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8="
|
||||
},
|
||||
"get-caller-file": {
|
||||
"version": "2.0.5",
|
||||
"resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz",
|
||||
"integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg=="
|
||||
},
|
||||
"get-func-name": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/get-func-name/-/get-func-name-2.0.0.tgz",
|
||||
"integrity": "sha1-6td0q+5y4gQJQzoGY2YCPdaIekE="
|
||||
},
|
||||
"get-stream": {
|
||||
"version": "4.1.0",
|
||||
"resolved": "https://registry.npmjs.org/get-stream/-/get-stream-4.1.0.tgz",
|
||||
"integrity": "sha512-GMat4EJ5161kIy2HevLlr4luNjBgvmj413KaQA7jt4V8B4RDsfpHk7WQ9GVqfYyyx8OS/L66Kox+rJRNklLK7w==",
|
||||
"requires": {
|
||||
"pump": "^3.0.0"
|
||||
}
|
||||
},
|
||||
"glob": {
|
||||
"version": "7.1.6",
|
||||
"resolved": "https://registry.npmjs.org/glob/-/glob-7.1.6.tgz",
|
||||
"integrity": "sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA==",
|
||||
"requires": {
|
||||
"fs.realpath": "^1.0.0",
|
||||
"inflight": "^1.0.4",
|
||||
"inherits": "2",
|
||||
"minimatch": "^3.0.4",
|
||||
"once": "^1.3.0",
|
||||
"path-is-absolute": "^1.0.0"
|
||||
}
|
||||
},
|
||||
"has-flag": {
|
||||
"version": "3.0.0",
|
||||
"resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz",
|
||||
"integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0="
|
||||
},
|
||||
"inflight": {
|
||||
"version": "1.0.6",
|
||||
"resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz",
|
||||
"integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=",
|
||||
"requires": {
|
||||
"once": "^1.3.0",
|
||||
"wrappy": "1"
|
||||
}
|
||||
},
|
||||
"inherits": {
|
||||
"version": "2.0.4",
|
||||
"resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz",
|
||||
"integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ=="
|
||||
},
|
||||
"invert-kv": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/invert-kv/-/invert-kv-2.0.0.tgz",
|
||||
"integrity": "sha512-wPVv/y/QQ/Uiirj/vh3oP+1Ww+AWehmi1g5fFWGPF6IpCBCDVrhgHRMvrLfdYcwDh3QJbGXDW4JAuzxElLSqKA=="
|
||||
},
|
||||
"is-fullwidth-code-point": {
|
||||
"version": "3.0.0",
|
||||
"resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz",
|
||||
"integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg=="
|
||||
},
|
||||
"is-stream": {
|
||||
"version": "1.1.0",
|
||||
"resolved": "https://registry.npmjs.org/is-stream/-/is-stream-1.1.0.tgz",
|
||||
"integrity": "sha1-EtSj3U5o4Lec6428hBc66A2RykQ="
|
||||
},
|
||||
"isexe": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz",
|
||||
"integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA="
|
||||
},
|
||||
"jake": {
|
||||
"version": "10.6.1",
|
||||
"resolved": "https://registry.npmjs.org/jake/-/jake-10.6.1.tgz",
|
||||
"integrity": "sha512-pHUK3+V0BjOb1XSi95rbBksrMdIqLVC9bJqDnshVyleYsET3H0XAq+3VB2E3notcYvv4wRdRHn13p7vobG+wfQ==",
|
||||
"requires": {
|
||||
"async": "0.9.x",
|
||||
"chalk": "^2.4.2",
|
||||
"filelist": "^1.0.1",
|
||||
"minimatch": "^3.0.4"
|
||||
}
|
||||
},
|
||||
"keccak": {
|
||||
"version": "3.0.0",
|
||||
"resolved": "https://registry.npmjs.org/keccak/-/keccak-3.0.0.tgz",
|
||||
"integrity": "sha512-/4h4FIfFEpTEuySXi/nVFM5rqSKPnnhI7cL4K3MFSwoI3VyM7AhPSq3SsysARtnEBEeIKMBUWD8cTh9nHE8AkA==",
|
||||
"requires": {
|
||||
"node-addon-api": "^2.0.0",
|
||||
"node-gyp-build": "^4.2.0"
|
||||
}
|
||||
},
|
||||
"lcid": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/lcid/-/lcid-2.0.0.tgz",
|
||||
"integrity": "sha512-avPEb8P8EGnwXKClwsNUgryVjllcRqtMYa49NTsbQagYuT1DcXnl1915oxWjoyGrXR6zH/Y0Zc96xWsPcoDKeA==",
|
||||
"requires": {
|
||||
"invert-kv": "^2.0.0"
|
||||
}
|
||||
},
|
||||
"locate-path": {
|
||||
"version": "5.0.0",
|
||||
"resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz",
|
||||
"integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==",
|
||||
"requires": {
|
||||
"p-locate": "^4.1.0"
|
||||
}
|
||||
},
|
||||
"map-age-cleaner": {
|
||||
"version": "0.1.3",
|
||||
"resolved": "https://registry.npmjs.org/map-age-cleaner/-/map-age-cleaner-0.1.3.tgz",
|
||||
"integrity": "sha512-bJzx6nMoP6PDLPBFmg7+xRKeFZvFboMrGlxmNj9ClvX53KrmvM5bXFXEWjbz4cz1AFn+jWJ9z/DJSz7hrs0w3w==",
|
||||
"requires": {
|
||||
"p-defer": "^1.0.0"
|
||||
}
|
||||
},
|
||||
"mem": {
|
||||
"version": "4.3.0",
|
||||
"resolved": "https://registry.npmjs.org/mem/-/mem-4.3.0.tgz",
|
||||
"integrity": "sha512-qX2bG48pTqYRVmDB37rn/6PT7LcR8T7oAX3bf99u1Tt1nzxYfxkgqDwUwolPlXweM0XzBOBFzSx4kfp7KP1s/w==",
|
||||
"requires": {
|
||||
"map-age-cleaner": "^0.1.1",
|
||||
"mimic-fn": "^2.0.0",
|
||||
"p-is-promise": "^2.0.0"
|
||||
}
|
||||
},
|
||||
"mimic-fn": {
|
||||
"version": "2.1.0",
|
||||
"resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz",
|
||||
"integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg=="
|
||||
},
|
||||
"minimatch": {
|
||||
"version": "3.0.4",
|
||||
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz",
|
||||
"integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==",
|
||||
"requires": {
|
||||
"brace-expansion": "^1.1.7"
|
||||
}
|
||||
},
|
||||
"nice-try": {
|
||||
"version": "1.0.5",
|
||||
"resolved": "https://registry.npmjs.org/nice-try/-/nice-try-1.0.5.tgz",
|
||||
"integrity": "sha512-1nh45deeb5olNY7eX82BkPO7SSxR5SSYJiPTrTdFUVYwAl8CKMA5N9PjTYkHiRjisVcxcQ1HXdLhx2qxxJzLNQ=="
|
||||
},
|
||||
"node-addon-api": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-2.0.0.tgz",
|
||||
"integrity": "sha512-ASCL5U13as7HhOExbT6OlWJJUV/lLzL2voOSP1UVehpRD8FbSrSDjfScK/KwAvVTI5AS6r4VwbOMlIqtvRidnA=="
|
||||
},
|
||||
"node-gyp-build": {
|
||||
"version": "4.2.2",
|
||||
"resolved": "https://registry.npmjs.org/node-gyp-build/-/node-gyp-build-4.2.2.tgz",
|
||||
"integrity": "sha512-Lqh7mrByWCM8Cf9UPqpeoVBBo5Ugx+RKu885GAzmLBVYjeywScxHXPGLa4JfYNZmcNGwzR0Glu5/9GaQZMFqyA=="
|
||||
},
|
||||
"npm-run-path": {
|
||||
"version": "2.0.2",
|
||||
"resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-2.0.2.tgz",
|
||||
"integrity": "sha1-NakjLfo11wZ7TLLd8jV7GHFTbF8=",
|
||||
"requires": {
|
||||
"path-key": "^2.0.0"
|
||||
}
|
||||
},
|
||||
"number-is-nan": {
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/number-is-nan/-/number-is-nan-1.0.1.tgz",
|
||||
"integrity": "sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0="
|
||||
},
|
||||
"once": {
|
||||
"version": "1.4.0",
|
||||
"resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz",
|
||||
"integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=",
|
||||
"requires": {
|
||||
"wrappy": "1"
|
||||
}
|
||||
},
|
||||
"os-locale": {
|
||||
"version": "3.1.0",
|
||||
"resolved": "https://registry.npmjs.org/os-locale/-/os-locale-3.1.0.tgz",
|
||||
"integrity": "sha512-Z8l3R4wYWM40/52Z+S265okfFj8Kt2cC2MKY+xNi3kFs+XGI7WXu/I309QQQYbRW4ijiZ+yxs9pqEhJh0DqW3Q==",
|
||||
"requires": {
|
||||
"execa": "^1.0.0",
|
||||
"lcid": "^2.0.0",
|
||||
"mem": "^4.0.0"
|
||||
}
|
||||
},
|
||||
"p-defer": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/p-defer/-/p-defer-1.0.0.tgz",
|
||||
"integrity": "sha1-n26xgvbJqozXQwBKfU+WsZaw+ww="
|
||||
},
|
||||
"p-finally": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/p-finally/-/p-finally-1.0.0.tgz",
|
||||
"integrity": "sha1-P7z7FbiZpEEjs0ttzBi3JDNqLK4="
|
||||
},
|
||||
"p-is-promise": {
|
||||
"version": "2.1.0",
|
||||
"resolved": "https://registry.npmjs.org/p-is-promise/-/p-is-promise-2.1.0.tgz",
|
||||
"integrity": "sha512-Y3W0wlRPK8ZMRbNq97l4M5otioeA5lm1z7bkNkxCka8HSPjR0xRWmpCmc9utiaLP9Jb1eD8BgeIxTW4AIF45Pg=="
|
||||
},
|
||||
"p-limit": {
|
||||
"version": "2.3.0",
|
||||
"resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz",
|
||||
"integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==",
|
||||
"requires": {
|
||||
"p-try": "^2.0.0"
|
||||
}
|
||||
},
|
||||
"p-locate": {
|
||||
"version": "4.1.0",
|
||||
"resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz",
|
||||
"integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==",
|
||||
"requires": {
|
||||
"p-limit": "^2.2.0"
|
||||
}
|
||||
},
|
||||
"p-try": {
|
||||
"version": "2.2.0",
|
||||
"resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz",
|
||||
"integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ=="
|
||||
},
|
||||
"path-exists": {
|
||||
"version": "4.0.0",
|
||||
"resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz",
|
||||
"integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w=="
|
||||
},
|
||||
"path-is-absolute": {
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz",
|
||||
"integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18="
|
||||
},
|
||||
"path-key": {
|
||||
"version": "2.0.1",
|
||||
"resolved": "https://registry.npmjs.org/path-key/-/path-key-2.0.1.tgz",
|
||||
"integrity": "sha1-QRyttXTFoUDTpLGRDUDYDMn0C0A="
|
||||
},
|
||||
"pathval": {
|
||||
"version": "1.1.0",
|
||||
"resolved": "https://registry.npmjs.org/pathval/-/pathval-1.1.0.tgz",
|
||||
"integrity": "sha1-uULm1L3mUwBe9rcTYd74cn0GReA="
|
||||
},
|
||||
"pump": {
|
||||
"version": "3.0.0",
|
||||
"resolved": "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz",
|
||||
"integrity": "sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==",
|
||||
"requires": {
|
||||
"end-of-stream": "^1.1.0",
|
||||
"once": "^1.3.1"
|
||||
}
|
||||
},
|
||||
"r1csfile": {
|
||||
"version": "0.0.5",
|
||||
"resolved": "https://registry.npmjs.org/r1csfile/-/r1csfile-0.0.5.tgz",
|
||||
"integrity": "sha512-B+BdKPb/WUTp4N/3X4d1Spgx9Ojx5tFVejGZRJxpTtzq34mC8Vi/czWfiPj85V8kud31lCfYcZ16z7+czvM0Sw==",
|
||||
"requires": {
|
||||
"fastfile": "0.0.1",
|
||||
"ffjavascript": "0.1.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"ffjavascript": {
|
||||
"version": "0.1.0",
|
||||
"resolved": "https://registry.npmjs.org/ffjavascript/-/ffjavascript-0.1.0.tgz",
|
||||
"integrity": "sha512-dmKlUasSfvUcxBm8nCSKl2x7EFJsXA7OVP8XLFA03T2+6mAc3IiVLC2ambEVOcMOhyhl0vJfVZjM9f9d38D1rw==",
|
||||
"requires": {
|
||||
"big-integer": "^1.6.48"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"require-directory": {
|
||||
"version": "2.1.1",
|
||||
"resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz",
|
||||
"integrity": "sha1-jGStX9MNqxyXbiNE/+f3kqam30I="
|
||||
},
|
||||
"require-main-filename": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-2.0.0.tgz",
|
||||
"integrity": "sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg=="
|
||||
},
|
||||
"rimraf": {
|
||||
"version": "2.7.1",
|
||||
"resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz",
|
||||
"integrity": "sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==",
|
||||
"requires": {
|
||||
"glob": "^7.1.3"
|
||||
}
|
||||
},
|
||||
"semver": {
|
||||
"version": "5.7.1",
|
||||
"resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz",
|
||||
"integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ=="
|
||||
},
|
||||
"set-blocking": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz",
|
||||
"integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc="
|
||||
},
|
||||
"shebang-command": {
|
||||
"version": "1.2.0",
|
||||
"resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-1.2.0.tgz",
|
||||
"integrity": "sha1-RKrGW2lbAzmJaMOfNj/uXer98eo=",
|
||||
"requires": {
|
||||
"shebang-regex": "^1.0.0"
|
||||
}
|
||||
},
|
||||
"shebang-regex": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-1.0.0.tgz",
|
||||
"integrity": "sha1-2kL0l0DAtC2yypcoVxyxkMmO/qM="
|
||||
},
|
||||
"signal-exit": {
|
||||
"version": "3.0.3",
|
||||
"resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.3.tgz",
|
||||
"integrity": "sha512-VUJ49FC8U1OxwZLxIbTTrDvLnf/6TDgxZcK8wxR8zs13xpx7xbG60ndBlhNrFi2EMuFRoeDoJO7wthSLq42EjA=="
|
||||
},
|
||||
"snarkjs": {
|
||||
"version": "0.1.31",
|
||||
"resolved": "https://registry.npmjs.org/snarkjs/-/snarkjs-0.1.31.tgz",
|
||||
"integrity": "sha512-Xu9Ai89GPLUI6hSyVkc6LRE3sUEje7+eokHeKkb4sZuWW4JqPKWRW7ZtwM7VjsisgVM2gVAg9IYsMD4k+MhuPA==",
|
||||
"requires": {
|
||||
"chai": "^4.2.0",
|
||||
"circom_runtime": "0.0.6",
|
||||
"escape-string-regexp": "^1.0.5",
|
||||
"ffjavascript": "0.1.0",
|
||||
"keccak": "^3.0.0",
|
||||
"r1csfile": "0.0.5",
|
||||
"yargs": "^12.0.5"
|
||||
},
|
||||
"dependencies": {
|
||||
"ansi-regex": {
|
||||
"version": "3.0.0",
|
||||
"resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz",
|
||||
"integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg="
|
||||
},
|
||||
"cliui": {
|
||||
"version": "4.1.0",
|
||||
"resolved": "https://registry.npmjs.org/cliui/-/cliui-4.1.0.tgz",
|
||||
"integrity": "sha512-4FG+RSG9DL7uEwRUZXZn3SS34DiDPfzP0VOiEwtUWlE+AR2EIg+hSyvrIgUUfhdgR/UkAeW2QHgeP+hWrXs7jQ==",
|
||||
"requires": {
|
||||
"string-width": "^2.1.1",
|
||||
"strip-ansi": "^4.0.0",
|
||||
"wrap-ansi": "^2.0.0"
|
||||
}
|
||||
},
|
||||
"ffjavascript": {
|
||||
"version": "0.1.0",
|
||||
"resolved": "https://registry.npmjs.org/ffjavascript/-/ffjavascript-0.1.0.tgz",
|
||||
"integrity": "sha512-dmKlUasSfvUcxBm8nCSKl2x7EFJsXA7OVP8XLFA03T2+6mAc3IiVLC2ambEVOcMOhyhl0vJfVZjM9f9d38D1rw==",
|
||||
"requires": {
|
||||
"big-integer": "^1.6.48"
|
||||
}
|
||||
},
|
||||
"find-up": {
|
||||
"version": "3.0.0",
|
||||
"resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz",
|
||||
"integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==",
|
||||
"requires": {
|
||||
"locate-path": "^3.0.0"
|
||||
}
|
||||
},
|
||||
"get-caller-file": {
|
||||
"version": "1.0.3",
|
||||
"resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-1.0.3.tgz",
|
||||
"integrity": "sha512-3t6rVToeoZfYSGd8YoLFR2DJkiQrIiUrGcjvFX2mDw3bn6k2OtwHN0TNCLbBO+w8qTvimhDkv+LSscbJY1vE6w=="
|
||||
},
|
||||
"is-fullwidth-code-point": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz",
|
||||
"integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8="
|
||||
},
|
||||
"locate-path": {
|
||||
"version": "3.0.0",
|
||||
"resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz",
|
||||
"integrity": "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==",
|
||||
"requires": {
|
||||
"p-locate": "^3.0.0",
|
||||
"path-exists": "^3.0.0"
|
||||
}
|
||||
},
|
||||
"p-locate": {
|
||||
"version": "3.0.0",
|
||||
"resolved": "https://registry.npmjs.org/p-locate/-/p-locate-3.0.0.tgz",
|
||||
"integrity": "sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==",
|
||||
"requires": {
|
||||
"p-limit": "^2.0.0"
|
||||
}
|
||||
},
|
||||
"path-exists": {
|
||||
"version": "3.0.0",
|
||||
"resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz",
|
||||
"integrity": "sha1-zg6+ql94yxiSXqfYENe1mwEP1RU="
|
||||
},
|
||||
"require-main-filename": {
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-1.0.1.tgz",
|
||||
"integrity": "sha1-l/cXtp1IeE9fUmpsWqj/3aBVpNE="
|
||||
},
|
||||
"string-width": {
|
||||
"version": "2.1.1",
|
||||
"resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz",
|
||||
"integrity": "sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==",
|
||||
"requires": {
|
||||
"is-fullwidth-code-point": "^2.0.0",
|
||||
"strip-ansi": "^4.0.0"
|
||||
}
|
||||
},
|
||||
"strip-ansi": {
|
||||
"version": "4.0.0",
|
||||
"resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz",
|
||||
"integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=",
|
||||
"requires": {
|
||||
"ansi-regex": "^3.0.0"
|
||||
}
|
||||
},
|
||||
"wrap-ansi": {
|
||||
"version": "2.1.0",
|
||||
"resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-2.1.0.tgz",
|
||||
"integrity": "sha1-2Pw9KE3QV5T+hJc8rs3Rz4JP3YU=",
|
||||
"requires": {
|
||||
"string-width": "^1.0.1",
|
||||
"strip-ansi": "^3.0.1"
|
||||
},
|
||||
"dependencies": {
|
||||
"ansi-regex": {
|
||||
"version": "2.1.1",
|
||||
"resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz",
|
||||
"integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8="
|
||||
},
|
||||
"is-fullwidth-code-point": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz",
|
||||
"integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=",
|
||||
"requires": {
|
||||
"number-is-nan": "^1.0.0"
|
||||
}
|
||||
},
|
||||
"string-width": {
|
||||
"version": "1.0.2",
|
||||
"resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz",
|
||||
"integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=",
|
||||
"requires": {
|
||||
"code-point-at": "^1.0.0",
|
||||
"is-fullwidth-code-point": "^1.0.0",
|
||||
"strip-ansi": "^3.0.0"
|
||||
}
|
||||
},
|
||||
"strip-ansi": {
|
||||
"version": "3.0.1",
|
||||
"resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz",
|
||||
"integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=",
|
||||
"requires": {
|
||||
"ansi-regex": "^2.0.0"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"yargs": {
|
||||
"version": "12.0.5",
|
||||
"resolved": "https://registry.npmjs.org/yargs/-/yargs-12.0.5.tgz",
|
||||
"integrity": "sha512-Lhz8TLaYnxq/2ObqHDql8dX8CJi97oHxrjUcYtzKbbykPtVW9WB+poxI+NM2UIzsMgNCZTIf0AQwsjK5yMAqZw==",
|
||||
"requires": {
|
||||
"cliui": "^4.0.0",
|
||||
"decamelize": "^1.2.0",
|
||||
"find-up": "^3.0.0",
|
||||
"get-caller-file": "^1.0.1",
|
||||
"os-locale": "^3.0.0",
|
||||
"require-directory": "^2.1.1",
|
||||
"require-main-filename": "^1.0.1",
|
||||
"set-blocking": "^2.0.0",
|
||||
"string-width": "^2.0.0",
|
||||
"which-module": "^2.0.0",
|
||||
"y18n": "^3.2.1 || ^4.0.0",
|
||||
"yargs-parser": "^11.1.1"
|
||||
}
|
||||
},
|
||||
"yargs-parser": {
|
||||
"version": "11.1.1",
|
||||
"resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-11.1.1.tgz",
|
||||
"integrity": "sha512-C6kB/WJDiaxONLJQnF8ccx9SEeoTTLek8RVbaOIsrAUS8VrBEXfmeSnCZxygc+XC2sNMBIwOOnfcxiynjHsVSQ==",
|
||||
"requires": {
|
||||
"camelcase": "^5.0.0",
|
||||
"decamelize": "^1.2.0"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"string-width": {
|
||||
"version": "4.2.0",
|
||||
"resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.0.tgz",
|
||||
"integrity": "sha512-zUz5JD+tgqtuDjMhwIg5uFVV3dtqZ9yQJlZVfq4I01/K5Paj5UHj7VyrQOJvzawSVlKpObApbfD0Ed6yJc+1eg==",
|
||||
"requires": {
|
||||
"emoji-regex": "^8.0.0",
|
||||
"is-fullwidth-code-point": "^3.0.0",
|
||||
"strip-ansi": "^6.0.0"
|
||||
}
|
||||
},
|
||||
"strip-ansi": {
|
||||
"version": "6.0.0",
|
||||
"resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.0.tgz",
|
||||
"integrity": "sha512-AuvKTrTfQNYNIctbR1K/YGTR1756GycPsg7b9bdV9Duqur4gv6aKqHXah67Z8ImS7WEz5QVcOtlfW2rZEugt6w==",
|
||||
"requires": {
|
||||
"ansi-regex": "^5.0.0"
|
||||
}
|
||||
},
|
||||
"strip-eof": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/strip-eof/-/strip-eof-1.0.0.tgz",
|
||||
"integrity": "sha1-u0P/VZim6wXYm1n80SnJgzE2Br8="
|
||||
},
|
||||
"supports-color": {
|
||||
"version": "5.5.0",
|
||||
"resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz",
|
||||
"integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==",
|
||||
"requires": {
|
||||
"has-flag": "^3.0.0"
|
||||
}
|
||||
},
|
||||
"tmp": {
|
||||
"version": "0.1.0",
|
||||
"resolved": "https://registry.npmjs.org/tmp/-/tmp-0.1.0.tgz",
|
||||
"integrity": "sha512-J7Z2K08jbGcdA1kkQpJSqLF6T0tdQqpR2pnSUXsIchbPdTI9v3e85cLW0d6WDhwuAleOV71j2xWs8qMPfK7nKw==",
|
||||
"requires": {
|
||||
"rimraf": "^2.6.3"
|
||||
}
|
||||
},
|
||||
"tmp-promise": {
|
||||
"version": "2.0.2",
|
||||
"resolved": "https://registry.npmjs.org/tmp-promise/-/tmp-promise-2.0.2.tgz",
|
||||
"integrity": "sha512-zl71nFWjPKW2KXs+73gEk8RmqvtAeXPxhWDkTUoa3MSMkjq3I+9OeknjF178MQoMYsdqL730hfzvNfEkePxq9Q==",
|
||||
"requires": {
|
||||
"tmp": "0.1.0"
|
||||
}
|
||||
},
|
||||
"type-detect": {
|
||||
"version": "4.0.8",
|
||||
"resolved": "https://registry.npmjs.org/type-detect/-/type-detect-4.0.8.tgz",
|
||||
"integrity": "sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g=="
|
||||
},
|
||||
"wasmbuilder": {
|
||||
"version": "0.0.10",
|
||||
"resolved": "https://registry.npmjs.org/wasmbuilder/-/wasmbuilder-0.0.10.tgz",
|
||||
"integrity": "sha512-zQSvZ7d74d9OvN+mCN6ucNne4QS5/cBBYTHldX0Oe+u9gStY21orapvuX1ajisA7RVIpuFhYg+ZgdySsPfeh0A==",
|
||||
"requires": {
|
||||
"big-integer": "^1.6.48"
|
||||
}
|
||||
},
|
||||
"wasmsnark": {
|
||||
"version": "0.0.10",
|
||||
"resolved": "https://registry.npmjs.org/wasmsnark/-/wasmsnark-0.0.10.tgz",
|
||||
"integrity": "sha512-ARrJWhxvnBJXMERwBcnEnO5ByLwYhJZr1xwac9dl61SN7+1eOmG7Od3SJL1GzU6zaf86b9wza20y1d5ThCecLw==",
|
||||
"requires": {
|
||||
"big-integer": "^1.6.42",
|
||||
"blakejs": "^1.1.0"
|
||||
}
|
||||
},
|
||||
"which": {
|
||||
"version": "1.3.1",
|
||||
"resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz",
|
||||
"integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==",
|
||||
"requires": {
|
||||
"isexe": "^2.0.0"
|
||||
}
|
||||
},
|
||||
"which-module": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/which-module/-/which-module-2.0.0.tgz",
|
||||
"integrity": "sha1-2e8H3Od7mQK4o6j6SzHD4/fm6Ho="
|
||||
},
|
||||
"wrap-ansi": {
|
||||
"version": "6.2.0",
|
||||
"resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-6.2.0.tgz",
|
||||
"integrity": "sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA==",
|
||||
"requires": {
|
||||
"ansi-styles": "^4.0.0",
|
||||
"string-width": "^4.1.0",
|
||||
"strip-ansi": "^6.0.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"ansi-styles": {
|
||||
"version": "4.2.1",
|
||||
"resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.2.1.tgz",
|
||||
"integrity": "sha512-9VGjrMsG1vePxcSweQsN20KY/c4zN0h9fLjqAbwbPfahM3t+NL+M9HC8xeXG2I8pX5NoamTGNuomEUFI7fcUjA==",
|
||||
"requires": {
|
||||
"@types/color-name": "^1.1.1",
|
||||
"color-convert": "^2.0.1"
|
||||
}
|
||||
},
|
||||
"color-convert": {
|
||||
"version": "2.0.1",
|
||||
"resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz",
|
||||
"integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==",
|
||||
"requires": {
|
||||
"color-name": "~1.1.4"
|
||||
}
|
||||
},
|
||||
"color-name": {
|
||||
"version": "1.1.4",
|
||||
"resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
|
||||
"integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA=="
|
||||
}
|
||||
}
|
||||
},
|
||||
"wrappy": {
|
||||
"version": "1.0.2",
|
||||
"resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz",
|
||||
"integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8="
|
||||
},
|
||||
"y18n": {
|
||||
"version": "4.0.0",
|
||||
"resolved": "https://registry.npmjs.org/y18n/-/y18n-4.0.0.tgz",
|
||||
"integrity": "sha512-r9S/ZyXu/Xu9q1tYlpsLIsa3EeLXXk0VwlxqTcFRfg9EhMW+17kbt9G0NrgCmhGb5vT2hyhJZLfDGx+7+5Uj/w=="
|
||||
},
|
||||
"yargs": {
|
||||
"version": "15.3.1",
|
||||
"resolved": "https://registry.npmjs.org/yargs/-/yargs-15.3.1.tgz",
|
||||
"integrity": "sha512-92O1HWEjw27sBfgmXiixJWT5hRBp2eobqXicLtPBIDBhYB+1HpwZlXmbW2luivBJHBzki+7VyCLRtAkScbTBQA==",
|
||||
"requires": {
|
||||
"cliui": "^6.0.0",
|
||||
"decamelize": "^1.2.0",
|
||||
"find-up": "^4.1.0",
|
||||
"get-caller-file": "^2.0.1",
|
||||
"require-directory": "^2.1.1",
|
||||
"require-main-filename": "^2.0.0",
|
||||
"set-blocking": "^2.0.0",
|
||||
"string-width": "^4.2.0",
|
||||
"which-module": "^2.0.0",
|
||||
"y18n": "^4.0.0",
|
||||
"yargs-parser": "^18.1.1"
|
||||
}
|
||||
},
|
||||
"yargs-parser": {
|
||||
"version": "18.1.3",
|
||||
"resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-18.1.3.tgz",
|
||||
"integrity": "sha512-o50j0JeToy/4K6OZcaQmW6lyXXKhq7csREXcDwk2omFPJEwUNOVtJKvmDr9EI1fAJZUyZcRF7kxGBWmRXudrCQ==",
|
||||
"requires": {
|
||||
"camelcase": "^5.0.0",
|
||||
"decamelize": "^1.2.0"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
16
testdata/package.json
vendored
Normal file
16
testdata/package.json
vendored
Normal file
@@ -0,0 +1,16 @@
|
||||
{
|
||||
"name": "binformat",
|
||||
"version": "0.0.1",
|
||||
"description": "",
|
||||
"main": "index.js",
|
||||
"scripts": {
|
||||
"test": "echo \"Error: no test specified\" && exit 1"
|
||||
},
|
||||
"author": "",
|
||||
"license": "GPL-3.0",
|
||||
"dependencies": {
|
||||
"wasmsnark": "0.0.10",
|
||||
"circom": "^0.5.11",
|
||||
"snarkjs": "^0.1.31"
|
||||
}
|
||||
}
|
||||
@@ -1,11 +1,15 @@
|
||||
package types
|
||||
|
||||
import (
|
||||
"encoding/hex"
|
||||
"encoding/json"
|
||||
"math/big"
|
||||
|
||||
bn256 "github.com/ethereum/go-ethereum/crypto/bn256/cloudflare"
|
||||
)
|
||||
|
||||
var Q, _ = new(big.Int).SetString("21888242871839275222246405745257275088696311157297823662689037894645226208583", 10)
|
||||
|
||||
// R is the mod of the finite field
|
||||
var R, _ = new(big.Int).SetString("21888242871839275222246405745257275088548364400416034343698204186575808495617", 10)
|
||||
|
||||
@@ -16,6 +20,52 @@ type Proof struct {
|
||||
C *bn256.G1
|
||||
}
|
||||
|
||||
type proofAux struct {
|
||||
A string `json:"pi_a"`
|
||||
B string `json:"pi_b"`
|
||||
C string `json:"pi_c"`
|
||||
}
|
||||
|
||||
func (p Proof) MarshalJSON() ([]byte, error) {
|
||||
var pa proofAux
|
||||
pa.A = hex.EncodeToString(p.A.Marshal())
|
||||
pa.B = hex.EncodeToString(p.B.Marshal())
|
||||
pa.C = hex.EncodeToString(p.C.Marshal())
|
||||
return json.Marshal(pa)
|
||||
}
|
||||
|
||||
func (p *Proof) UnmarshalJSON(data []byte) error {
|
||||
var pa proofAux
|
||||
if err := json.Unmarshal(data, &pa); err != nil {
|
||||
return err
|
||||
}
|
||||
aBytes, err := hex.DecodeString(pa.A)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
p.A = new(bn256.G1)
|
||||
if _, err := p.A.Unmarshal(aBytes); err != nil {
|
||||
return err
|
||||
}
|
||||
bBytes, err := hex.DecodeString(pa.B)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
p.B = new(bn256.G2)
|
||||
if _, err := p.B.Unmarshal(bBytes); err != nil {
|
||||
return err
|
||||
}
|
||||
cBytes, err := hex.DecodeString(pa.C)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
p.C = new(bn256.G1)
|
||||
if _, err := p.C.Unmarshal(cBytes); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// Pk holds the data structure of the ProvingKey
|
||||
type Pk struct {
|
||||
A []*bn256.G1
|
||||
@@ -33,7 +83,6 @@ type Pk struct {
|
||||
DomainSize int
|
||||
PolsA []map[int]*big.Int
|
||||
PolsB []map[int]*big.Int
|
||||
PolsC []map[int]*big.Int
|
||||
}
|
||||
|
||||
// Witness contains the witness
|
||||
|
||||
@@ -17,6 +17,7 @@ type Vk struct {
|
||||
IC []*bn256.G1
|
||||
}
|
||||
|
||||
// Verify verifies the Groth16 zkSNARK proof
|
||||
func Verify(vk *types.Vk, proof *types.Proof, inputs []*big.Int) bool {
|
||||
if len(inputs)+1 != len(vk.IC) {
|
||||
fmt.Println("len(inputs)+1 != len(vk.IC)")
|
||||
|
||||
Reference in New Issue
Block a user