Skip to content
Open
Show file tree
Hide file tree
Changes from 29 commits
Commits
Show all changes
37 commits
Select commit Hold shift + click to select a range
38abf76
bootstrap charon launcher
sugh01 May 18, 2025
96e44b5
adds charon key formatter service
sugh01 May 18, 2025
6c883c9
removes redundant code
sugh01 May 18, 2025
bf90e5f
Persists charon cluster artefacts
sugh01 May 18, 2025
658f009
adds charon service, the feature is still broken
sugh01 May 22, 2025
2df8c98
adds an experimental charon:local to debug run
sugh01 May 26, 2025
4bb5837
adds lighthouse vc integration with Charon
sugh01 May 29, 2025
e4cb57a
adds lodestar and teku vc
sugh01 Jun 7, 2025
bff3886
adds nimbus vc
sugh01 Jun 7, 2025
ff6acec
adds prysm vc
sugh01 Jun 7, 2025
92f5c12
replaces hard coded values with constants
sugh01 Jun 10, 2025
24e022f
replaces hard coded values with constants
sugh01 Jun 10, 2025
36586e4
uses charon_oparams field to configure charon VCs
sugh01 Jun 11, 2025
4150572
removes unused files
sugh01 Jun 11, 2025
fa0376b
adds readme
sugh01 Aug 8, 2025
0b0ff27
Change from ethpandaops to ObolNetwork
KaloyanTanev Jun 17, 2026
ed3ca90
Various fixes after rebase
KaloyanTanev Jun 17, 2026
7488a41
Default to 4 charon nodes
KaloyanTanev Jun 17, 2026
709f925
Gate the DV path
KaloyanTanev Jun 17, 2026
5239d4e
Spin up own relay; fix metrics; cleanup unused calls
KaloyanTanev Jun 18, 2026
318b6b5
Various charon updates; add vouch VC
KaloyanTanev Jun 22, 2026
b830840
Add remote write option to Prometheus
KaloyanTanev Jun 22, 2026
902261c
Don't launch Vouch outside of DVs
KaloyanTanev Jun 22, 2026
6c441d4
Test remote write with changes in the original prometheus kurtosis pa…
KaloyanTanev Jun 22, 2026
d1d0318
Fix prometheus metrics
KaloyanTanev Jun 24, 2026
b09c788
Remove remote write; use upstream prometheus package
KaloyanTanev Jun 24, 2026
df92bec
Revert unrelated formatting
KaloyanTanev Jun 24, 2026
8fb6f53
Fix linting
KaloyanTanev Jun 24, 2026
10d44e3
Add remote write via KaloyanTanev/prometheus-package fork
KaloyanTanev Jun 24, 2026
40d5c08
Fix linting
KaloyanTanev Jun 24, 2026
75be305
Merge branch 'main' into charon
KaloyanTanev Jun 24, 2026
087e3ee
Reuse pre-existing VC modules; add Vouch VC module
KaloyanTanev Jun 25, 2026
1b18387
Move Charon key formatting to the generator
KaloyanTanev Jun 25, 2026
94515b8
Merge pull request #2 from ObolNetwork/charon-remote-write
KaloyanTanev Jun 26, 2026
c07501e
Make split keystore files readable/writable for non-root VC images
pinebit Jun 29, 2026
7e22a12
Increase max threads Teku VC can keep to Charon to 50
KaloyanTanev Jul 28, 2026
cab5508
Disable doppelganger detection for distributed (Charon) Nimbus VCs
KaloyanTanev Jul 31, 2026
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
162 changes: 154 additions & 8 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -571,6 +571,33 @@ participants:
# network parameter num_validator_keys_per_node
validator_count: null

# Charon Distributed Validator Configuration
# The number of Charon nodes to create for distributed validation
# Each Charon node will run as a middleware between the beacon node and validator client
# Minimum 4 nodes recommended for fault tolerance
# Only used when vc_type is set to "charon"
# Defaults to 4
charon_node_count: 4

# Charon-specific parameters for distributed validator setup
# Only used when vc_type is set to "charon"
charon_params:
# The type of validator client to run with Charon
# Valid values are: lighthouse, lodestar, teku, nimbus, prysm
# Each Charon node will run this validator client type
# Defaults to "lighthouse"
charon_vc: lighthouse

# The Docker image for the validator client used with Charon
# This allows you to specify custom validator client images
# Defaults by client:
# - lighthouse: sigp/lighthouse:latest
# - lodestar: chainsafe/lodestar:latest
# - teku: consensys/teku:latest
# - nimbus: statusim/nimbus-validator-client:multiarch-latest
# - prysm: gcr.io/prysmaticlabs/prysm/validator:latest
charon_vc_image: sigp/lighthouse:latest

