OverviewFilesCommitsIssuesDocsReleasesPeers

hyperswarm-peer / integration / run_layer9.sh

145 lines · bash ref:
#!/usr/bin/env bash
# Layer 9: Mesh Mode + Role-Based Authority Election
# Tests Step 6 changes: is_server()=false for all swarm peers,
# role-based authority via RPC exchange, authority transfer on disconnect.
# 3 peers with assigned roles: admin, mod, peer.
set -euo pipefail
cd "$(dirname "$0")"

echo "=== Layer 9: Mesh Mode + Role-Based Authority ==="

# Cleanup
rm -f /tmp/layer9_peer_*.txt /tmp/layer_bootstrap.txt

# Write role assignments before starting peers
echo "admin" > /tmp/layer9_peer_0_role.txt
echo "mod"   > /tmp/layer9_peer_1_role.txt
echo "peer"  > /tmp/layer9_peer_2_role.txt

# Process tracking
PIDS=()
TESTNET_PID=""

cleanup() {
    for pid in "${PIDS[@]}" "$TESTNET_PID"; do
        [ -n "$pid" ] && kill "$pid" 2>/dev/null || true
        [ -n "$pid" ] && pkill -P "$pid" 2>/dev/null || true
    done
    sleep 0.5
    for pid in "${PIDS[@]}" "$TESTNET_PID"; do
        [ -n "$pid" ] && kill -9 "$pid" 2>/dev/null || true
        [ -n "$pid" ] && pkill -9 -P "$pid" 2>/dev/null || true
    done
    wait 2>/dev/null || true
    rm -f /tmp/layer9_*.txt /tmp/layer_bootstrap.txt
}
trap cleanup EXIT

# Start testnet
echo "[orchestrator] starting DHT testnet..."
node layer2_testnet.js &
TESTNET_PID=$!

# Wait for bootstrap
for i in $(seq 1 30); do
    [ -f /tmp/layer_bootstrap.txt ] && break
    sleep 0.2
done
[ -f /tmp/layer_bootstrap.txt ] || { echo "FAIL: testnet timeout"; exit 1; }
echo "[orchestrator] testnet ready"

# Project dirs for each peer
DIRS=(project project_b project_c)

# Start 3 peers
for i in 0 1 2; do
    echo "[orchestrator] starting peer $i (${DIRS[$i]}, role=$(cat /tmp/layer9_peer_${i}_role.txt))..."
    timeout -k 10 120 godot4 --headless --path "${DIRS[$i]}" --script res://layer9_mesh_authority.gd -- --peer-index $i 2>&1 | sed "s/^/  /" &
    PIDS+=($!)
    sleep 0.5
done

# Wait for all peers to complete (max 90s — extra time for authority transfer phase)
echo "[orchestrator] waiting for all peers to complete (max 90s)..."
ELAPSED=0
ALL_PASS=false
while [ $ELAPSED -lt 90 ]; do
    ALL_PASS=true
    ANY_FAIL=false
    for i in 0 1 2; do
        STATUS=$(cat /tmp/layer9_peer_${i}_status.txt 2>/dev/null || echo "")
        if echo "$STATUS" | grep -q "^FAIL"; then
            ANY_FAIL=true
            echo "[orchestrator] Peer $i FAILED: $STATUS"
        fi
        if [ "$STATUS" != "PASS" ] && ! echo "$STATUS" | grep -q "^FAIL"; then
            ALL_PASS=false
        fi
    done

    if $ANY_FAIL; then
        echo ""
        for i in 0 1 2; do
            echo "Peer $i: $(cat /tmp/layer9_peer_${i}_status.txt 2>/dev/null || echo 'no status')"
        done
        echo "=== Layer 9: FAILED ==="
        for pid in "${PIDS[@]}"; do kill "$pid" 2>/dev/null || true; done
        exit 1
    fi

    if $ALL_PASS; then
        break
    fi

    sleep 1
    ELAPSED=$((ELAPSED + 1))
done

# Report results
echo ""
for i in 0 1 2; do
    echo "Peer $i: $(cat /tmp/layer9_peer_${i}_status.txt 2>/dev/null || echo 'no status')"
done

# Check initial authority consistency
AUTH0=$(cat /tmp/layer9_peer_0_authority.txt 2>/dev/null || echo "?")
AUTH1=$(cat /tmp/layer9_peer_1_authority.txt 2>/dev/null || echo "?")
AUTH2=$(cat /tmp/layer9_peer_2_authority.txt 2>/dev/null || echo "?")
PK0=$(cat /tmp/layer9_peer_0_pk.txt 2>/dev/null || echo "?")
if [ "$AUTH0" = "$AUTH1" ] && [ "$AUTH1" = "$AUTH2" ] && [ "$AUTH0" = "$PK0" ]; then
    echo "Initial authority: consistent (admin peer 0 = ${AUTH0:0:12}...)"
else
    echo "Initial authority: INCONSISTENT (${AUTH0:0:12} vs ${AUTH1:0:12} vs ${AUTH2:0:12}, expected ${PK0:0:12})"
fi

# Check post-disconnect authority (peers 1+2 only)
AUTH1_POST=$(cat /tmp/layer9_peer_1_authority_post.txt 2>/dev/null || echo "?")
AUTH2_POST=$(cat /tmp/layer9_peer_2_authority_post.txt 2>/dev/null || echo "?")
PK1=$(cat /tmp/layer9_peer_1_pk.txt 2>/dev/null || echo "?")
if [ "$AUTH1_POST" = "$AUTH2_POST" ] && [ "$AUTH1_POST" = "$PK1" ]; then
    echo "Post-disconnect authority: consistent (mod peer 1 = ${AUTH1_POST:0:12}...)"
else
    echo "Post-disconnect authority: INCONSISTENT (${AUTH1_POST:0:12} vs ${AUTH2_POST:0:12}, expected ${PK1:0:12})"
fi

# Check is_server verification
for i in 0 1 2; do
    IS_SERVER=$(cat /tmp/layer9_peer_${i}_is_server.txt 2>/dev/null || echo "?")
    if [ "$IS_SERVER" != "false" ]; then
        echo "WARN: Peer $i is_server=$IS_SERVER (expected false)"
    fi
done

# Final verdict
if $ALL_PASS; then
    echo "=== Layer 9: PASS ==="
else
    echo "=== Layer 9: TIMEOUT ==="
fi

if $ALL_PASS; then
    exit 0
else
    exit 1
fi