mirror of
https://github.com/arnaucube/go-snark-study.git
synced 2026-02-02 17:26:41 +01:00
cli
This commit is contained in:
5
.gitignore
vendored
5
.gitignore
vendored
@@ -1 +1,6 @@
|
||||
*.Backup
|
||||
cli/compiledcircuit.json
|
||||
cli/inputs.json
|
||||
cli/proofs.json
|
||||
cli/test.circuit
|
||||
cli/trustedsetup.json
|
||||
|
||||
51
README.md
51
README.md
@@ -33,6 +33,7 @@ Current implementation status:
|
||||
- [](https://godoc.org/github.com/arnaucube/go-snark/r1csqap) R1CS to QAP (more details: https://github.com/arnaucube/go-snark/tree/master/r1csqap)
|
||||
- [](https://godoc.org/github.com/arnaucube/go-snark/circuitcompiler) Circuit Compiler
|
||||
|
||||
#### Library usage
|
||||
Example:
|
||||
```go
|
||||
// compile circuit and get the R1CS
|
||||
@@ -104,6 +105,56 @@ assert.Nil(t, err)
|
||||
assert.True(t, snark.VerifyProof(circuit, setup, proof))
|
||||
```
|
||||
|
||||
#### CLI usage
|
||||
|
||||
##### Compile circuit
|
||||
Having a circuit file `test.circuit`:
|
||||
```
|
||||
func test(x):
|
||||
aux = x*x
|
||||
y = aux*x
|
||||
z = x + y
|
||||
out = z + 5
|
||||
```
|
||||
And a inputs file `inputs.json`
|
||||
```
|
||||
[
|
||||
3
|
||||
]
|
||||
```
|
||||
|
||||
In the command line, execute:
|
||||
```
|
||||
> go-snark compile test.circuit
|
||||
```
|
||||
|
||||
This will output the `compiledcircuit.json` file.
|
||||
|
||||
##### Trusted Setup
|
||||
Having the `compiledcircuit.json`, now we can generate the `TrustedSetup`:
|
||||
```
|
||||
> go-snark trustedsetup compiledcircuit.json
|
||||
```
|
||||
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`.
|
||||
|
||||
|
||||
##### Generate Proofs
|
||||
Assumming that we have the `compiledcircuit.json` and the `trustedsetup.json`, we can now generate the `Proofs` with the following command:
|
||||
```
|
||||
> go-snark genproofs
|
||||
```
|
||||
|
||||
This will store the file `proofs.json`, that contains all the SNARK proofs.
|
||||
|
||||
##### Verify Proofs
|
||||
Having the `proofs.json`, `compiledcircuit.json`, `trustedsetup.json` files, we can now verify the `Pairings` of the proofs, in order to verify the proofs.
|
||||
```
|
||||
> go-snark verify
|
||||
```
|
||||
This will return a `true` if the proofs are verified, or a `false` if the proofs are not verified.
|
||||
|
||||
|
||||
|
||||
### Test
|
||||
```
|
||||
go test ./... -v
|
||||
|
||||
@@ -144,7 +144,10 @@ func grabVar(signals []string, w []*big.Int, vStr string) *big.Int {
|
||||
}
|
||||
|
||||
// CalculateWitness calculates the Witness of a Circuit based on the given inputs
|
||||
func (circ *Circuit) CalculateWitness(inputs []*big.Int) []*big.Int {
|
||||
func (circ *Circuit) CalculateWitness(inputs []*big.Int) ([]*big.Int, error) {
|
||||
if len(inputs) != len(circ.Inputs) {
|
||||
return []*big.Int{}, errors.New("given inputs != circuit.Inputs")
|
||||
}
|
||||
w := r1csqap.ArrayOfBigZeros(len(circ.Signals))
|
||||
w[0] = big.NewInt(int64(1))
|
||||
for i, input := range inputs {
|
||||
@@ -162,5 +165,5 @@ func (circ *Circuit) CalculateWitness(inputs []*big.Int) []*big.Int {
|
||||
w[indexInArray(circ.Signals, constraint.Out)] = new(big.Int).Div(grabVar(circ.Signals, w, constraint.V1), grabVar(circ.Signals, w, constraint.V2))
|
||||
}
|
||||
}
|
||||
return w
|
||||
return w, nil
|
||||
}
|
||||
|
||||
@@ -78,6 +78,7 @@ func TestCircuitParser(t *testing.T) {
|
||||
b3 := big.NewInt(int64(3))
|
||||
inputs := []*big.Int{b3}
|
||||
// Calculate Witness
|
||||
w := circuit.CalculateWitness(inputs)
|
||||
w, err := circuit.CalculateWitness(inputs)
|
||||
assert.Nil(t, err)
|
||||
fmt.Println("w", w)
|
||||
}
|
||||
|
||||
248
cli/main.go
Normal file
248
cli/main.go
Normal file
@@ -0,0 +1,248 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"bytes"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"log"
|
||||
"math/big"
|
||||
"os"
|
||||
|
||||
snark "github.com/arnaucube/go-snark"
|
||||
"github.com/arnaucube/go-snark/circuitcompiler"
|
||||
"github.com/arnaucube/go-snark/r1csqap"
|
||||
"github.com/urfave/cli"
|
||||
)
|
||||
|
||||
func panicErr(err error) {
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
}
|
||||
|
||||
var commands = []cli.Command{
|
||||
{
|
||||
Name: "compile",
|
||||
Aliases: []string{},
|
||||
Usage: "compile a circuit",
|
||||
Action: CompileCircuit,
|
||||
},
|
||||
{
|
||||
Name: "genproofs",
|
||||
Aliases: []string{},
|
||||
Usage: "generate the snark proofs",
|
||||
Action: GenerateProofs,
|
||||
},
|
||||
{
|
||||
Name: "verify",
|
||||
Aliases: []string{},
|
||||
Usage: "verify the snark proofs",
|
||||
Action: VerifyProofs,
|
||||
},
|
||||
}
|
||||
|
||||
func main() {
|
||||
app := cli.NewApp()
|
||||
app.Name = "go-snarks-cli"
|
||||
app.Version = "0.1.0-alpha"
|
||||
app.Flags = []cli.Flag{
|
||||
cli.StringFlag{Name: "config"},
|
||||
}
|
||||
app.Commands = commands
|
||||
|
||||
err := app.Run(os.Args)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
}
|
||||
|
||||
func CompileCircuit(context *cli.Context) error {
|
||||
fmt.Println("cli")
|
||||
|
||||
// read circuit file
|
||||
circuitFile, err := os.Open("test.circuit")
|
||||
panicErr(err)
|
||||
|
||||
// parse circuit code
|
||||
parser := circuitcompiler.NewParser(bufio.NewReader(circuitFile))
|
||||
circuit, err := parser.Parse()
|
||||
panicErr(err)
|
||||
fmt.Println("\ncircuit data:", circuit)
|
||||
|
||||
// read inputs file
|
||||
inputsFile, err := ioutil.ReadFile("inputs.json")
|
||||
panicErr(err)
|
||||
|
||||
// parse inputs from inputsFile
|
||||
var inputs []*big.Int
|
||||
json.Unmarshal([]byte(string(inputsFile)), &inputs)
|
||||
panicErr(err)
|
||||
|
||||
// calculate wittness
|
||||
w, err := circuit.CalculateWitness(inputs)
|
||||
panicErr(err)
|
||||
fmt.Println("\nwitness", w)
|
||||
|
||||
// flat code to R1CS
|
||||
fmt.Println("\ngenerating R1CS from flat code")
|
||||
a, b, c := circuit.GenerateR1CS()
|
||||
fmt.Println("\nR1CS:")
|
||||
fmt.Println("a:", a)
|
||||
fmt.Println("b:", b)
|
||||
fmt.Println("c:", c)
|
||||
|
||||
// R1CS to QAP
|
||||
alphas, betas, gammas, zx := snark.Utils.PF.R1CSToQAP(a, b, c)
|
||||
fmt.Println("qap")
|
||||
fmt.Println(alphas)
|
||||
fmt.Println(betas)
|
||||
fmt.Println(gammas)
|
||||
|
||||
ax, bx, cx, px := snark.Utils.PF.CombinePolynomials(w, alphas, betas, gammas)
|
||||
|
||||
hx := snark.Utils.PF.DivisorPolynomial(px, zx)
|
||||
|
||||
// hx==px/zx so px==hx*zx
|
||||
// assert.Equal(t, px, snark.Utils.PF.Mul(hx, zx))
|
||||
if !r1csqap.BigArraysEqual(px, snark.Utils.PF.Mul(hx, zx)) {
|
||||
panic(errors.New("px != hx*zx"))
|
||||
}
|
||||
|
||||
// p(x) = a(x) * b(x) - c(x) == h(x) * z(x)
|
||||
abc := snark.Utils.PF.Sub(snark.Utils.PF.Mul(ax, bx), cx)
|
||||
// assert.Equal(t, abc, px)
|
||||
if !r1csqap.BigArraysEqual(abc, px) {
|
||||
panic(errors.New("abc != px"))
|
||||
}
|
||||
hz := snark.Utils.PF.Mul(hx, zx)
|
||||
if !r1csqap.BigArraysEqual(abc, hz) {
|
||||
panic(errors.New("abc != hz"))
|
||||
}
|
||||
// assert.Equal(t, abc, hz)
|
||||
|
||||
div, rem := snark.Utils.PF.Div(px, zx)
|
||||
if !r1csqap.BigArraysEqual(hx, div) {
|
||||
panic(errors.New("hx != div"))
|
||||
}
|
||||
// assert.Equal(t, hx, div)
|
||||
// assert.Equal(t, rem, r1csqap.ArrayOfBigZeros(4))
|
||||
for _, r := range rem {
|
||||
if !bytes.Equal(r.Bytes(), big.NewInt(int64(0)).Bytes()) {
|
||||
panic(errors.New("error:error: px/zx rem not equal to zeros"))
|
||||
}
|
||||
}
|
||||
|
||||
// calculate trusted setup
|
||||
setup, err := snark.GenerateTrustedSetup(len(w), *circuit, alphas, betas, gammas, zx)
|
||||
panicErr(err)
|
||||
fmt.Println("\nt:", setup.Toxic.T)
|
||||
|
||||
// store circuit to json
|
||||
jsonData, err := json.Marshal(circuit)
|
||||
panicErr(err)
|
||||
// store setup into file
|
||||
jsonFile, err := os.Create("compiledcircuit.json")
|
||||
panicErr(err)
|
||||
defer jsonFile.Close()
|
||||
jsonFile.Write(jsonData)
|
||||
jsonFile.Close()
|
||||
fmt.Println("Compiled Circuit data written to ", jsonFile.Name())
|
||||
// store setup to json
|
||||
jsonData, err = json.Marshal(setup)
|
||||
panicErr(err)
|
||||
// store setup into file
|
||||
jsonFile, err = os.Create("trustedsetup.json")
|
||||
panicErr(err)
|
||||
defer jsonFile.Close()
|
||||
jsonFile.Write(jsonData)
|
||||
jsonFile.Close()
|
||||
fmt.Println("Trusted Setup data written to ", jsonFile.Name())
|
||||
return nil
|
||||
}
|
||||
|
||||
func GenerateProofs(context *cli.Context) error {
|
||||
// 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)
|
||||
var trustedsetup snark.Setup
|
||||
json.Unmarshal([]byte(string(trustedsetupFile)), &trustedsetup)
|
||||
panicErr(err)
|
||||
|
||||
// read inputs file
|
||||
inputsFile, err := ioutil.ReadFile("inputs.json")
|
||||
panicErr(err)
|
||||
// parse inputs from inputsFile
|
||||
var inputs []*big.Int
|
||||
json.Unmarshal([]byte(string(inputsFile)), &inputs)
|
||||
panicErr(err)
|
||||
// calculate wittness
|
||||
w, err := circuit.CalculateWitness(inputs)
|
||||
panicErr(err)
|
||||
fmt.Println("\nwitness", w)
|
||||
|
||||
// flat code to R1CS
|
||||
a, b, c := circuit.GenerateR1CS()
|
||||
// R1CS to QAP
|
||||
alphas, betas, gammas, zx := snark.Utils.PF.R1CSToQAP(a, b, c)
|
||||
_, _, _, px := snark.Utils.PF.CombinePolynomials(w, alphas, betas, gammas)
|
||||
hx := snark.Utils.PF.DivisorPolynomial(px, zx)
|
||||
|
||||
proof, err := snark.GenerateProofs(circuit, trustedsetup, hx, w)
|
||||
panicErr(err)
|
||||
|
||||
fmt.Println("\n proofs:")
|
||||
fmt.Println(proof)
|
||||
|
||||
// store proofs to json
|
||||
jsonData, err := json.Marshal(proof)
|
||||
panicErr(err)
|
||||
// store proof into file
|
||||
jsonFile, err := os.Create("proofs.json")
|
||||
panicErr(err)
|
||||
defer jsonFile.Close()
|
||||
jsonFile.Write(jsonData)
|
||||
jsonFile.Close()
|
||||
fmt.Println("Proofs data written to ", jsonFile.Name())
|
||||
return nil
|
||||
}
|
||||
|
||||
func VerifyProofs(context *cli.Context) error {
|
||||
// open proofs.json
|
||||
proofsFile, err := ioutil.ReadFile("proofs.json")
|
||||
panicErr(err)
|
||||
var proof snark.Proof
|
||||
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)
|
||||
var trustedsetup snark.Setup
|
||||
json.Unmarshal([]byte(string(trustedsetupFile)), &trustedsetup)
|
||||
panicErr(err)
|
||||
|
||||
verified := snark.VerifyProof(circuit, trustedsetup, proof, true)
|
||||
if !verified {
|
||||
fmt.Println("ERROR: proofs not verified")
|
||||
} else {
|
||||
fmt.Println("Proofs verified")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
@@ -143,10 +143,13 @@ func BigIsOdd(n *big.Int) bool {
|
||||
}
|
||||
|
||||
func (fq12 Fq12) Exp(base [2][3][2]*big.Int, e *big.Int) [2][3][2]*big.Int {
|
||||
// TODO fix bottleneck
|
||||
|
||||
res := fq12.One()
|
||||
rem := fq12.Fq2.F.Copy(e)
|
||||
exp := base
|
||||
|
||||
// before := time.Now()
|
||||
for !bytes.Equal(rem.Bytes(), big.NewInt(int64(0)).Bytes()) {
|
||||
if BigIsOdd(rem) {
|
||||
res = fq12.Mul(res, exp)
|
||||
@@ -154,6 +157,7 @@ func (fq12 Fq12) Exp(base [2][3][2]*big.Int, e *big.Int) [2][3][2]*big.Int {
|
||||
exp = fq12.Square(exp)
|
||||
rem = new(big.Int).Rsh(rem, 1)
|
||||
}
|
||||
// fmt.Println("time elapsed:", time.Since(before))
|
||||
return res
|
||||
}
|
||||
func (fq12 Fq12) Affine(a [2][3][2]*big.Int) [2][3][2]*big.Int {
|
||||
|
||||
1
go.mod
1
go.mod
@@ -4,4 +4,5 @@ require (
|
||||
github.com/davecgh/go-spew v1.1.1 // indirect
|
||||
github.com/pmezard/go-difflib v1.0.0 // indirect
|
||||
github.com/stretchr/testify v1.2.2
|
||||
github.com/urfave/cli v1.20.0
|
||||
)
|
||||
|
||||
2
go.sum
2
go.sum
@@ -4,3 +4,5 @@ github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZb
|
||||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||
github.com/stretchr/testify v1.2.2 h1:bSDNvY7ZPG5RlJ8otE/7V6gMiyenm9RtJ7IUVIAoJ1w=
|
||||
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
|
||||
github.com/urfave/cli v1.20.0 h1:fDqGv3UG/4jbVl/QkFwEdddtEDjh/5Ov6X+0B/3bPaw=
|
||||
github.com/urfave/cli v1.20.0/go.mod h1:70zkFmudgCuE/ngEzBv17Jvp/497gISqfk5gWijbERA=
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package r1csqap
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"math/big"
|
||||
|
||||
"github.com/arnaucube/go-snark/fields"
|
||||
@@ -28,6 +29,17 @@ func ArrayOfBigZeros(num int) []*big.Int {
|
||||
}
|
||||
return r
|
||||
}
|
||||
func BigArraysEqual(a, b []*big.Int) bool {
|
||||
if len(a) != len(b) {
|
||||
return false
|
||||
}
|
||||
for i := 0; i < len(a); i++ {
|
||||
if !bytes.Equal(a[i].Bytes(), b[i].Bytes()) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
// PolynomialField is the Polynomial over a Finite Field where the polynomial operations are performed
|
||||
type PolynomialField struct {
|
||||
|
||||
22
snark.go
22
snark.go
@@ -237,14 +237,16 @@ func GenerateProofs(circuit circuitcompiler.Circuit, setup Setup, hx []*big.Int,
|
||||
}
|
||||
|
||||
// VerifyProof verifies over the BN128 the Pairings of the Proof
|
||||
func VerifyProof(circuit circuitcompiler.Circuit, setup Setup, proof Proof) bool {
|
||||
func VerifyProof(circuit circuitcompiler.Circuit, setup Setup, proof Proof, printVer bool) bool {
|
||||
// e(piA, Va) == e(piA', g2)
|
||||
pairingPiaVa := Utils.Bn.Pairing(proof.PiA, setup.Vk.Vka)
|
||||
pairingPiapG2 := Utils.Bn.Pairing(proof.PiAp, Utils.Bn.G2.G)
|
||||
if !Utils.Bn.Fq12.Equal(pairingPiaVa, pairingPiapG2) {
|
||||
return false
|
||||
}
|
||||
fmt.Println("✓ e(piA, Va) == e(piA', g2), valid knowledge commitment for A")
|
||||
if printVer {
|
||||
fmt.Println("✓ e(piA, Va) == e(piA', g2), valid knowledge commitment for A")
|
||||
}
|
||||
|
||||
// e(Vb, piB) == e(piB', g2)
|
||||
pairingVbPib := Utils.Bn.Pairing(setup.Vk.Vkb, proof.PiB)
|
||||
@@ -252,7 +254,9 @@ func VerifyProof(circuit circuitcompiler.Circuit, setup Setup, proof Proof) bool
|
||||
if !Utils.Bn.Fq12.Equal(pairingVbPib, pairingPibpG2) {
|
||||
return false
|
||||
}
|
||||
fmt.Println("✓ e(Vb, piB) == e(piB', g2), valid knowledge commitment for B")
|
||||
if printVer {
|
||||
fmt.Println("✓ e(Vb, piB) == e(piB', g2), valid knowledge commitment for B")
|
||||
}
|
||||
|
||||
// e(piC, Vc) == e(piC', g2)
|
||||
pairingPicVc := Utils.Bn.Pairing(proof.PiC, setup.Vk.Vkc)
|
||||
@@ -260,7 +264,9 @@ func VerifyProof(circuit circuitcompiler.Circuit, setup Setup, proof Proof) bool
|
||||
if !Utils.Bn.Fq12.Equal(pairingPicVc, pairingPicpG2) {
|
||||
return false
|
||||
}
|
||||
fmt.Println("✓ e(piC, Vc) == e(piC', g2), valid knowledge commitment for C")
|
||||
if printVer {
|
||||
fmt.Println("✓ e(piC, Vc) == e(piC', g2), valid knowledge commitment for C")
|
||||
}
|
||||
|
||||
// Vkx, to then calculate Vkx+piA
|
||||
vkxpia := setup.Vk.A[0]
|
||||
@@ -276,7 +282,9 @@ func VerifyProof(circuit circuitcompiler.Circuit, setup Setup, proof Proof) bool
|
||||
Utils.Bn.Pairing(proof.PiC, Utils.Bn.G2.G))) {
|
||||
return false
|
||||
}
|
||||
fmt.Println("✓ e(Vkx+piA, piB) == e(piH, Vkz) * e(piC, g2), QAP disibility checked")
|
||||
if printVer {
|
||||
fmt.Println("✓ e(Vkx+piA, piB) == e(piH, Vkz) * e(piC, g2), QAP disibility checked")
|
||||
}
|
||||
|
||||
// e(Vkx+piA+piC, g2KbetaKgamma) * e(g1KbetaKgamma, piB)
|
||||
// == e(piK, g2Kgamma)
|
||||
@@ -288,7 +296,9 @@ func VerifyProof(circuit circuitcompiler.Circuit, setup Setup, proof Proof) bool
|
||||
if !Utils.Bn.Fq12.Equal(pairingL, pairingR) {
|
||||
return false
|
||||
}
|
||||
fmt.Println("✓ e(Vkx+piA+piC, g2KbetaKgamma) * e(g1KbetaKgamma, piB) == e(piK, g2Kgamma)")
|
||||
if printVer {
|
||||
fmt.Println("✓ e(Vkx+piA+piC, g2KbetaKgamma) * e(g1KbetaKgamma, piB) == e(piK, g2Kgamma)")
|
||||
}
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
@@ -34,7 +34,8 @@ func TestZkFromFlatCircuitCode(t *testing.T) {
|
||||
b3 := big.NewInt(int64(3))
|
||||
inputs := []*big.Int{b3}
|
||||
// wittness
|
||||
w := circuit.CalculateWitness(inputs)
|
||||
w, err := circuit.CalculateWitness(inputs)
|
||||
assert.Nil(t, err)
|
||||
fmt.Println("\nwitness", w)
|
||||
|
||||
// flat code to R1CS
|
||||
@@ -81,7 +82,7 @@ func TestZkFromFlatCircuitCode(t *testing.T) {
|
||||
fmt.Println("\n proofs:")
|
||||
fmt.Println(proof)
|
||||
before := time.Now()
|
||||
assert.True(t, VerifyProof(*circuit, setup, proof))
|
||||
assert.True(t, VerifyProof(*circuit, setup, proof, false))
|
||||
fmt.Println("verify proof time elapsed:", time.Since(before))
|
||||
}
|
||||
|
||||
@@ -142,11 +143,64 @@ func TestZkFromHardcodedR1CS(t *testing.T) {
|
||||
// calculate trusted setup
|
||||
setup, err := GenerateTrustedSetup(len(w), circuit, alphas, betas, gammas, zx)
|
||||
assert.Nil(t, err)
|
||||
fmt.Println("t", setup.Toxic.T)
|
||||
|
||||
// piA = g1 * A(t), piB = g2 * B(t), piC = g1 * C(t), piH = g1 * H(t)
|
||||
proof, err := GenerateProofs(circuit, setup, hx, w)
|
||||
assert.Nil(t, err)
|
||||
|
||||
assert.True(t, VerifyProof(circuit, setup, proof))
|
||||
assert.True(t, VerifyProof(circuit, setup, proof, true))
|
||||
}
|
||||
|
||||
func TestZkMultiplication(t *testing.T) {
|
||||
|
||||
// compile circuit and get the R1CS
|
||||
flatCode := `
|
||||
func test(a, b):
|
||||
out = a * b
|
||||
`
|
||||
|
||||
// parse the code
|
||||
parser := circuitcompiler.NewParser(strings.NewReader(flatCode))
|
||||
circuit, err := parser.Parse()
|
||||
assert.Nil(t, err)
|
||||
|
||||
b3 := big.NewInt(int64(3))
|
||||
b4 := big.NewInt(int64(4))
|
||||
inputs := []*big.Int{b3, b4}
|
||||
// wittness
|
||||
w, err := circuit.CalculateWitness(inputs)
|
||||
assert.Nil(t, err)
|
||||
|
||||
// flat code to R1CS
|
||||
a, b, c := circuit.GenerateR1CS()
|
||||
|
||||
// R1CS to QAP
|
||||
alphas, betas, gammas, zx := Utils.PF.R1CSToQAP(a, b, c)
|
||||
|
||||
ax, bx, cx, px := Utils.PF.CombinePolynomials(w, alphas, betas, gammas)
|
||||
|
||||
hx := Utils.PF.DivisorPolynomial(px, zx)
|
||||
|
||||
// hx==px/zx so px==hx*zx
|
||||
assert.Equal(t, px, Utils.PF.Mul(hx, zx))
|
||||
|
||||
// p(x) = a(x) * b(x) - c(x) == h(x) * z(x)
|
||||
abc := Utils.PF.Sub(Utils.PF.Mul(ax, bx), cx)
|
||||
assert.Equal(t, abc, px)
|
||||
hz := Utils.PF.Mul(hx, zx)
|
||||
assert.Equal(t, abc, hz)
|
||||
|
||||
div, rem := Utils.PF.Div(px, zx)
|
||||
assert.Equal(t, hx, div)
|
||||
assert.Equal(t, rem, r1csqap.ArrayOfBigZeros(1))
|
||||
|
||||
// calculate trusted setup
|
||||
setup, err := GenerateTrustedSetup(len(w), *circuit, alphas, betas, gammas, zx)
|
||||
assert.Nil(t, err)
|
||||
|
||||
// piA = g1 * A(t), piB = g2 * B(t), piC = g1 * C(t), piH = g1 * H(t)
|
||||
proof, err := GenerateProofs(*circuit, setup, hx, w)
|
||||
assert.Nil(t, err)
|
||||
|
||||
assert.True(t, VerifyProof(*circuit, setup, proof, false))
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user