11 Commits

Author SHA1 Message Date
arnaucube
478006134d Archive repository 2021-06-13 18:54:21 +02:00
arnaucube
aec3022978 Update README.md 2020-04-14 18:20:19 +02:00
arnau
2461f86bda Merge pull request #14 from KimiWu123/master
follow whitespace rule of strings.TrimSpace
2019-10-31 11:39:20 +01:00
kimiwu123
3308c3d94e follow whitespace rule of strings.TrimSpace 2019-10-31 15:18:01 +08:00
2cbba4e007 add verify proof generated from snarkjs 2019-07-30 22:28:42 +02:00
arnaucube
469eabd451 split trustedsetup in Pk & Vk for proof generation & verification smaller inputs 2019-07-28 12:56:13 +02:00
arnaucube
41f7a3518a remove circuit parameter from proof Verification 2019-07-27 18:11:28 +02:00
arnaucube
e98a97e9fe add wasm for Groth16 proof generation & verification 2019-07-10 21:06:02 +02:00
arnaucube
417cc92a97 add wasm snark proof verification function (Pinocchio) 2019-06-24 21:02:42 +02:00
arnaucube
0a162482ee wasm proof generation from browser working. Added cli wasm exporters, html&js browser example, wasm wrapper from go 2019-06-24 20:54:22 +02:00
arnaucube
662d92b697 add wasm utils: bigint-string parsers 2019-06-24 12:32:40 +02:00
43 changed files with 2287 additions and 186 deletions

View File

@@ -5,3 +5,6 @@ go:
env:
- GO111MODULE=on
before_install: rm wasm/go-snark-wasm-wrapper.go

View File

