Skip to content
Open
Show file tree
Hide file tree
Changes from 2 commits
Commits
Show all changes
23 commits
Select commit Hold shift + click to select a range
f8bec03
feat(rpc): add rpc pool for endpoint fallback
SeUkKim Jul 24, 2025
0bb912a
chore: fix typo
SeUkKim Jul 24, 2025
46f740a
chore: sort imports.
SeUkKim Jul 24, 2025
a447897
wip(rpc): apply feedbacks
SeUkKim Jul 24, 2025
eac5605
refactor(rpc): deduplicate retry logic in ExecuteWithFallback using t…
SeUkKim Jul 24, 2025
54e90de
refactor(config): rename RPCAddress to RPCAddresses for clarity
SeUkKim Jul 24, 2025
79a23d6
chore: add missed files
SeUkKim Jul 24, 2025
a81e174
fix(rpc): add mutex to ensure tread-safe access to HTTP client.
SeUkKim Jul 24, 2025
a531045
fix(rpc): use pointer receivers for RCPClient methods
SeUkKim Jul 24, 2025
ccfe38e
chore: fix lint error
SeUkKim Jul 25, 2025
a78ae66
refactor(rpcclient): pass rpc-timeout via context instead of env var
SeUkKim Jul 25, 2025
44aa89a
chore(challenger): update comments to reflect challenger
SeUkKim Jul 25, 2025
7547280
feat(rpcclient): implement advanced RPC pool with health scoring
SeUkKim Aug 6, 2025
7f7520d
fix(rpcclient): fix race condition when accessing client score
SeUkKim Aug 6, 2025
dc458b2
fix(rpcpool): delete invalid endpoints from the slice instead of mark…
SeUkKim Aug 14, 2025
395f427
docs(rpcpool): add a more descriptive comment for function
SeUkKim Aug 14, 2025
d721e33
test(rpcpool): add and fix tests.
SeUkKim Aug 14, 2025
c3f4e03
fix(rpcpool): mark client healthy for retry rather than recreating it
SeUkKim Aug 18, 2025
f46d2f5
style(rpcpool): format code with gofmt
SeUkKim Aug 18, 2025
114601b
fix(rpcpool): fix data race
SeUkKim Aug 18, 2025
ea3bf90
refactor(rpcpool): refactor client-health and scoring methods to take…
SeUkKim Aug 18, 2025
1980ef5
style(rpcpool): format code with gofmt
SeUkKim Aug 18, 2025
dd3db87
test(rpcpool): use fully qualified urls in tests.
SeUkKim Aug 18, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
48 changes: 48 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -100,3 +100,51 @@ Challenger node types:
- host
- child
```

## RPC Pool Configuration

To enhance reliability, the bots support multiple RPC endpoints for L1, L2, and DA nodes. This allows for automatic fallback and retries if an endpoint becomes unavailable.

### Endpoint Configuration

In your configuration file (`~/.opinit/[bot-name].json`), you can specify a list of RPC addresses for each node:

```json
{
"l1_node": {
"chain_id": "testnet-l1-1",
"bech32_prefix": "init",
"rpc_address": [
"tcp://doi-rpc:26657",
"tcp://another-l1-rpc:26657"
]
},
"l2_node": {
"chain_id": "testnet-l2-1",
"bech32_prefix": "init",
"rpc_address": [
"tcp://rpc:27657",
"tcp://another-l2-rpc:27657"
]
},
"da_node": {
"chain_id": "testnet-l1-1",
"bech32_prefix": "init",
"rpc_address": [
"tcp://rpc:26657",
"tcp://another-da-rpc:26657"
]
}
}
```

The bot will try the endpoints in the order they are listed. If a request to the first endpoint fails, it will automatically fall back to the next one in the list.

### Timeout Configuration

You can configure the timeout for each RPC request using the `RPC_TIMEOUT_SECONDS` environment variable. The value is in seconds. If the variable is not set, the default timeout is 5 seconds.

```bash
export RPC_TIMEOUT_SECONDS=10
opinitd start [bot-name]
```
10 changes: 8 additions & 2 deletions challenger/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -28,12 +28,18 @@ To configure the Challenger, fill in the values in the `~/.opinit/challenger.jso
"l1_node": {
"chain_id": "testnet-l1-1",
"bech32_prefix": "init",
"rpc_address": "tcp://localhost:26657",
"rpc_address": [
"tcp://doi-rpc:26657",
"tcp://localhost:26657"
],
},
"l2_node": {
"chain_id": "testnet-l2-1",
"bech32_prefix": "init",
"rpc_address": "tcp://localhost:27657",
"rpc_address": [
"tcp://another-rpc:26657",
"tcp://localhost:27657"
],
},
// DisableAutoSetL1Height is the flag to disable the automatic setting of the l1 height.
// If it is false, it will finds the optimal height and sets l1_start_height automatically
Expand Down
12 changes: 6 additions & 6 deletions challenger/types/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,9 @@ import (
)

