Created
June 8, 2026 18:31
-
-
Save AshwinSekar/d73ddd98e2657811dbf7543d324267d4 to your computer and use it in GitHub Desktop.
Check cluster to see what % of stake has set their BLS pubkey
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| #!/usr/bin/env bash | |
| set -euo pipefail | |
| SOLANA_BIN="${SOLANA_BIN:-$HOME/agave/bin/solana}" | |
| RPC_URL="${RPC_URL:-l}" | |
| shopt -s expand_aliases | |
| alias solana="$SOLANA_BIN -u $RPC_URL" | |
| if [[ ! -x "$SOLANA_BIN" ]]; then | |
| echo "error: Solana CLI not found or not executable: $SOLANA_BIN" >&2 | |
| exit 1 | |
| fi | |
| if ! command -v jq >/dev/null 2>&1; then | |
| echo "error: jq is required to parse solana CLI JSON output" >&2 | |
| exit 1 | |
| fi | |
| is_unset_bls_pubkey() { | |
| local value="${1:-}" | |
| [[ -z "$value" || "$value" == "null" || "$value" =~ ^1+$ ]] | |
| } | |
| lamports_to_sol() { | |
| local lamports="${1:-0}" | |
| awk -v lamports="$lamports" 'BEGIN { printf "%.9f", lamports / 1000000000 }' | |
| } | |
| stake_percent() { | |
| local stake="${1:-0}" | |
| local total="${2:-0}" | |
| awk -v stake="$stake" -v total="$total" 'BEGIN { | |
| if (total == 0) { | |
| printf "0.00" | |
| } else { | |
| printf "%.2f", (stake / total) * 100 | |
| } | |
| }' | |
| } | |
| main() { | |
| local validators_json | |
| if ! validators_json="$(solana validators --output json)"; then | |
| echo "error: failed to fetch validators from $RPC_URL" >&2 | |
| exit 1 | |
| fi | |
| local total | |
| total="$(jq '.validators | length' <<<"$validators_json")" | |
| local checked=0 | |
| local set_count=0 | |
| local unset_count=0 | |
| local error_count=0 | |
| local total_active_stake_lamports=0 | |
| local unset_stake_lamports=0 | |
| local error_stake_lamports=0 | |
| local missing=() | |
| local errors=() | |
| while IFS=$'\t' read -r identity vote_account activated_stake; do | |
| if [[ ! "$activated_stake" =~ ^[0-9]+$ ]]; then | |
| activated_stake=0 | |
| fi | |
| total_active_stake_lamports=$((total_active_stake_lamports + activated_stake)) | |
| local vote_json | |
| if ! vote_json="$(solana vote-account "$vote_account" --output json 2>&1)"; then | |
| ((error_count += 1)) | |
| error_stake_lamports=$((error_stake_lamports + activated_stake)) | |
| errors+=("$identity"$'\t'"$(head -n 1 <<<"$vote_json")") | |
| continue | |
| fi | |
| ((checked += 1)) | |
| local bls_pubkey | |
| bls_pubkey="$(jq -r '.blsPubkeyCompressed // .blsPubkey // .blsPublicKey // ""' <<<"$vote_json")" | |
| if is_unset_bls_pubkey "$bls_pubkey"; then | |
| ((unset_count += 1)) | |
| unset_stake_lamports=$((unset_stake_lamports + activated_stake)) | |
| if [[ -z "$bls_pubkey" ]]; then | |
| bls_pubkey="<missing>" | |
| fi | |
| missing+=("$identity") | |
| else | |
| ((set_count += 1)) | |
| fi | |
| done < <(jq -r '.validators[] | [.identityPubkey, .voteAccountPubkey, ((.activatedStake // 0) | tostring)] | @tsv' <<<"$validators_json") | |
| echo "Validators discovered: $total" | |
| echo "Vote accounts checked: $checked" | |
| echo "BLS pubkey set: $set_count" | |
| echo "BLS pubkey unset: $unset_count" | |
| echo "Total active stake: $(lamports_to_sol "$total_active_stake_lamports") SOL" | |
| echo "Stake with BLS pubkey unset: $(lamports_to_sol "$unset_stake_lamports") SOL ($(stake_percent "$unset_stake_lamports" "$total_active_stake_lamports")%)" | |
| if ((error_count > 0)); then | |
| echo "Vote-account query failures: $error_count" | |
| echo "Stake not checked due vote-account query failures: $(lamports_to_sol "$error_stake_lamports") SOL ($(stake_percent "$error_stake_lamports" "$total_active_stake_lamports")%)" | |
| fi | |
| if ((unset_count > 0)); then | |
| echo | |
| echo "Validators without a BLS pubkey:" | |
| printf "%s\n" "${missing[@]}" | |
| fi | |
| if ((error_count > 0)); then | |
| echo | |
| echo "Vote accounts that could not be checked:" | |
| printf "%-44s %s\n" "IDENTITY" "ERROR" | |
| printf "%-44s %s\n" "--------" "-----" | |
| printf "%s\n" "${errors[@]}" | while IFS=$'\t' read -r identity error; do | |
| printf "%-44s %s\n" "$identity" "$error" | |
| done | |
| fi | |
| } | |
| main "$@" |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment