#!/bin/bash # Test Simple Transfer on RPC Nodes # Identifies why simple transfers are failing without getting a hash set -euo pipefail SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" # Colors RED='\033[0;31m' GREEN='\033[0;32m' YELLOW='\033[1;33m' BLUE='\033[0;34m' CYAN='\033[0;36m' NC='\033[0m' log_info() { echo -e "${BLUE}[INFO]${NC} $1"; } log_success() { echo -e "${GREEN}[✓]${NC} $1"; } log_warn() { echo -e "${YELLOW}[⚠]${NC} $1"; } log_error() { echo -e "${RED}[✗]${NC} $1"; } log_section() { echo -e "${CYAN}════════════════════════════════════════${NC}"; } # RPC Nodes declare -A RPC_NODES RPC_NODES[2500]="192.168.11.250" RPC_NODES[2501]="192.168.11.251" RPC_NODES[2502]="192.168.11.252" RPC_NODES[2400]="192.168.11.240" PROXMOX_HOST="${PROXMOX_HOST:-192.168.11.10}" # Function to execute RPC call rpc_call() { local ip="$1" local method="$2" local params="${3:-[]}" local port="${4:-8545}" curl -s -X POST "http://${ip}:${port}" \ -H 'Content-Type: application/json' \ -d "{\"jsonrpc\":\"2.0\",\"method\":\"${method}\",\"params\":${params},\"id\":1}" 2>/dev/null || echo "{\"error\":\"connection_failed\"}" } # Function to test transfer on node test_transfer() { local vmid="$1" local ip="$2" local hostname="$3" log_section log_info "Testing Simple Transfer - ${hostname} (${ip})" log_section echo "" # 1. Check RPC is responding log_info "1. RPC Connectivity" CHAIN_ID=$(rpc_call "$ip" "eth_chainId" | grep -o '"result":"[^"]*"' | cut -d'"' -f4 || echo "") if [ -z "$CHAIN_ID" ]; then log_error "RPC not responding" return 1 fi log_success "RPC responding - Chain ID: ${CHAIN_ID}" echo "" # 2. Get a test account with balance log_info "2. Finding Test Account with Balance" # Try to get accounts (if eth_accounts is enabled) ACCOUNTS=$(rpc_call "$ip" "eth_accounts" | grep -o '"result":\[[^]]*\]' | grep -o '0x[^"]*' || echo "") if [ -z "$ACCOUNTS" ]; then log_warn "eth_accounts not available, checking recent blocks for addresses" # Get recent block to find addresses BLOCK_HEX=$(rpc_call "$ip" "eth_blockNumber" | grep -o '"result":"[^"]*"' | cut -d'"' -f4 || echo "") if [ -n "$BLOCK_HEX" ]; then BLOCK_DATA=$(rpc_call "$ip" "eth_getBlockByNumber" "[\"${BLOCK_HEX}\", true]") FROM_ADDR=$(echo "$BLOCK_DATA" | grep -o '"from":"0x[^"]*"' | cut -d'"' -f4 | head -1 || echo "") if [ -n "$FROM_ADDR" ]; then log_info "Found address in recent block: ${FROM_ADDR}" TEST_FROM="$FROM_ADDR" else log_warn "Could not find test address, using placeholder" TEST_FROM="0x0000000000000000000000000000000000000000" fi else log_warn "Could not get block number" TEST_FROM="0x0000000000000000000000000000000000000000" fi else TEST_FROM=$(echo "$ACCOUNTS" | head -1) log_success "Using account: ${TEST_FROM}" fi # Check balance BALANCE_HEX=$(rpc_call "$ip" "eth_getBalance" "[\"${TEST_FROM}\",\"latest\"]" | grep -o '"result":"[^"]*"' | cut -d'"' -f4 || echo "") if [ -n "$BALANCE_HEX" ]; then BALANCE_DEC=$(printf "%d" "$BALANCE_HEX" 2>/dev/null || echo "0") BALANCE_ETH=$(echo "scale=4; $BALANCE_DEC / 1000000000000000000" | bc 2>/dev/null || echo "0") log_info "Balance: ${BALANCE_ETH} ETH" if [ "$BALANCE_DEC" -eq 0 ]; then log_warn "Account has zero balance - cannot test transfer" echo "" return 0 fi fi echo "" # 3. Get nonce log_info "3. Getting Transaction Nonce" NONCE_HEX=$(rpc_call "$ip" "eth_getTransactionCount" "[\"${TEST_FROM}\",\"latest\"]" | grep -o '"result":"[^"]*"' | cut -d'"' -f4 || echo "") if [ -n "$NONCE_HEX" ]; then NONCE_DEC=$(printf "%d" "$NONCE_HEX" 2>/dev/null || echo "0") log_success "Nonce: ${NONCE_DEC} (${NONCE_HEX})" else log_error "Could not get nonce" echo "" return 1 fi echo "" # 4. Get gas price log_info "4. Getting Gas Price" GAS_PRICE_HEX=$(rpc_call "$ip" "eth_gasPrice" | grep -o '"result":"[^"]*"' | cut -d'"' -f4 || echo "") if [ -n "$GAS_PRICE_HEX" ]; then GAS_PRICE_DEC=$(printf "%d" "$GAS_PRICE_HEX" 2>/dev/null || echo "0") GAS_PRICE_GWEI=$(echo "scale=2; $GAS_PRICE_DEC / 1000000000" | bc 2>/dev/null || echo "0") log_success "Gas Price: ${GAS_PRICE_GWEI} gwei (${GAS_PRICE_HEX})" else log_warn "Could not get gas price, using default" GAS_PRICE_HEX="0x3b9aca00" # 1 gwei fi echo "" # 5. Prepare test transfer log_info "5. Preparing Test Transfer" TEST_TO="0x742d35Cc6634C0532925a3b844Bc9e7595f0bEb" # Test address TEST_VALUE="0x2386f26fc10000" # 0.01 ETH TRANSFER_DATA="{ \"from\": \"${TEST_FROM}\", \"to\": \"${TEST_TO}\", \"value\": \"${TEST_VALUE}\", \"gas\": \"0x5208\", \"gasPrice\": \"${GAS_PRICE_HEX}\", \"nonce\": \"${NONCE_HEX}\" }" log_info "From: ${TEST_FROM}" log_info "To: ${TEST_TO}" log_info "Value: 0.01 ETH" echo "" # 6. Try to send transaction (unsigned - will fail but shows validation) log_info "6. Testing Transaction Validation" log_warn "Note: This will fail without private key, but shows if RPC accepts the transaction format" # Try eth_sendTransaction (requires unlocked account or will fail) SEND_RESULT=$(rpc_call "$ip" "eth_sendTransaction" "[${TRANSFER_DATA}]") ERROR_CODE=$(echo "$SEND_RESULT" | grep -o '"code":[^,}]*' | cut -d':' -f2 || echo "") ERROR_MSG=$(echo "$SEND_RESULT" | grep -o '"message":"[^"]*"' | cut -d'"' -f4 || echo "") if [ -n "$ERROR_CODE" ]; then log_error "Transaction rejected with code: ${ERROR_CODE}" log_error "Error message: ${ERROR_MSG}" # Analyze error codes case "$ERROR_CODE" in -32000) log_warn "Error -32000: Invalid input or transaction rejected" ;; -32003) log_warn "Error -32003: Transaction rejected (pre-pool validation)" ;; -32009) log_warn "Error -32009: Gas price below minimum" ;; -32602) log_warn "Error -32602: Invalid params" ;; -32603) log_warn "Error -32603: Internal error" ;; esac else TX_HASH=$(echo "$SEND_RESULT" | grep -o '"result":"0x[^"]*"' | cut -d'"' -f4 || echo "") if [ -n "$TX_HASH" ]; then log_success "Transaction accepted! Hash: ${TX_HASH}" else log_warn "Unexpected response: ${SEND_RESULT}" fi fi echo "" # 7. Check account permissioning log_info "7. Checking Account Permissioning" PERM_CHECK=$(ssh -o StrictHostKeyChecking=no -o ConnectTimeout=5 root@"$PROXMOX_HOST" \ "pct exec ${vmid} -- grep -i 'permissions-accounts-config-file-enabled' /etc/besu/*.toml 2>/dev/null | head -1" 2>/dev/null || echo "") if [ -n "$PERM_CHECK" ]; then if echo "$PERM_CHECK" | grep -qi "true"; then log_warn "Account permissioning is ENABLED" log_info "Config: ${PERM_CHECK}" else log_success "Account permissioning is DISABLED" fi else log_warn "Could not check permissioning config" fi echo "" # 8. Check minimum gas price log_info "8. Checking Minimum Gas Price Configuration" MIN_GAS=$(ssh -o StrictHostKeyChecking=no -o ConnectTimeout=5 root@"$PROXMOX_HOST" \ "pct exec ${vmid} -- grep -i 'min-gas-price' /etc/besu/*.toml 2>/dev/null | head -1" 2>/dev/null || echo "") if [ -n "$MIN_GAS" ]; then log_info "Min gas price config: ${MIN_GAS}" else log_info "No minimum gas price configured (using default)" fi echo "" # 9. Check recent logs for transaction rejections log_info "9. Recent Transaction Rejection Logs" REJECTIONS=$(ssh -o StrictHostKeyChecking=no -o ConnectTimeout=5 root@"$PROXMOX_HOST" \ "pct exec ${vmid} -- journalctl -u besu-rpc --since '10 minutes ago' --no-pager 2>/dev/null | grep -iE 'reject|invalid|underpriced|permission' | tail -10" 2>/dev/null || echo "") if [ -z "$REJECTIONS" ]; then log_info "No recent rejection messages in logs" else log_warn "Recent rejection messages:" echo "$REJECTIONS" | while IFS= read -r line; do echo " $line" done fi echo "" echo "----------------------------------------" echo "" } # Main execution log_section log_info "Simple Transfer Failure Investigation" log_info "Testing why transfers fail without getting a hash" log_section echo "" # Test on primary RPC nodes test_transfer "2500" "${RPC_NODES[2500]}" "besu-rpc-1" test_transfer "2501" "${RPC_NODES[2501]}" "besu-rpc-2" test_transfer "2502" "${RPC_NODES[2502]}" "besu-rpc-3" log_section log_info "Investigation Complete" log_section echo "" log_info "Key Areas to Check:" log_info "1. Account permissioning configuration" log_info "2. Minimum gas price settings" log_info "3. Transaction validation errors" log_info "4. RPC method availability" echo ""