Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
28 commits
Select commit Hold shift + click to select a range
1a3fbea
Scripts for asdb and replace-operator
pinebit Feb 11, 2026
ef87c09
Updated gitignore
pinebit Feb 11, 2026
aaf299b
Added recreate edit script
pinebit Feb 16, 2026
3f880e8
Added CLAUDE.md
pinebit Feb 17, 2026
e29871f
Added add-validators script
pinebit Feb 17, 2026
997336d
Unified look and feel
pinebit Feb 17, 2026
34ffc35
Added add-operators scripts
pinebit Feb 17, 2026
f4449e2
Added remove-operators scripts
pinebit Feb 17, 2026
6913a09
Removed rotation script tests
pinebit Feb 17, 2026
f75dc38
Updated READMEs
pinebit Feb 17, 2026
f4c4833
Added e2e test
pinebit Feb 17, 2026
7910a2f
Updated READMEs
pinebit Feb 17, 2026
623d370
Verified and fixed add-validators script
pinebit Feb 18, 2026
d901419
Fixed scripts and readme
pinebit Feb 19, 2026
739d73b
Added Claude Skills for edit scripts
pinebit Feb 19, 2026
4952eae
Fixing scripts, wip
pinebit Feb 20, 2026
524ec7d
Fixing scripts, wip
pinebit Feb 20, 2026
99ab9ef
Updated skills
pinebit Feb 20, 2026
8ad480f
Unified skills and scripts
pinebit Feb 20, 2026
09a3b90
New e2e test and fixes
pinebit Feb 20, 2026
cecd695
Fixed replace-operator flow
pinebit Feb 20, 2026
eff0393
Fixed skills prerequisites
pinebit Feb 20, 2026
270ebfd
Fixed replace-operator flow
pinebit Feb 20, 2026
134244b
Updated skills
pinebit Feb 23, 2026
1f061df
Addressed PR feedback
pinebit Feb 24, 2026
46fad70
Addressed PR feedback
pinebit Feb 24, 2026
e6055af
Addressed PR feedback
pinebit Feb 24, 2026
8c3a3c4
Updated charon version to 1.9.0
pinebit Feb 24, 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
84 changes: 84 additions & 0 deletions .claude/skills/add-operators/SKILL.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
---
name: add-operators
description: Add new operators to an existing Charon distributed validator cluster
user-invokable: true
---

# Add Operators

> **Warning:** This is an alpha feature and is not yet recommended for production use.

Expand a Charon cluster by adding new operators. This is a coordinated operation involving both existing and new operators.

## Prerequisites

Read `scripts/edit/add-operators/README.md` for full details if needed.

Common prerequisites:
1. `.env` file exists with `NETWORK` and `VC` variables set
2. `.charon` directory with `cluster-lock.json` and `charon-enr-private-key`
3. Docker is running
4. `jq` installed

## Role Selection

Ask the user: **"Are you an existing operator in the cluster, or a new operator joining?"**

### If Existing Operator

**Script**: `scripts/edit/add-operators/existing-operator.sh`

**Additional prerequisites**:
- `.charon/cluster-lock.json` and `.charon/validator_keys/` must exist
- The script will automatically stop the VC container for ASDB export

**Arguments to gather**:
- `--new-operator-enrs`: Comma-separated ENRs of the new operators joining
- Whether to use `--dry-run` first

**Run**:
```bash
./scripts/edit/add-operators/existing-operator.sh \
--new-operator-enrs "enr:-...,enr:-..." \
[--dry-run]
```

Set `WORK_DIR` env var to override the repository root directory if running from a custom location.


The script will export the anti-slashing database, run the P2P ceremony, update keys, and print commands to start containers manually. After completion, remind the user to **wait ~2 epochs before starting** containers.

### If New Operator

**Script**: `scripts/edit/add-operators/new-operator.sh`

This is a **two-step process**:

#### Step 1: Generate ENR

Ask if the user needs to generate an ENR (first time setup):

```bash
./scripts/edit/add-operators/new-operator.sh --generate-enr
```

This creates `.charon/charon-enr-private-key` and displays the ENR. Tell the user to **share this ENR with the existing operators**.
The existing operators, in turn, need to share the `cluster-lock.json` with the new operators, which contains the current cluster configuration and is required for the P2P ceremony.

#### Step 2: Join the Ceremony

After the existing operators have the ENR, gather:
- `--new-operator-enrs`: Comma-separated ENRs of ALL new operators (including their own)
- `--cluster-lock`: Path to the `cluster-lock.json` received from existing operators
- Whether to use `--dry-run` first

