diff --git a/beacon/engine/gen_blockparams.go b/beacon/engine/gen_blockparams.go index b1f01b50ff..23d2d71183 100644 --- a/beacon/engine/gen_blockparams.go +++ b/beacon/engine/gen_blockparams.go @@ -21,6 +21,7 @@ func (p PayloadAttributes) MarshalJSON() ([]byte, error) { SuggestedFeeRecipient common.Address `json:"suggestedFeeRecipient" gencodec:"required"` Withdrawals []*types.Withdrawal `json:"withdrawals"` BeaconRoot *common.Hash `json:"parentBeaconBlockRoot"` + InclusionList types.InclusionList `json:"inclusionListTransactions"` } var enc PayloadAttributes enc.Timestamp = hexutil.Uint64(p.Timestamp) @@ -28,6 +29,7 @@ func (p PayloadAttributes) MarshalJSON() ([]byte, error) { enc.SuggestedFeeRecipient = p.SuggestedFeeRecipient enc.Withdrawals = p.Withdrawals enc.BeaconRoot = p.BeaconRoot + enc.InclusionList = p.InclusionList return json.Marshal(&enc) } @@ -39,6 +41,7 @@ func (p *PayloadAttributes) UnmarshalJSON(input []byte) error { SuggestedFeeRecipient *common.Address `json:"suggestedFeeRecipient" gencodec:"required"` Withdrawals []*types.Withdrawal `json:"withdrawals"` BeaconRoot *common.Hash `json:"parentBeaconBlockRoot"` + InclusionList types.InclusionList `json:"inclusionListTransactions"` } var dec PayloadAttributes if err := json.Unmarshal(input, &dec); err != nil { @@ -62,5 +65,8 @@ func (p *PayloadAttributes) UnmarshalJSON(input []byte) error { if dec.BeaconRoot != nil { p.BeaconRoot = dec.BeaconRoot } + if dec.InclusionList != nil { + p.InclusionList = dec.InclusionList + } return nil } diff --git a/beacon/engine/types.go b/beacon/engine/types.go index e1015d0006..88e6fde2ef 100644 --- a/beacon/engine/types.go +++ b/beacon/engine/types.go @@ -50,6 +50,7 @@ var ( // ExecutionPayloadV3 has the syntax of ExecutionPayloadV2 and appends the new // fields: blobGasUsed and excessBlobGas. PayloadV3 PayloadVersion = 0x3 + PayloadV4 PayloadVersion = 0x4 ) //go:generate go run github.com/fjl/gencodec -type PayloadAttributes -field-override payloadAttributesMarshaling -out gen_blockparams.go @@ -62,6 +63,7 @@ type PayloadAttributes struct { SuggestedFeeRecipient common.Address `json:"suggestedFeeRecipient" gencodec:"required"` Withdrawals []*types.Withdrawal `json:"withdrawals"` BeaconRoot *common.Hash `json:"parentBeaconBlockRoot"` + InclusionList types.InclusionList `json:"inclusionListTransactions"` } // JSON type overrides for PayloadAttributes. diff --git a/eth/catalyst/api.go b/eth/catalyst/api.go index 6f56f48130..b47bcca38f 100644 --- a/eth/catalyst/api.go +++ b/eth/catalyst/api.go @@ -88,6 +88,7 @@ var caps = []string{ "engine_forkchoiceUpdatedV1", "engine_forkchoiceUpdatedV2", "engine_forkchoiceUpdatedV3", + "engine_forkchoiceUpdatedV4", "engine_forkchoiceUpdatedWithWitnessV1", "engine_forkchoiceUpdatedWithWitnessV2", "engine_forkchoiceUpdatedWithWitnessV3", @@ -264,6 +265,22 @@ func (api *ConsensusAPI) ForkchoiceUpdatedV3(update engine.ForkchoiceStateV1, pa return api.forkchoiceUpdated(update, params, engine.PayloadV3, false) } +// ForkchoiceUpdatedV4 is equivalent to V3 with the addition of inclusion list +// in the payload attributes. It supports only PayloadAttributesV4. +func (api *ConsensusAPI) ForkchoiceUpdatedV4(update engine.ForkchoiceStateV1, params *engine.PayloadAttributes) (engine.ForkChoiceResponse, error) { + if params != nil { + switch { + case params.Withdrawals == nil: + return engine.STATUS_INVALID, attributesErr("missing withdrawals") + case params.BeaconRoot == nil: + return engine.STATUS_INVALID, attributesErr("missing beacon root") + case !api.checkFork(params.Timestamp, forks.Eip7805): + return engine.STATUS_INVALID, unsupportedForkErr("fcuV4 must only be called for eip7805 payloads") + } + } + return api.forkchoiceUpdated(update, params, engine.PayloadV4, false) +} + func (api *ConsensusAPI) forkchoiceUpdated(update engine.ForkchoiceStateV1, payloadAttributes *engine.PayloadAttributes, payloadVersion engine.PayloadVersion, payloadWitness bool) (engine.ForkChoiceResponse, error) { api.forkchoiceLock.Lock() defer api.forkchoiceLock.Unlock() @@ -391,18 +408,20 @@ func (api *ConsensusAPI) forkchoiceUpdated(update engine.ForkchoiceStateV1, payl // will replace it arbitrarily many times in between. if payloadAttributes != nil { args := &miner.BuildPayloadArgs{ - Parent: update.HeadBlockHash, - Timestamp: payloadAttributes.Timestamp, - FeeRecipient: payloadAttributes.SuggestedFeeRecipient, - Random: payloadAttributes.Random, - Withdrawals: payloadAttributes.Withdrawals, - BeaconRoot: payloadAttributes.BeaconRoot, - Version: payloadVersion, + Parent: update.HeadBlockHash, + Timestamp: payloadAttributes.Timestamp, + FeeRecipient: payloadAttributes.SuggestedFeeRecipient, + Random: payloadAttributes.Random, + Withdrawals: payloadAttributes.Withdrawals, + BeaconRoot: payloadAttributes.BeaconRoot, + InclusionList: payloadAttributes.InclusionList, + Version: payloadVersion, } id := args.Id() // If we already are busy generating this work, then we do not need // to start a second process. - if api.localBlocks.has(id) { + if payload := api.localBlocks.peek(id); payload != nil { + payload.UpdateInclusionList(payloadAttributes.InclusionList) return valid(&id), nil } payload, err := api.eth.Miner().BuildPayload(args, payloadWitness) diff --git a/eth/catalyst/simulated_beacon.go b/eth/catalyst/simulated_beacon.go index 6d92c2c67a..c4cfca1f48 100644 --- a/eth/catalyst/simulated_beacon.go +++ b/eth/catalyst/simulated_beacon.go @@ -200,6 +200,7 @@ func (c *SimulatedBeacon) sealBlock(withdrawals []*types.Withdrawal, timestamp u Withdrawals: withdrawals, Random: random, BeaconRoot: &common.Hash{}, + InclusionList: types.InclusionList{}, }, version, false) if err != nil { return err