Skip to content

Commit f4e7da2

Browse files
authored
engine_server: use chainRW instead of DB (#19296)
Requires erigontech/interfaces#279
1 parent e5fb3a9 commit f4e7da2

File tree

10 files changed

+595
-276
lines changed

10 files changed

+595
-276
lines changed

execution/engineapi/engine_api_methods.go

Lines changed: 12 additions & 96 deletions
Original file line numberDiff line numberDiff line change
@@ -19,14 +19,15 @@ package engineapi
1919
import (
2020
"context"
2121
"encoding/binary"
22+
"fmt"
2223

2324
"github.com/erigontech/erigon/cl/clparams"
2425
"github.com/erigontech/erigon/common"
2526
"github.com/erigontech/erigon/common/hexutil"
26-
"github.com/erigontech/erigon/db/kv"
27-
"github.com/erigontech/erigon/db/rawdb"
2827
"github.com/erigontech/erigon/db/version"
28+
"github.com/erigontech/erigon/execution/engineapi/engine_helpers"
2929
"github.com/erigontech/erigon/execution/engineapi/engine_types"
30+
"github.com/erigontech/erigon/rpc"
3031
)
3132

3233
var ourCapabilities = []string{
@@ -186,42 +187,11 @@ func (e *EngineServer) GetPayloadBodiesByHashV1(ctx context.Context, hashes []co
186187
// including blockAccessList sidecars from DB.
187188
// See https://github.com/ethereum/execution-apis/blob/main/src/engine/amsterdam.md#engine_getpayloadbodiesbyhashv2
188189
func (e *EngineServer) GetPayloadBodiesByHashV2(ctx context.Context, hashes []common.Hash) ([]*engine_types.ExecutionPayloadBodyV2, error) {
189-
bodies, err := e.getPayloadBodiesByHash(ctx, hashes)
190-
if err != nil {
191-
return nil, err
192-
}
193-
194-
bodyHashes := make([]common.Hash, len(bodies))
195-
bodyNumbers := make([]*uint64, len(bodies))
196-
for i := range bodies {
197-
if i >= len(hashes) {
198-
break
199-
}
200-
bodyHashes[i] = hashes[i]
201-
number, err := e.chainRW.HeaderNumber(ctx, hashes[i])
202-
if err != nil {
203-
return nil, err
204-
}
205-
bodyNumbers[i] = number
190+
if len(hashes) > 1024 {
191+
return nil, &engine_helpers.TooLargeRequestErr
206192
}
207-
208-
blockAccessLists, err := e.readBlockAccessLists(ctx, bodyHashes, bodyNumbers)
209-
if err != nil {
210-
return nil, err
211-
}
212-
213-
resp := make([]*engine_types.ExecutionPayloadBodyV2, len(bodies))
214-
for i := range bodies {
215-
if bodies[i] == nil {
216-
continue
217-
}
218-
resp[i] = &engine_types.ExecutionPayloadBodyV2{
219-
Transactions: bodies[i].Transactions,
220-
Withdrawals: bodies[i].Withdrawals,
221-
BlockAccessList: blockAccessLists[i],
222-
}
223-
}
224-
return resp, nil
193+
e.engineLogSpamer.RecordRequest()
194+
return e.chainRW.GetPayloadBodiesByHash(ctx, hashes)
225195
}
226196

227197
// Returns an ordered (as per canonical chain) array of execution payload bodies, with corresponding execution block numbers from "start", up to "count"
@@ -234,67 +204,13 @@ func (e *EngineServer) GetPayloadBodiesByRangeV1(ctx context.Context, start, cou
234204
// including blockAccessList sidecars from DB.
235205
// See https://github.com/ethereum/execution-apis/blob/main/src/engine/amsterdam.md#engine_getpayloadbodiesbyrangev2
236206
func (e *EngineServer) GetPayloadBodiesByRangeV2(ctx context.Context, start, count hexutil.Uint64) ([]*engine_types.ExecutionPayloadBodyV2, error) {
237-
bodies, err := e.getPayloadBodiesByRange(ctx, uint64(start), uint64(count))
238-
if err != nil {
239-
return nil, err
207+
if uint64(start) == 0 || uint64(count) == 0 {
208+
return nil, &rpc.InvalidParamsError{Message: fmt.Sprintf("invalid start or count, start: %v count: %v", start, count)}
240209
}
241-
242-
bodyHashes := make([]common.Hash, len(bodies))
243-
bodyNumbers := make([]*uint64, len(bodies))
244-
for i := range bodies {
245-
blockNumber := uint64(start) + uint64(i)
246-
header := e.chainRW.GetHeaderByNumber(ctx, blockNumber)
247-
if header == nil {
248-
continue
249-
}
250-
bodyHashes[i] = header.Hash()
251-
number := blockNumber
252-
bodyNumbers[i] = &number
253-
}
254-
255-
blockAccessLists, err := e.readBlockAccessLists(ctx, bodyHashes, bodyNumbers)
256-
if err != nil {
257-
return nil, err
258-
}
259-
260-
resp := make([]*engine_types.ExecutionPayloadBodyV2, len(bodies))
261-
for i := range bodies {
262-
if bodies[i] == nil {
263-
continue
264-
}
265-
resp[i] = &engine_types.ExecutionPayloadBodyV2{
266-
Transactions: bodies[i].Transactions,
267-
Withdrawals: bodies[i].Withdrawals,
268-
BlockAccessList: blockAccessLists[i],
269-
}
270-
}
271-
return resp, nil
272-
}
273-
274-
func (e *EngineServer) readBlockAccessLists(ctx context.Context, hashes []common.Hash, numbers []*uint64) ([]hexutil.Bytes, error) {
275-
resp := make([]hexutil.Bytes, len(hashes))
276-
if e.db == nil {
277-
return resp, nil
278-
}
279-
if err := e.db.View(ctx, func(tx kv.Tx) error {
280-
for i := range hashes {
281-
if numbers[i] == nil {
282-
continue
283-
}
284-
balBytes, err := rawdb.ReadBlockAccessListBytes(tx, hashes[i], *numbers[i])
285-
if err != nil {
286-
return err
287-
}
288-
if len(balBytes) == 0 {
289-
continue
290-
}
291-
resp[i] = append([]byte(nil), balBytes...)
292-
}
293-
return nil
294-
}); err != nil {
295-
return nil, err
210+
if uint64(count) > 1024 {
211+
return nil, &engine_helpers.TooLargeRequestErr
296212
}
297-
return resp, nil
213+
return e.chainRW.GetPayloadBodiesByRange(ctx, uint64(start), uint64(count))
298214
}
299215

300216
// Returns the node's code and commit details in a slice

execution/engineapi/engine_server.go

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -76,7 +76,6 @@ type EngineServer struct {
7676
caplin bool // we need to send errors for caplin.
7777
executionService executionproto.ExecutionClient
7878
txpool txpoolproto.TxpoolClient // needed for getBlobs
79-
db kv.TemporalRoDB
8079

8180
chainRW chainreader.ChainReaderWriterEth1
8281
lock sync.Mutex
@@ -131,8 +130,6 @@ func (e *EngineServer) Start(
131130
eth rpchelper.ApiBackend,
132131
mining txpoolproto.MiningClient,
133132
) error {
134-
e.db = db
135-
136133
var eg errgroup.Group
137134
if !e.caplin {
138135
eg.Go(func() error {

execution/engineapi/engine_server_test.go

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -281,7 +281,6 @@ func TestGetPayloadBodiesByHashV2(t *testing.T) {
281281
executionRpc := direct.NewExecutionClientDirect(mockSentry.Eth1ExecutionService)
282282
maxReorgDepth := ethconfig.Defaults.MaxReorgDepth
283283
engineServer := NewEngineServer(mockSentry.Log, mockSentry.ChainConfig, executionRpc, nil, false, false, true, nil, ethconfig.Defaults.FcuTimeout, maxReorgDepth)
284-
engineServer.db = mockSentry.DB
285284

286285
const blockNum = 1
287286
blockHash := canonicalHashAt(t, mockSentry.DB, blockNum)
@@ -315,7 +314,6 @@ func TestGetPayloadBodiesByRangeV2(t *testing.T) {
315314
executionRpc := direct.NewExecutionClientDirect(mockSentry.Eth1ExecutionService)
316315
maxReorgDepth := ethconfig.Defaults.MaxReorgDepth
317316
engineServer := NewEngineServer(mockSentry.Log, mockSentry.ChainConfig, executionRpc, nil, false, false, true, nil, ethconfig.Defaults.FcuTimeout, maxReorgDepth)
318-
engineServer.db = mockSentry.DB
319317

320318
const (
321319
start = 1

execution/execmodule/chainreader/chain_reader.go

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ import (
3030
"github.com/erigontech/erigon/cl/cltypes/solid"
3131
"github.com/erigontech/erigon/cl/utils"
3232
"github.com/erigontech/erigon/common"
33+
"github.com/erigontech/erigon/common/hexutil"
3334
"github.com/erigontech/erigon/common/log/v3"
3435
"github.com/erigontech/erigon/execution/chain"
3536
"github.com/erigontech/erigon/execution/engineapi/engine_types"
@@ -250,6 +251,50 @@ func (c ChainReaderWriterEth1) GetBodiesByRange(ctx context.Context, start, coun
250251
return ret, nil
251252
}
252253

254+
func (c ChainReaderWriterEth1) GetPayloadBodiesByHash(ctx context.Context, hashes []common.Hash) ([]*engine_types.ExecutionPayloadBodyV2, error) {
255+
grpcHashes := make([]*typesproto.H256, len(hashes))
256+
for i := range grpcHashes {
257+
grpcHashes[i] = gointerfaces.ConvertHashToH256(hashes[i])
258+
}
259+
resp, err := c.executionModule.GetPayloadBodiesByHash(ctx, &executionproto.GetPayloadBodiesByHashRequest{
260+
Hashes: grpcHashes,
261+
})
262+
if err != nil {
263+
return nil, err
264+
}
265+
return convertPayloadBodiesFromRpc(resp.Bodies), nil
266+
}
267+
268+
func (c ChainReaderWriterEth1) GetPayloadBodiesByRange(ctx context.Context, start, count uint64) ([]*engine_types.ExecutionPayloadBodyV2, error) {
269+
resp, err := c.executionModule.GetPayloadBodiesByRange(ctx, &executionproto.GetPayloadBodiesByRangeRequest{
270+
Start: start,
271+
Count: count,
272+
})
273+
if err != nil {
274+
return nil, err
275+
}
276+
return convertPayloadBodiesFromRpc(resp.Bodies), nil
277+
}
278+
279+
func convertPayloadBodiesFromRpc(bodies []*typesproto.ExecutionPayloadBody) []*engine_types.ExecutionPayloadBodyV2 {
280+
result := make([]*engine_types.ExecutionPayloadBodyV2, len(bodies))
281+
for i, body := range bodies {
282+
if body == nil {
283+
continue
284+
}
285+
txs := make([]hexutil.Bytes, len(body.Transactions))
286+
for j, tx := range body.Transactions {
287+
txs[j] = tx
288+
}
289+
result[i] = &engine_types.ExecutionPayloadBodyV2{
290+
Transactions: txs,
291+
Withdrawals: moduleutil.ConvertWithdrawalsFromRpc(body.Withdrawals),
292+
BlockAccessList: body.BlockAccessList,
293+
}
294+
}
295+
return result
296+
}
297+
253298
func (c ChainReaderWriterEth1) Ready(ctx context.Context) (bool, error) {
254299
resp, err := c.executionModule.Ready(ctx, &emptypb.Empty{})
255300
if err != nil {

execution/execmodule/getters.go

Lines changed: 110 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
package execmodule
1818

1919
import (
20+
"bytes"
2021
"context"
2122
"errors"
2223
"fmt"
@@ -214,6 +215,115 @@ func (e *EthereumExecutionModule) GetBodiesByRange(ctx context.Context, req *exe
214215
}, nil
215216
}
216217

218+
func (e *EthereumExecutionModule) GetPayloadBodiesByHash(ctx context.Context, req *executionproto.GetPayloadBodiesByHashRequest) (*executionproto.GetPayloadBodiesBatchResponse, error) {
219+
tx, err := e.db.BeginRo(ctx)
220+
if err != nil {
221+
return nil, fmt.Errorf("ethereumExecutionModule.GetPayloadBodiesByHash: could not begin database tx %w", err)
222+
}
223+
defer tx.Rollback()
224+
225+
bodies := make([]*typesproto.ExecutionPayloadBody, 0, len(req.Hashes))
226+
for _, hash := range req.Hashes {
227+
h := gointerfaces.ConvertH256ToHash(hash)
228+
number, err := e.blockReader.HeaderNumber(ctx, tx, h)
229+
if err != nil {
230+
return nil, fmt.Errorf("ethereumExecutionModule.GetPayloadBodiesByHash: HeaderNumber error %w", err)
231+
}
232+
if number == nil {
233+
bodies = append(bodies, nil)
234+
continue
235+
}
236+
body, err := e.getBody(ctx, tx, h, *number)
237+
if err != nil {
238+
return nil, fmt.Errorf("ethereumExecutionModule.GetPayloadBodiesByHash: getBody error %w", err)
239+
}
240+
if body == nil {
241+
bodies = append(bodies, nil)
242+
continue
243+
}
244+
txs, err := types.MarshalTransactionsBinary(body.Transactions)
245+
if err != nil {
246+
return nil, fmt.Errorf("ethereumExecutionModule.GetPayloadBodiesByHash: MarshalTransactionsBinary error %w", err)
247+
}
248+
balBytes, err := rawdb.ReadBlockAccessListBytes(tx, h, *number)
249+
if err != nil {
250+
return nil, fmt.Errorf("ethereumExecutionModule.GetPayloadBodiesByHash: ReadBlockAccessListBytes error %w", err)
251+
}
252+
var bal []byte
253+
if len(balBytes) > 0 {
254+
bal = bytes.Clone(balBytes)
255+
}
256+
257+
bodies = append(bodies, &typesproto.ExecutionPayloadBody{
258+
Transactions: txs,
259+
Withdrawals: moduleutil.ConvertWithdrawalsToRpc(body.Withdrawals),
260+
BlockAccessList: bal,
261+
})
262+
}
263+
264+
return &executionproto.GetPayloadBodiesBatchResponse{Bodies: bodies}, nil
265+
}
266+
267+
func (e *EthereumExecutionModule) GetPayloadBodiesByRange(ctx context.Context, req *executionproto.GetPayloadBodiesByRangeRequest) (*executionproto.GetPayloadBodiesBatchResponse, error) {
268+
tx, err := e.db.BeginRo(ctx)
269+
if err != nil {
270+
return nil, fmt.Errorf("ethereumExecutionModule.GetPayloadBodiesByRange: could not begin database tx %w", err)
271+
}
272+
defer tx.Rollback()
273+
274+
bodies := make([]*typesproto.ExecutionPayloadBody, 0, req.Count)
275+
276+
for i := uint64(0); i < req.Count; i++ {
277+
blockNum := req.Start + i
278+
hash, err := e.canonicalHash(ctx, tx, blockNum)
279+
if err != nil {
280+
return nil, fmt.Errorf("ethereumExecutionModule.GetPayloadBodiesByRange: ReadCanonicalHash error %w", err)
281+
}
282+
if hash == (common.Hash{}) {
283+
break
284+
}
285+
286+
body, err := e.getBody(ctx, tx, hash, blockNum)
287+
if err != nil {
288+
return nil, fmt.Errorf("ethereumExecutionModule.GetPayloadBodiesByRange: getBody error %w", err)
289+
}
290+
if body == nil {
291+
bodies = append(bodies, nil)
292+
continue
293+
}
294+
295+
txs, err := types.MarshalTransactionsBinary(body.Transactions)
296+
if err != nil {
297+
return nil, fmt.Errorf("ethereumExecutionModule.GetPayloadBodiesByRange: MarshalTransactionsBinary error %w", err)
298+
}
299+
balBytes, err := rawdb.ReadBlockAccessListBytes(tx, hash, blockNum)
300+
if err != nil {
301+
return nil, fmt.Errorf("ethereumExecutionModule.GetPayloadBodiesByRange: ReadBlockAccessListBytes error %w", err)
302+
}
303+
var bal []byte
304+
if len(balBytes) > 0 {
305+
bal = bytes.Clone(balBytes)
306+
}
307+
308+
bodies = append(bodies, &typesproto.ExecutionPayloadBody{
309+
Transactions: txs,
310+
Withdrawals: moduleutil.ConvertWithdrawalsToRpc(body.Withdrawals),
311+
BlockAccessList: bal,
312+
})
313+
}
314+
315+
// Remove trailing nil values
316+
for i := len(bodies) - 1; i >= 0; i-- {
317+
if bodies[i] == nil {
318+
bodies = bodies[:i]
319+
} else {
320+
break
321+
}
322+
}
323+
324+
return &executionproto.GetPayloadBodiesBatchResponse{Bodies: bodies}, nil
325+
}
326+
217327
func (e *EthereumExecutionModule) GetHeaderHashNumber(ctx context.Context, req *typesproto.H256) (*executionproto.GetHeaderHashNumberResponse, error) {
218328
tx, err := e.db.BeginRo(ctx)
219329
if err != nil {

node/direct/execution_client.go

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,14 @@ func (s *ExecutionClientDirect) GetBodiesByRange(ctx context.Context, in *execut
4646
return s.server.GetBodiesByRange(ctx, in)
4747
}
4848

49+
func (s *ExecutionClientDirect) GetPayloadBodiesByHash(ctx context.Context, in *executionproto.GetPayloadBodiesByHashRequest, opts ...grpc.CallOption) (*executionproto.GetPayloadBodiesBatchResponse, error) {
50+
return s.server.GetPayloadBodiesByHash(ctx, in)
51+
}
52+
53+
func (s *ExecutionClientDirect) GetPayloadBodiesByRange(ctx context.Context, in *executionproto.GetPayloadBodiesByRangeRequest, opts ...grpc.CallOption) (*executionproto.GetPayloadBodiesBatchResponse, error) {
54+
return s.server.GetPayloadBodiesByRange(ctx, in)
55+
}
56+
4957
func (s *ExecutionClientDirect) HasBlock(ctx context.Context, in *executionproto.GetSegmentRequest, opts ...grpc.CallOption) (*executionproto.HasBlockResponse, error) {
5058
return s.server.HasBlock(ctx, in)
5159
}

0 commit comments

Comments
 (0)