@@ -1,17 +1,17 @@
# go-snark [![Go Report Card](https://goreportcard.com/badge/github.com/arnaucube/go-snark)](https://goreportcard.com/report/github.com/arnaucube/go-snark) [![Build Status](https://travis-ci.org/arnaucube/go-snark.svg?branch=master)](https://travis-ci.org/arnaucube/go-snark) [![Gitter](https://badges.gitter.im/go-snark/community.svg)](https://gitter.im/go-snark/community?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge)
### Warning
Implementation of the zkSNARK [Pinocchio protocol](https://eprint.iacr.org/2013/279.pdf) and [Groth16 protocol](https://eprint.iacr.org/2016/260.pdf) from scratch in Go done in my free time to understand the concepts. Do not use in production.
If you want to generate proofs & verify them from Go, you can try https://github.com/vocdoni/go-snark, which is implemented using the [bn256](https://github.com/ethereum/go-ethereum/tree/master/crypto/bn256/cloudflare) for the Pairing curve operations for the Groth16 zkSNARK, and it is compatible with [circom](https://github.com/iden3/circom).
# go-snark-study [![Go Report Card](https://goreportcard.com/badge/github.com/arnaucube/go-snark-study)](https://goreportcard.com/report/github.com/arnaucube/go-snark-study) [![GoDoc](https://godoc.org/github.com/arnaucube/go-snark-study?status.svg)](https://godoc.org/github.com/arnaucube/go-snark-study)
zkSNARK library implementation in Go
- `Succinct Non-Interactive Zero Knowledge for a von Neumann Architecture`, Eli Ben-Sasson, Alessandro Chiesa, Eran Tromer, Madars Virza https://eprint.iacr.org/2013/879.pdf
- `Pinocchio: Nearly practical verifiable computation`, Bryan Parno, Craig Gentry, Jon Howell, Mariana Raykova https://eprint.iacr.org/2013/279.pdf
- `On the Size of Pairing-based Non-interactive Arguments`, Jens Groth https://eprint.iacr.org/2016/260.pdf
## Caution & Warning
Implementation of the zkSNARK [Pinocchio protocol](https://eprint.iacr.org/2013/279.pdf) and [Groth16 protocol](https://eprint.iacr.org/2016/260.pdf) from scratch in Go to understand the concepts. Do not use in production.
Not finished, implementing this in my free time to understand it better, so I don't have much time.
## Features
Currently allows to do the complete path with [Pinocchio protocol](https://eprint.iacr.org/2013/279.pdf) and [Groth16 protocol](https://eprint.iacr.org/2016/260.pdf) :
0. write circuit
@@ -33,22 +33,16 @@ Minimal complete flow implementation:
- [x] generate proofs
- [x] verify proofs with BN128 pairing
Improvements from the minimal implementation:
- [x] allow to call functions in circuits language
- [x] allow `import` in circuits language
- [ ] allow `for` in circuits language
- [ ] move witness values calculation outside the setup phase
- [x] Groth16
- [ ] multiple optimizations
## WASM usage
Experimentation with go-snark-study compiled to wasm: https://github.com/arnaucube/go-snark-study/tree/master/wasm
## Usage
- [![GoDoc](https://godoc.org/github.com/arnaucube/go-snark?status.svg)](https://godoc.org/github.com/arnaucube/go-snark) zkSnark
- [![GoDoc](https://godoc.org/github.com/arnaucube/go-snark/groth16?status.svg)](https://godoc.org/github.com/arnaucube/go-snark/groth16) zkSnark Groth16
- [![GoDoc](https://godoc.org/github.com/arnaucube/go-snark/bn128?status.svg)](https://godoc.org/github.com/arnaucube/go-snark/bn128) bn128 (more details: https://github.com/arnaucube/go-snark/tree/master/bn128)
- [![GoDoc](https://godoc.org/github.com/arnaucube/go-snark/fields?status.svg)](https://godoc.org/github.com/arnaucube/go-snark/fields) Finite Fields operations
- [![GoDoc](https://godoc.org/github.com/arnaucube/go-snark/r1csqap?status.svg)](https://godoc.org/github.com/arnaucube/go-snark/r1csqap) R1CS to QAP (more details: https://github.com/arnaucube/go-snark/tree/master/r1csqap)
- [![GoDoc](https://godoc.org/github.com/arnaucube/go-snark/circuitcompiler?status.svg)](https://godoc.org/github.com/arnaucube/go-snark/circuitcompiler) Circuit Compiler
- [![GoDoc](https://godoc.org/github.com/arnaucube/go-snark-study?status.svg)](https://godoc.org/github.com/arnaucube/go-snark-study) zkSnark
- [![GoDoc](https://godoc.org/github.com/arnaucube/go-snark-study/groth16?status.svg)](https://godoc.org/github.com/arnaucube/go-snark-study/groth16) zkSnark Groth16
- [![GoDoc](https://godoc.org/github.com/arnaucube/go-snark-study/bn128?status.svg)](https://godoc.org/github.com/arnaucube/go-snark-study/bn128) bn128 (more details: https://github.com/arnaucube/go-snark-study/tree/master/bn128)
- [![GoDoc](https://godoc.org/github.com/arnaucube/go-snark-study/fields?status.svg)](https://godoc.org/github.com/arnaucube/go-snark-study/fields) Finite Fields operations
- [![GoDoc](https://godoc.org/github.com/arnaucube/go-snark-study/r1csqap?status.svg)](https://godoc.org/github.com/arnaucube/go-snark-study/r1csqap) R1CS to QAP (more details: https://github.com/arnaucube/go-snark-study/tree/master/r1csqap)
- [![GoDoc](https://godoc.org/github.com/arnaucube/go-snark-study/circuitcompiler?status.svg)](https://godoc.org/github.com/arnaucube/go-snark-study/circuitcompiler) Circuit Compiler
### CLI usage
*The cli still needs some improvements, such as seting input files, etc.*
@@ -87,6 +81,10 @@ In the command line, execute:
```
> ./go-snark-cli compile test.circuit
```
If you want to have the wasm input ready also, add the flag `wasm`
```
> ./go-snark-cli compile test.circuit wasm
```
This will output the `compiledcircuit.json` file.
@@ -97,6 +95,10 @@ Having the `compiledcircuit.json`, now we can generate the `TrustedSetup`:
```
This will create the file `trustedsetup.json` with the TrustedSetup data, and also a `toxic.json` file, with the parameters to delete from the `Trusted Setup`.
If you want to have the wasm input ready also, add the flag `wasm`
```
> ./go-snark-cli trustedsetup wasm
```
#### Generate Proofs
Assumming that we have the `compiledcircuit.json`, `trustedsetup.json`, `privateInputs.json` and the `publicInputs.json` we can now generate the `Proofs` with the following command:
@@ -192,6 +194,16 @@ publicSignalsVerif := []*big.Int{b35Verif}
assert.True(t, VerifyProof(*circuit, setup, proof, publicSignalsVerif, true))
```
##### Verify Proof generated from [snarkjs](https://github.com/iden3/snarkjs)
Is possible with `go-snark-study` to verify proofs generated by `snarkjs`
Example:
```go
verified, err := VerifyFromCircom("circom-test/verification_key.json", "circom-test/proof.json", "circom-test/public.json")
assert.Nil(t, err)
assert.True(t, verified)
```
## Versions
History of versions & tags of this project:
@@ -205,7 +217,7 @@ go test ./... -v
```
## vim/nvim circuit syntax highlighter
For more details and installation instructions see https://github.com/arnaucube/go-snark/tree/master/vim-syntax
For more details and installation instructions see https://github.com/arnaucube/go-snark-study/tree/master/vim-syntax
---

View File

@@ -1,5 +1,5 @@
## Bn128
[![GoDoc](https://godoc.org/github.com/arnaucube/go-snark/bn128?status.svg)](https://godoc.org/github.com/arnaucube/go-snark/bn128) bn128
[![GoDoc](https://godoc.org/github.com/arnaucube/go-snark-study/bn128?status.svg)](https://godoc.org/github.com/arnaucube/go-snark-study/bn128) bn128
Implementation of the bn128 pairing in Go.

View File

@@ -4,7 +4,7 @@ import (
"errors"
"math/big"
"github.com/arnaucube/go-snark/fields"
"github.com/arnaucube/go-snark-study/fields"
)
// Bn128 is the data structure of the BN128

View File

@@ -3,7 +3,7 @@ package bn128
import (
"math/big"
"github.com/arnaucube/go-snark/fields"
"github.com/arnaucube/go-snark-study/fields"
)
type G1 struct {

View File

@@ -3,7 +3,7 @@ package bn128
import (
"math/big"
"github.com/arnaucube/go-snark/fields"
"github.com/arnaucube/go-snark-study/fields"
)
type G2 struct {

View File

@@ -5,7 +5,7 @@ import (
"math/big"
"strconv"
"github.com/arnaucube/go-snark/r1csqap"
"github.com/arnaucube/go-snark-study/r1csqap"
)
// Circuit is the data structure of the compiled circuit

View File

@@ -32,7 +32,7 @@ const (
var eof = rune(0)
func isWhitespace(ch rune) bool {
return ch == ' ' || ch == '\t' || ch == '\n'
return ch == ' ' || ch == '\t' || ch == '\n' || ch == '\r' || ch == '\v' || ch == '\f'
}
func isLetter(ch rune) bool {

View File

@@ -1,4 +1,4 @@
func test(private a, private b, public c):
func main(private a, private b, public c):
d = a * b
equals(c, d)
out = 1 * 1

View File

@@ -1,4 +1,4 @@
func test(private s0, public s1):
func main(private s0, public s1):
s2 = s0 * s0
s3 = s2 * s0
s4 = s3 + s0

View File

@@ -11,10 +11,11 @@ import (
"math/big"
"os"
snark "github.com/arnaucube/go-snark"
"github.com/arnaucube/go-snark/circuitcompiler"
"github.com/arnaucube/go-snark/groth16"
"github.com/arnaucube/go-snark/r1csqap"
snark "github.com/arnaucube/go-snark-study"
"github.com/arnaucube/go-snark-study/circuitcompiler"
"github.com/arnaucube/go-snark-study/groth16"
"github.com/arnaucube/go-snark-study/r1csqap"
"github.com/arnaucube/go-snark-study/utils"
"github.com/urfave/cli"
)
@@ -96,6 +97,11 @@ func CompileCircuit(context *cli.Context) error {
circuitPath := context.Args().Get(0)
wasmFlag := false
if context.Args().Get(1) == "wasm" {
wasmFlag = true
}
// read circuit file
circuitFile, err := os.Open(circuitPath)
panicErr(err)
@@ -185,10 +191,48 @@ func CompileCircuit(context *cli.Context) error {
jsonFile.Close()
fmt.Println("Compiled Circuit data written to ", jsonFile.Name())
if wasmFlag {
circuitString := utils.CircuitToString(*circuit)
jsonData, err := json.Marshal(circuitString)
panicErr(err)
// store setup into file
jsonFile, err := os.Create("compiledcircuitString.json")
panicErr(err)
defer jsonFile.Close()
jsonFile.Write(jsonData)
jsonFile.Close()
}
// store px
jsonData, err = json.Marshal(px)
panicErr(err)
// store setup into file
jsonFile, err = os.Create("px.json")
panicErr(err)
defer jsonFile.Close()
jsonFile.Write(jsonData)
jsonFile.Close()
fmt.Println("Px data written to ", jsonFile.Name())
if wasmFlag {
pxString := utils.ArrayBigIntToString(px)
jsonData, err = json.Marshal(pxString)
panicErr(err)
// store setup into file
jsonFile, err = os.Create("pxString.json")
panicErr(err)
defer jsonFile.Close()
jsonFile.Write(jsonData)
jsonFile.Close()
}
return nil
}
func TrustedSetup(context *cli.Context) error {
wasmFlag := false
if context.Args().Get(0) == "wasm" {
wasmFlag = true
}
// open compiledcircuit.json
compiledcircuitFile, err := ioutil.ReadFile("compiledcircuit.json")
panicErr(err)
@@ -230,8 +274,7 @@ func TrustedSetup(context *cli.Context) error {
var tsetup snark.Setup
tsetup.Pk = setup.Pk
tsetup.Vk = setup.Vk
tsetup.G1T = setup.G1T
tsetup.G2T = setup.G2T
tsetup.Pk.G1T = setup.Pk.G1T
// store setup to json
jsonData, err := json.Marshal(tsetup)
@@ -243,6 +286,17 @@ func TrustedSetup(context *cli.Context) error {
jsonFile.Write(jsonData)
jsonFile.Close()
fmt.Println("Trusted Setup data written to ", jsonFile.Name())
if wasmFlag {
tsetupString := utils.SetupToString(tsetup)
jsonData, err := json.Marshal(tsetupString)
panicErr(err)
// store setup into file
jsonFile, err := os.Create("trustedsetupString.json")
panicErr(err)
defer jsonFile.Close()
jsonFile.Write(jsonData)
jsonFile.Close()
}
return nil
}
@@ -289,10 +343,10 @@ func GenerateProofs(context *cli.Context) error {
hx := snark.Utils.PF.DivisorPolynomial(px, trustedsetup.Pk.Z)
fmt.Println(circuit)
fmt.Println(trustedsetup.G1T)
fmt.Println(trustedsetup.Pk.G1T)
fmt.Println(hx)
fmt.Println(w)
proof, err := snark.GenerateProofs(circuit, trustedsetup, w, px)
proof, err := snark.GenerateProofs(circuit, trustedsetup.Pk, w, px)
panicErr(err)
fmt.Println("\n proofs:")
@@ -319,13 +373,6 @@ func VerifyProofs(context *cli.Context) error {
json.Unmarshal([]byte(string(proofsFile)), &proof)
panicErr(err)
// open compiledcircuit.json
compiledcircuitFile, err := ioutil.ReadFile("compiledcircuit.json")
panicErr(err)
var circuit circuitcompiler.Circuit
json.Unmarshal([]byte(string(compiledcircuitFile)), &circuit)
panicErr(err)
// open trustedsetup.json
trustedsetupFile, err := ioutil.ReadFile("trustedsetup.json")
panicErr(err)
@@ -340,7 +387,7 @@ func VerifyProofs(context *cli.Context) error {
err = json.Unmarshal([]byte(string(publicInputsFile)), &publicSignals)
panicErr(err)
verified := snark.VerifyProof(circuit, trustedsetup, proof, publicSignals, true)
verified := snark.VerifyProof(trustedsetup.Vk, proof, publicSignals, true)
if !verified {
fmt.Println("ERROR: proofs not verified")
} else {
@@ -451,7 +498,7 @@ func Groth16GenerateProofs(context *cli.Context) error {
fmt.Println(trustedsetup.Pk.PowersTauDelta)
fmt.Println(hx)
fmt.Println(w)
proof, err := groth16.GenerateProofs(circuit, trustedsetup, w, px)
proof, err := groth16.GenerateProofs(circuit, trustedsetup.Pk, w, px)
panicErr(err)
fmt.Println("\n proofs:")
@@ -478,13 +525,6 @@ func Groth16VerifyProofs(context *cli.Context) error {
json.Unmarshal([]byte(string(proofsFile)), &proof)
panicErr(err)
// open compiledcircuit.json
compiledcircuitFile, err := ioutil.ReadFile("compiledcircuit.json")
panicErr(err)
var circuit circuitcompiler.Circuit
json.Unmarshal([]byte(string(compiledcircuitFile)), &circuit)
panicErr(err)
// open trustedsetup.json
trustedsetupFile, err := ioutil.ReadFile("trustedsetup.json")
panicErr(err)
@@ -499,7 +539,7 @@ func Groth16VerifyProofs(context *cli.Context) error {
err = json.Unmarshal([]byte(string(publicInputsFile)), &publicSignals)
panicErr(err)
verified := groth16.VerifyProof(circuit, trustedsetup, proof, publicSignals, true)
verified := groth16.VerifyProof(trustedsetup.Vk, proof, publicSignals, true)
if !verified {
fmt.Println("ERROR: proofs not verified")
} else {

12
externalVerif/README.md Normal file
View File

@@ -0,0 +1,12 @@
# go-snark-study /externalVerif
Utilities to verify zkSNARK proofs generated by other tools.
## Verify Proof generated from [snarkjs](https://github.com/iden3/snarkjs)
Is possible with `go-snark-study` to verify proofs generated by `snarkjs`
Example:
```go
verified, err := VerifyFromCircom("circom-test/verification_key.json", "circom-test/proof.json", "circom-test/public.json")
assert.Nil(t, err)
assert.True(t, verified)
```

View File

@@ -0,0 +1,8 @@
template Multiplier() {
signal private input a;
signal private input b;
signal output c;
c <== a*b;
}
component main = Multiplier();

View File

@@ -0,0 +1,74 @@
{
"mainCode": "{\n}\n",
"signalName2Idx": {
"one": 0,
"main.a": 2,
"main.b": 3,
"main.c": 1
},
"components": [
{
"name": "main",
"params": {},
"template": "Multiplier",
"inputSignals": 2
}
],
"componentName2Idx": {
"main": 0
},
"signals": [
{
"names": [
"one"
],
"triggerComponents": []
},
{
"names": [
"main.c"
],
"triggerComponents": []
},
{
"names": [
"main.a"
],
"triggerComponents": [
0
]
},
{
"names": [
"main.b"
],
"triggerComponents": [
0
]
}
],
"constraints": [
[
{
"2": "21888242871839275222246405745257275088548364400416034343698204186575808495616"
},
{
"3": "1"
},
{
"1": "21888242871839275222246405745257275088548364400416034343698204186575808495616"
}
]
],
"templates": {
"Multiplier": "function(ctx) {\n ctx.setSignal(\"c\", [], bigInt(ctx.getSignal(\"a\", [])).mul(bigInt(ctx.getSignal(\"b\", []))).mod(__P__));\n ctx.assert(ctx.getSignal(\"c\", []), bigInt(ctx.getSignal(\"a\", [])).mul(bigInt(ctx.getSignal(\"b\", []))).mod(__P__));\n}\n"
},
"functions": {},
"nPrvInputs": 2,
"nPubInputs": 0,
"nInputs": 2,
"nOutputs": 1,
"nVars": 4,
"nConstants": 0,
"nSignals": 4
}

View File

@@ -0,0 +1 @@
{"a": 3, "b": 11}

View File

@@ -0,0 +1,27 @@
{
"pi_a": [
"18388960469390566286541775203573681018272060202314500468244373257908579233056",
"7618815753031896296145768956584956596571516464117106968297323458939823682730",
"1"
],
"pi_b": [
[
"17050824088966017765399151386329118398626450147519924253020767437783796544260",
"19912572158122217836152914282050675315049542075120224143747749799495268338155"
],
[
"20465264120227255663865054937863503553147947378051666554617444700075602812731",
"18655251778322805691388473632530173510779859979743695956359151230786651584957"
],
[
"1",
"0"
]
],
"pi_c": [
"1422784641124790360586256228365363101120672643204565045434023905594849706813",
"8557716062509065082036904136615813135951258906799509331823365499907603810450",
"1"
],
"protocol": "groth"
}

View File

@@ -0,0 +1,221 @@
{
"protocol": "groth",
"nVars": 4,
"nPublic": 1,
"domainBits": 2,
"domainSize": 4,
"polsA": [
{
"1": "1"
},
{
"2": "1"
},
{
"0": "21888242871839275222246405745257275088548364400416034343698204186575808495616"
},
{}
],
"polsB": [
{},
{},
{},
{
"0": "1"
}
],
"polsC": [
{},
{
"0": "21888242871839275222246405745257275088548364400416034343698204186575808495616"
},
{},
{}
],
"A": [
[
"16145916318196730299582072104388453231952213805668281741813587224450782397538",
"4434505318477484327659527264104806919103674231447634885054368605283938696207",
"1"
],
[
"10618406967550056457559358662746625591602641004174976323307214433994084907915",
"1843236360452735081347085412539192450068665510574800388201121698908391533923",
"1"
],
[
"1208972877970123411566574123860641832032384890981476033353526096830198333194",
"777503551507025252294438107100944741641946695980350712141258191590862204805",
"1"
],
[
"0",
"1",
"0"
]
],
"B1": [
[
"0",
"1",
"0"
],
[
"0",
"1",
"0"
],
[
"0",
"1",
"0"
],
[
"1208972877970123411566574123860641832032384890981476033353526096830198333194",
"21110739320332249969951967638156330347054364461317472950547779703054364003778",
"1"
]
],
"B2": [
[
[
"0",
"0"
],
[
"1",
"0"
],
[
"0",
"0"
]
],
[
[
"0",
"0"
],
[
"1",
"0"
],
[
"0",
"0"
]
],
[
[
"0",
"0"
],
[
"1",
"0"
],
[
"0",
"0"
]
],
[
[
"9283666785342556550467669770956850930982548182701254051508520248901282197973",
"11369378229277445316894458966429873744779877313900506577160370623273013178252"
],
[
"10625777544326349817513295021482494426101347915428005055375725845993157551870",
"21401790227434807639472120486932615400751346915707967674912972446672152512583"
],
[
"1",
"0"
]
]
],
"C": [
null,
null,
[
"18545397130363256321926549041639729743141431075318462370025152832852939073307",
"2616861286119881509516846668252666108741377487742351180864484963773522850295",
"1"
],
[
"2525636894222523143142808451978966577881491159416335121257094078801746645235",
"16535861715720884910945782094658684127457731006848459401043529763859412916301",
"1"
]
],
"vk_alfa_1": [
"16068200068882411629410035093795608526771554471937479213726134794660780102550",
"20501676791339890155108177259376873296876233680064261776170683533526889207340",
"1"
],
"vk_beta_1": [
"5365573823291502335794132193185274277974617763863996013954364593194136465016",
"11644349101388223784378896360832586557929271772024496470708905460439243894584",
"1"
],
"vk_delta_1": [
"15680151079584844532489259722917096938769907841931133291928746685613811358733",
"16784279394546603697881462850128771845781623009095957214568117820968443242506",
"1"
],
"vk_beta_2": [
[
"13973091636763944887728510851169742544309374663995476311690518173988838518856",
"12903946180439304546475897520537621821375470264150438270817301786763517825250"
],
[
"370374369234123593044872519351942112043402224488849374153134091815693350697",
"17423079115073430837335625309232513526393852743032331213038909731579295753224"
],
[
"1",
"0"
]
],
"vk_delta_2": [
[
"1192908377564945353343974763532707545526009748811618581810344379529229172159",
"10373868200341234689659697947697825014338252335089936445608341428888724327154"
],
[
"6258644116885726740914814071115026921733331135830050167672544002787860516536",
"2784479362505735918824286514153638713518597314121639212447411360814573899319"
],
[
"1",
"0"
]
],
"hExps": [
[
"1137454402546542017796495169973321459788661791339116580816039119135416491226",
"10581992627412174102808274058339351114019966039682644500297077873241797449624",
"1"
],
[
"3253811140290017934039655168718326971539049766532829948316663892796117200680",
"3496418280903365070403555364992889823060908616232765866481366503085657668823",
"1"
],
[
"7426424892372059053157891943364774187577620238460342150964457392480230669997",
"14261604113665464620229095737623968407326243628348811684313201927885047569756",
"1"
],
[
"14706800931196014592083141709960980909656368788497354451613143286705158867076",
"8321358240716309588423491516494287064322707776658072083979021495463106099808",
"1"
],
[
"21560594640856118286219580794351895174554979903538723611152363886530011848778",
"15512645592267656573910252616175869133748229079507420222439452334013754939136",
"1"
]
]
}

View File

@@ -0,0 +1,3 @@
[
"33"
]

View File

@@ -0,0 +1,93 @@
{
"protocol": "groth",
"nPublic": 1,
"IC": [
[
"13238385840837109667936052879696151554096578146827286302729161004449442572510",
"7229895880483697230987627368481585486229758623816305076929725978466335833042",
"1"
],
[
"14970768730171390202518134018231251321095352434740566553215758534237407624223",
"11858341424183782282346697815973277820477089967861765360499368718702428507405",
"1"
]
],
"vk_alfa_1": [
"16068200068882411629410035093795608526771554471937479213726134794660780102550",
"20501676791339890155108177259376873296876233680064261776170683533526889207340",
"1"
],
"vk_beta_2": [
[
"13973091636763944887728510851169742544309374663995476311690518173988838518856",
"12903946180439304546475897520537621821375470264150438270817301786763517825250"
],
[
"370374369234123593044872519351942112043402224488849374153134091815693350697",
"17423079115073430837335625309232513526393852743032331213038909731579295753224"
],
[
"1",
"0"
]
],
"vk_gamma_2": [
[
"20123714298473938437207866646336289719062614610167653880378271328974655580609",
"13002533616763316572747276872341370962409012236118399865958073576789163874362"
],
[
"9275552728819724842865155645402980221399400114914205138826048710506018574007",
"9767402488181356088371101345613657976874749415205606884811092820466492903357"
],
[
"1",
"0"
]
],
"vk_delta_2": [
[
"1192908377564945353343974763532707545526009748811618581810344379529229172159",
"10373868200341234689659697947697825014338252335089936445608341428888724327154"
],
[
"6258644116885726740914814071115026921733331135830050167672544002787860516536",
"2784479362505735918824286514153638713518597314121639212447411360814573899319"
],
[
"1",
"0"
]
],
"vk_alfabeta_12": [
[
[
"5808968930823264229923553886264093087733079723496081749582815497064726636649",
"15704206953123342065158329174314435955575427797267883688615695147218681260603"
],
[
"2019376182570496317125733151845779676488434395598091282285101061771413397585",
"5033120379874305142732026662367866621873812132639805141544817513451132976303"
],
[
"6413062281604814018100947958938305639421600365853645030429871508055751771332",
"16501101898595852943280641675936242756163761586970222679114350546638012990295"
]
],
[
[
"7994355756858823685828118366797930607512610071147093396079158087328554257367",
"12608941378902474737301318807093065779176013217938745808277102463837219428790"
],
[
"7722352178656099663978033703115542396108273285932660670008724291332590018773",
"18402524427751774707431639562944919677540025075739837574780127622149131456184"
],
[
"8237540863924877742345165686185155147152873047203223764861378545202201950314",
"885942718772685438966081900822373900701293300627890502324305030525329921651"
]
]
]
}

View File

@@ -0,0 +1,6 @@
[
"1",
"33",
"3",
"11"
]

View File

@@ -0,0 +1,90 @@
package externalVerif
import (
"encoding/json"
"fmt"
"io/ioutil"
"github.com/arnaucube/go-snark-study/groth16"
"github.com/arnaucube/go-snark-study/utils"
)
type CircomProof struct {
PiA [3]string `json:"pi_a"`
PiB [3][2]string `json:"pi_b"`
PiC [3]string `json:"pi_c"`
}
type CircomVk struct {
IC [][3]string `json:"IC"`
Alpha1 [3]string `json:"vk_alfa_1"`
Beta2 [3][2]string `json:"vk_beta_2"`
Gamma2 [3][2]string `json:"vk_gamma_2"`
Delta2 [3][2]string `json:"vk_delta_2"`
AlphaBeta12 [2][3][2]string `json:"vk_alpfabeta_12"` // not really used, for the moment in go-snarks calculed in verification time
}
func VerifyFromCircom(vkPath, proofPath, publicSignalsPath string) (bool, error) {
// open verification_key.json
vkFile, err := ioutil.ReadFile(vkPath)
if err != nil {
return false, err
}
var circomVk CircomVk
json.Unmarshal([]byte(string(vkFile)), &circomVk)
if err != nil {
return false, err
}
var strVk utils.GrothVkString
strVk.IC = circomVk.IC
strVk.G1.Alpha = circomVk.Alpha1
strVk.G2.Beta = circomVk.Beta2
strVk.G2.Gamma = circomVk.Gamma2
strVk.G2.Delta = circomVk.Delta2
vk, err := utils.GrothVkFromString(strVk)
if err != nil {
return false, err
}
fmt.Println("vk parsed:", vk)
// open proof.json
proofsFile, err := ioutil.ReadFile(proofPath)
if err != nil {
return false, err
}
var circomProof CircomProof
json.Unmarshal([]byte(string(proofsFile)), &circomProof)
if err != nil {
return false, err
}
strProof := utils.GrothProofString{
PiA: circomProof.PiA,
PiB: circomProof.PiB,
PiC: circomProof.PiC,
}
proof, err := utils.GrothProofFromString(strProof)
if err != nil {
return false, err
}
fmt.Println("proof parsed:", proof)
// open public.json
publicFile, err := ioutil.ReadFile(publicSignalsPath)
if err != nil {
return false, err
}
var publicStr []string
json.Unmarshal([]byte(string(publicFile)), &publicStr)
if err != nil {
return false, err
}
publicSignals, err := utils.ArrayStringToBigInt(publicStr)
if err != nil {
return false, err
}
fmt.Println("publicSignals parsed:", publicSignals)
verified := groth16.VerifyProof(vk, proof, publicSignals, true)
return verified, nil
}

View File

@@ -0,0 +1,13 @@
package externalVerif
import (
"testing"
"github.com/stretchr/testify/assert"
)
func TestVerifyFromCircom(t *testing.T) {
verified, err := VerifyFromCircom("circom-test/verification_key.json", "circom-test/proof.json", "circom-test/public.json")
assert.Nil(t, err)
assert.True(t, verified)
}

Binary file not shown.

2
go.mod
View File

@@ -1,4 +1,4 @@
module github.com/arnaucube/go-snark
module github.com/arnaucube/go-snark-study
require (
github.com/davecgh/go-spew v1.1.1 // indirect

View File

@@ -6,12 +6,42 @@ import (
"fmt"
"math/big"
"github.com/arnaucube/go-snark/bn128"
"github.com/arnaucube/go-snark/circuitcompiler"
"github.com/arnaucube/go-snark/fields"
"github.com/arnaucube/go-snark/r1csqap"
"github.com/arnaucube/go-snark-study/bn128"
"github.com/arnaucube/go-snark-study/circuitcompiler"
"github.com/arnaucube/go-snark-study/fields"
"github.com/arnaucube/go-snark-study/r1csqap"
)
type Pk struct { // Proving Key
BACDelta [][3]*big.Int // {( βui(x)+αvi(x)+wi(x) ) / δ } from l+1 to m
Z []*big.Int
G1 struct {
Alpha [3]*big.Int
Beta [3]*big.Int
Delta [3]*big.Int
At [][3]*big.Int // {a(τ)} from 0 to m
BACGamma [][3]*big.Int // {( βui(x)+αvi(x)+wi(x) ) / γ } from 0 to m
}
G2 struct {
Beta [3][2]*big.Int
Gamma [3][2]*big.Int
Delta [3][2]*big.Int
BACGamma [][3][2]*big.Int // {( βui(x)+αvi(x)+wi(x) ) / γ } from 0 to m
}
PowersTauDelta [][3]*big.Int // powers of τ encrypted in G1 curve, divided by δ
}
type Vk struct {
IC [][3]*big.Int
G1 struct {
Alpha [3]*big.Int
}
G2 struct {
Beta [3][2]*big.Int
Gamma [3][2]*big.Int
Delta [3][2]*big.Int
}
}
// Setup is the data structure holding the Trusted Setup data. The Setup.Toxic sub struct must be destroyed after the GenerateTrustedSetup function is completed
type Setup struct {
Toxic struct {
@@ -23,35 +53,8 @@ type Setup struct {
}
// public
Pk struct { // Proving Key
BACDelta [][3]*big.Int // {( βui(x)+αvi(x)+wi(x) ) / γ } from 0 to l
Z []*big.Int
G1 struct {
Alpha [3]*big.Int
Beta [3]*big.Int
Delta [3]*big.Int
At [][3]*big.Int // {a(τ)} from 0 to m
BACGamma [][3]*big.Int // {( βui(x)+αvi(x)+wi(x) ) / δ } from l+1 to m
}
G2 struct {
Beta [3][2]*big.Int
Gamma [3][2]*big.Int
Delta [3][2]*big.Int
BACGamma [][3][2]*big.Int // {( βui(x)+αvi(x)+wi(x) ) / δ } from l+1 to m
}
PowersTauDelta [][3]*big.Int // powers of τ encrypted in G1 curve, divided by δ
}
Vk struct {
IC [][3]*big.Int
G1 struct {
Alpha [3]*big.Int
}
G2 struct {
Beta [3][2]*big.Int
Gamma [3][2]*big.Int
Delta [3][2]*big.Int
}
}
Pk Pk
Vk Vk
}
// Proof contains the parameters to proof the zkSNARK
@@ -165,9 +168,9 @@ func GenerateTrustedSetup(witnessLength int, circuit circuitcompiler.Circuit, al
bt := Utils.PF.Eval(betas[i], setup.Toxic.T)
g1bt := Utils.Bn.G1.MulScalar(Utils.Bn.G1.G, bt)
g2bt := Utils.Bn.G2.MulScalar(Utils.Bn.G2.G, bt)
// G1.BACGamma: {( βui(x)+αvi(x)+wi(x) ) / δ } from l+1 to m in G1
// G1.BACGamma: {( βui(x)+αvi(x)+wi(x) ) / γ } from 0 to m in G1
setup.Pk.G1.BACGamma = append(setup.Pk.G1.BACGamma, g1bt)
// G2.BACGamma: {( βui(x)+αvi(x)+wi(x) ) / δ } from l+1 to m in G2
// G2.BACGamma: {( βui(x)+αvi(x)+wi(x) ) / γ } from 0 to m in G2
setup.Pk.G2.BACGamma = append(setup.Pk.G2.BACGamma, g2bt)
}
@@ -192,7 +195,7 @@ func GenerateTrustedSetup(witnessLength int, circuit circuitcompiler.Circuit, al
)
g1c := Utils.Bn.G1.MulScalar(Utils.Bn.G1.G, c)
// Pk.BACDelta: {( βui(x)+αvi(x)+wi(x) ) / γ } from 0 to l
// Pk.BACDelta: {( βui(x)+αvi(x)+wi(x) ) / δ } from l+1 to m
setup.Pk.BACDelta = append(setup.Pk.BACDelta, g1c)
}
@@ -219,7 +222,7 @@ func GenerateTrustedSetup(witnessLength int, circuit circuitcompiler.Circuit, al
}
// GenerateProofs generates all the parameters to proof the zkSNARK from the Circuit, Setup and the Witness
func GenerateProofs(circuit circuitcompiler.Circuit, setup Setup, w []*big.Int, px []*big.Int) (Proof, error) {
func GenerateProofs(circuit circuitcompiler.Circuit, pk Pk, w []*big.Int, px []*big.Int) (Proof, error) {
var proof Proof
proof.PiA = [3]*big.Int{Utils.Bn.G1.F.Zero(), Utils.Bn.G1.F.Zero(), Utils.Bn.G1.F.Zero()}
proof.PiB = Utils.Bn.Fq6.Zero()
@@ -238,57 +241,57 @@ func GenerateProofs(circuit circuitcompiler.Circuit, setup Setup, w []*big.Int,
piBG1 := [3]*big.Int{Utils.Bn.G1.F.Zero(), Utils.Bn.G1.F.Zero(), Utils.Bn.G1.F.Zero()}
for i := 0; i < circuit.NVars; i++ {
proof.PiA = Utils.Bn.G1.Add(proof.PiA, Utils.Bn.G1.MulScalar(setup.Pk.G1.At[i], w[i]))
piBG1 = Utils.Bn.G1.Add(piBG1, Utils.Bn.G1.MulScalar(setup.Pk.G1.BACGamma[i], w[i]))
proof.PiB = Utils.Bn.G2.Add(proof.PiB, Utils.Bn.G2.MulScalar(setup.Pk.G2.BACGamma[i], w[i]))
proof.PiA = Utils.Bn.G1.Add(proof.PiA, Utils.Bn.G1.MulScalar(pk.G1.At[i], w[i]))
piBG1 = Utils.Bn.G1.Add(piBG1, Utils.Bn.G1.MulScalar(pk.G1.BACGamma[i], w[i]))
proof.PiB = Utils.Bn.G2.Add(proof.PiB, Utils.Bn.G2.MulScalar(pk.G2.BACGamma[i], w[i]))
}
for i := circuit.NPublic + 1; i < circuit.NVars; i++ {
proof.PiC = Utils.Bn.G1.Add(proof.PiC, Utils.Bn.G1.MulScalar(setup.Pk.BACDelta[i], w[i]))
proof.PiC = Utils.Bn.G1.Add(proof.PiC, Utils.Bn.G1.MulScalar(pk.BACDelta[i], w[i]))
}
// piA = (Σ from 0 to m (pk.A * w[i])) + pk.Alpha1 + r * δ
proof.PiA = Utils.Bn.G1.Add(proof.PiA, setup.Pk.G1.Alpha)
deltaR := Utils.Bn.G1.MulScalar(setup.Pk.G1.Delta, r)
proof.PiA = Utils.Bn.G1.Add(proof.PiA, pk.G1.Alpha)
deltaR := Utils.Bn.G1.MulScalar(pk.G1.Delta, r)
proof.PiA = Utils.Bn.G1.Add(proof.PiA, deltaR)
// piBG1 = (Σ from 0 to m (pk.B1 * w[i])) + pk.g1.Beta + s * δ
// piB = piB2 = (Σ from 0 to m (pk.B2 * w[i])) + pk.g2.Beta + s * δ
piBG1 = Utils.Bn.G1.Add(piBG1, setup.Pk.G1.Beta)
proof.PiB = Utils.Bn.G2.Add(proof.PiB, setup.Pk.G2.Beta)
deltaSG1 := Utils.Bn.G1.MulScalar(setup.Pk.G1.Delta, s)
piBG1 = Utils.Bn.G1.Add(piBG1, pk.G1.Beta)
proof.PiB = Utils.Bn.G2.Add(proof.PiB, pk.G2.Beta)
deltaSG1 := Utils.Bn.G1.MulScalar(pk.G1.Delta, s)
piBG1 = Utils.Bn.G1.Add(piBG1, deltaSG1)
deltaSG2 := Utils.Bn.G2.MulScalar(setup.Pk.G2.Delta, s)
deltaSG2 := Utils.Bn.G2.MulScalar(pk.G2.Delta, s)
proof.PiB = Utils.Bn.G2.Add(proof.PiB, deltaSG2)
hx := Utils.PF.DivisorPolynomial(px, setup.Pk.Z) // maybe move this calculation to a previous step
hx := Utils.PF.DivisorPolynomial(px, pk.Z) // maybe move this calculation to a previous step
// piC = (Σ from l+1 to m (w[i] * (pk.g1.Beta + pk.g1.Alpha + pk.C)) + h(tau)) / δ) + piA*s + r*piB - r*s*δ
for i := 0; i < len(hx); i++ {
proof.PiC = Utils.Bn.G1.Add(proof.PiC, Utils.Bn.G1.MulScalar(setup.Pk.PowersTauDelta[i], hx[i]))
proof.PiC = Utils.Bn.G1.Add(proof.PiC, Utils.Bn.G1.MulScalar(pk.PowersTauDelta[i], hx[i]))
}
proof.PiC = Utils.Bn.G1.Add(proof.PiC, Utils.Bn.G1.MulScalar(proof.PiA, s))
proof.PiC = Utils.Bn.G1.Add(proof.PiC, Utils.Bn.G1.MulScalar(piBG1, r))
negRS := Utils.FqR.Neg(Utils.FqR.Mul(r, s))
proof.PiC = Utils.Bn.G1.Add(proof.PiC, Utils.Bn.G1.MulScalar(setup.Pk.G1.Delta, negRS))
proof.PiC = Utils.Bn.G1.Add(proof.PiC, Utils.Bn.G1.MulScalar(pk.G1.Delta, negRS))
return proof, nil
}
// VerifyProof verifies over the BN128 the Pairings of the Proof
func VerifyProof(circuit circuitcompiler.Circuit, setup Setup, proof Proof, publicSignals []*big.Int, debug bool) bool {
func VerifyProof(vk Vk, proof Proof, publicSignals []*big.Int, debug bool) bool {
icPubl := setup.Vk.IC[0]
icPubl := vk.IC[0]
for i := 0; i < len(publicSignals); i++ {
icPubl = Utils.Bn.G1.Add(icPubl, Utils.Bn.G1.MulScalar(setup.Vk.IC[i+1], publicSignals[i]))
icPubl = Utils.Bn.G1.Add(icPubl, Utils.Bn.G1.MulScalar(vk.IC[i+1], publicSignals[i]))
}
if !Utils.Bn.Fq12.Equal(
Utils.Bn.Pairing(proof.PiA, proof.PiB),
Utils.Bn.Fq12.Mul(
Utils.Bn.Pairing(setup.Vk.G1.Alpha, setup.Vk.G2.Beta),
Utils.Bn.Pairing(vk.G1.Alpha, vk.G2.Beta),
Utils.Bn.Fq12.Mul(
Utils.Bn.Pairing(icPubl, setup.Vk.G2.Gamma),
Utils.Bn.Pairing(proof.PiC, setup.Vk.G2.Delta)))) {
Utils.Bn.Pairing(icPubl, vk.G2.Gamma),
Utils.Bn.Pairing(proof.PiC, vk.G2.Delta)))) {
if debug {
fmt.Println("❌ groth16 verification not passed")
}

View File

@@ -8,8 +8,8 @@ import (
"testing"
"time"
"github.com/arnaucube/go-snark/circuitcompiler"
"github.com/arnaucube/go-snark/r1csqap"
"github.com/arnaucube/go-snark-study/circuitcompiler"
"github.com/arnaucube/go-snark-study/r1csqap"
"github.com/stretchr/testify/assert"
)
@@ -85,7 +85,7 @@ func TestGroth16MinimalFlow(t *testing.T) {
// check length of polynomials H(x) and Z(x)
assert.Equal(t, len(hx), len(px)-len(setup.Pk.Z)+1)
proof, err := GenerateProofs(*circuit, setup, w, px)
proof, err := GenerateProofs(*circuit, setup.Pk, w, px)
assert.Nil(t, err)
// fmt.Println("\n proofs:")
@@ -97,11 +97,11 @@ func TestGroth16MinimalFlow(t *testing.T) {
b35Verif := big.NewInt(int64(35))
publicSignalsVerif := []*big.Int{b35Verif}
before := time.Now()
assert.True(t, VerifyProof(*circuit, setup, proof, publicSignalsVerif, true))
assert.True(t, VerifyProof(setup.Vk, proof, publicSignalsVerif, true))
fmt.Println("verify proof time elapsed:", time.Since(before))
// check that with another public input the verification returns false
bOtherWrongPublic := big.NewInt(int64(34))
wrongPublicSignalsVerif := []*big.Int{bOtherWrongPublic}
assert.True(t, !VerifyProof(*circuit, setup, proof, wrongPublicSignalsVerif, false))
assert.True(t, !VerifyProof(setup.Vk, proof, wrongPublicSignalsVerif, false))
}

View File

@@ -1,5 +1,5 @@
## R1CS to Quadratic Arithmetic Program
[![GoDoc](https://godoc.org/github.com/arnaucube/go-snark/r1csqap?status.svg)](https://godoc.org/github.com/arnaucube/go-snark/r1csqap) R1CS to QAP
[![GoDoc](https://godoc.org/github.com/arnaucube/go-snark-study/r1csqap?status.svg)](https://godoc.org/github.com/arnaucube/go-snark-study/r1csqap) R1CS to QAP
- `Succinct Non-Interactive Zero Knowledge for a von Neumann Architecture`, Eli Ben-Sasson, Alessandro Chiesa, Eran Tromer, Madars Virza https://eprint.iacr.org/2013/879.pdf
- Vitalik Buterin blog post about QAP https://medium.com/@VitalikButerin/quadratic-arithmetic-programs-from-zero-to-hero-f6d558cea649
- Ariel Gabizon in Zcash blog https://z.cash/blog/snark-explain5

View File

@@ -4,7 +4,7 @@ import (
"bytes"
"math/big"
"github.com/arnaucube/go-snark/fields"
"github.com/arnaucube/go-snark-study/fields"
)
// Transpose transposes the *big.Int matrix

View File

@@ -5,7 +5,7 @@ import (
"math/big"
"testing"
"github.com/arnaucube/go-snark/fields"
"github.com/arnaucube/go-snark-study/fields"
"github.com/stretchr/testify/assert"
)

View File

@@ -7,12 +7,35 @@ import (
"math/big"
"os"
"github.com/arnaucube/go-snark/bn128"
"github.com/arnaucube/go-snark/circuitcompiler"
"github.com/arnaucube/go-snark/fields"
"github.com/arnaucube/go-snark/r1csqap"
"github.com/arnaucube/go-snark-study/bn128"
"github.com/arnaucube/go-snark-study/circuitcompiler"
"github.com/arnaucube/go-snark-study/fields"
"github.com/arnaucube/go-snark-study/r1csqap"
)
type Pk struct { // Proving Key pk:=(pkA, pkB, pkC, pkH)
G1T [][3]*big.Int // t encrypted in G1 curve, G1T == Pk.H
A [][3]*big.Int
B [][3][2]*big.Int
C [][3]*big.Int
Kp [][3]*big.Int
Ap [][3]*big.Int
Bp [][3]*big.Int
Cp [][3]*big.Int
Z []*big.Int
}
type Vk struct {
Vka [3][2]*big.Int
Vkb [3]*big.Int
Vkc [3][2]*big.Int
IC [][3]*big.Int
G1Kbg [3]*big.Int // g1 * Kbeta * Kgamma
G2Kbg [3][2]*big.Int // g2 * Kbeta * Kgamma
G2Kg [3][2]*big.Int // g2 * Kgamma
Vkz [3][2]*big.Int
}
// Setup is the data structure holding the Trusted Setup data. The Setup.Toxic sub struct must be destroyed after the GenerateTrustedSetup function is completed
type Setup struct {
Toxic struct {
@@ -28,28 +51,8 @@ type Setup struct {
}
// public
G1T [][3]*big.Int // t encrypted in G1 curve, G1T == Pk.H
G2T [][3][2]*big.Int // t encrypted in G2 curve
Pk struct { // Proving Key pk:=(pkA, pkB, pkC, pkH)
A [][3]*big.Int
B [][3][2]*big.Int
C [][3]*big.Int
Kp [][3]*big.Int
Ap [][3]*big.Int
Bp [][3]*big.Int
Cp [][3]*big.Int
Z []*big.Int
}
Vk struct {
Vka [3][2]*big.Int
Vkb [3]*big.Int
Vkc [3][2]*big.Int
IC [][3]*big.Int
G1Kbg [3]*big.Int // g1 * Kbeta * Kgamma
G2Kbg [3][2]*big.Int // g2 * Kbeta * Kgamma
G2Kg [3][2]*big.Int // g2 * Kgamma
Vkz [3][2]*big.Int
}
Pk Pk
Vk Vk
}
// Proof contains the parameters to proof the zkSNARK
@@ -242,13 +245,13 @@ func GenerateTrustedSetup(witnessLength int, circuit circuitcompiler.Circuit, al
// tEncr = Utils.Bn.Fq1.Mul(tEncr, setup.Toxic.T)
tEncr = Utils.FqR.Mul(tEncr, setup.Toxic.T)
}
setup.G1T = gt1
setup.Pk.G1T = gt1
return setup, nil
}
// GenerateProofs generates all the parameters to proof the zkSNARK from the Circuit, Setup and the Witness
func GenerateProofs(circuit circuitcompiler.Circuit, setup Setup, w []*big.Int, px []*big.Int) (Proof, error) {
func GenerateProofs(circuit circuitcompiler.Circuit, pk Pk, w []*big.Int, px []*big.Int) (Proof, error) {
var proof Proof
proof.PiA = [3]*big.Int{Utils.Bn.G1.F.Zero(), Utils.Bn.G1.F.Zero(), Utils.Bn.G1.F.Zero()}
proof.PiAp = [3]*big.Int{Utils.Bn.G1.F.Zero(), Utils.Bn.G1.F.Zero(), Utils.Bn.G1.F.Zero()}
@@ -260,35 +263,35 @@ func GenerateProofs(circuit circuitcompiler.Circuit, setup Setup, w []*big.Int,
proof.PiKp = [3]*big.Int{Utils.Bn.G1.F.Zero(), Utils.Bn.G1.F.Zero(), Utils.Bn.G1.F.Zero()}
for i := circuit.NPublic + 1; i < circuit.NVars; i++ {
proof.PiA = Utils.Bn.G1.Add(proof.PiA, Utils.Bn.G1.MulScalar(setup.Pk.A[i], w[i]))
proof.PiAp = Utils.Bn.G1.Add(proof.PiAp, Utils.Bn.G1.MulScalar(setup.Pk.Ap[i], w[i]))
proof.PiA = Utils.Bn.G1.Add(proof.PiA, Utils.Bn.G1.MulScalar(pk.A[i], w[i]))
proof.PiAp = Utils.Bn.G1.Add(proof.PiAp, Utils.Bn.G1.MulScalar(pk.Ap[i], w[i]))
}
for i := 0; i < circuit.NVars; i++ {
proof.PiB = Utils.Bn.G2.Add(proof.PiB, Utils.Bn.G2.MulScalar(setup.Pk.B[i], w[i]))
proof.PiBp = Utils.Bn.G1.Add(proof.PiBp, Utils.Bn.G1.MulScalar(setup.Pk.Bp[i], w[i]))
proof.PiB = Utils.Bn.G2.Add(proof.PiB, Utils.Bn.G2.MulScalar(pk.B[i], w[i]))
proof.PiBp = Utils.Bn.G1.Add(proof.PiBp, Utils.Bn.G1.MulScalar(pk.Bp[i], w[i]))
proof.PiC = Utils.Bn.G1.Add(proof.PiC, Utils.Bn.G1.MulScalar(setup.Pk.C[i], w[i]))
proof.PiCp = Utils.Bn.G1.Add(proof.PiCp, Utils.Bn.G1.MulScalar(setup.Pk.Cp[i], w[i]))
proof.PiC = Utils.Bn.G1.Add(proof.PiC, Utils.Bn.G1.MulScalar(pk.C[i], w[i]))
proof.PiCp = Utils.Bn.G1.Add(proof.PiCp, Utils.Bn.G1.MulScalar(pk.Cp[i], w[i]))
proof.PiKp = Utils.Bn.G1.Add(proof.PiKp, Utils.Bn.G1.MulScalar(setup.Pk.Kp[i], w[i]))
proof.PiKp = Utils.Bn.G1.Add(proof.PiKp, Utils.Bn.G1.MulScalar(pk.Kp[i], w[i]))
}
hx := Utils.PF.DivisorPolynomial(px, setup.Pk.Z) // maybe move this calculation to a previous step
hx := Utils.PF.DivisorPolynomial(px, pk.Z) // maybe move this calculation to a previous step
// piH = pkH,0 + sum ( hi * pk H,i ), where pkH = G1T, hi=hx
// proof.PiH = Utils.Bn.G1.Add(proof.PiH, setup.G1T[0])
// proof.PiH = Utils.Bn.G1.Add(proof.PiH, pk.G1T[0])
for i := 0; i < len(hx); i++ {
proof.PiH = Utils.Bn.G1.Add(proof.PiH, Utils.Bn.G1.MulScalar(setup.G1T[i], hx[i]))
proof.PiH = Utils.Bn.G1.Add(proof.PiH, Utils.Bn.G1.MulScalar(pk.G1T[i], hx[i]))
}
return proof, nil
}
// VerifyProof verifies over the BN128 the Pairings of the Proof
func VerifyProof(circuit circuitcompiler.Circuit, setup Setup, proof Proof, publicSignals []*big.Int, debug bool) bool {
func VerifyProof(vk Vk, proof Proof, publicSignals []*big.Int, debug bool) bool {
// e(piA, Va) == e(piA', g2)
pairingPiaVa := Utils.Bn.Pairing(proof.PiA, setup.Vk.Vka)
pairingPiaVa := Utils.Bn.Pairing(proof.PiA, vk.Vka)
pairingPiapG2 := Utils.Bn.Pairing(proof.PiAp, Utils.Bn.G2.G)
if !Utils.Bn.Fq12.Equal(pairingPiaVa, pairingPiapG2) {
if debug {
@@ -301,7 +304,7 @@ func VerifyProof(circuit circuitcompiler.Circuit, setup Setup, proof Proof, publ
}
// e(Vb, piB) == e(piB', g2)
pairingVbPib := Utils.Bn.Pairing(setup.Vk.Vkb, proof.PiB)
pairingVbPib := Utils.Bn.Pairing(vk.Vkb, proof.PiB)
pairingPibpG2 := Utils.Bn.Pairing(proof.PiBp, Utils.Bn.G2.G)
if !Utils.Bn.Fq12.Equal(pairingVbPib, pairingPibpG2) {
if debug {
@@ -314,7 +317,7 @@ func VerifyProof(circuit circuitcompiler.Circuit, setup Setup, proof Proof, publ
}
// e(piC, Vc) == e(piC', g2)
pairingPicVc := Utils.Bn.Pairing(proof.PiC, setup.Vk.Vkc)
pairingPicVc := Utils.Bn.Pairing(proof.PiC, vk.Vkc)
pairingPicpG2 := Utils.Bn.Pairing(proof.PiCp, Utils.Bn.G2.G)
if !Utils.Bn.Fq12.Equal(pairingPicVc, pairingPicpG2) {
if debug {
@@ -327,16 +330,16 @@ func VerifyProof(circuit circuitcompiler.Circuit, setup Setup, proof Proof, publ
}
// Vkx, to then calculate Vkx+piA
vkxpia := setup.Vk.IC[0]
vkxpia := vk.IC[0]
for i := 0; i < len(publicSignals); i++ {
vkxpia = Utils.Bn.G1.Add(vkxpia, Utils.Bn.G1.MulScalar(setup.Vk.IC[i+1], publicSignals[i]))
vkxpia = Utils.Bn.G1.Add(vkxpia, Utils.Bn.G1.MulScalar(vk.IC[i+1], publicSignals[i]))
}
// e(Vkx+piA, piB) == e(piH, Vkz) * e(piC, g2)
if !Utils.Bn.Fq12.Equal(
Utils.Bn.Pairing(Utils.Bn.G1.Add(vkxpia, proof.PiA), proof.PiB), // TODO Add(vkxpia, proof.PiA) can go outside in order to save computation, as is reused later
Utils.Bn.Fq12.Mul(
Utils.Bn.Pairing(proof.PiH, setup.Vk.Vkz),
Utils.Bn.Pairing(proof.PiH, vk.Vkz),
Utils.Bn.Pairing(proof.PiC, Utils.Bn.G2.G))) {
if debug {
fmt.Println("❌ e(Vkx+piA, piB) == e(piH, Vkz) * e(piC, g2), QAP disibility checked")
@@ -350,10 +353,10 @@ func VerifyProof(circuit circuitcompiler.Circuit, setup Setup, proof Proof, publ
// e(Vkx+piA+piC, g2KbetaKgamma) * e(g1KbetaKgamma, piB)
// == e(piK, g2Kgamma)
piApiC := Utils.Bn.G1.Add(Utils.Bn.G1.Add(vkxpia, proof.PiA), proof.PiC)
pairingPiACG2Kbg := Utils.Bn.Pairing(piApiC, setup.Vk.G2Kbg)
pairingG1KbgPiB := Utils.Bn.Pairing(setup.Vk.G1Kbg, proof.PiB)
pairingPiACG2Kbg := Utils.Bn.Pairing(piApiC, vk.G2Kbg)
pairingG1KbgPiB := Utils.Bn.Pairing(vk.G1Kbg, proof.PiB)
pairingL := Utils.Bn.Fq12.Mul(pairingPiACG2Kbg, pairingG1KbgPiB)
pairingR := Utils.Bn.Pairing(proof.PiKp, setup.Vk.G2Kg)
pairingR := Utils.Bn.Pairing(proof.PiKp, vk.G2Kg)
if !Utils.Bn.Fq12.Equal(pairingL, pairingR) {
fmt.Println("❌ e(Vkx+piA+piC, g2KbetaKgamma) * e(g1KbetaKgamma, piB) == e(piK, g2Kgamma)")
return false

View File

@@ -8,9 +8,9 @@ import (
"testing"
"time"
"github.com/arnaucube/go-snark/circuitcompiler"
"github.com/arnaucube/go-snark/groth16"
"github.com/arnaucube/go-snark/r1csqap"
"github.com/arnaucube/go-snark-study/circuitcompiler"
"github.com/arnaucube/go-snark-study/groth16"
"github.com/arnaucube/go-snark-study/r1csqap"
"github.com/stretchr/testify/assert"
)
@@ -86,7 +86,7 @@ func TestGroth16MinimalFlow(t *testing.T) {
// check length of polynomials H(x) and Z(x)
assert.Equal(t, len(hx), len(px)-len(setup.Pk.Z)+1)
proof, err := groth16.GenerateProofs(*circuit, setup, w, px)
proof, err := groth16.GenerateProofs(*circuit, setup.Pk, w, px)
assert.Nil(t, err)
// fmt.Println("\n proofs:")
@@ -98,13 +98,13 @@ func TestGroth16MinimalFlow(t *testing.T) {
b35Verif := big.NewInt(int64(35))
publicSignalsVerif := []*big.Int{b35Verif}
before := time.Now()
assert.True(t, groth16.VerifyProof(*circuit, setup, proof, publicSignalsVerif, true))
assert.True(t, groth16.VerifyProof(setup.Vk, proof, publicSignalsVerif, true))
fmt.Println("verify proof time elapsed:", time.Since(before))
// check that with another public input the verification returns false
bOtherWrongPublic := big.NewInt(int64(34))
wrongPublicSignalsVerif := []*big.Int{bOtherWrongPublic}
assert.True(t, !groth16.VerifyProof(*circuit, setup, proof, wrongPublicSignalsVerif, false))
assert.True(t, !groth16.VerifyProof(setup.Vk, proof, wrongPublicSignalsVerif, false))
}
func TestZkFromFlatCircuitCode(t *testing.T) {
@@ -221,7 +221,7 @@ func TestZkFromFlatCircuitCode(t *testing.T) {
assert.Equal(t, len(hx), len(px)-len(setup.Pk.Z)+1)
assert.Equal(t, len(hxQAP), len(px)-len(zxQAP)+1)
proof, err := GenerateProofs(*circuit, setup, w, px)
proof, err := GenerateProofs(*circuit, setup.Pk, w, px)
assert.Nil(t, err)
// fmt.Println("\n proofs:")
@@ -233,13 +233,13 @@ func TestZkFromFlatCircuitCode(t *testing.T) {
b35Verif := big.NewInt(int64(35))
publicSignalsVerif := []*big.Int{b35Verif}
before := time.Now()
assert.True(t, VerifyProof(*circuit, setup, proof, publicSignalsVerif, true))
assert.True(t, VerifyProof(setup.Vk, proof, publicSignalsVerif, true))
fmt.Println("verify proof time elapsed:", time.Since(before))
// check that with another public input the verification returns false
bOtherWrongPublic := big.NewInt(int64(34))
wrongPublicSignalsVerif := []*big.Int{bOtherWrongPublic}
assert.True(t, !VerifyProof(*circuit, setup, proof, wrongPublicSignalsVerif, false))
assert.True(t, !VerifyProof(setup.Vk, proof, wrongPublicSignalsVerif, false))
}
func TestZkMultiplication(t *testing.T) {
@@ -329,7 +329,7 @@ func TestZkMultiplication(t *testing.T) {
assert.Equal(t, len(hx), len(px)-len(setup.Pk.Z)+1)
assert.Equal(t, len(hxQAP), len(px)-len(zxQAP)+1)
proof, err := GenerateProofs(*circuit, setup, w, px)
proof, err := GenerateProofs(*circuit, setup.Pk, w, px)
assert.Nil(t, err)
// fmt.Println("\n proofs:")
@@ -341,13 +341,13 @@ func TestZkMultiplication(t *testing.T) {
b12Verif := big.NewInt(int64(12))
publicSignalsVerif := []*big.Int{b12Verif}
before := time.Now()
assert.True(t, VerifyProof(*circuit, setup, proof, publicSignalsVerif, true))
assert.True(t, VerifyProof(setup.Vk, proof, publicSignalsVerif, true))
fmt.Println("verify proof time elapsed:", time.Since(before))
// check that with another public input the verification returns false
bOtherWrongPublic := big.NewInt(int64(11))
wrongPublicSignalsVerif := []*big.Int{bOtherWrongPublic}
assert.True(t, !VerifyProof(*circuit, setup, proof, wrongPublicSignalsVerif, false))
assert.True(t, !VerifyProof(setup.Vk, proof, wrongPublicSignalsVerif, false))
}
func TestMinimalFlow(t *testing.T) {
@@ -418,7 +418,7 @@ func TestMinimalFlow(t *testing.T) {
// check length of polynomials H(x) and Z(x)
assert.Equal(t, len(hx), len(px)-len(setup.Pk.Z)+1)
proof, err := GenerateProofs(*circuit, setup, w, px)
proof, err := GenerateProofs(*circuit, setup.Pk, w, px)
assert.Nil(t, err)
// fmt.Println("\n proofs:")
@@ -430,11 +430,11 @@ func TestMinimalFlow(t *testing.T) {
b35Verif := big.NewInt(int64(35))
publicSignalsVerif := []*big.Int{b35Verif}
before := time.Now()
assert.True(t, VerifyProof(*circuit, setup, proof, publicSignalsVerif, true))
assert.True(t, VerifyProof(setup.Vk, proof, publicSignalsVerif, true))
fmt.Println("verify proof time elapsed:", time.Since(before))
// check that with another public input the verification returns false
bOtherWrongPublic := big.NewInt(int64(34))
wrongPublicSignalsVerif := []*big.Int{bOtherWrongPublic}
assert.True(t, !VerifyProof(*circuit, setup, proof, wrongPublicSignalsVerif, false))
assert.True(t, !VerifyProof(setup.Vk, proof, wrongPublicSignalsVerif, false))
}

585
utils/base10parsers.go Normal file
View File

@@ -0,0 +1,585 @@
package utils
import (
"errors"
"math/big"
snark "github.com/arnaucube/go-snark-study"
"github.com/arnaucube/go-snark-study/circuitcompiler"
"github.com/arnaucube/go-snark-study/groth16"
)
// []*big.Int
func ArrayBigIntToString(b []*big.Int) []string {
var o []string
for i := 0; i < len(b); i++ {
o = append(o, b[i].String())
}
return o
}
func ArrayStringToBigInt(s []string) ([]*big.Int, error) {
var px []*big.Int
for i := 0; i < len(s); i++ {
param, ok := new(big.Int).SetString(s[i], 10)
if !ok {
return nil, errors.New("error parsing px from pxString")
}
px = append(px, param)
}
return px, nil
}
// [3]*big.Int
func String3ToBigInt(s [3]string) ([3]*big.Int, error) {
var o [3]*big.Int
for i := 0; i < len(s); i++ {
param, ok := new(big.Int).SetString(s[i], 10)
if !ok {
return o, errors.New("error parsing [3]*big.Int from [3]string")
}
o[i] = param
}
return o, nil
}
func BigInt3ToString(b [3]*big.Int) [3]string {
var o [3]string
o[0] = b[0].String()
o[1] = b[1].String()
o[2] = b[2].String()
return o
}
// [][3]*big.Int
func Array3StringToBigInt(s [][3]string) ([][3]*big.Int, error) {
var o [][3]*big.Int
for i := 0; i < len(s); i++ {
parsed, err := String3ToBigInt(s[i])
if err != nil {
return o, err
}
o = append(o, parsed)
}
return o, nil
}
func Array3BigIntToString(b [][3]*big.Int) [][3]string {
var o [][3]string
for i := 0; i < len(b); i++ {
o = append(o, BigInt3ToString(b[i]))
}
return o
}
func String2ToBigInt(s [2]string) ([2]*big.Int, error) {
var o [2]*big.Int
for i := 0; i < len(s); i++ {
param, ok := new(big.Int).SetString(s[i], 10)
if !ok {
return o, errors.New("error parsing [2]*big.Int from [2]string")
}
o[i] = param
}
return o, nil
}
// [3][2]*big.Int
func String32ToBigInt(s [3][2]string) ([3][2]*big.Int, error) {
var o [3][2]*big.Int
var err error
o[0], err = String2ToBigInt(s[0])
if err != nil {
return o, err
}
o[1], err = String2ToBigInt(s[1])
if err != nil {
return o, err
}
o[2], err = String2ToBigInt(s[2])
if err != nil {
return o, err
}
return o, nil
}
func BigInt32ToString(b [3][2]*big.Int) [3][2]string {
var o [3][2]string
o[0][0] = b[0][0].String()
o[0][1] = b[0][1].String()
o[1][0] = b[1][0].String()
o[1][1] = b[1][1].String()
o[2][0] = b[2][0].String()
o[2][1] = b[2][1].String()
return o
}
// [][3][2]*big.Int
func Array32StringToBigInt(s [][3][2]string) ([][3][2]*big.Int, error) {
var o [][3][2]*big.Int
for i := 0; i < len(s); i++ {
parsed, err := String32ToBigInt(s[i])
if err != nil {
return o, err
}
o = append(o, parsed)
}
return o, nil
}
func Array32BigIntToString(b [][3][2]*big.Int) [][3][2]string {
var o [][3][2]string
for i := 0; i < len(b); i++ {
o = append(o, BigInt32ToString(b[i]))
}
return o
}
// Setup
type SetupString struct {
// public
Pk struct {
G1T [][3]string
A [][3]string
B [][3][2]string
C [][3]string
Kp [][3]string
Ap [][3]string
Bp [][3]string
Cp [][3]string
Z []string
}
Vk struct {
Vka [3][2]string
Vkb [3]string
Vkc [3][2]string
IC [][3]string
G1Kbg [3]string
G2Kbg [3][2]string
G2Kg [3][2]string
Vkz [3][2]string
}
}
func SetupToString(setup snark.Setup) SetupString {
var s SetupString
s.Pk.G1T = Array3BigIntToString(setup.Pk.G1T)
s.Pk.A = Array3BigIntToString(setup.Pk.A)
s.Pk.B = Array32BigIntToString(setup.Pk.B)
s.Pk.C = Array3BigIntToString(setup.Pk.C)
s.Pk.Kp = Array3BigIntToString(setup.Pk.Kp)
s.Pk.Ap = Array3BigIntToString(setup.Pk.Ap)
s.Pk.Bp = Array3BigIntToString(setup.Pk.Bp)
s.Pk.Cp = Array3BigIntToString(setup.Pk.Cp)
s.Pk.Z = ArrayBigIntToString(setup.Pk.Z)
s.Vk.Vka = BigInt32ToString(setup.Vk.Vka)
s.Vk.Vkb = BigInt3ToString(setup.Vk.Vkb)
s.Vk.Vkc = BigInt32ToString(setup.Vk.Vkc)
s.Vk.IC = Array3BigIntToString(setup.Vk.IC)
s.Vk.G1Kbg = BigInt3ToString(setup.Vk.G1Kbg)
s.Vk.G2Kbg = BigInt32ToString(setup.Vk.G2Kbg)
s.Vk.G2Kg = BigInt32ToString(setup.Vk.G2Kg)
s.Vk.Vkz = BigInt32ToString(setup.Vk.Vkz)
return s
}
func SetupFromString(s SetupString) (snark.Setup, error) {
var o snark.Setup
var err error
o.Pk.G1T, err = Array3StringToBigInt(s.Pk.G1T)
if err != nil {
return o, err
}
o.Pk.A, err = Array3StringToBigInt(s.Pk.A)
if err != nil {
return o, err
}
o.Pk.B, err = Array32StringToBigInt(s.Pk.B)
if err != nil {
return o, err
}
o.Pk.C, err = Array3StringToBigInt(s.Pk.C)
if err != nil {
return o, err
}
o.Pk.Kp, err = Array3StringToBigInt(s.Pk.Kp)
if err != nil {
return o, err
}
o.Pk.Ap, err = Array3StringToBigInt(s.Pk.Ap)
if err != nil {
return o, err
}
o.Pk.Bp, err = Array3StringToBigInt(s.Pk.Bp)
if err != nil {
return o, err
}
o.Pk.Cp, err = Array3StringToBigInt(s.Pk.Cp)
if err != nil {
return o, err
}
o.Pk.Z, err = ArrayStringToBigInt(s.Pk.Z)
if err != nil {
return o, err
}
o.Vk.Vka, err = String32ToBigInt(s.Vk.Vka)
if err != nil {
return o, err
}
o.Vk.Vkb, err = String3ToBigInt(s.Vk.Vkb)
if err != nil {
return o, err
}
o.Vk.Vkc, err = String32ToBigInt(s.Vk.Vkc)
if err != nil {
return o, err
}
o.Vk.IC, err = Array3StringToBigInt(s.Vk.IC)
if err != nil {
return o, err
}
o.Vk.G1Kbg, err = String3ToBigInt(s.Vk.G1Kbg)
if err != nil {
return o, err
}
o.Vk.G2Kbg, err = String32ToBigInt(s.Vk.G2Kbg)
if err != nil {
return o, err
}
o.Vk.G2Kg, err = String32ToBigInt(s.Vk.G2Kg)
if err != nil {
return o, err
}
o.Vk.Vkz, err = String32ToBigInt(s.Vk.Vkz)
if err != nil {
return o, err
}
return o, nil
}
// circuit
type CircuitString struct {
NVars int
NPublic int
NSignals int
PrivateInputs []string
PublicInputs []string
Signals []string
Witness []string
Constraints []circuitcompiler.Constraint
R1CS struct {
A [][]string
B [][]string
C [][]string
}
}
func ArrayArrayBigIntToString(b [][]*big.Int) [][]string {
var o [][]string
for i := 0; i < len(b); i++ {
o = append(o, ArrayBigIntToString(b[i]))
}
return o
}
func ArrayArrayStringToBigInt(s [][]string) ([][]*big.Int, error) {
var o [][]*big.Int
for i := 0; i < len(s); i++ {
parsed, err := ArrayStringToBigInt(s[i])
if err != nil {
return o, err
}
o = append(o, parsed)
}
return o, nil
}
func CircuitToString(c circuitcompiler.Circuit) CircuitString {
var cs CircuitString
cs.NVars = c.NVars
cs.NPublic = c.NPublic
cs.NSignals = c.NSignals
cs.PrivateInputs = c.PrivateInputs
cs.PublicInputs = c.PublicInputs
cs.Signals = c.Signals
cs.Witness = ArrayBigIntToString(c.Witness)
cs.Constraints = c.Constraints
cs.R1CS.A = ArrayArrayBigIntToString(c.R1CS.A)
cs.R1CS.B = ArrayArrayBigIntToString(c.R1CS.B)
cs.R1CS.C = ArrayArrayBigIntToString(c.R1CS.C)
return cs
}
func CircuitFromString(cs CircuitString) (circuitcompiler.Circuit, error) {
var c circuitcompiler.Circuit
var err error
c.NVars = cs.NVars
c.NPublic = cs.NPublic
c.NSignals = cs.NSignals
c.PrivateInputs = cs.PrivateInputs
c.PublicInputs = cs.PublicInputs
c.Signals = cs.Signals
c.Witness, err = ArrayStringToBigInt(cs.Witness)
if err != nil {
return c, err
}
c.Constraints = cs.Constraints
c.R1CS.A, err = ArrayArrayStringToBigInt(cs.R1CS.A)
if err != nil {
return c, err
}
c.R1CS.B, err = ArrayArrayStringToBigInt(cs.R1CS.B)
if err != nil {
return c, err
}
c.R1CS.C, err = ArrayArrayStringToBigInt(cs.R1CS.C)
if err != nil {
return c, err
}
return c, nil
}
// Proof
type ProofString struct {
PiA [3]string
PiAp [3]string
PiB [3][2]string
PiBp [3]string
PiC [3]string
PiCp [3]string
PiH [3]string
PiKp [3]string
}
func ProofToString(p snark.Proof) ProofString {
var s ProofString
s.PiA = BigInt3ToString(p.PiA)
s.PiAp = BigInt3ToString(p.PiAp)
s.PiB = BigInt32ToString(p.PiB)
s.PiBp = BigInt3ToString(p.PiBp)
s.PiC = BigInt3ToString(p.PiC)
s.PiCp = BigInt3ToString(p.PiCp)
s.PiH = BigInt3ToString(p.PiH)
s.PiKp = BigInt3ToString(p.PiKp)
return s
}
func ProofFromString(s ProofString) (snark.Proof, error) {
var p snark.Proof
var err error
p.PiA, err = String3ToBigInt(s.PiA)
if err != nil {
return p, err
}
p.PiAp, err = String3ToBigInt(s.PiAp)
if err != nil {
return p, err
}
p.PiB, err = String32ToBigInt(s.PiB)
if err != nil {
return p, err
}
p.PiBp, err = String3ToBigInt(s.PiBp)
if err != nil {
return p, err
}
p.PiC, err = String3ToBigInt(s.PiC)
if err != nil {
return p, err
}
p.PiCp, err = String3ToBigInt(s.PiCp)
if err != nil {
return p, err
}
p.PiH, err = String3ToBigInt(s.PiH)
if err != nil {
return p, err
}
p.PiKp, err = String3ToBigInt(s.PiKp)
if err != nil {
return p, err
}
return p, nil
}
// groth
type GrothPkString struct { // Proving Key
BACDelta [][3]string
Z []string
G1 struct {
Alpha [3]string
Beta [3]string
Delta [3]string
At [][3]string
BACGamma [][3]string
}
G2 struct {
Beta [3][2]string
Gamma [3][2]string
Delta [3][2]string
BACGamma [][3][2]string
}
PowersTauDelta [][3]string
}
type GrothVkString struct {
IC [][3]string
G1 struct {
Alpha [3]string
}
G2 struct {
Beta [3][2]string
Gamma [3][2]string
Delta [3][2]string
}
}
type GrothSetupString struct {
Pk GrothPkString
Vk GrothVkString
}
func GrothSetupToString(setup groth16.Setup) GrothSetupString {
var s GrothSetupString
s.Pk.BACDelta = Array3BigIntToString(setup.Pk.BACDelta)
s.Pk.Z = ArrayBigIntToString(setup.Pk.Z)
s.Pk.G1.Alpha = BigInt3ToString(setup.Pk.G1.Alpha)
s.Pk.G1.Beta = BigInt3ToString(setup.Pk.G1.Beta)
s.Pk.G1.Delta = BigInt3ToString(setup.Pk.G1.Delta)
s.Pk.G1.At = Array3BigIntToString(setup.Pk.G1.At)
s.Pk.G1.BACGamma = Array3BigIntToString(setup.Pk.G1.BACGamma)
s.Pk.G2.Beta = BigInt32ToString(setup.Pk.G2.Beta)
s.Pk.G2.Gamma = BigInt32ToString(setup.Pk.G2.Gamma)
s.Pk.G2.Delta = BigInt32ToString(setup.Pk.G2.Delta)
s.Pk.G2.BACGamma = Array32BigIntToString(setup.Pk.G2.BACGamma)
s.Pk.PowersTauDelta = Array3BigIntToString(setup.Pk.PowersTauDelta)
s.Vk.IC = Array3BigIntToString(setup.Vk.IC)
s.Vk.G1.Alpha = BigInt3ToString(setup.Vk.G1.Alpha)
s.Vk.G2.Beta = BigInt32ToString(setup.Vk.G2.Beta)
s.Vk.G2.Gamma = BigInt32ToString(setup.Vk.G2.Gamma)
s.Vk.G2.Delta = BigInt32ToString(setup.Vk.G2.Delta)
return s
}
func GrothVkFromString(s GrothVkString) (groth16.Vk, error) {
var vk groth16.Vk
var err error
vk.IC, err = Array3StringToBigInt(s.IC)
if err != nil {
return vk, err
}
vk.G1.Alpha, err = String3ToBigInt(s.G1.Alpha)
if err != nil {
return vk, err
}
vk.G2.Beta, err = String32ToBigInt(s.G2.Beta)
if err != nil {
return vk, err
}
vk.G2.Gamma, err = String32ToBigInt(s.G2.Gamma)
if err != nil {
return vk, err
}
vk.G2.Delta, err = String32ToBigInt(s.G2.Delta)
if err != nil {
return vk, err
}
return vk, nil
}
func GrothSetupFromString(s GrothSetupString) (groth16.Setup, error) {
var o groth16.Setup
var err error
o.Pk.BACDelta, err = Array3StringToBigInt(s.Pk.BACDelta)
if err != nil {
return o, err
}
o.Pk.Z, err = ArrayStringToBigInt(s.Pk.Z)
if err != nil {
return o, err
}
o.Pk.G1.Alpha, err = String3ToBigInt(s.Pk.G1.Alpha)
if err != nil {
return o, err
}
o.Pk.G1.Beta, err = String3ToBigInt(s.Pk.G1.Beta)
if err != nil {
return o, err
}
o.Pk.G1.Delta, err = String3ToBigInt(s.Pk.G1.Delta)
if err != nil {
return o, err
}
o.Pk.G1.At, err = Array3StringToBigInt(s.Pk.G1.At)
if err != nil {
return o, err
}
o.Pk.G1.BACGamma, err = Array3StringToBigInt(s.Pk.G1.BACGamma)
if err != nil {
return o, err
}
o.Pk.G2.Beta, err = String32ToBigInt(s.Pk.G2.Beta)
if err != nil {
return o, err
}
o.Pk.G2.Gamma, err = String32ToBigInt(s.Pk.G2.Gamma)
if err != nil {
return o, err
}
o.Pk.G2.Delta, err = String32ToBigInt(s.Pk.G2.Delta)
if err != nil {
return o, err
}
o.Pk.G2.BACGamma, err = Array32StringToBigInt(s.Pk.G2.BACGamma)
if err != nil {
return o, err
}
o.Pk.PowersTauDelta, err = Array3StringToBigInt(s.Pk.PowersTauDelta)
if err != nil {
return o, err
}
o.Vk.IC, err = Array3StringToBigInt(s.Vk.IC)
if err != nil {
return o, err
}
o.Vk.G1.Alpha, err = String3ToBigInt(s.Vk.G1.Alpha)
if err != nil {
return o, err
}
o.Vk.G2.Beta, err = String32ToBigInt(s.Vk.G2.Beta)
if err != nil {
return o, err
}
o.Vk.G2.Gamma, err = String32ToBigInt(s.Vk.G2.Gamma)
if err != nil {
return o, err
}
o.Vk.G2.Delta, err = String32ToBigInt(s.Vk.G2.Delta)
if err != nil {
return o, err
}
return o, nil
}
type GrothProofString struct {
PiA [3]string
PiB [3][2]string
PiC [3]string
}
func GrothProofToString(p groth16.Proof) GrothProofString {
var s GrothProofString
s.PiA = BigInt3ToString(p.PiA)
s.PiB = BigInt32ToString(p.PiB)
s.PiC = BigInt3ToString(p.PiC)
return s
}
func GrothProofFromString(s GrothProofString) (groth16.Proof, error) {
var p groth16.Proof
var err error
p.PiA, err = String3ToBigInt(s.PiA)
if err != nil {
return p, err
}
p.PiB, err = String32ToBigInt(s.PiB)
if err != nil {
return p, err
}
p.PiC, err = String3ToBigInt(s.PiC)
if err != nil {
return p, err
}
return p, nil
}

562
utils/hexparsers.go Normal file
View File

@@ -0,0 +1,562 @@
package utils
import (
"errors"
"fmt"
"math/big"
snark "github.com/arnaucube/go-snark-study"
"github.com/arnaucube/go-snark-study/circuitcompiler"
"github.com/arnaucube/go-snark-study/groth16"
)
// []*big.Int
func ArrayBigIntToHex(b []*big.Int) []string {
var o []string
for i := 0; i < len(b); i++ {
o = append(o, fmt.Sprintf("%x", b[i]))
}
return o
}
func ArrayHexToBigInt(s []string) ([]*big.Int, error) {
var px []*big.Int
for i := 0; i < len(s); i++ {
param, ok := new(big.Int).SetString(s[i], 16)
if !ok {
return nil, errors.New("error parsing px from pxHex")
}
px = append(px, param)
}
return px, nil
}
// [3]*big.Int
func Hex3ToBigInt(s [3]string) ([3]*big.Int, error) {
var o [3]*big.Int
for i := 0; i < len(s); i++ {
param, ok := new(big.Int).SetString(s[i], 16)
if !ok {
return o, errors.New("error parsing [3]*big.Int from [3]string")
}
o[i] = param
}
return o, nil
}
func BigInt3ToHex(b [3]*big.Int) [3]string {
var o [3]string
o[0] = fmt.Sprintf("%x", b[0])
o[1] = fmt.Sprintf("%x", b[1])
o[2] = fmt.Sprintf("%x", b[2])
return o
}
// [][3]*big.Int
func Array3HexToBigInt(s [][3]string) ([][3]*big.Int, error) {
var o [][3]*big.Int
for i := 0; i < len(s); i++ {
parsed, err := Hex3ToBigInt(s[i])
if err != nil {
return o, err
}
o = append(o, parsed)
}
return o, nil
}
func Array3BigIntToHex(b [][3]*big.Int) [][3]string {
var o [][3]string
for i := 0; i < len(b); i++ {
o = append(o, BigInt3ToHex(b[i]))
}
return o
}
func Hex2ToBigInt(s [2]string) ([2]*big.Int, error) {
var o [2]*big.Int
for i := 0; i < len(s); i++ {
param, ok := new(big.Int).SetString(s[i], 16)
if !ok {
return o, errors.New("error parsing [2]*big.Int from [2]string")
}
o[i] = param
}
return o, nil
}
// [3][2]*big.Int
func Hex32ToBigInt(s [3][2]string) ([3][2]*big.Int, error) {
var o [3][2]*big.Int
var err error
o[0], err = Hex2ToBigInt(s[0])
if err != nil {
return o, err
}
o[1], err = Hex2ToBigInt(s[1])
if err != nil {
return o, err
}
o[2], err = Hex2ToBigInt(s[2])
if err != nil {
return o, err
}
return o, nil
}
func BigInt32ToHex(b [3][2]*big.Int) [3][2]string {
var o [3][2]string
o[0][0] = fmt.Sprintf("%x", b[0][0])
o[0][1] = fmt.Sprintf("%x", b[0][1])
o[1][0] = fmt.Sprintf("%x", b[1][0])
o[1][1] = fmt.Sprintf("%x", b[1][1])
o[2][0] = fmt.Sprintf("%x", b[2][0])
o[2][1] = fmt.Sprintf("%x", b[2][1])
return o
}
// [][3][2]*big.Int
func Array32HexToBigInt(s [][3][2]string) ([][3][2]*big.Int, error) {
var o [][3][2]*big.Int
for i := 0; i < len(s); i++ {
parsed, err := Hex32ToBigInt(s[i])
if err != nil {
return o, err
}
o = append(o, parsed)
}
return o, nil
}
func Array32BigIntToHex(b [][3][2]*big.Int) [][3][2]string {
var o [][3][2]string
for i := 0; i < len(b); i++ {
o = append(o, BigInt32ToHex(b[i]))
}
return o
}
// Setup
type PkHex struct {
G1T [][3]string
A [][3]string
B [][3][2]string
C [][3]string
Kp [][3]string
Ap [][3]string
Bp [][3]string
Cp [][3]string
Z []string
}
type VkHex struct {
Vka [3][2]string
Vkb [3]string
Vkc [3][2]string
IC [][3]string
G1Kbg [3]string
G2Kbg [3][2]string
G2Kg [3][2]string
Vkz [3][2]string
}
type SetupHex struct {
Pk PkHex
Vk VkHex
}
func SetupToHex(setup snark.Setup) SetupHex {
var s SetupHex
s.Pk.G1T = Array3BigIntToHex(setup.Pk.G1T)
s.Pk.A = Array3BigIntToHex(setup.Pk.A)
s.Pk.B = Array32BigIntToHex(setup.Pk.B)
s.Pk.C = Array3BigIntToHex(setup.Pk.C)
s.Pk.Kp = Array3BigIntToHex(setup.Pk.Kp)
s.Pk.Ap = Array3BigIntToHex(setup.Pk.Ap)
s.Pk.Bp = Array3BigIntToHex(setup.Pk.Bp)
s.Pk.Cp = Array3BigIntToHex(setup.Pk.Cp)
s.Pk.Z = ArrayBigIntToHex(setup.Pk.Z)
s.Vk.Vka = BigInt32ToHex(setup.Vk.Vka)
s.Vk.Vkb = BigInt3ToHex(setup.Vk.Vkb)
s.Vk.Vkc = BigInt32ToHex(setup.Vk.Vkc)
s.Vk.IC = Array3BigIntToHex(setup.Vk.IC)
s.Vk.G1Kbg = BigInt3ToHex(setup.Vk.G1Kbg)
s.Vk.G2Kbg = BigInt32ToHex(setup.Vk.G2Kbg)
s.Vk.G2Kg = BigInt32ToHex(setup.Vk.G2Kg)
s.Vk.Vkz = BigInt32ToHex(setup.Vk.Vkz)
return s
}
func SetupFromHex(s SetupHex) (snark.Setup, error) {
var o snark.Setup
var err error
o.Pk.G1T, err = Array3HexToBigInt(s.Pk.G1T)
if err != nil {
return o, err
}
o.Pk.A, err = Array3HexToBigInt(s.Pk.A)
if err != nil {
return o, err
}
o.Pk.B, err = Array32HexToBigInt(s.Pk.B)
if err != nil {
return o, err
}
o.Pk.C, err = Array3HexToBigInt(s.Pk.C)
if err != nil {
return o, err
}
o.Pk.Kp, err = Array3HexToBigInt(s.Pk.Kp)
if err != nil {
return o, err
}
o.Pk.Ap, err = Array3HexToBigInt(s.Pk.Ap)
if err != nil {
return o, err
}
o.Pk.Bp, err = Array3HexToBigInt(s.Pk.Bp)
if err != nil {
return o, err
}
o.Pk.Cp, err = Array3HexToBigInt(s.Pk.Cp)
if err != nil {
return o, err
}
o.Pk.Z, err = ArrayHexToBigInt(s.Pk.Z)
if err != nil {
return o, err
}
o.Vk.Vka, err = Hex32ToBigInt(s.Vk.Vka)
if err != nil {
return o, err
}
o.Vk.Vkb, err = Hex3ToBigInt(s.Vk.Vkb)
if err != nil {
return o, err
}
o.Vk.Vkc, err = Hex32ToBigInt(s.Vk.Vkc)
if err != nil {
return o, err
}
o.Vk.IC, err = Array3HexToBigInt(s.Vk.IC)
if err != nil {
return o, err
}
o.Vk.G1Kbg, err = Hex3ToBigInt(s.Vk.G1Kbg)
if err != nil {
return o, err
}
o.Vk.G2Kbg, err = Hex32ToBigInt(s.Vk.G2Kbg)
if err != nil {
return o, err
}
o.Vk.G2Kg, err = Hex32ToBigInt(s.Vk.G2Kg)
if err != nil {
return o, err
}
o.Vk.Vkz, err = Hex32ToBigInt(s.Vk.Vkz)
if err != nil {
return o, err
}
return o, nil
}
// circuit
type CircuitHex struct {
NVars int
NPublic int
NSignals int
PrivateInputs []string
PublicInputs []string
Signals []string
Witness []string
Constraints []circuitcompiler.Constraint
R1CS struct {
A [][]string
B [][]string
C [][]string
}
}
func ArrayArrayBigIntToHex(b [][]*big.Int) [][]string {
var o [][]string
for i := 0; i < len(b); i++ {
o = append(o, ArrayBigIntToHex(b[i]))
}
return o
}
func ArrayArrayHexToBigInt(s [][]string) ([][]*big.Int, error) {
var o [][]*big.Int
for i := 0; i < len(s); i++ {
parsed, err := ArrayHexToBigInt(s[i])
if err != nil {
return o, err
}
o = append(o, parsed)
}
return o, nil
}
func CircuitToHex(c circuitcompiler.Circuit) CircuitHex {
var cs CircuitHex
cs.NVars = c.NVars
cs.NPublic = c.NPublic
cs.NSignals = c.NSignals
cs.PrivateInputs = c.PrivateInputs
cs.PublicInputs = c.PublicInputs
cs.Signals = c.Signals
cs.Witness = ArrayBigIntToHex(c.Witness)
cs.Constraints = c.Constraints
cs.R1CS.A = ArrayArrayBigIntToHex(c.R1CS.A)
cs.R1CS.B = ArrayArrayBigIntToHex(c.R1CS.B)
cs.R1CS.C = ArrayArrayBigIntToHex(c.R1CS.C)
return cs
}
func CircuitFromHex(cs CircuitHex) (circuitcompiler.Circuit, error) {
var c circuitcompiler.Circuit
var err error
c.NVars = cs.NVars
c.NPublic = cs.NPublic
c.NSignals = cs.NSignals
c.PrivateInputs = cs.PrivateInputs
c.PublicInputs = cs.PublicInputs
c.Signals = cs.Signals
c.Witness, err = ArrayHexToBigInt(cs.Witness)
if err != nil {
return c, err
}
c.Constraints = cs.Constraints
c.R1CS.A, err = ArrayArrayHexToBigInt(cs.R1CS.A)
if err != nil {
return c, err
}
c.R1CS.B, err = ArrayArrayHexToBigInt(cs.R1CS.B)
if err != nil {
return c, err
}
c.R1CS.C, err = ArrayArrayHexToBigInt(cs.R1CS.C)
if err != nil {
return c, err
}
return c, nil
}
// Proof
type ProofHex struct {
PiA [3]string
PiAp [3]string
PiB [3][2]string
PiBp [3]string
PiC [3]string
PiCp [3]string
PiH [3]string
PiKp [3]string
}
func ProofToHex(p snark.Proof) ProofHex {
var s ProofHex
s.PiA = BigInt3ToHex(p.PiA)
s.PiAp = BigInt3ToHex(p.PiAp)
s.PiB = BigInt32ToHex(p.PiB)
s.PiBp = BigInt3ToHex(p.PiBp)
s.PiC = BigInt3ToHex(p.PiC)
s.PiCp = BigInt3ToHex(p.PiCp)
s.PiH = BigInt3ToHex(p.PiH)
s.PiKp = BigInt3ToHex(p.PiKp)
return s
}
func ProofFromHex(s ProofHex) (snark.Proof, error) {
var p snark.Proof
var err error
p.PiA, err = Hex3ToBigInt(s.PiA)
if err != nil {
return p, err
}
p.PiAp, err = Hex3ToBigInt(s.PiAp)
if err != nil {
return p, err
}
p.PiB, err = Hex32ToBigInt(s.PiB)
if err != nil {
return p, err
}
p.PiBp, err = Hex3ToBigInt(s.PiBp)
if err != nil {
return p, err
}
p.PiC, err = Hex3ToBigInt(s.PiC)
if err != nil {
return p, err
}
p.PiCp, err = Hex3ToBigInt(s.PiCp)
if err != nil {
return p, err
}
p.PiH, err = Hex3ToBigInt(s.PiH)
if err != nil {
return p, err
}
p.PiKp, err = Hex3ToBigInt(s.PiKp)
if err != nil {
return p, err
}
return p, nil
}
// groth
type GrothPkHex struct { // Proving Key
BACDelta [][3]string
Z []string
G1 struct {
Alpha [3]string
Beta [3]string
Delta [3]string
At [][3]string
BACGamma [][3]string
}
G2 struct {
Beta [3][2]string
Gamma [3][2]string
Delta [3][2]string
BACGamma [][3][2]string
}
PowersTauDelta [][3]string
}
type GrothVkHex struct {
IC [][3]string
G1 struct {
Alpha [3]string
}
G2 struct {
Beta [3][2]string
Gamma [3][2]string
Delta [3][2]string
}
}
type GrothSetupHex struct {
Pk GrothPkHex
Vk GrothVkHex
}
func GrothSetupToHex(setup groth16.Setup) GrothSetupHex {
var s GrothSetupHex
s.Pk.BACDelta = Array3BigIntToHex(setup.Pk.BACDelta)
s.Pk.Z = ArrayBigIntToHex(setup.Pk.Z)
s.Pk.G1.Alpha = BigInt3ToHex(setup.Pk.G1.Alpha)
s.Pk.G1.Beta = BigInt3ToHex(setup.Pk.G1.Beta)
s.Pk.G1.Delta = BigInt3ToHex(setup.Pk.G1.Delta)
s.Pk.G1.At = Array3BigIntToHex(setup.Pk.G1.At)
s.Pk.G1.BACGamma = Array3BigIntToHex(setup.Pk.G1.BACGamma)
s.Pk.G2.Beta = BigInt32ToHex(setup.Pk.G2.Beta)
s.Pk.G2.Gamma = BigInt32ToHex(setup.Pk.G2.Gamma)
s.Pk.G2.Delta = BigInt32ToHex(setup.Pk.G2.Delta)
s.Pk.G2.BACGamma = Array32BigIntToHex(setup.Pk.G2.BACGamma)
s.Pk.PowersTauDelta = Array3BigIntToHex(setup.Pk.PowersTauDelta)
s.Vk.IC = Array3BigIntToHex(setup.Vk.IC)
s.Vk.G1.Alpha = BigInt3ToHex(setup.Vk.G1.Alpha)
s.Vk.G2.Beta = BigInt32ToHex(setup.Vk.G2.Beta)
s.Vk.G2.Gamma = BigInt32ToHex(setup.Vk.G2.Gamma)
s.Vk.G2.Delta = BigInt32ToHex(setup.Vk.G2.Delta)
return s
}
func GrothSetupFromHex(s GrothSetupHex) (groth16.Setup, error) {
var o groth16.Setup
var err error
o.Pk.BACDelta, err = Array3HexToBigInt(s.Pk.BACDelta)
if err != nil {
return o, err
}
o.Pk.Z, err = ArrayHexToBigInt(s.Pk.Z)
if err != nil {
return o, err
}
o.Pk.G1.Alpha, err = Hex3ToBigInt(s.Pk.G1.Alpha)
if err != nil {
return o, err
}
o.Pk.G1.Beta, err = Hex3ToBigInt(s.Pk.G1.Beta)
if err != nil {
return o, err
}
o.Pk.G1.Delta, err = Hex3ToBigInt(s.Pk.G1.Delta)
if err != nil {
return o, err
}
o.Pk.G1.At, err = Array3HexToBigInt(s.Pk.G1.At)
if err != nil {
return o, err
}
o.Pk.G1.BACGamma, err = Array3HexToBigInt(s.Pk.G1.BACGamma)
if err != nil {
return o, err
}
o.Pk.G2.Beta, err = Hex32ToBigInt(s.Pk.G2.Beta)
if err != nil {
return o, err
}
o.Pk.G2.Gamma, err = Hex32ToBigInt(s.Pk.G2.Gamma)
if err != nil {
return o, err
}
o.Pk.G2.Delta, err = Hex32ToBigInt(s.Pk.G2.Delta)
if err != nil {
return o, err
}
o.Pk.G2.BACGamma, err = Array32HexToBigInt(s.Pk.G2.BACGamma)
if err != nil {
return o, err
}
o.Pk.PowersTauDelta, err = Array3HexToBigInt(s.Pk.PowersTauDelta)
if err != nil {
return o, err
}
o.Vk.IC, err = Array3HexToBigInt(s.Vk.IC)
if err != nil {
return o, err
}
o.Vk.G1.Alpha, err = Hex3ToBigInt(s.Vk.G1.Alpha)
if err != nil {
return o, err
}
o.Vk.G2.Beta, err = Hex32ToBigInt(s.Vk.G2.Beta)
if err != nil {
return o, err
}
o.Vk.G2.Gamma, err = Hex32ToBigInt(s.Vk.G2.Gamma)
if err != nil {
return o, err
}
o.Vk.G2.Delta, err = Hex32ToBigInt(s.Vk.G2.Delta)
if err != nil {
return o, err
}
return o, nil
}
type GrothProofHex struct {
PiA [3]string
PiB [3][2]string
PiC [3]string
}
func GrothProofToHex(p groth16.Proof) GrothProofHex {
var s GrothProofHex
s.PiA = BigInt3ToHex(p.PiA)
s.PiB = BigInt32ToHex(p.PiB)
s.PiC = BigInt3ToHex(p.PiC)
return s
}
func GrothProofFromHex(s GrothProofHex) (groth16.Proof, error) {
var p groth16.Proof
var err error
p.PiA, err = Hex3ToBigInt(s.PiA)
if err != nil {
return p, err
}
p.PiB, err = Hex32ToBigInt(s.PiB)
if err != nil {
return p, err
}
p.PiC, err = Hex3ToBigInt(s.PiC)
if err != nil {
return p, err
}
return p, nil
}

View File

@@ -3,8 +3,8 @@
## Installation in vim/nvim using plug
Using [Plug](https://github.com/junegunn/vim-plug), add this lines into the `.vimrc`/`init.vim`:
```
Plug 'arnaucube/go-snark'
Plug 'arnaucube/go-snark', {'rtp': 'vim-syntax'}
Plug 'arnaucube/go-snark-study'
Plug 'arnaucube/go-snark-study', {'rtp': 'vim-syntax'}
```
![screenshot-vim](https://raw.githubusercontent.com/arnaucube/go-snark/master/vim-syntax/screenshot.png "screenshot-vim")
![screenshot-vim](https://raw.githubusercontent.com/arnaucube/go-snark-study/master/vim-syntax/screenshot.png "screenshot-vim")

View File

@@ -24,6 +24,7 @@ syn keyword goSnarkCircuitPrivatePublic private public
syn keyword goSnarkCircuitOut out
syn keyword goSnarkCircuitEquals equals
syn keyword goSnarkCircuitFunction func
syn keyword goSnarkCircuitStatement return
syn keyword goSnarkCircuitImport import
syn match goSnarkCircuitFuncCall /\<\K\k*\ze\s*(/
syn keyword goSnarkCircuitPrivate private nextgroup=goSnarkCircuitInputName skipwhite
@@ -46,6 +47,7 @@ hi def link goSnarkCircuitOpSymbols Operator
hi def link goSnarkCircuitFuncCall Function
hi def link goSnarkCircuitEquals Identifier
hi def link goSnarkCircuitFunction Keyword
hi def link goSnarkCircuitStatement Statement
hi def link goSnarkCircuitImport Keyword
hi def link goSnarkCircuitBraces Function
hi def link goSnarkCircuitPrivate Keyword

3
wasm/.gitignore vendored Normal file
View File

@@ -0,0 +1,3 @@
node_modules
package-lock.json
wasm_exec.js

22
wasm/README.md Normal file
View File

@@ -0,0 +1,22 @@
# go-snark-study wasm
*Warning: this is an ongoing experimentation*
WASM wrappers for zkSNARK Pinocchio & Groth16 protocols.
## Wasm usage
To compile to wasm, inside the `wasm` directory, execute:
```
GOARCH=wasm GOOS=js go build -o go-snark.wasm go-snark-wasm-wrapper.go
```
Add the file `wasm_exec.js` in the directory:
```
cp "$(go env GOROOT)/misc/wasm/wasm_exec.js" .
```
To see the usage from javascript, check `index.js` file.
Run the http server that allows to load the `.wasm` file:
```
node server.js
```

View File

@@ -0,0 +1,246 @@
package main
import (
"encoding/json"
"math/big"
"syscall/js"
"github.com/arnaucube/go-snark-study"
"github.com/arnaucube/go-snark-study/circuitcompiler"
"github.com/arnaucube/go-snark-study/groth16"
"github.com/arnaucube/go-snark-study/utils"
)
func main() {
c := make(chan struct{}, 0)
println("WASM Go Initialized")
registerCallbacks()
<-c
}
func registerCallbacks() {
js.Global().Set("generateProofs", js.FuncOf(generateProofs))
js.Global().Set("verifyProofs", js.FuncOf(verifyProofs))
js.Global().Set("grothGenerateProofs", js.FuncOf(grothGenerateProofs))
js.Global().Set("grothVerifyProofs", js.FuncOf(grothVerifyProofs))
}
func generateProofs(this js.Value, i []js.Value) interface{} {
var circuitStr utils.CircuitString
err := json.Unmarshal([]byte(i[0].String()), &circuitStr)
if err != nil {
println(i[0].String())
println("error parsing circuit from stringified json")
}
circuit, err := utils.CircuitFromString(circuitStr)
if err != nil {
println("error " + err.Error())
}
sj, err := json.Marshal(circuit)
if err != nil {
println("error " + err.Error())
}
println("circuit", string(sj))
var setupStr utils.SetupString
println(i[1].String())
err = json.Unmarshal([]byte(i[1].String()), &setupStr)
if err != nil {
println("error parsing setup from stringified json")
}
setup, err := utils.SetupFromString(setupStr)
if err != nil {
println("error " + err.Error())
}
sj, err = json.Marshal(setup)
if err != nil {
println("error " + err.Error())
}
println("set", string(sj))
var pxStr []string
err = json.Unmarshal([]byte(i[2].String()), &pxStr)
if err != nil {
println("error parsing pxStr from stringified json")
}
px, err := utils.ArrayStringToBigInt(pxStr)
if err != nil {
println(err.Error())
}
sj, err = json.Marshal(px)
if err != nil {
println("error " + err.Error())
}
println("px", string(sj))
var inputs circuitcompiler.Inputs
err = json.Unmarshal([]byte(i[3].String()), &inputs)
if err != nil {
println("error parsing inputs from stringified json")
}
w, err := circuit.CalculateWitness(inputs.Private, inputs.Public)
proof, err := snark.GenerateProofs(circuit, setup.Pk, w, px)
if err != nil {
println("error generating proof", err)
}
proofString := utils.ProofToString(proof)
proofJson, err := json.Marshal(proofString)
if err != nil {
println("error marshal proof to json", err)
}
println("proofJson", string(proofJson))
return js.ValueOf(string(proofJson))
}
func verifyProofs(this js.Value, i []js.Value) interface{} {
var setupStr utils.SetupString
println(i[0].String())
err := json.Unmarshal([]byte(i[0].String()), &setupStr)
if err != nil {
println("error parsing setup from stringified json")
}
setup, err := utils.SetupFromString(setupStr)
if err != nil {
println("error " + err.Error())
}
var proofStr utils.ProofString
err = json.Unmarshal([]byte(i[1].String()), &proofStr)
if err != nil {
println(i[1].String())
println("error parsing proof from stringified json")
}
proof, err := utils.ProofFromString(proofStr)
if err != nil {
println("error " + err.Error())
}
var publicInputs []*big.Int
err = json.Unmarshal([]byte(i[2].String()), &publicInputs)
if err != nil {
println(i[2].String())
println("error parsing publicInputs from stringified json")
}
verified := snark.VerifyProof(setup.Vk, proof, publicInputs, false)
if err != nil {
println("error verifiyng proof", err)
}
verifiedJson, err := json.Marshal(verified)
if err != nil {
println("error marshal verified to json", err)
}
println("verifiedJson", string(verifiedJson))
return js.ValueOf(string(verifiedJson))
}
func grothGenerateProofs(this js.Value, i []js.Value) interface{} {
var circuitStr utils.CircuitString
err := json.Unmarshal([]byte(i[0].String()), &circuitStr)
if err != nil {
println(i[0].String())
println("error parsing circuit from stringified json")
}
circuit, err := utils.CircuitFromString(circuitStr)
if err != nil {
println("error " + err.Error())
}
sj, err := json.Marshal(circuit)
if err != nil {
println("error " + err.Error())
}
println("circuit", string(sj))
var setupStr utils.GrothSetupString
println(i[1].String())
err = json.Unmarshal([]byte(i[1].String()), &setupStr)
if err != nil {
println("error parsing setup from stringified json")
}
setup, err := utils.GrothSetupFromString(setupStr)
if err != nil {
println("error " + err.Error())
}
sj, err = json.Marshal(setup)
if err != nil {
println("error " + err.Error())
}
println("set", string(sj))
var pxStr []string
err = json.Unmarshal([]byte(i[2].String()), &pxStr)
if err != nil {
println("error parsing pxStr from stringified json")
}
px, err := utils.ArrayStringToBigInt(pxStr)
if err != nil {
println(err.Error())
}
sj, err = json.Marshal(px)
if err != nil {
println("error " + err.Error())
}
println("px", string(sj))
var inputs circuitcompiler.Inputs
err = json.Unmarshal([]byte(i[3].String()), &inputs)
if err != nil {
println("error parsing inputs from stringified json")
}
w, err := circuit.CalculateWitness(inputs.Private, inputs.Public)
proof, err := groth16.GenerateProofs(circuit, setup.Pk, w, px)
if err != nil {
println("error generating proof", err)
}
proofString := utils.GrothProofToString(proof)
proofJson, err := json.Marshal(proofString)
if err != nil {
println("error marshal proof to json", err)
}
println("proofJson", string(proofJson))
return js.ValueOf(string(proofJson))
}
func grothVerifyProofs(this js.Value, i []js.Value) interface{} {
var setupStr utils.GrothSetupString
println(i[0].String())
err := json.Unmarshal([]byte(i[0].String()), &setupStr)
if err != nil {
println("error parsing setup from stringified json")
}
setup, err := utils.GrothSetupFromString(setupStr)
if err != nil {
println("error " + err.Error())
}
var proofStr utils.GrothProofString
err = json.Unmarshal([]byte(i[1].String()), &proofStr)
if err != nil {
println(i[1].String())
println("error parsing proof from stringified json")
}
proof, err := utils.GrothProofFromString(proofStr)
if err != nil {
println("error " + err.Error())
}
var publicInputs []*big.Int
err = json.Unmarshal([]byte(i[2].String()), &publicInputs)
if err != nil {
println(i[2].String())
println("error parsing publicInputs from stringified json")
}
verified := groth16.VerifyProof(setup.Vk, proof, publicInputs, false)
if err != nil {
println("error verifiyng proof", err)
}
verifiedJson, err := json.Marshal(verified)
if err != nil {
println("error marshal verified to json", err)
}
println("verifiedJson", string(verifiedJson))
return js.ValueOf(string(verifiedJson))
}

BIN
wasm/go-snark.wasm Executable file

Binary file not shown.

20
wasm/index.html Normal file
View File

@@ -0,0 +1,20 @@
<html>
<head>
<meta charset="utf-8">
<title>go-snark wasm experiments</title>
</head>
<body>
<script src="wasm_exec.js"></script>
<script>
const go = new Go();
WebAssembly.instantiateStreaming(fetch('go-snark.wasm'), go.importObject).then(function(dat) {
go.run(dat.instance);
});
</script>
<button onClick="callGenerateProof();">Generate Proof</button>
<textarea id="proofResult" rows="15" style="width: 80%;">
</textarea>
<button onClick="callVerifyProof();">Verify Proof</button>
<script src="index.js"></script>
</body>
</html>

30
wasm/index.js Normal file

File diff suppressed because one or more lines are too long

15
wasm/package.json Normal file
View File

@@ -0,0 +1,15 @@
{
"name": "server",
"version": "1.0.0",
"description": "",
"main": "server.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1",
"start": "node server.js"
},
"author": "",
"license": "ISC",
"dependencies": {
"express": "^4.16.4"
}
}

7
wasm/server.js Normal file
View File

@@ -0,0 +1,7 @@
var express = require('express');
var app = express();
express.static.mime.types['wasm'] = 'application/wasm';
app.use(express.static(__dirname + '/'));
port=8080
app.listen(8080);
console.log("server running at :8080")