Implement fulu related change to getblobsv1 and getpayloadv4

This commit is contained in:
Francis Li 2025-03-20 15:53:12 -07:00
parent 2e2eebe252
commit c4be2bbd19
No known key found for this signature in database
GPG key ID: 39F1A72C987F3F88
4 changed files with 100 additions and 13 deletions

View file

@ -116,11 +116,13 @@ type BlobsBundleV1 struct {
Commitments []hexutil.Bytes `json:"commitments"`
Proofs []hexutil.Bytes `json:"proofs"`
Blobs []hexutil.Bytes `json:"blobs"`
CellProofs []hexutil.Bytes `json:"cellProofs"` // Added in Osaka for 7594
}
type BlobAndProofV1 struct {
Blob hexutil.Bytes `json:"blob"`
Proof hexutil.Bytes `json:"proof"`
Blob hexutil.Bytes `json:"blob"`
Proof hexutil.Bytes `json:"proof"`
CellProofs []hexutil.Bytes `json:"cellProofs"` // Added in Osaka for 7594
}
// JSON type overrides for ExecutionPayloadEnvelope.
@ -326,6 +328,7 @@ 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 {

View file

@ -29,6 +29,8 @@ import (
"sync"
"time"
gokzg4844 "github.com/crate-crypto/go-eth-kzg"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/consensus/misc/eip1559"
"github.com/ethereum/go-ethereum/consensus/misc/eip4844"
@ -1239,7 +1241,12 @@ func (p *BlobPool) GetRLP(hash common.Hash) []byte {
// GetBlobs returns a number of blobs are proofs for the given versioned hashes.
// This is a utility method for the engine API, enabling consensus clients to
// retrieve blobs from the pools directly instead of the network.
// After Osaka, the proofs are returned as cell proofs.
func (p *BlobPool) GetBlobs(vhashes []common.Hash) ([]*kzg4844.Blob, []*kzg4844.Proof) {
if p.chain.Config().IsOsaka(p.head.Number, p.head.Time) {
return p.GetBlobsWithCellProofs(vhashes)
}
// Create a map of the blob hash to indices for faster fills
var (
blobs = make([]*kzg4844.Blob, len(vhashes))
@ -1285,6 +1292,64 @@ func (p *BlobPool) GetBlobs(vhashes []common.Hash) ([]*kzg4844.Blob, []*kzg4844.
}
}
}
return blobs, proofs
}
// GetBlobsWithCellProofs returns a number of blobs and cell proofs for the given versioned hashes after Osaka.
func (p *BlobPool) GetBlobsWithCellProofs(vhashes []common.Hash) ([]*kzg4844.Blob, []*kzg4844.Proof) {
var (
blobs = make([]*kzg4844.Blob, len(vhashes))
proofs = make([]*kzg4844.Proof, len(vhashes)*gokzg4844.CellsPerExtBlob)
)
index := make(map[common.Hash]int)
for i, vhash := range vhashes {
index[vhash] = i
}
for i, vhash := range vhashes {
if blobs[i] != nil {
continue
}
p.lock.RLock()
id, exists := p.lookup.storeidOfBlob(vhash)
if !exists {
p.lock.RUnlock()
continue
}
data, err := p.store.Get(id)
p.lock.RUnlock()
if err != nil {
log.Error("Tracked blob transaction missing from store", "id", id, "err", err)
continue
}
item := new(types.Transaction)
if err = rlp.DecodeBytes(data, item); err != nil {
log.Error("Blobs corrupted for traced transaction", "id", id, "err", err)
continue
}
sidecar := item.BlobTxSidecar()
if len(sidecar.Blobs)*gokzg4844.CellsPerExtBlob != len(sidecar.Proofs) {
log.Warn("potentially old blob tx with blob proofs, dropping it")
//TODO: implement dropping of blob txs
continue
}
for j, blobhash := range item.BlobHashes() {
if idx, ok := index[blobhash]; ok {
blobs[idx] = &sidecar.Blobs[j]
proofStart := idx * gokzg4844.CellsPerExtBlob
sidecarStart := j * gokzg4844.CellsPerExtBlob
for k := 0; k < gokzg4844.CellsPerExtBlob; k++ {
proofs[proofStart+k] = &sidecar.Proofs[sidecarStart+k]
}
}
}
}
return blobs, proofs
}

View file

@ -169,7 +169,7 @@ func ValidateTransaction(tx *types.Transaction, head *types.Header, signer types
func validateBlobSidecar(cfg *params.ChainConfig, time uint64, hashes []common.Hash, sidecar *types.BlobTxSidecar) error {
if len(sidecar.Blobs) != len(hashes) {
return fmt.Errorf("invalid number of %d blobs compared to %d blob hashes", ErrInvalidBlobSidecar, len(sidecar.Blobs), len(hashes))
return fmt.Errorf("%w: invalid number of %d blobs compared to %d blob hashes", ErrInvalidBlobSidecar, len(sidecar.Blobs), len(hashes))
}
if err := sidecar.ValidateBlobCommitmentHashes(hashes); err != nil {
return err
@ -178,7 +178,7 @@ func validateBlobSidecar(cfg *params.ChainConfig, time uint64, hashes []common.H
fork := cfg.LatestFork(time)
if fork >= forks.Osaka {
if len(sidecar.Blobs)*gokzg4844.CellsPerExtBlob != len(sidecar.Proofs) {
return fmt.Errorf("invalid number of %d cell proofs compared to %d blobs", ErrInvalidBlobSidecar, len(sidecar.Proofs), len(sidecar.Blobs))
return fmt.Errorf("%w: invalid number of %d cell proofs compared to %d blobs", ErrInvalidBlobSidecar, len(sidecar.Proofs), len(sidecar.Blobs))
}
// Prepare cells and cell indices for each blob
@ -189,7 +189,7 @@ func validateBlobSidecar(cfg *params.ChainConfig, time uint64, hashes []common.H
// Compute cells for the currentblob
blobCells, err := kzg4844.ComputeCells(&sidecar.Blobs[i])
if err != nil {
return fmt.Errorf("failed to compute cells for blob %d: %v", ErrInvalidBlobSidecar, i, err)
return fmt.Errorf("%w: failed to compute cells for blob %d: %v", ErrInvalidBlobSidecar, i, err)
}
cells = append(cells, blobCells...)
@ -199,18 +199,18 @@ func validateBlobSidecar(cfg *params.ChainConfig, time uint64, hashes []common.H
}
if err := kzg4844.VerifyCellKZGProofBatch(sidecar.Commitments, cellIndices, cells, sidecar.Proofs); err != nil {
return fmt.Errorf("failed to verify cell proofs: %v", ErrInvalidBlobSidecar, err)
return fmt.Errorf("%w: failed to verify cell proofs: %v", ErrInvalidBlobSidecar, err)
}
} else { // older folks
if len(sidecar.Proofs) != len(hashes) {
return fmt.Errorf("invalid number of %d blob proofs compared to %d blob hashes", ErrInvalidBlobSidecar, len(sidecar.Proofs), len(hashes))
return fmt.Errorf("%w: invalid number of %d blob proofs compared to %d blob hashes", ErrInvalidBlobSidecar, len(sidecar.Proofs), len(hashes))
}
// Blob commitments match with the hashes in the transaction, verify the
// blobs themselves via KZG
for i := range sidecar.Blobs {
if err := kzg4844.VerifyBlobProof(&sidecar.Blobs[i], sidecar.Commitments[i], sidecar.Proofs[i]); err != nil {
return fmt.Errorf("invalid blob %d: %v", ErrInvalidBlobSidecar, i, err)
return fmt.Errorf("%w: invalid blob %d: %v", ErrInvalidBlobSidecar, i, err)
}
}
}

View file

@ -24,6 +24,8 @@ import (
"sync"
"time"
gokzg4844 "github.com/crate-crypto/go-eth-kzg"
"github.com/ethereum/go-ethereum/beacon/engine"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/common/hexutil"
@ -536,14 +538,31 @@ func (api *ConsensusAPI) GetBlobsV1(hashes []common.Hash) ([]*engine.BlobAndProo
res := make([]*engine.BlobAndProofV1, len(hashes))
blobs, proofs := api.eth.TxPool().GetBlobs(hashes)
for i := 0; i < len(blobs); i++ {
if blobs[i] != nil {
res[i] = &engine.BlobAndProofV1{
Blob: (*blobs[i])[:],
Proof: (*proofs[i])[:],
// after Osaka, the proofs are returned as cell proofs.
if len(blobs) != len(proofs) {
for i := range blobs {
if blobs[i] != nil {
cellProofs := make([]hexutil.Bytes, gokzg4844.CellsPerExtBlob)
for j := range cellProofs {
cellProofs[j] = hexutil.Bytes((*proofs[i*gokzg4844.CellsPerExtBlob+j])[:])
}
res[i] = &engine.BlobAndProofV1{
Blob: (*blobs[i])[:],
CellProofs: cellProofs,
}
}
}
} else {
for i := 0; i < len(blobs); i++ {
if blobs[i] != nil {
res[i] = &engine.BlobAndProofV1{
Blob: (*blobs[i])[:],
Proof: (*proofs[i])[:],
}
}
}
}
return res, nil
}