Files
mev-beta/vendor/github.com/crate-crypto/go-eth-kzg/serialization.go

217 lines
8.2 KiB
Go

package goethkzg
import (
"fmt"
bls12381 "github.com/consensys/gnark-crypto/ecc/bls12-381"
"github.com/consensys/gnark-crypto/ecc/bls12-381/fr"
"github.com/crate-crypto/go-eth-kzg/internal/kzg"
"github.com/crate-crypto/go-eth-kzg/internal/utils"
)
// CompressedG1Size is the number of bytes needed to represent a group element in G1 when compressed.
const CompressedG1Size = 48
// CompressedG2Size is the number of bytes needed to represent a group element in G2 when compressed.
const CompressedG2Size = 96
// SerializedScalarSize is the number of bytes needed to represent a field element corresponding to the order of the G1
// group.
//
// It matches [BYTES_PER_FIELD_ELEMENT] in the spec.
//
// [BYTES_PER_FIELD_ELEMENT]: https://github.com/ethereum/consensus-specs/blob/017a8495f7671f5fff2075a9bfc9238c1a0982f8/specs/deneb/polynomial-commitments.md#constants
const SerializedScalarSize = 32
// ScalarsPerBlob is the number of serialized scalars in a blob.
//
// It matches [FIELD_ELEMENTS_PER_BLOB] in the spec.
//
// Note: These scalars are not guaranteed to be valid (a value less than [BLS_MODULUS]). If any of the scalars in a blob
// are invalid (non-canonical), an error will be returned on deserialization.
//
// [BLS_MODULUS]: https://github.com/ethereum/consensus-specs/blob/017a8495f7671f5fff2075a9bfc9238c1a0982f8/specs/deneb/polynomial-commitments.md#constants
// [FIELD_ELEMENTS_PER_BLOB]: https://github.com/ethereum/consensus-specs/blob/017a8495f7671f5fff2075a9bfc9238c1a0982f8/specs/deneb/polynomial-commitments.md#blob
const ScalarsPerBlob = 4096
// BytesPerCell is the number of bytes in a `Cell`.
const BytesPerCell = scalarsPerCell * SerializedScalarSize
// The number of cells in an extended blob.
const CellsPerExtBlob = 128
// scalarsPerCell is the number of scalars in a cell.
const scalarsPerCell = 64
// expansionFactor is the factor by which the number of
// scalars in a blob is expanded to create an extended blob.
const expansionFactor = 2
// scalarsPerExtBlob is the number of scalars in an extended blob.
//
// An extended blob is a blob that has been evaluated at more points than is needed
// to uniquely determine the polynomial its corresponding polynomial.
const scalarsPerExtBlob = expansionFactor * ScalarsPerBlob
type (
// G1Point matches [G1Point] in the spec.
//
// [G1Point]: https://github.com/ethereum/consensus-specs/blob/017a8495f7671f5fff2075a9bfc9238c1a0982f8/specs/deneb/polynomial-commitments.md#custom-types
G1Point [CompressedG1Size]byte
// G2Point matches [G2Point] in the spec.
//
// [G2Point]: https://github.com/ethereum/consensus-specs/blob/017a8495f7671f5fff2075a9bfc9238c1a0982f8/specs/deneb/polynomial-commitments.md#custom-types
G2Point [CompressedG2Size]byte
// Scalar matches [BLSFieldElement] in the spec.
//
// [BLSFieldElement]: https://github.com/ethereum/consensus-specs/blob/017a8495f7671f5fff2075a9bfc9238c1a0982f8/specs/deneb/polynomial-commitments.md#custom-types
Scalar [SerializedScalarSize]byte
// Blob is a flattened representation of a serialized polynomial.
//
// It matches [Blob] in the spec.
//
// [Blob]: https://github.com/ethereum/consensus-specs/blob/017a8495f7671f5fff2075a9bfc9238c1a0982f8/specs/deneb/polynomial-commitments.md#custom-types
Blob [ScalarsPerBlob * SerializedScalarSize]byte
// KZGProof is a serialized commitment to the quotient polynomial.
//
// It matches [KZGProof] in the spec.
//
// [KZGProof]: https://github.com/ethereum/consensus-specs/blob/017a8495f7671f5fff2075a9bfc9238c1a0982f8/specs/deneb/polynomial-commitments.md#custom-types
KZGProof G1Point
// KZGCommitment is a serialized commitment to a polynomial.
//
// It matches [KZGCommitment] in the spec.
//
// [KZGCommitment]: https://github.com/ethereum/consensus-specs/blob/017a8495f7671f5fff2075a9bfc9238c1a0982f8/specs/deneb/polynomial-commitments.md#custom-types
KZGCommitment G1Point
// Cell is a serialized version of a set of evaluations to a polynomial
Cell [BytesPerCell]byte
)
// SerializeG1Point converts a [bls12381.G1Affine] to [G1Point].
func SerializeG1Point(affine bls12381.G1Affine) G1Point {
return affine.Bytes()
}
// deserializeG1Point converts a [G1Point] to the internal [bls12381.G1Affine] type. It will return an error if the
// point is not on the group or if the point is not in the correct subgroup.
//
// It implements [validate_kzg_g1].
//
// [validate_kzg_g1]: https://github.com/ethereum/consensus-specs/blob/017a8495f7671f5fff2075a9bfc9238c1a0982f8/specs/deneb/polynomial-commitments.md#validate_kzg_g1
func deserializeG1Point(serPoint G1Point) (bls12381.G1Affine, error) {
var point bls12381.G1Affine
_, err := point.SetBytes(serPoint[:])
if err != nil {
return bls12381.G1Affine{}, err
}
return point, nil
}
// DeserializeKZGCommitment implements [bytes_to_kzg_commitment].
//
// [bytes_to_kzg_commitment]: https://github.com/ethereum/consensus-specs/blob/017a8495f7671f5fff2075a9bfc9238c1a0982f8/specs/deneb/polynomial-commitments.md#bytes_to_kzg_commitment
func DeserializeKZGCommitment(commitment KZGCommitment) (bls12381.G1Affine, error) {
return deserializeG1Point(G1Point(commitment))
}
// DeserializeKZGProof implements [bytes_to_kzg_proof].
//
// [bytes_to_kzg_proof]: https://github.com/ethereum/consensus-specs/blob/017a8495f7671f5fff2075a9bfc9238c1a0982f8/specs/deneb/polynomial-commitments.md#bytes_to_kzg_proof
func DeserializeKZGProof(proof KZGProof) (bls12381.G1Affine, error) {
return deserializeG1Point(G1Point(proof))
}
// DeserializeBlob implements [blob_to_polynomial].
//
// [blob_to_polynomial]: https://github.com/ethereum/consensus-specs/blob/017a8495f7671f5fff2075a9bfc9238c1a0982f8/specs/deneb/polynomial-commitments.md#blob_to_polynomial
func DeserializeBlob(blob *Blob) (kzg.Polynomial, error) {
if blob == nil {
return nil, ErrDeserializeNilInput
}
poly := make(kzg.Polynomial, ScalarsPerBlob)
for i := 0; i < ScalarsPerBlob; i++ {
chunk := blob[i*SerializedScalarSize : (i+1)*SerializedScalarSize]
if err := poly[i].SetBytesCanonical(chunk); err != nil {
return nil, ErrNonCanonicalScalar
}
}
return poly, nil
}
// DeserializeScalar implements [bytes_to_bls_field].
//
// Note: Returns an error if the scalar is not in the range [0, p-1] (inclusive) where `p` is the prime associated with the scalar field.
//
// [bytes_to_bls_field]: https://github.com/ethereum/consensus-specs/blob/017a8495f7671f5fff2075a9bfc9238c1a0982f8/specs/deneb/polynomial-commitments.md#bytes_to_bls_field
func DeserializeScalar(serScalar Scalar) (fr.Element, error) {
scalar, err := utils.ReduceCanonicalBigEndian(serScalar[:])
if err != nil {
return fr.Element{}, ErrNonCanonicalScalar
}
return scalar, nil
}
// SerializeScalar converts a [fr.Element] to [Scalar].
func SerializeScalar(element fr.Element) Scalar {
return element.Bytes()
}
// SerializePoly converts a [kzg.Polynomial] to [Blob].
//
// Note: This method is never used in the API because we always expect a byte array and will never receive deserialized
// field elements. We include it so that upstream fuzzers do not need to reimplement it.
func SerializePoly(poly kzg.Polynomial) *Blob {
if len(poly) != ScalarsPerBlob {
panic(fmt.Sprintf("expected polynomial to have size %d but it has size %d", ScalarsPerBlob, len(poly)))
}
var blob Blob
for i := 0; i < ScalarsPerBlob; i++ {
chunk := blob[i*SerializedScalarSize : (i+1)*SerializedScalarSize]
serScalar := SerializeScalar(poly[i])
copy(chunk, serScalar[:])
}
return &blob
}
// serializeEvaluations converts an array of scalars of size `scalarsPerCell` to [Cell].
func serializeEvaluations(evals *[scalarsPerCell]fr.Element) *Cell {
var cell Cell
for i := 0; i < scalarsPerCell; i++ {
chunk := cell[i*SerializedScalarSize : (i+1)*SerializedScalarSize]
serScalar := SerializeScalar(evals[i])
copy(chunk, serScalar[:])
}
return &cell
}
func deserializeCell(cell *Cell) ([]fr.Element, error) {
if cell == nil {
return nil, ErrDeserializeNilInput
}
evals := make([]fr.Element, scalarsPerCell)
for i := 0; i < scalarsPerCell; i++ {
chunk := cell[i*SerializedScalarSize : (i+1)*SerializedScalarSize]
chunk_arr := [SerializedScalarSize]byte{}
copy(chunk_arr[:], chunk)
eval, err := DeserializeScalar(chunk_arr)
if err != nil {
return nil, err
}
evals[i] = eval
}
return evals, nil
}