@ -81,8 +81,10 @@ var caps = []string{
"engine_exchangeTransitionConfigurationV1" ,
"engine_exchangeTransitionConfigurationV1" ,
"engine_getPayloadV1" ,
"engine_getPayloadV1" ,
"engine_getPayloadV2" ,
"engine_getPayloadV2" ,
"engine_getPayloadV3" ,
"engine_newPayloadV1" ,
"engine_newPayloadV1" ,
"engine_newPayloadV2" ,
"engine_newPayloadV2" ,
"engine_newPayloadV3" ,
"engine_getPayloadBodiesByHashV1" ,
"engine_getPayloadBodiesByHashV1" ,
"engine_getPayloadBodiesByRangeV1" ,
"engine_getPayloadBodiesByRangeV1" ,
}
}
@ -405,23 +407,13 @@ func (api *ConsensusAPI) GetPayloadV2(payloadID engine.PayloadID) (*engine.Execu
return api . getPayload ( payloadID )
return api . getPayload ( payloadID )
}
}
func ( api * ConsensusAPI ) getPayload ( payloadID engine . PayloadID ) ( * engine . ExecutionPayloadEnvelope , error ) {
// GetPayloadV3 returns a cached payload by id.
log . Trace ( "Engine API request received" , "method" , "GetPayload" , "id" , payloadID )
func ( api * ConsensusAPI ) GetPayloadV3 ( payloadID engine . PayloadID ) ( * engine . ExecutionPayloadEnvelope , error ) {
data := api . localBlocks . get ( payloadID , false )
return api . getPayload ( payloadID )
if data == nil {
return nil , engine . UnknownPayload
}
return data , nil
}
}
// getFullPayload returns a cached payload by it. The difference is that this
func ( api * ConsensusAPI ) getPayload ( payloadID engine . PayloadID ) ( * engine . ExecutionPayloadEnvelope , error ) {
// function always expects a non-empty payload, but can also return empty one
log . Trace ( "Engine API request received" , "method" , "GetPayload" , "id" , payloadID )
// if no transaction is executable.
//
// Note, this function is not a part of standard engine API, meant to be used
// by consensus client mock in dev mode.
func ( api * ConsensusAPI ) getFullPayload ( payloadID engine . PayloadID ) ( * engine . ExecutionPayloadEnvelope , error ) {
log . Trace ( "Engine API request received" , "method" , "GetFullPayload" , "id" , payloadID )
data := api . localBlocks . get ( payloadID , true )
data := api . localBlocks . get ( payloadID , true )
if data == nil {
if data == nil {
return nil , engine . UnknownPayload
return nil , engine . UnknownPayload
@ -434,7 +426,7 @@ func (api *ConsensusAPI) NewPayloadV1(params engine.ExecutableData) (engine.Payl
if params . Withdrawals != nil {
if params . Withdrawals != nil {
return engine . PayloadStatusV1 { Status : engine . INVALID } , engine . InvalidParams . With ( errors . New ( "withdrawals not supported in V1" ) )
return engine . PayloadStatusV1 { Status : engine . INVALID } , engine . InvalidParams . With ( errors . New ( "withdrawals not supported in V1" ) )
}
}
return api . newPayload ( params )
return api . newPayload ( params , nil )
}
}
// NewPayloadV2 creates an Eth1 block, inserts it in the chain, and returns the status of the chain.
// 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
} else if params . Withdrawals != nil {
} else if params . Withdrawals != nil {
return engine . PayloadStatusV1 { Status : engine . INVALID } , engine . InvalidParams . With ( errors . New ( "non-nil withdrawals pre-shanghai" ) )
return engine . PayloadStatusV1 { Status : engine . INVALID } , engine . InvalidParams . With ( errors . New ( "non-nil withdrawals pre-shanghai" ) )
}
}
return api . newPayload ( params )
if api . eth . BlockChain ( ) . Config ( ) . IsCancun ( new ( big . Int ) . SetUint64 ( params . Number ) , params . Timestamp ) {
return engine . PayloadStatusV1 { Status : engine . INVALID } , engine . InvalidParams . With ( errors . New ( "newPayloadV2 called post-cancun" ) )
}
return api . newPayload ( params , nil )
}
}
func ( api * ConsensusAPI ) newPayload ( params engine . ExecutableData ) ( engine . PayloadStatusV1 , error ) {
// NewPayloadV3 creates an Eth1 block, inserts it in the chain, and returns the status of the chain.
func ( api * ConsensusAPI ) NewPayloadV3 ( params engine . ExecutableData , versionedHashes * [ ] common . Hash ) ( engine . PayloadStatusV1 , error ) {
if ! api . eth . BlockChain ( ) . Config ( ) . IsCancun ( new ( big . Int ) . SetUint64 ( params . Number ) , params . Timestamp ) {
return engine . PayloadStatusV1 { Status : engine . INVALID } , engine . InvalidParams . With ( errors . New ( "newPayloadV3 called pre-cancun" ) )
}
if params . ExcessDataGas == nil {
return engine . PayloadStatusV1 { Status : engine . INVALID } , engine . InvalidParams . With ( fmt . Errorf ( "nil excessDataGas post-cancun" ) )
}
var hashes [ ] common . Hash
if versionedHashes != nil {
hashes = * versionedHashes
}
return api . newPayload ( params , hashes )
}
func ( api * ConsensusAPI ) newPayload ( params engine . ExecutableData , versionedHashes [ ] common . Hash ) ( engine . PayloadStatusV1 , error ) {
// The locking here is, strictly, not required. Without these locks, this can happen:
// The locking here is, strictly, not required. Without these locks, this can happen:
//
//
// 1. NewPayload( execdata-N ) is invoked from the CL. It goes all the way down to
// 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
defer api . newPayloadLock . Unlock ( )
defer api . newPayloadLock . Unlock ( )
log . Trace ( "Engine API request received" , "method" , "NewPayload" , "number" , params . Number , "hash" , params . BlockHash )
log . Trace ( "Engine API request received" , "method" , "NewPayload" , "number" , params . Number , "hash" , params . BlockHash )
block , err := engine . ExecutableDataToBlock ( params )
block , err := engine . ExecutableDataToBlock ( params , versionedHashes )
if err != nil {
if err != nil {
log . Debug ( "Invalid NewPayload params" , "params" , params , "error" , err )
log . Warn ( "Invalid NewPayload params" , "params" , params , "error" , err )
return engine . PayloadStatusV1 { Status : engine . INVALID } , nil
return engine . PayloadStatusV1 { Status : engine . INVALID } , nil
}
}
// Stash away the last update to warn the user if the beacon client goes offline
// 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 {
return caps
return caps
}
}
// GetPayloadBodiesByHashV1 implements engine_getPayloadBodiesByHashV1 which
// GetPayloadBodiesByHashV1 implements engine_getPayloadBodiesByHashV1 which allows for retrieval of a list
// allows for retrieval of a list of block bodies by the engine api.
// of block bodies by the engine api.
func ( api * ConsensusAPI ) GetPayloadBodiesByHashV1 ( hashes [ ] common . Hash ) [ ] * engine . ExecutionPayloadBodyV1 {
func ( api * ConsensusAPI ) GetPayloadBodiesByHashV1 ( hashes [ ] common . Hash ) [ ] * engine . ExecutionPayloadBodyV1 {
var bodies = make ( [ ] * engine . ExecutionPayloadBodyV1 , len ( hashes ) )
var bodies = make ( [ ] * engine . ExecutionPayloadBodyV1 , len ( hashes ) )
for i , hash := range hashes {
for i , hash := range hashes {
@ -741,8 +752,8 @@ func (api *ConsensusAPI) GetPayloadBodiesByHashV1(hashes []common.Hash) []*engin
return bodies
return bodies
}
}
// GetPayloadBodiesByRangeV1 implements engine_getPayloadBodiesByRangeV1 which
// GetPayloadBodiesByRangeV1 implements engine_getPayloadBodiesByRangeV1 which allows for retrieval of a range
// allows for retrieval of a range of block bodies by the engine api.
// of block bodies by the engine api.
func ( api * ConsensusAPI ) GetPayloadBodiesByRangeV1 ( start , count hexutil . Uint64 ) ( [ ] * engine . ExecutionPayloadBodyV1 , error ) {
func ( api * ConsensusAPI ) GetPayloadBodiesByRangeV1 ( start , count hexutil . Uint64 ) ( [ ] * engine . ExecutionPayloadBodyV1 , error ) {
if start == 0 || count == 0 {
if start == 0 || count == 0 {
return nil , engine . InvalidParams . With ( fmt . Errorf ( "invalid start or count, start: %v count: %v" , start , count ) )
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 {
if block == nil {
if block == nil {
return nil
return nil
}
}
var (
var (
body = block . Body ( )
body = block . Body ( )
txs = make ( [ ] hexutil . Bytes , len ( body . Transactions ) )
txs = make ( [ ] hexutil . Bytes , len ( body . Transactions ) )
withdrawals = body . Withdrawals
withdrawals = body . Withdrawals
)
)
for j , tx := range body . Transactions {
for j , tx := range body . Transactions {
data , _ := tx . MarshalBinary ( )
data , _ := tx . MarshalBinary ( )
txs [ j ] = hexutil . Bytes ( data )
txs [ j ] = hexutil . Bytes ( data )
}
}
// Post-shanghai withdrawals MUST be set to empty slice instead of nil
// Post-shanghai withdrawals MUST be set to empty slice instead of nil
if withdrawals == nil && block . Header ( ) . WithdrawalsHash != nil {
if withdrawals == nil && block . Header ( ) . WithdrawalsHash != nil {
withdrawals = make ( [ ] * types . Withdrawal , 0 )
withdrawals = make ( [ ] * types . Withdrawal , 0 )
}
}
return & engine . ExecutionPayloadBodyV1 {
return & engine . ExecutionPayloadBodyV1 {
TransactionData : txs ,
TransactionData : txs ,
Withdrawals : withdrawals ,
Withdrawals : withdrawals ,