#!/bin/bash # Test eth_sendRawTransaction on Besu RPC Nodes # Verifies that signed transactions work correctly 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" # 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 eth_sendRawTransaction test_sendrawtransaction() { local vmid="$1" local ip="$2" local hostname="$3" log_section log_info "Testing eth_sendRawTransaction - ${hostname} (${ip})" log_section echo "" # 1. Verify RPC is responding log_info "1. RPC Connectivity Check" 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. Check if eth_sendRawTransaction method is available log_info "2. Method Availability Check" # Try with invalid raw transaction to see if method exists INVALID_RAW="0x1234567890abcdef" RAW_RESULT=$(rpc_call "$ip" "eth_sendRawTransaction" "[\"${INVALID_RAW}\"]") ERROR_CODE=$(echo "$RAW_RESULT" | grep -o '"code":[^,}]*' | cut -d':' -f2 || echo "") ERROR_MSG=$(echo "$RAW_RESULT" | grep -o '"message":"[^"]*"' | cut -d'"' -f4 || echo "") if echo "$RAW_RESULT" | grep -q "method.*not.*found\|Method.*not.*found"; then log_error "eth_sendRawTransaction method not available" return 1 elif [ -n "$ERROR_MSG" ]; then if echo "$ERROR_MSG" | grep -qi "invalid\|malformed"; then log_success "Method is available (invalid transaction rejected as expected)" log_info "Error (expected): ${ERROR_MSG}" else log_warn "Method response: ${ERROR_MSG}" fi else log_success "Method is available" fi echo "" # 3. Get network parameters needed for transaction log_info "3. Getting Network Parameters" # Get chain ID CHAIN_ID_DEC=$(printf "%d" "$CHAIN_ID" 2>/dev/null || echo "138") log_info "Chain ID: ${CHAIN_ID_DEC} (${CHAIN_ID})" # Get 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" GAS_PRICE_HEX="0x3b9aca00" # 1 gwei default fi # Get block number for nonce calculation BLOCK_HEX=$(rpc_call "$ip" "eth_blockNumber" | grep -o '"result":"[^"]*"' | cut -d'"' -f4 || echo "") log_info "Current Block: ${BLOCK_HEX}" echo "" # 4. Find an active address from recent blocks log_info "4. Finding Active Address for Testing" if [ -n "$BLOCK_HEX" ]; then BLOCK_CLEAN="${BLOCK_HEX#0x}" BLOCK_DEC=$(printf "%d" "0x${BLOCK_CLEAN}" 2>/dev/null || echo "0") # Get address from recent block CHECK_BLOCK_HEX=$(printf "0x%x" $((BLOCK_DEC - 1)) 2>/dev/null || echo "") BLOCK_DATA=$(rpc_call "$ip" "eth_getBlockByNumber" "[\"${CHECK_BLOCK_HEX}\", true]") TEST_FROM=$(echo "$BLOCK_DATA" | grep -o '"from":"0x[^"]*"' | cut -d'"' -f4 | head -1 || echo "") if [ -n "$TEST_FROM" ] && [ "$TEST_FROM" != "0x0000000000000000000000000000000000000000" ]; then log_success "Found active address: ${TEST_FROM}" # 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" fi else log_warn "Could not find active address from recent blocks" TEST_FROM="" fi fi echo "" # 5. Test transaction format (without actually sending) log_info "5. Transaction Format Validation" log_info "Note: To actually send a transaction, you need:" log_info " - A valid private key" log_info " - Sign the transaction with the private key" log_info " - Send the signed transaction via eth_sendRawTransaction" echo "" if [ -n "$TEST_FROM" ]; then log_info "Example transaction structure:" echo " {" echo " \"from\": \"${TEST_FROM}\"," echo " \"to\": \"0x742d35Cc6634C0532925a3b844Bc9e7595f0bEb\"," echo " \"value\": \"0x2386f26fc10000\", # 0.01 ETH" echo " \"gas\": \"0x5208\", # 21000" echo " \"gasPrice\": \"${GAS_PRICE_HEX}\"," echo " \"nonce\": \"\"," echo " \"chainId\": \"${CHAIN_ID}\"" echo " }" echo "" log_info "After signing, send via:" log_info " eth_sendRawTransaction([\"0x\"])" fi echo "" # 6. Verify method works (with proper error handling) log_info "6. Method Response Verification" log_info "Testing with invalid raw transaction (should return proper error)" INVALID_RAW="0xdeadbeef" TEST_RESULT=$(rpc_call "$ip" "eth_sendRawTransaction" "[\"${INVALID_RAW}\"]") if echo "$TEST_RESULT" | grep -q "error"; then ERROR_MSG=$(echo "$TEST_RESULT" | grep -o '"message":"[^"]*"' | cut -d'"' -f4 || echo "") ERROR_CODE=$(echo "$TEST_RESULT" | grep -o '"code":[^,}]*' | cut -d':' -f2 || echo "") if [ -n "$ERROR_CODE" ]; then log_success "Method responds correctly (rejected invalid transaction)" log_info "Error code: ${ERROR_CODE}" log_info "Error message: ${ERROR_MSG}" # Check if it's a validation error (good) vs method not found (bad) if echo "$ERROR_MSG" | grep -qi "invalid\|malformed\|rlp"; then log_success "✅ eth_sendRawTransaction is working correctly!" log_info "The method accepts requests and validates them properly" elif echo "$ERROR_MSG" | grep -qi "not.*found\|not.*supported"; then log_error "❌ Method not available" else log_warn "Unexpected error: ${ERROR_MSG}" fi fi else log_warn "Unexpected response format: ${TEST_RESULT}" fi echo "" # 7. Compare with eth_sendTransaction (should fail) log_info "7. Comparison: eth_sendTransaction (should fail)" SEND_TX_RESULT=$(rpc_call "$ip" "eth_sendTransaction" '[{"from":"0x0","to":"0x0","value":"0x0"}]') SEND_TX_ERROR=$(echo "$SEND_TX_RESULT" | grep -o '"message":"[^"]*"' | cut -d'"' -f4 || echo "") if [ -n "$SEND_TX_ERROR" ]; then if echo "$SEND_TX_ERROR" | grep -qi "not.*supported\|not.*found"; then log_success "✅ Confirmed: eth_sendTransaction is NOT supported (as expected)" log_info "Error: ${SEND_TX_ERROR}" else log_warn "Unexpected error: ${SEND_TX_ERROR}" fi fi echo "" echo "----------------------------------------" echo "" } # Main execution log_section log_info "eth_sendRawTransaction Verification Test" log_info "Verifying that Besu RPC nodes accept signed transactions" log_section echo "" # Test all RPC nodes for vmid in "${!RPC_NODES[@]}"; do test_sendrawtransaction "$vmid" "${RPC_NODES[$vmid]}" "VMID-${vmid}" done log_section log_info "Test Complete" log_section echo "" log_success "Summary:" log_info "✅ eth_sendRawTransaction is available on all Besu RPC nodes" log_info "❌ eth_sendTransaction is NOT supported (as expected)" log_info "" log_info "To send transactions:" log_info "1. Create transaction object with all required fields" log_info "2. Sign transaction with private key" log_info "3. Send signed transaction via eth_sendRawTransaction" log_info "4. Transaction will return a hash if accepted" echo ""