# Whether to use a remote signer instead of the vc directly handling keys
# Note Lighthouse VC does not support this flag
# Defaults to false
Expand Down Expand Up @@ -2180,16 +2207,135 @@ participants:
"/configs": "validator_config.json" # File available at: /configs/validator_config.json
```

### Notes

- All file paths must be relative to the package root directory
- Files outside the package directory cannot be mounted directly
- The entire directory structure is preserved when mounting directories

## Charon Distributed Validator Technology (DVT)

[Charon](https://github.com/ObolNetwork/charon) is a distributed validator middleware that enables fault-tolerant Ethereum validation by running validator duties across multiple nodes. This package supports deploying Charon clusters with any of the supported validator clients.

### What is Distributed Validation?

Distributed validation splits validator duties across multiple nodes (typically 4-7), providing:

- **Fault Tolerance**: Continue validating even if some nodes go offline
- **Reduced Slashing Risk**: Consensus mechanisms prevent double-signing
- **Improved Uptime**: No single point of failure
- **Decentralization**: Distribute validator operations across multiple operators

### Charon Configuration

To use Charon distributed validators, set `vc_type: charon` in your participant configuration:

```yaml
participants:
- el_type: geth
el_image: ethereum/client-go:latest
cl_type: lighthouse
cl_image: sigp/lighthouse:latest-unstable
use_separate_vc: true
# Charon Configuration
vc_type: charon
vc_image: obolnetwork/charon:latest
charon_node_count: 4
charon_params:
charon_vc: teku
charon_vc_image: consensys/teku:latest
```

### Supported Validator Clients with Charon

All major Ethereum validator clients are supported with Charon:

| Validator Client | Status | Implementation | Notes |
| ---------------- | ------ | ------------------------ | ----------------------------- |
| **Lighthouse** | ✅ | Two-stage health checks | Default choice, most tested |
| **Lodestar** | ✅ | Script-based execution | Custom key management |
| **Teku** | ✅ | Config file approach | External signer mode |
| **Nimbus** | ✅ | Two-service architecture | Key import + validator client |
| **Prysm** | ✅ | Wallet-based import | Prysm wallet integration |

### Example Configurations

#### Basic Charon Setup (4 nodes with Lighthouse)

```yaml
participants:
- vc_type: charon
vc_image: obolnetwork/charon:latest
charon_node_count: 4
charon_params:
charon_vc: lighthouse
charon_vc_image: sigp/lighthouse:latest-unstable
```

#### Mixed Network (Charon + Standard Validators)

```yaml
participants:
# Distributed validator with Charon
- vc_type: charon
charon_node_count: 4
charon_params:
charon_vc: prysm
charon_vc_image: gcr.io/prysmaticlabs/prysm/validator:latest
# Standard validator
- vc_type: lighthouse
vc_image: sigp/lighthouse:latest-unstable
```

### Running Charon Networks

```bash
# Create your network_params.yaml with Charon configuration
kurtosis run --enclave charon-testnet github.com/ethpandaops/ethereum-package --args-file network_params.yaml
```

### Running Charon Networks from source code

```bash
# Create your network_params.yaml with Charon configuration
kurtosis run . --args-file network_params_charon_example.yaml
```


### Charon Architecture

When you deploy a Charon participant, the package creates:

1. **Charon Cluster**: Multiple Charon nodes that form a distributed validator cluster
2. **Validator Clients**: Each Charon node connects to a validator client of your chosen type
3. **Key Distribution**: Validator keys are split and distributed across the Charon nodes
4. **Consensus Layer**: All nodes connect to the same beacon node for chain data

```
Beacon Node
┌─────────────────────────────────────┐
│ Charon Cluster │
│ ┌─────────┐ ┌─────────┐ ┌─────────┐ │
│ │Charon-1 │ │Charon-2 │ │Charon-3 │ │
│ │ ↓ │ │ ↓ │ │ ↓ │ │
│ │ Teku VC │ │ Teku VC │ │ Teku VC │ │
│ └─────────┘ └─────────┘ └─────────┘ │
└─────────────────────────────────────┘
```

## Beacon Node <> Validator Client compatibility

| | Lighthouse VC | Prysm VC | Teku VC | Lodestar VC | Nimbus VC
|---------------|---------------|----------|---------|-------------|-----------|
| Lighthouse BN | ✅ | ✅ | ✅ | ✅ | ✅
| Prysm BN | ✅ | ✅ | ✅ | ✅ | ✅
| Teku BN | ✅ | ✅ | ✅ | ✅ | ✅
| Lodestar BN | ✅ | ✅ | ✅ | ✅ | ✅
| Nimbus BN | ✅ | ✅ | ✅ | ✅ | ✅
| Grandine BN | ✅ | ✅ | ✅ | ✅ | ✅
| | Lighthouse VC | Prysm VC | Teku VC | Lodestar VC | Nimbus VC | Charon DVT |
|---------------|---------------|----------|---------|-------------|-----------|------------|
| Lighthouse BN | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ |
| Prysm BN | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ |
| Teku BN | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ |
| Lodestar BN | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ |
| Nimbus BN | ✅ | ✅ | ✅ | ✅ | ✅ | ✅ |
| Grandine BN | ✅ | ✅ | ✅ | ✅ | ✅ | |

**Note**: Charon DVT (Distributed Validator Technology) is compatible with all beacon node clients and can run any of the supported validator clients (Lighthouse, Lodestar, Teku, Nimbus, Prysm) in a distributed configuration.

## Custom labels for Docker and Kubernetes

Expand Down
2 changes: 1 addition & 1 deletion kurtosis.yml
Original file line number Diff line number Diff line change
@@ -1 +1 @@
name: "github.com/ethpandaops/ethereum-package"
name: "github.com/ObolNetwork/ethereum-package"
5 changes: 5 additions & 0 deletions main.star
Original file line number Diff line number Diff line change
Expand Up @@ -530,6 +530,7 @@ def run(plan, args={}):
network_id,
osaka_time,
shadowfork_block_height,
charon_metrics_jobs,
) = participant_network.launch_participant_network(
plan,
args_with_right_defaults,
Expand All @@ -549,6 +550,10 @@ def run(plan, args={}):
detected_backend,
)

# Charon clusters expose extra per-node/per-VC metrics endpoints that aren't
# captured by the single vc_context per participant; register them directly.
prometheus_additional_metrics_jobs.extend(charon_metrics_jobs)

for p in all_participants:
if p.el_context != None:
plan.print(
Expand Down
168 changes: 168 additions & 0 deletions network_params_charon_example.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,168 @@
participants:
# EL
- el_type: geth
el_image: ethereum/client-go:latest
# CL
cl_type: lighthouse
cl_image: sigp/lighthouse:latest-unstable
supernode: false
use_separate_vc: true
# Validator
vc_type: charon
vc_image: obolnetwork/charon:latest
charon_node_count: 4
charon_params:
charon_vc: teku
charon_vc_image: consensys/teku:latest
validator_count: null
use_remote_signer: false
- el_type: geth
el_image: ethereum/client-go:latest
# CL
cl_type: lighthouse
cl_image: sigp/lighthouse:latest-unstable
supernode: false
use_separate_vc: true
# Validator
vc_type: lighthouse
vc_image: sigp/lighthouse:latest-unstable
use_remote_signer: false
- el_type: geth
el_image: ethereum/client-go:latest
# CL
cl_type: lighthouse
cl_image: sigp/lighthouse:latest-unstable
supernode: false
use_separate_vc: true
# Validator
vc_type: lighthouse
vc_image: sigp/lighthouse:latest-unstable
use_remote_signer: false
network_params:
network: kurtosis
network_id: "3151908"
deposit_contract_address: "0x00000000219ab540356cBB839Cbe05303d7705Fa"
seconds_per_slot: 12
num_validator_keys_per_node: 64
preregistered_validator_keys_mnemonic:
"giant issue aisle success illegal bike spike
question tent bar rely arctic volcano long crawl hungry vocal artwork sniff fantasy
very lucky have athlete"
preregistered_validator_count: 0
genesis_delay: 20
genesis_gaslimit: 30000000
max_per_epoch_activation_churn_limit: 8
churn_limit_quotient: 65536
ejection_balance: 16000000000
eth1_follow_distance: 2048
min_validator_withdrawability_delay: 256
shard_committee_period: 256
deneb_fork_epoch: 0
electra_fork_epoch: 0
fulu_fork_epoch: 18446744073709551615
network_sync_base_url: https://snapshots.ethpandaops.io/
force_snapshot_sync: false
samples_per_slot: 8
custody_requirement: 4
max_blobs_per_block_electra: 9
target_blobs_per_block_electra: 6
base_fee_update_fraction_electra: 5007716
additional_preloaded_contracts: {}
devnet_repo: ethpandaops
prefunded_accounts: {}
additional_services: []
dora_params:
image: ""
tx_fuzz_params:
tx_fuzz_extra_args: []
spamoor_params:
min_cpu: 100
max_cpu: 1000
min_mem: 20
max_mem: 300
extra_args: []
prometheus_params:
storage_tsdb_retention_time: "1d"
storage_tsdb_retention_size: "512MB"
min_cpu: 10
max_cpu: 1000
min_mem: 128
max_mem: 2048
grafana_params:
additional_dashboards: []
min_cpu: 10
max_cpu: 1000
min_mem: 128
max_mem: 2048
assertoor_params:
image: ""
run_stability_check: false
run_block_proposal_check: false
run_transaction_test: false
run_blob_transaction_test: false
run_opcodes_transaction_test: false
run_lifecycle_test: false
tests: []
wait_for_finalization: false
global_log_level: info
snooper_enabled: false
ethereum_metrics_exporter_enabled: false
parallel_keystore_generation: false
disable_peer_scoring: false
persistent: false
mev_type: null
mev_params:
mev_relay_image: ethpandaops/mev-boost-relay:main
mev_builder_image: ethpandaops/flashbots-builder:main
mev_builder_cl_image: sigp/lighthouse:latest
mev_boost_image: ethpandaops/mev-boost:develop
mev_boost_args: ["mev-boost", "--relay-check"]
mev_relay_api_extra_args: []
mev_relay_housekeeper_extra_args: []
mev_relay_website_extra_args: []
mev_builder_extra_args: []
mev_builder_prometheus_config:
scrape_interval: 15s
labels: {}
custom_flood_params:
interval_between_transactions: 1
xatu_sentry_enabled: false
xatu_sentry_params:
xatu_sentry_image: ethpandaops/xatu-sentry
xatu_server_addr: localhost:8000
xatu_server_tls: false
xatu_server_headers: {}
beacon_subscriptions:
- attestation
- block
- chain_reorg
- finalized_checkpoint
- head
- voluntary_exit
- contribution_and_proof
- blob_sidecar
apache_port: 40000
global_tolerations: []
global_node_selectors: {}
keymanager_enabled: false
checkpoint_sync_enabled: false
checkpoint_sync_url: ""
ethereum_genesis_generator_params:
image: ethpandaops/ethereum-genesis-generator:4.0.4
port_publisher:
nat_exit_ip: KURTOSIS_IP_ADDR_PLACEHOLDER
el:
enabled: false
public_port_start: 32000
cl:
enabled: false
public_port_start: 33000
vc:
enabled: false
public_port_start: 34000
remote_signer:
enabled: false
public_port_start: 35000
additional_services:
enabled: false
public_port_start: 36000
Comment on lines +1 to +183

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This seems to be the same as :

Suggested change
participants:
# EL
- el_type: geth
el_image: ethereum/client-go:latest
# CL
cl_type: lighthouse
cl_image: sigp/lighthouse:latest-unstable
supernode: false
use_separate_vc: true
# Validator
vc_type: charon
vc_image: obolnetwork/charon:latest
charon_node_count: 4
charon_params:
charon_vc: teku
charon_vc_image: consensys/teku:latest
validator_count: null
use_remote_signer: false
- el_type: geth
el_image: ethereum/client-go:latest
# CL
cl_type: lighthouse
cl_image: sigp/lighthouse:latest-unstable
supernode: false
use_separate_vc: true
# Validator
vc_type: lighthouse
vc_image: sigp/lighthouse:latest-unstable
use_remote_signer: false
- el_type: geth
el_image: ethereum/client-go:latest
# CL
cl_type: lighthouse
cl_image: sigp/lighthouse:latest-unstable
supernode: false
use_separate_vc: true
# Validator
vc_type: lighthouse
vc_image: sigp/lighthouse:latest-unstable
use_remote_signer: false
network_params:
network: kurtosis
network_id: "3151908"
deposit_contract_address: "0x00000000219ab540356cBB839Cbe05303d7705Fa"
seconds_per_slot: 12
num_validator_keys_per_node: 64
preregistered_validator_keys_mnemonic:
"giant issue aisle success illegal bike spike
question tent bar rely arctic volcano long crawl hungry vocal artwork sniff fantasy
very lucky have athlete"
preregistered_validator_count: 0
genesis_delay: 20
genesis_gaslimit: 30000000
max_per_epoch_activation_churn_limit: 8
churn_limit_quotient: 65536
ejection_balance: 16000000000
eth1_follow_distance: 2048
min_validator_withdrawability_delay: 256
shard_committee_period: 256
deneb_fork_epoch: 0
electra_fork_epoch: 0
fulu_fork_epoch: 18446744073709551615
network_sync_base_url: https://snapshots.ethpandaops.io/
force_snapshot_sync: false
samples_per_slot: 8
custody_requirement: 4
max_blobs_per_block_electra: 9
target_blobs_per_block_electra: 6
base_fee_update_fraction_electra: 5007716
additional_preloaded_contracts: {}
devnet_repo: ethpandaops
prefunded_accounts: {}
additional_services: []
dora_params:
image: ""
tx_fuzz_params:
tx_fuzz_extra_args: []
spamoor_params:
min_cpu: 100
max_cpu: 1000
min_mem: 20
max_mem: 300
extra_args: []
prometheus_params:
storage_tsdb_retention_time: "1d"
storage_tsdb_retention_size: "512MB"
min_cpu: 10
max_cpu: 1000
min_mem: 128
max_mem: 2048
grafana_params:
additional_dashboards: []
min_cpu: 10
max_cpu: 1000
min_mem: 128
max_mem: 2048
assertoor_params:
image: ""
run_stability_check: false
run_block_proposal_check: false
run_transaction_test: false
run_blob_transaction_test: false
run_opcodes_transaction_test: false
run_lifecycle_test: false
tests: []
wait_for_finalization: false
global_log_level: info
snooper_enabled: false
ethereum_metrics_exporter_enabled: false
parallel_keystore_generation: false
disable_peer_scoring: false
persistent: false
mev_type: null
mev_params:
mev_relay_image: ethpandaops/mev-boost-relay:main
mev_builder_image: ethpandaops/flashbots-builder:main
mev_builder_cl_image: sigp/lighthouse:latest
mev_boost_image: ethpandaops/mev-boost:develop
mev_boost_args: ["mev-boost", "--relay-check"]
mev_relay_api_extra_args: []
mev_relay_housekeeper_extra_args: []
mev_relay_website_extra_args: []
mev_builder_extra_args: []
mev_builder_prometheus_config:
scrape_interval: 15s
labels: {}
custom_flood_params:
interval_between_transactions: 1
xatu_sentry_enabled: false
xatu_sentry_params:
xatu_sentry_image: ethpandaops/xatu-sentry
xatu_server_addr: localhost:8000
xatu_server_tls: false
xatu_server_headers: {}
beacon_subscriptions:
- attestation
- block
- chain_reorg
- finalized_checkpoint
- head
- voluntary_exit
- contribution_and_proof
- blob_sidecar
apache_port: 40000
global_tolerations: []
global_node_selectors: {}
keymanager_enabled: false
checkpoint_sync_enabled: false
checkpoint_sync_url: ""
ethereum_genesis_generator_params:
image: ethpandaops/ethereum-genesis-generator:4.0.4
port_publisher:
nat_exit_ip: KURTOSIS_IP_ADDR_PLACEHOLDER
el:
enabled: false
public_port_start: 32000
cl:
enabled: false
public_port_start: 33000
vc:
enabled: false
public_port_start: 34000
remote_signer:
enabled: false
public_port_start: 35000
additional_services:
enabled: false
public_port_start: 36000
participants:
- el_type: geth
cl_type: lighthouse
vc_type: charon
vc_image: obolnetwork/charon:latest
charon_node_count: 4
charon_params:
charon_vc: teku
charon_vc_image: consensys/teku:latest
validator_count: null
use_remote_signer: false
- el_type: geth
cl_type: lighthouse
count: 2

3 changes: 3 additions & 0 deletions src/package_io/constants.star
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,8 @@ VC_TYPE = struct(
vero="vero",
grandine="grandine",
consensoor="consensoor",
charon="charon",
vouch="vouch",
)

REMOTE_SIGNER_TYPE = struct(web3signer="web3signer")
Expand Down Expand Up @@ -72,6 +74,7 @@ LITTLE_BIGTABLE_PORT_ID = "littlebigtable"
VALIDATOR_GRPC_PORT_ID = "grpc"

VALIDATING_REWARDS_ACCOUNT = "0x8943545177806ED17B9F23F0a21ee5948eCaa776"
CHARON_WITHDRAWAL_ADDRESS = "0xBc7c960C1097ef1Af0FD32407701465f3c03e407"
MAX_ENR_ENTRIES = 20
MAX_ENODE_ENTRIES = 20
MIN_PEERS = 0
Expand Down
Loading