go-ethereum/scripts/partial-state-devnet-test.sh
CPerezz c3c4dfd838
core, eth: fix post-sync block processing and BAL type compatibility
Fix the post-sync deadlock where blocks validated via BAL in newPayload
were never written to the database, causing ForkchoiceUpdated to fail
finding them and triggering infinite sync cycles.

Changes:
- Export WriteBlockWithoutState and call it after ProcessBlockWithBAL
  in newPayload, so FCU can find blocks via GetBlockByHash
- Guard SetCanonical against recoverAncestors for partial state nodes
  (they can't re-execute blocks, only apply BAL diffs)
- Auto-disable log indexing when partial state is enabled (no receipts)
- Fix BAL type field accesses to match upstream bal-devnet-2 types
  (StorageChanges, CodeChanges, BalanceChanges, Validate signature)
- Update newPayload signature (BAL now comes from ExecutableData params)
- Add partial sync scripts and documentation

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-17 12:04:09 +02:00

178 lines
5.7 KiB
Bash
Executable file

#!/bin/bash
# Partial State Devnet Test Script
#
# This script sets up a 2-node devnet to test partial state functionality.
# It starts a full node in dev mode and a partial state node that syncs from it.
#
# Usage: ./scripts/partial-state-devnet-test.sh
set -e
# Configuration
FULL_NODE_DIR="/tmp/partial-state-test/full-node"
PARTIAL_NODE_DIR="/tmp/partial-state-test/partial-node"
FULL_NODE_PORT=30303
PARTIAL_NODE_PORT=30304
FULL_NODE_RPC=8545
PARTIAL_NODE_RPC=8546
# Test contract address (will be tracked by partial node)
TRACKED_CONTRACT="0x1234567890123456789012345678901234567890"
# Colors for output
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
NC='\033[0m' # No Color
log_info() {
echo -e "${GREEN}[INFO]${NC} $1"
}
log_warn() {
echo -e "${YELLOW}[WARN]${NC} $1"
}
log_error() {
echo -e "${RED}[ERROR]${NC} $1"
}
cleanup() {
log_info "Cleaning up..."
if [ -n "$FULL_PID" ]; then
kill $FULL_PID 2>/dev/null || true
fi
if [ -n "$PARTIAL_PID" ]; then
kill $PARTIAL_PID 2>/dev/null || true
fi
wait 2>/dev/null || true
log_info "Cleanup complete"
}
trap cleanup EXIT
# Build geth if not already built
if [ ! -f "./geth" ]; then
log_info "Building geth..."
# go build ./cmd/geth
fi
# Clean up old test data
log_info "Setting up test directories..."
rm -rf /tmp/partial-state-test
mkdir -p "$FULL_NODE_DIR" "$PARTIAL_NODE_DIR"
# Start full node
log_info "Starting full node..."
./geth --datadir "$FULL_NODE_DIR" \
--dev \
--dev.period 2 \
--port $FULL_NODE_PORT \
--http --http.port $FULL_NODE_RPC \
--http.api eth,net,web3,admin \
--verbosity 2 \
--nodiscover &
FULL_PID=$!
log_info "Full node started with PID $FULL_PID"
# Wait for full node to start
log_info "Waiting for full node to initialize..."
sleep 5
# Get enode from full node
log_info "Getting enode from full node..."
for i in {1..10}; do
ENODE=$(./geth attach "$FULL_NODE_DIR/geth.ipc" --exec admin.nodeInfo.enode 2>/dev/null | tr -d '"')
if [ -n "$ENODE" ]; then
break
fi
sleep 1
done
if [ -z "$ENODE" ]; then
log_error "Failed to get enode from full node"
exit 1
fi
log_info "Full node enode: ${ENODE:0:50}..."
# Start partial state node
log_info "Starting partial state node..."
./geth --datadir "$PARTIAL_NODE_DIR" \
--port $PARTIAL_NODE_PORT \
--http --http.port $PARTIAL_NODE_RPC \
--http.api eth,net,web3 \
--partial-state \
--partial-state.contracts "$TRACKED_CONTRACT" \
--bootnodes "$ENODE" \
--networkid 1337 \
--verbosity 2 &
PARTIAL_PID=$!
log_info "Partial state node started with PID $PARTIAL_PID"
# Wait for nodes to connect
log_info "Waiting for nodes to connect..."
sleep 10
# Run tests
log_info "Running tests..."
# Test 1: Check both nodes are running
log_info "Test 1: Checking node connectivity..."
FULL_PEERS=$(curl -s -X POST --data '{"jsonrpc":"2.0","method":"net_peerCount","params":[],"id":1}' \
-H "Content-Type: application/json" localhost:$FULL_NODE_RPC | grep -o '"result":"[^"]*"' | cut -d'"' -f4)
PARTIAL_PEERS=$(curl -s -X POST --data '{"jsonrpc":"2.0","method":"net_peerCount","params":[],"id":1}' \
-H "Content-Type: application/json" localhost:$PARTIAL_NODE_RPC | grep -o '"result":"[^"]*"' | cut -d'"' -f4)
log_info "Full node peers: $FULL_PEERS, Partial node peers: $PARTIAL_PEERS"
# Test 2: Send a transaction and verify sync
log_info "Test 2: Sending test transaction..."
./geth attach "$FULL_NODE_DIR/geth.ipc" --exec "eth.sendTransaction({from: eth.coinbase, to: '$TRACKED_CONTRACT', value: web3.toWei(1, 'ether')})" 2>/dev/null || true
# Wait for block to be mined
sleep 5
# Test 3: Compare block numbers
log_info "Test 3: Comparing block numbers..."
FULL_BLOCK=$(curl -s -X POST --data '{"jsonrpc":"2.0","method":"eth_blockNumber","params":[],"id":1}' \
-H "Content-Type: application/json" localhost:$FULL_NODE_RPC | grep -o '"result":"[^"]*"' | cut -d'"' -f4)
PARTIAL_BLOCK=$(curl -s -X POST --data '{"jsonrpc":"2.0","method":"eth_blockNumber","params":[],"id":1}' \
-H "Content-Type: application/json" localhost:$PARTIAL_NODE_RPC | grep -o '"result":"[^"]*"' | cut -d'"' -f4)
log_info "Full node block: $FULL_BLOCK, Partial node block: $PARTIAL_BLOCK"
# Test 4: Compare balances
log_info "Test 4: Comparing account balances..."
FULL_BALANCE=$(curl -s -X POST --data "{\"jsonrpc\":\"2.0\",\"method\":\"eth_getBalance\",\"params\":[\"$TRACKED_CONTRACT\",\"latest\"],\"id\":1}" \
-H "Content-Type: application/json" localhost:$FULL_NODE_RPC | grep -o '"result":"[^"]*"' | cut -d'"' -f4)
PARTIAL_BALANCE=$(curl -s -X POST --data "{\"jsonrpc\":\"2.0\",\"method\":\"eth_getBalance\",\"params\":[\"$TRACKED_CONTRACT\",\"latest\"],\"id\":1}" \
-H "Content-Type: application/json" localhost:$PARTIAL_NODE_RPC | grep -o '"result":"[^"]*"' | cut -d'"' -f4)
log_info "Full node balance: $FULL_BALANCE, Partial node balance: $PARTIAL_BALANCE"
if [ "$FULL_BALANCE" = "$PARTIAL_BALANCE" ]; then
log_info "Balances match!"
else
log_warn "Balances do not match (this may be expected if partial node is still syncing)"
fi
# Summary
echo ""
log_info "========== Test Summary =========="
log_info "Full node: PID=$FULL_PID, Port=$FULL_NODE_PORT, RPC=$FULL_NODE_RPC"
log_info "Partial node: PID=$PARTIAL_PID, Port=$PARTIAL_NODE_PORT, RPC=$PARTIAL_NODE_RPC"
log_info "Tracked contract: $TRACKED_CONTRACT"
log_info ""
log_info "Database sizes:"
du -sh "$FULL_NODE_DIR/geth/chaindata" 2>/dev/null || echo " Full node: N/A"
du -sh "$PARTIAL_NODE_DIR/geth/chaindata" 2>/dev/null || echo " Partial node: N/A"
log_info "================================="
echo ""
log_info "Test complete. Press Ctrl+C to stop nodes and cleanup."
# Keep running until interrupted
wait