eth/catalyst: prefix payload id with version (#28246)
GetPayloadVX should only return payloads which match its version. GetPayloadV2 is a special snowflake that supports v1 and v2 payloads. This change uses a a version-specific prefix within in the payload id, basically a namespace for the version number.
This commit is contained in:
parent
6b0de79935
commit
a8a87586c1
@ -26,6 +26,16 @@ import (
|
|||||||
"github.com/ethereum/go-ethereum/trie"
|
"github.com/ethereum/go-ethereum/trie"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// PayloadVersion denotes the version of PayloadAttributes used to request the
|
||||||
|
// building of the payload to commence.
|
||||||
|
type PayloadVersion byte
|
||||||
|
|
||||||
|
var (
|
||||||
|
PayloadV1 PayloadVersion = 0x1
|
||||||
|
PayloadV2 PayloadVersion = 0x2
|
||||||
|
PayloadV3 PayloadVersion = 0x3
|
||||||
|
)
|
||||||
|
|
||||||
//go:generate go run github.com/fjl/gencodec -type PayloadAttributes -field-override payloadAttributesMarshaling -out gen_blockparams.go
|
//go:generate go run github.com/fjl/gencodec -type PayloadAttributes -field-override payloadAttributesMarshaling -out gen_blockparams.go
|
||||||
|
|
||||||
// PayloadAttributes describes the environment context in which a block should
|
// PayloadAttributes describes the environment context in which a block should
|
||||||
@ -115,6 +125,21 @@ type TransitionConfigurationV1 struct {
|
|||||||
// PayloadID is an identifier of the payload build process
|
// PayloadID is an identifier of the payload build process
|
||||||
type PayloadID [8]byte
|
type PayloadID [8]byte
|
||||||
|
|
||||||
|
// Version returns the payload version associated with the identifier.
|
||||||
|
func (b PayloadID) Version() PayloadVersion {
|
||||||
|
return PayloadVersion(b[0])
|
||||||
|
}
|
||||||
|
|
||||||
|
// Is returns whether the identifier matches any of provided payload versions.
|
||||||
|
func (b PayloadID) Is(versions ...PayloadVersion) bool {
|
||||||
|
for _, v := range versions {
|
||||||
|
if v == b.Version() {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
func (b PayloadID) String() string {
|
func (b PayloadID) String() string {
|
||||||
return hexutil.Encode(b[:])
|
return hexutil.Encode(b[:])
|
||||||
}
|
}
|
||||||
|
@ -180,7 +180,7 @@ func (api *ConsensusAPI) ForkchoiceUpdatedV1(update engine.ForkchoiceStateV1, pa
|
|||||||
return engine.STATUS_INVALID, engine.InvalidParams.With(errors.New("forkChoiceUpdateV1 called post-shanghai"))
|
return engine.STATUS_INVALID, engine.InvalidParams.With(errors.New("forkChoiceUpdateV1 called post-shanghai"))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return api.forkchoiceUpdated(update, payloadAttributes, false)
|
return api.forkchoiceUpdated(update, payloadAttributes, engine.PayloadV1, false)
|
||||||
}
|
}
|
||||||
|
|
||||||
// ForkchoiceUpdatedV2 is equivalent to V1 with the addition of withdrawals in the payload attributes.
|
// ForkchoiceUpdatedV2 is equivalent to V1 with the addition of withdrawals in the payload attributes.
|
||||||
@ -196,7 +196,7 @@ func (api *ConsensusAPI) ForkchoiceUpdatedV2(update engine.ForkchoiceStateV1, pa
|
|||||||
return engine.STATUS_INVALID, engine.UnsupportedFork.With(errors.New("forkchoiceUpdatedV2 must only be called for shanghai payloads"))
|
return engine.STATUS_INVALID, engine.UnsupportedFork.With(errors.New("forkchoiceUpdatedV2 must only be called for shanghai payloads"))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return api.forkchoiceUpdated(update, params, false)
|
return api.forkchoiceUpdated(update, params, engine.PayloadV2, false)
|
||||||
}
|
}
|
||||||
|
|
||||||
// ForkchoiceUpdatedV3 is equivalent to V2 with the addition of parent beacon block root in the payload attributes.
|
// ForkchoiceUpdatedV3 is equivalent to V2 with the addition of parent beacon block root in the payload attributes.
|
||||||
@ -220,10 +220,10 @@ func (api *ConsensusAPI) ForkchoiceUpdatedV3(update engine.ForkchoiceStateV1, pa
|
|||||||
// hash, even if params are wrong. To do this we need to split up
|
// hash, even if params are wrong. To do this we need to split up
|
||||||
// forkchoiceUpdate into a function that only updates the head and then a
|
// forkchoiceUpdate into a function that only updates the head and then a
|
||||||
// function that kicks off block construction.
|
// function that kicks off block construction.
|
||||||
return api.forkchoiceUpdated(update, params, false)
|
return api.forkchoiceUpdated(update, params, engine.PayloadV3, false)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (api *ConsensusAPI) forkchoiceUpdated(update engine.ForkchoiceStateV1, payloadAttributes *engine.PayloadAttributes, simulatorMode bool) (engine.ForkChoiceResponse, error) {
|
func (api *ConsensusAPI) forkchoiceUpdated(update engine.ForkchoiceStateV1, payloadAttributes *engine.PayloadAttributes, payloadVersion engine.PayloadVersion, simulatorMode bool) (engine.ForkChoiceResponse, error) {
|
||||||
api.forkchoiceLock.Lock()
|
api.forkchoiceLock.Lock()
|
||||||
defer api.forkchoiceLock.Unlock()
|
defer api.forkchoiceLock.Unlock()
|
||||||
|
|
||||||
@ -367,6 +367,7 @@ func (api *ConsensusAPI) forkchoiceUpdated(update engine.ForkchoiceStateV1, payl
|
|||||||
Random: payloadAttributes.Random,
|
Random: payloadAttributes.Random,
|
||||||
Withdrawals: payloadAttributes.Withdrawals,
|
Withdrawals: payloadAttributes.Withdrawals,
|
||||||
BeaconRoot: payloadAttributes.BeaconRoot,
|
BeaconRoot: payloadAttributes.BeaconRoot,
|
||||||
|
Version: payloadVersion,
|
||||||
}
|
}
|
||||||
id := args.Id()
|
id := args.Id()
|
||||||
// If we already are busy generating this work, then we do not need
|
// If we already are busy generating this work, then we do not need
|
||||||
@ -430,6 +431,9 @@ func (api *ConsensusAPI) ExchangeTransitionConfigurationV1(config engine.Transit
|
|||||||
|
|
||||||
// GetPayloadV1 returns a cached payload by id.
|
// GetPayloadV1 returns a cached payload by id.
|
||||||
func (api *ConsensusAPI) GetPayloadV1(payloadID engine.PayloadID) (*engine.ExecutableData, error) {
|
func (api *ConsensusAPI) GetPayloadV1(payloadID engine.PayloadID) (*engine.ExecutableData, error) {
|
||||||
|
if !payloadID.Is(engine.PayloadV1) {
|
||||||
|
return nil, engine.UnsupportedFork
|
||||||
|
}
|
||||||
data, err := api.getPayload(payloadID, false)
|
data, err := api.getPayload(payloadID, false)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
@ -439,11 +443,17 @@ func (api *ConsensusAPI) GetPayloadV1(payloadID engine.PayloadID) (*engine.Execu
|
|||||||
|
|
||||||
// GetPayloadV2 returns a cached payload by id.
|
// GetPayloadV2 returns a cached payload by id.
|
||||||
func (api *ConsensusAPI) GetPayloadV2(payloadID engine.PayloadID) (*engine.ExecutionPayloadEnvelope, error) {
|
func (api *ConsensusAPI) GetPayloadV2(payloadID engine.PayloadID) (*engine.ExecutionPayloadEnvelope, error) {
|
||||||
|
if !payloadID.Is(engine.PayloadV1, engine.PayloadV2) {
|
||||||
|
return nil, engine.UnsupportedFork
|
||||||
|
}
|
||||||
return api.getPayload(payloadID, false)
|
return api.getPayload(payloadID, false)
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetPayloadV3 returns a cached payload by id.
|
// GetPayloadV3 returns a cached payload by id.
|
||||||
func (api *ConsensusAPI) GetPayloadV3(payloadID engine.PayloadID) (*engine.ExecutionPayloadEnvelope, error) {
|
func (api *ConsensusAPI) GetPayloadV3(payloadID engine.PayloadID) (*engine.ExecutionPayloadEnvelope, error) {
|
||||||
|
if !payloadID.Is(engine.PayloadV3) {
|
||||||
|
return nil, engine.UnsupportedFork
|
||||||
|
}
|
||||||
return api.getPayload(payloadID, false)
|
return api.getPayload(payloadID, false)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -210,6 +210,7 @@ func TestEth2PrepareAndGetPayload(t *testing.T) {
|
|||||||
FeeRecipient: blockParams.SuggestedFeeRecipient,
|
FeeRecipient: blockParams.SuggestedFeeRecipient,
|
||||||
Random: blockParams.Random,
|
Random: blockParams.Random,
|
||||||
BeaconRoot: blockParams.BeaconRoot,
|
BeaconRoot: blockParams.BeaconRoot,
|
||||||
|
Version: engine.PayloadV1,
|
||||||
}).Id()
|
}).Id()
|
||||||
execData, err := api.GetPayloadV1(payloadID)
|
execData, err := api.GetPayloadV1(payloadID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -1076,6 +1077,7 @@ func TestWithdrawals(t *testing.T) {
|
|||||||
Random: blockParams.Random,
|
Random: blockParams.Random,
|
||||||
Withdrawals: blockParams.Withdrawals,
|
Withdrawals: blockParams.Withdrawals,
|
||||||
BeaconRoot: blockParams.BeaconRoot,
|
BeaconRoot: blockParams.BeaconRoot,
|
||||||
|
Version: engine.PayloadV2,
|
||||||
}).Id()
|
}).Id()
|
||||||
execData, err := api.GetPayloadV2(payloadID)
|
execData, err := api.GetPayloadV2(payloadID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -1124,6 +1126,7 @@ func TestWithdrawals(t *testing.T) {
|
|||||||
Random: blockParams.Random,
|
Random: blockParams.Random,
|
||||||
Withdrawals: blockParams.Withdrawals,
|
Withdrawals: blockParams.Withdrawals,
|
||||||
BeaconRoot: blockParams.BeaconRoot,
|
BeaconRoot: blockParams.BeaconRoot,
|
||||||
|
Version: engine.PayloadV2,
|
||||||
}).Id()
|
}).Id()
|
||||||
execData, err = api.GetPayloadV2(payloadID)
|
execData, err = api.GetPayloadV2(payloadID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -1238,12 +1241,15 @@ func TestNilWithdrawals(t *testing.T) {
|
|||||||
|
|
||||||
for _, test := range tests {
|
for _, test := range tests {
|
||||||
var (
|
var (
|
||||||
err error
|
err error
|
||||||
shanghai = genesis.Config.IsShanghai(genesis.Config.LondonBlock, test.blockParams.Timestamp)
|
payloadVersion engine.PayloadVersion
|
||||||
|
shanghai = genesis.Config.IsShanghai(genesis.Config.LondonBlock, test.blockParams.Timestamp)
|
||||||
)
|
)
|
||||||
if !shanghai {
|
if !shanghai {
|
||||||
|
payloadVersion = engine.PayloadV1
|
||||||
_, err = api.ForkchoiceUpdatedV1(fcState, &test.blockParams)
|
_, err = api.ForkchoiceUpdatedV1(fcState, &test.blockParams)
|
||||||
} else {
|
} else {
|
||||||
|
payloadVersion = engine.PayloadV2
|
||||||
_, err = api.ForkchoiceUpdatedV2(fcState, &test.blockParams)
|
_, err = api.ForkchoiceUpdatedV2(fcState, &test.blockParams)
|
||||||
}
|
}
|
||||||
if test.wantErr {
|
if test.wantErr {
|
||||||
@ -1262,6 +1268,7 @@ func TestNilWithdrawals(t *testing.T) {
|
|||||||
Timestamp: test.blockParams.Timestamp,
|
Timestamp: test.blockParams.Timestamp,
|
||||||
FeeRecipient: test.blockParams.SuggestedFeeRecipient,
|
FeeRecipient: test.blockParams.SuggestedFeeRecipient,
|
||||||
Random: test.blockParams.Random,
|
Random: test.blockParams.Random,
|
||||||
|
Version: payloadVersion,
|
||||||
}).Id()
|
}).Id()
|
||||||
execData, err := api.GetPayloadV2(payloadID)
|
execData, err := api.GetPayloadV2(payloadID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -1616,6 +1623,7 @@ func TestParentBeaconBlockRoot(t *testing.T) {
|
|||||||
Random: blockParams.Random,
|
Random: blockParams.Random,
|
||||||
Withdrawals: blockParams.Withdrawals,
|
Withdrawals: blockParams.Withdrawals,
|
||||||
BeaconRoot: blockParams.BeaconRoot,
|
BeaconRoot: blockParams.BeaconRoot,
|
||||||
|
Version: engine.PayloadV3,
|
||||||
}).Id()
|
}).Id()
|
||||||
execData, err := api.GetPayloadV3(payloadID)
|
execData, err := api.GetPayloadV3(payloadID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -160,7 +160,7 @@ func (c *SimulatedBeacon) sealBlock(withdrawals []*types.Withdrawal, timestamp u
|
|||||||
SuggestedFeeRecipient: feeRecipient,
|
SuggestedFeeRecipient: feeRecipient,
|
||||||
Withdrawals: withdrawals,
|
Withdrawals: withdrawals,
|
||||||
Random: random,
|
Random: random,
|
||||||
}, true)
|
}, engine.PayloadV2, true)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
@ -35,12 +35,13 @@ import (
|
|||||||
// Check engine-api specification for more details.
|
// Check engine-api specification for more details.
|
||||||
// https://github.com/ethereum/execution-apis/blob/main/src/engine/cancun.md#payloadattributesv3
|
// https://github.com/ethereum/execution-apis/blob/main/src/engine/cancun.md#payloadattributesv3
|
||||||
type BuildPayloadArgs struct {
|
type BuildPayloadArgs struct {
|
||||||
Parent common.Hash // The parent block to build payload on top
|
Parent common.Hash // The parent block to build payload on top
|
||||||
Timestamp uint64 // The provided timestamp of generated payload
|
Timestamp uint64 // The provided timestamp of generated payload
|
||||||
FeeRecipient common.Address // The provided recipient address for collecting transaction fee
|
FeeRecipient common.Address // The provided recipient address for collecting transaction fee
|
||||||
Random common.Hash // The provided randomness value
|
Random common.Hash // The provided randomness value
|
||||||
Withdrawals types.Withdrawals // The provided withdrawals
|
Withdrawals types.Withdrawals // The provided withdrawals
|
||||||
BeaconRoot *common.Hash // The provided beaconRoot (Cancun)
|
BeaconRoot *common.Hash // The provided beaconRoot (Cancun)
|
||||||
|
Version engine.PayloadVersion // Versioning byte for payload id calculation.
|
||||||
}
|
}
|
||||||
|
|
||||||
// Id computes an 8-byte identifier by hashing the components of the payload arguments.
|
// Id computes an 8-byte identifier by hashing the components of the payload arguments.
|
||||||
@ -57,6 +58,7 @@ func (args *BuildPayloadArgs) Id() engine.PayloadID {
|
|||||||
}
|
}
|
||||||
var out engine.PayloadID
|
var out engine.PayloadID
|
||||||
copy(out[:], hasher.Sum(nil)[:8])
|
copy(out[:], hasher.Sum(nil)[:8])
|
||||||
|
out[0] = byte(args.Version)
|
||||||
return out
|
return out
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user