Skip to content

Commit

Permalink
engine payload bodies rpc endpoints
Browse files Browse the repository at this point in the history
  • Loading branch information
hexoscott committed Jan 24, 2023
1 parent 49f8d4c commit e00409d
Show file tree
Hide file tree
Showing 4 changed files with 148 additions and 0 deletions.
47 changes: 47 additions & 0 deletions cmd/rpcdaemon/commands/engine_api.go
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,11 @@ type TransitionConfiguration struct {
TerminalBlockNumber *hexutil.Big `json:"terminalBlockNumber" gencodec:"required"`
}

type ExecutionPayloadBodyV1 struct {
Transactions [][]byte `json:"transactions" gencodec:"required"`
Withdrawals []*types.Withdrawal `json:"withdrawals" gencodec:"required"`
}

// EngineAPI Beacon chain communication endpoint
type EngineAPI interface {
NewPayloadV1(context.Context, *ExecutionPayload) (map[string]interface{}, error)
Expand All @@ -78,6 +83,8 @@ type EngineAPI interface {
GetPayloadV1(ctx context.Context, payloadID hexutil.Bytes) (*ExecutionPayload, error)
GetPayloadV2(ctx context.Context, payloadID hexutil.Bytes) (*GetPayloadV2Response, error)
ExchangeTransitionConfigurationV1(ctx context.Context, transitionConfiguration *TransitionConfiguration) (*TransitionConfiguration, error)
GetPayloadBodiesByHashV1(ctx context.Context, hashes []libcommon.Hash) ([]*ExecutionPayloadBodyV1, error)
GetPayloadBodiesByRangeV1(ctx context.Context, start uint64, count uint64) ([]*ExecutionPayloadBodyV1, error)
}

// EngineImpl is implementation of the EngineAPI interface
Expand Down Expand Up @@ -358,6 +365,46 @@ func (e *EngineImpl) ExchangeTransitionConfigurationV1(ctx context.Context, beac
}, nil
}

func (e *EngineImpl) GetPayloadBodiesByHashV1(ctx context.Context, hashes []libcommon.Hash) ([]*ExecutionPayloadBodyV1, error) {
h := make([]*types2.H256, len(hashes))
for i, hash := range hashes {
h[i] = gointerfaces.ConvertHashToH256(hash)
}

apiRes, err := e.api.EngineGetPayloadBodiesByHashV1(ctx, &remote.EngineGetPayloadBodiesByHashV1Request{Hashes: h})
if err != nil {
return nil, err
}

return convertExecutionPayloadV1(apiRes), nil
}

func (e *EngineImpl) GetPayloadBodiesByRangeV1(ctx context.Context, start uint64, count uint64) ([]*ExecutionPayloadBodyV1, error) {
apiRes, err := e.api.EngineGetPayloadBodiesByRangeV1(ctx, &remote.EngineGetPayloadBodiesByRangeV1Request{Start: start, Count: count})
if err != nil {
return nil, err
}

return convertExecutionPayloadV1(apiRes), nil
}

func convertExecutionPayloadV1(response *remote.EngineGetPayloadBodiesV1Response) []*ExecutionPayloadBodyV1 {
result := make([]*ExecutionPayloadBodyV1, len(response.Bodies))
for idx, body := range response.Bodies {
if body == nil {
result[idx] = nil
} else {
pl := &ExecutionPayloadBodyV1{
Transactions: body.Transactions,
Withdrawals: privateapi.ConvertWithdrawalsFromRpc(body.Withdrawals),
}
result[idx] = pl
}
}

return result
}

// NewEngineAPI returns EngineImpl instance
func NewEngineAPI(base *BaseAPI, db kv.RoDB, api rpchelper.ApiBackend, internalCL bool) *EngineImpl {
return &EngineImpl{
Expand Down
8 changes: 8 additions & 0 deletions cmd/rpcdaemon/rpcservices/eth_backend.go
Original file line number Diff line number Diff line change
Expand Up @@ -212,6 +212,14 @@ func (back *RemoteBackend) EngineGetPayload(ctx context.Context, payloadId uint6
})
}

func (back *RemoteBackend) EngineGetPayloadBodiesByHashV1(ctx context.Context, request *remote.EngineGetPayloadBodiesByHashV1Request) (*remote.EngineGetPayloadBodiesV1Response, error) {
return back.remoteEthBackend.EngineGetPayloadBodiesByHashV1(ctx, request)
}

func (back *RemoteBackend) EngineGetPayloadBodiesByRangeV1(ctx context.Context, request *remote.EngineGetPayloadBodiesByRangeV1Request) (*remote.EngineGetPayloadBodiesV1Response, error) {
return back.remoteEthBackend.EngineGetPayloadBodiesByRangeV1(ctx, request)
}

