Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

move more EIP-4844 crypto functions to crypto/kzg #46

Merged
merged 1 commit into from
Nov 9, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 3 additions & 6 deletions core/types/data_blob.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@ import (

"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/common/hexutil"
"github.com/ethereum/go-ethereum/crypto"
"github.com/ethereum/go-ethereum/crypto/kzg"
"github.com/ethereum/go-ethereum/params"
"github.com/protolambda/go-kzg/bls"
Expand Down Expand Up @@ -63,10 +62,8 @@ func (p *KZGCommitment) Point() (*bls.G1Point, error) {
return bls.FromCompressedG1(p[:])
}

func (kzg KZGCommitment) ComputeVersionedHash() common.Hash {
h := crypto.Keccak256Hash(kzg[:])
h[0] = params.BlobCommitmentVersionKZG
return h
func (c KZGCommitment) ComputeVersionedHash() common.Hash {
return kzg.KZGToVersionedHash(c)
}

// Compressed BLS12-381 G1 element
Expand Down Expand Up @@ -528,7 +525,7 @@ func (b *BlobTxWrapData) verifyBlobs(inner TxData) error {
if err != nil {
return fmt.Errorf("aggregate proof parse error: %v", err)
}
if !kzg.VerifyKzgProof(aggregateCommitmentG1, &z, &y, aggregateProofG1) {
if !kzg.VerifyKZGProofFromPoints(aggregateCommitmentG1, &z, &y, aggregateProofG1) {
return errors.New("failed to verify kzg")
}
return nil
Expand Down
64 changes: 1 addition & 63 deletions core/vm/contracts.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,6 @@ import (
"errors"
"math/big"

"github.com/ethereum/go-ethereum/core/types"

"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/common/math"
"github.com/ethereum/go-ethereum/crypto"
Expand All @@ -33,7 +31,6 @@ import (
"github.com/ethereum/go-ethereum/crypto/kzg"
"github.com/ethereum/go-ethereum/params"
big2 "github.com/holiman/big"
"github.com/protolambda/go-kzg/bls"
"golang.org/x/crypto/ripemd160"
)

Expand Down Expand Up @@ -1077,70 +1074,11 @@ func (c *bls12381MapG2) Run(input []byte) ([]byte, error) {
// to check if a value is part of a blob at a specific point with a KZG proof.
type pointEvaluation struct{}

var (
errPointEvaluationInputLength = errors.New("invalid input length")
errPointEvaluationInvalidVersionedHash = errors.New("invalid versioned hash")
errPointEvaluationInvalidX = errors.New("invalid evaluation point")
errPointEvaluationInvalidY = errors.New("invalid expected output")
errPointEvaluationInvalidKzg = errors.New("invalid data kzg")
errPointEvaluationInvalidProof = errors.New("invalid proof")
errPointEvaluationMismatchVersionedHash = errors.New("mismatched versioned hash")
errPointEvaluationBadProof = errors.New("bad proof")
)

// RequiredGas returns the gas required to execute the pre-compiled contract.
func (c *pointEvaluation) RequiredGas(input []byte) uint64 {
return params.PointEvaluationGas
}

func (c *pointEvaluation) Run(input []byte) ([]byte, error) {
if len(input) != 192 {
return nil, errPointEvaluationInputLength
}

var versionedHash common.Hash
copy(versionedHash[:], input[:32])
// XXX Should we version check the hash?
if versionedHash[0] != params.BlobCommitmentVersionKZG {
return nil, errPointEvaluationInvalidVersionedHash
}

var x bls.Fr
var data [32]byte
copy(data[:], input[32:64])
ok := bls.FrFrom32(&x, data)
if !ok {
return nil, errPointEvaluationInvalidX
}

var y bls.Fr
copy(data[:], input[64:96])
ok = bls.FrFrom32(&y, data)
if !ok {
return nil, errPointEvaluationInvalidY
}

var commitment types.KZGCommitment
copy(commitment[:], input[96:144])
if commitment.ComputeVersionedHash() != versionedHash {
return nil, errPointEvaluationMismatchVersionedHash
}

parsedCommitment, err := commitment.Point()
if err != nil {
return nil, errPointEvaluationInvalidKzg
}

var proof types.KZGCommitment
copy(proof[:], input[144:192])
parsedProof, err := proof.Point()
if err != nil {
return nil, errPointEvaluationInvalidProof
}

if !kzg.VerifyKzgProof(parsedCommitment, &x, &y, parsedProof) {
return nil, errPointEvaluationBadProof
}

return []byte{}, nil
return kzg.PointEvaluationPrecompile(input)
}
15 changes: 0 additions & 15 deletions crypto/kzg/kzg.go
Original file line number Diff line number Diff line change
Expand Up @@ -50,21 +50,6 @@ func BlobToKzg(eval []bls.Fr) *bls.G1Point {
return bls.LinCombG1(kzgSetupLagrange, eval)
}

// Verify a KZG proof
func VerifyKzgProof(commitment *bls.G1Point, x *bls.Fr, y *bls.Fr, proof *bls.G1Point) bool {
// Verify the pairing equation
var xG2 bls.G2Point
bls.MulG2(&xG2, &bls.GenG2, x)
var sMinuxX bls.G2Point
bls.SubG2(&sMinuxX, &kzgSetupG2[1], &xG2)
var yG1 bls.G1Point
bls.MulG1(&yG1, &bls.GenG1, y)
var commitmentMinusY bls.G1Point
bls.SubG1(&commitmentMinusY, commitment, &yG1)

return bls.PairingsVerify(&commitmentMinusY, &bls.GenG2, proof, &sMinuxX)
}

type BlobsBatch struct {
sync.Mutex
init bool
Expand Down
94 changes: 94 additions & 0 deletions crypto/kzg/kzg_new.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
package kzg

import (
"errors"
"fmt"

"github.com/protolambda/go-kzg/bls"

"github.com/ethereum/go-ethereum/crypto"
"github.com/ethereum/go-ethereum/params"
)

// VerifyKZGProof implements verify_kzg_proof from the EIP-4844 consensus spec:
// https://github.com/ethereum/consensus-specs/blob/dev/specs/eip4844/polynomial-commitments.md#verify_kzg_proof
func VerifyKZGProof(polynomialKZG [48]byte, z *bls.Fr, y *bls.Fr, kzgProof [48]byte) (bool, error) {
polynomialKZGG1, err := bls.FromCompressedG1(polynomialKZG[:])
if err != nil {
return false, fmt.Errorf("failed to decode polynomialKZG: %v", err)
}
kzgProofG1, err := bls.FromCompressedG1(kzgProof[:])
if err != nil {
return false, fmt.Errorf("failed to decode kzgProof: %v", err)
}
return VerifyKZGProofFromPoints(polynomialKZGG1, z, y, kzgProofG1), nil
}

func VerifyKZGProofFromPoints(polynomialKZG *bls.G1Point, z *bls.Fr, y *bls.Fr, kzgProof *bls.G1Point) bool {
var zG2 bls.G2Point
bls.MulG2(&zG2, &bls.GenG2, z)
var yG1 bls.G1Point
bls.MulG1(&yG1, &bls.GenG1, y)

var xMinusZ bls.G2Point
bls.SubG2(&xMinusZ, &kzgSetupG2[1], &zG2)
var pMinusY bls.G1Point
bls.SubG1(&pMinusY, polynomialKZG, &yG1)

return bls.PairingsVerify(&pMinusY, &bls.GenG2, kzgProof, &xMinusZ)
}

// KZGToVersionedHash implements kzg_to_versioned_hash from EIP-4844
func KZGToVersionedHash(kzg [48]byte) [32]byte {
h := crypto.Keccak256Hash(kzg[:])
h[0] = params.BlobCommitmentVersionKZG
return h
}

// PointEvaluationPrecompile implements point_evaluation_precompile from EIP-4844
func PointEvaluationPrecompile(input []byte) ([]byte, error) {
if len(input) != 192 {
return nil, errors.New("invalid input length")
}

// versioned hash: first 32 bytes
var versionedHash [32]byte
copy(versionedHash[:], input[:32])

var x, y [32]byte
// Evaluation point: next 32 bytes
copy(x[:], input[32:64])
// Expected output: next 32 bytes
copy(y[:], input[64:96])

// successfully converting x and y to bls.Fr confirms they are < MODULUS per the spec
var xFr, yFr bls.Fr
ok := bls.FrFrom32(&xFr, x)
if !ok {
return nil, errors.New("invalid evaluation point")
}
ok = bls.FrFrom32(&yFr, y)
if !ok {
return nil, errors.New("invalid expected output")
}

// input kzg point: next 48 bytes
var dataKZG [48]byte
copy(dataKZG[:], input[96:144])
if KZGToVersionedHash(dataKZG) != versionedHash {
return nil, errors.New("mismatched versioned hash")
}

// Quotient kzg: next 48 bytes
var quotientKZG [48]byte
copy(quotientKZG[:], input[144:192])

ok, err := VerifyKZGProof(dataKZG, &xFr, &yFr, quotientKZG)
if err != nil {
return nil, fmt.Errorf("verify_kzg_proof error: %v", err)
}
if !ok {
return nil, errors.New("failed to verify kzg proof")
}
return []byte{}, nil
}
4 changes: 2 additions & 2 deletions tests/kzg_bench_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,7 @@ func BenchmarkVerifyBlobs(b *testing.B) {
}
}

func BenchmarkVerifyKzgProof(b *testing.B) {
func BenchmarkVerifyKZGProof(b *testing.B) {
// First let's do some go-kzg preparations to be able to convert polynomial between coefficient and evaluation form
fs := gokzg.NewFFTSettings(uint8(math.Log2(params.FieldElementsPerBlob)))

Expand Down Expand Up @@ -109,7 +109,7 @@ func BenchmarkVerifyKzgProof(b *testing.B) {
b.ResetTimer()
for i := 0; i < b.N; i++ {
// Verify kzg proof
if kzg.VerifyKzgProof(commitment, &xFr, &value, proof) != true {
if kzg.VerifyKZGProofFromPoints(commitment, &xFr, &value, proof) != true {
b.Fatal("failed proof verification")
}
}
Expand Down