Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -7,3 +7,4 @@ test-*.yaml

.hack/devnet/generated-**
.hack/devnet/custom-**
CLAUDE.md
50 changes: 50 additions & 0 deletions pkg/coordinator/clients/execution/rpc/ethconfig.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
package rpc

import (
"context"
"encoding/json"
)

// EthConfigResponse represents the response from eth_config RPC call (EIP-7910)
type EthConfigResponse struct {
Current *ForkConfig `json:"current"`
Next *ForkConfig `json:"next"`
Last *ForkConfig `json:"last"`
}

// ForkConfig represents a fork configuration
type ForkConfig struct {
ActivationTime int64 `json:"activationTime"`
BlobSchedule map[string]interface{} `json:"blobSchedule,omitempty"`
ChainID string `json:"chainId"`
ForkID string `json:"forkId"`
Precompiles map[string]interface{} `json:"precompiles,omitempty"`
SystemContracts map[string]interface{} `json:"systemContracts,omitempty"`
}

// GetEthConfig queries the eth_config RPC method (EIP-7910)
func (ec *ExecutionClient) GetEthConfig(ctx context.Context) (*EthConfigResponse, error) {
closeFn := ec.enforceConcurrencyLimit(ctx)
if closeFn == nil {
return nil, nil
}

defer closeFn()

reqCtx, reqCtxCancel := context.WithTimeout(ctx, ec.requestTimeout)
defer reqCtxCancel()

var result json.RawMessage
err := ec.rpcClient.CallContext(reqCtx, &result, "eth_config")

if err != nil {
return nil, err
}

var config EthConfigResponse
if err := json.Unmarshal(result, &config); err != nil {
return nil, err
}

return &config, nil
}
86 changes: 86 additions & 0 deletions pkg/coordinator/tasks/check_eth_config/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
## `check_eth_config` Task

### Description
The `check_eth_config` task verifies that all execution clients in the network return consistent chain configuration via the `eth_config` JSON-RPC method as defined in EIP-7910. This task is essential for ensuring that all execution layer clients have the same fork configuration, including chain ID, fork IDs, activation times, precompiles, and system contracts. When mismatches are detected, the task provides a detailed diff showing which clients returned which configuration variants.

### Configuration Parameters

- **`clientPattern`**:
A regex pattern to select specific execution client endpoints for querying `eth_config`. This allows targeting specific clients within the network. An empty pattern (default) targets all ready execution clients.

- **`excludeClientPattern`**:
A regex pattern to exclude certain execution clients from the `eth_config` check. This is useful for excluding known misconfigured or test clients from the consistency check.

- **`failOnMismatch`**:
Determines whether the task should fail if any execution client returns a different `eth_config` response. If set to `true` (default), the task fails on configuration mismatches. If set to `false`, mismatches are logged but the task continues without failure.

- **`excludeSyncingClients`**:
When set to `true`, the task excludes execution clients that are currently syncing. If set to `false` (default), syncing clients are included in the check. This is useful for testing configuration consistency even before clients are fully synced, as `eth_config` returns configuration data that doesn't depend on sync status.

### Outputs

- **`ethConfig`**:
The reference `eth_config` response from the first successful client query, returned as a JSON string. This output contains the complete fork configuration including current, next, and last fork details with activation times, chain ID, fork ID, blob schedule, precompiles, and system contracts.

### Defaults

Default settings for the `check_eth_config` task:

```yaml
- name: check_eth_config
config:
clientPattern: ""
excludeClientPattern: ""
failOnMismatch: true
excludeSyncingClients: false
```

### Example Usage

Basic usage checking all execution clients:

```yaml
- name: check_eth_config
title: "Verify eth_config consistency across all EL clients"
config:
failOnMismatch: true
```

Checking specific clients only:

```yaml
- name: check_eth_config
title: "Verify eth_config for Geth clients only"
config:
clientPattern: ".*geth.*"
failOnMismatch: true
```

Non-blocking check that logs mismatches but doesn't fail:

```yaml
- name: check_eth_config
title: "Monitor eth_config consistency"
config:
failOnMismatch: false
```

Only check fully synced clients:

```yaml
- name: check_eth_config
title: "Verify eth_config for synced clients only"
config:
excludeSyncingClients: true
failOnMismatch: true
```

### Implementation Details

The task queries the `eth_config` RPC method (EIP-7910) from all matching execution clients and performs a JSON-level comparison of the responses. When configurations match, the task succeeds and outputs the reference configuration. When mismatches are detected, the task provides a detailed error log showing:

- All unique configuration variants encountered
- Which clients returned each variant
- The full JSON structure of each variant for easy comparison

This makes it easy to diagnose configuration drift or misconfiguration across the execution layer.
19 changes: 19 additions & 0 deletions pkg/coordinator/tasks/check_eth_config/config.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
package checkethconfig

type Config struct {
ClientPattern string `yaml:"clientPattern" json:"clientPattern"`
ExcludeClientPattern string `yaml:"excludeClientPattern" json:"excludeClientPattern"`
FailOnMismatch bool `yaml:"failOnMismatch" json:"failOnMismatch"`
ExcludeSyncingClients bool `yaml:"excludeSyncingClients" json:"excludeSyncingClients"`
}

func DefaultConfig() Config {
return Config{
FailOnMismatch: true,
ExcludeSyncingClients: false,
}
}

func (c *Config) Validate() error {
return nil
}
Loading
Loading