diff --git a/core/txpool/blobpool/blobpool.go b/core/txpool/blobpool/blobpool.go index 87aefb9756..2c50809716 100644 --- a/core/txpool/blobpool/blobpool.go +++ b/core/txpool/blobpool/blobpool.go @@ -1325,6 +1325,19 @@ func (p *BlobPool) GetBlobs(vhashes []common.Hash) []*types.BlobTxSidecar { return sidecars } +func (p *BlobPool) HasBlobs(vhashes []common.Hash) bool { + for _, vhash := range vhashes { + // Retrieve the datastore item (in a short lock) + p.lock.RLock() + _, exists := p.lookup.storeidOfBlob(vhash) + p.lock.RUnlock() + if !exists { + return false + } + } + return true +} + // Add inserts a set of blob transactions into the pool if they pass validation (both // consensus validity and pool restrictions). // diff --git a/core/txpool/legacypool/legacypool.go b/core/txpool/legacypool/legacypool.go index a69ff70251..bf1014d9e0 100644 --- a/core/txpool/legacypool/legacypool.go +++ b/core/txpool/legacypool/legacypool.go @@ -1068,6 +1068,12 @@ func (pool *LegacyPool) GetBlobs(vhashes []common.Hash) []*types.BlobTxSidecar { return nil } +// HasBlobs is not supported by the legacy transaction pool, it is just here to +// implement the txpool.SubPool interface. +func (pool *LegacyPool) HasBlobs(vhashes []common.Hash) bool { + return false +} + // Has returns an indicator whether txpool has a transaction cached with the // given hash. func (pool *LegacyPool) Has(hash common.Hash) bool { diff --git a/core/txpool/subpool.go b/core/txpool/subpool.go index 70595934a5..90f1d5d9e5 100644 --- a/core/txpool/subpool.go +++ b/core/txpool/subpool.go @@ -137,6 +137,10 @@ type SubPool interface { // retrieve blobs from the pools directly instead of the network. GetBlobs(vhashes []common.Hash) []*types.BlobTxSidecar + // HasBlobs returns true if all blobs corresponding to the versioned hashes + // are in the sub pool. + HasBlobs(vhashes []common.Hash) bool + // ValidateTxBasics checks whether a transaction is valid according to the consensus // rules, but does not check state-dependent validation such as sufficient balance. // This check is meant as a static check which can be performed without holding the diff --git a/core/txpool/txpool.go b/core/txpool/txpool.go index 5bc83bab58..666fdddcdb 100644 --- a/core/txpool/txpool.go +++ b/core/txpool/txpool.go @@ -323,6 +323,31 @@ func (p *TxPool) GetBlobs(vhashes []common.Hash) []*types.BlobTxSidecar { return nil } +// HasBlobs will return true if all the vhashes are available in the same subpool. +func (p *TxPool) HasBlobs(vhashes []common.Hash) bool { + for _, subpool := range p.subpools { + // It's an ugly to assume that only one pool will be capable of returning + // anything meaningful for this call, but anything else requires merging + // partial responses and that's too annoying to do until we get a second + // blobpool (probably never). + if subpool.HasBlobs(vhashes) { + return true + } + } + return false +} + +// ValidateTxBasics checks whether a transaction is valid according to the consensus +// rules, but does not check state-dependent validation such as sufficient balance. +func (p *TxPool) ValidateTxBasics(tx *types.Transaction) error { + for _, subpool := range p.subpools { + if subpool.Filter(tx) { + return subpool.ValidateTxBasics(tx) + } + } + return fmt.Errorf("%w: received type %d", core.ErrTxTypeNotSupported, tx.Type()) +} + // Add enqueues a batch of transactions into the pool if they are valid. Due // to the large transaction churn, add may postpone fully integrating the tx // to a later point to batch multiple ones together. diff --git a/eth/catalyst/api.go b/eth/catalyst/api.go index 13b85fc454..1c5390e7e3 100644 --- a/eth/catalyst/api.go +++ b/eth/catalyst/api.go @@ -593,6 +593,13 @@ func (api *ConsensusAPI) GetBlobsV2(hashes []common.Hash) ([]*engine.BlobAndProo if len(hashes) > 128 { return nil, engine.TooLargeRequest.With(fmt.Errorf("requested blob count too large: %v", len(hashes))) } + + // Optimization: check first if all blobs are available, if not, return empty response + if !api.eth.TxPool().HasBlobs(hashes) { + return nil, nil + } + + // pull up the blob hashes var ( res = make([]*engine.BlobAndProofV2, len(hashes)) index = make(map[common.Hash]int) diff --git a/miner/worker.go b/miner/worker.go index d80cb8913b..3423015247 100644 --- a/miner/worker.go +++ b/miner/worker.go @@ -32,6 +32,7 @@ import ( "github.com/ethereum/go-ethereum/core/txpool" "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/log" "github.com/ethereum/go-ethereum/params" "github.com/holiman/uint256" @@ -390,6 +391,17 @@ func (miner *Miner) commitTransactions(env *environment, plainTxs, blobTxs *tran continue } + if miner.chainConfig.IsOsaka(env.header.Number, env.header.Time) { + if sidecar := tx.BlobTxSidecar(); sidecar != nil { + if len(sidecar.Blobs) != len(sidecar.Proofs)*kzg4844.CellProofsPerBlob { + log.Warn("Ignoring V1 blob transaction post-Osaka", "hash", ltx.Hash) + txs.Pop() + continue + } + } + + } + // Error may be ignored here. The error has already been checked // during transaction acceptance in the transaction pool. from, _ := types.Sender(env.signer, tx)