├── grafana
├── grafana.ini
├── dashboards.yml
├── datasource.yml
└── dashboards
│ ├── simnet_dash.json
│ └── local_cluster_dash.json
├── jwt
└── jwt.hex
├── relay
└── sample
├── .charon
└── sample
├── DVCluster.png
├── example-infura-details.png
├── vouch
├── Dockerfile
├── vouch.yml
└── run.sh
├── nimbus
├── Dockerfile
└── run.sh
├── .gitignore
├── teku
└── teku-config.yaml
├── .github
├── workflows
│ ├── label-issues.yml
│ ├── add_issue_to_project.yml
│ └── dispath-update.yml
├── renovate.json
└── ISSUE_TEMPLATE
│ ├── bug_report.md
│ └── feature_ticket.md
├── lighthouse
└── run.sh
├── prometheus
└── prometheus.yml
├── README.md
├── .env.sample
├── docker-compose.override.yml.sample
└── docker-compose.yml
/grafana/grafana.ini:
--------------------------------------------------------------------------------
1 | [auth.anonymous]
2 | enabled = true
3 | org_role = Admin
--------------------------------------------------------------------------------
/jwt/jwt.hex:
--------------------------------------------------------------------------------
1 | 7074a5bf6bd6dae368fa598249d57edfcbccc67a1205b2c8d5d2fe7b800663aa
--------------------------------------------------------------------------------
/relay/sample:
--------------------------------------------------------------------------------
1 | This is a placeholder file to get relay directory included in git.
--------------------------------------------------------------------------------
/.charon/sample:
--------------------------------------------------------------------------------
1 | This is a placeholder file to get .charon directory included in git.
--------------------------------------------------------------------------------
/DVCluster.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ObolNetwork/charon-distributed-validator-cluster/HEAD/DVCluster.png
--------------------------------------------------------------------------------
/example-infura-details.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ObolNetwork/charon-distributed-validator-cluster/HEAD/example-infura-details.png
--------------------------------------------------------------------------------
/grafana/dashboards.yml:
--------------------------------------------------------------------------------
1 | apiVersion: 1
2 |
3 | providers:
4 | - name: dashboards
5 | type: file
6 | updateIntervalSeconds: 30
7 | options:
8 | path: /etc/dashboards
9 |
--------------------------------------------------------------------------------
/vouch/Dockerfile:
--------------------------------------------------------------------------------
1 | FROM wealdtech/ethdo:1.35.2 as ethdo
2 |
3 | FROM attestant/vouch:1.8.0
4 |
5 | COPY --from=ethdo /app/ethdo /app/ethdo
6 |
7 | RUN apt-get update && apt-get install -y curl jq wget
8 |
9 | ENTRYPOINT ["/opt/vouch/run.sh"]
--------------------------------------------------------------------------------
/nimbus/Dockerfile:
--------------------------------------------------------------------------------
1 | FROM statusim/nimbus-eth2:multiarch-v25.9.2 as nimbusbn
2 |
3 | FROM statusim/nimbus-validator-client:multiarch-v25.9.2
4 |
5 | COPY --from=nimbusbn /home/user/nimbus_beacon_node /home/user/nimbus_beacon_node
6 |
7 | ENTRYPOINT ["/home/user/data/run.sh"]
8 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | charon.yml
2 | charon
3 | .charon/cluster/
4 | manifest.json
5 | cluster_definition.json
6 | cluster_lock.json
7 | p2pkey
8 | keystore*
9 | prater
10 | .env
11 | .data
12 | beaconnode.env.old
13 | split_keys/
14 | relay/charon-enr-private-key
15 | .idea/
16 | data/
17 | nethermind/nethermind_db/
18 | docker-compose.override.yml
19 | nimbus/node*/
--------------------------------------------------------------------------------
/teku/teku-config.yaml:
--------------------------------------------------------------------------------
1 | metrics-enabled: true
2 | metrics-host-allowlist: "*"
3 | metrics-interface: "0.0.0.0"
4 | metrics-port: "8008"
5 | validators-keystore-locking-enabled: false
6 | network: auto
7 | validator-keys: "/opt/charon/validator_keys:/opt/charon/validator_keys"
8 | validators-proposer-default-fee-recipient: "0x0000000000000000000000000000000000000000"
9 | Xobol-dvt-integration-enabled: true
10 |
--------------------------------------------------------------------------------
/.github/workflows/label-issues.yml:
--------------------------------------------------------------------------------
1 | name: Label issues
2 | on:
3 | issues:
4 | types:
5 | - reopened
6 | - opened
7 | jobs:
8 | label_issues:
9 | runs-on: ubuntu-latest
10 | permissions:
11 | issues: write
12 | steps:
13 | - uses: actions/github-script@v8
14 | with:
15 | script: |
16 | github.rest.issues.addLabels({
17 | issue_number: context.issue.number,
18 | owner: context.repo.owner,
19 | repo: context.repo.repo,
20 | labels: ["protocol"]
21 | })
22 |
--------------------------------------------------------------------------------
/.github/renovate.json:
--------------------------------------------------------------------------------
1 | {
2 | "$schema": "https://docs.renovatebot.com/renovate-schema.json",
3 | "extends": [
4 | "config:recommended"
5 | ],
6 | "enabledManagers": [
7 | "github-actions"
8 | ],
9 | "packageRules": [
10 | {
11 | "matchManagers": [
12 | "github-actions"
13 | ],
14 | "matchDepTypes": [
15 | "github-actions"
16 | ],
17 | "matchFileNames": [
18 | ".github/workflows/**"
19 | ],
20 | "schedule": [
21 | "every weekend"
22 | ],
23 | "labels": [
24 | "renovate/github-actions"
25 | ],
26 | "groupName": "GitHub Actions updates"
27 | }
28 | ]
29 | }
30 |
--------------------------------------------------------------------------------
/.github/workflows/add_issue_to_project.yml:
--------------------------------------------------------------------------------
1 | # This is a basic workflow adding every issue in this repo to the new Project Management Board
2 | name: Add Issue To Project
3 |
4 | # Controls when the workflow will run - new issues
5 | on:
6 | issues:
7 | types:
8 | - opened
9 |
10 | # This workflow contains a single job called "build"
11 | jobs:
12 | build:
13 | runs-on: ubuntu-latest
14 | # Steps
15 | steps:
16 | - name: Add Issue To Project
17 | uses: actions/add-to-project@v1.0.2
18 | with:
19 | # URL of the project to add issues to
20 | project-url: https://github.com/orgs/ObolNetwork/projects/7
21 | # A GitHub personal access token with write access to the project, need org admin's token with repo and project permissions, need to store the token outside the script if public
22 | github-token: ${{ secrets.GH_ORG_ADMIN_SECRET }}
23 |
--------------------------------------------------------------------------------
/lighthouse/run.sh:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env bash
2 |
3 | apt-get update && apt-get install -y curl jq wget
4 |
5 | while ! curl "${LIGHTHOUSE_BEACON_NODE_ADDRESS}/eth/v1/node/health" 2>/dev/null; do
6 | echo "Waiting for ${LIGHTHOUSE_BEACON_NODE_ADDRESS} to become available..."
7 | sleep 5
8 | done
9 |
10 | # Refer: https://lighthouse-book.sigmaprime.io/advanced-datadir.html
11 | # Running a lighthouse VC involves two steps which needs to run in order:
12 | # 1. Loading the validator keys
13 | # 2. Actually running the VC
14 |
15 | for f in /opt/charon/keys/keystore-*.json; do
16 | echo "Importing key ${f}"
17 | lighthouse --network "${ETH2_NETWORK}" account validator import \
18 | --reuse-password \
19 | --keystore "${f}" \
20 | --password-file "${f//json/txt}"
21 | done
22 |
23 | echo "Starting lighthouse validator client for ${NODE}"
24 | exec lighthouse --network "${ETH2_NETWORK}" validator \
25 | --beacon-nodes ${LIGHTHOUSE_BEACON_NODE_ADDRESS} \
26 | --suggested-fee-recipient "0x0000000000000000000000000000000000000000" \
27 | --metrics \
28 | --metrics-address "0.0.0.0" \
29 | --metrics-allow-origin "*" \
30 | --metrics-port "5064" \
31 | --use-long-timeouts \
32 | --distributed
33 |
--------------------------------------------------------------------------------
/.github/ISSUE_TEMPLATE/bug_report.md:
--------------------------------------------------------------------------------
1 | ---
2 | name: "\U0001F41E Bug report"
3 | about: Report a bug or problem with running this repo
4 | labels: Bug
5 | ---
6 |
14 |
15 | # 🐞 Bug Report
16 |
17 | ### Description
18 |
19 | A clear and concise description of the problem...
20 |
21 | ## 🔬 Minimal Reproduction
22 |
23 |
26 |
27 | ## 🔥 Error
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 | ## 🌍 Your Environment
37 |
38 | **Operating System:**
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 | **What version of Charon are you running? (Which release)**
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 | **Anything else relevant (validator index / public key)?**
55 |
56 |
--------------------------------------------------------------------------------
/nimbus/run.sh:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env bash
2 |
3 | # Cleanup nimbus directories if they already exist.
4 | rm -rf /home/user/data/${NODE}
5 |
6 | # Refer: https://nimbus.guide/keys.html
7 | # Running a nimbus VC involves two steps which need to run in order:
8 | # 1. Importing the validator keys
9 | # 2. And then actually running the VC
10 | tmpkeys="/home/validator_keys/tmpkeys"
11 | mkdir -p ${tmpkeys}
12 |
13 | for f in /home/validator_keys/keystore-*.json; do
14 | echo "Importing key ${f}"
15 |
16 | # Read password from keystore-*.txt into $password variable.
17 | password=$(<"${f//json/txt}")
18 |
19 | # Copy keystore file to tmpkeys/ directory.
20 | cp "${f}" "${tmpkeys}"
21 |
22 | # Import keystore with the password.
23 | echo "$password" | \
24 | /home/user/nimbus_beacon_node deposits import \
25 | --data-dir=/home/user/data/${NODE} \
26 | /home/validator_keys/tmpkeys
27 |
28 | # Delete tmpkeys/keystore-*.json file that was copied before.
29 | filename="$(basename ${f})"
30 | rm "${tmpkeys}/${filename}"
31 | done
32 |
33 | # Delete the tmpkeys/ directory since it's no longer needed.
34 | rm -r ${tmpkeys}
35 |
36 | echo "Imported all keys"
37 |
38 | # Now run nimbus VC
39 | exec /home/user/nimbus_validator_client \
40 | --data-dir=/home/user/data/"${NODE}" \
41 | --beacon-node="http://$NODE:3600" \
42 | --doppelganger-detection=false \
43 | --metrics \
44 | --metrics-address=0.0.0.0 \
45 | --distributed
46 |
--------------------------------------------------------------------------------
/.github/ISSUE_TEMPLATE/feature_ticket.md:
--------------------------------------------------------------------------------
1 | ---
2 | name: "\U0001F680 Feature or Improvement Ticket"
3 | about: Create a new feature or suggest an improvement
4 | labels: Enhancement
5 | ---
6 |
7 | # 🎯 Problem to be solved
8 |
9 |
10 |
11 | # 🛠️ Proposed solution
12 |
13 |
14 |
15 | # 🧪 Tests
16 |
17 |
18 |
19 | - [ ] Works in local docker-compose
20 | - [ ] Has a attested on a testnet at least once
21 |
22 | # 👐 Additional acceptance criteria
23 |
24 |
25 |
26 | # ❌ Out of Scope
27 |
28 |
29 |
30 |
37 |
--------------------------------------------------------------------------------
/.github/workflows/dispath-update.yml:
--------------------------------------------------------------------------------
1 | name: Dispatch Update Version
2 |
3 | on:
4 | repository_dispatch:
5 | types: [update-version]
6 |
7 | jobs:
8 | update-version:
9 | runs-on: ubuntu-latest
10 | steps:
11 | - name: Checkout this repository
12 | uses: actions/checkout@v5
13 |
14 | - name: Extract tag name
15 | run: echo "TAG_NAME=${{ github.event.client_payload.tag }}" >> $GITHUB_ENV
16 |
17 | - name: Update version in Ansible configuration
18 | run: |
19 | TAG_NAME="$(echo "${TAG_NAME}" | sed 's/^v//')"
20 |
21 | sed -i -E "s/# Charon docker container image version, e\.g\. \`v[0-9]+\.[0-9]+\.[0-9]+[a-zA-Z0-9\-]*\`/# Charon docker container image version, e\.g\. \`v${TAG_NAME}\`/" .env.sample
22 | sed -i -E 's|(image: obolnetwork/charon:\$\{CHARON_VERSION:-)v\.?[0-9]+\.[0-9]+\.[0-9]+[a-zA-Z0-9\-]*}|\1v'"${TAG_NAME}"'}|' docker-compose.yml
23 |
24 | - name: Create Pull Request
25 | uses: peter-evans/create-pull-request@v7
26 | with:
27 | token: ${{ secrets.GITHUB_TOKEN }}
28 | base: main
29 | branch: update-version-${{ env.TAG_NAME }}
30 | title: "Update version to ${{ env.TAG_NAME }}"
31 | body: "Automatically generated PR to update version to ${{ env.TAG_NAME }}"
32 | commit-message: "Update version to ${{ env.TAG_NAME }}"
33 | author-name: "obol-platform"
34 | author-email: "platform@obol.tech"
35 |
--------------------------------------------------------------------------------
/grafana/datasource.yml:
--------------------------------------------------------------------------------
1 | # config file version
2 | apiVersion: 1
3 |
4 | # list of datasources that should be deleted from the database
5 | deleteDatasources:
6 | - name: Prometheus
7 | orgId: 1
8 |
9 | # list of datasources to insert/update depending
10 | # whats available in the database
11 | datasources:
12 | # name of the datasource. Required
13 | - name: Prometheus
14 | # datasource type. Required
15 | type: prometheus
16 | # org id. will default to orgId 1 if not specified
17 | orgId: 1
18 | # url
19 | url: http://prometheus:9090
20 | # database password, if used
21 | password:
22 | # database user, if used
23 | user:
24 | # database name, if used
25 | database:
26 | # enable/disable basic auth
27 | basicAuth: false
28 | # enable/disable with credentials headers
29 | withCredentials:
30 | # mark as default datasource. Max one per org
31 | isDefault: true
32 | #