Skip to content
Permalink

Comparing changes

This is a direct comparison between two commits made in this repository or its related repositories. View the default comparison for this range or learn more about diff comparisons.

Open a pull request

Create a new pull request by comparing changes across two branches. If you need to, you can also . Learn more about diff comparisons here.
base repository: duneanalytics/node-indexer
Failed to load repositories. Confirm that selected base ref is valid, then try again.
Loading
base: 685f2b0d54f38b18177df99c88e86d1c07c33d4f
Choose a base ref
..
head repository: duneanalytics/node-indexer
Failed to load repositories. Confirm that selected head ref is valid, then try again.
Loading
compare: 82794c1d2c7db6ef2f1bab8b9b634088ed83da3a
Choose a head ref
Showing with 70 additions and 19 deletions.
  1. +44 −0 client/jsonrpc/arbitrum_nitro.go
  2. +12 −1 client/jsonrpc/client.go
  3. +3 −0 client/jsonrpc/models.go
  4. +2 −5 client/jsonrpc/opstack.go
  5. +8 −12 cmd/main.go
  6. +1 −1 models/evm.go
44 changes: 44 additions & 0 deletions client/jsonrpc/arbitrum_nitro.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
package jsonrpc

import (
"context"
"errors"
"log/slog"
"time"

"github.com/duneanalytics/blockchain-ingester/models"
)

type ArbitrumNitroClient struct {
rpcClient
}

var _ BlockchainClient = &ArbitrumNitroClient{}

func NewArbitrumNitroClient(log *slog.Logger, cfg Config) (*ArbitrumNitroClient, error) {
rpcClient, err := newClient(log.With("module", "jsonrpc"), cfg)
if err != nil {
return nil, err
}
return &ArbitrumNitroClient{*rpcClient}, nil
}

// BlockByNumber returns the block with the given blockNumber.
// it uses 3 different methods to get the block:
// 1. eth_getBlockByNumber
// 2. debug_traceBlockByNumber with tracer "callTracer"
// TODO: this method should be optional
// 2. call to eth_getTransactionReceipt for each Tx present in the Block
//
// We encode the payload in NDJSON, and use a header line to indicate how many Tx are present in the block
func (c *ArbitrumNitroClient) BlockByNumber(_ context.Context, blockNumber int64) (models.RPCBlock, error) {
tStart := time.Now()
defer func() {
c.log.Debug("BlockByNumber", "blockNumber", blockNumber, "duration", time.Since(tStart))
}()
// TODO: lets not implement this yet
return models.RPCBlock{
BlockNumber: blockNumber,
Error: errors.New("not implemented"),
}, errors.New("not implemented")
}
13 changes: 12 additions & 1 deletion client/jsonrpc/client.go
Original file line number Diff line number Diff line change
@@ -37,7 +37,18 @@ type rpcClient struct {
wrkPool *ants.Pool
}

func NewClient(log *slog.Logger, cfg Config) (*rpcClient, error) { // revive:disable-line:unexported-return
func NewClient(logger *slog.Logger, cfg Config) (BlockchainClient, error) {
switch cfg.EVMStack {
case models.OpStack:
return NewOpStackClient(logger, cfg)
case models.ArbitrumNitro:
return NewArbitrumNitroClient(logger, cfg)
default:
return nil, fmt.Errorf("unsupported EVM stack: %s", cfg.EVMStack)
}
}

func newClient(log *slog.Logger, cfg Config) (*rpcClient, error) { // revive:disable-line:unexported-return
client := retryablehttp.NewClient()
client.RetryMax = MaxRetries
client.Logger = log
3 changes: 3 additions & 0 deletions client/jsonrpc/models.go
Original file line number Diff line number Diff line change
@@ -2,12 +2,15 @@ package jsonrpc

import (
"time"

"github.com/duneanalytics/blockchain-ingester/models"
)

type Config struct {
URL string
PollInterval time.Duration
HTTPHeaders map[string]string
EVMStack models.EVMStack
// rpcClient is used in parallel by the ingester to fetch blocks
// but it also has internal request concurrency on handling each block
// to avoid spawning too many http requests to the RPC node we set here an upper limit
7 changes: 2 additions & 5 deletions client/jsonrpc/opstack.go
Original file line number Diff line number Diff line change
@@ -18,7 +18,7 @@ type OpStackClient struct {
var _ BlockchainClient = &OpStackClient{}

func NewOpStackClient(log *slog.Logger, cfg Config) (*OpStackClient, error) {
rpcClient, err := NewClient(log.With("module", "jsonrpc"), cfg)
rpcClient, err := newClient(log.With("module", "jsonrpc"), cfg)
if err != nil {
return nil, err
}
@@ -37,10 +37,7 @@ func NewOpStackClient(log *slog.Logger, cfg Config) (*OpStackClient, error) {
func (c *OpStackClient) BlockByNumber(ctx context.Context, blockNumber int64) (models.RPCBlock, error) {
tStart := time.Now()
defer func() {
c.log.Debug("BlockByNumber",
"blockNumber", blockNumber,
"duration", time.Since(tStart),
)
c.log.Debug("BlockByNumber", "blockNumber", blockNumber, "duration", time.Since(tStart))
}()
blockNumberHex := fmt.Sprintf("0x%x", blockNumber)

20 changes: 8 additions & 12 deletions cmd/main.go
Original file line number Diff line number Diff line change
@@ -85,18 +85,14 @@ func main() {
logger.Info("Adding extra HTTP header to RPC requests", "key", key, "value", value)
rpcHTTPHeaders[key] = value
}
switch cfg.RPCStack {
case models.OpStack:
rpcClient, err = jsonrpc.NewOpStackClient(logger, jsonrpc.Config{
URL: cfg.RPCNode.NodeURL,
HTTPHeaders: rpcHTTPHeaders,
// real max request concurrency to RPP node
// each block requires multiple RPC requests
TotalRPCConcurrency: cfg.BlockConcurrency * 4,
})
default:
stdlog.Fatalf("unsupported RPC stack: %s", cfg.RPCStack)
}
rpcClient, err = jsonrpc.NewClient(logger, jsonrpc.Config{
URL: cfg.RPCNode.NodeURL,
HTTPHeaders: rpcHTTPHeaders,
EVMStack: cfg.RPCStack,
// real max request concurrency to RPP node
// each block requires multiple RPC requests
TotalRPCConcurrency: cfg.BlockConcurrency * 4,
})
if err != nil {
stdlog.Fatal(err)
}
2 changes: 1 addition & 1 deletion models/evm.go
Original file line number Diff line number Diff line change
@@ -4,7 +4,7 @@ type EVMStack string

const (
OpStack EVMStack = "opstack"
ArbitrumNitro EVMStack = "arbitrumnitro"
ArbitrumNitro EVMStack = "arbitrum-nitro"
)

func (e EVMStack) String() string {