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  }