From 9b5446c1e8097b88a25b5577bbaebfe5eda26b39 Mon Sep 17 00:00:00 2001 From: Darien Hernandez Date: Fri, 23 Jan 2026 10:55:04 +0100 Subject: [PATCH 1/3] feat(skills): Add GenLayer validator node setup and update skill Add comprehensive Claude Code skill for setting up and updating GenLayer validator nodes with focus on zero-downtime operations and proactive issue prevention. Key features: - Interactive installation wizard for new validator nodes - Zero-downtime update procedure (10-15 sec vs 3-4 min downtime) - Shared database structure for patch versions (v0.4.x) - Proactive edge case detection and prevention (30+ documented cases) - Pre-update validation checklist to catch issues before they occur - Support for local, SSH, GCP, AWS, and Azure deployments Critical edge cases documented: - OpenAI provider disabled by default (prevents bootstrap failure) - Database storage must be shared between patch versions - High-downtime update procedure (stops node before preparation) - LLM configuration validation before version switching Files added: - skill.yaml: Main skill definition with installation flow - sharp-edges.yaml: 30+ edge cases with detection and fixes - validations.yaml: Automated validation rules - update-procedure.md: Zero-downtime update guide - pre-update-checklist.md: Proactive validation steps - SKILL.md: Complete skill documentation --- .claude-plugin/plugin.json | 16 + .claude/skills/README.md | 93 ++ .../skills/genlayer-validator-setup/SKILL.md | 898 ++++++++++++++ .../collaboration.yaml | 95 ++ .../pre-update-checklist.md | 210 ++++ .../genlayer-validator-setup/sharp-edges.yaml | 687 +++++++++++ .../genlayer-validator-setup/skill.yaml | 1094 +++++++++++++++++ .../update-procedure.md | 149 +++ .../genlayer-validator-setup/validations.yaml | 252 ++++ 9 files changed, 3494 insertions(+) create mode 100644 .claude-plugin/plugin.json create mode 100644 .claude/skills/README.md create mode 100644 .claude/skills/genlayer-validator-setup/SKILL.md create mode 100644 .claude/skills/genlayer-validator-setup/collaboration.yaml create mode 100644 .claude/skills/genlayer-validator-setup/pre-update-checklist.md create mode 100644 .claude/skills/genlayer-validator-setup/sharp-edges.yaml create mode 100644 .claude/skills/genlayer-validator-setup/skill.yaml create mode 100644 .claude/skills/genlayer-validator-setup/update-procedure.md create mode 100644 .claude/skills/genlayer-validator-setup/validations.yaml diff --git a/.claude-plugin/plugin.json b/.claude-plugin/plugin.json new file mode 100644 index 000000000..065f111d3 --- /dev/null +++ b/.claude-plugin/plugin.json @@ -0,0 +1,16 @@ +{ + "name": "genlayer-docs", + "description": "GenLayer validator setup and node management skills", + "version": "1.3.0", + "author": "GenLayer", + "repository": "https://github.com/genlayerlabs/genlayer-docs", + "skills": [ + { + "path": ".claude/skills/genlayer-validator-setup", + "name": "genlayer-validator-setup", + "description": "Interactive wizard to set up a GenLayer validator node on Linux", + "version": "1.3.0", + "tags": ["validator", "node", "installation", "blockchain", "genlayer"] + } + ] +} \ No newline at end of file diff --git a/.claude/skills/README.md b/.claude/skills/README.md new file mode 100644 index 000000000..5689363a5 --- /dev/null +++ b/.claude/skills/README.md @@ -0,0 +1,93 @@ +# GenLayer Skills + +Claude Code skills for GenLayer validator operations and node management. + +## Available Skills + +### genlayer-validator-setup + +Interactive wizard to set up a GenLayer validator node on Linux servers. + +**Features:** +- Prerequisites verification (architecture, RAM, dependencies) +- Wallet and staking wizard integration +- Software download with versioned directories +- Configuration generation with sensible defaults +- Operator key management +- LLM provider setup (Anthropic, Google, Heurist, etc.) +- Systemd service creation +- Telemetry/monitoring setup (optional) +- Version upgrades with shared storage + +**Version:** 1.3.0 + +**Documentation:** +- [Full Documentation](./genlayer-validator-setup/SKILL.md) +- [Installation Guide](#installation) + +## Installation + +### Method 1: Claude Code Plugin (Recommended) + +```bash +# Add the plugin marketplace +/plugin marketplace add genlayerlabs/genlayer-docs + +# Install the skill +/plugin install genlayer-validator-setup@genlayer-docs +``` + +### Method 2: Manual Installation + +```bash +# Clone the repository +git clone https://github.com/genlayerlabs/genlayer-docs.git + +# Copy skill to your project +cp -r genlayer-docs/.claude/skills/genlayer-validator-setup \ + your-project/.claude/skills/ + +# Or symlink it +ln -s $(pwd)/genlayer-docs/.claude/skills/genlayer-validator-setup \ + your-project/.claude/skills/genlayer-validator-setup +``` + +### Method 3: Direct Usage (If in genlayer-docs repo) + +The skill is already available if you're working within the genlayer-docs repository. Just invoke it: + +```bash +/genlayer-validator-setup +``` + +## Usage + +Once installed, activate the skill: + +```bash +/genlayer-validator-setup +``` + +Then tell Claude what you want to do: +- "I want to set up a new validator node" +- "Help me upgrade my node from v0.4.3 to v0.4.4" +- "I need to configure a new operator key" + +## What's Included + +The skill provides: +- **46 documented anti-patterns** - Common mistakes to avoid +- **33 documented sharp edges** - Runtime issues with detection and fixes +- **Complete installation procedure** - Step-by-step guided setup +- **Validation rules** - Ensures correct configuration +- **Collaboration patterns** - Multi-session support + +## Support + +- **Issues**: [GitHub Issues](https://github.com/genlayerlabs/genlayer-docs/issues) +- **Documentation**: [GenLayer Docs](https://docs.genlayer.com) +- **Discord**: [GenLayer Community](https://discord.gg/genlayer) + +## License + +Apache 2.0 diff --git a/.claude/skills/genlayer-validator-setup/SKILL.md b/.claude/skills/genlayer-validator-setup/SKILL.md new file mode 100644 index 000000000..a1580c6d3 --- /dev/null +++ b/.claude/skills/genlayer-validator-setup/SKILL.md @@ -0,0 +1,898 @@ +--- +name: genlayer-validator-setup +description: Interactive wizard to set up a GenLayer validator node on Linux. +tools: + - Bash + - Read + - Write + - Edit + - WebFetch + - AskUserQuestion +hooks: [] +--- + +# GenLayer Validator Setup + +Interactive wizard to set up a GenLayer validator node from scratch on a Linux server. + +## What This Skill Will Do + +This skill guides you through the complete validator node installation process. When you invoke this skill, it will: + +1. **Determine your setup environment** - Local machine, remote server (SSH), or cloud VM (GCP/AWS/Azure) +2. **Verify prerequisites** - Check that your server meets minimum requirements (architecture, RAM, software dependencies) +3. **Guide wallet setup** - Help create a new validator wallet or use an existing one +4. **Download node software** - Fetch the specified version (or latest) from official storage +5. **Generate configuration** - Create config.yaml and .env files with your specific settings +6. **Import/generate operator keys** - Set up the validator's operator account +7. **Configure LLM provider** - Set up API keys for intelligent contract execution +8. **Start the node** - Launch as systemd service, Docker Compose, or manual process +9. **Verify installation** - Check health and sync status +10. **Optional: Enable monitoring** - Set up telemetry push to central monitoring + +**Total time estimate**: 20-45 minutes depending on your experience level and setup method. + +## ⚠️ CRITICAL: Update Procedure Warning + +**If you are UPDATING an existing node, read this first:** + +### Zero-Downtime Update Procedure +**NEVER stop your old node before preparing the new version!** + +Traditional update process (WRONG - causes 3-4 min downtime): +``` +❌ Stop node → Download → Extract → GenVM setup (2 min) → Start +``` + +**Correct procedure (10-15 sec downtime):** +``` +✓ Download → Extract → GenVM setup WHILE OLD NODE RUNS +✓ THEN: Stop old → Switch symlinks → Start new +``` + +**Impact of wrong procedure:** +- 3-4 minutes downtime vs 10-15 seconds +- Missed 12-24 validation opportunities +- Lost rewards during downtime +- Validator needs to re-prime +- Potential slashing penalties + +**See `update-procedure.md` for detailed zero-downtime update steps.** + +### Database Storage Structure +For patch versions (v0.4.x), the database MUST be shared, not copied: + +**Correct structure:** +``` +/opt/genlayer-node/v0.4/data/node/genlayer.db ← Shared DB +/opt/genlayer-node/v0.4.3/data/node/genlayer.db → symlink to shared +/opt/genlayer-node/v0.4.4/data/node/genlayer.db → symlink to shared +``` + +### OpenAI Provider Configuration +If using OpenAI, you MUST enable it in GenVM config: +```bash +# Check if enabled +grep -A 2 'openai:' third_party/genvm/config/genvm-module-llm.yaml + +# If shows 'enabled: false', enable it: +sed -i '/^ openai:/,/^ / s/enabled: false/enabled: true/' \ + third_party/genvm/config/genvm-module-llm.yaml +``` + +**Symptom if not enabled:** Node fails to start with "module_failed_to_start" error. + +--- + +## Requirements + +Before starting, ensure your setup meets these requirements: + +### System Requirements +- **Architecture**: AMD64 (x86_64) Linux server - ARM64 is NOT supported +- **RAM**: Minimum 16GB (32GB recommended for production) +- **CPU**: Minimum 8 cores (16+ recommended for production) +- **Storage**: Minimum 128GB SSD (256GB+ recommended for production) +- **Operating System**: Ubuntu 20.04+, Debian 11+, or compatible Linux distribution + +### Software Dependencies +- **Node.js**: v18 or higher +- **Docker**: v20.10 or higher with Compose plugin +- **Python**: Python 3.8+ with pip and venv modules +- **Git**: For version control (optional but recommended) + +### Blockchain Requirements +- **GEN Tokens**: 42,000+ GEN for self-stake (if creating new validator) +- **ETH**: Small amount of ETH for gas fees on operator account (~0.1 ETH recommended) +- **RPC Access**: HTTP and WebSocket URLs for GenLayer Chain (ZkSync-based) + +### API Keys Required +- **LLM Provider**: API key from one of these providers: + - Heurist (recommended for validators) + - Comput3 + - io.net + - OpenAI + - LibertAI + - Anthropic + - Google (Gemini) + +### Access Requirements +- **SSH Access**: If installing on remote server (username@hostname) +- **Sudo Privileges**: Installation requires root or sudo access +- **Port Access**: Ports 9151 (RPC), 9153 (Ops), 9155 (Admin), 4444 (WebDriver) must be available + +## Installation Process Overview + +The skill follows this step-by-step process: + +``` +┌─────────────────────────────────────────┐ +│ 1. Environment Setup │ +│ • Determine server location │ +│ • Verify prerequisites │ +└──────────────────┬──────────────────────┘ + │ +┌──────────────────▼──────────────────────┐ +│ 2. Wallet & Staking │ +│ • New validator: Run staking wizard │ +│ • Existing: Provide wallet address │ +└──────────────────┬──────────────────────┘ + │ +┌──────────────────▼──────────────────────┐ +│ 3. Software Download │ +│ • List available versions │ +│ • Download specified/latest version │ +│ • Extract to versioned directory │ +│ • Setup shared storage for DB │ +└──────────────────┬──────────────────────┘ + │ +┌──────────────────▼──────────────────────┐ +│ 4. Configuration │ +│ • Create .env file │ +│ • Generate config.yaml via wizard │ +│ • Set RPC/WebSocket URLs │ +│ • Configure node identity │ +└──────────────────┬──────────────────────┘ + │ +┌──────────────────▼──────────────────────┐ +│ 5. Operator Key Setup │ +│ • Import from staking wizard, OR │ +│ • Copy from previous install, OR │ +│ • Generate new key │ +└──────────────────┬──────────────────────┘ + │ +┌──────────────────▼──────────────────────┐ +│ 6. LLM Configuration │ +│ • Choose LLM provider │ +│ • Set API key in .env │ +│ • Enable OpenAI backend if needed │ +└──────────────────┬──────────────────────┘ + │ +┌──────────────────▼──────────────────────┐ +│ 7. Start Services │ +│ • Start WebDriver container │ +│ • Run doctor check │ +│ • Start node (systemd/docker/manual) │ +└──────────────────┬──────────────────────┘ + │ +┌──────────────────▼──────────────────────┐ +│ 8. Verification & Cleanup │ +│ • Check health endpoint │ +│ • Verify sync status │ +│ • Clean up previous version │ +│ • Optional: Enable monitoring │ +└─────────────────────────────────────────┘ +``` + +### Version Handling + +When specifying a version: +- **Specific version**: Use exact version like `v0.4.4` +- **Latest version**: Use `latest` to automatically download the most recent release +- **No version specified**: Skill will prompt you to choose from the 5 most recent versions + +The skill automatically handles: +- Version-specific directory structure (`/opt/genlayer-node/v0.4.4/`) +- Shared database storage across patch versions (v0.4.x shares same DB) +- Version-specific keystore and logs for safety +- Symlinks for easy access to current version + +## Purpose + +Guide validators through complete GenLayer node installation including: +- Prerequisites verification (Python3, pip, venv, Docker, Node.js) +- Wallet creation via staking wizard (requires 42,000+ GEN) +- Node software download and extraction +- Configuration via config.yaml and .env file +- Operator key import from wizard export +- LLM provider setup (Heurist, Comput3, io.net, OpenAI, LibertAI, Anthropic, Google) +- Node startup as systemd service (binary) or Docker Compose +- Optional telemetry/monitoring setup + +## Quick Reference + +### Directory Structure After Installation +``` +/opt/genlayer-node/ +├── v0.4.4/ # Version-specific directory +│ ├── bin/genlayernode +│ ├── third_party/genvm/ +│ ├── docker-compose.yaml +│ ├── .env +│ ├── data/node/ +│ │ ├── genlayer.db +│ │ ├── keystore/ +│ │ ├── logs/ +│ │ └── merkle/ +│ └── configs/node/config.yaml +├── bin -> v0.4.4/bin # Symlinks for easy access +├── third_party -> v0.4.4/third_party +├── data -> v0.4.4/data +├── configs -> v0.4.4/configs +├── docker-compose.yaml -> v0.4.4/docker-compose.yaml +├── .env -> v0.4.4/.env +└── alloy-config.river # Telemetry config (if monitoring enabled) +``` + +### Requires +- AMD64 Linux server (16GB+ RAM, 8+ cores, 128GB+ SSD) +- Node.js v18+, Docker, Python 3 with pip and venv +- 42,000+ GEN tokens for self-stake (if new validator) +- LLM API key from supported provider +- Operator keystore from staking wizard (or generate new) + +### Default Configuration +| Setting | Default Value | +|---------|---------------| +| RPC URL | **No default** - user must provide | +| WebSocket | **No default** - user must provide | +| Main Contract | `0x67fd4aC71530FB220E0B7F90668BAF977B88fF07` | +| Data Contract | `0xB6E1316E57d47d82FDcEa5002028a554754EF243` | +| Genesis Block | `4632386` | +| Install Path | `/opt/genlayer-node` | +| RPC Port | `9151` | +| Ops Port | `9153` | +| Admin Port | `9155` | +| Metrics Interval | `15s` | + +### LLM Provider Environment Variables +| Provider | Environment Variable | +|----------|---------------------| +| Heurist | `HEURISTKEY` | +| Comput3 | `COMPUT3KEY` | +| io.net | `IOINTELLIGENCEKEY` | +| OpenAI | `OPENAIKEY` | +| LibertAI | `LIBERTAI_API_KEY` | +| Anthropic | `ANTHROPICKEY` | +| Google | `GEMINIKEY` | + +## Installation Flow + +The skill guides through these steps interactively: + +### 0. Determine Server Location and Access Method +**CRITICAL FIRST STEP**: Before any installation begins, determine where the validator will run and how to access it. + +**Question**: "Where will you run the validator node?" + +**Options**: +- **This machine (local setup)**: Running validator on this computer + - Commands execute directly via Bash tool + - Files copied using local filesystem + - Health checks use localhost +- **Remote Linux server (SSH)**: Generic Linux server accessed via SSH + - Provide commands as text for user to run via SSH + - File transfers via scp + - Collect: username@hostname or username@IP +- **Google Cloud Platform VM**: GCP Compute Engine instance + - Commands use gcloud compute ssh + - File transfers via gcloud compute scp + - Collect: project-id/zone/instance-name +- **AWS EC2 Instance**: Amazon Web Services EC2 instance + - Commands use AWS Systems Manager or SSH + - File transfers via scp or AWS transfer + - Collect: instance-id/region +- **Azure VM**: Azure Virtual Machine + - Commands use Azure CLI or SSH + - File transfers via scp + - Collect: resource-group/vm-name +- **Other cloud provider**: DigitalOcean, Linode, Vultr, etc. + - Commands use standard SSH + - File transfers via scp + +**Impact**: This choice affects ALL subsequent steps: +- How commands are executed (direct vs via SSH) +- How files are transferred (cp vs scp vs cloud-specific tools) +- How to verify installation (local curl vs SSH tunneling) +- Which CLI tools are needed (gcloud, aws cli, azure cli) + +### 1. Check Prerequisites +Verify system meets requirements before starting: + +```bash +# Check architecture (must be x86_64) +uname -m + +# Check Node.js (v18+ required) +node --version + +# Check Docker and Docker Compose +docker --version +docker compose version + +# Check Python 3 with pip and venv +python3 --version +pip3 --version +python3 -m venv --help +``` + +**Minimum requirements:** +- AMD64 (x86_64) architecture +- 16GB+ RAM, 8+ CPU cores, 128GB+ SSD +- Node.js v18+ +- Docker with Compose plugin +- Python 3 with pip and venv + +### 1. New Validator or Existing? +**Note**: Commands shown here assume local execution. For remote servers, adapt based on your chosen access method from Step 0. + +- **New**: Run staking wizard (requires 42,000+ GEN) + ```bash + npm install -g genlayer + genlayer staking wizard + ``` + This creates validator wallet and exports operator keystore +- **Existing**: Skip to download (must have validator wallet address) + +### 2. Download & Setup +**Note**: For remote servers, download to the remote server, not your local machine. + +**List available versions:** +```bash +curl -s "https://storage.googleapis.com/storage/v1/b/gh-af/o?prefix=genlayer-node/bin/amd64" | \ + grep -o '"name": *"[^"]*"' | sed -n 's/.*\/\(v[^/]*\)\/.*/\1/p' | sort -ru | head -5 +``` + +**Download and extract (replace ${VERSION} with actual version, e.g., v0.4.4):** +```bash +# Download to /tmp +wget https://storage.googleapis.com/gh-af/genlayer-node/bin/amd64/${VERSION}/genlayer-node-linux-amd64-${VERSION}.tar.gz \ + -O /tmp/genlayer-node-${VERSION}.tar.gz + +# Create versioned directory and extract +sudo mkdir -p /opt/genlayer-node/${VERSION} +sudo tar -xzvf /tmp/genlayer-node-${VERSION}.tar.gz \ + -C /opt/genlayer-node/${VERSION} --strip-components=1 + +# Create data and config directories inside version folder +sudo mkdir -p /opt/genlayer-node/${VERSION}/{data/node,configs/node} +sudo chown -R $USER:$USER /opt/genlayer-node + +# Setup symlinks for easy access +ln -sfn /opt/genlayer-node/${VERSION}/bin /opt/genlayer-node/bin +ln -sfn /opt/genlayer-node/${VERSION}/third_party /opt/genlayer-node/third_party +ln -sfn /opt/genlayer-node/${VERSION}/data /opt/genlayer-node/data +ln -sfn /opt/genlayer-node/${VERSION}/configs /opt/genlayer-node/configs +ln -sfn /opt/genlayer-node/${VERSION}/docker-compose.yaml /opt/genlayer-node/docker-compose.yaml +ln -sfn /opt/genlayer-node/${VERSION}/.env /opt/genlayer-node/.env +``` + +**Run GenVM setup:** +```bash +python3 /opt/genlayer-node/third_party/genvm/bin/setup.py +``` + +This downloads GenVM dependencies (genvm binary and genvm-modules). + +### 3. Environment Configuration (.env) + +**IMPORTANT**: Always start from the `.env.example` included in the downloaded artifact. This ensures all required variables are present. + +First ask if user wants to copy existing .env or create from example: +- **Use example (Recommended)**: Copy from artifact's `.env.example`, then customize +- **Copy from previous**: Copy .env from previous installation + +**Create .env from example:** +```bash +cp /opt/genlayer-node/${VERSION}/.env.example /opt/genlayer-node/${VERSION}/.env +``` + +**Key values to configure:** +1. **Rollup URLs** - Add these lines (not in .env.example by default): + ```bash + GENLAYERNODE_ROLLUP_GENLAYERCHAINRPCURL= + GENLAYERNODE_ROLLUP_GENLAYERCHAINWSSURL= + ``` + +2. **LLM API Key** - Set ONE of these (leave others empty): + - `HEURISTKEY=` + - `ANTHROPICKEY=` + - `GEMINIKEY=` + - `OPENAIKEY=` (add if using OpenAI - not in default .env.example) + +3. **Node Password** - Update `NODE_PASSWORD=` with a secure password + +**After creating .env, instruct user to:** +1. SSH to the VM: `gcloud compute ssh USER@VM --zone=ZONE` +2. Edit the .env file: `nano /opt/genlayer-node/.env` +3. Set the LLM API key for their chosen provider +4. Set a secure `NODE_PASSWORD` +5. Save and confirm when done + +### 4. Node Configuration (config.yaml) + +**IMPORTANT**: Always start from the example config included in the downloaded artifact (`configs/node/config.yaml.example`). This ensures the config format is compatible with the installed version. + +First ask if user wants to copy existing config or use example: +- **Use example config (Recommended)**: Copy from artifact's config.yaml.example, then customize via wizard +- **Copy from previous**: Copy config.yaml from previous installation + +#### Configuration Wizard (Group-based) +After copying the base config, go through each configuration GROUP and ask whether to modify or keep defaults: + +**Group 1: Node Identity** +- Ask: "Do you want to modify Node Identity settings?" (Keep defaults / Modify) +- If modify: Ask for validator address, operator address + +**Group 2: RPC Endpoints** +- Ask: "Do you want to modify RPC Endpoint settings?" (Keep defaults / Modify) +- If modify: Ask for port, enabled groups (genlayer, genlayer_debug, ethereum, zksync) + +**Group 3: Ops Endpoints** +- Ask: "Do you want to modify Ops Endpoint settings?" (Keep defaults / Modify) +- If modify: Ask for port, enable metrics/health/balance endpoints + +**Group 4: Admin Endpoints** +- Ask: "Do you want to modify Admin Endpoint settings?" (Keep defaults / Modify) +- If modify: Ask for port + +**Group 5: Metrics Configuration** +- Ask: "Do you want to modify Metrics settings?" (Keep defaults / Modify) +- If modify: Ask for collection intervals + +**Note**: Rollup URLs (RPC, WebSocket) are configured in .env. Contract addresses and other settings remain in config.yaml with defaults. + +### 5. Operator Key +First ask how user wants to provide the operator key: + +**Source options:** +- **Upload keystore.json** - Upload the keystore.json file exported from staking wizard (requires passphrase to import) +- **Upload keystore directory** - Upload the keystore directory directly (no import needed, just copy to data/node/keystore/) +- **Copy from previous** - Copy keystore from existing installation on this VM +- **Generate new** - Create new key ⚠️ + - Must fund new address with ETH for gas fees + - Must update validator settings to use new operator address + +**Upload flow:** +1. Ask which type of file user has (keystore.json or keystore directory) +2. **Create the keystore directory first** (required before upload): + ```bash + mkdir -p /opt/genlayer-node/${VERSION}/data/node/keystore + ``` +3. **Provide upload instructions based on server location (from Step 0)**: + + **For local setup:** + ```bash + # Copy keystore.json + cp ./keystore.json /opt/genlayer-node/${VERSION}/data/node/keystore.json + + # Or copy keystore directory + cp -r ./keystore/* /opt/genlayer-node/${VERSION}/data/node/keystore/ + ``` + + **For remote SSH server:** + ```bash + # Upload keystore.json + scp ./keystore.json username@hostname:/opt/genlayer-node/${VERSION}/data/node/keystore.json + + # Or upload keystore directory + scp -r ./keystore/* username@hostname:/opt/genlayer-node/${VERSION}/data/node/keystore/ + ``` + + **For GCP VM:** + ```bash + # Upload keystore.json + gcloud compute scp ./keystore.json instance-name:/opt/genlayer-node/${VERSION}/data/node/keystore.json \ + --project=project-id --zone=zone + + # Or upload keystore directory + gcloud compute scp --recurse ./keystore/* instance-name:/opt/genlayer-node/${VERSION}/data/node/keystore/ \ + --project=project-id --zone=zone + ``` + + **For AWS EC2:** + ```bash + # Upload keystore.json (assuming SSH access) + scp -i ~/.ssh/your-key.pem ./keystore.json ec2-user@instance-ip:/opt/genlayer-node/${VERSION}/data/node/keystore.json + + # Or upload keystore directory + scp -i ~/.ssh/your-key.pem -r ./keystore/* ec2-user@instance-ip:/opt/genlayer-node/${VERSION}/data/node/keystore/ + ``` + +4. Wait for user confirmation +5. Verify upload: + ```bash + ls -la /opt/genlayer-node/${VERSION}/data/node/keystore/ + ``` +6. For keystore.json: Run import command (user provides passphrase manually on VM): + ```bash + cd /opt/genlayer-node && source .env && ./bin/genlayernode account import \ + --password "$NODE_PASSWORD" \ + --path /opt/genlayer-node/${VERSION}/data/node/keystore.json + ``` + Note: User will be prompted for the export passphrase interactively +7. For keystore directory: Already in correct location, just verify contents show UTC--* file + +**Note**: Always use the version-specific path (e.g., `/opt/genlayer-node/v0.4.4/data/node/keystore/`), not the symlink path. + +### 6. Start WebDriver +WebDriver is required for web-based contract operations. Start it before running doctor check: + +```bash +cd /opt/genlayer-node && docker compose up -d +``` + +Wait for WebDriver to be healthy: +```bash +until docker inspect --format='{{.State.Health.Status}}' genlayer-node-webdriver | grep -q 'healthy'; do + echo "Waiting for WebDriver to be healthy..." + sleep 2 +done +echo "WebDriver is healthy!" +``` + +Verify WebDriver is running: +```bash +docker ps | grep webdriver +curl -s http://localhost:4444/status | jq '.value.ready' +``` + +### 7. Run Doctor Check +Run the doctor command to verify all configuration is correct: + +```bash +cd /opt/genlayer-node && source .env && ./bin/genlayernode doctor check +``` + +**Expected output on success:** +``` +GenLayer Node Doctor +=================== + + ✓ GenVM Binaries: Found at /opt/genlayer-node/third_party/genvm/bin + ✓ WebDriver: Connected to http://localhost:4444 (ready: true) + +✓ All checks passed! +``` + +**If checks fail:** +- GenVM Binaries missing: Re-run `python3 /opt/genlayer-node/third_party/genvm/bin/setup.py` +- WebDriver not ready: Check `docker logs genlayer-node-webdriver` + +### 8. Deployment Method +Ask user which deployment method they prefer: + +- **Systemd Service** (Recommended): Auto-restart, journald logs +- **Docker Compose**: All-in-one containers +- **Manual**: screen/tmux session + +#### Systemd Service Setup (Recommended) + +1. Create the service file at `/etc/systemd/system/genlayer-node.service`: + +```ini +[Unit] +Description=GenLayer Node +After=network.target docker.service +Requires=docker.service + +[Service] +Type=simple +User=root +WorkingDirectory=/opt/genlayer-node +EnvironmentFile=/opt/genlayer-node/.env +ExecStart=/opt/genlayer-node/bin/genlayernode run --password ${NODE_PASSWORD} +Restart=always +RestartSec=10 + +[Install] +WantedBy=multi-user.target +``` + +2. Enable and start the service: +```bash +sudo systemctl daemon-reload +sudo systemctl enable genlayer-node +sudo systemctl start genlayer-node +``` + +3. Check service status: +```bash +sudo systemctl status genlayer-node +``` + +4. View logs: +```bash +journalctl -u genlayer-node -f +``` + +#### Docker Compose Deployment + +```bash +cd /opt/genlayer-node && source .env && docker compose --profile node up -d +``` + +#### Manual Deployment (screen/tmux) + +```bash +screen -S genlayer +cd /opt/genlayer-node && source .env && ./bin/genlayernode run --password "$NODE_PASSWORD" +# Detach: Ctrl+A, D +# Reattach: screen -r genlayer +``` + +### 9. Verify Node Running + +After starting the node, verify it's running and syncing: + +**Health check:** +```bash +curl -s http://localhost:9153/health | jq +``` + +Expected response: +```json +{ + "status": "up", + "checks": { ... } +} +``` + +**Sync status:** +```bash +curl -s http://localhost:9153/metrics | grep genlayer_node_synced +``` + +Expected output (1 = synced, 0 = syncing): +``` +genlayer_node_synced{node="0x..."} 1 +``` + +**Check blocks behind:** +```bash +curl -s http://localhost:9153/metrics | grep genlayer_node_blocks_behind +``` + +**View logs (systemd):** +```bash +journalctl -u genlayer-node -f --no-hostname +``` + +**View logs (Docker):** +```bash +docker logs -f genlayer-node +``` + +### 10. Monitoring (Optional) +- Enable telemetry push to central infrastructure +- Requires monitoring credentials +- See: https://docs.genlayer.com/validators/monitoring + +## Deployment Methods + +### Binary (Systemd Service) - Recommended for production +- Persistent service with auto-restart +- Logs via journalctl +- Environment from .env file +- Service file at `/etc/systemd/system/genlayer-node.service` + +### Docker Compose +- All-in-one container deployment +- Includes monitoring profile +- Override files for LLM config + +## Automation + +This skill is defined by canonical YAML files: + +- **skill.yaml** - Main procedure, patterns, anti-patterns, defaults, config wizard +- **sharp-edges.yaml** - 30+ common gotchas with detection and fixes +- **validations.yaml** - 25+ automated pre/post checks +- **collaboration.yaml** - Dependencies and triggers + +## Usage + +Invoke this skill when: +- Setting up a new validator node +- Someone asks "how do I become a validator" +- Installing GenLayer node software +- Troubleshooting validator installation issues +- Upgrading an existing node + +The skill will guide through each step interactively, verifying prerequisites and configuration at each stage. + +### How to Invoke + +**Basic invocation:** +``` +I want to set up a validator node +``` + +**With specific version:** +``` +Install validator node version v0.4.4 +``` + +**With latest version:** +``` +Install validator node using the latest version +``` +or simply: +``` +Install validator node latest +``` + +When you use the word "latest", the skill will automatically fetch and install the most recent version from the official storage. + +## Complete Installation Steps + +| Step | Description | Key Actions | +|------|-------------|-------------| +| 0 | **Determine Server Location** | **Local vs Remote, SSH vs GCP vs AWS** | +| 1 | Check Prerequisites | Architecture, Node.js, Docker, Python | +| 2 | New Validator or Existing? | Staking wizard or skip | +| 3 | Download & Setup | Download tarball, extract, create directories, symlinks, run GenVM setup | +| 4 | Environment (.env) | RPC URL, WebSocket URL, LLM key placeholder, password placeholder | +| 5 | Node Config (config.yaml) | Validator address, operator address, ports | +| 6 | Operator Key | Upload keystore (method depends on Step 0) or generate new | +| 7 | Start WebDriver | `docker compose up -d`, wait for healthy | +| 8 | Run Doctor Check | Verify all configuration | +| 9 | Deployment Method | Systemd (recommended), Docker, or manual | +| 10 | Verify Node Running | Health check, sync status | +| 11 | Monitoring (Optional) | Enable telemetry push | + +## Key Decision Points + +1. **Server location?** → Local / Remote SSH / GCP / AWS / Azure / Other cloud +2. **New validator?** → Staking wizard or skip +3. **.env source?** → Copy from previous / Create new +4. **Config source?** → Use example (recommended) / Copy from previous +5. **Operator key?** → Upload keystore.json / Upload keystore directory / Copy from previous / Generate new +6. **Deployment?** → Systemd (recommended) / Docker / Manual +7. **Monitoring?** → Enable / Skip + +## Critical Input Rules + +**IMPORTANT**: When collecting user inputs, follow these rules: + +### .env Configuration (Step 3) - Ask via Wizard +Use AskUserQuestion with these options (tool requires minimum 2 options): +- **RPC URL** - Options: ["Skip for now", "I'll enter my URL"] +- **WebSocket URL** - Options: ["Skip for now", "I'll enter my URL"] + +**IMPORTANT**: The "Other" text field in AskUserQuestion does not work reliably. When user selects "I'll enter my URL", follow up with a **plain text question** asking them to type the URL directly. + +Example flow: +``` +Step 1: AskUserQuestion + Question: "Do you have the GenLayer Chain RPC URL?" + Options: + - "Skip for now" (will need to configure manually later) + - "I'll enter my URL" + +Step 2: If user selected "I'll enter my URL", ask: + "Please enter the RPC URL:" + [User types URL directly in chat] +``` + +### config.yaml Configuration (Step 4) - Node Identity Group +These values are configured in config.yaml during the Node Identity group: +- **Validator Wallet Address** - Ask in Group 1: Node Identity +- **Operator Address** - Ask in Group 1: Node Identity (will be set after importing operator key) + +### Sensitive Values - NEVER Ask for These +These values must NEVER be collected by Claude. Generate .env with placeholders, then ask user to update manually on the VM: +- **LLM API Key** - Generate placeholder: `YOUR_API_KEY_HERE` +- **Node Password** - Generate placeholder: `YOUR_PASSWORD_HERE` + +After generating .env, instruct user to: +1. SSH to the VM +2. Edit the .env file manually to set sensitive values +3. Confirm when done + +## Secret Masking Policy + +**CRITICAL**: When displaying any output that may contain secret values, they MUST be masked. + +### What Qualifies as a Secret +- **LLM API Keys**: `OPENAIKEY`, `HEURISTKEY`, `ANTHROPICKEY`, `GEMINIKEY`, etc. +- **Passwords**: `NODE_PASSWORD`, export passphrases +- **Auth Tokens**: Monitoring credentials, API tokens +- **Private Keys**: Never displayed at all + +### 🚨 FORBIDDEN OPERATIONS 🚨 + +**NEVER execute these types of commands that expose secrets:** + +```bash +# ❌ FORBIDDEN - DO NOT USE +grep 'OPENAIKEY' /opt/genlayer-node/.env +cat /opt/genlayer-node/.env | grep KEY +gcloud compute ssh ... --command="grep 'OPENAIKEY' /opt/genlayer-node/.env" +ssh username@host "cat /opt/genlayer-node/.env" +``` + +**Why this is forbidden:** +1. **Exposes secrets in command output** - Keys will be visible in plain text +2. **Violates security policy** - Secrets must NEVER be displayed unmasked +3. **Creates audit trail of secrets** - Command history will contain the secret +4. **Risk of screenshot/log exposure** - User may share output containing secrets + +**Instead, instruct the user to check values themselves:** +```bash +# ✅ CORRECT - Instruct user to run this on their VM +"To verify your API key is set, SSH to your VM and run: + grep 'OPENAIKEY' /opt/genlayer-node/.env +This will show the key value on your secure terminal." +``` + +### Masking Rules + +1. **When displaying .env file contents**: + - Mask all API keys showing only first 8 and last 4 characters + - Example: `OPENAIKEY=sk-proj-********...YblE` instead of full key + +2. **When displaying command output**: + - If output contains secrets, mask them before showing to user + - Example: `export OPENAIKEY=sk-proj-********...YblE` + +3. **When verifying configuration**: + - Show masked values: `OPENAIKEY: Set (sk-proj-********...YblE)` + - Never show the full secret value + +4. **In logs and error messages**: + - Ensure logs don't expose secrets + - Replace any secret values with `***MASKED***` + +5. **Remote command execution**: + - NEVER use `--command` flag with SSH/gcloud to read secrets + - NEVER pipe secret-containing files through remote commands + - NEVER execute grep/cat on files with secrets via remote tools + +### Implementation Examples + +**Reading .env file:** +```bash +# Before displaying, mask secrets using sed +cat /opt/genlayer-node/.env | sed -E 's/(KEY|PASSWORD|TOKEN)=([^[:space:]]{12}).*/\1=\2********.../' +``` + +**Verifying environment variables:** +```bash +# Show only that key is set, not the value +env | grep -E 'KEY|PASSWORD|TOKEN' | sed -E 's/=.*/=***MASKED***/' +``` + +**Creating systemd service:** +- NEVER include plain-text passwords in service files +- Use `EnvironmentFile` directive to load from .env +- Example: `ExecStart=/opt/genlayer-node/bin/genlayernode run --password "${NODE_PASSWORD}"` + +### When User Needs to See Full Value +If user needs the actual secret value: +1. Instruct them to read the file directly on their VM +2. Example: "To view your API key, run: `cat /opt/genlayer-node/.env | grep OPENAIKEY`" +3. Never display the full secret in the conversation + +### Can Offer Options +These can be presented as multiple choice: +- New validator or existing? +- LLM provider selection (Heurist, OpenAI, etc.) - select provider, NOT the key +- Operator key source (import, copy, generate) +- Deployment method (systemd, docker, manual) +- Enable monitoring? (yes/no) + +## Official Documentation + +For the latest official setup guide, see: +https://docs.genlayer.com/validators/setup-guide diff --git a/.claude/skills/genlayer-validator-setup/collaboration.yaml b/.claude/skills/genlayer-validator-setup/collaboration.yaml new file mode 100644 index 000000000..14b97bbba --- /dev/null +++ b/.claude/skills/genlayer-validator-setup/collaboration.yaml @@ -0,0 +1,95 @@ +# Collaboration: skill dependencies and composition + +name: genlayer-validator-setup +version: "1.1.0" + +dependencies: + - name: nodejs + description: "Node.js v18+ must be installed" + check: "node --version | grep -E 'v(1[89]|[2-9][0-9])'" + install: "curl -fsSL https://deb.nodesource.com/setup_20.x | sudo -E bash - && sudo apt install -y nodejs" + + - name: docker + description: "Docker must be installed and running" + check: "docker info" + install: "curl -fsSL https://get.docker.com | sh && sudo usermod -aG docker $USER" + + - name: docker-compose + description: "Docker Compose must be available" + check: "docker compose version" + install: "Usually included with Docker. If missing, install docker-compose-plugin" + + - name: python3 + description: "Python 3 must be installed" + check: "python3 --version" + install: "sudo apt install -y python3" + + - name: python3-pip + description: "pip3 must be installed for GenVM setup" + check: "pip3 --version" + install: "sudo apt install -y python3-pip" + + - name: python3-venv + description: "python3-venv must be installed for GenVM setup" + check: "python3 -m venv --help" + install: "sudo apt install -y python3-venv" + + - name: wget + description: "wget must be installed for downloading node binaries" + check: "wget --version" + install: "sudo apt install -y wget" + + - name: tar + description: "tar must be installed for extracting archives" + check: "tar --version" + install: "sudo apt install -y tar" + + - name: jq + description: "jq is recommended for JSON parsing" + check: "jq --version" + install: "sudo apt install -y jq" + + - name: curl + description: "curl is needed for health checks and API calls" + check: "curl --version" + install: "sudo apt install -y curl" + +composition: + - when: "First-time validator setup" + sequence: + - genlayer-validator-setup + + - when: "Setup with monitoring" + sequence: + - genlayer-validator-setup + - genlayer-validator-monitor + + - when: "Update existing validator" + sequence: + - genlayer-validator-update + +triggers: + - pattern: "install node|setup validator|install validator" + suggest: genlayer-validator-setup + - pattern: "become validator|run validator|start validating" + suggest: genlayer-validator-setup + - pattern: "genlayer node|genlayer setup" + suggest: genlayer-validator-setup + - pattern: "42000 gen|stake gen|self stake" + suggest: genlayer-validator-setup + - pattern: "validator guide|validator tutorial" + suggest: genlayer-validator-setup + - pattern: "how to validate|how to run node" + suggest: genlayer-validator-setup + - pattern: "systemd service|create service|enable service" + suggest: genlayer-validator-setup + - pattern: "docker compose|docker deployment" + suggest: genlayer-validator-setup + - pattern: "import operator key|operator keystore" + suggest: genlayer-validator-setup + - pattern: "llm provider|llm api key|heurist|comput3|ionet" + suggest: genlayer-validator-setup + - pattern: "webdriver|web module" + suggest: genlayer-validator-setup + - pattern: "testnet asimov|testnet node" + suggest: genlayer-validator-setup diff --git a/.claude/skills/genlayer-validator-setup/pre-update-checklist.md b/.claude/skills/genlayer-validator-setup/pre-update-checklist.md new file mode 100644 index 000000000..3c70fc5a3 --- /dev/null +++ b/.claude/skills/genlayer-validator-setup/pre-update-checklist.md @@ -0,0 +1,210 @@ +# Pre-Update Validation Checklist + +This checklist MUST be executed before starting any validator node update to catch known edge cases proactively. + +## Phase 1: Current Node Analysis + +### 1.1 Check Current LLM Configuration +**Purpose:** Detect if OpenAI is used but not enabled (edge: openai-backend-disabled) + +```bash +# Check which LLM key is set in .env +grep -E '(HEURISTKEY|COMPUT3KEY|IOINTELLIGENCEKEY|OPENAIKEY|LIBERTAI_API_KEY|ANTHROPICKEY|GEMINIKEY)=' /opt/genlayer-node/.env | grep -v '^#' | grep -v '=$' + +# For each non-empty key, check if that provider is enabled +# Example for OpenAI: +if grep -q 'OPENAIKEY=' /opt/genlayer-node/.env | grep -v '=$'; then + grep -A 2 'openai:' /opt/genlayer-node/third_party/genvm/config/genvm-module-llm.yaml | grep 'enabled' + # If shows "enabled: false" → FLAG FOR FIX +fi +``` + +**Action if detected:** Note that OpenAI will need to be enabled in new version. + +### 1.2 Check Current Database Structure +**Purpose:** Detect if database is not shared between patch versions (edge: database-not-shared-patch-versions) + +```bash +# Check if current installation has separate databases +ls -la /opt/genlayer-node/v0.4.*/data/node/genlayer.db 2>/dev/null +readlink /opt/genlayer-node/v0.4.*/data/node/genlayer.db 2>/dev/null + +# If both show as directories (not symlinks) → FLAG FOR FIX +``` + +**Action if detected:** Plan to create shared database structure during update. + +### 1.3 Record Current Sync State +**Purpose:** Baseline to verify new version syncs correctly + +```bash +# Record current version and sync block +curl -s http://localhost:9153/health | jq -r '.node_version, .checks.validating.error' +curl -s http://localhost:9153/metrics | grep 'genlayer_node_synced_block' +``` + +**Action:** Save this information to compare after update. + +### 1.4 Verify Node is Running +**Purpose:** Confirm we're not stopping a non-running node (edge: high-downtime-update) + +```bash +sudo systemctl status genlayer-node --no-pager +``` + +**Action if NOT running:** Different procedure - no downtime concern, but check why it's not running. + +## Phase 2: Pre-Download Preparation + +### 2.1 Check Disk Space +**Purpose:** Ensure enough space for new version (edge: not explicitly documented but critical) + +```bash +df -h /opt/genlayer-node +# Need at least 5GB free for new version + shared DB growth +``` + +**Action if low:** Clean up old versions or warn user. + +### 2.2 Verify Prerequisites Still Met +**Purpose:** Ensure system hasn't degraded since initial install + +```bash +# Python with pip and venv +python3 --version && pip3 --version && python3 -m venv --help + +# Docker +docker --version && docker compose version +``` + +**Action if missing:** Reinstall prerequisites before proceeding. + +## Phase 3: Post-Download Validation + +### 3.1 Verify GenVM Setup Completion +**Purpose:** Ensure slow GenVM setup completed successfully (edge: setup-py-failed) + +```bash +ls -la /opt/genlayer-node/${NEW_VERSION}/third_party/genvm/bin/genvm +ls -la /opt/genlayer-node/${NEW_VERSION}/third_party/genvm/bin/genvm-modules +``` + +**Action if missing:** Re-run setup.py, don't proceed to switch. + +### 3.2 Check LLM Config in New Version +**Purpose:** Proactively fix OpenAI disabled issue BEFORE switching (edge: openai-backend-disabled) + +```bash +# If OpenAI key was found in current .env: +grep -A 2 'openai:' /opt/genlayer-node/${NEW_VERSION}/third_party/genvm/config/genvm-module-llm.yaml | grep 'enabled' + +# If disabled, enable it NOW before switching: +if [ "$USING_OPENAI" = "true" ]; then + sed -i '/^ openai:/,/^ / s/enabled: false/enabled: true/' \ + /opt/genlayer-node/${NEW_VERSION}/third_party/genvm/config/genvm-module-llm.yaml +fi +``` + +**Action:** Fix BEFORE switching versions. + +### 3.3 Verify Shared Database Structure +**Purpose:** Ensure new version uses shared DB (edge: database-not-shared-patch-versions) + +```bash +# Check that symlink was created correctly +readlink /opt/genlayer-node/${NEW_VERSION}/data/node/genlayer.db +# Should point to /opt/genlayer-node/v0.4/data/node/genlayer.db + +# Verify shared DB exists +ls -la /opt/genlayer-node/v0.4/data/node/genlayer.db +``` + +**Action if wrong:** Fix structure before switching. + +## Phase 4: Pre-Switch Final Checks + +### 4.1 Verify WebDriver Ready +**Purpose:** Ensure WebDriver won't cause startup failure (edge: webdriver-not-healthy) + +```bash +docker inspect --format='{{.State.Health.Status}}' genlayer-node-webdriver +# Should be 'healthy' +``` + +**Action if not healthy:** Fix before switching. + +### 4.2 Doctor Check on New Version (Dry Run) +**Purpose:** Test new version without committing to it + +```bash +# Temporarily point to new version (without stopping old node) +cd /opt/genlayer-node/${NEW_VERSION} +source .env +./bin/genlayernode doctor +``` + +**Action if fails:** Fix issues before switching. + +## Phase 5: Post-Switch Validation + +### 5.1 Verify Version Switched +```bash +curl -s http://localhost:9153/health | jq -r '.node_version' +# Should show new version +``` + +### 5.2 Verify Sync Progressing +```bash +# Wait 30 seconds, then check sync increased +sleep 30 +curl -s http://localhost:9153/metrics | grep 'genlayer_node_synced_block' +# Should be higher than pre-update baseline +``` + +### 5.3 Check LLM Module Started +```bash +# Should NOT see "module_failed_to_start" errors +sudo journalctl -u genlayer-node --since '2 minutes ago' --no-pager | grep -i 'llm\|genvm is ready' +# Should see "genvm is ready" +``` + +## Automation Recommendation + +This checklist should be encoded into the skill as mandatory validation steps: + +```yaml +# In validations.yaml +pre_update_validations: + - id: check-llm-provider-enabled + when: before_version_switch + check: | + # Check if LLM provider in use is enabled in new version + action: Enable if needed + + - id: verify-shared-database + when: before_version_switch + check: | + # Verify new version uses shared DB + action: Create shared structure if needed + + - id: verify-genvm-setup-complete + when: before_version_switch + check: | + # Ensure GenVM binaries present + action: Re-run setup.py if missing +``` + +## Summary + +**Current State:** +- Edge cases documented in sharp-edges.yaml +- But not actively checked during execution +- Issues discovered reactively after failure + +**Target State:** +- Edge cases checked proactively before each phase +- Issues prevented before they cause failures +- Validation failures stop the process early + +**Implementation:** +Each phase of the update should explicitly check relevant edge cases from sharp-edges.yaml before proceeding. \ No newline at end of file diff --git a/.claude/skills/genlayer-validator-setup/sharp-edges.yaml b/.claude/skills/genlayer-validator-setup/sharp-edges.yaml new file mode 100644 index 000000000..402d27fef --- /dev/null +++ b/.claude/skills/genlayer-validator-setup/sharp-edges.yaml @@ -0,0 +1,687 @@ +# Sharp edges for genlayer-validator-setup +# +# CRITICAL: These edge cases MUST be actively checked during skill execution, +# not just used for reactive diagnosis after failures. +# +# HOW TO USE THIS FILE: +# 1. BEFORE each major phase, review relevant edges +# 2. PROACTIVELY check for edge case conditions +# 3. FIX or WARN before proceeding +# 4. Document when each edge was checked +# +# Example: Before starting update, explicitly check: +# - Is OpenAI key set but provider disabled? → Fix before switching +# - Is database structure incorrect? → Fix before switching +# - Is GenVM setup complete? → Verify before switching +# +# BAD: Wait for node to fail, then search edges for diagnosis +# GOOD: Check edges before each step, prevent failures +# +# See pre-update-checklist.md for structured validation approach. + +edges: + # ============================================================================ + # PREREQUISITES + # ============================================================================ + + - id: wrong-architecture + description: "Installing on ARM64 instead of AMD64" + detect: | + uname -m + # Must return x86_64, not aarch64 or arm64 + impact: "Binaries will not execute. Container won't start." + fix: | + Use an AMD64 Linux server: + - AWS: t3/m5/c5 instances (not Graviton) + - GCP: n1/n2 instances + - Azure: D/E series + + If on Mac M1/M2, use a cloud server or VM. + severity: critical + + - id: insufficient-ram + description: "Server has less than 16GB RAM" + detect: | + free -g | grep Mem | awk '{print $2}' + # Should be >= 16 + impact: "Node may crash under load or during contract execution." + fix: | + Upgrade to a server with at least 16GB RAM. + Recommended: 32GB for production validators. + severity: high + + - id: nodejs-not-installed + description: "Node.js is not installed or version too old" + detect: | + node --version + # Should be v18 or higher + impact: "Cannot install genlayer CLI." + fix: | + Install Node.js 18+: + curl -fsSL https://deb.nodesource.com/setup_20.x | sudo -E bash - + sudo apt install -y nodejs + severity: critical + + - id: docker-not-installed + description: "Docker or Docker Compose not installed" + detect: | + docker --version + docker compose version + impact: "Cannot run WebDriver or Docker-based deployment." + fix: | + Install Docker: + curl -fsSL https://get.docker.com | sh + sudo usermod -aG docker $USER + # Log out and back in + severity: critical + + # ============================================================================ + # WALLET AND STAKING + # ============================================================================ + + - id: insufficient-gen-balance + description: "Wallet has less than 42,000 GEN for staking" + detect: | + genlayer staking balance --address YOUR_ADDRESS + impact: "Cannot create validator. Staking wizard will fail." + fix: | + Acquire at least 42,000 GEN tokens: + - Purchase on supported exchanges + - Transfer from another wallet + - Use testnet faucet (for testnet only) + severity: critical + + - id: keystore-export-forgotten + description: "Didn't export operator keystore during wizard" + detect: | + ls /path/to/operator-keystore.json + impact: "Cannot import operator key to node." + fix: | + Re-run parts of the wizard or use the account new command + to generate a new operator key, then update the operator + address in your validator settings. + severity: high + + - id: wrong-network-selected + description: "Selected wrong network in staking wizard" + detect: | + Check the RPC URL in your config matches the network + you selected during wallet creation. + impact: "Validator won't be recognized on the correct network." + fix: | + Re-run staking wizard with correct network selection + or manually update configuration to match. + severity: critical + + # ============================================================================ + # DOWNLOAD AND EXTRACTION + # ============================================================================ + + - id: download-failed + description: "Node binary download failed" + detect: | + ls genlayer-node-linux-amd64-*.tar.gz + # Check file size is reasonable (>50MB) + impact: "Cannot proceed with installation." + fix: | + Check network connectivity: + curl -I https://storage.googleapis.com + + Retry download or use alternative mirror. + severity: high + + - id: extraction-failed + description: "Tar extraction failed or incomplete" + detect: | + ls -la ${VERSION}/bin/genlayernode + ls -la ${VERSION}/third_party/genvm/bin/ + impact: "Missing binaries, node won't start." + fix: | + Re-download and extract: + rm -rf ${VERSION} + tar -xzvf genlayer-node-linux-amd64-${VERSION}.tar.gz -C ./${VERSION} + severity: high + + - id: setup-py-failed + description: "GenVM setup.py failed to download dependencies" + detect: | + ls ${VERSION}/third_party/genvm/bin/genvm + ls ${VERSION}/third_party/genvm/bin/genvm-modules + impact: "GenVM cannot execute intelligent contracts." + fix: | + Check Python and pip are installed: + python3 --version + pip3 --version + + Re-run setup: + cd ${VERSION} && python3 ./third_party/genvm/bin/setup.py + severity: critical + + # ============================================================================ + # CONFIGURATION + # ============================================================================ + + - id: invalid-yaml + description: "config.yaml has syntax errors" + detect: | + python3 -c "import yaml; yaml.safe_load(open('configs/node/config.yaml'))" + impact: "Node will fail to start with config parse error." + fix: | + Validate YAML syntax: + - Check indentation (use spaces, not tabs) + - Ensure colons have space after them + - Quote strings with special characters + severity: high + + - id: wrong-contract-addresses + description: "Using outdated or wrong consensus contract addresses" + detect: | + grep contractmainaddress configs/node/config.yaml + # Compare with official documentation + impact: "Node cannot interact with consensus, transactions fail." + fix: | + Use the official contract addresses from docs: + contractmainaddress: "0x67fd4aC71530FB220E0B7F90668BAF977B88fF07" + contractdataaddress: "0xB6E1316E57d47d82FDcEa5002028a554754EF243" + severity: critical + + - id: rpc-url-unreachable + description: "RPC or WebSocket URL is not accessible" + detect: | + curl -X POST ${RPC_URL} -H "Content-Type: application/json" \ + -d '{"jsonrpc":"2.0","method":"eth_blockNumber","params":[],"id":1}' + impact: "Node cannot sync with the network." + fix: | + Verify RPC URL is correct and accessible: + 1. Check URL spelling + 2. Verify network connectivity + 3. Check if provider is operational + severity: critical + + # ============================================================================ + # KEY IMPORT + # ============================================================================ + + - id: wrong-passphrase + description: "Using wrong passphrase for keystore import" + detect: | + Error message: "could not decrypt key with given passphrase" + impact: "Cannot import operator key." + fix: | + Use the exact passphrase set during wizard export. + If forgotten, generate a new operator key and update + your validator's operator address. + severity: high + + - id: keystore-permissions + description: "Keystore file has wrong permissions" + detect: | + ls -la /path/to/operator-keystore.json + # Should be readable by current user + impact: "Import command cannot read the file." + fix: | + Fix permissions: + chmod 600 /path/to/operator-keystore.json + severity: medium + + # ============================================================================ + # LLM CONFIGURATION + # ============================================================================ + + - id: no-llm-key-set + description: "No LLM provider API key configured" + detect: | + env | grep -E "(HEURISTKEY|COMPUT3KEY|IOINTELLIGENCE_API_KEY)" + impact: "Node cannot execute intelligent contracts." + fix: | + Set at least one LLM API key: + export HEURISTKEY='your_key' + + Add to shell profile for persistence: + echo "export HEURISTKEY='your_key'" >> ~/.bashrc + severity: critical + + - id: llm-key-invalid + description: "LLM API key is invalid or expired" + detect: | + Check LLM module logs for authentication errors. + impact: "Contract executions fail with LLM errors." + fix: | + Verify API key in provider dashboard. + Generate new key if needed. + severity: high + + - id: openai-backend-disabled + description: "OpenAI backend disabled in GenVM config despite OPENAIKEY being set" + detect: | + # PROACTIVE CHECK (before switching versions): + # 1. Check which LLM key is set in .env + grep -E '(OPENAIKEY)=' .env | grep -v '^#' | grep -v '=$' + + # 2. If OPENAIKEY is set, check if OpenAI is enabled in GenVM config + grep -A 5 'openai:' third_party/genvm/config/genvm-module-llm.yaml | grep 'enabled: false' + + # REACTIVE DETECTION (after node fails to bootstrap): + # Node logs show: "failed to start module via manager error=\"starting module Llm: manager request failed: 500" + journalctl -u genlayer-node | grep -i "module_failed_to_start\|starting module Llm" + impact: | + ⚠️ CRITICAL BOOTSTRAP FAILURE - NODE NEVER BECOMES OPERATIONAL ⚠️ + + This is NOT a runtime failure - this is a COMPLETE BOOTSTRAP FAILURE: + - Node NEVER successfully starts + - Lifecycle worker fails to initialize + - Node enters crash loop (systemd keeps restarting it) + - INFINITE DOWNTIME until manually fixed + - Validator is 100% offline + - NO validations, NO consensus participation, NO rewards + - Health endpoint unreachable + - RPC endpoints never become available + + Timeline: + - 08:44:02: Node service started + - 08:45:35: LLM module fails to start (attempt 3) + - 08:47:00: Lifecycle worker failed to start + - 08:47:00: Node crashed + - 08:47:10: Systemd auto-restart → Same failure cycle repeats + + IMPACT ON UPDATE: + If this occurs during an update from working node: + - Old version stopped (as planned) + - New version FAILS to bootstrap (unexpected) + - Result: Complete outage instead of 10-15 sec downtime + - Validator misses ALL validations until manually fixed + + WHY THIS HAPPENS: + Downloaded v0.4.4 tarball includes GenVM config with OpenAI disabled by default. + Enabled providers: Heurist, Comput3, io.net, LibertAI + If you're using OpenAI, you MUST enable it manually after extraction. + fix: | + PROACTIVE FIX (during update preparation, BEFORE switching): + ================================================================ + After extracting new version, BEFORE switching symlinks: + + # Check if current .env uses OpenAI + if grep -q 'OPENAIKEY=' /opt/genlayer-node/.env | grep -v '=$'; then + echo "OpenAI key detected - enabling in new version" + sed -i '/^ openai:/,/^ / s/enabled: false/enabled: true/' \ + /opt/genlayer-node/${NEW_VERSION}/third_party/genvm/config/genvm-module-llm.yaml + fi + + # Verify it's enabled + grep -A 2 'openai:' /opt/genlayer-node/${NEW_VERSION}/third_party/genvm/config/genvm-module-llm.yaml + # Should show: enabled: true + + REACTIVE FIX (after node failed to bootstrap): + ============================================== + 1. Stop the failing node: + sudo systemctl stop genlayer-node + + 2. Enable OpenAI in GenVM config: + sed -i '/^ openai:/,/^ / s/enabled: false/enabled: true/' \ + /opt/genlayer-node/third_party/genvm/config/genvm-module-llm.yaml + + 3. Verify the change: + grep -A 2 'openai:' /opt/genlayer-node/third_party/genvm/config/genvm-module-llm.yaml + # Should show: enabled: true + + 4. Restart the node: + sudo systemctl start genlayer-node + + 5. Verify bootstrap succeeds: + sudo journalctl -u genlayer-node -f --no-hostname + # Should see: "genvm is ready" + # Should NOT see: "module_failed_to_start" + + 6. Verify node is operational: + curl -s http://localhost:9153/health | jq '.status' + # Should show: "up" or "down" (syncing) but NOT connection refused + severity: critical + when_to_check: | + MANDATORY CHECKS: + 1. During update preparation (after extracting new version) + 2. After any version switch (verify bootstrap succeeds) + 3. When setting up new installation with OpenAI + + NEVER skip this check if using OpenAI! + + # ============================================================================ + # RUNTIME + # ============================================================================ + + - id: port-already-in-use + description: "Required ports (9151, 9153, 4444) already in use" + detect: | + lsof -i :9151 + lsof -i :9153 + lsof -i :4444 + impact: "Node or WebDriver cannot start." + fix: | + Kill conflicting processes: + lsof -i :PORT + kill -9 PID + + Or change ports in config.yaml. + severity: high + + - id: webdriver-not-running + description: "WebDriver container not started" + detect: | + docker ps | grep webdriver + curl http://localhost:4444/status + impact: "Web module cannot execute, contracts fail." + fix: | + Start WebDriver: + docker compose up -d + + Check logs: + docker logs genlayer-node-webdriver + severity: high + + - id: node-not-syncing + description: "Node started but not syncing blocks" + detect: | + curl -s http://localhost:9153/health | jq .status + curl -s http://localhost:9153/metrics | grep synced + impact: "Validator cannot participate in consensus." + fix: | + Check: + 1. RPC URL is correct and accessible + 2. Network has sufficient peers + 3. Firewall allows outbound connections + + Check logs for errors. + severity: high + + - id: docker-env-not-sourced + description: "Running docker compose without sourcing .env" + detect: | + # Check if running without environment variables + docker compose config | grep NODE_VERSION + impact: "Docker containers start with wrong or missing configuration." + fix: | + Always source .env before docker compose: + source .env && docker compose --profile node up -d + severity: high + + - id: screen-tmux-not-used + description: "Running node in SSH session without screen/tmux" + detect: | + # Check if running in screen or tmux + echo $STY $TMUX + impact: "Node stops when SSH session disconnects." + fix: | + Use screen or tmux for persistent sessions: + + # Using screen + screen -S genlayer + ./bin/genlayernode run ... + # Detach: Ctrl+A, D + # Reattach: screen -r genlayer + + # Using tmux + tmux new -s genlayer + ./bin/genlayernode run ... + # Detach: Ctrl+B, D + # Reattach: tmux attach -t genlayer + + OR use systemd service (recommended for production): + See create-systemd-service pattern. + severity: high + + # ============================================================================ + # SYSTEMD SERVICE (from infrastructure patterns) + # ============================================================================ + + - id: systemd-service-not-enabled + description: "Systemd service created but not enabled for auto-start" + detect: | + systemctl is-enabled genlayer-node + impact: "Node won't start automatically after server reboot." + fix: | + Enable the service: + sudo systemctl enable genlayer-node + + Then verify: + sudo systemctl is-enabled genlayer-node + severity: medium + + - id: env-file-not-sourced + description: "Running node without environment file loaded" + detect: | + # Check if required env vars are set + [ -z "$GENLAYERNODE_ROLLUP_GENLAYERCHAINRPCURL" ] && echo "not set" + impact: "Node fails to connect to rollup or consensus contracts." + fix: | + For manual runs, source the .env file first: + source /opt/genlayer-node/.env + ./bin/genlayernode run --password "$NODE_PASSWORD" + + For systemd, ensure EnvironmentFile is set in service file. + severity: high + + - id: wrong-llm-env-var-name + description: "Using wrong environment variable name for LLM provider" + detect: | + # io.net uses IOINTELLIGENCEKEY (no underscore), not IOINTELLIGENCE_API_KEY + env | grep -E "IOINTELLIGENCE" + impact: "LLM module fails to authenticate." + fix: | + Correct environment variable names: + - Heurist: HEURISTKEY + - Comput3: COMPUT3KEY + - io.net: IOINTELLIGENCEKEY (not IOINTELLIGENCE_API_KEY) + - OpenAI: OPENAIKEY + - LibertAI: LIBERTAI_API_KEY + - Anthropic: ANTHROPICKEY + - Google: GEMINIKEY + severity: high + + - id: data-directory-permissions + description: "Data directory has wrong ownership" + detect: | + ls -la /opt/genlayer-node/data/ + # Should be owned by the user running the node + impact: "Node cannot write to data directory, fails to start." + fix: | + Fix ownership: + sudo chown -R $USER:$USER /opt/genlayer-node/data/ + + Or for systemd service user: + sudo chown -R ansible:ansible /opt/genlayer-node/data/ + severity: high + + - id: webdriver-not-healthy + description: "WebDriver container running but not healthy" + detect: | + docker inspect --format='{{.State.Health.Status}}' genlayer-node-webdriver + # Should return 'healthy' + impact: "Web module cannot execute, contracts fail." + fix: | + Check WebDriver logs: + docker logs genlayer-node-webdriver + + Restart if needed: + docker compose down + docker compose up -d + + Wait for healthy: + until docker inspect --format='{{.State.Health.Status}}' genlayer-node-webdriver | grep -q 'healthy'; do sleep 2; done + severity: high + + - id: missing-python-packages + description: "Missing python3-pip or python3-venv packages" + detect: | + dpkg -l | grep -E "python3-pip|python3-venv" + impact: "GenVM setup.py fails to install dependencies." + fix: | + Install required Python packages: + sudo apt update + sudo apt install -y python3 python3-pip python3-venv + severity: high + + - id: new-operator-not-funded + description: "Generated new operator key but didn't fund it" + detect: | + # Check operator balance is zero or very low + # Node will fail to submit transactions + journalctl -u genlayer-node | grep -i "insufficient funds" + impact: "Node cannot submit transactions (activate, propose, vote). Validator will miss duties." + fix: | + 1. Get operator address from node logs or keystore + 2. Send ETH to the operator address for gas fees + 3. Recommended minimum: 0.1 ETH for initial operations + + To find operator address: + cat /opt/genlayer-node/data/node/keystore/*/address + + Or check logs: + journalctl -u genlayer-node | grep "operator" + severity: critical + + - id: new-operator-not-registered + description: "Generated new operator key but didn't update validator settings" + detect: | + # Check if operator address in config matches what's registered + # Node will show unauthorized errors + journalctl -u genlayer-node | grep -i "unauthorized\|not authorized\|operator mismatch" + impact: "Node cannot act on behalf of validator. All transactions will be rejected." + fix: | + Update validator's operator address: + + Option 1: Using staking UI + - Go to staking dashboard + - Find your validator + - Update operator address to the new one + + Option 2: Using genlayer CLI + genlayer staking update-operator --validator YOUR_VALIDATOR_ADDRESS --new-operator NEW_OPERATOR_ADDRESS + severity: critical + + - id: consensus-genesis-not-set + description: "Consensus genesis block not configured" + detect: | + grep GENLAYERNODE_CONSENSUS_GENESIS .env + # Should have a value (usually 0 for testnet) + impact: "Node may sync from wrong starting point." + fix: | + Add to .env file: + GENLAYERNODE_CONSENSUS_GENESIS=0 + + For testnet, genesis is typically 0. + severity: medium + + - id: strip-components-extraction + description: "Extracting tarball without --strip-components" + detect: | + # Check if node was extracted with nested directory + ls /opt/genlayer-node/genlayer-node-*/ + impact: "Binaries at wrong path, commands fail." + fix: | + Use --strip-components=1 when extracting: + sudo tar -xzvf genlayer-node.tar.gz -C /opt/genlayer-node --strip-components=1 + + Or move files to correct location: + sudo mv /opt/genlayer-node/genlayer-node-*/* /opt/genlayer-node/ + severity: medium + +T # ============================================================================ + # UPDATE PROCEDURE + # ============================================================================ + + - id: high-downtime-update + description: "Stopping old node before preparing new version causes 3-4 minute downtime" + detect: | + # Detect if update procedure stops node before preparation + # Check if these steps happen in wrong order: + # 1. systemctl stop (WRONG - should be last) + # 2. Download new version + # 3. GenVM setup (~2 minutes) + # 4. systemctl start + impact: | + CRITICAL VALIDATOR IMPACT: + - 3-4 minutes downtime vs 10-15 seconds with correct procedure + - Missed ~12-24 validation opportunities (at 10-20s block times) + - Lost consensus participation in current epoch + - Missed rewards from validations during downtime + - Validator needs to re-prime after reconnecting + - Potential slashing penalties for extended downtime + fix: | + CORRECT UPDATE PROCEDURE (Zero-Downtime): + + Phase 1: PREPARE WHILE OLD NODE RUNS (No Downtime) + =================================================== + 1. Download new version to /tmp + 2. Create new version directory + 3. Extract tarball + 4. Run GenVM setup (THIS IS THE SLOW PART - 2+ minutes) + 5. Copy config.yaml and .env + 6. Enable OpenAI in GenVM config if needed + 7. Create data directory and symlinks to shared DB + 8. Copy keystore + + Phase 2: QUICK SWITCH (10-15 seconds downtime) + ============================================== + 1. Stop old node: systemctl stop genlayer-node + 2. Update symlinks (very fast - <1 second) + 3. Start new node: systemctl start genlayer-node + + KEY PRINCIPLE: Never stop old node until new version is 100% ready to start. + + See update-procedure.md for detailed commands. + severity: critical + validator_impact: "missed validations, lost rewards, priming delay, potential slashing" + + - id: database-not-shared-patch-versions + description: "Database copied instead of shared between v0.4.x patch versions" + detect: | + # Check if each patch version has its own database instead of shared + ls -la /opt/genlayer-node/v0.4.3/data/node/genlayer.db + ls -la /opt/genlayer-node/v0.4.4/data/node/genlayer.db + # If both are directories (not symlinks), they're not shared + + # Correct structure should show: + # v0.4.3/data/node/genlayer.db -> ../../../v0.4/data/node/genlayer.db (symlink) + # v0.4.4/data/node/genlayer.db -> ../../../v0.4/data/node/genlayer.db (symlink) + impact: | + - Wasted disk space (duplicate databases) + - Each version has different sync state + - Cannot switch between patch versions easily + - Future v0.4.x updates will need their own copy + - When upgrading improperly configured old installations, sync state diverges + fix: | + FIX EXISTING INSTALLATION WITH SEPARATE DATABASES: + + 1. Stop the node: + sudo systemctl stop genlayer-node + + 2. Create shared v0.4 directory: + sudo mkdir -p /opt/genlayer-node/v0.4/data/node + sudo chown -R $USER:$USER /opt/genlayer-node/v0.4 + + 3. Move the MOST RECENT database to shared location: + # Use the database from the version with highest sync block + sudo mv /opt/genlayer-node/v0.4.4/data/node/genlayer.db /opt/genlayer-node/v0.4/data/node/ + + 4. Replace old databases with symlinks: + sudo rm -rf /opt/genlayer-node/v0.4.3/data/node/genlayer.db + ln -s /opt/genlayer-node/v0.4/data/node/genlayer.db /opt/genlayer-node/v0.4.3/data/node/genlayer.db + ln -s /opt/genlayer-node/v0.4/data/node/genlayer.db /opt/genlayer-node/v0.4.4/data/node/genlayer.db + + 5. Verify both versions point to shared DB: + readlink /opt/genlayer-node/v0.4.3/data/node/genlayer.db + readlink /opt/genlayer-node/v0.4.4/data/node/genlayer.db + # Both should output: /opt/genlayer-node/v0.4/data/node/genlayer.db + + 6. Start the node: + sudo systemctl start genlayer-node + + STRUCTURE FOR NEW INSTALLATIONS: + + For major.minor versions (v0.4.x), use shared database: + /opt/genlayer-node/v0.4/data/node/genlayer.db (shared DB) + /opt/genlayer-node/v0.4.3/data/node/genlayer.db -> symlink to shared + /opt/genlayer-node/v0.4.4/data/node/genlayer.db -> symlink to shared + + Keystore and logs remain version-specific (not shared). + severity: high + note: "This issue typically occurs when upgrading from old installations that weren't set up with shared storage" diff --git a/.claude/skills/genlayer-validator-setup/skill.yaml b/.claude/skills/genlayer-validator-setup/skill.yaml new file mode 100644 index 000000000..45e9a4793 --- /dev/null +++ b/.claude/skills/genlayer-validator-setup/skill.yaml @@ -0,0 +1,1094 @@ +name: genlayer-validator-setup +kind: setup +version: "1.3.0" +description: "Interactive wizard to set up a GenLayer validator node on Linux." +severity: high +tags: + - validator + - node + - installation + - blockchain + - genlayer + +purpose: | + Guide validators through complete GenLayer node installation on Linux servers. + Walks through prerequisites verification, wallet creation, software download, + configuration, key import, LLM setup, and node startup. + Supports both binary (systemd service) and Docker Compose deployment methods. + Provides interactive wizard for configuration with sensible defaults. + +owns: + - "Validator node installation from scratch" + - "Node configuration generation" + - "Operator key management" + - "LLM provider configuration" + - "Systemd service setup" + - "Telemetry/monitoring setup" + - "Node upgrades and version management" + +# Default configuration values (from infrastructure) +defaults: + network: testnet-asimov + # NOTE: rpc_url and websocket_url have NO defaults - user must provide + consensus_contract_main: "0x67fd4aC71530FB220E0B7F90668BAF977B88fF07" + consensus_contract_data: "0xB6E1316E57d47d82FDcEa5002028a554754EF243" + consensus_genesis: 4632386 + install_path: "/opt/genlayer-node" + data_dir: "./data/node" + node_rpc_port: 9151 + node_admin_port: 9155 + node_ops_port: 9153 + webdriver_port: 4444 + genvm_manager_url: "http://127.0.0.1:3999" + metrics_interval: "15s" + +# Required user configuration (no defaults) +required_inputs: + - rpc_url: "GenLayer Chain ZKSync HTTP RPC URL" + - websocket_url: "GenLayer Chain ZKSync WebSocket URL" + - validator_wallet_address: "From staking wizard or existing wallet" + - operator_address: "From keystore import or generate new" + - llm_api_key: "From chosen LLM provider" + +# Directory structure after installation +directory_structure: + install_path: "/opt/genlayer-node" + layout: + - path: "{VERSION}/" + description: "Version-specific directory containing all node files" + contents: + - "bin/genlayernode" + - "third_party/genvm/" + - "docker-compose.yaml" + - ".env" + - "data/node/genlayer.db" + - "data/node/keystore/" + - "data/node/logs/" + - "data/node/merkle/" + - "configs/node/config.yaml" + - path: "bin -> {VERSION}/bin" + description: "Symlink to current version binary" + - path: "third_party -> {VERSION}/third_party" + description: "Symlink to current version third_party" + - path: "data -> {VERSION}/data" + description: "Symlink to current version data" + - path: "configs -> {VERSION}/configs" + description: "Symlink to current version configs" + - path: "docker-compose.yaml -> {VERSION}/docker-compose.yaml" + description: "Symlink to current version docker-compose" + - path: ".env -> {VERSION}/.env" + description: "Symlink to current version .env" + - path: "alloy-config.river" + description: "Telemetry configuration (if monitoring enabled)" + +inputs_required: + - id: server_location + description: "Where the validator node will run" + type: choice + question: "Where will you run the validator node?" + options: + - label: "This machine (local setup)" + value: local + description: "Running validator on this computer" + - label: "Remote Linux server (SSH)" + value: remote-ssh + description: "Generic Linux server accessed via SSH" + - label: "Google Cloud Platform VM" + value: gcp + description: "GCP Compute Engine instance" + - label: "AWS EC2 Instance" + value: aws + description: "Amazon Web Services EC2 instance" + - label: "Azure VM" + value: azure + description: "Azure Virtual Machine" + - label: "Other cloud provider" + value: other-cloud + description: "DigitalOcean, Linode, Vultr, etc." + required: true + + - id: connection_details + description: "Connection information for remote server" + type: string + condition: "server_location != local" + question: "Provide connection details for your server" + help: | + For SSH: Enter username@hostname or username@IP + For GCP: Enter project-id/zone/instance-name + For AWS: Enter instance-id/region + For Azure: Enter resource-group/vm-name + required: true + + - id: is_new_validator + description: "Whether user needs to run staking wizard to become a validator" + type: boolean + question: "Do you need to create a new validator wallet and stake GEN tokens?" + options: + - label: "Yes, run staking wizard" + value: true + description: "I need to create validator wallet and stake 42,000+ GEN" + - label: "No, I already have a validator wallet" + value: false + description: "I already completed staking and have my operator keystore" + required: true + + - id: deployment_method + description: "How to run the node" + type: choice + question: "How would you like to run the node?" + options: + - label: "Systemd Service (Recommended)" + value: binary + description: "Run as a system service with auto-restart" + - label: "Docker Compose" + value: docker + description: "Run everything in Docker containers" + - label: "Manual (screen/tmux)" + value: manual + description: "Run manually in terminal session" + required: true + + - id: node_version + description: "Version of genlayer-node to install" + type: string + how_to_find: | + curl -s "https://storage.googleapis.com/storage/v1/b/gh-af/o?prefix=genlayer-node/bin/amd64" | \ + grep -o '"name": *"[^"]*"' | sed -n 's/.*\/\(v[^/]*\)\/.*/\1/p' | sort -ru | head -5 + required: true + + - id: validator_wallet_address + description: "Your validator wallet address" + type: string + source: "From staking wizard or existing wallet" + required: true + + - id: operator_address + description: "Your operator address" + type: string + source: "From wizard export, previous installation, or generate new" + required: true + + - id: operator_key_source + description: "Where to get the operator key" + type: choice + question: "How would you like to configure the operator key?" + options: + - label: "Import from staking wizard export" + value: import + description: "I have the operator-keystore.json from the wizard" + - label: "Copy from previous installation" + value: copy + description: "Copy keystore from existing node installation" + - label: "Generate new operator key" + value: generate + description: "Create a new operator key (requires updating validator settings)" + required: true + + - id: llm_provider + description: "LLM provider for intelligent contract execution" + type: choice + question: "Which LLM provider will you use?" + options: + - label: "Heurist" + value: heurist + env_var: "HEURISTKEY" + - label: "Comput3" + value: comput3 + env_var: "COMPUT3KEY" + - label: "io.net" + value: ionet + env_var: "IOINTELLIGENCEKEY" + - label: "OpenAI" + value: openai + env_var: "OPENAIKEY" + - label: "LibertAI" + value: libertai + env_var: "LIBERTAI_API_KEY" + - label: "Anthropic" + value: anthropic + env_var: "ANTHROPICKEY" + - label: "Google (Gemini)" + value: google + env_var: "GEMINIKEY" + required: true + + - id: llm_api_key + description: "API key for the chosen LLM provider" + type: secret + required: true + + - id: node_password + description: "Password to encrypt the operator keystore (min 8 characters)" + type: secret + required: true + + - id: config_source + description: "How to configure config.yaml" + type: choice + question: "How would you like to configure the node?" + options: + - label: "Interactive wizard (Recommended)" + value: wizard + description: "Answer questions to generate config.yaml" + - label: "Copy from previous version" + value: copy + description: "Use config.yaml from an existing installation" + - label: "Manual configuration" + value: manual + description: "I'll edit config.yaml manually" + required: true + + - id: enable_monitoring + description: "Enable telemetry push to central monitoring" + type: boolean + default: false + required: false + +# Configuration wizard questions +config_wizard: + sections: + - id: rollup + name: "Rollup Configuration (Required - No Defaults)" + questions: + - id: genlayerchainrpcurl + prompt: "GenLayer Chain RPC URL" + required: true + validation: "Must be a valid HTTP(S) URL - user must provide ZKSync RPC endpoint" + - id: genlayerchainwebsocketurl + prompt: "GenLayer Chain WebSocket URL" + required: true + validation: "Must be a valid WSS URL - user must provide ZKSync WebSocket endpoint" + + - id: node_identity + name: "Node Identity" + questions: + - id: validatorWalletAddress + prompt: "Validator Wallet Address" + source: "From staking wizard or existing" + validation: "Must be a valid Ethereum address (0x...)" + - id: operatorAddress + prompt: "Operator Address" + source: "From keystore import or generate" + validation: "Must be a valid Ethereum address (0x...)" + + - id: rpc_endpoints + name: "RPC Endpoints Configuration" + questions: + - id: rpc_enabled + prompt: "Enable RPC endpoints?" + type: boolean + default: true + - id: rpc_port + prompt: "RPC port" + type: number + default: 9151 + condition: "rpc_enabled == true" + - id: rpc_groups + prompt: "Which RPC endpoint groups to enable?" + type: multi_choice + default: ["genlayer", "ethereum", "zksync"] + options: + - label: "genlayer" + description: "gen_* methods (call, getContractSchema, etc.)" + - label: "genlayer_debug" + description: "gen_dbg_* methods (ping, load_test, trie)" + - label: "ethereum" + description: "eth_* proxy methods" + - label: "zksync" + description: "zks_* proxy methods" + condition: "rpc_enabled == true" + - id: rpc_custom_methods + prompt: "Configure individual methods? (Advanced)" + type: boolean + default: false + condition: "rpc_enabled == true" + + - id: ops_endpoints + name: "Operations Endpoints Configuration" + questions: + - id: ops_enabled + prompt: "Enable ops endpoints?" + type: boolean + default: true + - id: ops_port + prompt: "Ops port" + type: number + default: 9153 + condition: "ops_enabled == true" + - id: ops_metrics + prompt: "Enable /metrics endpoint?" + type: boolean + default: true + condition: "ops_enabled == true" + - id: ops_health + prompt: "Enable /health endpoint?" + type: boolean + default: true + condition: "ops_enabled == true" + - id: ops_balance + prompt: "Enable /balance endpoint?" + type: boolean + default: true + condition: "ops_enabled == true" + + - id: metrics + name: "Metrics Configuration" + condition: "ops_metrics == true" + questions: + - id: metrics_interval + prompt: "Default metrics collection interval" + type: string + default: "15s" + validation: "Duration format (e.g., 15s, 1m)" + - id: metrics_node_enabled + prompt: "Enable node metrics collector?" + type: boolean + default: true + - id: metrics_node_interval + prompt: "Node metrics interval (leave empty for default)" + type: string + default: "" + condition: "metrics_node_enabled == true" + - id: metrics_genvm_enabled + prompt: "Enable GenVM metrics collector?" + type: boolean + default: true + - id: metrics_genvm_interval + prompt: "GenVM metrics interval (leave empty for default)" + type: string + default: "" + condition: "metrics_genvm_enabled == true" + - id: metrics_webdriver_enabled + prompt: "Enable WebDriver metrics collector?" + type: boolean + default: true + - id: metrics_webdriver_interval + prompt: "WebDriver metrics interval (leave empty for default)" + type: string + default: "" + condition: "metrics_webdriver_enabled == true" + +patterns: + - id: verify-prerequisites + description: | + Check all required software is installed before proceeding. + commands: + - "uname -m | grep -E '^(x86_64|amd64)$'" + - "node --version" + - "npm --version" + - "docker --version" + - "docker compose version" + - "python3 --version" + - "pip3 --version" + - "python3 -m venv --help" + + - id: install-prerequisites-ubuntu + description: | + Install required packages on Ubuntu/Debian. + commands: + - "sudo apt update" + - "sudo apt install -y python3 python3-pip python3-venv wget curl jq tar" + + - id: install-genlayer-cli + description: | + Install the GenLayer CLI globally via npm. + command: "npm install -g genlayer" + + - id: create-validator-wallet + description: | + Run the interactive staking wizard to create validator wallet. + User must have 42,000+ GEN tokens. + command: "genlayer staking wizard" + outputs: + - "validator_wallet_address" + - "operator_keystore_path" + - "export_passphrase" + + - id: list-available-versions + description: | + List available node versions from the release bucket. + command: | + curl -s "https://storage.googleapis.com/storage/v1/b/gh-af/o?prefix=genlayer-node/bin/amd64" | \ + grep -o '"name": *"[^"]*"' | sed -n 's/.*\/\(v[^/]*\)\/.*/\1/p' | sort -ru | head -10 + + - id: download-and-extract + description: | + Download to /tmp, then extract to versioned directory structure. + commands: + - "export VERSION=${VERSION}" + - "wget https://storage.googleapis.com/gh-af/genlayer-node/bin/amd64/${VERSION}/genlayer-node-linux-amd64-${VERSION}.tar.gz -O /tmp/genlayer-node-${VERSION}.tar.gz" + - "sudo mkdir -p /opt/genlayer-node/${VERSION}" + - "sudo tar -xzvf /tmp/genlayer-node-${VERSION}.tar.gz -C /opt/genlayer-node/${VERSION} --strip-components=1" + - "sudo mkdir -p /opt/genlayer-node/${VERSION}/{data/node,configs/node}" + - "sudo chown -R $USER:$USER /opt/genlayer-node" + - "rm /tmp/genlayer-node-${VERSION}.tar.gz" + + - id: setup-symlinks + description: | + Create symlinks for current version for easy access from /opt/genlayer-node. + commands: + - "ln -sfn /opt/genlayer-node/${VERSION}/bin /opt/genlayer-node/bin" + - "ln -sfn /opt/genlayer-node/${VERSION}/third_party /opt/genlayer-node/third_party" + - "ln -sfn /opt/genlayer-node/${VERSION}/data /opt/genlayer-node/data" + - "ln -sfn /opt/genlayer-node/${VERSION}/configs /opt/genlayer-node/configs" + - "ln -sfn /opt/genlayer-node/${VERSION}/docker-compose.yaml /opt/genlayer-node/docker-compose.yaml" + - "ln -sfn /opt/genlayer-node/${VERSION}/.env /opt/genlayer-node/.env" + + - id: run-genvm-setup + description: | + Run GenVM post-install script to download dependencies. + command: "python3 /opt/genlayer-node/third_party/genvm/bin/setup.py" + + - id: create-env-file + description: | + Create .env file from template if it doesn't exist. + check: "[ -f /opt/genlayer-node/.env ]" + template: | + # GenLayer Node Environment Configuration + # Generated by genlayer-validator-setup skill + + # Node identification + NODE_ID=${NODE_ID} + NODE_TYPE=validator + NODE_ENV=testnet-asimov + NODE_VERSION=${VERSION} + + # Node password (for keystore encryption) + NODE_PASSWORD=${PASSWORD} + + # LLM API Key (only set the one you're using) + OPENAIKEY=${OPENAI_KEY} + HEURISTKEY=${HEURIST_KEY} + COMPUT3KEY=${COMPUT3_KEY} + IOINTELLIGENCEKEY=${IONET_KEY} + LIBERTAI_API_KEY=${LIBERTAI_KEY} + ANTHROPICKEY=${ANTHROPIC_KEY} + GEMINIKEY=${GEMINI_KEY} + + # Rollup configuration + GENLAYERNODE_ROLLUP_GENLAYERCHAINRPCURL=${RPC_URL} + GENLAYERNODE_ROLLUP_GENLAYERCHAINWEBSOCKETURL=${WEBSOCKET_URL} + + # Consensus configuration + GENLAYERNODE_CONSENSUS_CONTRACTMAINADDRESS=0x67fd4aC71530FB220E0B7F90668BAF977B88fF07 + GENLAYERNODE_CONSENSUS_CONTRACTDATAADDRESS=0xB6E1316E57d47d82FDcEa5002028a554754EF243 + GENLAYERNODE_CONSENSUS_GENESIS=4632386 + + # Node configuration + GENLAYERNODE_NODE_VALIDATORWALLETADDRESS=${VALIDATOR_ADDRESS} + GENLAYERNODE_NODE_OPERATORADDRESS=${OPERATOR_ADDRESS} + GENLAYERNODE_NODE_MODE=validator + + # Ports + NODE_RPC_PORT=${RPC_PORT:-9151} + NODE_OPS_PORT=${OPS_PORT:-9153} + NODE_ADMIN_PORT=${ADMIN_PORT:-9155} + + # Monitoring (optional) + # CENTRAL_MONITORING_USERNAME= + # CENTRAL_MONITORING_PASSWORD= + # CENTRAL_LOKI_USERNAME= + # CENTRAL_LOKI_PASSWORD= + # VALIDATOR_NAME= + + - id: generate-config-yaml + description: | + Generate config.yaml from wizard answers. + template: | + # GenLayer Node Configuration + # Generated by genlayer-validator-setup skill + + # Rollup configuration + rollup: + genlayerchainrpcurl: "${RPC_URL}" + genlayerchainwebsocketurl: "${WEBSOCKET_URL}" + + # Consensus contracts configuration + consensus: + contractmainaddress: "0x67fd4aC71530FB220E0B7F90668BAF977B88fF07" + contractdataaddress: "0xB6E1316E57d47d82FDcEa5002028a554754EF243" + genesis: 4632386 + + # Data directory + datadir: "./data/node" + + # Logging configuration + logging: + level: "INFO" + json: false + file: + enabled: true + level: "DEBUG" + folder: logs + maxsize: 10 + maxage: 7 + maxbackups: 100 + localtime: false + compress: true + + # Node configuration + node: + mode: "validator" + validatorWalletAddress: "${VALIDATOR_ADDRESS}" + operatorAddress: "${OPERATOR_ADDRESS}" + admin: + port: ${ADMIN_PORT:-9155} + rpc: + port: ${RPC_PORT:-9151} + endpoints: + groups: + genlayer: ${RPC_GENLAYER:-true} + genlayer_debug: ${RPC_DEBUG:-false} + ethereum: ${RPC_ETHEREUM:-true} + zksync: ${RPC_ZKSYNC:-true} + ops: + port: ${OPS_PORT:-9153} + endpoints: + metrics: ${OPS_METRICS:-true} + health: ${OPS_HEALTH:-true} + balance: ${OPS_BALANCE:-true} + dev: + disableSubscription: false + + # GenVM configuration + genvm: + root_dir: ./third_party/genvm + start_manager: true + manager_url: http://127.0.0.1:3999 + permits: + + # Merkle tree configuration + merkleforest: + maxdepth: 16 + dbpath: "./data/node/merkle/forest/data.db" + indexdbpath: "./data/node/merkle/index.db" + merkletree: + maxdepth: 16 + dbpath: "./data/node/merkle/tree/" + + # Metrics configuration + metrics: + interval: "${METRICS_INTERVAL:-15s}" + collectors: + node: + enabled: ${METRICS_NODE:-true} + ${METRICS_NODE_INTERVAL:+interval: "${METRICS_NODE_INTERVAL}"} + genvm: + enabled: ${METRICS_GENVM:-true} + ${METRICS_GENVM_INTERVAL:+interval: "${METRICS_GENVM_INTERVAL}"} + webdriver: + enabled: ${METRICS_WEBDRIVER:-true} + ${METRICS_WEBDRIVER_INTERVAL:+interval: "${METRICS_WEBDRIVER_INTERVAL}"} + + - id: copy-config-from-previous + description: | + Copy config.yaml from a previous version. + command: | + cp /opt/genlayer-node/${PREVIOUS_VERSION}/configs/node/config.yaml \ + /opt/genlayer-node/${VERSION}/configs/node/config.yaml + + - id: import-operator-key-from-wizard + description: | + Import operator keystore exported from staking wizard. + command: | + cd /opt/genlayer-node && \ + ./bin/genlayernode account import \ + --password "${NODE_PASSWORD}" \ + --passphrase "${EXPORT_PASSPHRASE}" \ + --path "${KEYSTORE_PATH}" \ + --quiet + + - id: copy-operator-key-from-previous + description: | + Copy operator keystore from previous installation. + command: | + cp -r ${PREVIOUS_KEYSTORE_PATH}/* /opt/genlayer-node/data/node/keystore/ + + - id: generate-new-operator-key + description: | + Generate a new operator key. + command: | + cd /opt/genlayer-node && \ + ./bin/genlayernode account new \ + --setup \ + --password "${NODE_PASSWORD}" + warnings: + - "You must update your validator's operator address after generating!" + - "You must fund the new operator address with ETH for gas fees!" + post_steps: + - "Note the new operator address from command output" + - "Fund the operator address with ETH (for transaction gas)" + - "Update validator settings to use new operator address" + + - id: start-webdriver + description: | + Start WebDriver container and wait for healthy status. + commands: + - "cd /opt/genlayer-node && docker compose up -d" + - "echo 'Waiting for WebDriver to be healthy...'" + - "until docker inspect --format='{{.State.Health.Status}}' genlayer-node-webdriver 2>/dev/null | grep -q 'healthy'; do sleep 2; done" + - "echo 'WebDriver is healthy'" + + - id: run-doctor-check + description: | + Validate configuration before starting. + command: "cd /opt/genlayer-node && source .env && ./bin/genlayernode doctor" + + - id: run-node-manual + description: | + Start node manually (use with screen/tmux). + commands: + - "cd /opt/genlayer-node" + - "source .env" + - "./bin/genlayernode run --password '${NODE_PASSWORD}'" + + - id: create-systemd-service + description: | + Create systemd service for persistent node operation. + template: | + [Unit] + Description=GenLayer Node Service + After=network.target docker.service + Wants=docker.service + + [Service] + Type=simple + User=${USER} + Group=${USER} + WorkingDirectory=/opt/genlayer-node + EnvironmentFile=/opt/genlayer-node/.env + ExecStart=/opt/genlayer-node/bin/genlayernode run --password ${NODE_PASSWORD} + Restart=always + RestartSec=10 + StandardOutput=journal + StandardError=journal + NoNewPrivileges=true + ReadWritePaths=/opt/genlayer-node/data/ + + [Install] + WantedBy=multi-user.target + install_commands: + - "sudo cp /tmp/genlayer-node.service /etc/systemd/system/" + - "sudo systemctl daemon-reload" + - "sudo systemctl enable genlayer-node" + - "sudo systemctl start genlayer-node" + + - id: run-node-docker + description: | + Start node using Docker Compose method. + commands: + - "cd /opt/genlayer-node && source .env && docker compose --profile node up -d" + + - id: verify-node-running + description: | + Check node is running and syncing. + commands: + - "curl -s http://localhost:9153/health | jq" + - "curl -s http://localhost:9153/metrics | grep genlayer_node_synced" + + - id: check-systemd-status + description: | + Check systemd service status for binary deployment. + commands: + - "sudo systemctl status genlayer-node" + - "journalctl -u genlayer-node -f --no-pager -n 50" + + - id: enable-monitoring + description: | + Enable telemetry push to central monitoring (optional). + env_vars: + - "CENTRAL_MONITORING_USERNAME" + - "CENTRAL_MONITORING_PASSWORD" + - "CENTRAL_LOKI_USERNAME" + - "CENTRAL_LOKI_PASSWORD" + - "VALIDATOR_NAME" + command: "cd /opt/genlayer-node && docker compose --profile monitoring up -d" + +anti_patterns: + - id: skip-prerequisites + description: "Starting installation without checking prerequisites" + why_bad: "Will fail mid-installation with confusing errors." + fix: "Run prerequisite checks first." + + - id: wrong-architecture + description: "Installing on ARM64 (Apple Silicon, AWS Graviton)" + why_bad: "Only AMD64 is supported. Binaries won't run." + fix: "Use an AMD64 Linux server." + + - id: insufficient-tokens + description: "Creating validator with less than 42,000 GEN" + why_bad: "Cannot stake and validator won't be active." + fix: "Acquire 42,000+ GEN before running staking wizard." + + - id: missing-llm-key + description: "Not setting any LLM API key" + why_bad: "Node cannot execute intelligent contracts." + fix: "Set at least one LLM provider API key." + + - id: plaintext-password-in-history + description: "Typing password directly in command line" + why_bad: "Password saved in shell history." + fix: "Use environment variables or prompt input." + + - id: skip-doctor-check + description: "Running node without running doctor first" + why_bad: "May miss configuration issues that cause runtime failures." + fix: "Always run ./bin/genlayernode doctor before starting the node." + + - id: extract-without-strip-components + description: "Extracting tarball without --strip-components=1" + why_bad: "Creates nested directory structure, binaries at wrong path." + fix: "Use: tar -xzvf ... --strip-components=1" + + - id: wrong-llm-env-var + description: "Using wrong environment variable name for LLM provider" + why_bad: "LLM module fails to authenticate." + fix: | + Correct names: + - Heurist: HEURISTKEY + - io.net: IOINTELLIGENCEKEY (not IOINTELLIGENCE_API_KEY) + - OpenAI: OPENAIKEY + + - id: displaying-unmasked-secrets + description: "Showing full API keys, passwords, or tokens in conversation" + why_bad: "Exposes sensitive credentials in conversation history and logs." + fix: | + Always mask secrets when displaying: + - API keys: Show first 8 and last 4 chars (sk-proj-********...YblE) + - Passwords: Never display, use ***MASKED*** + - When reading .env: cat .env | sed -E 's/(KEY|PASSWORD|TOKEN)=([^[:space:]]{12}).*/\1=\2********.../' + + - id: secrets-in-systemd-service + description: "Including plaintext passwords in systemd service file" + why_bad: "Service files may be readable by multiple users. Passwords exposed." + fix: | + Use EnvironmentFile directive: + - EnvironmentFile=/opt/genlayer-node/.env + - ExecStart=.../genlayernode run --password "${NODE_PASSWORD}" + + - id: secrets-in-command-output + description: "Showing secrets in command output or verification steps" + why_bad: "Secrets visible in terminal scrollback and logs." + fix: | + Mask secrets in verification: + - env | grep KEY | sed -E 's/=.*/=***MASKED***/' + - Show only that key is set, not the value + + - id: executing-remote-commands-that-expose-secrets + description: "Using gcloud/ssh --command to grep/cat files containing secrets" + why_bad: | + CRITICAL SECURITY VIOLATION: + - Exposes secrets in plain text in command output + - Creates audit trail of secrets in command history + - Violates secret masking policy + - Risk of user sharing output with exposed secrets + examples_of_forbidden_commands: | + ❌ NEVER DO THIS: + - gcloud compute ssh ... --command="grep 'OPENAIKEY' /opt/genlayer-node/.env" + - ssh username@host "cat /opt/genlayer-node/.env" + - gcloud compute ssh ... --command="cat /opt/genlayer-node/.env | grep KEY" + - ssh username@host "echo $OPENAIKEY" + fix: | + INSTEAD, instruct the user to check values themselves: + + ✅ CORRECT approach: + "To verify your API key is set, please SSH to your VM and run: + grep 'OPENAIKEY' /opt/genlayer-node/.env + + This will show the key value on your secure terminal, not in this conversation." + + NEVER execute commands via Bash tool that will display secrets. + NEVER use --command flag with SSH/gcloud to read secrets. + ALWAYS provide instructions for user to run on their own terminal. + severity: critical + +procedure: + - step: "Check prerequisites" + decision_point: false + detail: | + Verify system meets requirements: + - AMD64 architecture (x86_64) + - Node.js v18+, Docker, Python 3 + - 16GB+ RAM, 8+ cores, 128GB+ SSD + commands: + - "uname -m" + - "node --version" + - "docker compose version" + - "python3 --version" + on_failure: "Install missing prerequisites" + + - step: "Decide: New validator or existing?" + decision_point: true + question: "Do you need to create a new validator wallet and stake GEN tokens?" + options: + - answer: "Yes, I need to become a validator" + next_step: "Install GenLayer CLI and run staking wizard" + - answer: "No, I already have a validator wallet" + next_step: "Download node software" + requires: + - "validator_wallet_address" + - "operator_keystore (or will generate new)" + + - step: "Install GenLayer CLI and run staking wizard" + condition: "is_new_validator == true" + detail: | + Install CLI and run staking wizard. + Requires 42,000+ GEN tokens. + commands: + - "npm install -g genlayer" + - "genlayer staking wizard" + outputs: + - "validator_wallet_address" + - "operator-keystore.json" + - "export_passphrase" + notes: + - "Save the operator keystore file securely" + - "Remember the export passphrase" + + - step: "Determine version to install" + detail: | + If user specified "latest", fetch the latest version. + Otherwise, use the specified version or let user choose. + decision_point: true + question: "Which version would you like to install?" + options: + - answer: "Latest version (recommended)" + action: "Fetch latest from storage" + command: 'VERSION=$(curl -s "https://storage.googleapis.com/storage/v1/b/gh-af/o?prefix=genlayer-node/bin/amd64" | grep -o ''"name": *"[^"]*"'' | sed -n ''s/.*\/\(v[^/]*\)\/.*/\1/p'' | sort -Vr | head -1)' + - answer: "Specific version" + action: "List available versions and let user choose" + command: 'curl -s "https://storage.googleapis.com/storage/v1/b/gh-af/o?prefix=genlayer-node/bin/amd64" | grep -o ''"name": *"[^"]*"'' | sed -n ''s/.*\/\(v[^/]*\)\/.*/\1/p'' | sort -ru | head -5' + notes: + - "If user input contains 'latest', automatically use the latest version" + - "Version is stored in ${VERSION} variable for subsequent steps" + + - step: "Download node software" + detail: | + Download and extract to versioned directory structure with shared storage for database. + + Directory structure created: + /opt/genlayer-node/ + ├── v0.4/ # Major version (shared storage) + │ └── data/node/ # Shared database directory + │ └── genlayer.db # Database shared across v0.4.x + ├── v0.4.3/ # Patch version + │ ├── bin/ + │ ├── third_party/ + │ ├── configs/ + │ ├── data/node/ + │ │ ├── genlayer.db -> ../../v0.4/data/node/genlayer.db (symlink) + │ │ ├── keystore/ # Version-specific keystore + │ │ └── logs/ # Version-specific logs + │ ├── docker-compose.yaml + │ └── .env + └── [convenience symlinks pointing to current version] + + command: | + # Extract major version for shared storage (e.g., v0.4 from v0.4.3) + MAJOR_VERSION=$(echo ${VERSION} | grep -oE 'v[0-9]+\.[0-9]+' || echo ${VERSION}) + echo "Installing version: ${VERSION} (major: ${MAJOR_VERSION})" + + # Download to /tmp + wget https://storage.googleapis.com/gh-af/genlayer-node/bin/amd64/${VERSION}/genlayer-node-linux-amd64-${VERSION}.tar.gz -O /tmp/genlayer-node-${VERSION}.tar.gz + + # Create major version directory for shared storage FIRST + sudo mkdir -p /opt/genlayer-node/${MAJOR_VERSION}/data/node + echo "Created major version directory: /opt/genlayer-node/${MAJOR_VERSION}/data/node" + + # Create patch version directory structure + sudo mkdir -p /opt/genlayer-node/${VERSION} + sudo tar -xzvf /tmp/genlayer-node-${VERSION}.tar.gz -C /opt/genlayer-node/${VERSION} --strip-components=1 + + # Create version-specific directories (keystore and logs are NOT shared) + sudo mkdir -p /opt/genlayer-node/${VERSION}/data/node/keystore + sudo mkdir -p /opt/genlayer-node/${VERSION}/data/node/logs + sudo mkdir -p /opt/genlayer-node/${VERSION}/configs/node + echo "Created version-specific directories" + + # Remove any existing genlayer.db file in patch version (we'll symlink it) + sudo rm -f /opt/genlayer-node/${VERSION}/data/node/genlayer.db + + # Create symlink from patch version to major version shared database + sudo ln -sfn ../../${MAJOR_VERSION}/data/node/genlayer.db /opt/genlayer-node/${VERSION}/data/node/genlayer.db + echo "Created symlink: /opt/genlayer-node/${VERSION}/data/node/genlayer.db -> ../../${MAJOR_VERSION}/data/node/genlayer.db" + + # Change ownership + sudo chown -R $USER:$USER /opt/genlayer-node + + # Setup convenience symlinks pointing to current version + ln -sfn /opt/genlayer-node/${VERSION}/bin /opt/genlayer-node/bin + ln -sfn /opt/genlayer-node/${VERSION}/third_party /opt/genlayer-node/third_party + ln -sfn /opt/genlayer-node/${VERSION}/data /opt/genlayer-node/data + ln -sfn /opt/genlayer-node/${VERSION}/configs /opt/genlayer-node/configs + ln -sfn /opt/genlayer-node/${VERSION}/docker-compose.yaml /opt/genlayer-node/docker-compose.yaml + ln -sfn /opt/genlayer-node/${VERSION}/.env /opt/genlayer-node/.env + + # Verify structure + echo "Directory structure:" + ls -la /opt/genlayer-node/ + echo "" + echo "Major version directory:" + ls -la /opt/genlayer-node/${MAJOR_VERSION}/data/node/ + echo "" + echo "Patch version data directory:" + ls -la /opt/genlayer-node/${VERSION}/data/node/ + + - step: "Run GenVM setup" + detail: "Download GenVM dependencies." + command: "python3 /opt/genlayer-node/third_party/genvm/bin/setup.py" + + - step: "Create .env file" + decision_point: true + question: ".env file configuration" + check: "[ -f /opt/genlayer-node/.env ]" + options: + - answer: ".env exists - keep existing" + action: "Skip, optionally update specific values" + - answer: ".env exists - recreate" + action: "Backup and create new from template" + - answer: ".env doesn't exist - create new" + action: "Create from template with wizard values" + + - step: "Decide: Configuration source" + decision_point: true + question: "How would you like to configure config.yaml?" + options: + - answer: "Interactive wizard (Recommended)" + next_step: "Run configuration wizard" + - answer: "Copy from previous version" + next_step: "Copy existing config" + requires: "previous_version_path" + - answer: "Manual configuration" + next_step: "Skip - user will edit manually" + + - step: "Run configuration wizard" + condition: "config_source == wizard" + sub_steps: + - name: "Rollup URLs (Required - No Defaults)" + questions: + - "GenLayer Chain RPC URL (user must provide ZKSync HTTP RPC URL)" + - "GenLayer Chain WebSocket URL (user must provide ZKSync WebSocket URL)" + - name: "Node Identity" + questions: + - "Validator Wallet Address" + - "Operator Address" + - name: "RPC Endpoints" + questions: + - "Enable RPC endpoints? (default: yes)" + - "RPC port (default: 9151)" + - "Enable genlayer group? (default: yes)" + - "Enable genlayer_debug group? (default: no)" + - "Enable ethereum group? (default: yes)" + - "Enable zksync group? (default: yes)" + - name: "Ops Endpoints" + questions: + - "Enable ops endpoints? (default: yes)" + - "Ops port (default: 9153)" + - "Enable /metrics? (default: yes)" + - "Enable /health? (default: yes)" + - "Enable /balance? (default: yes)" + - name: "Metrics (if ops_metrics enabled)" + questions: + - "Default metrics interval (default: 15s)" + - "Enable node metrics? (default: yes)" + - "Enable GenVM metrics? (default: yes)" + - "Enable WebDriver metrics? (default: yes)" + - "Custom intervals for any collector? (default: no)" + + - step: "Decide: Operator key source" + decision_point: true + question: "How would you like to configure the operator key?" + options: + - answer: "Import from staking wizard export" + command: "./bin/genlayernode account import --password '${PASSWORD}' --passphrase '${PASSPHRASE}' --path '${KEYSTORE_PATH}' --quiet" + - answer: "Copy from previous installation" + command: "cp -r ${PREV_KEYSTORE}/* /opt/genlayer-node/data/node/keystore/" + - answer: "Generate new operator key" + command: "./bin/genlayernode account new --setup --password '${PASSWORD}'" + warnings: + - "You must update your validator's operator address after generating!" + - "You must fund the new operator address with ETH for gas fees!" + post_steps: + - "Note the new operator address from command output" + - "Send ETH to the new operator address for transaction gas" + - "Update validator settings via staking UI or CLI to use new operator" + + - step: "Configure LLM provider" + detail: "Set API key for chosen LLM provider in .env" + decision_point: true + question: "Which LLM provider?" + options: + - "Heurist → HEURISTKEY" + - "Comput3 → COMPUT3KEY" + - "io.net → IOINTELLIGENCEKEY" + - "OpenAI → OPENAIKEY" + - "LibertAI → LIBERTAI_API_KEY" + - "Anthropic → ANTHROPICKEY" + - "Google → GEMINIKEY" + + - step: "Start WebDriver" + detail: "Start WebDriver container and wait for healthy status." + commands: + - "cd /opt/genlayer-node && docker compose up -d" + - "until docker inspect --format='{{.State.Health.Status}}' genlayer-node-webdriver | grep -q 'healthy'; do sleep 2; done" + + - step: "Run doctor check" + detail: "Validate configuration before starting." + command: "cd /opt/genlayer-node && source .env && ./bin/genlayernode doctor" + + - step: "Decide: Deployment method" + decision_point: true + question: "How would you like to run the node?" + options: + - answer: "Systemd Service (Recommended)" + next_step: "Create and start systemd service" + - answer: "Docker Compose" + next_step: "Start with docker compose" + - answer: "Manual (screen/tmux)" + next_step: "Start manually" + + - step: "Create and start systemd service" + condition: "deployment_method == binary" + commands: + - "# Create service file" + - "sudo cp /tmp/genlayer-node.service /etc/systemd/system/" + - "sudo systemctl daemon-reload" + - "sudo systemctl enable genlayer-node" + - "sudo systemctl start genlayer-node" + + - step: "Verify node is running" + commands: + - "curl -s http://localhost:9153/health | jq" + - "curl -s http://localhost:9153/metrics | grep genlayer_node_synced" + + - step: "Decide: Clean up previous version?" + decision_point: true + condition: "previous_version_exists" + question: "Installation complete! Would you like to remove the previous version (${PREVIOUS_VERSION})?" + detail: | + This will free up disk space by removing the old version directory. + Shared database storage will be kept (used by the current version). + options: + - answer: "Yes, remove previous version" + command: "sudo rm -rf /opt/genlayer-node/${PREVIOUS_VERSION}" + note: "Only removes the patch version directory, keeps major version shared storage" + - answer: "No, keep previous version" + action: "Skip cleanup" + note: "Previous version will remain at /opt/genlayer-node/${PREVIOUS_VERSION}" + + - step: "Decide: Enable monitoring?" + decision_point: true + question: "Enable telemetry push to central monitoring?" + options: + - answer: "Yes" + next_step: "Configure and start monitoring" + - answer: "No" + next_step: "Done" + +handoffs: + - skill: "genlayer-validator-monitor" + when: "After node is running, to set up monitoring dashboards." + - skill: "genlayer-validator-manage" + when: "To manage stake, exit, or update validator identity." + - skill: "genlayer-validator-upgrade" + when: "To upgrade to a new node version." diff --git a/.claude/skills/genlayer-validator-setup/update-procedure.md b/.claude/skills/genlayer-validator-setup/update-procedure.md new file mode 100644 index 000000000..7b1e0d969 --- /dev/null +++ b/.claude/skills/genlayer-validator-setup/update-procedure.md @@ -0,0 +1,149 @@ +# GenLayer Validator Zero-Downtime Update Procedure + +## Goal +Minimize validator downtime during updates by preparing the new version while the old version continues running. + +## Update Sequence (for v0.4.x patch updates) + +### Phase 1: Preparation (Old Version Running) +All preparation steps happen WHILE the validator is actively running and validating: + +```bash +# 1. Check current version +curl -s http://localhost:9153/health | jq '.node_version' + +# 2. Download new version to /tmp +VERSION=v0.4.5 # or whatever new version +wget https://storage.googleapis.com/gh-af/genlayer-node/bin/amd64/${VERSION}/genlayer-node-linux-amd64-${VERSION}.tar.gz \ + -O /tmp/genlayer-node-${VERSION}.tar.gz + +# 3. Create version directory and extract +sudo mkdir -p /opt/genlayer-node/${VERSION} +sudo tar -xzvf /tmp/genlayer-node-${VERSION}.tar.gz \ + -C /opt/genlayer-node/${VERSION} --strip-components=1 + +# 4. Set permissions +sudo chown -R $USER:$USER /opt/genlayer-node/${VERSION} + +# 5. Run GenVM setup (IMPORTANT: This is the slow part - 2+ minutes) +python3 /opt/genlayer-node/${VERSION}/third_party/genvm/bin/setup.py + +# 6. Create configs directory +sudo mkdir -p /opt/genlayer-node/${VERSION}/configs/node + +# 7. Copy config from current version +sudo cp /opt/genlayer-node/configs/node/config.yaml \ + /opt/genlayer-node/${VERSION}/configs/node/config.yaml + +# 8. Copy .env from current version +sudo cp /opt/genlayer-node/.env /opt/genlayer-node/${VERSION}/.env + +# 9. Enable OpenAI in GenVM config (if using OpenAI) +sudo sed -i '/^ openai:/,/^ / s/enabled: false/enabled: true/' \ + /opt/genlayer-node/${VERSION}/third_party/genvm/config/genvm-module-llm.yaml + +# 10. Create data directory structure +sudo mkdir -p /opt/genlayer-node/${VERSION}/data/node + +# 11. Create symlinks to shared v0.4 database +ln -s /opt/genlayer-node/v0.4/data/node/genlayer.db \ + /opt/genlayer-node/${VERSION}/data/node/genlayer.db + +# 12. Copy keystore from shared location +sudo cp -r /opt/genlayer-node/data/node/keystore \ + /opt/genlayer-node/${VERSION}/data/node/ +``` + +**At this point, everything is ready for the new version.** + +### Phase 2: Quick Switch (Minimize Downtime) +Now we do the fastest possible switch: + +```bash +# 1. Stop old version +sudo systemctl stop genlayer-node + +# 2. Update symlinks (very fast - <1 second) +cd /opt/genlayer-node +ln -sfn /opt/genlayer-node/${VERSION}/bin bin +ln -sfn /opt/genlayer-node/${VERSION}/third_party third_party +ln -sfn /opt/genlayer-node/${VERSION}/data data +ln -sfn /opt/genlayer-node/${VERSION}/configs configs +ln -sfn /opt/genlayer-node/${VERSION}/docker-compose.yaml docker-compose.yaml +ln -sfn /opt/genlayer-node/${VERSION}/.env .env + +# 3. Start new version immediately +sudo systemctl start genlayer-node + +# Total downtime: 10-15 seconds +``` + +### Phase 3: Verification +```bash +# Check version +curl -s http://localhost:9153/health | jq '.node_version' + +# Check sync status +curl -s http://localhost:9153/health | jq '.checks.validating' + +# Monitor logs +sudo journalctl -u genlayer-node -f --no-hostname +``` + +## For Major Version Updates (e.g., v0.4.x → v0.5.x) + +Major version updates may require: +1. New shared storage directory (e.g., `/opt/genlayer-node/v0.5/`) +2. Database migration scripts +3. Configuration format changes + +The principle remains: **Prepare everything first, then quick switch.** + +## Downtime Comparison + +| Method | Downtime | Validation Loss | +|--------|----------|-----------------| +| **Old way (stop first)** | 3-4 minutes | High - missed many validation rounds | +| **New way (prepare first)** | 10-15 seconds | Minimal - maybe 1 validation round | + +## Key Principles + +1. **Never stop the old node until the new node is 100% ready to start** +2. **GenVM setup is the slowest part** - do it while old node runs +3. **Shared database** - instant access to current sync state +4. **Symlink switching** - takes <1 second +5. **Test the new version setup** - verify files exist before switching + +## Rollback Procedure (if new version fails) + +If the new version fails to start: + +```bash +# 1. Stop failed new version +sudo systemctl stop genlayer-node + +# 2. Switch symlinks back to old version +cd /opt/genlayer-node +ln -sfn /opt/genlayer-node/v0.4.3/bin bin +ln -sfn /opt/genlayer-node/v0.4.3/third_party third_party +ln -sfn /opt/genlayer-node/v0.4.3/data data +ln -sfn /opt/genlayer-node/v0.4.3/configs configs +ln -sfn /opt/genlayer-node/v0.4.3/docker-compose.yaml docker-compose.yaml +ln -sfn /opt/genlayer-node/v0.4.3/.env .env + +# 3. Start old version +sudo systemctl start genlayer-node + +# Total rollback time: 10-15 seconds +``` + +## Pre-Update Checklist + +Before starting any update: + +- [ ] Current node is running and synced +- [ ] Disk space available (check with `df -h`) +- [ ] Backup current .env and config.yaml +- [ ] Know the rollback procedure +- [ ] Have monitoring ready to check after switch +- [ ] Note current synced block number \ No newline at end of file diff --git a/.claude/skills/genlayer-validator-setup/validations.yaml b/.claude/skills/genlayer-validator-setup/validations.yaml new file mode 100644 index 000000000..21c6dcfe6 --- /dev/null +++ b/.claude/skills/genlayer-validator-setup/validations.yaml @@ -0,0 +1,252 @@ +validations: + # ============================================================================ + # SYSTEM REQUIREMENTS + # ============================================================================ + + - id: architecture-amd64 + name: "System is AMD64 architecture" + type: command + command: "uname -m | grep -E '^(x86_64|amd64)$' >/dev/null" + expect: "exit 0" + message: "Only AMD64 Linux is supported. ARM64 (including Apple Silicon) is not supported." + + - id: ram-sufficient + name: "System has at least 16GB RAM" + type: command + command: "[ $(free -g | awk '/Mem:/ {print $2}') -ge 15 ]" + expect: "exit 0" + message: "At least 16GB RAM is required. Current system has insufficient memory." + + - id: disk-sufficient + name: "System has at least 100GB free disk space" + type: command + command: "[ $(df -BG . | awk 'NR==2 {print $4}' | tr -d 'G') -ge 100 ]" + expect: "exit 0" + message: "At least 100GB free disk space is required." + + # ============================================================================ + # SOFTWARE PREREQUISITES + # ============================================================================ + + - id: nodejs-installed + name: "Node.js v18+ is installed" + type: command + command: "node --version 2>/dev/null | grep -E 'v(1[89]|[2-9][0-9])' >/dev/null" + expect: "exit 0" + message: "Node.js v18+ is required. Install with: curl -fsSL https://deb.nodesource.com/setup_20.x | sudo -E bash - && sudo apt install -y nodejs" + + - id: npm-installed + name: "npm is installed" + type: command + command: "command -v npm >/dev/null 2>&1" + expect: "exit 0" + message: "npm is required. Usually installed with Node.js." + + - id: docker-installed + name: "Docker is installed" + type: command + command: "command -v docker >/dev/null 2>&1" + expect: "exit 0" + message: "Docker is required. Install with: curl -fsSL https://get.docker.com | sh" + + - id: docker-compose-installed + name: "Docker Compose is installed" + type: command + command: "docker compose version >/dev/null 2>&1" + expect: "exit 0" + message: "Docker Compose is required. Usually included with Docker." + + - id: python3-installed + name: "Python 3 is installed" + type: command + command: "command -v python3 >/dev/null 2>&1" + expect: "exit 0" + message: "Python 3 is required. Install with: sudo apt install python3" + + - id: python3-pip-installed + name: "pip3 is installed" + type: command + command: "command -v pip3 >/dev/null 2>&1" + expect: "exit 0" + message: "pip3 is required. Install with: sudo apt install python3-pip" + + - id: python3-venv-installed + name: "python3-venv is installed" + type: command + command: "dpkg -l python3-venv >/dev/null 2>&1 || python3 -m venv --help >/dev/null 2>&1" + expect: "exit 0" + message: "python3-venv is required. Install with: sudo apt install python3-venv" + + - id: wget-installed + name: "wget is installed" + type: command + command: "command -v wget >/dev/null 2>&1" + expect: "exit 0" + message: "wget is required. Install with: sudo apt install wget" + + - id: jq-installed + name: "jq is installed" + type: command + command: "command -v jq >/dev/null 2>&1" + expect: "exit 0" + message: "jq is recommended. Install with: sudo apt install jq" + + # ============================================================================ + # GENLAYER CLI + # ============================================================================ + + - id: genlayer-cli-installed + name: "GenLayer CLI is installed" + type: command + command: "command -v genlayer >/dev/null 2>&1" + expect: "exit 0" + message: "GenLayer CLI not installed. Install with: npm install -g genlayer" + + # ============================================================================ + # DOCKER STATE + # ============================================================================ + + - id: docker-running + name: "Docker daemon is running" + type: command + command: "docker info >/dev/null 2>&1" + expect: "exit 0" + message: "Docker daemon is not running. Start with: sudo systemctl start docker" + + - id: docker-no-sudo + name: "Current user can run Docker without sudo" + type: command + command: "docker ps >/dev/null 2>&1" + expect: "exit 0" + message: "Cannot run Docker without sudo. Run: sudo usermod -aG docker $USER, then log out and back in." + + # ============================================================================ + # POST-INSTALLATION CHECKS + # ============================================================================ + + - id: config-file-exists + name: "Config file exists" + type: command + command: "[ -f configs/node/config.yaml ]" + expect: "exit 0" + message: "Configuration file not found. Create configs/node/config.yaml" + + - id: config-valid-yaml + name: "Config file is valid YAML" + type: command + command: "python3 -c 'import yaml; yaml.safe_load(open(\"configs/node/config.yaml\"))' 2>/dev/null" + expect: "exit 0" + message: "Configuration file has YAML syntax errors." + + - id: genvm-binaries-exist + name: "GenVM binaries are downloaded" + type: command + command: "[ -f third_party/genvm/bin/genvm ] && [ -f third_party/genvm/bin/genvm-modules ]" + expect: "exit 0" + message: "GenVM binaries not found. Run: python3 ./third_party/genvm/bin/setup.py" + + - id: llm-key-configured + name: "At least one LLM API key is set" + type: command + command: "[ -n \"${HEURISTKEY:-}\" ] || [ -n \"${COMPUT3KEY:-}\" ] || [ -n \"${IOINTELLIGENCE_API_KEY:-}\" ]" + expect: "exit 0" + message: "No LLM API key configured. Set HEURISTKEY, COMPUT3KEY, or IOINTELLIGENCE_API_KEY" + + - id: webdriver-running + name: "WebDriver container is running" + type: command + command: "docker ps | grep -q webdriver" + expect: "exit 0" + message: "WebDriver container not running. Start with: docker compose up -d" + + - id: node-health-ok + name: "Node health endpoint returns OK" + type: command + command: "curl -sf http://localhost:9153/health | grep -q 'up'" + expect: "exit 0" + message: "Node health check failed. Check if node is running." + + # ============================================================================ + # SYSTEMD SERVICE CHECKS + # ============================================================================ + + - id: systemd-service-exists + name: "Systemd service file exists" + type: command + command: "[ -f /etc/systemd/system/genlayer-node.service ]" + expect: "exit 0" + message: "Systemd service not installed. Create service file in /etc/systemd/system/" + + - id: systemd-service-enabled + name: "Systemd service is enabled" + type: command + command: "systemctl is-enabled genlayer-node >/dev/null 2>&1" + expect: "exit 0" + message: "Service not enabled. Run: sudo systemctl enable genlayer-node" + + - id: systemd-service-active + name: "Systemd service is active" + type: command + command: "systemctl is-active genlayer-node >/dev/null 2>&1" + expect: "exit 0" + message: "Service not running. Run: sudo systemctl start genlayer-node" + + # ============================================================================ + # WEBDRIVER HEALTH CHECKS + # ============================================================================ + + - id: webdriver-healthy + name: "WebDriver container is healthy" + type: command + command: "docker inspect --format='{{.State.Health.Status}}' genlayer-node-webdriver 2>/dev/null | grep -q 'healthy'" + expect: "exit 0" + message: "WebDriver not healthy. Check: docker logs genlayer-node-webdriver" + + # ============================================================================ + # ENVIRONMENT FILE CHECKS + # ============================================================================ + + - id: env-file-exists + name: ".env file exists" + type: command + command: "[ -f /opt/genlayer-node/.env ] || [ -f .env ]" + expect: "exit 0" + message: ".env file not found. Create from template." + + - id: rpc-url-configured + name: "RPC URL is configured" + type: command + command: "grep -q 'GENLAYERNODE_ROLLUP_GENLAYERCHAINRPCURL' /opt/genlayer-node/.env 2>/dev/null || grep -q 'GENLAYERNODE_ROLLUP_GENLAYERCHAINRPCURL' .env 2>/dev/null" + expect: "exit 0" + message: "RPC URL not configured in .env file" + + - id: validator-address-configured + name: "Validator address is configured" + type: command + command: "grep -q 'GENLAYERNODE_NODE_VALIDATORWALLETADDRESS' /opt/genlayer-node/.env 2>/dev/null || grep -q 'GENLAYERNODE_NODE_VALIDATORWALLETADDRESS' .env 2>/dev/null" + expect: "exit 0" + message: "Validator address not configured in .env file" + + - id: rpc-url-reachable + name: "RPC URL is reachable" + type: command + command: "curl -sf -X POST https://genlayer-testnet.rpc.caldera.xyz/http -H 'Content-Type: application/json' -d '{\"jsonrpc\":\"2.0\",\"method\":\"eth_blockNumber\",\"params\":[],\"id\":1}' | grep -q 'result'" + expect: "exit 0" + message: "Cannot reach RPC endpoint. Check network connectivity." + +# Validations that must pass before installation +on_stop: + - architecture-amd64 + - nodejs-installed + - docker-installed + - docker-running + - python3-installed + +# Validations that are warnings +on_warn: + - ram-sufficient + - disk-sufficient + - jq-installed + - docker-no-sudo + - python3-pip-installed + - python3-venv-installed From adc9ecea98267ffaeb7a763db2433249f25900b0 Mon Sep 17 00:00:00 2001 From: Darien Hernandez Date: Fri, 23 Jan 2026 13:15:47 +0100 Subject: [PATCH 2/3] feat(skills): Add mandatory process overview to validator setup Add documentation requiring the validator setup skill to display a complete overview of all installation steps at the start of any setup or upgrade operation. This ensures users understand the full process before beginning and know what each step will do before it executes. Includes: - Required start message template with all 11 steps - Per-step explanation requirement before execution - Clear guidance to never skip showing step descriptions --- .../skills/genlayer-validator-setup/SKILL.md | 94 +++++++++++++++++++ 1 file changed, 94 insertions(+) diff --git a/.claude/skills/genlayer-validator-setup/SKILL.md b/.claude/skills/genlayer-validator-setup/SKILL.md index a1580c6d3..d93fd5270 100644 --- a/.claude/skills/genlayer-validator-setup/SKILL.md +++ b/.claude/skills/genlayer-validator-setup/SKILL.md @@ -15,6 +15,100 @@ hooks: [] Interactive wizard to set up a GenLayer validator node from scratch on a Linux server. +## 🚨 MANDATORY: Show Process Overview at Start + +**CRITICAL REQUIREMENT**: At the very beginning of ANY setup or upgrade operation, you MUST display a complete overview of ALL steps that will be performed. This is NON-NEGOTIABLE. + +### Before Starting ANY Installation or Upgrade: + +1. **Display the full process overview** showing all steps that will be executed +2. **Ask user to confirm** they want to proceed with the installation/upgrade +3. **Before EACH step**, briefly explain what that step will do before executing it + +### Required Start Message Format: + +``` +## GenLayer Validator Node Setup + +I'll guide you through the complete validator node installation. Here's what we'll do: + +**Step 1: Determine Server Location** +- Identify where the validator will run (local/GCP/AWS/SSH) +- Configure access method for commands + +**Step 2: Verify Prerequisites** +- Check system architecture (must be x86_64) +- Verify RAM, CPU, and disk space +- Check Node.js, Docker, Python installations + +**Step 3: New or Existing Validator** +- New: Run staking wizard (requires 42,000+ GEN) +- Existing: Provide validator wallet address + +**Step 4: Download & Extract Node Software** +- Download GenLayer node tarball from official storage +- Extract to /opt/genlayer-node/${VERSION}/ +- Set up directory structure and symlinks +- Run GenVM setup to download dependencies + +**Step 5: Configure Environment (.env)** +- Create .env from example template +- Configure RPC and WebSocket URLs +- Set LLM provider (you'll add API key manually) + +**Step 6: Configure Node (config.yaml)** +- Set validator wallet address +- Configure operator address +- Set network endpoints and ports + +**Step 7: Set Up Operator Key** +- Import keystore from staking wizard, OR +- Copy from previous installation, OR +- Generate new operator key + +**Step 8: Start WebDriver Container** +- Launch WebDriver via Docker Compose +- Wait for health check to pass + +**Step 9: Run Doctor Check** +- Verify GenVM binaries are installed +- Verify WebDriver connectivity + +**Step 10: Choose Deployment Method** +- Systemd service (recommended) +- Docker Compose +- Manual (screen/tmux) + +**Step 11: Verify Node Running** +- Check health endpoint +- Verify sync status + +**Estimated time: 20-45 minutes** + +Ready to begin? +``` + +### Before Each Step: + +Always show a brief description of what will happen: + +``` +## Step 4: Download & Extract Node Software + +This step will: +1. Download the GenLayer node v0.4.4 tarball (~XX MB) +2. Create directory /opt/genlayer-node/v0.4.4/ +3. Extract binary, configs, and GenVM files +4. Set up symlinks for easy access +5. Run GenVM setup to download dependencies (~2 min) + +Proceeding... +``` + +**NEVER skip showing what a step will do before executing it.** + +--- + ## What This Skill Will Do This skill guides you through the complete validator node installation process. When you invoke this skill, it will: From 36a23837fdeecd58c537ec4a1147adeda9248b52 Mon Sep 17 00:00:00 2001 From: Darien Hernandez Date: Fri, 23 Jan 2026 13:34:47 +0100 Subject: [PATCH 3/3] docs: Add Claude Code skill callout to setup guide Add an info callout at the top of the validator setup guide that introduces the assisted setup option via Claude Code. The callout includes: - Instructions to install the skill from the marketplace - Commands to run the wizard (install node / upgrade node) - Brief description of supported environments (local, SSH, cloud VMs) --- pages/validators/setup-guide.mdx | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/pages/validators/setup-guide.mdx b/pages/validators/setup-guide.mdx index 79210b069..fe8fc17b2 100644 --- a/pages/validators/setup-guide.mdx +++ b/pages/validators/setup-guide.mdx @@ -6,6 +6,32 @@ Running a GenLayer Validator node ensures the security and reliability of the Ge For a deeper understanding of how staking works in GenLayer, see the [Staking documentation](/understand-genlayer-protocol/core-concepts/optimistic-democracy/staking). + +**Prefer an Assisted Setup?** + +If you have [Claude Code](https://docs.anthropic.com/en/docs/claude-code) installed, you can use an interactive wizard that guides you through the entire setup process. + +**Install the skill:** +```bash +claude +/plugin marketplace add genlayerlabs/genlayer-docs +/plugin install genlayer-validator-setup@genlayer-docs +``` + +**Run the wizard:** +```bash +# For new installations +/genlayer-validator-setup install node + +# For upgrading an existing node +/genlayer-validator-setup upgrade node +``` + +The wizard handles prerequisites verification, software download, configuration, operator key setup, and deployment - all interactively. It supports local machines, remote SSH servers, and cloud VMs (GCP, AWS, Azure). + +Continue below for the manual setup guide. + + ## Create the Validator Wallet Before setting up your validator node, you need to create your validator wallet and stake GEN tokens.