Files
universe/scripts/kms-gen-validator-keys.sh
zeekayandHanzo Dev 8c6119f357 Lux zones match the live DNS; KMS scripts name their endpoint; explorer rollouts keep a pod serving
k8s/dns is re-exported from the live zones: bridge.lux.network, the ACME TXT
left for bridge, bridge-api, mpc and api.mpc, lux.chat's Azure asuid records and
the GoDaddy _domainconnect CNAMEs on lux.review and lux.training are gone, and
lux.build lists the AWS ingress it has pointed at since 2026-09-19.

kms.lux.cloud has no AWS backend: Lux's own KMS (lux-kms-go) runs on no cluster
here. kms-gen-validator-keys.sh and kms-seed.sh no longer default to it; they
require KMS_API_URL, because a default that does not resolve turned every key
push into a "SKIP" line. NETWORKS.yaml stops listing mpc-api.lux.network,
mpc.lux.network and kms.lux.cloud for the MPC topology.

explore-fe-lux and explore-fe-zoo run one replica each; with maxUnavailable 1 a
rollout stopped the only pod before its replacement was Ready, and the explorer
answered 503 until it was. maxUnavailable is 0 now, as applied live.

Co-authored-by: Hanzo Dev <[email protected]>
2026-09-23 19:45:42 -07:00

135 lines
5.0 KiB
Bash
Executable File

#!/usr/bin/env bash
# kms-gen-validator-keys.sh — Generate and store validator staking keys in KMS
#
# The lux-operator uses KMS to source staking keys for new validator pods.
# When scaling from 5→8 validators, nodes 5-7 need new staking keys.
#
# Key types per validator:
# - EC (secp256k1): TLS staker cert + key (staker.crt / staker.key)
# - BLS: Consensus signer key (signer.key)
#
# Usage:
# ./scripts/kms-gen-validator-keys.sh [start_index] [end_index] [network]
# ./scripts/kms-gen-validator-keys.sh 5 8 mainnet
#
# Prerequisites:
# - lux CLI installed
# - KMS CLI authenticated (kms login)
# - KMS_PROJECT_ID and KMS_API_URL set
set -euo pipefail
START=${1:-5}
END=${2:-7}
NETWORK=${3:-mainnet}
KMS_API="${KMS_API_URL:-}"
PROJECT="${KMS_PROJECT_ID:-}"
# Pushing keys needs an endpoint named by the operator. There is no default: a
# default that stops resolving turns every push below into a "SKIP" line.
if [ -n "$PROJECT" ] && [ -z "$KMS_API" ]; then
echo "ERROR: KMS_API_URL is required with KMS_PROJECT_ID (the KMS the keys are written to)"
exit 1
fi
MNEMONIC="${LUX_MNEMONIC:-}"
if [ -z "$MNEMONIC" ]; then
echo "ERROR: LUX_MNEMONIC is required (source from KMS, never hardcode)"
exit 1
fi
echo "=== Generate Validator Keys for KMS ==="
echo "Validators: $START to $END"
echo "Network: $NETWORK"
echo "KMS: $KMS_API"
echo ""
for i in $(seq "$START" "$END"); do
KEY_NAME="validator-$i"
echo "--- Generating $KEY_NAME ---"
# Generate key from mnemonic at unique account index
lux key create "$KEY_NAME" \
--phrase "$MNEMONIC" \
--account "$i" \
2>/dev/null || echo "Key $KEY_NAME may already exist"
# Extract key details
NODE_ID=$(lux key show "$KEY_NAME" 2>/dev/null | grep "NodeID:" | awk '{print $2}')
BLS_PUB=$(lux key show "$KEY_NAME" 2>/dev/null | grep -A1 "BLS" | grep "Public Key:" | awk '{print $3}')
BLS_POP=$(lux key show "$KEY_NAME" 2>/dev/null | grep -A2 "BLS" | grep "PoP:" | awk '{print $2}')
EC_ADDR=$(lux key show "$KEY_NAME" 2>/dev/null | grep "Address:" | head -1 | awk '{print $2}')
echo " NodeID: $NODE_ID"
echo " BLS Pub: ${BLS_PUB:0:20}..."
echo " Address: $EC_ADDR"
# Export staking materials
STAKING_DIR="$HOME/.lux/keys/$KEY_NAME/staking"
if [ -d "$STAKING_DIR" ]; then
echo " Staking dir: $STAKING_DIR"
else
echo " Warning: No staking directory found"
fi
# Push to KMS if project ID is set
if [ -n "$PROJECT" ]; then
echo " Pushing to KMS..."
# Store NodeID
KMS_API_URL="$KMS_API" kms secrets set "NODE_ID_$i=$NODE_ID" \
--projectId "$PROJECT" --env "$NETWORK" --secret-path "/staking" 2>/dev/null \
&& echo " OK: NODE_ID_$i" || echo " SKIP: NODE_ID_$i (already exists?)"
# Store BLS public key
KMS_API_URL="$KMS_API" kms secrets set "BLS_PUB_$i=$BLS_PUB" \
--projectId "$PROJECT" --env "$NETWORK" --secret-path "/staking" 2>/dev/null \
&& echo " OK: BLS_PUB_$i" || echo " SKIP: BLS_PUB_$i"
# Store BLS proof of possession
KMS_API_URL="$KMS_API" kms secrets set "BLS_POP_$i=$BLS_POP" \
--projectId "$PROJECT" --env "$NETWORK" --secret-path "/staking" 2>/dev/null \
&& echo " OK: BLS_POP_$i" || echo " SKIP: BLS_POP_$i"
# Store staking cert/key (base64 encoded)
if [ -f "$STAKING_DIR/staker.crt" ]; then
CERT_B64=$(base64 < "$STAKING_DIR/staker.crt")
KMS_API_URL="$KMS_API" kms secrets set "STAKER_CRT_$i=$CERT_B64" \
--projectId "$PROJECT" --env "$NETWORK" --secret-path "/staking" 2>/dev/null \
&& echo " OK: STAKER_CRT_$i" || echo " SKIP: STAKER_CRT_$i"
fi
if [ -f "$STAKING_DIR/staker.key" ]; then
KEY_B64=$(base64 < "$STAKING_DIR/staker.key")
KMS_API_URL="$KMS_API" kms secrets set "STAKER_KEY_$i=$KEY_B64" \
--projectId "$PROJECT" --env "$NETWORK" --secret-path "/staking" 2>/dev/null \
&& echo " OK: STAKER_KEY_$i" || echo " SKIP: STAKER_KEY_$i"
fi
# Store BLS signer key (base64 encoded)
BLS_DIR="$HOME/.lux/keys/$KEY_NAME/bls"
if [ -f "$BLS_DIR/private.key" ]; then
SIGNER_B64=$(base64 < "$BLS_DIR/private.key")
KMS_API_URL="$KMS_API" kms secrets set "SIGNER_KEY_$i=$SIGNER_B64" \
--projectId "$PROJECT" --env "$NETWORK" --secret-path "/staking" 2>/dev/null \
&& echo " OK: SIGNER_KEY_$i" || echo " SKIP: SIGNER_KEY_$i"
fi
else
echo " KMS_PROJECT_ID not set — keys stored locally only"
echo " Set KMS_PROJECT_ID to push to KMS"
fi
echo ""
done
echo "=== Summary ==="
echo "Generated keys for validators $START-$END"
echo "Network: $NETWORK"
if [ -n "$PROJECT" ]; then
echo "Keys stored in KMS project: $PROJECT (env: $NETWORK, path: /staking)"
else
echo "Keys stored locally in ~/.lux/keys/"
echo "Run with KMS_PROJECT_ID=<id> to push to KMS"
fi
echo ""
echo "Next steps:"
echo " 1. Deploy KMS: kubectl apply -k k8s/lux-k8s/kms/"
echo " 2. Apply validator scale: kubectl apply -f k8s/lux-k8s/validators/statefulset.yaml"
echo " 3. The lux-operator will provision new pods with KMS-backed keys"
echo " 4. Register validators on P-Chain via wallet.lux.network"