Skip to content

Commit e3c8949

Browse files
committed
utilize eth_getBlockReceipts if possible
1 parent 0beab4a commit e3c8949

File tree

12 files changed

+337
-69
lines changed

12 files changed

+337
-69
lines changed

README.md

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -136,6 +136,43 @@ rpc:
136136
batchDelay: 100
137137
```
138138

139+
#### RPC Block Receipts Enabled
140+
If this is `true`, will use `eth_getBlockReceipts` instead of `eth_getLogs` if the RPC supports it. Allows getting receipt data for transactions, but is not supported by every RPC. Default is `false`.
141+
142+
cmd: `--rpc-block-receipts-enabled`
143+
env: `RPC_BLOCKRECEIPTS_ENABLED`
144+
yaml:
145+
```yaml
146+
rpc:
147+
blockReceipts:
148+
enabled: true
149+
```
150+
151+
#### RPC Block Receipts Blocks Per Request
152+
How many blocks at a time to fetch block receipts for from the RPC. Default is 250.
153+
Has no effect if it's larger than RPC blocks per request.
154+
155+
cmd: `--rpc-block-receipts-blocksPerRequest`
156+
env: `RPC_BLOCKRECEIPTS_BLOCKSPERREQUEST`
157+
yaml:
158+
```yaml
159+
rpc:
160+
blockReceipts:
161+
blocksPerRequest: 100
162+
```
163+
164+
#### RPC Block Receipts Batch Delay
165+
Milliseconds to wait between batches of block receipts when fetching from the RPC. Default is 0.
166+
167+
cmd: `--rpc-block-receipts-batchDelay`
168+
env: `RPC_BLOCKRECEIPTS_BATCHDELAY`
169+
yaml:
170+
```yaml
171+
rpc:
172+
blockReceipts:
173+
batchDelay: 100
174+
```
175+
139176
#### RPC Traces Enabled
140177
Whether to enable fetching traces from the RPC. Default is `true`, but it will try to detect if the RPC supports traces automatically.
141178

cmd/root.go

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,9 @@ func init() {
4141
rootCmd.PersistentFlags().Int("rpc-blocks-batchDelay", 0, "Milliseconds to wait between batches of blocks when fetching from the RPC")
4242
rootCmd.PersistentFlags().Int("rpc-logs-blocksPerRequest", 0, "How many blocks to fetch logs per request")
4343
rootCmd.PersistentFlags().Int("rpc-logs-batchDelay", 0, "Milliseconds to wait between batches of logs when fetching from the RPC")
44+
rootCmd.PersistentFlags().Bool("rpc-blockReceipts-enabled", false, "Whether to enable fetching block receipts from the RPC")
45+
rootCmd.PersistentFlags().Int("rpc-blockReceipts-blocksPerRequest", 0, "How many blocks to fetch receipts for per request")
46+
rootCmd.PersistentFlags().Int("rpc-blockReceipts-batchDelay", 0, "Milliseconds to wait between batches of receipts when fetching from the RPC")
4447
rootCmd.PersistentFlags().Bool("rpc-traces-enabled", true, "Whether to enable fetching traces from the RPC")
4548
rootCmd.PersistentFlags().Int("rpc-traces-blocksPerRequest", 0, "How many blocks to fetch traces per request")
4649
rootCmd.PersistentFlags().Int("rpc-traces-batchDelay", 0, "Milliseconds to wait between batches of traces when fetching from the RPC")
@@ -89,6 +92,9 @@ func init() {
8992
viper.BindPFlag("rpc.blocks.batchDelay", rootCmd.PersistentFlags().Lookup("rpc-blocks-batchDelay"))
9093
viper.BindPFlag("rpc.logs.blocksPerRequest", rootCmd.PersistentFlags().Lookup("rpc-logs-blocksPerRequest"))
9194
viper.BindPFlag("rpc.logs.batchDelay", rootCmd.PersistentFlags().Lookup("rpc-logs-batchDelay"))
95+
viper.BindPFlag("rpc.blockReceipts.enabled", rootCmd.PersistentFlags().Lookup("rpc-blockReceipts-enabled"))
96+
viper.BindPFlag("rpc.blockReceipts.blocksPerRequest", rootCmd.PersistentFlags().Lookup("rpc-blockReceipts-blocksPerRequest"))
97+
viper.BindPFlag("rpc.blockReceipts.batchDelay", rootCmd.PersistentFlags().Lookup("rpc-blockReceipts-batchDelay"))
9298
viper.BindPFlag("rpc.traces.enabled", rootCmd.PersistentFlags().Lookup("rpc-traces-enabled"))
9399
viper.BindPFlag("rpc.traces.blocksPerRequest", rootCmd.PersistentFlags().Lookup("rpc-traces-blocksPerRequest"))
94100
viper.BindPFlag("rpc.traces.batchDelay", rootCmd.PersistentFlags().Lookup("rpc-traces-batchDelay"))

configs/config.example.yml

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,10 @@ rpc:
55
logs:
66
blocksPerRequest: 400
77
batchDelay: 100
8+
blockReceipts:
9+
enabled: true
10+
blocksPerRequest: 500
11+
batchDelay: 100
812
traces:
913
enabled: true
1014
blocksPerRequest: 200
@@ -29,6 +33,11 @@ failureRecoverer:
2933
interval: 10000
3034
blocksPerRun: 100
3135

36+
reorgHandler:
37+
enabled: true
38+
interval: 1000
39+
blocksPerScan: 50
40+
3241
storage:
3342
main:
3443
clickhouse:

configs/config.go

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -81,22 +81,22 @@ type RedisConfig struct {
8181
DB int `mapstructure:"db"`
8282
}
8383

84-
type RPCBatchSizeConfig struct {
84+
type RPCBatchRequestConfig struct {
8585
BlocksPerRequest int `mapstructure:"blocksPerRequest"`
8686
BatchDelay int `mapstructure:"batchDelay"`
8787
}
8888

89-
type RPCTracesConfig struct {
90-
Enabled bool `mapstructure:"enabled"`
91-
BlocksPerRequest int `mapstructure:"blocksPerRequest"`
92-
BatchDelay int `mapstructure:"batchDelay"`
89+
type ToggleableRPCBatchRequestConfig struct {
90+
Enabled bool `mapstructure:"enabled"`
91+
RPCBatchRequestConfig
9392
}
9493

9594
type RPCConfig struct {
96-
URL string `mapstructure:"url"`
97-
Blocks RPCBatchSizeConfig `mapstructure:"blocks"`
98-
Logs RPCBatchSizeConfig `mapstructure:"logs"`
99-
Traces RPCTracesConfig `mapstructure:"traces"`
95+
URL string `mapstructure:"url"`
96+
Blocks RPCBatchRequestConfig `mapstructure:"blocks"`
97+
Logs RPCBatchRequestConfig `mapstructure:"logs"`
98+
BlockReceipts ToggleableRPCBatchRequestConfig `mapstructure:"blockReceipts"`
99+
Traces ToggleableRPCBatchRequestConfig `mapstructure:"traces"`
100100
}
101101

102102
type APIConfig struct {

internal/common/log.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,3 +18,5 @@ type Log struct {
1818
}
1919

2020
type RawLogs = []map[string]interface{}
21+
type RawReceipts = []RawReceipt
22+
type RawReceipt = map[string]interface{}

internal/common/transaction.go

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,5 +25,13 @@ type Transaction struct {
2525
R *big.Int `json:"r"`
2626
S *big.Int `json:"s"`
2727
V *big.Int `json:"v"`
28-
AccessListJson string `json:"access_list_json"`
28+
AccessListJson *string `json:"access_list_json"`
29+
ContractAddress *string `json:"contract_address"`
30+
GasUsed *uint64 `json:"gas_used"`
31+
CumulativeGasUsed *uint64 `json:"cumulative_gas_used"`
32+
EffectiveGasPrice *big.Int `json:"effective_gas_price"`
33+
BlobGasUsed *uint64 `json:"blob_gas_used"`
34+
BlobGasPrice *big.Int `json:"blob_gas_price"`
35+
LogsBloom *string `json:"logs_bloom"`
36+
Status *uint64 `json:"status"`
2937
}

internal/rpc/params.go

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,3 +21,7 @@ func GetLogsParams(blockNum *big.Int) []interface{} {
2121
func TraceBlockParams(blockNum *big.Int) []interface{} {
2222
return []interface{}{hexutil.EncodeBig(blockNum)}
2323
}
24+
25+
func GetBlockReceiptsParams(blockNum *big.Int) []interface{} {
26+
return []interface{}{hexutil.EncodeBig(blockNum)}
27+
}

internal/rpc/rpc.go

Lines changed: 84 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -27,9 +27,10 @@ type GetBlocksResult struct {
2727
}
2828

2929
type BlocksPerRequestConfig struct {
30-
Blocks int
31-
Logs int
32-
Traces int
30+
Blocks int
31+
Logs int
32+
Traces int
33+
Receipts int
3334
}
3435

3536
type IRPCClient interface {
@@ -44,13 +45,14 @@ type IRPCClient interface {
4445
}
4546

4647
type Client struct {
47-
RPCClient *gethRpc.Client
48-
EthClient *ethclient.Client
49-
supportsTraceBlock bool
50-
isWebsocket bool
51-
url string
52-
chainID *big.Int
53-
blocksPerRequest BlocksPerRequestConfig
48+
RPCClient *gethRpc.Client
49+
EthClient *ethclient.Client
50+
supportsTraceBlock bool
51+
supportsBlockReceipts bool
52+
isWebsocket bool
53+
url string
54+
chainID *big.Int
55+
blocksPerRequest BlocksPerRequestConfig
5456
}
5557

5658
func Initialize() (IRPCClient, error) {
@@ -111,28 +113,75 @@ func (rpc *Client) Close() {
111113
}
112114

113115
func (rpc *Client) checkSupportedMethods() error {
116+
if err := rpc.checkGetBlockByNumberSupport(); err != nil {
117+
return err
118+
}
119+
if err := rpc.checkGetBlockReceiptsSupport(); err != nil {
120+
return err
121+
}
122+
if err := rpc.checkGetLogsSupport(); err != nil {
123+
return err
124+
}
125+
if err := rpc.checkTraceBlockSupport(); err != nil {
126+
return err
127+
}
128+
return nil
129+
}
130+
131+
func (rpc *Client) checkGetBlockByNumberSupport() error {
114132
var blockByNumberResult interface{}
115133
err := rpc.RPCClient.Call(&blockByNumberResult, "eth_getBlockByNumber", "latest", true)
116134
if err != nil {
117135
return fmt.Errorf("eth_getBlockByNumber method not supported: %v", err)
118136
}
119137
log.Debug().Msg("eth_getBlockByNumber method supported")
138+
return nil
139+
}
120140

141+
func (rpc *Client) checkGetBlockReceiptsSupport() error {
142+
if config.Cfg.RPC.BlockReceipts.Enabled {
143+
var getBlockReceiptsResult interface{}
144+
receiptsErr := rpc.RPCClient.Call(&getBlockReceiptsResult, "eth_getBlockReceipts", "latest")
145+
if receiptsErr != nil {
146+
log.Warn().Err(receiptsErr).Msg("eth_getBlockReceipts method not supported")
147+
return fmt.Errorf("eth_getBlockReceipts method not supported: %v", receiptsErr)
148+
} else {
149+
rpc.supportsBlockReceipts = true
150+
log.Debug().Msg("eth_getBlockReceipts method supported")
151+
}
152+
} else {
153+
rpc.supportsBlockReceipts = false
154+
log.Debug().Msg("eth_getBlockReceipts method disabled")
155+
}
156+
return nil
157+
}
158+
159+
func (rpc *Client) checkGetLogsSupport() error {
160+
if rpc.supportsBlockReceipts {
161+
return nil
162+
}
121163
var getLogsResult interface{}
122164
logsErr := rpc.RPCClient.Call(&getLogsResult, "eth_getLogs", map[string]string{"fromBlock": "0x0", "toBlock": "0x0"})
123165
if logsErr != nil {
124166
return fmt.Errorf("eth_getLogs method not supported: %v", logsErr)
125167
}
126168
log.Debug().Msg("eth_getLogs method supported")
169+
return nil
170+
}
127171

128-
var traceBlockResult interface{}
172+
func (rpc *Client) checkTraceBlockSupport() error {
129173
if config.Cfg.RPC.Traces.Enabled {
174+
var traceBlockResult interface{}
130175
if traceBlockErr := rpc.RPCClient.Call(&traceBlockResult, "trace_block", "latest"); traceBlockErr != nil {
131176
log.Warn().Err(traceBlockErr).Msg("Optional method trace_block not supported")
177+
} else {
178+
rpc.supportsTraceBlock = true
179+
log.Debug().Msg("trace_block method supported")
132180
}
181+
} else {
182+
rpc.supportsTraceBlock = false
183+
log.Debug().Msg("trace_block method disabled")
133184
}
134-
rpc.supportsTraceBlock = traceBlockResult != nil
135-
log.Debug().Msgf("trace_block method supported: %v", rpc.supportsTraceBlock)
136185
return nil
137186
}
138187

@@ -147,33 +196,44 @@ func (rpc *Client) setChainID() error {
147196

148197
func (rpc *Client) GetFullBlocks(blockNumbers []*big.Int) []GetFullBlockResult {
149198
var wg sync.WaitGroup
150-
var blocks []RPCFetchBatchResult[common.RawBlock]
151-
var logs []RPCFetchBatchResult[common.RawLogs]
152-
var traces []RPCFetchBatchResult[common.RawTraces]
153-
199+
var blocks *[]RPCFetchBatchResult[common.RawBlock]
200+
var logs *[]RPCFetchBatchResult[common.RawLogs]
201+
var traces *[]RPCFetchBatchResult[common.RawTraces]
202+
var receipts *[]RPCFetchBatchResult[common.RawReceipts]
154203
wg.Add(2)
155204

156205
go func() {
157206
defer wg.Done()
158-
blocks = RPCFetchBatch[common.RawBlock](rpc, blockNumbers, "eth_getBlockByNumber", GetBlockWithTransactionsParams)
207+
result := RPCFetchBatch[common.RawBlock](rpc, blockNumbers, "eth_getBlockByNumber", GetBlockWithTransactionsParams)
208+
blocks = &result
159209
}()
160210

161-
go func() {
162-
defer wg.Done()
163-
logs = RPCFetchInBatches[common.RawLogs](rpc, blockNumbers, rpc.blocksPerRequest.Logs, config.Cfg.RPC.Logs.BatchDelay, "eth_getLogs", GetLogsParams)
164-
}()
211+
if rpc.supportsBlockReceipts {
212+
go func() {
213+
defer wg.Done()
214+
result := RPCFetchInBatches[common.RawReceipts](rpc, blockNumbers, rpc.blocksPerRequest.Receipts, config.Cfg.RPC.BlockReceipts.BatchDelay, "eth_getBlockReceipts", GetBlockReceiptsParams)
215+
receipts = &result
216+
}()
217+
} else {
218+
go func() {
219+
defer wg.Done()
220+
result := RPCFetchInBatches[common.RawLogs](rpc, blockNumbers, rpc.blocksPerRequest.Logs, config.Cfg.RPC.Logs.BatchDelay, "eth_getLogs", GetLogsParams)
221+
logs = &result
222+
}()
223+
}
165224

166225
if rpc.supportsTraceBlock {
167226
wg.Add(1)
168227
go func() {
169228
defer wg.Done()
170-
traces = RPCFetchInBatches[common.RawTraces](rpc, blockNumbers, rpc.blocksPerRequest.Traces, config.Cfg.RPC.Traces.BatchDelay, "trace_block", TraceBlockParams)
229+
result := RPCFetchInBatches[common.RawTraces](rpc, blockNumbers, rpc.blocksPerRequest.Traces, config.Cfg.RPC.Traces.BatchDelay, "trace_block", TraceBlockParams)
230+
traces = &result
171231
}()
172232
}
173233

174234
wg.Wait()
175235

176-
return SerializeFullBlocks(rpc.chainID, blocks, logs, traces)
236+
return SerializeFullBlocks(rpc.chainID, blocks, logs, traces, receipts)
177237
}
178238

179239
func (rpc *Client) GetBlocks(blockNumbers []*big.Int) []GetBlocksResult {

0 commit comments

Comments
 (0)