From f4e5e73edf3c7da15842d91737a6fb34beba730f Mon Sep 17 00:00:00 2001 From: Marius van der Wijden Date: Tue, 11 Mar 2025 12:54:40 +0100 Subject: [PATCH] eth/catalyst: implement getBlobsV2 --- beacon/engine/types.go | 15 +++++++++++ crypto/kzg4844/kzg4844.go | 8 ++++++ eth/catalyst/api.go | 55 +++++++++++++++++++++++++++++++++++++-- go.mod | 1 + 4 files changed, 77 insertions(+), 2 deletions(-) diff --git a/beacon/engine/types.go b/beacon/engine/types.go index 3e52933a90..c305507dbb 100644 --- a/beacon/engine/types.go +++ b/beacon/engine/types.go @@ -24,6 +24,7 @@ import ( "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common/hexutil" "github.com/ethereum/go-ethereum/core/types" + "github.com/ethereum/go-ethereum/crypto/kzg4844" "github.com/ethereum/go-ethereum/params" "github.com/ethereum/go-ethereum/trie" ) @@ -116,6 +117,7 @@ type BlobsBundleV1 struct { Commitments []hexutil.Bytes `json:"commitments"` Proofs []hexutil.Bytes `json:"proofs"` Blobs []hexutil.Bytes `json:"blobs"` + CellProofs []hexutil.Bytes `json:"cell_proofs"` } type BlobAndProofV1 struct { @@ -123,6 +125,11 @@ type BlobAndProofV1 struct { Proof hexutil.Bytes `json:"proof"` } +type BlobAndProofV2 struct { + Blob hexutil.Bytes `json:"blob"` + CellProofs []hexutil.Bytes `json:"cell_proofs"` +} + // JSON type overrides for ExecutionPayloadEnvelope. type executionPayloadEnvelopeMarshaling struct { BlockValue *hexutil.Big @@ -326,12 +333,20 @@ func BlockToExecutableData(block *types.Block, fees *big.Int, sidecars []*types. Commitments: make([]hexutil.Bytes, 0), Blobs: make([]hexutil.Bytes, 0), Proofs: make([]hexutil.Bytes, 0), + CellProofs: make([]hexutil.Bytes, 0), } for _, sidecar := range sidecars { for j := range sidecar.Blobs { bundle.Blobs = append(bundle.Blobs, hexutil.Bytes(sidecar.Blobs[j][:])) bundle.Commitments = append(bundle.Commitments, hexutil.Bytes(sidecar.Commitments[j][:])) bundle.Proofs = append(bundle.Proofs, hexutil.Bytes(sidecar.Proofs[j][:])) + cellProofs, err := kzg4844.ComputeCells(&sidecar.Blobs[j]) + if err != nil { + panic(err) + } + for _, proof := range cellProofs { + bundle.CellProofs = append(bundle.CellProofs, hexutil.Bytes(proof[:])) + } } } diff --git a/crypto/kzg4844/kzg4844.go b/crypto/kzg4844/kzg4844.go index 0a2478cea0..1e1fc8ef87 100644 --- a/crypto/kzg4844/kzg4844.go +++ b/crypto/kzg4844/kzg4844.go @@ -84,6 +84,10 @@ type Claim [32]byte // useCKZG controls whether the cryptography should use the Go or C backend. var useCKZG atomic.Bool +func init() { + UseCKZG(true) +} + // UseCKZG can be called to switch the default Go implementation of KZG to the C // library if for some reason the user wishes to do so (e.g. consensus bug in one // or the other). @@ -177,3 +181,7 @@ func CalcBlobHashV1(hasher hash.Hash, commit *Commitment) (vh [32]byte) { func IsValidVersionedHash(h []byte) bool { return len(h) == 32 && h[0] == 0x01 } + +func ComputeCells(blob *Blob) ([]Proof, error) { + return ckzgComputeCells(blob) +} diff --git a/eth/catalyst/api.go b/eth/catalyst/api.go index 4493c1fcbb..fbefbfe6b7 100644 --- a/eth/catalyst/api.go +++ b/eth/catalyst/api.go @@ -32,6 +32,7 @@ import ( "github.com/ethereum/go-ethereum/core/stateless" "github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/core/vm" + "github.com/ethereum/go-ethereum/crypto/kzg4844" "github.com/ethereum/go-ethereum/eth" "github.com/ethereum/go-ethereum/eth/ethconfig" "github.com/ethereum/go-ethereum/internal/version" @@ -511,7 +512,12 @@ func (api *ConsensusAPI) GetPayloadV3(payloadID engine.PayloadID) (*engine.Execu if !payloadID.Is(engine.PayloadV3) { return nil, engine.UnsupportedFork } - return api.getPayload(payloadID, false) + envelope, err := api.getPayload(payloadID, false) + if err != nil { + return nil, err + } + envelope.BlobsBundle.CellProofs = nil + return envelope, nil } // GetPayloadV4 returns a cached payload by id. @@ -519,7 +525,25 @@ func (api *ConsensusAPI) GetPayloadV4(payloadID engine.PayloadID) (*engine.Execu if !payloadID.Is(engine.PayloadV3) { return nil, engine.UnsupportedFork } - return api.getPayload(payloadID, false) + envelope, err := api.getPayload(payloadID, false) + if err != nil { + return nil, err + } + envelope.BlobsBundle.CellProofs = nil + return envelope, nil +} + +// GetPayloadV4 returns a cached payload by id. +func (api *ConsensusAPI) GetPayloadV5(payloadID engine.PayloadID) (*engine.ExecutionPayloadEnvelope, error) { + if !payloadID.Is(engine.PayloadV3) { + return nil, engine.UnsupportedFork + } + envelope, err := api.getPayload(payloadID, false) + if err != nil { + return nil, err + } + envelope.BlobsBundle.Proofs = nil + return envelope, nil } func (api *ConsensusAPI) getPayload(payloadID engine.PayloadID, full bool) (*engine.ExecutionPayloadEnvelope, error) { @@ -550,6 +574,33 @@ func (api *ConsensusAPI) GetBlobsV1(hashes []common.Hash) ([]*engine.BlobAndProo return res, nil } +// GetBlobsV2 returns a blob from the transaction pool. +func (api *ConsensusAPI) GetBlobsV2(hashes []common.Hash) ([]*engine.BlobAndProofV2, error) { + if len(hashes) > 128 { + return nil, engine.TooLargeRequest.With(fmt.Errorf("requested blob count too large: %v", len(hashes))) + } + res := make([]*engine.BlobAndProofV2, len(hashes)) + + blobs, _ := api.eth.TxPool().GetBlobs(hashes) + for i := 0; i < len(blobs); i++ { + if blobs[i] != nil { + cellProofs, err := kzg4844.ComputeCells(blobs[i]) + if err != nil { + return nil, err + } + var proofs []hexutil.Bytes + for _, proof := range cellProofs { + proofs = append(proofs, hexutil.Bytes(proof[:])) + } + res[i] = &engine.BlobAndProofV2{ + Blob: (*blobs[i])[:], + CellProofs: proofs, + } + } + } + return res, nil +} + // NewPayloadV1 creates an Eth1 block, inserts it in the chain, and returns the status of the chain. func (api *ConsensusAPI) NewPayloadV1(params engine.ExecutableData) (engine.PayloadStatusV1, error) { if params.Withdrawals != nil { diff --git a/go.mod b/go.mod index 924f0d2642..57315875fb 100644 --- a/go.mod +++ b/go.mod @@ -103,6 +103,7 @@ require ( github.com/cpuguy83/go-md2man/v2 v2.0.5 // indirect github.com/deepmap/oapi-codegen v1.6.0 // indirect github.com/dlclark/regexp2 v1.7.0 // indirect + github.com/ethereum/c-kzg-4844/v2 v2.0.1 // indirect github.com/garslo/gogen v0.0.0-20170306192744-1d203ffc1f61 // indirect github.com/getsentry/sentry-go v0.27.0 // indirect github.com/go-ole/go-ole v1.3.0 // indirect