```bash
./scripts/edit/add-operators/new-operator.sh \
--new-operator-enrs "enr:-...,enr:-..." \
--cluster-lock ./received-cluster-lock.json \
[--dry-run]
```

Set `WORK_DIR` env var to override the repository root directory if running from a custom location.

Remind the user that **all operators (existing AND new) must participate simultaneously** in the P2P ceremony. After completion, the script will print commands to start containers manually. The new operator does NOT have slashing protection history (fresh start).
58 changes: 58 additions & 0 deletions .claude/skills/add-validators/SKILL.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
---
name: add-validators
description: Add new validators to an existing Charon distributed validator cluster
user-invokable: true
---

# Add Validators

> **Warning:** This is an alpha feature and is not yet recommended for production use.

Add new validators to an existing Charon distributed validator cluster. All operators must run this simultaneously as it requires a P2P ceremony.

## Prerequisites

Before running, verify:
1. `.env` file exists with `NETWORK` and `VC` variables set
2. `.charon/cluster-lock.json` and `.charon/deposit-data*.json` exist
3. Docker is running
4. `jq` is installed

Read `scripts/edit/add-validators/README.md` for full details if needed.

## Gather Arguments

Ask the user for the following required arguments using AskUserQuestion:

1. **Number of validators** (`--num-validators`): How many new validators to add (positive integer)
2. **Withdrawal addresses** (`--withdrawal-addresses`): Comma-separated Ethereum withdrawal address(es)
3. **Fee recipient addresses** (`--fee-recipient-addresses`): Comma-separated fee recipient address(es)

Also ask whether they want to:
- Run with `--dry-run` first to preview the operation
- Use `--unverified` flag (skip key verification, used for remote KeyManager API setups)

## Execution

Run the script from the repository root:

```bash
./scripts/edit/add-validators/add-validators.sh \
--num-validators <N> \
--withdrawal-addresses <addrs> \
--fee-recipient-addresses <addrs> \
[--unverified] [--dry-run]
```

Set `WORK_DIR` env var to override the repository root directory if running from a custom location.

The script will:
1. Validate prerequisites
2. Display current cluster info (operators, validators)
3. Run a P2P ceremony (all operators must participate simultaneously)
4. Stop containers if they were running
5. Backup `.charon/` to `./backups/`
6. Install new configuration
7. Print commands to start containers manually

Remind the user that **all operators must run this script at the same time** for the P2P ceremony to succeed.
31 changes: 31 additions & 0 deletions .claude/skills/export-asdb/SKILL.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
---
name: export-asdb
description: Export the anti-slashing database (EIP-3076) from the validator client
user-invokable: true
---

# Export Anti-Slashing Database

> **Warning:** This is an alpha feature and is not yet recommended for production use.

Export the EIP-3076 anti-slashing database from the validator client. The VC container must be stopped before export.

## Prerequisites

1. `.env` file exists with `VC` variable set
2. VC container must be **stopped**

Read `scripts/edit/vc/README.md` for full details if needed.

## Gather Arguments

Ask the user for:
- `--output-file`: Path to write the exported JSON file (e.g., `./asdb-export/slashing-protection.json`)

## Execution

```bash
./scripts/edit/vc/export_asdb.sh --output-file <path>
```

The `VC` variable is read from `.env` automatically. The script routes to the appropriate VC-specific export implementation (lodestar, teku, prysm, or nimbus).
31 changes: 31 additions & 0 deletions .claude/skills/import-asdb/SKILL.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
---
name: import-asdb
description: Import an anti-slashing database (EIP-3076) into the validator client
user-invokable: true
---

# Import Anti-Slashing Database

> **Warning:** This is an alpha feature and is not yet recommended for production use.

Import an EIP-3076 anti-slashing database into the validator client. The VC container must be stopped.

## Prerequisites

1. `.env` file exists with `VC` variable set
2. VC container must be **stopped**

Read `scripts/edit/vc/README.md` for full details if needed.

## Gather Arguments

Ask the user for:
- `--input-file`: Path to the JSON file to import (e.g., `./asdb-export/slashing-protection.json`)

## Execution

```bash
./scripts/edit/vc/import_asdb.sh --input-file <path>
```

The `VC` variable is read from `.env` automatically. The script routes to the appropriate VC-specific import implementation (lodestar, teku, prysm, or nimbus).
52 changes: 52 additions & 0 deletions .claude/skills/recreate-private-keys/SKILL.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
---
name: recreate-private-keys
description: Recreate private key shares for a Charon cluster while keeping the same validator public keys
user-invokable: true
---

# Recreate Private Keys

> **Warning:** This is an alpha feature and is not yet recommended for production use.

