diff --git a/beacon/engine/types.go b/beacon/engine/types.go index 32cb7ca152..f91e18c27b 100644 --- a/beacon/engine/types.go +++ b/beacon/engine/types.go @@ -112,17 +112,21 @@ type ExecutionPayloadEnvelope struct { Witness *hexutil.Bytes `json:"witness,omitempty"` } +// Don't necessarily have to change to V2 (since it has the same fields as V1) in this PoC implementation. 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"` - CellProofs []hexutil.Bytes `json:"cellProofs"` // Added in Osaka for 7594 + Blob hexutil.Bytes `json:"blob"` + Proof hexutil.Bytes `json:"proof"` +} + +type BlobAndProofV2 struct { + Blob hexutil.Bytes `json:"blob"` + Proofs []hexutil.Bytes `json:"proofs"` } // JSON type overrides for ExecutionPayloadEnvelope. @@ -328,7 +332,6 @@ 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 { diff --git a/core/txpool/blobpool/blobpool.go b/core/txpool/blobpool/blobpool.go index 96f59f132f..2dcfa8f868 100644 --- a/core/txpool/blobpool/blobpool.go +++ b/core/txpool/blobpool/blobpool.go @@ -106,23 +106,30 @@ type blobTxMeta struct { evictionExecTip *uint256.Int // Worst gas tip across all previous nonces evictionExecFeeJumps float64 // Worst base fee (converted to fee jumps) across all previous nonces evictionBlobFeeJumps float64 // Worse blob fee (converted to fee jumps) across all previous nonces + + proofVersion uint64 // Version of the proof to use for this transaction } // newBlobTxMeta retrieves the indexed metadata fields from a blob transaction // and assembles a helper struct to track in memory. func newBlobTxMeta(id uint64, size uint32, tx *types.Transaction) *blobTxMeta { + proofVersion := uint64(0) + if len(tx.BlobTxSidecar().Blobs) != len(tx.BlobTxSidecar().Proofs) { + proofVersion = 1 // cell proofs + } meta := &blobTxMeta{ - hash: tx.Hash(), - vhashes: tx.BlobHashes(), - id: id, - size: size, - nonce: tx.Nonce(), - costCap: uint256.MustFromBig(tx.Cost()), - execTipCap: uint256.MustFromBig(tx.GasTipCap()), - execFeeCap: uint256.MustFromBig(tx.GasFeeCap()), - blobFeeCap: uint256.MustFromBig(tx.BlobGasFeeCap()), - execGas: tx.Gas(), - blobGas: tx.BlobGas(), + hash: tx.Hash(), + vhashes: tx.BlobHashes(), + id: id, + size: size, + nonce: tx.Nonce(), + costCap: uint256.MustFromBig(tx.Cost()), + execTipCap: uint256.MustFromBig(tx.GasTipCap()), + execFeeCap: uint256.MustFromBig(tx.GasFeeCap()), + blobFeeCap: uint256.MustFromBig(tx.BlobGasFeeCap()), + execGas: tx.Gas(), + blobGas: tx.BlobGas(), + proofVersion: proofVersion, } meta.basefeeJumps = dynamicFeeJumps(meta.execFeeCap) meta.blobfeeJumps = dynamicFeeJumps(meta.blobFeeCap) @@ -1639,6 +1646,11 @@ func (p *BlobPool) Pending(filter txpool.PendingFilter) map[common.Address][]*tx break // blobfee too low, cannot be included, discard rest of txs from the account } } + + if filter.OnlyBlobTxWithCellProofs && tx.proofVersion == 0 { + continue // not a blob tx with cell proofs, skip + } + // Transaction was accepted according to the filter, append to the pending list lazies = append(lazies, &txpool.LazyTransaction{ Pool: p, diff --git a/core/txpool/subpool.go b/core/txpool/subpool.go index 1392cfb274..33a9044683 100644 --- a/core/txpool/subpool.go +++ b/core/txpool/subpool.go @@ -82,8 +82,9 @@ type PendingFilter struct { BaseFee *uint256.Int // Minimum 1559 basefee needed to include a transaction BlobFee *uint256.Int // Minimum 4844 blobfee needed to include a blob transaction - OnlyPlainTxs bool // Return only plain EVM transactions (peer-join announces, block space filling) - OnlyBlobTxs bool // Return only blob transactions (block blob-space filling) + OnlyPlainTxs bool // Return only plain EVM transactions (peer-join announces, block space filling) + OnlyBlobTxs bool // Return only blob transactions (block blob-space filling) + OnlyBlobTxWithCellProofs bool // Return only blob transactions with cell proofs } // SubPool represents a specialized transaction pool that lives on its own (e.g. diff --git a/eth/catalyst/api.go b/eth/catalyst/api.go index 52c790f15c..115e3d0353 100644 --- a/eth/catalyst/api.go +++ b/eth/catalyst/api.go @@ -521,6 +521,14 @@ func (api *ConsensusAPI) GetPayloadV4(payloadID engine.PayloadID) (*engine.Execu return api.getPayload(payloadID, false) } +// GetPayloadV5 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 + } + return api.getPayload(payloadID, false) +} + func (api *ConsensusAPI) getPayload(payloadID engine.PayloadID, full bool) (*engine.ExecutionPayloadEnvelope, error) { log.Trace("Engine API request received", "method", "GetPayload", "id", payloadID) data := api.localBlocks.get(payloadID, full) @@ -538,27 +546,34 @@ func (api *ConsensusAPI) GetBlobsV1(hashes []common.Hash) ([]*engine.BlobAndProo res := make([]*engine.BlobAndProofV1, len(hashes)) blobs, proofs := api.eth.TxPool().GetBlobs(hashes) - // 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, - } + for i := 0; i < len(blobs); i++ { + if blobs[i] != nil { + res[i] = &engine.BlobAndProofV1{ + Blob: (*blobs[i])[:], + Proof: (*proofs[i])[:], } } - } 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 +} + +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, proofs := api.eth.TxPool().GetBlobs(hashes) + for i := 0; i < len(blobs); i++ { + if blobs[i] != nil { + res[i] = &engine.BlobAndProofV2{ + Blob: (*blobs[i])[:], + Proofs: make([]hexutil.Bytes, gokzg4844.CellsPerExtBlob), + } + + for j := 0; j < gokzg4844.CellsPerExtBlob; j++ { + res[i].Proofs[j] = hexutil.Bytes((*proofs[i*gokzg4844.CellsPerExtBlob+j])[:]) } } }