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
|
||||
|
||||
|
||||
### Usage
|
||||
## Usage
|
||||
- [](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/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/circuitcompiler) Circuit Compiler
|
||||
|
||||
#### Library usage
|
||||
### Library usage
|
||||
Example:
|
||||
```go
|
||||
// compile circuit and get the R1CS
|
||||
@@ -105,9 +105,9 @@ assert.Nil(t, err)
|
||||
assert.True(t, snark.VerifyProof(circuit, setup, proof))
|
||||
```
|
||||
|
||||
#### CLI usage
|
||||
### CLI usage
|
||||
|
||||
##### Compile circuit
|
||||
#### Compile circuit
|
||||
Having a circuit file `test.circuit`:
|
||||
```
|
||||
func test(x):
|
||||
@@ -125,37 +125,37 @@ And a inputs file `inputs.json`
|
||||
|
||||
In the command line, execute:
|
||||
```
|
||||
> go-snark compile test.circuit
|
||||
> go-snark-cli compile test.circuit
|
||||
```
|
||||
|
||||
This will output the `compiledcircuit.json` file.
|
||||
|
||||
##### Trusted Setup
|
||||
#### Trusted Setup
|
||||
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`.
|
||||
|
||||
|
||||
##### 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:
|
||||
```
|
||||
> go-snark genproofs
|
||||
> go-snark-cli genproofs
|
||||
```
|
||||
|
||||
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.
|
||||
```
|
||||
> 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.
|
||||
|
||||
|
||||
|
||||
### Test
|
||||
## Test
|
||||
```
|
||||
go test ./... -v
|
||||
```
|
||||
|
||||
@@ -10,14 +10,15 @@ import (
|
||||
|
||||
// Circuit is the data structure of the compiled circuit
|
||||
type Circuit struct {
|
||||
NVars int
|
||||
NPublic int
|
||||
NSignals int
|
||||
Inputs []string
|
||||
Signals []string
|
||||
Witness []*big.Int
|
||||
Constraints []Constraint
|
||||
R1CS struct {
|
||||
NVars int
|
||||
NPublic int
|
||||
NSignals int
|
||||
Inputs []string
|
||||
Signals []string
|
||||
PublicSignals []string
|
||||
Witness []*big.Int
|
||||
Constraints []Constraint
|
||||
R1CS struct {
|
||||
A [][]*big.Int
|
||||
B [][]*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[0] = big.NewInt(int64(1))
|
||||
for i, input := range inputs {
|
||||
w[i+1] = input
|
||||
w[i+2] = input
|
||||
}
|
||||
for _, constraint := range circ.Constraints {
|
||||
if constraint.Op == "in" {
|
||||
|
||||
@@ -50,14 +50,14 @@ func TestCircuitParser(t *testing.T) {
|
||||
b1 := big.NewInt(int64(1))
|
||||
b5 := big.NewInt(int64(5))
|
||||
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, b1, b0, b0, b1, b0},
|
||||
[]*big.Int{b0, b0, b1, b0, b1, b0},
|
||||
[]*big.Int{b5, b0, b0, b0, b0, b1},
|
||||
}
|
||||
bExpected := [][]*big.Int{
|
||||
[]*big.Int{b0, b1, b0, b0, b0, b0},
|
||||
[]*big.Int{b0, b1, b0, b0, b0, b0},
|
||||
[]*big.Int{b0, b0, b1, 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},
|
||||
}
|
||||
@@ -65,7 +65,7 @@ func TestCircuitParser(t *testing.T) {
|
||||
[]*big.Int{b0, b0, b0, b1, b0, b0},
|
||||
[]*big.Int{b0, b0, b0, b0, b1, b0},
|
||||
[]*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)
|
||||
|
||||
@@ -147,14 +147,16 @@ func (p *Parser) Parse() (*Circuit, error) {
|
||||
circuit.Signals = addToArrayIfNotExist(circuit.Signals, constraint.V2)
|
||||
}
|
||||
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) {
|
||||
signalsCopy := copyArray(circuit.Signals)
|
||||
var auxSignals []string
|
||||
auxSignals = append(auxSignals, signalsCopy[0:nInputs+1]...)
|
||||
auxSignals = append(auxSignals, signalsCopy[0])
|
||||
auxSignals = append(auxSignals, constraint.Out)
|
||||
auxSignals = append(auxSignals, signalsCopy[nInputs+1:]...)
|
||||
auxSignals = append(auxSignals, signalsCopy[1:]...)
|
||||
circuit.Signals = auxSignals
|
||||
circuit.PublicSignals = append(circuit.PublicSignals, constraint.Out)
|
||||
circuit.NPublic++
|
||||
}
|
||||
} else {
|
||||
circuit.Signals = addToArrayIfNotExist(circuit.Signals, constraint.Out)
|
||||
@@ -162,7 +164,6 @@ func (p *Parser) Parse() (*Circuit, error) {
|
||||
}
|
||||
circuit.NVars = len(circuit.Signals)
|
||||
circuit.NSignals = len(circuit.Signals)
|
||||
circuit.NPublic = 0
|
||||
return circuit, nil
|
||||
}
|
||||
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 {
|
||||
fmt.Println("cli")
|
||||
|
||||
circuitPath := context.Args().Get(0)
|
||||
|
||||
// read circuit file
|
||||
circuitFile, err := os.Open("test.circuit")
|
||||
circuitFile, err := os.Open(circuitPath)
|
||||
panicErr(err)
|
||||
|
||||
// parse circuit code
|
||||
@@ -150,8 +152,16 @@ func CompileCircuit(context *cli.Context) error {
|
||||
jsonFile.Write(jsonData)
|
||||
jsonFile.Close()
|
||||
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
|
||||
jsonData, err = json.Marshal(setup)
|
||||
jsonData, err = json.Marshal(tsetup)
|
||||
panicErr(err)
|
||||
// store setup into file
|
||||
jsonFile, err = os.Create("trustedsetup.json")
|
||||
@@ -202,6 +212,7 @@ func GenerateProofs(context *cli.Context) error {
|
||||
|
||||
fmt.Println("\n proofs:")
|
||||
fmt.Println(proof)
|
||||
fmt.Println("public signals:", proof.PublicSignals)
|
||||
|
||||
// store proofs to json
|
||||
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++ {
|
||||
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
|
||||
}
|
||||
@@ -270,7 +270,7 @@ func VerifyProof(circuit circuitcompiler.Circuit, setup Setup, proof Proof, prin
|
||||
|
||||
// Vkx, to then calculate Vkx+piA
|
||||
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]))
|
||||
}
|
||||
|
||||
|
||||
@@ -81,13 +81,13 @@ func TestZkFromFlatCircuitCode(t *testing.T) {
|
||||
|
||||
fmt.Println("\n proofs:")
|
||||
fmt.Println(proof)
|
||||
fmt.Println("public signals:", proof.PublicSignals)
|
||||
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))
|
||||
}
|
||||
|
||||
func TestZkFromHardcodedR1CS(t *testing.T) {
|
||||
|
||||
b0 := big.NewInt(int64(0))
|
||||
b1 := big.NewInt(int64(1))
|
||||
b3 := big.NewInt(int64(3))
|
||||
@@ -97,14 +97,14 @@ func TestZkFromHardcodedR1CS(t *testing.T) {
|
||||
b30 := big.NewInt(int64(30))
|
||||
b35 := big.NewInt(int64(35))
|
||||
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, b1, b0, b0, b1, b0},
|
||||
[]*big.Int{b0, b0, b1, b0, b1, b0},
|
||||
[]*big.Int{b5, b0, b0, b0, b0, b1},
|
||||
}
|
||||
b := [][]*big.Int{
|
||||
[]*big.Int{b0, b1, b0, b0, b0, b0},
|
||||
[]*big.Int{b0, b1, b0, b0, b0, b0},
|
||||
[]*big.Int{b0, b0, b1, 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},
|
||||
}
|
||||
@@ -112,15 +112,15 @@ func TestZkFromHardcodedR1CS(t *testing.T) {
|
||||
[]*big.Int{b0, b0, b0, b1, b0, b0},
|
||||
[]*big.Int{b0, b0, b0, b0, b1, b0},
|
||||
[]*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)
|
||||
|
||||
// wittness = 1, 3, 35, 9, 27, 30
|
||||
w := []*big.Int{b1, b3, b35, b9, b27, b30}
|
||||
// wittness = 1, 35, 3, 9, 27, 30
|
||||
w := []*big.Int{b1, b35, b3, b9, b27, b30}
|
||||
circuit := circuitcompiler.Circuit{
|
||||
NVars: 6,
|
||||
NPublic: 0,
|
||||
NPublic: 1,
|
||||
NSignals: len(w),
|
||||
}
|
||||
ax, bx, cx, px := Utils.PF.CombinePolynomials(w, alphas, betas, gammas)
|
||||
|
||||
Reference in New Issue
Block a user