Refresh private key shares held by operators while keeping the same validator public keys. Validators stay registered on the beacon chain - only the operator key shares change. All operators must participate simultaneously.

## Use Cases

- Security concerns: private key shares may have been compromised
- Key rotation: regular security practice
- Recovery: after a security incident

## Prerequisites

Before running, verify:
1. `.env` file exists with `NETWORK` and `VC` variables set
2. `.charon` directory with `cluster-lock.json` and `validator_keys`
3. Docker is running
4. `jq` installed

Read `scripts/edit/recreate-private-keys/README.md` for full details if needed.

## Execution

Ask the user whether they want to run with `--dry-run` first to preview the operation.

```bash
./scripts/edit/recreate-private-keys/recreate-private-keys.sh [--dry-run]
```

Set `WORK_DIR` env var to override the repository root directory if running from a custom location.

The script will:
1. Validate prerequisites
2. Stop the VC container and export the anti-slashing database
3. Run a P2P ceremony (all operators must participate simultaneously)
4. Update ASDB pubkeys to match new key shares
5. Stop containers
6. Backup `.charon/` to `./backups/`
7. Install new key shares
8. Import updated ASDB
9. Print commands to start containers manually

After completion, remind the user to **wait ~2 epochs before starting** containers.

Remind the user that **all operators must run this script at the same time** for the P2P ceremony to succeed.
88 changes: 88 additions & 0 deletions .claude/skills/remove-operators/SKILL.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
---
name: remove-operators
description: Remove operators from an existing Charon distributed validator cluster
user-invokable: true
---

# Remove Operators

> **Warning:** This is an alpha feature and is not yet recommended for production use.

Remove one or more operators from a Charon cluster. Whether removed operators need to participate depends on fault tolerance.

## Prerequisites

Read `scripts/edit/remove-operators/README.md` for full details if needed.

Common prerequisites:
1. `.env` file exists with `NETWORK` and `VC` variables set
2. `.charon` directory with `cluster-lock.json` and `validator_keys`
3. Docker is running
4. `jq` installed

## Fault Tolerance Context

Explain to the user:
- Fault tolerance `f = operators - threshold`
- If removing **<= f** operators: removed operators do NOT need to participate (they just stop their nodes)
- If removing **> f** operators: removed operators MUST also participate using `removed-operator.sh`

## Role Selection

Ask the user: **"Are you a remaining operator (staying in the cluster) or a removed operator (leaving the cluster)?"**

### If Remaining Operator

**Script**: `scripts/edit/remove-operators/remaining-operator.sh`

**Additional prerequisites**:
- `.charon/validator_keys/` must exist
- The script will automatically stop the VC container for ASDB export

**Arguments to gather**:
- `--operator-enrs-to-remove`: Comma-separated ENRs of operators being removed
- `--participating-operator-enrs` (only if removal exceeds fault tolerance): Comma-separated ENRs of ALL participating operators
- `--new-threshold` (optional): Override the default threshold (defaults to ceil(n * 2/3))
- Whether to use `--dry-run` first

**Run**:
```bash
./scripts/edit/remove-operators/remaining-operator.sh \
--operator-enrs-to-remove "enr:-...,enr:-..." \
[--participating-operator-enrs "enr:-...,enr:-..."] \
[--new-threshold N] \
[--dry-run]
```

Set `WORK_DIR` env var to override the repository root directory if running from a custom location.

After completion, the script will print commands to start containers manually. Remind the user to **wait ~2 epochs before starting** containers.

### If Removed Operator

**Script**: `scripts/edit/remove-operators/removed-operator.sh`

This is **only needed when the removal exceeds fault tolerance**. If within fault tolerance, the removed operator simply stops their node.

**Additional prerequisites**:
- `.charon/charon-enr-private-key` must exist
- `.charon/validator_keys/` must exist

**Arguments to gather**:
- `--operator-enrs-to-remove`: Comma-separated ENRs of operators being removed
- `--participating-operator-enrs`: Comma-separated ENRs of ALL participating operators (must include your own ENR)
- `--new-threshold` (optional): Override the default threshold
- Whether to use `--dry-run` first

**Run**:
```bash
./scripts/edit/remove-operators/removed-operator.sh \
--operator-enrs-to-remove "enr:-...,enr:-..." \
--participating-operator-enrs "enr:-...,enr:-..." \
[--new-threshold N] \
[--dry-run]
```

Set `WORK_DIR` env var to override the repository root directory if running from a custom location.

The script will participate in the ceremony and then stop your charon and VC containers. No ASDB operations are needed since you're leaving the cluster.
Loading