Skip to content
Open
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
74 changes: 74 additions & 0 deletions .claude/skills/add-operators/SKILL.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
---
name: add-operators
description: Add new operators to an existing Charon distributed validator cluster
user-invokable: true
---

# Add Operators

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. Docker is running

## 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
- VC container must be running (needed 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]
```

The script will export the anti-slashing database, run the P2P ceremony, update keys, and provide restart instructions. After completion, remind the user to **wait ~2 epochs before restarting** 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**.

#### 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]
```

Remind the user that **all operators (existing AND new) must participate simultaneously** in the P2P ceremony.
53 changes: 53 additions & 0 deletions .claude/skills/add-validators/SKILL.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
---
name: add-validators
description: Add new validators to an existing Charon distributed validator cluster
user-invokable: true
---

# Add Validators

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` exists
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]
```

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

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

# Export Anti-Slashing Database

Export the EIP-3076 anti-slashing database from the currently running validator client. The VC container must be running.

## Prerequisites

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

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).
29 changes: 29 additions & 0 deletions .claude/skills/import-asdb/SKILL.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
---
name: import-asdb
description: Import an anti-slashing database (EIP-3076) into the validator client
user-invokable: true
---

# Import Anti-Slashing Database

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).
47 changes: 47 additions & 0 deletions .claude/skills/recreate-private-keys/SKILL.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
---
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

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/cluster-lock.json` and `.charon/validator_keys/` exist
3. Docker is running
4. VC container must be running (for ASDB export)

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]
```

The script will:
1. Validate prerequisites
2. Export the anti-slashing database from the running VC
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

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

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

# Remove Operators

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/cluster-lock.json` exists
3. Docker is running

## 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
- VC container must be running (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]
```

After completion, remind the user to **wait ~2 epochs before restarting** 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]
```

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.
76 changes: 76 additions & 0 deletions .claude/skills/replace-operator/SKILL.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
---
name: replace-operator
description: Replace a single operator in a Charon distributed validator cluster
user-invokable: true
---

# Replace Operator

Replace a single operator in a Charon cluster with a new one. This is a non-P2P local operation (no coordinated ceremony required).

## Prerequisites

Read `scripts/edit/replace-operator/README.md` for full details if needed.

Common prerequisites:
1. `.env` file exists with `NETWORK` and `VC` variables set
2. Docker is running

## Role Selection

Ask the user: **"Are you a remaining operator (performing the replacement) or the new operator joining as a replacement?"**

### If Remaining Operator

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

**Additional prerequisites**:
- `.charon/cluster-lock.json` and `.charon/charon-enr-private-key` must exist
- VC container must be running (for ASDB export, unless `--skip-export` is used)

**Arguments to gather**:
- `--new-enr`: ENR of the new replacement operator
- `--operator-index`: Index of the operator being replaced (0-based)
- `--skip-export` (optional): Skip ASDB export if already done
- Whether to use `--dry-run` first

**Run**:
```bash
./scripts/edit/replace-operator/remaining-operator.sh \
--new-enr "enr:-..." \
--operator-index <N> \
[--skip-export] \
[--dry-run]
```

After completion, the script will output the new `cluster-lock.json`. Remind the user to **share the new cluster-lock.json with the new operator** and to **wait ~2 epochs before restarting** containers.

### If New Operator

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

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

#### Step 1: Generate ENR

Ask if the user needs to generate an ENR:

```bash
./scripts/edit/replace-operator/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 remaining operators**.

#### Step 2: Install Cluster Lock

After receiving the new `cluster-lock.json` from remaining operators:
- `--cluster-lock`: Path to the received `cluster-lock.json`
- Whether to use `--dry-run` first

```bash
./scripts/edit/replace-operator/new-operator.sh \
--cluster-lock ./received-cluster-lock.json \
[--dry-run]
```

The script will verify the ENR is present in the cluster-lock, install the configuration, and start charon and VC containers. Note: the new operator does NOT have slashing protection history (fresh start).
Loading