From fa664e7e59516d0ce2f9b6dceb2a846fc02ceb8e Mon Sep 17 00:00:00 2001 From: Marius van der Wijden Date: Fri, 14 Feb 2025 12:54:02 +0100 Subject: [PATCH] eth/catalyst: refactor latest fork check --- eth/catalyst/api.go | 38 +++++++++++++++++++++++++------------- 1 file changed, 25 insertions(+), 13 deletions(-) diff --git a/eth/catalyst/api.go b/eth/catalyst/api.go index e6f29c970b..25b01cf96c 100644 --- a/eth/catalyst/api.go +++ b/eth/catalyst/api.go @@ -180,6 +180,18 @@ func newConsensusAPIWithoutHeartbeat(eth *eth.Ethereum) *ConsensusAPI { return api } +// isLatestForkAt returns true if the latest fork at the given timestamp +// is one of the forks provided +func (api *ConsensusAPI) isLatestForkAt(timestamp uint64, forks ...forks.Fork) bool { + latest := api.eth.BlockChain().Config().LatestFork(timestamp) + for _, fork := range forks { + if latest == fork { + return true + } + } + return false +} + // ForkchoiceUpdatedV1 has several responsibilities: // // We try to set our blockchain to the headBlock. @@ -239,8 +251,8 @@ func (api *ConsensusAPI) ForkchoiceUpdatedV3(update engine.ForkchoiceStateV1, pa if params.BeaconRoot == nil { return engine.STATUS_INVALID, engine.InvalidPayloadAttributes.With(errors.New("missing beacon root")) } - if api.eth.BlockChain().Config().LatestFork(params.Timestamp) != forks.Cancun && api.eth.BlockChain().Config().LatestFork(params.Timestamp) != forks.Prague { - return engine.STATUS_INVALID, engine.UnsupportedFork.With(errors.New("forkchoiceUpdatedV3 must only be called for cancun payloads")) + if api.isLatestForkAt(params.Timestamp, forks.Cancun, forks.Prague) { + return engine.STATUS_INVALID, engine.UnsupportedFork.With(errors.New("forkchoiceUpdatedV3 must only be called for cancun or prague payloads")) } } // TODO(matt): the spec requires that fcu is applied when called on a valid @@ -297,8 +309,8 @@ func (api *ConsensusAPI) ForkchoiceUpdatedWithWitnessV3(update engine.Forkchoice if params.BeaconRoot == nil { return engine.STATUS_INVALID, engine.InvalidPayloadAttributes.With(errors.New("missing beacon root")) } - if api.eth.BlockChain().Config().LatestFork(params.Timestamp) != forks.Cancun && api.eth.BlockChain().Config().LatestFork(params.Timestamp) != forks.Prague { - return engine.STATUS_INVALID, engine.UnsupportedFork.With(errors.New("forkchoiceUpdatedV3 must only be called for cancun payloads")) + if api.isLatestForkAt(params.Timestamp, forks.Cancun, forks.Prague) { + return engine.STATUS_INVALID, engine.UnsupportedFork.With(errors.New("forkchoiceUpdatedV3 must only be called for cancun or prague payloads")) } } // TODO(matt): the spec requires that fcu is applied when called on a valid @@ -560,7 +572,7 @@ func (api *ConsensusAPI) NewPayloadV2(params engine.ExecutableData) (engine.Payl if api.eth.BlockChain().Config().IsCancun(api.eth.BlockChain().Config().LondonBlock, params.Timestamp) { return engine.PayloadStatusV1{Status: engine.INVALID}, engine.InvalidParams.With(errors.New("can't use newPayloadV2 post-cancun")) } - if api.eth.BlockChain().Config().LatestFork(params.Timestamp) == forks.Shanghai { + if api.isLatestForkAt(params.Timestamp, forks.Shanghai) { if params.Withdrawals == nil { return engine.PayloadStatusV1{Status: engine.INVALID}, engine.InvalidParams.With(errors.New("nil withdrawals post-shanghai")) } @@ -597,7 +609,7 @@ func (api *ConsensusAPI) NewPayloadV3(params engine.ExecutableData, versionedHas return engine.PayloadStatusV1{Status: engine.INVALID}, engine.InvalidParams.With(errors.New("nil beaconRoot post-cancun")) } - if api.eth.BlockChain().Config().LatestFork(params.Timestamp) != forks.Cancun { + if !api.isLatestForkAt(params.Timestamp, forks.Cancun) { return engine.PayloadStatusV1{Status: engine.INVALID}, engine.UnsupportedFork.With(errors.New("newPayloadV3 must only be called for cancun payloads")) } return api.newPayload(params, versionedHashes, beaconRoot, nil, false) @@ -625,7 +637,7 @@ func (api *ConsensusAPI) NewPayloadV4(params engine.ExecutableData, versionedHas return engine.PayloadStatusV1{Status: engine.INVALID}, engine.InvalidParams.With(errors.New("nil executionRequests post-prague")) } - if api.eth.BlockChain().Config().LatestFork(params.Timestamp) != forks.Prague { + if !api.isLatestForkAt(params.Timestamp, forks.Prague) { return engine.PayloadStatusV1{Status: engine.INVALID}, engine.UnsupportedFork.With(errors.New("newPayloadV4 must only be called for prague payloads")) } requests := convertRequests(executionRequests) @@ -650,7 +662,7 @@ func (api *ConsensusAPI) NewPayloadWithWitnessV2(params engine.ExecutableData) ( if api.eth.BlockChain().Config().IsCancun(api.eth.BlockChain().Config().LondonBlock, params.Timestamp) { return engine.PayloadStatusV1{Status: engine.INVALID}, engine.InvalidParams.With(errors.New("can't use newPayloadV2 post-cancun")) } - if api.eth.BlockChain().Config().LatestFork(params.Timestamp) == forks.Shanghai { + if api.isLatestForkAt(params.Timestamp, forks.Shanghai) { if params.Withdrawals == nil { return engine.PayloadStatusV1{Status: engine.INVALID}, engine.InvalidParams.With(errors.New("nil withdrawals post-shanghai")) } @@ -688,7 +700,7 @@ func (api *ConsensusAPI) NewPayloadWithWitnessV3(params engine.ExecutableData, v return engine.PayloadStatusV1{Status: engine.INVALID}, engine.InvalidParams.With(errors.New("nil beaconRoot post-cancun")) } - if api.eth.BlockChain().Config().LatestFork(params.Timestamp) != forks.Cancun { + if !api.isLatestForkAt(params.Timestamp, forks.Cancun) { return engine.PayloadStatusV1{Status: engine.INVALID}, engine.UnsupportedFork.With(errors.New("newPayloadWithWitnessV3 must only be called for cancun payloads")) } return api.newPayload(params, versionedHashes, beaconRoot, nil, true) @@ -717,7 +729,7 @@ func (api *ConsensusAPI) NewPayloadWithWitnessV4(params engine.ExecutableData, v return engine.PayloadStatusV1{Status: engine.INVALID}, engine.InvalidParams.With(errors.New("nil executionRequests post-prague")) } - if api.eth.BlockChain().Config().LatestFork(params.Timestamp) != forks.Prague { + if !api.isLatestForkAt(params.Timestamp, forks.Prague) { return engine.PayloadStatusV1{Status: engine.INVALID}, engine.UnsupportedFork.With(errors.New("newPayloadWithWitnessV4 must only be called for prague payloads")) } requests := convertRequests(executionRequests) @@ -742,7 +754,7 @@ func (api *ConsensusAPI) ExecuteStatelessPayloadV2(params engine.ExecutableData, if api.eth.BlockChain().Config().IsCancun(api.eth.BlockChain().Config().LondonBlock, params.Timestamp) { return engine.StatelessPayloadStatusV1{Status: engine.INVALID}, engine.InvalidParams.With(errors.New("can't use newPayloadV2 post-cancun")) } - if api.eth.BlockChain().Config().LatestFork(params.Timestamp) == forks.Shanghai { + if api.isLatestForkAt(params.Timestamp, forks.Shanghai) { if params.Withdrawals == nil { return engine.StatelessPayloadStatusV1{Status: engine.INVALID}, engine.InvalidParams.With(errors.New("nil withdrawals post-shanghai")) } @@ -780,7 +792,7 @@ func (api *ConsensusAPI) ExecuteStatelessPayloadV3(params engine.ExecutableData, return engine.StatelessPayloadStatusV1{Status: engine.INVALID}, engine.InvalidParams.With(errors.New("nil beaconRoot post-cancun")) } - if api.eth.BlockChain().Config().LatestFork(params.Timestamp) != forks.Cancun { + if !api.isLatestForkAt(params.Timestamp, forks.Cancun) { return engine.StatelessPayloadStatusV1{Status: engine.INVALID}, engine.UnsupportedFork.With(errors.New("executeStatelessPayloadV3 must only be called for cancun payloads")) } return api.executeStatelessPayload(params, versionedHashes, beaconRoot, nil, opaqueWitness) @@ -809,7 +821,7 @@ func (api *ConsensusAPI) ExecuteStatelessPayloadV4(params engine.ExecutableData, return engine.StatelessPayloadStatusV1{Status: engine.INVALID}, engine.InvalidParams.With(errors.New("nil executionRequests post-prague")) } - if api.eth.BlockChain().Config().LatestFork(params.Timestamp) != forks.Prague { + if !api.isLatestForkAt(params.Timestamp, forks.Prague) { return engine.StatelessPayloadStatusV1{Status: engine.INVALID}, engine.UnsupportedFork.With(errors.New("executeStatelessPayloadV4 must only be called for prague payloads")) } requests := convertRequests(executionRequests)