Skip to content

blockblaz/lean-quickstart

Repository files navigation

lean quickstart

A single command line quickstart to spin up lean node(s)

Benefits

  • Single source of truth - validator-config.yaml
    • defines everything
    • Generates full genesis state (JSON + SSZ) plus config files
    • add/remove nodes, modify validator count, assign IPs, ports, enr keys
    • Uses PK's eth-beacon-genesis docker tool (not custom tooling)
    • Generates PQ keys based on specified configuration in validator-config.yaml
      • Force regen with flag --forceKeyGen when supplied with generateGenesis
  • ✅ Integrates zeam, ream, qlean (and more incoming...)
  • ✅ Configure to run clients in docker or binary mode for easy development
  • ✅ Linux & Mac compatible & tested
  • ✅ Option to operate on single or multiple nodes or all

Requirements

  1. Shell terminal: Preferably linux especially if you want to pop out separate new terminals for node
  2. Docker: Required to run PK's eth-beacon-genesis tool and hash-sig-cli for post-quantum keys
  3. yq: YAML processor for automated configuration parsing

Quick Start

First Time Setup:

# 1. Clone the repository
git clone <repo-url>
cd lean-quickstart

Scenarios

Quickly startup various nodes as a local devnet

NETWORK_DIR=local-devnet ./spin-node.sh --node all --generateGenesis --popupTerminal

Startup specific nodes only

# Run only zeam_0 and ream_0 nodes (comma-separated)
NETWORK_DIR=local-devnet ./spin-node.sh --node zeam_0,ream_0 --generateGenesis --popupTerminal

# Run only zeam_0 and qlean_0 nodes (space-separated)
NETWORK_DIR=local-devnet ./spin-node.sh --node "zeam_0 qlean_0" --generateGenesis --popupTerminal

# Run only a single node
NETWORK_DIR=local-devnet ./spin-node.sh --node zeam_0 --generateGenesis --popupTerminal

Args

  1. NETWORK_DIR is an env to specify the network directory. Should have a genesis directory with genesis config. A data folder will be created inside this NETWORK_DIR if not already there. genesis directory should have the following files

    a. validator-config.yaml which has node setup information for all the bootnodes b. validators.yaml which assigns validator indices c. nodes.yaml which has the enrs generated for each of the respective nodes. d. config.yaml the actual network config

  2. --generateGenesis regenerate all genesis files with fresh genesis time and clean data directories

  3. --popupTerminal if you want to pop out new terminals to run the nodes, opens gnome terminals

  4. --node specify which node(s) you want to run:

    • Use all to run all the nodes in a single go
    • Specify a single node name (e.g., zeam_0) to run just that node
    • Use comma-separated node names (e.g., zeam_0,qlean_0) to run multiple specific nodes
    • Use whitespace-separated node names (e.g., "zeam_0 ream_0") to run multiple specific nodes

    The client is provided this input so as to parse the correct node configuration to startup the node.

  5. --validatorConfig is the path to specify your nodes validator-config.yaml, validators.yaml (for which --node is still the node key to index) if your node is not a bootnode. If unspecified it assumes value of genesis_bootnode which is to say that your node config is to be picked from genesis folder with --node as the node key index. This value is further provided to the client so that they can parse the correct config information.

Genesis Generator

The quickstart includes an automated genesis generator that eliminates the need for hardcoded validators.yaml and nodes.yaml files.

Clients supported

Current following clients are supported:

  1. Zeam
  2. Ream
  3. Qlean

However adding a lean client to this setup is very easy. Feel free to do the PR or reach out to the maintainers.

How It Works

The genesis generator (generate-genesis.sh) uses PK's official eth-beacon-genesis docker tool to automatically generate:

  1. validators.yaml - Validator index assignments using round-robin distribution
  2. nodes.yaml - ENR (Ethereum Node Records) for peer discovery
  3. genesis.json - Genesis state in JSON format
  4. genesis.ssz - Genesis state in SSZ format
  5. .key files - Private key files for each node

Docker Image: ethpandaops/eth-beacon-genesis:pk910-leanchain
Source: ethpandaops/eth-beacon-genesis#36

config.yaml is also generated from scratch with the appropriate properties populated.

Usage

The genesis generator runs automatically when:

  • validators.yaml or nodes.yaml don't exist, OR
  • You use the --generateGenesis flag
# Regenerate genesis files with fresh genesis time
NETWORK_DIR=local-devnet ./spin-node.sh --node all --generateGenesis

You can also run the generator standalone:

./generate-genesis.sh local-devnet/genesis

Hash-Based Signature (Post-Quantum) Validator Keys

This quickstart includes integrated support for post-quantum secure hash-based signatures for validator keys. The system automatically generates and manages hash-sig keys during genesis generation.

How It Works

The genesis generator automatically:

  1. Uses Docker image blockblaz/hash-sig-cli:latest to generate hash-sig keys
  2. Generates hash-sig keys for N validators (Step 1 of genesis generation)
  3. Stores keys in genesis/hash-sig-keys/ directory
  4. Loads keys automatically when nodes start via environment variables

Key Generation

When you run the genesis generator, it creates post-quantum secure keys for each validator:

./generate-genesis.sh local-devnet/genesis

Generated files:

