- Introduced Aggregator.sol for Chainlink-compatible oracle functionality, including round-based updates and access control. - Added OracleWithCCIP.sol to extend Aggregator with CCIP cross-chain messaging capabilities. - Created .gitmodules to include OpenZeppelin contracts as a submodule. - Developed a comprehensive deployment guide in NEXT_STEPS_COMPLETE_GUIDE.md for Phase 2 and smart contract deployment. - Implemented Vite configuration for the orchestration portal, supporting both Vue and React frameworks. - Added server-side logic for the Multi-Cloud Orchestration Portal, including API endpoints for environment management and monitoring. - Created scripts for resource import and usage validation across non-US regions. - Added tests for CCIP error handling and integration to ensure robust functionality. - Included various new files and directories for the orchestration portal and deployment scripts.
361 lines
11 KiB
Bash
Executable File
361 lines
11 KiB
Bash
Executable File
#!/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)"
|
|
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" <<EOF
|
|
# Deployment Verification Report
|
|
|
|
Generated: $timestamp
|
|
|
|
## Test Results
|
|
|
|
### RPC Endpoint
|
|
- **URL**: $RPC_URL
|
|
- **Status**: $(test_rpc && echo "✅ PASS" || echo "❌ FAIL")
|
|
|
|
### Blockscout Explorer
|
|
- **URL**: $EXPLORER_URL
|
|
- **Status**: $(test_blockscout && echo "✅ PASS" || echo "❌ FAIL")
|
|
|
|
### Contracts
|
|
- **Status**: $(test_contracts && echo "✅ PASS" || echo "❌ FAIL")
|
|
- **Addresses File**: $CONTRACT_ADDRESSES_FILE
|
|
|
|
### Kubernetes Resources
|
|
- **Status**: $(test_kubernetes && echo "✅ PASS" || echo "❌ FAIL")
|
|
|
|
### MetaMask Integration
|
|
- **Status**: $(test_metamask && echo "✅ PASS" || echo "❌ FAIL")
|
|
|
|
### DNS Configuration
|
|
- **Status**: $(test_dns && echo "✅ PASS" || echo "❌ FAIL")
|
|
|
|
## Next Steps
|
|
|
|
1. Fix any failed tests
|
|
2. Re-run verification: ./scripts/deployment/verify-deployment.sh
|
|
3. Proceed with Ethereum-Lists PR submission
|
|
4. Proceed with token list submissions
|
|
EOF
|
|
|
|
log "Verification report generated: $report_file"
|
|
}
|
|
|
|
# Main function
|
|
main() {
|
|
log "Starting deployment verification..."
|
|
|
|
local tests_passed=0
|
|
local tests_total=6
|
|
|
|
# Run tests
|
|
test_rpc && tests_passed=$((tests_passed + 1)) || true
|
|
test_blockscout && tests_passed=$((tests_passed + 1)) || true
|
|
test_contracts && tests_passed=$((tests_passed + 1)) || true
|
|
test_kubernetes && tests_passed=$((tests_passed + 1)) || true
|
|
test_metamask && tests_passed=$((tests_passed + 1)) || true
|
|
test_dns && tests_passed=$((tests_passed + 1)) || true
|
|
|
|
# Generate report
|
|
generate_report
|
|
|
|
# Summary
|
|
log "Verification completed: $tests_passed/$tests_total tests passed"
|
|
|
|
if [ $tests_passed -eq $tests_total ]; then
|
|
log "All tests passed! Deployment is ready."
|
|
return 0
|
|
else
|
|
warn "Some tests failed. See deployment-verification-report.md for details."
|
|
return 1
|
|
fi
|
|
}
|
|
|
|
# Run main function
|
|
main "$@"
|
|
|