Documentation ¶
Overview ¶
Package kzg implements KZG polynomial commitment verification.
KZG polynomial commitment allows for the prover to commit to a polynomial and then selectively prove evaluations of the said polynomial. The size of the commitment is a single G1 element and the size of the evaluation proof is also a single G1 element. However, KZG polynomial commitment scheme requires a trusted SRS.
This package supersedes previous type-specific implementations and allows to use any implemented pairing-friendly curve implementation, being defined over a 2-chain (native implementation) or using field emulation.
Example (Emulated) ¶
Example of using KZG verifier using emulated pairing implementation.
package main import ( "crypto/rand" "fmt" "github.com/aakash4dev/gnark2/backend/groth16" "github.com/aakash4dev/gnark2/frontend" "github.com/aakash4dev/gnark2/frontend/cs/r1cs" "github.com/aakash4dev/gnark2/std/algebra" "github.com/aakash4dev/gnark2/std/algebra/emulated/sw_bn254" "github.com/aakash4dev/gnark2/std/commitments/kzg" "github.com/aakash4dev/gnark2/std/math/emulated" "github.com/consensys/gnark-crypto/ecc" fr_bn254 "github.com/consensys/gnark-crypto/ecc/bn254/fr" kzg_bn254 "github.com/consensys/gnark-crypto/ecc/bn254/kzg" ) type KZGVerificationCircuit[FR emulated.FieldParams, G1El algebra.G1ElementT, G2El algebra.G2ElementT, GTEl algebra.GtElementT] struct { kzg.VerifyingKey[G1El, G2El] kzg.Commitment[G1El] kzg.OpeningProof[FR, G1El] Point emulated.Element[FR] } func (c *KZGVerificationCircuit[FR, G1El, G2El, GTEl]) Define(api frontend.API) error { verifier, err := kzg.NewVerifier[FR, G1El, G2El, GTEl](api) if err != nil { return fmt.Errorf("new verifier: %w", err) } if err := verifier.CheckOpeningProof(c.Commitment, c.OpeningProof, c.Point, c.VerifyingKey); err != nil { return fmt.Errorf("assert proof: %w", err) } return nil } // Example of using KZG verifier using emulated pairing implementation. func main() { // !!! UNSAFE SRS. FOR EXAMPLE PURPOSES ONLY. We create a trusted SRS for // KZG polynomial commitment scheme. In practice this must be prepared using // MPC or by reusing existing SRS. !!! const ( // size of the SRS. Defines the maximum degree of the polynomial which can be committed to kzgSize = 128 // degree of the random polynomial in the example polynomialSize = 100 ) // create new SRS for example purposes (NB! UNSAFE!) alpha, err := rand.Int(rand.Reader, ecc.BN254.ScalarField()) if err != nil { panic("sampling alpha failed: " + err.Error()) } srs, err := kzg_bn254.NewSRS(kzgSize, alpha) // UNSAFE! if err != nil { panic("new SRS failed: " + err.Error()) } // sample the random polynomial by sampling the coefficients. f := make([]fr_bn254.Element, polynomialSize) for i := range f { f[i].SetRandom() } // natively commit to the polynomial using SRS com, err := kzg_bn254.Commit(f, srs.Pk) if err != nil { panic("commitment failed: " + err.Error()) } // sample random evaluation point var point fr_bn254.Element point.SetRandom() // construct a proof of correct opening. The evaluation value is proof.ClaimedValue proof, err := kzg_bn254.Open(f, point, srs.Pk) if err != nil { panic("test opening failed: " + err.Error()) } // test opening proof natively if err = kzg_bn254.Verify(&com, &proof, point, srs.Vk); err != nil { panic("test verify failed: " + err.Error()) } // create a witness element of the commitment wCmt, err := kzg.ValueOfCommitment[sw_bn254.G1Affine](com) if err != nil { panic("commitment witness failed: " + err.Error()) } // create a witness element of the opening proof wProof, err := kzg.ValueOfOpeningProof[sw_bn254.ScalarField, sw_bn254.G1Affine](proof) if err != nil { panic("opening proof witness failed: " + err.Error()) } // create a witness element of the SRS wVk, err := kzg.ValueOfVerifyingKey[sw_bn254.G1Affine, sw_bn254.G2Affine](srs.Vk) if err != nil { panic("verifying key witness failed: " + err.Error()) } // create a witness element of the evaluation point wPt, err := kzg.ValueOfScalar[sw_bn254.ScalarField](point) if err != nil { panic("point witness failed: " + err.Error()) } assignment := KZGVerificationCircuit[sw_bn254.ScalarField, sw_bn254.G1Affine, sw_bn254.G2Affine, sw_bn254.GTEl]{ VerifyingKey: wVk, Commitment: wCmt, OpeningProof: wProof, Point: wPt, } circuit := KZGVerificationCircuit[sw_bn254.ScalarField, sw_bn254.G1Affine, sw_bn254.G2Affine, sw_bn254.GTEl]{} // as we are currently using the emulated implementation of BN254 // in-circuit, then we can compile to any curve. For example purposes, here // we use BN254. ccs, err := frontend.Compile(ecc.BN254.ScalarField(), r1cs.NewBuilder, &circuit) if err != nil { panic("compile failed: " + err.Error()) } // create Groth16 setup. NB! UNSAFE pk, vk, err := groth16.Setup(ccs) // UNSAFE! Use MPC if err != nil { panic("setup failed: " + err.Error()) } // create prover witness from the assignment secretWitness, err := frontend.NewWitness(&assignment, ecc.BN254.ScalarField()) if err != nil { panic("secret witness failed: " + err.Error()) } // create public witness from the assignment publicWitness, err := secretWitness.Public() if err != nil { panic("public witness failed: " + err.Error()) } // construct the groth16 proof of verifying KZG commitment opening in-circuit circuitProof, err := groth16.Prove(ccs, pk, secretWitness) if err != nil { panic("proving failed: " + err.Error()) } // verify the Groth16 proof err = groth16.Verify(circuitProof, vk, publicWitness) if err != nil { panic("circuit verification failed: " + err.Error()) } }
Output:
Example (Native) ¶
Example of using KZG verifier using 2-chains of curves. It is significantly more efficient than using field emulation, but requires a specific chain of inner and outer curves.
// !!! UNSAFE SRS. FOR EXAMPLE PURPOSES ONLY. We create a trusted SRS for // KZG polynomial commitment scheme. In practice this must be prepared using // MPC or by reusing existing SRS. !!! const ( // size of the SRS. Defines the maximum degree of the polynomial which can be committed to kzgSize = 128 // degree of the random polynomial in the example polynomialSize = 100 ) // create new SRS for example purposes (NB! UNSAFE!) alpha, err := rand.Int(rand.Reader, ecc.BLS12_377.ScalarField()) if err != nil { panic("sampling alpha failed: " + err.Error()) } srs, err := kzg_bls12377.NewSRS(kzgSize, alpha) // UNSAFE! if err != nil { panic("new SRS failed: " + err.Error()) } // sample the random polynomial by sampling the coefficients. f := make([]fr_bls12377.Element, polynomialSize) for i := range f { f[i].SetRandom() } // natively commit to the polynomial using SRS com, err := kzg_bls12377.Commit(f, srs.Pk) if err != nil { panic("commitment failed: " + err.Error()) } // sample random evaluation point var point fr_bls12377.Element point.SetRandom() // construct a proof of correct opening. The evaluation value is proof.ClaimedValue proof, err := kzg_bls12377.Open(f, point, srs.Pk) if err != nil { panic("test opening failed: " + err.Error()) } // test opening proof natively if err = kzg_bls12377.Verify(&com, &proof, point, srs.Vk); err != nil { panic("test verify failed: " + err.Error()) } // create a witness element of the commitment wCmt, err := kzg.ValueOfCommitment[sw_bls12377.G1Affine](com) if err != nil { panic("commitment witness failed: " + err.Error()) } // create a witness element of the opening proof wProof, err := kzg.ValueOfOpeningProof[sw_bls12377.ScalarField, sw_bls12377.G1Affine](proof) if err != nil { panic("opening proof witness failed: " + err.Error()) } // create a witness element of the SRS wVk, err := kzg.ValueOfVerifyingKey[sw_bls12377.G1Affine, sw_bls12377.G2Affine](srs.Vk) if err != nil { panic("verifying key witness failed: " + err.Error()) } // create a witness element of the evaluation point wPt, err := kzg.ValueOfScalar[sw_bls12377.ScalarField](point) if err != nil { panic("point witness failed: " + err.Error()) } assignment := KZGVerificationCircuit[sw_bls12377.ScalarField, sw_bls12377.G1Affine, sw_bls12377.G2Affine, sw_bls12377.GT]{ VerifyingKey: wVk, Commitment: wCmt, OpeningProof: wProof, Point: wPt, } circuit := KZGVerificationCircuit[sw_bls12377.ScalarField, sw_bls12377.G1Affine, sw_bls12377.G2Affine, sw_bls12377.GT]{} // because we are using 2-chains then the outer curve must correspond to the // inner curve. For inner BLS12-377 the outer curve is BW6-761. ccs, err := frontend.Compile(ecc.BW6_761.ScalarField(), r1cs.NewBuilder, &circuit) if err != nil { panic("compile failed: " + err.Error()) } // create Groth16 setup. NB! UNSAFE pk, vk, err := groth16.Setup(ccs) // UNSAFE! Use MPC if err != nil { panic("setup failed: " + err.Error()) } // create prover witness from the assignment secretWitness, err := frontend.NewWitness(&assignment, ecc.BW6_761.ScalarField()) if err != nil { panic("secret witness failed: " + err.Error()) } // create public witness from the assignment publicWitness, err := secretWitness.Public() if err != nil { panic("public witness failed: " + err.Error()) } // construct the groth16 proof of verifying KZG commitment opening in-circuit circuitProof, err := groth16.Prove(ccs, pk, secretWitness) if err != nil { panic("proving failed: " + err.Error()) } // verify the Groth16 proof err = groth16.Verify(circuitProof, vk, publicWitness) if err != nil { panic("circuit verification failed: " + err.Error()) }
Output:
Index ¶
- func ValueOfScalar[FR emulated.FieldParams](scalar any) (emulated.Element[FR], error)
- type BatchOpeningProof
- type Commitment
- type OpeningProof
- type Verifier
- func (v *Verifier[FR, G1El, G2El, GTEl]) BatchVerifyMultiPoints(digests []Commitment[G1El], proofs []OpeningProof[FR, G1El], ...) error
- func (v *Verifier[FR, G1El, G2El, GTEl]) BatchVerifySinglePoint(digests []Commitment[G1El], batchOpeningProof BatchOpeningProof[FR, G1El], ...) error
- func (v *Verifier[FR, G1El, G2El, GTEl]) CheckOpeningProof(commitment Commitment[G1El], proof OpeningProof[FR, G1El], ...) error
- func (v *Verifier[FR, G1El, G2El, GTEl]) FoldProof(digests []Commitment[G1El], batchOpeningProof BatchOpeningProof[FR, G1El], ...) (OpeningProof[FR, G1El], Commitment[G1El], error)
- func (v *Verifier[FR, G1El, G2El, GTEl]) FoldProofsMultiPoint(digests []Commitment[G1El], proofs []OpeningProof[FR, G1El], ...) (*G1El, *G1El, error)
- type VerifyingKey
- func PlaceholderVerifyingKey[G1El algebra.G1ElementT, G2El algebra.G2ElementT]() VerifyingKey[G1El, G2El]
- func ValueOfVerifyingKey[G1El algebra.G1ElementT, G2El algebra.G2ElementT](vk any) (VerifyingKey[G1El, G2El], error)
- func ValueOfVerifyingKeyFixed[G1El algebra.G1ElementT, G2El algebra.G2ElementT](vk any) (VerifyingKey[G1El, G2El], error)
Examples ¶
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
func ValueOfScalar ¶
ValueOfScalar initializes a scalar in a witness from a native scalar (Fr) point. The scalars are always emulated.
Types ¶
type BatchOpeningProof ¶
type BatchOpeningProof[FR emulated.FieldParams, G1El algebra.G1ElementT] struct { Quotient G1El ClaimedValues []emulated.Element[FR] }
func ValueOfBatchOpeningProof ¶
func ValueOfBatchOpeningProof[FR emulated.FieldParams, G1El any](proof any) (BatchOpeningProof[FR, G1El], error)
type Commitment ¶
type Commitment[G1El algebra.G1ElementT] struct { G1El G1El }
Commitment is an KZG commitment to a polynomial. Use ValueOfCommitment to initialize a witness from the native commitment.
func ValueOfCommitment ¶
func ValueOfCommitment[G1El algebra.G1ElementT](cmt any) (Commitment[G1El], error)
ValueOfCommitment initializes a KZG commitment witness from a native commitment. It returns an error if there is a conflict between the type parameters and provided native commitment type.
type OpeningProof ¶
type OpeningProof[FR emulated.FieldParams, G1El algebra.G1ElementT] struct { Quotient G1El ClaimedValue emulated.Element[FR] }
OpeningProof embeds the opening proof that polynomial evaluated at Point is equal to ClaimedValue. Use ValueOfOpeningProof to initialize a witness from a native opening proof.
func ValueOfOpeningProof ¶
func ValueOfOpeningProof[FR emulated.FieldParams, G1El algebra.G1ElementT](proof any) (OpeningProof[FR, G1El], error)
ValueOfOpeningProof initializes an opening proof from the given proof and point. It returns an error if there is a mismatch between the type parameters and types of the provided point and proof.
type Verifier ¶
type Verifier[FR emulated.FieldParams, G1El algebra.G1ElementT, G2El algebra.G2ElementT, GtEl algebra.G2ElementT] struct { // contains filtered or unexported fields }
Verifier allows verifying KZG opening proofs.
func NewVerifier ¶
func NewVerifier[FR emulated.FieldParams, G1El algebra.G1ElementT, G2El algebra.G2ElementT, GtEl algebra.G2ElementT](api frontend.API) (*Verifier[FR, G1El, G2El, GtEl], error)
NewVerifier initializes a new Verifier instance.
func (*Verifier[FR, G1El, G2El, GTEl]) BatchVerifyMultiPoints ¶
func (v *Verifier[FR, G1El, G2El, GTEl]) BatchVerifyMultiPoints(digests []Commitment[G1El], proofs []OpeningProof[FR, G1El], points []emulated.Element[FR], vk VerifyingKey[G1El, G2El]) error
BatchVerifyMultiPoints verifies multiple opening proofs at different points.
func (*Verifier[FR, G1El, G2El, GTEl]) BatchVerifySinglePoint ¶
func (v *Verifier[FR, G1El, G2El, GTEl]) BatchVerifySinglePoint(digests []Commitment[G1El], batchOpeningProof BatchOpeningProof[FR, G1El], point emulated.Element[FR], vk VerifyingKey[G1El, G2El], dataTranscript ...emulated.Element[FR]) error
BatchVerifySinglePoint verifies multiple opening proofs at a single point.
func (*Verifier[FR, G1El, G2El, GTEl]) CheckOpeningProof ¶
func (v *Verifier[FR, G1El, G2El, GTEl]) CheckOpeningProof(commitment Commitment[G1El], proof OpeningProof[FR, G1El], point emulated.Element[FR], vk VerifyingKey[G1El, G2El]) error
CheckOpeningProof asserts the validity of the opening proof for the given commitment at point.
func (*Verifier[FR, G1El, G2El, GTEl]) FoldProof ¶
func (v *Verifier[FR, G1El, G2El, GTEl]) FoldProof(digests []Commitment[G1El], batchOpeningProof BatchOpeningProof[FR, G1El], point emulated.Element[FR], dataTranscript ...emulated.Element[FR]) (OpeningProof[FR, G1El], Commitment[G1El], error)
FoldProof folds multiple commitments and a batch opening proof for a single opening check.
func (*Verifier[FR, G1El, G2El, GTEl]) FoldProofsMultiPoint ¶
func (v *Verifier[FR, G1El, G2El, GTEl]) FoldProofsMultiPoint(digests []Commitment[G1El], proofs []OpeningProof[FR, G1El], points []emulated.Element[FR], vk VerifyingKey[G1El, G2El]) (*G1El, *G1El, error)
FoldProofsMultiPoint folds multiple proofs with openings at multiple points. Used for batch verification of different opening proofs. See also Verifier.BatchVerifyMultiPoints.
type VerifyingKey ¶
type VerifyingKey[G1El algebra.G1ElementT, G2El algebra.G2ElementT] struct { G2 [2]G2El G1 G1El }
VerifyingKey is the trusted setup for KZG polynomial commitment scheme. Use ValueOfVerifyingKey to initialize a witness from the native VerifyingKey.
func PlaceholderVerifyingKey ¶
func PlaceholderVerifyingKey[G1El algebra.G1ElementT, G2El algebra.G2ElementT]() VerifyingKey[G1El, G2El]
PlaceholderVerifyingKey returns a placeholder value for the verifying key for compiling if the witness is going to be in precomputed form using ValueOfVerifyingKeyFixed.
func ValueOfVerifyingKey ¶
func ValueOfVerifyingKey[G1El algebra.G1ElementT, G2El algebra.G2ElementT](vk any) (VerifyingKey[G1El, G2El], error)
ValueOfVerifyingKey initializes verifying key witness from the native verifying key. It returns an error if there is a mismatch between the type parameters and the provided verifying key type.
func ValueOfVerifyingKeyFixed ¶
func ValueOfVerifyingKeyFixed[G1El algebra.G1ElementT, G2El algebra.G2ElementT](vk any) (VerifyingKey[G1El, G2El], error)
ValueOfVerifyingKeyFixed initializes verifying key witness from the native verifying key and perform pre-computations for G2 elements. It returns an error if there is a mismatch between the type parameters and the provided verifying key type. Such witness is significantly larger than without precomputations. If witness size is important, then use ValueOfVerifyingKey instead.