diff --git a/beacon/engine/gen_epe.go b/beacon/engine/gen_epe.go index 664a50fc5b29..4a62f45a8ba3 100644 --- a/beacon/engine/gen_epe.go +++ b/beacon/engine/gen_epe.go @@ -18,11 +18,13 @@ func (e ExecutionPayloadEnvelope) MarshalJSON() ([]byte, error) { ExecutionPayload *ExecutableData `json:"executionPayload" gencodec:"required"` BlockValue *hexutil.Big `json:"blockValue" gencodec:"required"` BlobsBundle *BlobsBundleV1 `json:"blobsBundle"` + OverrideBuilder bool `json:"shouldOverrideBuilder" gencodec:"required"` } var enc ExecutionPayloadEnvelope enc.ExecutionPayload = e.ExecutionPayload enc.BlockValue = (*hexutil.Big)(e.BlockValue) enc.BlobsBundle = e.BlobsBundle + enc.OverrideBuilder = e.OverrideBuilder return json.Marshal(&enc) } @@ -32,6 +34,7 @@ func (e *ExecutionPayloadEnvelope) UnmarshalJSON(input []byte) error { ExecutionPayload *ExecutableData `json:"executionPayload" gencodec:"required"` BlockValue *hexutil.Big `json:"blockValue" gencodec:"required"` BlobsBundle *BlobsBundleV1 `json:"blobsBundle"` + OverrideBuilder *bool `json:"shouldOverrideBuilder" gencodec:"required"` } var dec ExecutionPayloadEnvelope if err := json.Unmarshal(input, &dec); err != nil { @@ -48,5 +51,9 @@ func (e *ExecutionPayloadEnvelope) UnmarshalJSON(input []byte) error { if dec.BlobsBundle != nil { e.BlobsBundle = dec.BlobsBundle } + if dec.OverrideBuilder == nil { + return errors.New("missing required field 'shouldOverrideBuilder' for ExecutionPayloadEnvelope") + } + e.OverrideBuilder = *dec.OverrideBuilder return nil } diff --git a/beacon/engine/types.go b/beacon/engine/types.go index d96bece8560b..afe7969e6c75 100644 --- a/beacon/engine/types.go +++ b/beacon/engine/types.go @@ -86,6 +86,7 @@ type ExecutionPayloadEnvelope struct { ExecutionPayload *ExecutableData `json:"executionPayload" gencodec:"required"` BlockValue *big.Int `json:"blockValue" gencodec:"required"` BlobsBundle *BlobsBundleV1 `json:"blobsBundle"` + OverrideBuilder bool `json:"shouldOverrideBuilder" gencodec:"required"` } type BlobsBundleV1 struct { diff --git a/core/blockchain.go b/core/blockchain.go index 3545e6b8ebec..9797cd2364af 100644 --- a/core/blockchain.go +++ b/core/blockchain.go @@ -215,7 +215,8 @@ type BlockChain struct { futureBlocks *lru.Cache[common.Hash, *types.Block] // Reorged transactions - droppedTxCache *lru.Cache[common.Hash, struct{}] + droppedTxCache *lru.Cache[common.Hash, int] + forceLocalBuilding bool wg sync.WaitGroup // quit chan struct{} // shutdown signal, closed in Stop. @@ -271,7 +272,7 @@ func NewBlockChain(db ethdb.Database, cacheConfig *CacheConfig, genesis *Genesis blockCache: lru.NewCache[common.Hash, *types.Block](blockCacheLimit), txLookupCache: lru.NewCache[common.Hash, *rawdb.LegacyTxLookupEntry](txLookupCacheLimit), futureBlocks: lru.NewCache[common.Hash, *types.Block](maxFutureBlocks), - droppedTxCache: lru.NewCache[common.Hash, struct{}](droppedTxCacheLimit), + droppedTxCache: lru.NewCache[common.Hash, int](droppedTxCacheLimit), engine: engine, vmConfig: vmConfig, } @@ -2155,10 +2156,15 @@ func (bc *BlockChain) reorg(oldHead *types.Header, newHead *types.Block) error { // transaction indexes, canonical chain indexes which above the head. indexesBatch := bc.db.NewBatch() for _, tx := range types.HashDifference(deletedTxs, addedTxs) { - if bc.droppedTxCache.Contains(tx) { - log.Warn("Transaction reorged twice", "hash", tx) + if key, ok := bc.droppedTxCache.Get(tx); ok { + if key > 2 { + // Transaction dropped at least three times + // indicates a censoring event + bc.forceLocalBuilding = true + } + bc.droppedTxCache.Add(tx, key+1) } else { - bc.droppedTxCache.Add(tx, struct{}{}) + bc.droppedTxCache.Add(tx, 1) } rawdb.DeleteTxLookupEntry(indexesBatch, tx) } diff --git a/core/blockchain_reader.go b/core/blockchain_reader.go index f9d0e3531f72..6778fb1e5bd2 100644 --- a/core/blockchain_reader.go +++ b/core/blockchain_reader.go @@ -411,3 +411,8 @@ func (bc *BlockChain) SubscribeLogsEvent(ch chan<- []*types.Log) event.Subscript func (bc *BlockChain) SubscribeBlockProcessingEvent(ch chan<- bool) event.Subscription { return bc.scope.Track(bc.blockProcFeed.Subscribe(ch)) } + +// ShouldForceLocalBuilding returns true if the node suspects transactions being censored. +func (bc *BlockChain) ShouldForceLocalBuilding() bool { + return bc.forceLocalBuilding +} diff --git a/eth/catalyst/api.go b/eth/catalyst/api.go index 2e3a236e00bc..3157f77efa1b 100644 --- a/eth/catalyst/api.go +++ b/eth/catalyst/api.go @@ -418,6 +418,7 @@ func (api *ConsensusAPI) getPayload(payloadID engine.PayloadID) (*engine.Executi if data == nil { return nil, engine.UnknownPayload } + data.OverrideBuilder = api.eth.BlockChain().ShouldForceLocalBuilding() return data, nil }