Files
proxmox/scripts/verify/verify-besu-enodes-and-ips.sh
defiQUG fbda1b4beb
Some checks failed
Deploy to Phoenix / deploy (push) Has been cancelled
docs: Ledger Live integration, contract deploy learnings, NEXT_STEPS updates
- ADD_CHAIN138_TO_LEDGER_LIVE: Ledger form done; public code review repo bis-innovations/LedgerLive; init/push commands
- CONTRACT_DEPLOYMENT_RUNBOOK: Chain 138 gas price 1 gwei, 36-addr check, TransactionMirror workaround
- CONTRACT_*: AddressMapper, MirrorManager deployed 2026-02-12; 36-address on-chain check
- NEXT_STEPS_FOR_YOU: Ledger done; steps completable now (no LAN); run-completable-tasks-from-anywhere
- MASTER_INDEX, OPERATOR_OPTIONAL, SMART_CONTRACTS_INVENTORY_SIMPLE: updates
- LEDGER_BLOCKCHAIN_INTEGRATION_COMPLETE: bis-innovations/LedgerLive reference

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-02-12 15:46:57 -08:00

238 lines
7.4 KiB
Bash

#!/usr/bin/env bash
# Verify enode addresses and IP addresses in static-nodes.json and permissions-nodes.toml.
# Ensures: (1) both files match (same enode@ip set), (2) IPs match expected VMID->IP mapping,
# (3) no duplicate node IDs (same key, different IPs).
#
# Usage: bash scripts/verify/verify-besu-enodes-and-ips.sh [--json]
# --json: output machine-readable summary only.
set -euo pipefail
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
PROJECT_ROOT="$(cd "$SCRIPT_DIR/../.." && pwd)"
cd "$PROJECT_ROOT"
STATIC_FILE="${PROJECT_ROOT}/config/besu-node-lists/static-nodes.json"
PERM_FILE="${PROJECT_ROOT}/config/besu-node-lists/permissions-nodes.toml"
# Expected IP -> VMID/role (from config/ip-addresses.conf and BESU_NODES_FILE_REFERENCE)
declare -A EXPECTED_IP
EXPECTED_IP[192.168.11.100]=1000
EXPECTED_IP[192.168.11.101]=1001
EXPECTED_IP[192.168.11.102]=1002
EXPECTED_IP[192.168.11.103]=1003
EXPECTED_IP[192.168.11.104]=1004
EXPECTED_IP[192.168.11.150]=1500
EXPECTED_IP[192.168.11.151]=1501
EXPECTED_IP[192.168.11.152]=1502
EXPECTED_IP[192.168.11.153]=1503
EXPECTED_IP[192.168.11.154]=1504
EXPECTED_IP[192.168.11.211]=2101
EXPECTED_IP[192.168.11.212]=2102
EXPECTED_IP[192.168.11.221]=2201
EXPECTED_IP[192.168.11.232]=2301
EXPECTED_IP[192.168.11.233]=2303
EXPECTED_IP[192.168.11.234]=2304
EXPECTED_IP[192.168.11.235]=2305
EXPECTED_IP[192.168.11.236]=2306
EXPECTED_IP[192.168.11.240]=2400
EXPECTED_IP[192.168.11.241]=2401
EXPECTED_IP[192.168.11.242]=2402
EXPECTED_IP[192.168.11.243]=2403
EXPECTED_IP[192.168.11.172]=2500
EXPECTED_IP[192.168.11.173]=2501
EXPECTED_IP[192.168.11.174]=2502
EXPECTED_IP[192.168.11.246]=2503
EXPECTED_IP[192.168.11.247]=2504
EXPECTED_IP[192.168.11.248]=2505
EXPECTED_IP[192.168.11.213]=1505
EXPECTED_IP[192.168.11.214]=1506
EXPECTED_IP[192.168.11.244]=1507
EXPECTED_IP[192.168.11.245]=1508
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
CYAN='\033[0;36m'
NC='\033[0m'
log_ok() { echo -e "${GREEN}[✓]${NC} $1"; }
log_warn() { echo -e "${YELLOW}[⚠]${NC} $1"; }
log_err() { echo -e "${RED}[✗]${NC} $1"; }
log_section() { echo -e "\n${CYAN}━━━ $1 ━━━${NC}\n"; }
JSON_OUT=false
[[ "${1:-}" = "--json" ]] && JSON_OUT=true
# Parse enode URLs from a line or JSON array: enode://<node_id>@<ip>:<port>
parse_enodes() {
local content="$1"
# Extract enode://...@...:30303 (optional ?discport=0 at end)
echo "$content" | grep -oE 'enode://[a-fA-F0-9]+@[0-9.]+:[0-9]+(\?discport=[0-9]+)?' | sed 's/?discport=0//' || true
}
# Get node_id (128 hex) from enode URL
node_id_from_enode() {
local enode="$1"
echo "$enode" | sed -n 's|enode://\([a-fA-F0-9]*\)@.*|\1|p'
}
# Get IP from enode URL
ip_from_enode() {
local enode="$1"
echo "$enode" | sed -n 's|enode://[a-fA-F0-9]*@\([0-9.]*\):.*|\1|p'
}
FAILED=0
if [[ ! -f "$STATIC_FILE" ]] || [[ ! -f "$PERM_FILE" ]]; then
log_err "Missing node list files: $STATIC_FILE or $PERM_FILE"
exit 1
fi
# Collect enodes from static (JSON array)
STATIC_CONTENT=$(jq -r '.[]' "$STATIC_FILE" 2>/dev/null | tr -d '"' || cat "$STATIC_FILE")
# From permissions (TOML lines with enode://)
PERM_CONTENT=$(grep -oE 'enode://[^"]+' "$PERM_FILE" 2>/dev/null || true)
STATIC_ENODES=$(parse_enodes "$STATIC_CONTENT")
PERM_ENODES=$(parse_enodes "$PERM_CONTENT")
# Build set of node_id -> ip from static
declare -A STATIC_MAP
declare -A PERM_MAP
declare -A NODE_ID_COUNT
while IFS= read -r enode; do
[[ -z "$enode" ]] && continue
nid=$(node_id_from_enode "$enode")
ip=$(ip_from_enode "$enode")
[[ -n "$nid" && -n "$ip" ]] || continue
STATIC_MAP["$nid"]="$ip"
NODE_ID_COUNT["$nid"]=$((${NODE_ID_COUNT["$nid"]:-0} + 1))
done <<< "$STATIC_ENODES"
# Reset count for perm so we count per-file
declare -A PERM_NODE_COUNT
while IFS= read -r enode; do
[[ -z "$enode" ]] && continue
nid=$(node_id_from_enode "$enode")
ip=$(ip_from_enode "$enode")
[[ -n "$nid" && -n "$ip" ]] || continue
PERM_MAP["$nid"]="$ip"
PERM_NODE_COUNT["$nid"]=$((${PERM_NODE_COUNT["$nid"]:-0} + 1))
done <<< "$PERM_ENODES"
if $JSON_OUT; then
echo '{"static_count":'${#STATIC_MAP[@]}',"perm_count":'${#PERM_MAP[@]}',"issues":[]}'
exit 0
fi
log_section "Enode and IP verification"
# 1) Duplicate node IDs (same key, different IP) — critical
log_section "1. Duplicate node IDs (same enode key, different IPs)"
DUP_FOUND=0
for nid in "${!STATIC_MAP[@]}"; do
count=${NODE_ID_COUNT["$nid"]:-0}
if [[ "$count" -gt 1 ]]; then
log_err "Duplicate node ID in static-nodes: $nid appears multiple times (IPs may differ)."
((DUP_FOUND++)) || true
fi
done
# In our list we have .240 and .241 with same ID - check by IP count per nid
declare -A ID_TO_IPS
while IFS= read -r enode; do
[[ -z "$enode" ]] && continue
nid=$(node_id_from_enode "$enode")
ip=$(ip_from_enode "$enode")
[[ -z "$nid" ]] && continue
ID_TO_IPS["$nid"]="${ID_TO_IPS["$nid"]:-} $ip"
done <<< "$STATIC_ENODES"
for nid in "${!ID_TO_IPS[@]}"; do
ips="${ID_TO_IPS[$nid]}"
num_ips=$(echo "$ips" | wc -w)
if [[ "$num_ips" -gt 1 ]]; then
log_err "Same enode key used for multiple IPs: $nid -> $ips (each node must have a unique key)."
((DUP_FOUND++)) || true
((FAILED++)) || true
fi
done
if [[ "$DUP_FOUND" -eq 0 ]]; then
log_ok "No duplicate node IDs in static-nodes."
else
log_warn "Fix: Get the real enode for each VMID (e.g. admin_nodeInfo on 2401) and ensure unique keys."
fi
# 2) Static vs permissions match
log_section "2. static-nodes.json vs permissions-nodes.toml"
MISMATCH=0
for nid in "${!STATIC_MAP[@]}"; do
sip="${STATIC_MAP[$nid]}"
pip="${PERM_MAP[$nid]:-}"
if [[ -z "$pip" ]]; then
log_err "In static but not in permissions: node_id=${nid:0:16}... @ $sip"
((MISMATCH++)) || true
elif [[ "$sip" != "$pip" ]]; then
log_err "IP mismatch for same node_id: static=$sip permissions=$pip"
((MISMATCH++)) || true
((FAILED++)) || true
fi
done
for nid in "${!PERM_MAP[@]}"; do
if [[ -z "${STATIC_MAP[$nid]:-}" ]]; then
log_err "In permissions but not in static: node_id=${nid:0:16}... @ ${PERM_MAP[$nid]}"
((MISMATCH++)) || true
fi
done
if [[ "$MISMATCH" -eq 0 ]]; then
log_ok "Static and permissions lists match (same enodes, same IPs)."
else
((FAILED++)) || true
fi
# 3) IPs match expected mapping
log_section "3. IP addresses vs expected VMID mapping"
UNKNOWN_IP=0
for nid in "${!STATIC_MAP[@]}"; do
ip="${STATIC_MAP[$nid]}"
vmid="${EXPECTED_IP[$ip]:-}"
if [[ -z "$vmid" ]]; then
log_warn "IP $ip not in expected list (add to ip-addresses.conf / BESU_NODES_FILE_REFERENCE if intentional)."
((UNKNOWN_IP++)) || true
else
log_ok "$ip -> VMID $vmid"
fi
done
if [[ "$UNKNOWN_IP" -gt 0 ]]; then
log_warn "$UNKNOWN_IP IP(s) not in expected mapping (may be intentional, e.g. .154 when added)."
fi
# 4) Expected IPs missing from list
log_section "4. Expected nodes missing from lists"
for ip in "${!EXPECTED_IP[@]}"; do
vmid="${EXPECTED_IP[$ip]}"
found=false
for nid in "${!STATIC_MAP[@]}"; do
if [[ "${STATIC_MAP[$nid]}" = "$ip" ]]; then
found=true
break
fi
done
if [[ "$found" = false ]]; then
if [[ "$vmid" = 1504 ]]; then
log_warn "192.168.11.154 (VMID 1504) not in lists — add when enode is available."
else
log_warn "Expected $ip (VMID $vmid) not in static-nodes / permissions."
fi
fi
done
log_section "Summary"
if [[ "$FAILED" -eq 0 ]]; then
log_ok "Verification passed (no critical mismatches)."
else
log_err "$FAILED critical issue(s) found. Fix duplicate enode keys and static/permissions mismatch."
exit 1
fi
exit 0