mirror of
https://github.com/arnaucube/go-circom-prover-verifier.git
synced 2026-02-07 11:26:44 +01:00
Compare commits
9 Commits
feature/pr
...
feature/rm
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
9f2587151f | ||
|
|
e652f34753 | ||
|
|
42961f6b94 | ||
|
|
386758370e | ||
|
|
2b8a15ca1a | ||
|
|
d1b3979eb6 | ||
|
|
de95d7a3e4 | ||
|
|
5c2aaec1ca | ||
|
|
bedd64cc70 |
4
.github/workflows/main.yml
vendored
4
.github/workflows/main.yml
vendored
@@ -23,6 +23,6 @@ jobs:
|
|||||||
- name: Compile circuits and execute Go tests
|
- name: Compile circuits and execute Go tests
|
||||||
run: |
|
run: |
|
||||||
cd testdata && sh ./compile-circuits.sh && cd ..
|
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 -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 -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/circuit5k/proving_key.json -witness=testdata/circuit5k/witness.json -proof=testdata/circuit5k/proof.json -public=testdata/circuit5k/public.json
|
||||||
go test ./...
|
go test ./...
|
||||||
|
|||||||
34
cli/cli.go
34
cli/cli.go
@@ -21,12 +21,14 @@ func main() {
|
|||||||
|
|
||||||
prove := flag.Bool("prove", false, "prover mode")
|
prove := flag.Bool("prove", false, "prover mode")
|
||||||
verify := flag.Bool("verify", false, "verifier 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")
|
witnessPath := flag.String("witness", "witness.json", "witness path")
|
||||||
proofPath := flag.String("proof", "proof.json", "proof 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")
|
publicPath := flag.String("public", "public.json", "public signals path")
|
||||||
|
provingKeyBinPath := flag.String("pkbin", "proving_key.go.bin", "provingKey Bin path")
|
||||||
|
|
||||||
flag.Parse()
|
flag.Parse()
|
||||||
|
|
||||||
@@ -42,6 +44,12 @@ func main() {
|
|||||||
fmt.Println("Error:", err)
|
fmt.Println("Error:", err)
|
||||||
}
|
}
|
||||||
os.Exit(0)
|
os.Exit(0)
|
||||||
|
} else if *convert {
|
||||||
|
err := cmdConvert(*provingKeyPath, *provingKeyBinPath)
|
||||||
|
if err != nil {
|
||||||
|
fmt.Println("Error:", err)
|
||||||
|
}
|
||||||
|
os.Exit(0)
|
||||||
}
|
}
|
||||||
flag.PrintDefaults()
|
flag.PrintDefaults()
|
||||||
}
|
}
|
||||||
@@ -133,3 +141,25 @@ func cmdVerify(proofPath, verificationKeyPath, publicPath string) error {
|
|||||||
fmt.Println("verification:", v)
|
fmt.Println("verification:", v)
|
||||||
return nil
|
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
|
||||||
|
}
|
||||||
|
err = ioutil.WriteFile(provingKeyBinPath, pkGBin, 0644)
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ package parsers
|
|||||||
import (
|
import (
|
||||||
"bufio"
|
"bufio"
|
||||||
"bytes"
|
"bytes"
|
||||||
|
"encoding/binary"
|
||||||
"encoding/hex"
|
"encoding/hex"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"fmt"
|
"fmt"
|
||||||
@@ -33,7 +34,6 @@ type PkString struct {
|
|||||||
DomainSize int `json:"domainSize"`
|
DomainSize int `json:"domainSize"`
|
||||||
PolsA []map[string]string `json:"polsA"`
|
PolsA []map[string]string `json:"polsA"`
|
||||||
PolsB []map[string]string `json:"polsB"`
|
PolsB []map[string]string `json:"polsB"`
|
||||||
PolsC []map[string]string `json:"polsC"`
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// WitnessString contains the Witness in string representation
|
// WitnessString contains the Witness in string representation
|
||||||
@@ -148,10 +148,6 @@ func pkStringToPk(ps PkString) (*types.Pk, error) {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
p.PolsC, err = polsStringToBigInt(ps.PolsC)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
return &p, nil
|
return &p, nil
|
||||||
}
|
}
|
||||||
@@ -308,6 +304,13 @@ func stringToBigInt(s string) (*big.Int, error) {
|
|||||||
return n, nil
|
return n, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func addPadding32(b []byte) []byte {
|
||||||
|
if len(b) != 32 {
|
||||||
|
b = addZPadding(b)
|
||||||
|
}
|
||||||
|
return b
|
||||||
|
}
|
||||||
|
|
||||||
func addZPadding(b []byte) []byte {
|
func addZPadding(b []byte) []byte {
|
||||||
var z [32]byte
|
var z [32]byte
|
||||||
var r []byte
|
var r []byte
|
||||||
@@ -599,3 +602,715 @@ func swapEndianness(b []byte) []byte {
|
|||||||
}
|
}
|
||||||
return o
|
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
|
||||||
|
}
|
||||||
|
pk.C = append(pk.C, z) // circom behaviour (3x null==["0", "0", "0"])
|
||||||
|
pk.C = append(pk.C, z)
|
||||||
|
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,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
// 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, v := range pk.PolsA[i] {
|
||||||
|
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, v := range pk.PolsB[i] {
|
||||||
|
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
|
||||||
|
}
|
||||||
|
pk.C = append(pk.C, z)
|
||||||
|
pk.C = append(pk.C, z)
|
||||||
|
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
|
||||||
|
}
|
||||||
|
|||||||
@@ -211,3 +211,115 @@ func TestProofJSON(t *testing.T) {
|
|||||||
require.Nil(t, err)
|
require.Nil(t, err)
|
||||||
require.Equal(t, *proof, proof1)
|
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
|
||||||
|
}
|
||||||
|
|
||||||
|
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)
|
||||||
|
}
|
||||||
|
|
||||||
|
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")
|
||||||
|
}
|
||||||
|
|||||||
@@ -13,36 +13,6 @@ import (
|
|||||||
//"fmt"
|
//"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
|
// Group Size
|
||||||
const (
|
const (
|
||||||
GSIZE = 6
|
GSIZE = 6
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ import (
|
|||||||
"encoding/json"
|
"encoding/json"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
|
"os"
|
||||||
"testing"
|
"testing"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
@@ -16,25 +17,45 @@ import (
|
|||||||
func TestCircuitsGenerateProof(t *testing.T) {
|
func TestCircuitsGenerateProof(t *testing.T) {
|
||||||
testCircuitGenerateProof(t, "circuit1k") // 1000 constraints
|
testCircuitGenerateProof(t, "circuit1k") // 1000 constraints
|
||||||
testCircuitGenerateProof(t, "circuit5k") // 5000 constraints
|
testCircuitGenerateProof(t, "circuit5k") // 5000 constraints
|
||||||
//testCircuitGenerateProof(t, "circuit10k") // 10000 constraints
|
// testCircuitGenerateProof(t, "circuit10k") // 10000 constraints
|
||||||
//testCircuitGenerateProof(t, "circuit20k") // 20000 constraints
|
// testCircuitGenerateProof(t, "circuit20k") // 20000 constraints
|
||||||
}
|
}
|
||||||
|
|
||||||
func testCircuitGenerateProof(t *testing.T, circuit string) {
|
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)
|
require.Nil(t, err)
|
||||||
pk, err := parsers.ParsePk(provingKeyJson)
|
defer pkGoBinFile.Close()
|
||||||
|
pk, err := parsers.ParsePkGoBin(pkGoBinFile)
|
||||||
require.Nil(t, err)
|
require.Nil(t, err)
|
||||||
|
|
||||||
witnessJson, err := ioutil.ReadFile("../testdata/" + circuit + "/witness.json")
|
witnessBinFile, err := os.Open("../testdata/" + circuit + "/witness.bin")
|
||||||
require.Nil(t, err)
|
require.Nil(t, err)
|
||||||
w, err := parsers.ParseWitness(witnessJson)
|
defer witnessBinFile.Close()
|
||||||
|
w, err := parsers.ParseWitnessBin(witnessBinFile)
|
||||||
require.Nil(t, err)
|
require.Nil(t, err)
|
||||||
|
|
||||||
beforeT := time.Now()
|
beforeT := time.Now()
|
||||||
proof, pubSignals, err := GenerateProof(pk, w)
|
proof, pubSignals, err := GenerateProof(pk, w)
|
||||||
assert.Nil(t, err)
|
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)
|
proofStr, err := parsers.ProofToJson(proof)
|
||||||
assert.Nil(t, err)
|
assert.Nil(t, err)
|
||||||
|
|||||||
1
testdata/clean-gereated-files.sh
vendored
1
testdata/clean-gereated-files.sh
vendored
@@ -7,3 +7,4 @@ rm */*.cpp
|
|||||||
rm */*.sym
|
rm */*.sym
|
||||||
rm */*.r1cs
|
rm */*.r1cs
|
||||||
rm */*.sol
|
rm */*.sol
|
||||||
|
rm */*.bin
|
||||||
|
|||||||
12
testdata/compile-circuits.sh
vendored
12
testdata/compile-circuits.sh
vendored
@@ -45,19 +45,23 @@ compile_and_ts_and_witness
|
|||||||
|
|
||||||
cd ../
|
cd ../
|
||||||
|
|
||||||
echo "convert witness & pk of circuit1k to bin"
|
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/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
|
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"
|
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/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
|
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"
|
# 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/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
|
# 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"
|
# 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/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
|
# 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
|
||||||
|
|
||||||
|
|||||||
@@ -8,6 +8,8 @@ import (
|
|||||||
bn256 "github.com/ethereum/go-ethereum/crypto/bn256/cloudflare"
|
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
|
// R is the mod of the finite field
|
||||||
var R, _ = new(big.Int).SetString("21888242871839275222246405745257275088548364400416034343698204186575808495617", 10)
|
var R, _ = new(big.Int).SetString("21888242871839275222246405745257275088548364400416034343698204186575808495617", 10)
|
||||||
|
|
||||||
@@ -81,7 +83,6 @@ type Pk struct {
|
|||||||
DomainSize int
|
DomainSize int
|
||||||
PolsA []map[int]*big.Int
|
PolsA []map[int]*big.Int
|
||||||
PolsB []map[int]*big.Int
|
PolsB []map[int]*big.Int
|
||||||
PolsC []map[int]*big.Int
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Witness contains the witness
|
// Witness contains the witness
|
||||||
|
|||||||
Reference in New Issue
Block a user