mirror of
https://github.com/arnaucube/go-snark-study.git
synced 2026-02-02 17:26:41 +01:00
circuit output in proof.PublicSignals for proof verification
This commit is contained in:
24
README.md
24
README.md
@@ -26,14 +26,14 @@ Current implementation status:
|
|||||||
- [x] verify proofs with BN128 pairing
|
- [x] verify proofs with BN128 pairing
|
||||||
|
|
||||||
|
|
||||||
### Usage
|
## Usage
|
||||||
- [](https://godoc.org/github.com/arnaucube/go-snark) zkSnark
|
- [](https://godoc.org/github.com/arnaucube/go-snark) zkSnark
|
||||||
- [](https://godoc.org/github.com/arnaucube/go-snark/bn128) bn128 (more details: https://github.com/arnaucube/go-snark/tree/master/bn128)
|
- [](https://godoc.org/github.com/arnaucube/go-snark/bn128) bn128 (more details: https://github.com/arnaucube/go-snark/tree/master/bn128)
|
||||||
- [](https://godoc.org/github.com/arnaucube/go-snark/fields) Finite Fields operations
|
- [](https://godoc.org/github.com/arnaucube/go-snark/fields) Finite Fields operations
|
||||||
- [](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/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
|
- [](https://godoc.org/github.com/arnaucube/go-snark/circuitcompiler) Circuit Compiler
|
||||||
|
|
||||||
#### Library usage
|
### Library usage
|
||||||
Example:
|
Example:
|
||||||
```go
|
```go
|
||||||
// compile circuit and get the R1CS
|
// compile circuit and get the R1CS
|
||||||
@@ -105,9 +105,9 @@ assert.Nil(t, err)
|
|||||||
assert.True(t, snark.VerifyProof(circuit, setup, proof))
|
assert.True(t, snark.VerifyProof(circuit, setup, proof))
|
||||||
```
|
```
|
||||||
|
|
||||||
#### CLI usage
|
### CLI usage
|
||||||
|
|
||||||
##### Compile circuit
|
#### Compile circuit
|
||||||
Having a circuit file `test.circuit`:
|
Having a circuit file `test.circuit`:
|
||||||
```
|
```
|
||||||
func test(x):
|
func test(x):
|
||||||
@@ -125,37 +125,37 @@ And a inputs file `inputs.json`
|
|||||||
|
|
||||||
In the command line, execute:
|
In the command line, execute:
|
||||||
```
|
```
|
||||||
> go-snark compile test.circuit
|
> go-snark-cli compile test.circuit
|
||||||
```
|
```
|
||||||
|
|
||||||
This will output the `compiledcircuit.json` file.
|
This will output the `compiledcircuit.json` file.
|
||||||
|
|
||||||
##### Trusted Setup
|
#### Trusted Setup
|
||||||
Having the `compiledcircuit.json`, now we can generate the `TrustedSetup`:
|
Having the `compiledcircuit.json`, now we can generate the `TrustedSetup`:
|
||||||
```
|
```
|
||||||
> go-snark trustedsetup compiledcircuit.json
|
> go-snark-cli 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`.
|
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
|
#### Generate Proofs
|
||||||
Assumming that we have the `compiledcircuit.json` and the `trustedsetup.json`, we can now generate the `Proofs` with the following command:
|
Assumming that we have the `compiledcircuit.json` and the `trustedsetup.json`, we can now generate the `Proofs` with the following command:
|
||||||
```
|
```
|
||||||
> go-snark genproofs
|
> go-snark-cli genproofs
|
||||||
```
|
```
|
||||||
|
|
||||||
This will store the file `proofs.json`, that contains all the SNARK proofs.
|
This will store the file `proofs.json`, that contains all the SNARK proofs.
|
||||||
|
|
||||||
##### Verify 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.
|
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
|
> go-snark-cli verify
|
||||||
```
|
```
|
||||||
This will return a `true` if the proofs are verified, or a `false` if the proofs are not verified.
|
This will return a `true` if the proofs are verified, or a `false` if the proofs are not verified.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
### Test
|
## Test
|
||||||
```
|
```
|
||||||
go test ./... -v
|
go test ./... -v
|
||||||
```
|
```
|
||||||
|
|||||||
@@ -10,14 +10,15 @@ import (
|
|||||||
|
|
||||||
// Circuit is the data structure of the compiled circuit
|
// Circuit is the data structure of the compiled circuit
|
||||||
type Circuit struct {
|
type Circuit struct {
|
||||||
NVars int
|
NVars int
|
||||||
NPublic int
|
NPublic int
|
||||||
NSignals int
|
NSignals int
|
||||||
Inputs []string
|
Inputs []string
|
||||||
Signals []string
|
Signals []string
|
||||||
Witness []*big.Int
|
PublicSignals []string
|
||||||
Constraints []Constraint
|
Witness []*big.Int
|
||||||
R1CS struct {
|
Constraints []Constraint
|
||||||
|
R1CS struct {
|
||||||
A [][]*big.Int
|
A [][]*big.Int
|
||||||
B [][]*big.Int
|
B [][]*big.Int
|
||||||
C [][]*big.Int
|
C [][]*big.Int
|
||||||
@@ -151,7 +152,7 @@ func (circ *Circuit) CalculateWitness(inputs []*big.Int) ([]*big.Int, error) {
|
|||||||
w := r1csqap.ArrayOfBigZeros(len(circ.Signals))
|
w := r1csqap.ArrayOfBigZeros(len(circ.Signals))
|
||||||
w[0] = big.NewInt(int64(1))
|
w[0] = big.NewInt(int64(1))
|
||||||
for i, input := range inputs {
|
for i, input := range inputs {
|
||||||
w[i+1] = input
|
w[i+2] = input
|
||||||
}
|
}
|
||||||
for _, constraint := range circ.Constraints {
|
for _, constraint := range circ.Constraints {
|
||||||
if constraint.Op == "in" {
|
if constraint.Op == "in" {
|
||||||
|
|||||||
@@ -50,14 +50,14 @@ func TestCircuitParser(t *testing.T) {
|
|||||||
b1 := big.NewInt(int64(1))
|
b1 := big.NewInt(int64(1))
|
||||||
b5 := big.NewInt(int64(5))
|
b5 := big.NewInt(int64(5))
|
||||||
aExpected := [][]*big.Int{
|
aExpected := [][]*big.Int{
|
||||||
[]*big.Int{b0, b1, b0, b0, b0, b0},
|
[]*big.Int{b0, b0, b1, b0, b0, b0},
|
||||||
[]*big.Int{b0, b0, b0, b1, b0, b0},
|
[]*big.Int{b0, b0, b0, b1, b0, b0},
|
||||||
[]*big.Int{b0, b1, b0, b0, b1, b0},
|
[]*big.Int{b0, b0, b1, b0, b1, b0},
|
||||||
[]*big.Int{b5, b0, b0, b0, b0, b1},
|
[]*big.Int{b5, b0, b0, b0, b0, b1},
|
||||||
}
|
}
|
||||||
bExpected := [][]*big.Int{
|
bExpected := [][]*big.Int{
|
||||||
[]*big.Int{b0, b1, b0, b0, b0, b0},
|
[]*big.Int{b0, b0, b1, b0, b0, b0},
|
||||||
[]*big.Int{b0, b1, b0, b0, b0, b0},
|
[]*big.Int{b0, b0, b1, b0, b0, b0},
|
||||||
[]*big.Int{b1, b0, b0, b0, b0, b0},
|
[]*big.Int{b1, b0, b0, b0, b0, b0},
|
||||||
[]*big.Int{b1, b0, b0, b0, b0, b0},
|
[]*big.Int{b1, b0, b0, b0, b0, b0},
|
||||||
}
|
}
|
||||||
@@ -65,7 +65,7 @@ func TestCircuitParser(t *testing.T) {
|
|||||||
[]*big.Int{b0, b0, b0, b1, b0, b0},
|
[]*big.Int{b0, b0, b0, b1, b0, b0},
|
||||||
[]*big.Int{b0, b0, b0, b0, b1, b0},
|
[]*big.Int{b0, b0, b0, b0, b1, b0},
|
||||||
[]*big.Int{b0, b0, b0, b0, b0, b1},
|
[]*big.Int{b0, b0, b0, b0, b0, b1},
|
||||||
[]*big.Int{b0, b0, b1, b0, b0, b0},
|
[]*big.Int{b0, b1, b0, b0, b0, b0},
|
||||||
}
|
}
|
||||||
|
|
||||||
assert.Equal(t, aExpected, a)
|
assert.Equal(t, aExpected, a)
|
||||||
|
|||||||
@@ -147,14 +147,16 @@ func (p *Parser) Parse() (*Circuit, error) {
|
|||||||
circuit.Signals = addToArrayIfNotExist(circuit.Signals, constraint.V2)
|
circuit.Signals = addToArrayIfNotExist(circuit.Signals, constraint.V2)
|
||||||
}
|
}
|
||||||
if constraint.Out == "out" {
|
if constraint.Out == "out" {
|
||||||
// if Out is "out", put it after the inputs
|
// if Out is "out", put it after first value (one) and before the inputs
|
||||||
if !existInArray(circuit.Signals, constraint.Out) {
|
if !existInArray(circuit.Signals, constraint.Out) {
|
||||||
signalsCopy := copyArray(circuit.Signals)
|
signalsCopy := copyArray(circuit.Signals)
|
||||||
var auxSignals []string
|
var auxSignals []string
|
||||||
auxSignals = append(auxSignals, signalsCopy[0:nInputs+1]...)
|
auxSignals = append(auxSignals, signalsCopy[0])
|
||||||
auxSignals = append(auxSignals, constraint.Out)
|
auxSignals = append(auxSignals, constraint.Out)
|
||||||
auxSignals = append(auxSignals, signalsCopy[nInputs+1:]...)
|
auxSignals = append(auxSignals, signalsCopy[1:]...)
|
||||||
circuit.Signals = auxSignals
|
circuit.Signals = auxSignals
|
||||||
|
circuit.PublicSignals = append(circuit.PublicSignals, constraint.Out)
|
||||||
|
circuit.NPublic++
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
circuit.Signals = addToArrayIfNotExist(circuit.Signals, constraint.Out)
|
circuit.Signals = addToArrayIfNotExist(circuit.Signals, constraint.Out)
|
||||||
@@ -162,7 +164,6 @@ func (p *Parser) Parse() (*Circuit, error) {
|
|||||||
}
|
}
|
||||||
circuit.NVars = len(circuit.Signals)
|
circuit.NVars = len(circuit.Signals)
|
||||||
circuit.NSignals = len(circuit.Signals)
|
circuit.NSignals = len(circuit.Signals)
|
||||||
circuit.NPublic = 0
|
|
||||||
return circuit, nil
|
return circuit, nil
|
||||||
}
|
}
|
||||||
func copyArray(in []string) []string { // tmp
|
func copyArray(in []string) []string { // tmp
|
||||||
|
|||||||
BIN
cli/go-snark-cli
Executable file
BIN
cli/go-snark-cli
Executable file
Binary file not shown.
15
cli/main.go
15
cli/main.go
@@ -62,8 +62,10 @@ func main() {
|
|||||||
func CompileCircuit(context *cli.Context) error {
|
func CompileCircuit(context *cli.Context) error {
|
||||||
fmt.Println("cli")
|
fmt.Println("cli")
|
||||||
|
|
||||||
|
circuitPath := context.Args().Get(0)
|
||||||
|
|
||||||
// read circuit file
|
// read circuit file
|
||||||
circuitFile, err := os.Open("test.circuit")
|
circuitFile, err := os.Open(circuitPath)
|
||||||
panicErr(err)
|
panicErr(err)
|
||||||
|
|
||||||
// parse circuit code
|
// parse circuit code
|
||||||
@@ -150,8 +152,16 @@ func CompileCircuit(context *cli.Context) error {
|
|||||||
jsonFile.Write(jsonData)
|
jsonFile.Write(jsonData)
|
||||||
jsonFile.Close()
|
jsonFile.Close()
|
||||||
fmt.Println("Compiled Circuit data written to ", jsonFile.Name())
|
fmt.Println("Compiled Circuit data written to ", jsonFile.Name())
|
||||||
|
|
||||||
|
// remove setup.Toxic
|
||||||
|
var tsetup snark.Setup
|
||||||
|
tsetup.Pk = setup.Pk
|
||||||
|
tsetup.Vk = setup.Vk
|
||||||
|
tsetup.G1T = setup.G1T
|
||||||
|
tsetup.G2T = setup.G2T
|
||||||
|
|
||||||
// store setup to json
|
// store setup to json
|
||||||
jsonData, err = json.Marshal(setup)
|
jsonData, err = json.Marshal(tsetup)
|
||||||
panicErr(err)
|
panicErr(err)
|
||||||
// store setup into file
|
// store setup into file
|
||||||
jsonFile, err = os.Create("trustedsetup.json")
|
jsonFile, err = os.Create("trustedsetup.json")
|
||||||
@@ -202,6 +212,7 @@ func GenerateProofs(context *cli.Context) error {
|
|||||||
|
|
||||||
fmt.Println("\n proofs:")
|
fmt.Println("\n proofs:")
|
||||||
fmt.Println(proof)
|
fmt.Println(proof)
|
||||||
|
fmt.Println("public signals:", proof.PublicSignals)
|
||||||
|
|
||||||
// store proofs to json
|
// store proofs to json
|
||||||
jsonData, err := json.Marshal(proof)
|
jsonData, err := json.Marshal(proof)
|
||||||
|
|||||||
4
snark.go
4
snark.go
@@ -231,7 +231,7 @@ func GenerateProofs(circuit circuitcompiler.Circuit, setup Setup, hx []*big.Int,
|
|||||||
for i := 0; i < len(hx); i++ {
|
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(setup.G1T[i], hx[i]))
|
||||||
}
|
}
|
||||||
proof.PublicSignals = w[1 : circuit.NPublic+1]
|
proof.PublicSignals = w[1:2] // out signal
|
||||||
|
|
||||||
return proof, nil
|
return proof, nil
|
||||||
}
|
}
|
||||||
@@ -270,7 +270,7 @@ func VerifyProof(circuit circuitcompiler.Circuit, setup Setup, proof Proof, prin
|
|||||||
|
|
||||||
// Vkx, to then calculate Vkx+piA
|
// Vkx, to then calculate Vkx+piA
|
||||||
vkxpia := setup.Vk.A[0]
|
vkxpia := setup.Vk.A[0]
|
||||||
for i := 0; i < circuit.NPublic; i++ {
|
for i := 0; i < len(proof.PublicSignals); i++ {
|
||||||
vkxpia = Utils.Bn.G1.Add(vkxpia, Utils.Bn.G1.MulScalar(setup.Vk.A[i+1], proof.PublicSignals[i]))
|
vkxpia = Utils.Bn.G1.Add(vkxpia, Utils.Bn.G1.MulScalar(setup.Vk.A[i+1], proof.PublicSignals[i]))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -81,13 +81,13 @@ func TestZkFromFlatCircuitCode(t *testing.T) {
|
|||||||
|
|
||||||
fmt.Println("\n proofs:")
|
fmt.Println("\n proofs:")
|
||||||
fmt.Println(proof)
|
fmt.Println(proof)
|
||||||
|
fmt.Println("public signals:", proof.PublicSignals)
|
||||||
before := time.Now()
|
before := time.Now()
|
||||||
assert.True(t, VerifyProof(*circuit, setup, proof, false))
|
assert.True(t, VerifyProof(*circuit, setup, proof, true))
|
||||||
fmt.Println("verify proof time elapsed:", time.Since(before))
|
fmt.Println("verify proof time elapsed:", time.Since(before))
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestZkFromHardcodedR1CS(t *testing.T) {
|
func TestZkFromHardcodedR1CS(t *testing.T) {
|
||||||
|
|
||||||
b0 := big.NewInt(int64(0))
|
b0 := big.NewInt(int64(0))
|
||||||
b1 := big.NewInt(int64(1))
|
b1 := big.NewInt(int64(1))
|
||||||
b3 := big.NewInt(int64(3))
|
b3 := big.NewInt(int64(3))
|
||||||
@@ -97,14 +97,14 @@ func TestZkFromHardcodedR1CS(t *testing.T) {
|
|||||||
b30 := big.NewInt(int64(30))
|
b30 := big.NewInt(int64(30))
|
||||||
b35 := big.NewInt(int64(35))
|
b35 := big.NewInt(int64(35))
|
||||||
a := [][]*big.Int{
|
a := [][]*big.Int{
|
||||||
[]*big.Int{b0, b1, b0, b0, b0, b0},
|
[]*big.Int{b0, b0, b1, b0, b0, b0},
|
||||||
[]*big.Int{b0, b0, b0, b1, b0, b0},
|
[]*big.Int{b0, b0, b0, b1, b0, b0},
|
||||||
[]*big.Int{b0, b1, b0, b0, b1, b0},
|
[]*big.Int{b0, b0, b1, b0, b1, b0},
|
||||||
[]*big.Int{b5, b0, b0, b0, b0, b1},
|
[]*big.Int{b5, b0, b0, b0, b0, b1},
|
||||||
}
|
}
|
||||||
b := [][]*big.Int{
|
b := [][]*big.Int{
|
||||||
[]*big.Int{b0, b1, b0, b0, b0, b0},
|
[]*big.Int{b0, b0, b1, b0, b0, b0},
|
||||||
[]*big.Int{b0, b1, b0, b0, b0, b0},
|
[]*big.Int{b0, b0, b1, b0, b0, b0},
|
||||||
[]*big.Int{b1, b0, b0, b0, b0, b0},
|
[]*big.Int{b1, b0, b0, b0, b0, b0},
|
||||||
[]*big.Int{b1, b0, b0, b0, b0, b0},
|
[]*big.Int{b1, b0, b0, b0, b0, b0},
|
||||||
}
|
}
|
||||||
@@ -112,15 +112,15 @@ func TestZkFromHardcodedR1CS(t *testing.T) {
|
|||||||
[]*big.Int{b0, b0, b0, b1, b0, b0},
|
[]*big.Int{b0, b0, b0, b1, b0, b0},
|
||||||
[]*big.Int{b0, b0, b0, b0, b1, b0},
|
[]*big.Int{b0, b0, b0, b0, b1, b0},
|
||||||
[]*big.Int{b0, b0, b0, b0, b0, b1},
|
[]*big.Int{b0, b0, b0, b0, b0, b1},
|
||||||
[]*big.Int{b0, b0, b1, b0, b0, b0},
|
[]*big.Int{b0, b1, b0, b0, b0, b0},
|
||||||
}
|
}
|
||||||
alphas, betas, gammas, zx := Utils.PF.R1CSToQAP(a, b, c)
|
alphas, betas, gammas, zx := Utils.PF.R1CSToQAP(a, b, c)
|
||||||
|
|
||||||
// wittness = 1, 3, 35, 9, 27, 30
|
// wittness = 1, 35, 3, 9, 27, 30
|
||||||
w := []*big.Int{b1, b3, b35, b9, b27, b30}
|
w := []*big.Int{b1, b35, b3, b9, b27, b30}
|
||||||
circuit := circuitcompiler.Circuit{
|
circuit := circuitcompiler.Circuit{
|
||||||
NVars: 6,
|
NVars: 6,
|
||||||
NPublic: 0,
|
NPublic: 1,
|
||||||
NSignals: len(w),
|
NSignals: len(w),
|
||||||
}
|
}
|
||||||
ax, bx, cx, px := Utils.PF.CombinePolynomials(w, alphas, betas, gammas)
|
ax, bx, cx, px := Utils.PF.CombinePolynomials(w, alphas, betas, gammas)
|
||||||
|
|||||||
Reference in New Issue
Block a user