Skip to content
4 changes: 2 additions & 2 deletions charts/charon-cluster/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
Charon Cluster
===========

![Version: 0.3.10](https://img.shields.io/badge/Version-0.3.10-informational?style=flat-square) ![Type: application](https://img.shields.io/badge/Type-application-informational?style=flat-square) ![AppVersion: 1.7.1](https://img.shields.io/badge/AppVersion-1.7.1-informational?style=flat-square)
![Version: 0.3.12](https://img.shields.io/badge/Version-0.3.12-informational?style=flat-square) ![Type: application](https://img.shields.io/badge/Type-application-informational?style=flat-square) ![AppVersion: 1.8.1](https://img.shields.io/badge/AppVersion-1.8.1-informational?style=flat-square)

Charon is an open-source Ethereum Distributed validator middleware written in golang. This chart deploys a full Charon cluster.

Expand Down Expand Up @@ -52,7 +52,7 @@ Charon is an open-source Ethereum Distributed validator middleware written in go
| config.validatorApiAddress | string | `"0.0.0.0:3600"` | Listening address (ip and port) for validator-facing traffic proxying the beacon-node API. (default "127.0.0.1:3600") |
| containerSecurityContext | object | See `values.yaml` | The security context for containers |
| fullnameOverride | string | `""` | Provide a name to substitute for the full names of resources |
| image | object | `{"pullPolicy":"IfNotPresent","repository":"obolnetwork/charon","tag":"v1.7.1"}` | Charon image repository, pull policy, and tag version |
| image | object | `{"pullPolicy":"IfNotPresent","repository":"obolnetwork/charon","tag":"v1.8.1"}` | Charon image repository, pull policy, and tag version |
| imagePullSecrets | list | `[]` | Credentials to fetch images from private registry # ref: https://kubernetes.io/docs/tasks/configure-pod-container/pull-image-private-registry/ |
| livenessProbe | object | `{"enabled":false,"httpGet":{"path":"/livez"},"initialDelaySeconds":10,"periodSeconds":5}` | Configure liveness probes # ref: https://kubernetes.io/docs/tasks/configure-pod-container/configure-liveness-readiness-startup-probes/ |
| nameOverride | string | `""` | Provide a name in place of lighthouse for `app:` labels |
Expand Down
4 changes: 2 additions & 2 deletions charts/charon/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
Charon
===========

![Version: 0.4.10](https://img.shields.io/badge/Version-0.4.10-informational?style=flat-square) ![Type: application](https://img.shields.io/badge/Type-application-informational?style=flat-square) ![AppVersion: 1.7.1](https://img.shields.io/badge/AppVersion-1.7.1-informational?style=flat-square)
![Version: 0.4.12](https://img.shields.io/badge/Version-0.4.12-informational?style=flat-square) ![Type: application](https://img.shields.io/badge/Type-application-informational?style=flat-square) ![AppVersion: 1.8.1](https://img.shields.io/badge/AppVersion-1.8.1-informational?style=flat-square)

Charon is an open-source Ethereum Distributed validator middleware written in golang.

Expand Down Expand Up @@ -56,7 +56,7 @@ Charon is an open-source Ethereum Distributed validator middleware written in go
| extraVolumes | list | `[]` | Additional volumes |
| fullnameOverride | string | `""` | Provide a name to substitute for the full names of resources |
| httpPort | int | `3600` | HTTP Port |
| image | object | `{"pullPolicy":"IfNotPresent","repository":"obolnetwork/charon","tag":"v1.7.1"}` | Charon image repository, pull policy, and tag version |
| image | object | `{"pullPolicy":"IfNotPresent","repository":"obolnetwork/charon","tag":"v1.8.1"}` | Charon image repository, pull policy, and tag version |
| imagePullSecrets | list | `[]` | Credentials to fetch images from private registry # ref: https://kubernetes.io/docs/tasks/configure-pod-container/pull-image-private-registry/ |
| initContainers | list | `[]` | Additional init containers |
| jaegerPort | int | `6831` | Jaeger Port |
Expand Down
83 changes: 73 additions & 10 deletions charts/dv-pod/QUICKSTART.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ Each operator deploys their node:
```bash
helm upgrade --install my-dv-pod obol/dv-pod \
--set charon.operatorAddress=0xYOUR_OPERATOR_ADDRESS \
--set chainId=1 \
--set network=mainnet \
--namespace=dv-pod \
--timeout=10m --create-namespace
```
Expand Down Expand Up @@ -122,7 +122,7 @@ Expected output: `["charon-enr-private-key", "enr"]`
helm upgrade --install my-dv-pod obol/dv-pod \
--set charon.operatorAddress=0xYOUR_OPERATOR_ADDRESS \
--set charon.dkgSidecar.targetConfigHash=0xYOUR_CONFIG_HASH \
--set chainId=1 \
--set network=mainnet \
--set 'charon.beaconNodeEndpoints[0]=http://YOUR_BEACON_NODE:5052' \
--set charon.enr.existingSecret.name=charon-enr-private-key \
--namespace=dv-pod \
Expand Down Expand Up @@ -156,16 +156,13 @@ kubectl exec -n dv-pod my-dv-pod-dv-pod-0 -- ls -la /charon-data/cluster-lock.js

```bash
# Mainnet (default)
--set chainId=1
--set network=mainnet

# Sepolia testnet
--set chainId=11155111
--set network=sepolia

# Hoodi testnet
--set chainId=560048

# Gnosis Chain
--set chainId=100
--set network=hoodi
```

### Custom DKG Sidecar Image
Expand Down Expand Up @@ -198,8 +195,7 @@ kubectl exec -n dv-pod my-dv-pod-dv-pod-0 -- ls -la /charon-data/cluster-lock.js
--set validatorClient.type=teku

# Prysm
--set validatorClient.type=prysm \
--set validatorClient.config.prysm.acceptTermsOfUse=true
--set validatorClient.type=prysm

# Lodestar
--set validatorClient.type=lodestar
Expand Down Expand Up @@ -293,6 +289,73 @@ kubectl port-forward -n dv-pod my-dv-pod-dv-pod-0 3620:3620

---

## Challenge & Testing Environments

For testing, development, or challenge environments, you may need to override the default API endpoint or use a specific DKG sidecar version.

### Override API Endpoint

To point to a different Obol API (e.g., dev, staging, or local):

```bash
# Using development API
helm upgrade --install my-dv-pod charts/dv-pod/ \
--set charon.operatorAddress=0xYOUR_OPERATOR_ADDRESS \
--set charon.dkgSidecar.apiEndpoint=https://obol-api-nonprod-dev.dev.obol.tech \
--set network=hoodi \
--namespace=dv-pod \
--timeout=10m --create-namespace

# Using local API for development
helm upgrade --install my-dv-pod charts/dv-pod/ \
--set charon.operatorAddress=0xYOUR_OPERATOR_ADDRESS \
--set charon.dkgSidecar.apiEndpoint=http://localhost:3000 \
--set network=hoodi \
--namespace=dv-pod \
--timeout=10m --create-namespace
```

### Use Specific DKG Sidecar Commit

To test with a specific DKG sidecar commit or branch:

```bash
# Using a specific commit SHA
helm upgrade --install my-dv-pod charts/dv-pod/ \
--set charon.operatorAddress=0xYOUR_OPERATOR_ADDRESS \
--set charon.dkgSidecar.image.tag=90a1656 \
--set charon.dkgSidecar.image.pullPolicy=Always \
--set network=hoodi \
--namespace=dv-pod \
--timeout=10m --create-namespace

### Complete Challenge Example

Full example combining custom API endpoint, specific DKG sidecar commit, and hoodi testnet:

```bash
helm upgrade --install challenge-dv-pod charts/dv-pod/ \
--set charon.operatorAddress=0xYOUR_OPERATOR_ADDRESS \
--set network=hoodi \
--set 'charon.fallbackBeaconNodeEndpoints[0]=https://ethereum-hoodi-beacon-api.publicnode.com' \
--set charon.dkgSidecar.apiEndpoint=https://obol-api-nonprod-dev.dev.obol.tech \
--set charon.dkgSidecar.image.tag=90a1656 \
--set charon.dkgSidecar.image.pullPolicy=Always \
--set validatorClient.type=prysm \
--set centralMonitoring.enabled=true \
--set-string centralMonitoring.token='YOUR_MONITORING_TOKEN' \
--namespace=dv-pod \
--timeout=10m --create-namespace
```

**Key Parameters for Challenges:**
- `network=hoodi` - Use Hoodi testnet for testing
- `charon.dkgSidecar.apiEndpoint` - Point to dev/staging API
- `charon.dkgSidecar.image.tag` - Specific commit SHA or branch name
- `charon.dkgSidecar.image.pullPolicy=Always` - Force pull latest image

---

## Next Steps

After successful DKG:
Expand Down
24 changes: 12 additions & 12 deletions charts/dv-pod/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,7 @@ kubectl create secret generic validator-keys \
kubectl create configmap cluster-lock --from-file=cluster/node0/cluster-lock.json

# Install the chart, referencing your ConfigMap and Secrets
helm install my-dv-pod obol/dv-pod \
helm upgrade --install my-dv-pod obol/dv-pod \
--set configMaps.clusterLock=cluster-lock \
--set validatorClient.keystores.secretName=validator-keys
```
Expand Down Expand Up @@ -104,7 +104,7 @@ kubectl create configmap cluster-lock \
--from-file=.charon/cluster-lock.json

# Install the chart
helm install my-dv-pod obol/dv-pod \
helm upgrade --install my-dv-pod obol/dv-pod \
--set configMaps.clusterLock=cluster-lock \
--set validatorClient.keystores.secretName=validator-keys
```
Expand All @@ -121,7 +121,7 @@ If you don't have pre-existing artifacts, the chart can automatically:

Simply deploy the chart with your operator address:
```sh
helm install my-dv-pod obol/dv-pod \
helm upgrade --install my-dv-pod obol/dv-pod \
--set charon.operatorAddress=0xYOUR_OPERATOR_ADDRESS
```

Expand Down Expand Up @@ -170,13 +170,13 @@ validatorClient:
- --suggested-fee-recipient=0xYOUR_FEE_RECIPIENT_ADDRESS
```

With a `helm install` command for pre-existing artifacts.
With a `helm upgrade --install` command for pre-existing artifacts.

```sh
helm install my-dv-pod obol/dv-pod \
helm upgrade --install my-dv-pod obol/dv-pod \
--set configMaps.clusterLock=cluster-lock \
--set validatorClient.keystores.secretName=validator-keys \
--set validatorClient.type=prysm --set validatorClient.config.prysm.acceptTermsOfUse=true
--set validatorClient.type=prysm
```

> [!NOTE]
Expand All @@ -199,7 +199,7 @@ kubectl create secret generic validator-keys \
--from-file=keystore-1.txt

# Deploy the chart with the keystore secret
helm install my-dv-pod obol/dv-pod \
helm upgrade --install my-dv-pod obol/dv-pod \
--set validatorClient.keystores.secretName=validator-keys \
--set configMaps.clusterLock=my-cluster-lock
```
Expand Down Expand Up @@ -227,11 +227,11 @@ The ENR (Ethereum Node Record) secret **MUST** be created in the same namespace
```bash
# Wrong approach - secret and chart in different namespaces
kubectl create secret generic charon-enr-private-key -n dv-pod --from-literal=...
helm install my-dv-pod obol/dv-pod # Installs in default namespace - ENR will be regenerated!
helm upgrade --install my-dv-pod obol/dv-pod # Installs in default namespace - ENR will be regenerated!

# Correct approach - both in same namespace
kubectl create secret generic charon-enr-private-key -n dv-pod --from-literal=...
helm install my-dv-pod obol/dv-pod -n dv-pod # Both in dv-pod namespace
helm upgrade --install my-dv-pod obol/dv-pod -n dv-pod # Both in dv-pod namespace
```

## Advanced Usage
Expand Down Expand Up @@ -278,7 +278,7 @@ In this case, you have two options:

2. Install the chart with the lockHash value:
```sh
helm install my-dv-pod obol/dv-pod \
helm upgrade --install my-dv-pod obol/dv-pod \
--set charon.lockHash=$LOCK_HASH \
--set charon.operatorAddress=<YOUR_OPERATOR_ADDRESS>
```
Expand All @@ -294,7 +294,7 @@ In this case, you have two options:

2. Install the chart referencing the ConfigMap:
```sh
helm install my-dv-pod obol/dv-pod \
helm upgrade --install my-dv-pod obol/dv-pod \
--set configMaps.lockHash=cluster-lock-hash \
--set charon.operatorAddress=<YOUR_OPERATOR_ADDRESS>
```
Expand Down Expand Up @@ -346,7 +346,7 @@ The command removes all the Kubernetes components associated with the chart and
| charon.enr.privateKey | string | `""` | Provide the ENR private key directly (hex format, e.g., 0x...). If set, 'generate' and 'existingSecret' are ignored. |
| charon.enrJob.enabled | bool | `true` | Enable or disable the Kubernetes Job that generates/manages the ENR. Note: This is typically not needed as the job automatically detects existing secrets. The job will check if the ENR secret already exists and skip generation if found. Only set to false for advanced use cases where you need to completely disable the job. |
| charon.executionClientRpcEndpoint | string | `""` | Optional: Execution client RPC endpoint URL (e.g., your Ethereum execution client) Note: Charon currently only supports a single execution endpoint This is only needed if an operator in the cluster uses a smart contract wallet for an operator signature. If that does not apply to this cluster, this field can be left unset. |
| charon.fallbackBeaconNodeEndpoints | list | `["https://ethereum-beacon-api.publicnode.com"]` | Fallback beacon node endpoints (optional) These will be used if the primary beaconNodeEndpoints are unavailable |
| charon.fallbackBeaconNodeEndpoints | list | `["https://ethereum-beacon-api.publicnode.com"]` | Fallback beacon node endpoints (optional) These will be used if the primary beaconNodeEndpoints are unavailable If not specified, intelligent defaults based on network will be used: - mainnet: https://ethereum-beacon-api.publicnode.com - sepolia: https://ethereum-sepolia-beacon-api.publicnode.com - hoodi: https://ethereum-hoodi-beacon-api.publicnode.com |
| charon.featureSet | string | `"stable"` | Minimum feature set to enable by default: alpha, beta, or stable. Warning: modify at own risk. (default "stable") |
| charon.featureSetDisable | string | `""` | Comma-separated list of features to disable, overriding the default minimum feature set. |
| charon.featureSetEnable | string | `""` | Comma-separated list of features to enable, overriding the default minimum feature set. |
Expand Down
22 changes: 11 additions & 11 deletions charts/dv-pod/README.md.gotmpl
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@ kubectl create secret generic validator-keys \
kubectl create configmap cluster-lock --from-file=cluster/node0/cluster-lock.json

# Install the chart, referencing your ConfigMap and Secrets
helm install my-dv-pod obol/dv-pod \
helm upgrade --install my-dv-pod obol/dv-pod \
--set configMaps.clusterLock=cluster-lock \
--set validatorClient.keystores.secretName=validator-keys
```
Expand Down Expand Up @@ -105,7 +105,7 @@ kubectl create configmap cluster-lock \
--from-file=.charon/cluster-lock.json

# Install the chart
helm install my-dv-pod obol/dv-pod \
helm upgrade --install my-dv-pod obol/dv-pod \
--set configMaps.clusterLock=cluster-lock \
--set validatorClient.keystores.secretName=validator-keys
```
Expand All @@ -123,7 +123,7 @@ If you don't have pre-existing artifacts, the chart can automatically:

Simply deploy the chart with your operator address:
```sh
helm install my-dv-pod obol/dv-pod \
helm upgrade --install my-dv-pod obol/dv-pod \
--set charon.operatorAddress=0xYOUR_OPERATOR_ADDRESS
```

Expand Down Expand Up @@ -172,13 +172,13 @@ validatorClient:
- --suggested-fee-recipient=0xYOUR_FEE_RECIPIENT_ADDRESS
```

With a `helm install` command for pre-existing artifacts.
With a `helm upgrade --install` command for pre-existing artifacts.

```sh
helm install my-dv-pod obol/dv-pod \
helm upgrade --install my-dv-pod obol/dv-pod \
--set configMaps.clusterLock=cluster-lock \
--set validatorClient.keystores.secretName=validator-keys \
--set validatorClient.type=prysm --set validatorClient.config.prysm.acceptTermsOfUse=true
--set validatorClient.type=prysm
```

> [!NOTE]
Expand All @@ -201,7 +201,7 @@ kubectl create secret generic validator-keys \
--from-file=keystore-1.txt

# Deploy the chart with the keystore secret
helm install my-dv-pod obol/dv-pod \
helm upgrade --install my-dv-pod obol/dv-pod \
--set validatorClient.keystores.secretName=validator-keys \
--set configMaps.clusterLock=my-cluster-lock
```
Expand Down Expand Up @@ -229,11 +229,11 @@ The ENR (Ethereum Node Record) secret **MUST** be created in the same namespace
```bash
# Wrong approach - secret and chart in different namespaces
kubectl create secret generic charon-enr-private-key -n dv-pod --from-literal=...
helm install my-dv-pod obol/dv-pod # Installs in default namespace - ENR will be regenerated!
helm upgrade --install my-dv-pod obol/dv-pod # Installs in default namespace - ENR will be regenerated!

# Correct approach - both in same namespace
kubectl create secret generic charon-enr-private-key -n dv-pod --from-literal=...
helm install my-dv-pod obol/dv-pod -n dv-pod # Both in dv-pod namespace
helm upgrade --install my-dv-pod obol/dv-pod -n dv-pod # Both in dv-pod namespace
```

## Advanced Usage
Expand Down Expand Up @@ -280,7 +280,7 @@ In this case, you have two options:

2. Install the chart with the lockHash value:
```sh
helm install my-dv-pod obol/dv-pod \
helm upgrade --install my-dv-pod obol/dv-pod \
--set charon.lockHash=$LOCK_HASH \
--set charon.operatorAddress=<YOUR_OPERATOR_ADDRESS>
```
Expand All @@ -296,7 +296,7 @@ In this case, you have two options:

2. Install the chart referencing the ConfigMap:
```sh
helm install my-dv-pod obol/dv-pod \
helm upgrade --install my-dv-pod obol/dv-pod \
--set configMaps.lockHash=cluster-lock-hash \
--set charon.operatorAddress=<YOUR_OPERATOR_ADDRESS>
```
Expand Down
42 changes: 41 additions & 1 deletion charts/dv-pod/templates/_helpers.tpl
Original file line number Diff line number Diff line change
Expand Up @@ -141,10 +141,20 @@ Create comma-separated list of primary beacon node endpoints

{{/*
Create comma-separated list of fallback beacon node endpoints
Returns user-specified endpoints or intelligent defaults based on network
*/}}
{{- define "dv-pod.fallbackBeaconNodeEndpoints" -}}
{{- if .Values.charon.fallbackBeaconNodeEndpoints -}}
{{- join "," .Values.charon.fallbackBeaconNodeEndpoints -}}
{{- else -}}
{{- $network := .Values.network -}}
{{- if eq $network "mainnet" -}}
https://ethereum-beacon-api.publicnode.com
{{- else if eq $network "sepolia" -}}
https://ethereum-sepolia-beacon-api.publicnode.com
{{- else if eq $network "hoodi" -}}
https://ethereum-hoodi-beacon-api.publicnode.com
{{- end -}}
{{- end -}}
{{- end -}}

Expand All @@ -156,7 +166,37 @@ Validate validator client type
{{- $validTypes := list "lighthouse" "lodestar" "teku" "prysm" "nimbus" -}}
{{- $currentType := .Values.validatorClient.type -}}
{{- if not (has $currentType $validTypes) -}}
{{- fail (printf "ERROR: Invalid validator client type '%s'. Valid options are: %s" $currentType (join ", " $validTypes)) -}}
{{- $errorMsg := printf "\n\nERROR: Invalid validator client type '%s'.\n\nValid options: %s" $currentType (join ", " $validTypes) -}}
{{- /* Try to find the closest match using proximity detection */ -}}
{{- $currentLower := lower $currentType -}}
{{- $ctx := dict "suggestion" "" -}}
{{- range $validType := $validTypes -}}
{{- $validLower := lower $validType -}}
{{- /* Check if they share at least 3 character prefix */ -}}
{{- $minLen := min (len $currentLower) (len $validLower) -}}
{{- if ge $minLen 3 -}}
{{- $inputPrefix := substr 0 3 $currentLower -}}
{{- $validPrefix := substr 0 3 $validLower -}}
{{- if eq $inputPrefix $validPrefix -}}
{{- $_ := set $ctx "suggestion" $validType -}}
{{- end -}}
{{- end -}}
{{- /* Check if one contains the other */ -}}
{{- if or (contains $currentLower $validLower) (contains $validLower $currentLower) -}}
{{- $_ := set $ctx "suggestion" $validType -}}
{{- end -}}
{{- end -}}
{{- /* Add suggestion to error message if found */ -}}
{{- if $ctx.suggestion -}}
{{- $errorMsg = printf "%s\n\n⚠️ Did you mean '%s'?" $errorMsg $ctx.suggestion -}}
{{- end -}}
{{- /* Use suggestion if available, otherwise use lodestar as example */ -}}
{{- $exampleType := "lodestar" -}}
{{- if $ctx.suggestion -}}
{{- $exampleType = $ctx.suggestion -}}
{{- end -}}
{{- $errorMsg = printf "%s\n\nHow to fix this:\n • Using --set flag:\n --set validatorClient.type=%s\n\n • In your values.yaml file:\n validatorClient:\n type: %s\n\n • Using custom values file:\n helm install my-dv-pod obol/dv-pod -f myvalues.yaml\n\nFor more information, see the Validator Client section in charts/dv-pod/README.md\n" $errorMsg $exampleType $exampleType -}}
{{- fail $errorMsg -}}
{{- end -}}
{{- end -}}
{{- end -}}
Expand Down
Loading