func (back *RemoteBackend) NodeInfo(ctx context.Context, limit uint32) ([]p2p.NodeInfo, error) {
nodes, err := back.remoteEthBackend.NodeInfo(ctx, &remote.NodesInfoRequest{Limit: limit})
if err != nil {
Expand Down
91 changes: 91 additions & 0 deletions ethdb/privateapi/ethbackend.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package privateapi

import (
"bytes"
"context"
"errors"
"fmt"
Expand Down Expand Up @@ -679,6 +680,96 @@ func (s *EthBackendServer) EngineForkChoiceUpdated(ctx context.Context, req *rem
}, nil
}

func (s *EthBackendServer) EngineGetPayloadBodiesByHashV1(ctx context.Context, request *remote.EngineGetPayloadBodiesByHashV1Request) (*remote.EngineGetPayloadBodiesV1Response, error) {
tx, err := s.db.BeginRo(ctx)
if err != nil {
return nil, err
}

bodies := make([]*types2.ExecutionPayloadBodyV1, len(request.Hashes))

for hashIdx, hash := range request.Hashes {
h := gointerfaces.ConvertH256ToHash(hash)
block, err := rawdb.ReadBlockByHash(tx, h)
if err != nil {
return nil, err
}

body, err := extractPayloadBodyFromBlock(block)
if err != nil {
return nil, err
}
bodies[hashIdx] = body
}

return &remote.EngineGetPayloadBodiesV1Response{Bodies: bodies}, nil
}

func (s *EthBackendServer) EngineGetPayloadBodiesByRangeV1(ctx context.Context, request *remote.EngineGetPayloadBodiesByRangeV1Request) (*remote.EngineGetPayloadBodiesV1Response, error) {
tx, err := s.db.BeginRo(ctx)
if err != nil {
return nil, err
}

bodies := make([]*types2.ExecutionPayloadBodyV1, request.Count)

var i uint64
for i = 0; i < request.Count; i++ {
block, err := rawdb.ReadBlockByNumber(tx, request.Start+i)
if err != nil {
return nil, err
}
body, err := extractPayloadBodyFromBlock(block)
if err != nil {
return nil, err
}
if body == nil {
// break early if the body is nil to trim the response. A missing body indicates we don't have the
// canonical block so can just stop outputting from here
break
}
bodies[i] = body
}

return &remote.EngineGetPayloadBodiesV1Response{Bodies: bodies}, nil
}

func extractPayloadBodyFromBlock(block *types.Block) (*types2.ExecutionPayloadBodyV1, error) {
if block == nil {
return nil, nil
}

txs := block.Transactions()
bdTxs := make([][]byte, len(txs))
for idx, tx := range txs {
var buf bytes.Buffer
if err := tx.MarshalBinary(&buf); err != nil {
return nil, err
} else {
bdTxs[idx] = buf.Bytes()
}
}

wds := block.Withdrawals()
bdWds := make([]*types2.Withdrawal, len(wds))

if wds == nil {
// pre shanghai blocks could have nil withdrawals so nil the slice as per spec
bdWds = nil
} else {
for idx, wd := range wds {
bdWds[idx] = &types2.Withdrawal{
Index: wd.Index,
ValidatorIndex: wd.Validator,
Address: gointerfaces.ConvertAddressToH160(wd.Address),
Amount: wd.Amount,
}
}
}

return &types2.ExecutionPayloadBodyV1{Transactions: bdTxs, Withdrawals: bdWds}, nil
}

func (s *EthBackendServer) evictOldBuilders() {
ids := common.SortedKeys(s.builders)

Expand Down
2 changes: 2 additions & 0 deletions turbo/rpchelper/interface.go
Original file line number Diff line number Diff line change
Expand Up @@ -31,4 +31,6 @@ type ApiBackend interface {
NodeInfo(ctx context.Context, limit uint32) ([]p2p.NodeInfo, error)
Peers(ctx context.Context) ([]*p2p.PeerInfo, error)
PendingBlock(ctx context.Context) (*types.Block, error)
EngineGetPayloadBodiesByHashV1(ctx context.Context, request *remote.EngineGetPayloadBodiesByHashV1Request) (*remote.EngineGetPayloadBodiesV1Response, error)
EngineGetPayloadBodiesByRangeV1(ctx context.Context, request *remote.EngineGetPayloadBodiesByRangeV1Request) (*remote.EngineGetPayloadBodiesV1Response, error)
}

0 comments on commit e00409d

Please sign in to comment.