mirror of
https://github.com/ethereum/go-ethereum.git
synced 2026-06-08 16:01:36 +00:00
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>
178 lines
5.7 KiB
Bash
Executable file
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
|