github.com/consensys/gnark@v0.11.0/backend/groth16/groth16.go (about) 1 // Copyright 2020 ConsenSys AG 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 // Package groth16 implements Groth16 Zero Knowledge Proof system (aka zkSNARK). 16 // 17 // # See also 18 // 19 // https://eprint.iacr.org/2016/260.pdf 20 package groth16 21 22 import ( 23 "io" 24 25 "github.com/consensys/gnark-crypto/ecc" 26 "github.com/consensys/gnark/backend" 27 "github.com/consensys/gnark/backend/solidity" 28 "github.com/consensys/gnark/backend/witness" 29 "github.com/consensys/gnark/constraint" 30 cs_bls12377 "github.com/consensys/gnark/constraint/bls12-377" 31 cs_bls12381 "github.com/consensys/gnark/constraint/bls12-381" 32 cs_bls24315 "github.com/consensys/gnark/constraint/bls24-315" 33 cs_bls24317 "github.com/consensys/gnark/constraint/bls24-317" 34 cs_bn254 "github.com/consensys/gnark/constraint/bn254" 35 cs_bw6633 "github.com/consensys/gnark/constraint/bw6-633" 36 cs_bw6761 "github.com/consensys/gnark/constraint/bw6-761" 37 38 fr_bls12377 "github.com/consensys/gnark-crypto/ecc/bls12-377/fr" 39 fr_bls12381 "github.com/consensys/gnark-crypto/ecc/bls12-381/fr" 40 fr_bls24315 "github.com/consensys/gnark-crypto/ecc/bls24-315/fr" 41 fr_bls24317 "github.com/consensys/gnark-crypto/ecc/bls24-317/fr" 42 fr_bn254 "github.com/consensys/gnark-crypto/ecc/bn254/fr" 43 fr_bw6633 "github.com/consensys/gnark-crypto/ecc/bw6-633/fr" 44 fr_bw6761 "github.com/consensys/gnark-crypto/ecc/bw6-761/fr" 45 46 gnarkio "github.com/consensys/gnark/io" 47 48 groth16_bls12377 "github.com/consensys/gnark/backend/groth16/bls12-377" 49 groth16_bls12381 "github.com/consensys/gnark/backend/groth16/bls12-381" 50 groth16_bls24315 "github.com/consensys/gnark/backend/groth16/bls24-315" 51 groth16_bls24317 "github.com/consensys/gnark/backend/groth16/bls24-317" 52 groth16_bn254 "github.com/consensys/gnark/backend/groth16/bn254" 53 icicle_bn254 "github.com/consensys/gnark/backend/groth16/bn254/icicle" 54 groth16_bw6633 "github.com/consensys/gnark/backend/groth16/bw6-633" 55 groth16_bw6761 "github.com/consensys/gnark/backend/groth16/bw6-761" 56 ) 57 58 // Proof represents a Groth16 proof generated by groth16.Prove 59 // 60 // it's underlying implementation is curve specific (see gnark/internal/backend) 61 type Proof interface { 62 CurveID() ecc.ID 63 64 io.WriterTo 65 io.ReaderFrom 66 67 // Raw methods for faster serialization-deserialization. Does not perform checks on the data. 68 // Only use if you are sure of the data you are reading comes from trusted source. 69 gnarkio.WriterRawTo 70 } 71 72 // ProvingKey represents a Groth16 ProvingKey 73 // 74 // it's underlying implementation is strongly typed with the curve (see gnark/internal/backend) 75 type ProvingKey interface { 76 CurveID() ecc.ID 77 78 io.WriterTo 79 io.ReaderFrom 80 81 // Raw methods for faster serialization-deserialization. Does not perform checks on the data. 82 // Only use if you are sure of the data you are reading comes from trusted source. 83 gnarkio.WriterRawTo 84 gnarkio.UnsafeReaderFrom 85 86 // BinaryDumper is the interface that wraps the WriteDump and ReadDump 87 // methods. It performs a very fast and very unsafe memory dump writing and 88 // reading. 89 gnarkio.BinaryDumper 90 91 // NbG1 returns the number of G1 elements in the ProvingKey 92 NbG1() int 93 94 // NbG2 returns the number of G2 elements in the ProvingKey 95 NbG2() int 96 97 // IsDifferent compares against another proving key and returns true if they are different. 98 IsDifferent(any) bool 99 } 100 101 // VerifyingKey represents a Groth16 VerifyingKey 102 // 103 // it's underlying implementation is strongly typed with the curve (see gnark/internal/backend) 104 // 105 // ExportSolidity is implemented for BN254 and will return an error with other curves 106 type VerifyingKey interface { 107 CurveID() ecc.ID 108 109 io.WriterTo 110 io.ReaderFrom 111 112 // Raw methods for faster serialization-deserialization. Does not perform checks on the data. 113 // Only use if you are sure of the data you are reading comes from trusted source. 114 gnarkio.WriterRawTo 115 gnarkio.UnsafeReaderFrom 116 117 // VerifyingKey are the methods required for generating the Solidity 118 // verifier contract from the VerifyingKey. This will return an error if not 119 // supported on the CurveID(). 120 solidity.VerifyingKey 121 122 // NbPublicWitness returns number of elements expected in the public witness 123 NbPublicWitness() int 124 125 // NbG1 returns the number of G1 elements in the VerifyingKey 126 NbG1() int 127 128 // NbG2 returns the number of G2 elements in the VerifyingKey 129 NbG2() int 130 131 IsDifferent(interface{}) bool 132 } 133 134 // Verify runs the groth16.Verify algorithm on provided proof with given witness 135 func Verify(proof Proof, vk VerifyingKey, publicWitness witness.Witness, opts ...backend.VerifierOption) error { 136 137 switch _proof := proof.(type) { 138 case *groth16_bls12377.Proof: 139 w, ok := publicWitness.Vector().(fr_bls12377.Vector) 140 if !ok { 141 return witness.ErrInvalidWitness 142 } 143 return groth16_bls12377.Verify(_proof, vk.(*groth16_bls12377.VerifyingKey), w, opts...) 144 case *groth16_bls12381.Proof: 145 w, ok := publicWitness.Vector().(fr_bls12381.Vector) 146 if !ok { 147 return witness.ErrInvalidWitness 148 } 149 return groth16_bls12381.Verify(_proof, vk.(*groth16_bls12381.VerifyingKey), w, opts...) 150 case *groth16_bn254.Proof: 151 w, ok := publicWitness.Vector().(fr_bn254.Vector) 152 if !ok { 153 return witness.ErrInvalidWitness 154 } 155 return groth16_bn254.Verify(_proof, vk.(*groth16_bn254.VerifyingKey), w, opts...) 156 case *groth16_bw6761.Proof: 157 w, ok := publicWitness.Vector().(fr_bw6761.Vector) 158 if !ok { 159 return witness.ErrInvalidWitness 160 } 161 return groth16_bw6761.Verify(_proof, vk.(*groth16_bw6761.VerifyingKey), w, opts...) 162 case *groth16_bls24317.Proof: 163 w, ok := publicWitness.Vector().(fr_bls24317.Vector) 164 if !ok { 165 return witness.ErrInvalidWitness 166 } 167 return groth16_bls24317.Verify(_proof, vk.(*groth16_bls24317.VerifyingKey), w, opts...) 168 case *groth16_bls24315.Proof: 169 w, ok := publicWitness.Vector().(fr_bls24315.Vector) 170 if !ok { 171 return witness.ErrInvalidWitness 172 } 173 return groth16_bls24315.Verify(_proof, vk.(*groth16_bls24315.VerifyingKey), w, opts...) 174 case *groth16_bw6633.Proof: 175 w, ok := publicWitness.Vector().(fr_bw6633.Vector) 176 if !ok { 177 return witness.ErrInvalidWitness 178 } 179 return groth16_bw6633.Verify(_proof, vk.(*groth16_bw6633.VerifyingKey), w, opts...) 180 default: 181 panic("unrecognized R1CS curve type") 182 } 183 } 184 185 // Prove runs the groth16.Prove algorithm. 186 // 187 // if the force flag is set: 188 // 189 // will execute all the prover computations, even if the witness is invalid 190 // will produce an invalid proof 191 // internally, the solution vector to the R1CS will be filled with random values which may impact benchmarking 192 func Prove(r1cs constraint.ConstraintSystem, pk ProvingKey, fullWitness witness.Witness, opts ...backend.ProverOption) (Proof, error) { 193 switch _r1cs := r1cs.(type) { 194 case *cs_bls12377.R1CS: 195 return groth16_bls12377.Prove(_r1cs, pk.(*groth16_bls12377.ProvingKey), fullWitness, opts...) 196 197 case *cs_bls12381.R1CS: 198 return groth16_bls12381.Prove(_r1cs, pk.(*groth16_bls12381.ProvingKey), fullWitness, opts...) 199 200 case *cs_bn254.R1CS: 201 if icicle_bn254.HasIcicle { 202 return icicle_bn254.Prove(_r1cs, pk.(*icicle_bn254.ProvingKey), fullWitness, opts...) 203 } 204 return groth16_bn254.Prove(_r1cs, pk.(*groth16_bn254.ProvingKey), fullWitness, opts...) 205 206 case *cs_bw6761.R1CS: 207 return groth16_bw6761.Prove(_r1cs, pk.(*groth16_bw6761.ProvingKey), fullWitness, opts...) 208 209 case *cs_bls24317.R1CS: 210 return groth16_bls24317.Prove(_r1cs, pk.(*groth16_bls24317.ProvingKey), fullWitness, opts...) 211 212 case *cs_bls24315.R1CS: 213 return groth16_bls24315.Prove(_r1cs, pk.(*groth16_bls24315.ProvingKey), fullWitness, opts...) 214 215 case *cs_bw6633.R1CS: 216 return groth16_bw6633.Prove(_r1cs, pk.(*groth16_bw6633.ProvingKey), fullWitness, opts...) 217 218 default: 219 panic("unrecognized R1CS curve type") 220 } 221 } 222 223 // Setup runs groth16.Setup with provided R1CS and outputs a key pair associated with the circuit. 224 // 225 // Note that careful consideration must be given to this step in a production environment. 226 // groth16.Setup uses some randomness to precompute the Proving and Verifying keys. If the process 227 // or machine leaks this randomness, an attacker could break the ZKP protocol. 228 // 229 // Two main solutions to this deployment issues are: running the Setup through a MPC (multi party computation) 230 // or using a ZKP backend like PLONK where the per-circuit Setup is deterministic. 231 func Setup(r1cs constraint.ConstraintSystem) (ProvingKey, VerifyingKey, error) { 232 233 switch _r1cs := r1cs.(type) { 234 case *cs_bls12377.R1CS: 235 var pk groth16_bls12377.ProvingKey 236 var vk groth16_bls12377.VerifyingKey 237 if err := groth16_bls12377.Setup(_r1cs, &pk, &vk); err != nil { 238 return nil, nil, err 239 } 240 return &pk, &vk, nil 241 case *cs_bls12381.R1CS: 242 var pk groth16_bls12381.ProvingKey 243 var vk groth16_bls12381.VerifyingKey 244 if err := groth16_bls12381.Setup(_r1cs, &pk, &vk); err != nil { 245 return nil, nil, err 246 } 247 return &pk, &vk, nil 248 case *cs_bn254.R1CS: 249 var vk groth16_bn254.VerifyingKey 250 if icicle_bn254.HasIcicle { 251 var pk icicle_bn254.ProvingKey 252 if err := icicle_bn254.Setup(_r1cs, &pk, &vk); err != nil { 253 return nil, nil, err 254 } 255 return &pk, &vk, nil 256 } 257 var pk groth16_bn254.ProvingKey 258 if err := groth16_bn254.Setup(_r1cs, &pk, &vk); err != nil { 259 return nil, nil, err 260 } 261 return &pk, &vk, nil 262 case *cs_bw6761.R1CS: 263 var pk groth16_bw6761.ProvingKey 264 var vk groth16_bw6761.VerifyingKey 265 if err := groth16_bw6761.Setup(_r1cs, &pk, &vk); err != nil { 266 return nil, nil, err 267 } 268 return &pk, &vk, nil 269 case *cs_bls24317.R1CS: 270 var pk groth16_bls24317.ProvingKey 271 var vk groth16_bls24317.VerifyingKey 272 if err := groth16_bls24317.Setup(_r1cs, &pk, &vk); err != nil { 273 return nil, nil, err 274 } 275 return &pk, &vk, nil 276 case *cs_bls24315.R1CS: 277 var pk groth16_bls24315.ProvingKey 278 var vk groth16_bls24315.VerifyingKey 279 if err := groth16_bls24315.Setup(_r1cs, &pk, &vk); err != nil { 280 return nil, nil, err 281 } 282 return &pk, &vk, nil 283 case *cs_bw6633.R1CS: 284 var pk groth16_bw6633.ProvingKey 285 var vk groth16_bw6633.VerifyingKey 286 if err := groth16_bw6633.Setup(_r1cs, &pk, &vk); err != nil { 287 return nil, nil, err 288 } 289 return &pk, &vk, nil 290 default: 291 panic("unrecognized R1CS curve type") 292 } 293 } 294 295 // DummySetup create a random ProvingKey with provided R1CS 296 // it doesn't return a VerifyingKey and is use for benchmarking or test purposes only. 297 func DummySetup(r1cs constraint.ConstraintSystem) (ProvingKey, error) { 298 switch _r1cs := r1cs.(type) { 299 case *cs_bls12377.R1CS: 300 var pk groth16_bls12377.ProvingKey 301 if err := groth16_bls12377.DummySetup(_r1cs, &pk); err != nil { 302 return nil, err 303 } 304 return &pk, nil 305 case *cs_bls12381.R1CS: 306 var pk groth16_bls12381.ProvingKey 307 if err := groth16_bls12381.DummySetup(_r1cs, &pk); err != nil { 308 return nil, err 309 } 310 return &pk, nil 311 case *cs_bn254.R1CS: 312 if icicle_bn254.HasIcicle { 313 var pk icicle_bn254.ProvingKey 314 if err := icicle_bn254.DummySetup(_r1cs, &pk); err != nil { 315 return nil, err 316 } 317 return &pk, nil 318 } 319 var pk groth16_bn254.ProvingKey 320 if err := groth16_bn254.DummySetup(_r1cs, &pk); err != nil { 321 return nil, err 322 } 323 return &pk, nil 324 case *cs_bw6761.R1CS: 325 var pk groth16_bw6761.ProvingKey 326 if err := groth16_bw6761.DummySetup(_r1cs, &pk); err != nil { 327 return nil, err 328 } 329 return &pk, nil 330 case *cs_bls24317.R1CS: 331 var pk groth16_bls24317.ProvingKey 332 if err := groth16_bls24317.DummySetup(_r1cs, &pk); err != nil { 333 return nil, err 334 } 335 return &pk, nil 336 case *cs_bls24315.R1CS: 337 var pk groth16_bls24315.ProvingKey 338 if err := groth16_bls24315.DummySetup(_r1cs, &pk); err != nil { 339 return nil, err 340 } 341 return &pk, nil 342 case *cs_bw6633.R1CS: 343 var pk groth16_bw6633.ProvingKey 344 if err := groth16_bw6633.DummySetup(_r1cs, &pk); err != nil { 345 return nil, err 346 } 347 return &pk, nil 348 default: 349 panic("unrecognized R1CS curve type") 350 } 351 } 352 353 // NewProvingKey instantiates a curve-typed ProvingKey and returns an interface object 354 // This function exists for serialization purposes 355 func NewProvingKey(curveID ecc.ID) ProvingKey { 356 var pk ProvingKey 357 switch curveID { 358 case ecc.BN254: 359 pk = &groth16_bn254.ProvingKey{} 360 if icicle_bn254.HasIcicle { 361 pk = &icicle_bn254.ProvingKey{} 362 } 363 case ecc.BLS12_377: 364 pk = &groth16_bls12377.ProvingKey{} 365 case ecc.BLS12_381: 366 pk = &groth16_bls12381.ProvingKey{} 367 case ecc.BW6_761: 368 pk = &groth16_bw6761.ProvingKey{} 369 case ecc.BLS24_317: 370 pk = &groth16_bls24317.ProvingKey{} 371 case ecc.BLS24_315: 372 pk = &groth16_bls24315.ProvingKey{} 373 case ecc.BW6_633: 374 pk = &groth16_bw6633.ProvingKey{} 375 default: 376 panic("not implemented") 377 } 378 return pk 379 } 380 381 // NewVerifyingKey instantiates a curve-typed VerifyingKey and returns an interface 382 // This function exists for serialization purposes 383 func NewVerifyingKey(curveID ecc.ID) VerifyingKey { 384 var vk VerifyingKey 385 switch curveID { 386 case ecc.BN254: 387 vk = &groth16_bn254.VerifyingKey{} 388 case ecc.BLS12_377: 389 vk = &groth16_bls12377.VerifyingKey{} 390 case ecc.BLS12_381: 391 vk = &groth16_bls12381.VerifyingKey{} 392 case ecc.BW6_761: 393 vk = &groth16_bw6761.VerifyingKey{} 394 case ecc.BLS24_317: 395 vk = &groth16_bls24317.VerifyingKey{} 396 case ecc.BLS24_315: 397 vk = &groth16_bls24315.VerifyingKey{} 398 case ecc.BW6_633: 399 vk = &groth16_bw6633.VerifyingKey{} 400 default: 401 panic("not implemented") 402 } 403 404 return vk 405 } 406 407 // NewProof instantiates a curve-typed Proof and returns an interface 408 // This function exists for serialization purposes 409 func NewProof(curveID ecc.ID) Proof { 410 var proof Proof 411 switch curveID { 412 case ecc.BN254: 413 proof = &groth16_bn254.Proof{} 414 case ecc.BLS12_377: 415 proof = &groth16_bls12377.Proof{} 416 case ecc.BLS12_381: 417 proof = &groth16_bls12381.Proof{} 418 case ecc.BW6_761: 419 proof = &groth16_bw6761.Proof{} 420 case ecc.BLS24_317: 421 proof = &groth16_bls24317.Proof{} 422 case ecc.BLS24_315: 423 proof = &groth16_bls24315.Proof{} 424 case ecc.BW6_633: 425 proof = &groth16_bw6633.Proof{} 426 default: 427 panic("not implemented") 428 } 429 430 return proof 431 } 432 433 // NewCS instantiate a concrete curved-typed R1CS and return a R1CS interface 434 // This method exists for (de)serialization purposes 435 func NewCS(curveID ecc.ID) constraint.ConstraintSystem { 436 var r1cs constraint.ConstraintSystem 437 switch curveID { 438 case ecc.BN254: 439 r1cs = &cs_bn254.R1CS{} 440 case ecc.BLS12_377: 441 r1cs = &cs_bls12377.R1CS{} 442 case ecc.BLS12_381: 443 r1cs = &cs_bls12381.R1CS{} 444 case ecc.BW6_761: 445 r1cs = &cs_bw6761.R1CS{} 446 case ecc.BLS24_317: 447 r1cs = &cs_bls24317.R1CS{} 448 case ecc.BLS24_315: 449 r1cs = &cs_bls24315.R1CS{} 450 case ecc.BW6_633: 451 r1cs = &cs_bw6633.R1CS{} 452 default: 453 panic("not implemented") 454 } 455 return r1cs 456 }