Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add eth_getBlockByHash/Number to engine API #27

Merged
merged 4 commits into from May 13, 2022
Merged
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
118 changes: 65 additions & 53 deletions engine.go
Expand Up @@ -165,18 +165,8 @@ func (c *EngineCmd) startRPC(ctx context.Context) {
c.log.Fatal(err)
}

rpcSrv.RegisterName("eth", c.backend)
if err := node.RegisterApis([]rpc.API{
{
Namespace: "eth",
Version: "1.0",
Service: c.backend,
Public: true,
Authenticated: false,
},
}, []string{"eth"}, rpcSrv, false); err != nil {
c.log.Fatal(fmt.Errorf("could not register api: %s", err))
}
ethBackend := NewEthBackend(c.backend.mockChain.chain)
ethBackend.Register(rpcSrv)

c.rpcSrv = rpcSrv
c.srv = rpc.NewHTTPServer(ctx, c.log, c.rpcSrv, c.ListenAddr, c.Timeout, c.Cors)
Expand All @@ -198,47 +188,6 @@ func NewEngineBackend(log logrus.Ext1FieldLogger, mock *MockChain) (*EngineBacke
return &EngineBackend{log, mock, 0, cache}, nil
}

func (s *EngineBackend) rpcMarshalBlock(ctx context.Context, b *ethTypes.Block, inclTx bool, fullTx bool) (map[string]interface{}, error) {
fields, err := types.RPCMarshalBlock(b, inclTx, fullTx, s.mockChain.chain.Config())
if err != nil {
return nil, err
}
if inclTx {
fields["totalDifficulty"] = (*hexutil.Big)(s.mockChain.chain.GetTd(b.Hash(), b.NumberU64()))
}
return fields, err
}

func (s *EngineBackend) GetBlockByHash(ctx context.Context, hash common.Hash, fullTx bool) (map[string]interface{}, error) {
block := s.mockChain.chain.GetBlockByHash(hash)
if block == nil {
return nil, errors.New("unknown block")
}
response, err := s.rpcMarshalBlock(ctx, block, true, fullTx)
return response, err
}

func (s *EngineBackend) GetBlockByNumber(ctx context.Context, number gethRpc.BlockNumber, fullTx bool) (map[string]interface{}, error) {
switch number {
case gethRpc.PendingBlockNumber:
return nil, errors.New("not implemented")
case gethRpc.LatestBlockNumber:
block := s.mockChain.chain.CurrentBlock()
if block == nil {
block = s.mockChain.chain.Genesis()
}
response, err := s.rpcMarshalBlock(ctx, block, true, fullTx)
return response, err
default:
block := s.mockChain.chain.GetBlockByNumber(uint64(number))
if block == nil {
return nil, errors.New("unknown block")
}
response, err := s.rpcMarshalBlock(ctx, block, true, fullTx)
return response, err
}
}

func (e *EngineBackend) GetPayloadV1(ctx context.Context, id types.PayloadID) (*types.ExecutionPayloadV1, error) {
plog := e.log.WithField("payload_id", id)

Expand Down Expand Up @@ -325,3 +274,66 @@ func (e *EngineBackend) ForkchoiceUpdatedV1(ctx context.Context, heads *types.Fo

return &types.ForkchoiceUpdatedResult{PayloadStatus: types.PayloadStatusV1{Status: types.ExecutionValid, LatestValidHash: &heads.HeadBlockHash}, PayloadID: &id}, nil
}

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Super minor suggestion but I think the code will be more maintainable longer-term if the EthBackend was moved to eth.go and the new RPCMarshal functions moved to types/rpc_encoding.go

type EthBackend struct {
chain *core.BlockChain
}

func NewEthBackend(chain *core.BlockChain) *EthBackend {
return &EthBackend{
chain: chain,
}
}
func (b *EthBackend) Register(srv *rpc.Server) error {
srv.RegisterName("eth", b)
return node.RegisterApis([]rpc.API{
{
Namespace: "eth",
Version: "1.0",
Service: b,
Public: true,
Authenticated: false,
},
}, []string{"eth"}, srv, false)
}

func (b *EthBackend) rpcMarshalBlock(ctx context.Context, block *ethTypes.Block, inclTx bool, fullTx bool) (map[string]interface{}, error) {
fields, err := types.RPCMarshalBlock(block, inclTx, fullTx, b.chain.Config())
if err != nil {
return nil, err
}
if inclTx {
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The parameter name is confusing (inclTx but really includes Td instead), and it's always set to true.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I agree. From geth's ethapi I'd avoid deviating since it'll be even more confusing!

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

maybe could link to the upstream code in the function docstring 🤔

fields["totalDifficulty"] = (*hexutil.Big)(b.chain.GetTd(block.Hash(), block.NumberU64()))
}
return fields, err
}

func (b *EthBackend) GetBlockByHash(ctx context.Context, hash common.Hash, fullTx bool) (map[string]interface{}, error) {
block := b.chain.GetBlockByHash(hash)
if block == nil {
return nil, errors.New("unknown block")
}
response, err := b.rpcMarshalBlock(ctx, block, true, fullTx)
return response, err
Ruteri marked this conversation as resolved.
Show resolved Hide resolved
}

func (b *EthBackend) GetBlockByNumber(ctx context.Context, number gethRpc.BlockNumber, fullTx bool) (map[string]interface{}, error) {
switch number {
case gethRpc.PendingBlockNumber:
return nil, errors.New("not implemented")
case gethRpc.LatestBlockNumber:
block := b.chain.CurrentBlock()
if block == nil {
block = b.chain.Genesis()
}
response, err := b.rpcMarshalBlock(ctx, block, true, fullTx)
return response, err
Ruteri marked this conversation as resolved.
Show resolved Hide resolved
default:
block := b.chain.GetBlockByNumber(uint64(number))
if block == nil {
return nil, errors.New("unknown block")
}
response, err := b.rpcMarshalBlock(ctx, block, true, fullTx)
return response, err
Ruteri marked this conversation as resolved.
Show resolved Hide resolved
}
}