type NodeConfig struct {
ChainID string `json:"chain_id"`
Bech32Prefix string `json:"bech32_prefix"`
RPCAddress string `json:"rpc_address"`
ChainID string `json:"chain_id"`
Bech32Prefix string `json:"bech32_prefix"`
RPCAddress []string `json:"rpc_address"`
}

func (nc NodeConfig) Validate() error {
Expand All @@ -20,7 +20,7 @@ func (nc NodeConfig) Validate() error {
if nc.Bech32Prefix == "" {
return errors.New("bech32 prefix is required")
}
if nc.RPCAddress == "" {
if len(nc.RPCAddress) == 0 {
return errors.New("RPC address is required")
}
return nil
Expand Down Expand Up @@ -66,13 +66,13 @@ func DefaultConfig() *Config {
L1Node: NodeConfig{
ChainID: "testnet-l1-1",
Bech32Prefix: "init",
RPCAddress: "tcp://localhost:26657",
RPCAddress: []string{"tcp://localhost:26657"},
},

L2Node: NodeConfig{
ChainID: "testnet-l2-1",
Bech32Prefix: "init",
RPCAddress: "tcp://localhost:27657",
RPCAddress: []string{"tcp://localhost:27657"},
},
DisableAutoSetL1Height: false,
L1StartHeight: 1,
Expand Down
15 changes: 12 additions & 3 deletions executor/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -26,23 +26,32 @@ To configure the Executor, fill in the values in the `~/.opinit/executor.json` f
"l1_node": {
"chain_id": "testnet-l1-1",
"bech32_prefix": "init",
"rpc_address": "tcp://localhost:26657",
"rpc_address": [
"tcp://doi-rpc.com",
"tcp://localhost:26657"
],
"gas_price": "0.15uinit",
"gas_adjustment": 1.5,
"tx_timeout": 60
},
"l2_node": {
"chain_id": "testnet-l2-1",
"bech32_prefix": "init",
"rpc_address": "tcp://localhost:27657",
"rpc_address": [
"tcp://another-rpc:27657",
"tcp://localhost:27657"
],
"gas_price": "",
"gas_adjustment": 1.5,
"tx_timeout": 60
},
"da_node": {
"chain_id": "testnet-l1-1",
"bech32_prefix": "init",
"rpc_address": "tcp://localhost:26657",
"rpc_address": [
"tcp://another-rpc:26657",
"tcp://localhost:26657"
],
"gas_price": "0.15uinit",
"gas_adjustment": 1.5,
"tx_timeout": 60
Expand Down
6 changes: 4 additions & 2 deletions executor/batchsubmitter/batch_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -272,7 +272,8 @@ func TestFinalizeBatch(t *testing.T) {
require.NoError(t, err)

mockCaller := mockclient.NewMockCaller()
rpcClient := rpcclient.NewRPCClientWithClient(appCodec, client.NewWithCaller(mockCaller))
rpcClient, err := rpcclient.NewRPCClientWithClient(appCodec, client.NewWithCaller(mockCaller), []string{"http://localhost:26657"})
require.NoError(t, err)
batchNode := node.NewTestNode(nodetypes.NodeConfig{}, batchDB, appCodec, txConfig, rpcClient, nil)

hostCdc, _, err := hostprovider.GetCodec("init")
Expand Down Expand Up @@ -753,7 +754,8 @@ func TestSubmitGenesis(t *testing.T) {
require.NoError(t, err)

mockCaller := mockclient.NewMockCaller()
rpcClient := rpcclient.NewRPCClientWithClient(appCodec, client.NewWithCaller(mockCaller))
rpcClient, err := rpcclient.NewRPCClientWithClient(appCodec, client.NewWithCaller(mockCaller), []string{"http://localhost:26657"})
require.NoError(t, err)
batchNode := node.NewTestNode(nodetypes.NodeConfig{}, batchDB, appCodec, txConfig, rpcClient, nil)

hostCdc, _, err := hostprovider.GetCodec("init")
Expand Down
3 changes: 2 additions & 1 deletion executor/batchsubmitter/handler_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,8 @@ func TestRawBlockHandler(t *testing.T) {
require.NoError(t, err)

mockCaller := mockclient.NewMockCaller()
rpcClient := rpcclient.NewRPCClientWithClient(appCodec, client.NewWithCaller(mockCaller))
rpcClient, err := rpcclient.NewRPCClientWithClient(appCodec, client.NewWithCaller(mockCaller), []string{"http://localhost:26657"})
require.NoError(t, err)
batchNode := node.NewTestNode(nodetypes.NodeConfig{}, batchDB, appCodec, txConfig, rpcClient, nil)

hostCdc, _, err := hostprovider.GetCodec("init")
Expand Down
20 changes: 10 additions & 10 deletions executor/types/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,12 +11,12 @@ import (
)

type NodeConfig struct {
ChainID string `json:"chain_id"`
Bech32Prefix string `json:"bech32_prefix"`
RPCAddress string `json:"rpc_address"`
GasPrice string `json:"gas_price"`
GasAdjustment float64 `json:"gas_adjustment"`
TxTimeout int64 `json:"tx_timeout"` // seconds
ChainID string `json:"chain_id"`
Bech32Prefix string `json:"bech32_prefix"`
RPCAddress []string `json:"rpc_address"`
Comment thread
SeUkKim marked this conversation as resolved.
Outdated
GasPrice string `json:"gas_price"`
GasAdjustment float64 `json:"gas_adjustment"`
TxTimeout int64 `json:"tx_timeout"` // seconds
}

func (nc NodeConfig) Validate() error {
Expand All @@ -26,7 +26,7 @@ func (nc NodeConfig) Validate() error {
if nc.Bech32Prefix == "" {
return errors.New("bech32 prefix is required")
}
if nc.RPCAddress == "" {
if len(nc.RPCAddress) == 0 {
return errors.New("RPC address is required")
}
return nil
Expand Down Expand Up @@ -109,7 +109,7 @@ func DefaultConfig() *Config {
L1Node: NodeConfig{
ChainID: "testnet-l1-1",
Bech32Prefix: "init",
RPCAddress: "tcp://localhost:26657",
RPCAddress: []string{"tcp://localhost:26657"},
GasPrice: "0.15uinit",
GasAdjustment: 1.5,
TxTimeout: 60,
Expand All @@ -118,7 +118,7 @@ func DefaultConfig() *Config {
L2Node: NodeConfig{
ChainID: "testnet-l2-1",
Bech32Prefix: "init",
RPCAddress: "tcp://localhost:27657",
RPCAddress: []string{"tcp://localhost:27657"},
GasPrice: "",
GasAdjustment: 1.5,
TxTimeout: 60,
Expand All @@ -127,7 +127,7 @@ func DefaultConfig() *Config {
DANode: NodeConfig{
ChainID: "testnet-l1-1",
Bech32Prefix: "init",
RPCAddress: "tcp://localhost:26657",
RPCAddress: []string{"tcp://localhost:26657"},
GasPrice: "0.15uinit",
GasAdjustment: 1.5,
TxTimeout: 60,
Expand Down
2 changes: 1 addition & 1 deletion node/node.go
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ func NewNode(cfg nodetypes.NodeConfig, db types.DB, cdc codec.Codec, txConfig cl

rpcClient, err := rpcclient.NewRPCClient(cdc, cfg.RPC)
if err != nil {
return nil, err
return nil, errors.Wrap(err, "failed to create RPC client")
}

n := &Node{
Expand Down
Loading