func NewProof(curveID ecc.ID) Proof {
	var proof Proof
	switch curveID {
	case ecc.BN254:
		proof = &groth16_bn254.Proof{}
	case ecc.BLS12_377:
		proof = &groth16_bls12377.Proof{}
	case ecc.BLS12_381:
		proof = &groth16_bls12381.Proof{}
	case ecc.BW6_761:
		proof = &groth16_bw6761.Proof{}
	case ecc.BLS24_315:
		proof = &groth16_bls24315.Proof{}
	default:
		panic("not implemented")
	}
	return proof
}
NewProof instantiates a curve-typed Proof and returns an interface
This function exists for serialization purposes
package groth16
import (
	"io"
	"github.com/consensys/gnark-crypto/ecc"
	"github.com/consensys/gnark/backend"
	"github.com/consensys/gnark/frontend"
	backend_bls12377 "github.com/consensys/gnark/internal/backend/bls12-377/cs"
	backend_bls12381 "github.com/consensys/gnark/internal/backend/bls12-381/cs"
	backend_bls24315 "github.com/consensys/gnark/internal/backend/bls24-315/cs"
	backend_bn254 "github.com/consensys/gnark/internal/backend/bn254/cs"
	backend_bw6761 "github.com/consensys/gnark/internal/backend/bw6-761/cs"
	witness_bls12377 "github.com/consensys/gnark/internal/backend/bls12-377/witness"
	witness_bls12381 "github.com/consensys/gnark/internal/backend/bls12-381/witness"
	witness_bls24315 "github.com/consensys/gnark/internal/backend/bls24-315/witness"
	witness_bn254 "github.com/consensys/gnark/internal/backend/bn254/witness"
	witness_bw6761 "github.com/consensys/gnark/internal/backend/bw6-761/witness"
	gnarkio "github.com/consensys/gnark/io"
	groth16_bls12377 "github.com/consensys/gnark/internal/backend/bls12-377/groth16"
	groth16_bls12381 "github.com/consensys/gnark/internal/backend/bls12-381/groth16"
	groth16_bls24315 "github.com/consensys/gnark/internal/backend/bls24-315/groth16"
	groth16_bn254 "github.com/consensys/gnark/internal/backend/bn254/groth16"
	groth16_bw6761 "github.com/consensys/gnark/internal/backend/bw6-761/groth16"
)
type groth16Object interface {
	gnarkio.WriterRawTo
	io.WriterTo
	io.ReaderFrom
	CurveID() ecc.ID
}
type Proof interface {
	groth16Object
}
type ProvingKey interface {
	groth16Object
	NbG1() int
	NbG2() int
	IsDifferent(interface{}) bool
}
type VerifyingKey interface {
	groth16Object
	NbPublicWitness() int
	NbG1() int
	NbG2() int
	ExportSolidity(w io.Writer) error
	IsDifferent(interface{}) bool
}
func Verify(proof Proof, vk VerifyingKey, publicWitness frontend.Circuit) error {
	switch _proof := proof.(type) {
	case *groth16_bls12377.Proof:
		w := witness_bls12377.Witness{}
		if err := w.FromPublicAssignment(publicWitness); err != nil {
			return err
		}
		return groth16_bls12377.Verify(_proof, vk.(*groth16_bls12377.VerifyingKey), w)
	case *groth16_bls12381.Proof:
		w := witness_bls12381.Witness{}
		if err := w.FromPublicAssignment(publicWitness); err != nil {
			return err
		}
		return groth16_bls12381.Verify(_proof, vk.(*groth16_bls12381.VerifyingKey), w)
	case *groth16_bn254.Proof:
		w := witness_bn254.Witness{}
		if err := w.FromPublicAssignment(publicWitness); err != nil {
			return err
		}
		return groth16_bn254.Verify(_proof, vk.(*groth16_bn254.VerifyingKey), w)
	case *groth16_bw6761.Proof:
		w := witness_bw6761.Witness{}
		if err := w.FromPublicAssignment(publicWitness); err != nil {
			return err
		}
		return groth16_bw6761.Verify(_proof, vk.(*groth16_bw6761.VerifyingKey), w)
	case *groth16_bls24315.Proof:
		w := witness_bls24315.Witness{}
		if err := w.FromPublicAssignment(publicWitness); err != nil {
			return err
		}
		return groth16_bls24315.Verify(_proof, vk.(*groth16_bls24315.VerifyingKey), w)
	default:
		panic("unrecognized R1CS curve type")
	}
}
func ReadAndVerify(proof Proof, vk VerifyingKey, publicWitness io.Reader) error {
	switch _vk := vk.(type) {
	case *groth16_bls12377.VerifyingKey:
		w := witness_bls12377.Witness{}
		if _, err := w.LimitReadFrom(publicWitness, vk.NbPublicWitness()); err != nil {
			return err
		}
		return groth16_bls12377.Verify(proof.(*groth16_bls12377.Proof), _vk, w)
	case *groth16_bls12381.VerifyingKey:
		w := witness_bls12381.Witness{}
		if _, err := w.LimitReadFrom(publicWitness, vk.NbPublicWitness()); err != nil {
			return err
		}
		return groth16_bls12381.Verify(proof.(*groth16_bls12381.Proof), _vk, w)
	case *groth16_bn254.VerifyingKey:
		w := witness_bn254.Witness{}
		if _, err := w.LimitReadFrom(publicWitness, vk.NbPublicWitness()); err != nil {
			return err
		}
		return groth16_bn254.Verify(proof.(*groth16_bn254.Proof), _vk, w)
	case *groth16_bw6761.VerifyingKey:
		w := witness_bw6761.Witness{}
		if _, err := w.LimitReadFrom(publicWitness, vk.NbPublicWitness()); err != nil {
			return err
		}
		return groth16_bw6761.Verify(proof.(*groth16_bw6761.Proof), _vk, w)
	case *groth16_bls24315.VerifyingKey:
		w := witness_bls24315.Witness{}
		if _, err := w.LimitReadFrom(publicWitness, vk.NbPublicWitness()); err != nil {
			return err
		}
		return groth16_bls24315.Verify(proof.(*groth16_bls24315.Proof), _vk, w)
	default:
		panic("unrecognized R1CS curve type")
	}
}
func Prove(r1cs frontend.CompiledConstraintSystem, pk ProvingKey, witness frontend.Circuit, opts ...func(opt *backend.ProverOption) error) (Proof, error) {
	opt, err := backend.NewProverOption(opts...)
	if err != nil {
		return nil, err
	}
	switch _r1cs := r1cs.(type) {
	case *backend_bls12377.R1CS:
		w := witness_bls12377.Witness{}
		if err := w.FromFullAssignment(witness); err != nil {
			return nil, err
		}
		return groth16_bls12377.Prove(_r1cs, pk.(*groth16_bls12377.ProvingKey), w, opt)
	case *backend_bls12381.R1CS:
		w := witness_bls12381.Witness{}
		if err := w.FromFullAssignment(witness); err != nil {
			return nil, err
		}
		return groth16_bls12381.Prove(_r1cs, pk.(*groth16_bls12381.ProvingKey), w, opt)
	case *backend_bn254.R1CS:
		w := witness_bn254.Witness{}
		if err := w.FromFullAssignment(witness); err != nil {
			return nil, err
		}
		return groth16_bn254.Prove(_r1cs, pk.(*groth16_bn254.ProvingKey), w, opt)
	case *backend_bw6761.R1CS:
		w := witness_bw6761.Witness{}
		if err := w.FromFullAssignment(witness); err != nil {
			return nil, err
		}
		return groth16_bw6761.Prove(_r1cs, pk.(*groth16_bw6761.ProvingKey), w, opt)
	case *backend_bls24315.R1CS:
		w := witness_bls24315.Witness{}
		if err := w.FromFullAssignment(witness); err != nil {
			return nil, err
		}
		return groth16_bls24315.Prove(_r1cs, pk.(*groth16_bls24315.ProvingKey), w, opt)
	default:
		panic("unrecognized R1CS curve type")
	}
}
func ReadAndProve(r1cs frontend.CompiledConstraintSystem, pk ProvingKey, witness io.Reader, opts ...func(opt *backend.ProverOption) error) (Proof, error) {
	opt, err := backend.NewProverOption(opts...)
	if err != nil {
		return nil, err
	}
	_, nbSecret, nbPublic := r1cs.GetNbVariables()
	expectedSize := (nbSecret + nbPublic - 1)
	switch _r1cs := r1cs.(type) {
	case *backend_bls12377.R1CS:
		w := witness_bls12377.Witness{}
		if _, err := w.LimitReadFrom(witness, expectedSize); err != nil {
			return nil, err
		}
		return groth16_bls12377.Prove(_r1cs, pk.(*groth16_bls12377.ProvingKey), w, opt)
	case *backend_bls12381.R1CS:
		w := witness_bls12381.Witness{}
		if _, err := w.LimitReadFrom(witness, expectedSize); err != nil {
			return nil, err
		}
		return groth16_bls12381.Prove(_r1cs, pk.(*groth16_bls12381.ProvingKey), w, opt)
	case *backend_bn254.R1CS:
		w := witness_bn254.Witness{}
		if _, err := w.LimitReadFrom(witness, expectedSize); err != nil {
			return nil, err
		}
		return groth16_bn254.Prove(_r1cs, pk.(*groth16_bn254.ProvingKey), w, opt)
	case *backend_bw6761.R1CS:
		w := witness_bw6761.Witness{}
		if _, err := w.LimitReadFrom(witness, expectedSize); err != nil {
			return nil, err
		}
		return groth16_bw6761.Prove(_r1cs, pk.(*groth16_bw6761.ProvingKey), w, opt)
	case *backend_bls24315.R1CS:
		w := witness_bls24315.Witness{}
		if _, err := w.LimitReadFrom(witness, expectedSize); err != nil {
			return nil, err
		}
		return groth16_bls24315.Prove(_r1cs, pk.(*groth16_bls24315.ProvingKey), w, opt)
	default:
		panic("unrecognized R1CS curve type")
	}
}
func Setup(r1cs frontend.CompiledConstraintSystem) (ProvingKey, VerifyingKey, error) {
	switch _r1cs := r1cs.(type) {
	case *backend_bls12377.R1CS:
		var pk groth16_bls12377.ProvingKey
		var vk groth16_bls12377.VerifyingKey
		if err := groth16_bls12377.Setup(_r1cs, &pk, &vk); err != nil {
			return nil, nil, err
		}
		return &pk, &vk, nil
	case *backend_bls12381.R1CS:
		var pk groth16_bls12381.ProvingKey
		var vk groth16_bls12381.VerifyingKey
		if err := groth16_bls12381.Setup(_r1cs, &pk, &vk); err != nil {
			return nil, nil, err
		}
		return &pk, &vk, nil
	case *backend_bn254.R1CS:
		var pk groth16_bn254.ProvingKey
		var vk groth16_bn254.VerifyingKey
		if err := groth16_bn254.Setup(_r1cs, &pk, &vk); err != nil {
			return nil, nil, err
		}
		return &pk, &vk, nil
	case *backend_bw6761.R1CS:
		var pk groth16_bw6761.ProvingKey
		var vk groth16_bw6761.VerifyingKey
		if err := groth16_bw6761.Setup(_r1cs, &pk, &vk); err != nil {
			return nil, nil, err
		}
		return &pk, &vk, nil
	case *backend_bls24315.R1CS:
		var pk groth16_bls24315.ProvingKey
		var vk groth16_bls24315.VerifyingKey
		if err := groth16_bls24315.Setup(_r1cs, &pk, &vk); err != nil {
			return nil, nil, err
		}
		return &pk, &vk, nil
	default:
		panic("unrecognized R1CS curve type")
	}
}
func DummySetup(r1cs frontend.CompiledConstraintSystem) (ProvingKey, error) {
	switch _r1cs := r1cs.(type) {
	case *backend_bls12377.R1CS:
		var pk groth16_bls12377.ProvingKey
		if err := groth16_bls12377.DummySetup(_r1cs, &pk); err != nil {
			return nil, err
		}
		return &pk, nil
	case *backend_bls12381.R1CS:
		var pk groth16_bls12381.ProvingKey
		if err := groth16_bls12381.DummySetup(_r1cs, &pk); err != nil {
			return nil, err
		}
		return &pk, nil
	case *backend_bn254.R1CS:
		var pk groth16_bn254.ProvingKey
		if err := groth16_bn254.DummySetup(_r1cs, &pk); err != nil {
			return nil, err
		}
		return &pk, nil
	case *backend_bw6761.R1CS:
		var pk groth16_bw6761.ProvingKey
		if err := groth16_bw6761.DummySetup(_r1cs, &pk); err != nil {
			return nil, err
		}
		return &pk, nil
	case *backend_bls24315.R1CS:
		var pk groth16_bls24315.ProvingKey
		if err := groth16_bls24315.DummySetup(_r1cs, &pk); err != nil {
			return nil, err
		}
		return &pk, nil
	default:
		panic("unrecognized R1CS curve type")
	}
}
func NewProvingKey(curveID ecc.ID) ProvingKey {
	var pk ProvingKey
	switch curveID {
	case ecc.BN254:
		pk = &groth16_bn254.ProvingKey{}
	case ecc.BLS12_377:
		pk = &groth16_bls12377.ProvingKey{}
	case ecc.BLS12_381:
		pk = &groth16_bls12381.ProvingKey{}
	case ecc.BW6_761:
		pk = &groth16_bw6761.ProvingKey{}
	case ecc.BLS24_315:
		pk = &groth16_bls24315.ProvingKey{}
	default:
		panic("not implemented")
	}
	return pk
}
func NewVerifyingKey(curveID ecc.ID) VerifyingKey {
	var vk VerifyingKey
	switch curveID {
	case ecc.BN254:
		vk = &groth16_bn254.VerifyingKey{}
	case ecc.BLS12_377:
		vk = &groth16_bls12377.VerifyingKey{}
	case ecc.BLS12_381:
		vk = &groth16_bls12381.VerifyingKey{}
	case ecc.BW6_761:
		vk = &groth16_bw6761.VerifyingKey{}
	case ecc.BLS24_315:
		vk = &groth16_bls24315.VerifyingKey{}
	default:
		panic("not implemented")
	}
	return vk
}