erigon-pulse/crypto/kzg/kzg.go
2023-07-11 17:53:00 +02:00

66 lines
1.6 KiB
Go

package kzg
import (
"errors"
"fmt"
"math/big"
gokzg4844 "github.com/crate-crypto/go-kzg-4844"
libkzg "github.com/ledgerwatch/erigon-lib/crypto/kzg"
)
const (
PrecompileInputLength int = 192
)
var (
errInvalidInputLength = errors.New("invalid input length")
// The value that gets returned when the `verify_kzg_proof“ precompile is called
precompileReturnValue [64]byte
)
// InitializeCrypytoCtx initializes the global context object returned via CryptoCtx
func init() {
new(big.Int).SetUint64(gokzg4844.ScalarsPerBlob).FillBytes(precompileReturnValue[:32])
copy(precompileReturnValue[32:], gokzg4844.BlsModulus[:])
}
// PointEvaluationPrecompile implements point_evaluation_precompile from EIP-4844
func PointEvaluationPrecompile(input []byte) ([]byte, error) {
if len(input) != PrecompileInputLength {
return nil, errInvalidInputLength
}
// 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])
// input kzg point: next 48 bytes
var dataKZG [48]byte
copy(dataKZG[:], input[96:144])
if libkzg.KZGToVersionedHash(dataKZG) != versionedHash {
return nil, errors.New("mismatched versioned hash")
}
// Quotient kzg: next 48 bytes
var quotientKZG [48]byte
copy(quotientKZG[:], input[144:PrecompileInputLength])
cryptoCtx := libkzg.Ctx()
err := cryptoCtx.VerifyKZGProof(dataKZG, x, y, quotientKZG)
if err != nil {
return nil, fmt.Errorf("verify_kzg_proof error: %v", err)
}
result := precompileReturnValue // copy the value
return result[:], nil
}