170 lines
5.3 KiB
Go
170 lines
5.3 KiB
Go
package goethkzg
|
|
|
|
import (
|
|
bls12381 "github.com/consensys/gnark-crypto/ecc/bls12-381"
|
|
"github.com/crate-crypto/go-eth-kzg/internal/kzg"
|
|
"golang.org/x/sync/errgroup"
|
|
)
|
|
|
|
// VerifyKZGProof implements [verify_kzg_proof].
|
|
//
|
|
// [verify_kzg_proof]: https://github.com/ethereum/consensus-specs/blob/017a8495f7671f5fff2075a9bfc9238c1a0982f8/specs/deneb/polynomial-commitments.md#verify_kzg_proof
|
|
func (c *Context) VerifyKZGProof(blobCommitment KZGCommitment, inputPointBytes, claimedValueBytes Scalar, kzgProof KZGProof) error {
|
|
// 1. Deserialization
|
|
//
|
|
claimedValue, err := DeserializeScalar(claimedValueBytes)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
inputPoint, err := DeserializeScalar(inputPointBytes)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
polynomialCommitment, err := DeserializeKZGCommitment(blobCommitment)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
quotientCommitment, err := DeserializeKZGProof(kzgProof)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
// 2. Verify opening proof
|
|
proof := kzg.OpeningProof{
|
|
QuotientCommitment: quotientCommitment,
|
|
InputPoint: inputPoint,
|
|
ClaimedValue: claimedValue,
|
|
}
|
|
|
|
return kzg.Verify(&polynomialCommitment, &proof, c.openKey4844)
|
|
}
|
|
|
|
// VerifyBlobKZGProof implements [verify_blob_kzg_proof].
|
|
//
|
|
// [verify_blob_kzg_proof]: https://github.com/ethereum/consensus-specs/blob/017a8495f7671f5fff2075a9bfc9238c1a0982f8/specs/deneb/polynomial-commitments.md#verify_blob_kzg_proof
|
|
func (c *Context) VerifyBlobKZGProof(blob *Blob, blobCommitment KZGCommitment, kzgProof KZGProof) error {
|
|
// 1. Deserialize
|
|
//
|
|
polynomial, err := DeserializeBlob(blob)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
polynomialCommitment, err := DeserializeKZGCommitment(blobCommitment)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
quotientCommitment, err := DeserializeKZGProof(kzgProof)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
// 2. Compute the evaluation challenge
|
|
evaluationChallenge := computeChallenge(blob, blobCommitment)
|
|
|
|
// 3. Compute output point/ claimed value
|
|
outputPoint, err := c.domain.EvaluateLagrangePolynomial(polynomial, evaluationChallenge)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
// 4. Verify opening proof
|
|
openingProof := kzg.OpeningProof{
|
|
QuotientCommitment: quotientCommitment,
|
|
InputPoint: evaluationChallenge,
|
|
ClaimedValue: *outputPoint,
|
|
}
|
|
|
|
return kzg.Verify(&polynomialCommitment, &openingProof, c.openKey4844)
|
|
}
|
|
|
|
// VerifyBlobKZGProofBatch implements [verify_blob_kzg_proof_batch].
|
|
//
|
|
// [verify_blob_kzg_proof_batch]: https://github.com/ethereum/consensus-specs/blob/017a8495f7671f5fff2075a9bfc9238c1a0982f8/specs/deneb/polynomial-commitments.md#verify_blob_kzg_proof_batch
|
|
func (c *Context) VerifyBlobKZGProofBatch(blobs []*Blob, polynomialCommitments []KZGCommitment, kzgProofs []KZGProof) error {
|
|
// 1. Check that all components in the batch have the same size
|
|
//
|
|
blobsLen := len(blobs)
|
|
lengthsAreEqual := blobsLen == len(polynomialCommitments) && blobsLen == len(kzgProofs)
|
|
if !lengthsAreEqual {
|
|
return ErrBatchLengthCheck
|
|
}
|
|
batchSize := blobsLen
|
|
|
|
// 2. Collect opening proofs
|
|
//
|
|
openingProofs := make([]kzg.OpeningProof, batchSize)
|
|
commitments := make([]bls12381.G1Affine, batchSize)
|
|
for i := 0; i < batchSize; i++ {
|
|
// 2a. Deserialize
|
|
//
|
|
serComm := polynomialCommitments[i]
|
|
polynomialCommitment, err := DeserializeKZGCommitment(serComm)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
kzgProof := kzgProofs[i]
|
|
quotientCommitment, err := DeserializeKZGProof(kzgProof)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
blob := blobs[i]
|
|
polynomial, err := DeserializeBlob(blob)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
// 2b. Compute the evaluation challenge
|
|
evaluationChallenge := computeChallenge(blob, serComm)
|
|
|
|
// 2c. Compute output point/ claimed value
|
|
outputPoint, err := c.domain.EvaluateLagrangePolynomial(polynomial, evaluationChallenge)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
// 2d. Append opening proof to list
|
|
openingProof := kzg.OpeningProof{
|
|
QuotientCommitment: quotientCommitment,
|
|
InputPoint: evaluationChallenge,
|
|
ClaimedValue: *outputPoint,
|
|
}
|
|
openingProofs[i] = openingProof
|
|
commitments[i] = polynomialCommitment
|
|
}
|
|
|
|
// 3. Verify opening proofs
|
|
return kzg.BatchVerifyMultiPoints(commitments, openingProofs, c.openKey4844)
|
|
}
|
|
|
|
// VerifyBlobKZGProofBatchPar implements [verify_blob_kzg_proof_batch]. This is the parallelized version of
|
|
// [Context.VerifyBlobKZGProofBatch], which is single-threaded. This function uses go-routines to process each proof in
|
|
// parallel. If you are worried about resource starvation on large batches, it is advised to schedule your own
|
|
// go-routines in a more intricate way than done below for large batches.
|
|
//
|
|
// [verify_blob_kzg_proof_batch]: https://github.com/ethereum/consensus-specs/blob/017a8495f7671f5fff2075a9bfc9238c1a0982f8/specs/deneb/polynomial-commitments.md#verify_blob_kzg_proof_batch
|
|
func (c *Context) VerifyBlobKZGProofBatchPar(blobs []*Blob, commitments []KZGCommitment, proofs []KZGProof) error {
|
|
// 1. Check that all components in the batch have the same size
|
|
if len(commitments) != len(blobs) || len(proofs) != len(blobs) {
|
|
return ErrBatchLengthCheck
|
|
}
|
|
|
|
// 2. Verify each opening proof using green threads
|
|
var errG errgroup.Group
|
|
for i := range blobs {
|
|
j := i // Capture the value of the loop variable
|
|
errG.Go(func() error {
|
|
return c.VerifyBlobKZGProof(blobs[j], commitments[j], proofs[j])
|
|
})
|
|
}
|
|
|
|
// 3. Wait for all go routines to complete and check if any returned an error
|
|
return errG.Wait()
|
|
}
|