@@ -81,8 +81,10 @@ var caps = []string{
8181 "engine_exchangeTransitionConfigurationV1" ,
8282 "engine_getPayloadV1" ,
8383 "engine_getPayloadV2" ,
84+ "engine_getPayloadV3" ,
8485 "engine_newPayloadV1" ,
8586 "engine_newPayloadV2" ,
87+ "engine_newPayloadV3" ,
8688 "engine_getPayloadBodiesByHashV1" ,
8789 "engine_getPayloadBodiesByRangeV1" ,
8890}
@@ -405,23 +407,13 @@ func (api *ConsensusAPI) GetPayloadV2(payloadID engine.PayloadID) (*engine.Execu
405407 return api .getPayload (payloadID )
406408}
407409
408- func (api * ConsensusAPI ) getPayload (payloadID engine.PayloadID ) (* engine.ExecutionPayloadEnvelope , error ) {
409- log .Trace ("Engine API request received" , "method" , "GetPayload" , "id" , payloadID )
410- data := api .localBlocks .get (payloadID , false )
411- if data == nil {
412- return nil , engine .UnknownPayload
413- }
414- return data , nil
410+ // GetPayloadV3 returns a cached payload by id.
411+ func (api * ConsensusAPI ) GetPayloadV3 (payloadID engine.PayloadID ) (* engine.ExecutionPayloadEnvelope , error ) {
412+ return api .getPayload (payloadID )
415413}
416414
417- // getFullPayload returns a cached payload by it. The difference is that this
418- // function always expects a non-empty payload, but can also return empty one
419- // if no transaction is executable.
420- //
421- // Note, this function is not a part of standard engine API, meant to be used
422- // by consensus client mock in dev mode.
423- func (api * ConsensusAPI ) getFullPayload (payloadID engine.PayloadID ) (* engine.ExecutionPayloadEnvelope , error ) {
424- log .Trace ("Engine API request received" , "method" , "GetFullPayload" , "id" , payloadID )
415+ func (api * ConsensusAPI ) getPayload (payloadID engine.PayloadID ) (* engine.ExecutionPayloadEnvelope , error ) {
416+ log .Trace ("Engine API request received" , "method" , "GetPayload" , "id" , payloadID )
425417 data := api .localBlocks .get (payloadID , true )
426418 if data == nil {
427419 return nil , engine .UnknownPayload
@@ -434,7 +426,7 @@ func (api *ConsensusAPI) NewPayloadV1(params engine.ExecutableData) (engine.Payl
434426 if params .Withdrawals != nil {
435427 return engine.PayloadStatusV1 {Status : engine .INVALID }, engine .InvalidParams .With (errors .New ("withdrawals not supported in V1" ))
436428 }
437- return api .newPayload (params )
429+ return api .newPayload (params , nil )
438430}
439431
440432// NewPayloadV2 creates an Eth1 block, inserts it in the chain, and returns the status of the chain.
@@ -446,10 +438,29 @@ func (api *ConsensusAPI) NewPayloadV2(params engine.ExecutableData) (engine.Payl
446438 } else if params .Withdrawals != nil {
447439 return engine.PayloadStatusV1 {Status : engine .INVALID }, engine .InvalidParams .With (errors .New ("non-nil withdrawals pre-shanghai" ))
448440 }
449- return api .newPayload (params )
441+ if api .eth .BlockChain ().Config ().IsCancun (new (big.Int ).SetUint64 (params .Number ), params .Timestamp ) {
442+ return engine.PayloadStatusV1 {Status : engine .INVALID }, engine .InvalidParams .With (errors .New ("newPayloadV2 called post-cancun" ))
443+ }
444+ return api .newPayload (params , nil )
450445}
451446
452- func (api * ConsensusAPI ) newPayload (params engine.ExecutableData ) (engine.PayloadStatusV1 , error ) {
447+ // NewPayloadV3 creates an Eth1 block, inserts it in the chain, and returns the status of the chain.
448+ func (api * ConsensusAPI ) NewPayloadV3 (params engine.ExecutableData , versionedHashes * []common.Hash ) (engine.PayloadStatusV1 , error ) {
449+ if ! api .eth .BlockChain ().Config ().IsCancun (new (big.Int ).SetUint64 (params .Number ), params .Timestamp ) {
450+ return engine.PayloadStatusV1 {Status : engine .INVALID }, engine .InvalidParams .With (errors .New ("newPayloadV3 called pre-cancun" ))
451+ }
452+
453+ if params .ExcessDataGas == nil {
454+ return engine.PayloadStatusV1 {Status : engine .INVALID }, engine .InvalidParams .With (fmt .Errorf ("nil excessDataGas post-cancun" ))
455+ }
456+ var hashes []common.Hash
457+ if versionedHashes != nil {
458+ hashes = * versionedHashes
459+ }
460+ return api .newPayload (params , hashes )
461+ }
462+
463+ func (api * ConsensusAPI ) newPayload (params engine.ExecutableData , versionedHashes []common.Hash ) (engine.PayloadStatusV1 , error ) {
453464 // The locking here is, strictly, not required. Without these locks, this can happen:
454465 //
455466 // 1. NewPayload( execdata-N ) is invoked from the CL. It goes all the way down to
@@ -467,9 +478,9 @@ func (api *ConsensusAPI) newPayload(params engine.ExecutableData) (engine.Payloa
467478 defer api .newPayloadLock .Unlock ()
468479
469480 log .Trace ("Engine API request received" , "method" , "NewPayload" , "number" , params .Number , "hash" , params .BlockHash )
470- block , err := engine .ExecutableDataToBlock (params )
481+ block , err := engine .ExecutableDataToBlock (params , versionedHashes )
471482 if err != nil {
472- log .Debug ("Invalid NewPayload params" , "params" , params , "error" , err )
483+ log .Warn ("Invalid NewPayload params" , "params" , params , "error" , err )
473484 return engine.PayloadStatusV1 {Status : engine .INVALID }, nil
474485 }
475486 // Stash away the last update to warn the user if the beacon client goes offline
@@ -730,8 +741,8 @@ func (api *ConsensusAPI) ExchangeCapabilities([]string) []string {
730741 return caps
731742}
732743
733- // GetPayloadBodiesByHashV1 implements engine_getPayloadBodiesByHashV1 which
734- // allows for retrieval of a list of block bodies by the engine api.
744+ // GetPayloadBodiesByHashV1 implements engine_getPayloadBodiesByHashV1 which allows for retrieval of a list
745+ // of block bodies by the engine api.
735746func (api * ConsensusAPI ) GetPayloadBodiesByHashV1 (hashes []common.Hash ) []* engine.ExecutionPayloadBodyV1 {
736747 var bodies = make ([]* engine.ExecutionPayloadBodyV1 , len (hashes ))
737748 for i , hash := range hashes {
@@ -741,8 +752,8 @@ func (api *ConsensusAPI) GetPayloadBodiesByHashV1(hashes []common.Hash) []*engin
741752 return bodies
742753}
743754
744- // GetPayloadBodiesByRangeV1 implements engine_getPayloadBodiesByRangeV1 which
745- // allows for retrieval of a range of block bodies by the engine api.
755+ // GetPayloadBodiesByRangeV1 implements engine_getPayloadBodiesByRangeV1 which allows for retrieval of a range
756+ // of block bodies by the engine api.
746757func (api * ConsensusAPI ) GetPayloadBodiesByRangeV1 (start , count hexutil.Uint64 ) ([]* engine.ExecutionPayloadBodyV1 , error ) {
747758 if start == 0 || count == 0 {
748759 return nil , engine .InvalidParams .With (fmt .Errorf ("invalid start or count, start: %v count: %v" , start , count ))
@@ -768,19 +779,23 @@ func getBody(block *types.Block) *engine.ExecutionPayloadBodyV1 {
768779 if block == nil {
769780 return nil
770781 }
782+
771783 var (
772784 body = block .Body ()
773785 txs = make ([]hexutil.Bytes , len (body .Transactions ))
774786 withdrawals = body .Withdrawals
775787 )
788+
776789 for j , tx := range body .Transactions {
777790 data , _ := tx .MarshalBinary ()
778791 txs [j ] = hexutil .Bytes (data )
779792 }
793+
780794 // Post-shanghai withdrawals MUST be set to empty slice instead of nil
781795 if withdrawals == nil && block .Header ().WithdrawalsHash != nil {
782796 withdrawals = make ([]* types.Withdrawal , 0 )
783797 }
798+
784799 return & engine.ExecutionPayloadBodyV1 {
785800 TransactionData : txs ,
786801 Withdrawals : withdrawals ,
0 commit comments