Skip to content

Validator Operations

This guide covers day-to-day operations for Ashen validator nodes: key management, monitoring, backup/restore, and common operational procedures.

For initial setup, see Running a Node. For PoA allowlist management, see PoA Policy.

Each validator holds an ed25519 keypair used for signing blocks and consensus messages. Generate one with:

Terminal window
just ed25519-keygen > validator.key.json
# Deterministic (for reproducible testnet setups)
just ed25519-keygen --seed 12345

The key file contains secret_key, public_key, and address. Store the secret key securely — it controls the validator’s identity.

See Keystore & Signatures for key storage details.

Validators participate in Distributed Key Generation (DKG) each epoch to produce a shared BLS threshold key used for:

  • Finality signatures (threshold BLS aggregation)
  • Threshold encryption keys for the private mempool

DKG runs automatically. Monitor its status via:

Terminal window
curl -s http://localhost:3030/v2/rpc \
-d '{"jsonrpc":"2.0","id":1,"method":"validator_status","params":{}}' | jq .result.dkg

Response:

{
"phase": "complete",
"epoch": 42,
"rounds_started": 42,
"rounds_completed": 41,
"rounds_failed": 1,
"fallbacks": 0
}

DKG phases: idle → commit → share → complaint → finalize → complete (or failed → fallback to deterministic keygen).

If rounds_failed increases, check peer connectivity and logs for DKG-related errors.

The node exposes three HTTP endpoints for monitoring:

EndpointPurposeResponse
GET /metricsPrometheus metricstext/plain (Prometheus format)
GET /healthLiveness probeJSON with health status
GET /readyReadiness probeJSON with sync/readiness status

These are Kubernetes-compatible. Configure probes:

livenessProbe:
httpGet:
path: /health
port: 3030
readinessProbe:
httpGet:
path: /ready
port: 3030
MetricTypeDescription
ashen_block_heightGaugeCurrent tip height
ashen_finalized_heightGaugeLatest finalized height
ashen_epochGaugeCurrent consensus epoch
ashen_peer_countGaugeConnected P2P peers
ashen_txpool_sizeGaugePending transactions
ashen_dkg_current_phaseGaugeDKG phase (0=idle..6=failed)
ashen_dkg_rounds_startedCounterTotal DKG rounds started
ashen_dkg_rounds_completedCounterSuccessful DKG rounds
ashen_poa_validators_allowedGaugeValidators in PoA allowlist
ashen_poa_missed_proposals_totalCounterMissed block proposals
ashen_consensus_verify_totalCounterVerification outcomes (success/failed)

The validator_status method returns a comprehensive operational snapshot:

Terminal window
curl -s http://localhost:3030/v2/rpc \
-d '{"jsonrpc":"2.0","id":1,"method":"validator_status","params":{}}' | jq .result

Fields returned:

FieldDescription
validator_pubkeyThis node’s public key (null if not a validator)
roleleader, validator, follower, or observer
dkgDKG phase, epoch, rounds started/completed/failed, fallbacks
syncsynced, tip/finalized heights, finalization lag, time since last block
peersConnected/inbound/outbound peer counts, banned peers
consensusEpoch, view, leader changes, blocks finalized, verifications
epoch_key_availableWhether the threshold encryption key is ready
uptime_msNode uptime
{
"healthy": true,
"block_height": 12345,
"finalized_height": 12340,
"epoch": 42,
"last_block_time_ms": 1706900000000,
"uptime_seconds": 86400,
"peer_count": 5,
"memory_rss_bytes": 524288000,
"dkg_current_epoch": 42,
"dkg_current_phase": 5,
"status": "healthy",
"issues": []
}
node-data/
├── genesis.json # Genesis configuration
├── chain/ # Block and transaction data
├── state/ # State database (accounts, storage)
├── consensus/ # Consensus state, DKG keys
└── checkpoints/ # Periodic state snapshots
  • genesis.json: immutable after init, but essential for recovery
  • Validator key file: the ed25519 secret key — most critical
  • consensus/: DKG shares and epoch keys — loss requires re-DKG
  • checkpoints/: enables fast recovery without full replay

Configure automatic checkpoint creation:

Terminal window
node run --checkpoint-interval 200 # snapshot every 200 blocks

List available checkpoints:

Terminal window
curl -s http://localhost:3030/v2/rpc \
-d '{"jsonrpc":"2.0","id":1,"method":"list_checkpoints","params":{}}' | jq .result
  1. Stop the node.
  2. Copy genesis.json and the validator key to a fresh data directory.
  3. Start the node with the checkpoint:
    Terminal window
    node run --data-dir ./restored-data --sync-from-checkpoint <height>
  4. The node will sync forward from the checkpoint.
ModeFlagDescription
Pruned (default)--prune-keep-epochs 10Keeps last N epochs
Archive--archive-modeRetains all historical state

Archive mode is required for:

  • Historical state queries
  • Analytics and indexing
  • Serving state_proof for old blocks

For disk growth projections, see Disk Growth.

  1. Generate the validator’s ed25519 keypair.
  2. Add the public key to the allowlist file.
  3. Restart nodes or wait for hot-reload.
  4. Verify: check validator_status shows the new validator.
  1. Remove the public key from the allowlist file.
  2. Restart nodes.
  3. Confirm consensus continues (need 2/3+1 remaining).
Terminal window
node --poa-allowlist /path/to/allowlist.txt --poa-exclude <pubkey_hex>

If consensus stops progressing:

  1. Check validator_status — is finalization lag growing?
  2. Check peer connectivity — are enough peers connected?
  3. Check DKG status — did a round fail?
  4. Check logs for leader_timeout or notarization_timeout.
  5. If needed, restart with adjusted timeouts:
    Terminal window
    node run --leader-timeout-ms 4000 --notarization-timeout-ms 8000
Terminal window
# Trace output for debugging
ASHEN_TRACE_OUTPUT=1 node run --data-dir ./node-data
# Trace to directory
ASHEN_TRACE_OUTPUT_DIR=target/feedback node run --data-dir ./node-data
# Rust log level
RUST_LOG=info,ashen=debug node run --data-dir ./node-data