forked from Consensys/gnark
-
Notifications
You must be signed in to change notification settings - Fork 0
/
main.go
172 lines (140 loc) · 4.47 KB
/
main.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
// Copyright 2020 ConsenSys AG
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package main
import (
"fmt"
"log"
"github.com/consensys/gnark-crypto/ecc"
"github.com/consensys/gnark/backend/plonk"
cs "github.com/consensys/gnark/constraint/bn254"
"github.com/consensys/gnark/frontend/cs/scs"
"github.com/consensys/gnark/frontend"
"github.com/consensys/gnark/test/unsafekzg"
)
// In this example we show how to use PLONK with KZG commitments. The circuit that is
// showed here is the same as in ../exponentiate.
// Circuit y == x**e
// only the bitSize least significant bits of e are used
type Circuit struct {
// tagging a variable is optional
// default uses variable name and secret visibility.
X frontend.Variable `gnark:",public"`
Y frontend.Variable `gnark:",public"`
E frontend.Variable
}
// Define declares the circuit's constraints
// y == x**e
func (circuit *Circuit) Define(api frontend.API) error {
// number of bits of exponent
const bitSize = 4000
// specify constraints
output := frontend.Variable(1)
bits := api.ToBinary(circuit.E, bitSize)
for i := 0; i < len(bits); i++ {
// api.Println(fmt.Sprintf("e[%d]", i), bits[i]) // we may print a variable for testing and / or debugging purposes
if i != 0 {
output = api.Mul(output, output)
}
multiply := api.Mul(output, circuit.X)
output = api.Select(bits[len(bits)-1-i], multiply, output)
}
api.AssertIsEqual(circuit.Y, output)
return nil
}
func main() {
var circuit Circuit
// // building the circuit...
ccs, err := frontend.Compile(ecc.BN254.ScalarField(), scs.NewBuilder, &circuit)
if err != nil {
fmt.Println("circuit compilation error")
}
// create the necessary data for KZG.
// This is a toy example, normally the trusted setup to build ZKG
// has been run before.
// The size of the data in KZG should be the closest power of 2 bounding //
// above max(nbConstraints, nbVariables).
scs := ccs.(*cs.SparseR1CS)
srs, srsLagrange, err := unsafekzg.NewSRS(scs)
if err != nil {
panic(err)
}
// Correct data: the proof passes
{
// Witnesses instantiation. Witness is known only by the prover,
// while public w is a public data known by the verifier.
var w Circuit
w.X = 2
w.E = 2
w.Y = 4
witnessFull, err := frontend.NewWitness(&w, ecc.BN254.ScalarField())
if err != nil {
log.Fatal(err)
}
witnessPublic, err := frontend.NewWitness(&w, ecc.BN254.ScalarField(), frontend.PublicOnly())
if err != nil {
log.Fatal(err)
}
// public data consists of the polynomials describing the constants involved
// in the constraints, the polynomial describing the permutation ("grand
// product argument"), and the FFT domains.
pk, vk, err := plonk.Setup(ccs, srs, srsLagrange)
//_, err := plonk.Setup(r1cs, kate, &publicWitness)
if err != nil {
log.Fatal(err)
}
proof, err := plonk.Prove(ccs, pk, witnessFull)
if err != nil {
log.Fatal(err)
}
err = plonk.Verify(proof, vk, witnessPublic)
if err != nil {
log.Fatal(err)
}
}
// Wrong data: the proof fails
{
// Witnesses instantiation. Witness is known only by the prover,
// while public w is a public data known by the verifier.
var w, pW Circuit
w.X = 2
w.E = 12
w.Y = 4096
pW.X = 3
pW.Y = 4096
witnessFull, err := frontend.NewWitness(&w, ecc.BN254.ScalarField())
if err != nil {
log.Fatal(err)
}
witnessPublic, err := frontend.NewWitness(&pW, ecc.BN254.ScalarField(), frontend.PublicOnly())
if err != nil {
log.Fatal(err)
}
// public data consists of the polynomials describing the constants involved
// in the constraints, the polynomial describing the permutation ("grand
// product argument"), and the FFT domains.
pk, vk, err := plonk.Setup(ccs, srs, srsLagrange)
//_, err := plonk.Setup(r1cs, kate, &publicWitness)
if err != nil {
log.Fatal(err)
}
proof, err := plonk.Prove(ccs, pk, witnessFull)
if err != nil {
log.Fatal(err)
}
err = plonk.Verify(proof, vk, witnessPublic)
if err == nil {
log.Fatal("Error: wrong proof is accepted")
}
}
}