#!/usr/bin/env bash # Verify Deployment Script # Comprehensive verification of all deployed components set -euo pipefail # Configuration SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" source "$SCRIPT_DIR/../lib/init.sh" SCRIPT_NAME="verify-deployment.sh" SCRIPT_DESC="Run verification checks for deployed infrastructure and contracts" SCRIPT_USAGE="${SCRIPT_NAME} [--fast] [--verbose] [--help]" SCRIPT_OPTIONS="--fast Skip long-running checks\n--verbose Verbose logging\n--help Show help" SCRIPT_REQUIREMENTS="Azure CLI, jq, access to cluster contexts" handle_help "${1:-}" PROJECT_ROOT="$(cd "$SCRIPT_DIR/../.." && pwd)" # Load .env via dotenv (RPC CR/LF trim). Fallback: raw source. if [[ -f "$SCRIPT_DIR/../lib/deployment/dotenv.sh" ]]; then # shellcheck disable=SC1090 source "$SCRIPT_DIR/../lib/deployment/dotenv.sh" load_deployment_env --repo-root "${PROJECT_ROOT:-$REPO_ROOT}" elif [[ -n "${PROJECT_ROOT:-}" && -f "$PROJECT_ROOT/.env" ]]; then set -a # shellcheck disable=SC1090 source "$PROJECT_ROOT/.env" set +a elif [[ -n "${REPO_ROOT:-}" && -f "$REPO_ROOT/.env" ]]; then set -a # shellcheck disable=SC1090 source "$REPO_ROOT/.env" set +a fi CONTRACT_ADDRESSES_FILE="${PROJECT_ROOT}/contracts-deployed.json" # Load environment variables if [ -f "${PROJECT_ROOT}/.env" ]; then set -a source "${PROJECT_ROOT}/.env" set +a fi RPC_URL="${RPC_URL:-https://rpc.d-bis.org}" EXPLORER_URL="${EXPLORER_URL:-https://explorer.d-bis.org}" # Logging function log() { log_success "[$(date +'%Y-%m-%d %H:%M:%S')] $1" } error() { log_error "[ERROR] $1" return 1 } warn() { log_warn "[WARNING] $1" } info() { log_info "[INFO] $1" } # Test RPC endpoint test_rpc() { log "Testing RPC endpoint: $RPC_URL" local response=$(curl -s -X POST "$RPC_URL" \ -H "Content-Type: application/json" \ -d '{ "jsonrpc":"2.0", "method":"eth_blockNumber", "params":[], "id":1 }' 2>&1) if echo "$response" | jq -e '.result' > /dev/null 2>&1; then local block_number=$(echo "$response" | jq -r '.result') log "RPC endpoint is accessible - Current block: $block_number" return 0 else error "RPC endpoint is not accessible: $response" return 1 fi } # Test Blockscout explorer test_blockscout() { log "Testing Blockscout explorer: $EXPLORER_URL" local status_code=$(curl -s -o /dev/null -w "%{http_code}" "$EXPLORER_URL" || echo "000") if [ "$status_code" = "200" ]; then log "Blockscout explorer is accessible (HTTP $status_code)" return 0 else warn "Blockscout explorer returned HTTP $status_code (may still be starting)" return 1 fi } # Test contract deployment test_contracts() { log "Testing deployed contracts..." if [ ! -f "$CONTRACT_ADDRESSES_FILE" ]; then warn "Contract addresses file not found: $CONTRACT_ADDRESSES_FILE" return 1 fi local contracts_verified=0 local contracts_total=0 # Test WETH local weth_address=$(jq -r '.weth // empty' "$CONTRACT_ADDRESSES_FILE") if [ -n "$weth_address" ] && [ "$weth_address" != "null" ]; then contracts_total=$((contracts_total + 1)) if command -v cast &> /dev/null; then local code=$(cast code "$weth_address" --rpc-url "$RPC_URL" 2>/dev/null || echo "0x") if [ "$code" != "0x" ] && [ ${#code} -gt 2 ]; then log "WETH contract verified at: $weth_address" contracts_verified=$((contracts_verified + 1)) else warn "WETH contract code not found at: $weth_address" fi else warn "cast not installed, skipping contract verification" fi fi # Test Multicall local multicall_address=$(jq -r '.multicall // empty' "$CONTRACT_ADDRESSES_FILE") if [ -n "$multicall_address" ] && [ "$multicall_address" != "null" ]; then contracts_total=$((contracts_total + 1)) if command -v cast &> /dev/null; then local code=$(cast code "$multicall_address" --rpc-url "$RPC_URL" 2>/dev/null || echo "0x") if [ "$code" != "0x" ] && [ ${#code} -gt 2 ]; then log "Multicall contract verified at: $multicall_address" contracts_verified=$((contracts_verified + 1)) else warn "Multicall contract code not found at: $multicall_address" fi fi fi # Test Oracle local oracle_address=$(jq -r '.oracle // empty' "$CONTRACT_ADDRESSES_FILE") if [ -n "$oracle_address" ] && [ "$oracle_address" != "null" ]; then contracts_total=$((contracts_total + 1)) if command -v cast &> /dev/null; then local code=$(cast code "$oracle_address" --rpc-url "$RPC_URL" 2>/dev/null || echo "0x") if [ "$code" != "0x" ] && [ ${#code} -gt 2 ]; then log "Oracle contract verified at: $oracle_address" contracts_verified=$((contracts_verified + 1)) else warn "Oracle contract code not found at: $oracle_address" fi fi fi if [ $contracts_total -gt 0 ]; then log "Contracts verified: $contracts_verified/$contracts_total" if [ $contracts_verified -eq $contracts_total ]; then return 0 else return 1 fi else warn "No contracts found in contract addresses file" return 1 fi } # Test Kubernetes resources test_kubernetes() { log "Testing Kubernetes resources..." if ! command -v kubectl &> /dev/null; then warn "kubectl not installed, skipping Kubernetes tests" return 1 fi # Check namespace if kubectl get namespace besu-network &> /dev/null; then log "Namespace 'besu-network' exists" else error "Namespace 'besu-network' not found" return 1 fi # Check RPC pods local rpc_pods=$(kubectl get pods -n besu-network -l component=rpc --no-headers 2>/dev/null | wc -l) if [ "$rpc_pods" -gt 0 ]; then log "RPC pods: $rpc_pods" # Check if pods are ready local ready_pods=$(kubectl get pods -n besu-network -l component=rpc --no-headers 2>/dev/null | grep -c "Running" || echo "0") if [ "$ready_pods" -eq "$rpc_pods" ]; then log "All RPC pods are running" else warn "Some RPC pods are not running: $ready_pods/$rpc_pods" fi else warn "No RPC pods found" fi # Check Blockscout pods local blockscout_pods=$(kubectl get pods -n besu-network -l app=blockscout --no-headers 2>/dev/null | wc -l) if [ "$blockscout_pods" -gt 0 ]; then log "Blockscout pods: $blockscout_pods" else warn "No Blockscout pods found" fi return 0 } # Test MetaMask integration test_metamask() { log "Testing MetaMask integration..." # Check network metadata file local network_metadata="${PROJECT_ROOT}/metamask/network-metadata.json" if [ -f "$network_metadata" ]; then if jq empty "$network_metadata" 2>/dev/null; then log "Network metadata file is valid" else error "Network metadata file is invalid" return 1 fi else error "Network metadata file not found: $network_metadata" return 1 fi # Check token list file local token_list="${PROJECT_ROOT}/metamask/token-list.json" if [ -f "$token_list" ]; then if jq empty "$token_list" 2>/dev/null; then log "Token list file is valid" # Check if tokens have valid addresses local token_count=$(jq '.tokens | length' "$token_list") log "Token list contains $token_count tokens" # Check if WETH address is set local weth_address=$(jq -r '.tokens[0].address // empty' "$token_list") if [ -n "$weth_address" ] && [ "$weth_address" != "0x0000000000000000000000000000000000000000" ]; then log "WETH address is set in token list: $weth_address" else warn "WETH address is not set in token list" fi else error "Token list file is invalid" return 1 fi else error "Token list file not found: $token_list" return 1 fi return 0 } # Test DNS configuration test_dns() { log "Testing DNS configuration..." local domains=( "d-bis.org" "rpc.d-bis.org" "rpc2.d-bis.org" "explorer.d-bis.org" ) local dns_verified=0 local dns_total=${#domains[@]} for domain in "${domains[@]}"; do info "Checking DNS for: $domain" local ip=$(dig +short "$domain" A | head -n 1 || echo "") if [ -n "$ip" ]; then log "DNS resolved for $domain: $ip" dns_verified=$((dns_verified + 1)) else warn "DNS not resolved for $domain" fi done log "DNS resolution: $dns_verified/$dns_total domains" if [ $dns_verified -eq $dns_total ]; then return 0 else return 1 fi } # Generate verification report generate_report() { log "Generating verification report..." local report_file="${PROJECT_ROOT}/deployment-verification-report.md" local timestamp=$(date -u +%Y-%m-%dT%H:%M:%SZ) cat > "$report_file" <