local-devnet/genesis/hash-sig-keys/
├── validator-keys-manifest.yaml    # Metadata for all keys
├── validator_0_pk.json             # Public key for validator 0
├── validator_0_sk.json             # Secret key for validator 0
├── validator_1_pk.json             # Public key for validator 1
├── validator_1_sk.json             # Secret key for validator 1
└── ...                             # Keys for additional validators

Signature Scheme

The system uses the SIGTopLevelTargetSumLifetime32Dim64Base8 hash-based signature scheme, which provides:

  • Post-quantum security: Resistant to attacks from quantum computers
  • Active epochs: 2^18 (262,144 signatures)
  • Total lifetime: 2^32 (4,294,967,296 signatures)
  • Stateful signatures: Uses hierarchical signature tree structure

Configuration

The validator-config.yaml file defines the shuffle algorithm, active epoch configuration, and validator specifications:

shuffle: roundrobin
config:
  activeEpoch: 18              # Required: Exponent for active epochs (2^18 = 262,144 signatures)
  keyType: "hash-sig"          # Required: Network-wide signature scheme (hash-sig for post-quantum security)
validators:
  - name: "zeam_0"
    privkey: "bdf953adc161873ba026330c56450453f582e3c4ee6cb713644794bcfdd85fe5"
    enrFields:
      ip: "127.0.0.1"
      quic: 9000
    metricsPort: 8080
    count: 1

Required Top-Level Fields:

  • shuffle: Validator shuffle algorithm (e.g., roundrobin)
  • config.activeEpoch: Exponent for active epochs used in hash-sig key generation (2^activeEpoch signatures per active period)
  • config.keyType: Network-wide signature scheme - must be "hash-sig" for post-quantum security

Validator Fields:

  • Hash-sig key files are automatically mapped based on validator position in the array (first validator uses validator_0_*.json, second uses validator_1_*.json, etc.)

Key Loading

The parse-vc.sh script automatically loads hash-sig keys when starting nodes:

  1. Reads config.keyType from validator config (network-wide setting)
  2. Automatically calculates key index based on validator position in the array
  3. Locates corresponding key files in genesis/hash-sig-keys/
  4. Exports environment variables for client use:
    • HASH_SIG_PK_PATH: Path to public key file
    • HASH_SIG_SK_PATH: Path to secret key file
    • HASH_SIG_KEY_INDEX: Validator's key index (auto-calculated)

Client Integration:

Your client implementation should read these environment variables and use the hash-sig keys for validator operations.

Key Management

Key Lifetime

Each hash-sig key has a finite lifetime of 2^32 signatures. The keys are structured as:

  • Active epochs: 2^18 epochs before requiring key rotation
  • Total lifetime: 2^32 total signatures possible

Key Rotation

Hash-based signatures are stateful - each signature uses a unique one-time key from the tree. Once exhausted, keys must be rotated:

# Regenerate all hash-sig keys
./generate-genesis.sh local-devnet/genesis

Warning: Keep track of signature counts to avoid key exhaustion.

Key Security

Secret keys are highly sensitive:

  • ⚠️ Never commit validator_*_sk.json files to version control
  • ⚠️ Never share secret keys
  • Backup secret keys in secure, encrypted storage
  • Restrict permissions on key files (e.g., chmod 600)

The .gitignore should already exclude hash-sig keys:

local-devnet/genesis/hash-sig-keys/

Verifying Keys

The manifest file (validator-keys-manifest.yaml) contains metadata about all generated keys:

# Hash-Sig Validator Keys Manifest
# Generated: 2024-01-15T10:30:00Z

scheme: "SIGTopLevelTargetSumLifetime32Dim64Base8"
activeEpochs: 262144  # 2^18
totalLifetime: 4294967296  # 2^32
validatorCount: 3

validators:
  - index: 0
    publicKey: "validator_0_pk.json"
    secretKey: "validator_0_sk.json"
  - index: 1
    publicKey: "validator_1_pk.json"
    secretKey: "validator_1_sk.json"
  # ... additional validators

Troubleshooting

Problem: Hash-sig keys not loading during node startup

Warning: Hash-sig public key not found at genesis/hash-sig-keys/validator_0_pk.json

Solution: Run the genesis generator to create keys:

./generate-genesis.sh local-devnet/genesis

Problem: Hash-sig key file not found

Warning: Hash-sig secret key not found at genesis/hash-sig-keys/validator_5_sk.json

Solution: This usually means you have more validators configured than hash-sig keys generated. Regenerate genesis files:

./generate-genesis.sh local-devnet/genesis

Automation Features

This quickstart includes automated configuration parsing:

  • Official Genesis Generation: Uses PK's eth-beacon-genesis docker tool from PR #36
  • Complete File Set: Generates validators.yaml, nodes.yaml, genesis.json, genesis.ssz, and .key files
  • QUIC Port Detection: Automatically extracts QUIC ports from validator-config.yaml using yq
  • Node Detection: Dynamically discovers available nodes from the validator configuration
  • Private Key Management: Automatically extracts and creates .key files for each node
  • Error Handling: Provides clear error messages when nodes or ports are not found

The system reads all configuration from YAML files, making it easy to add new nodes or modify existing ones without changing any scripts.

Client branches

Clients can maintain their own branches to integrated and use binay with their repos as the static targets (check git diff main zeam_repo). And those branches can be rebased as per client convinience whenever the main code is updated.

About

a utility to quickly spin up a localnet of lean (multi-client) nodes

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Languages