Files
super_ball_thrower/tests/test_multi_hop.sh
2025-12-17 09:43:21 -04:00

169 lines
5.8 KiB
Bash
Executable File

#!/bin/bash
# Test SUP-02: Multi-Hop Routing
# Tests: Builder → Thrower A → Thrower B → Thrower C → Final Relay
set -e
TEST_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
source "$TEST_DIR/helpers/timing_utils.sh"
source "$TEST_DIR/helpers/event_utils.sh"
# Load test configuration
KEYS_FILE="$TEST_DIR/fixtures/test_keys.json"
RELAYS_FILE="$TEST_DIR/fixtures/test_relays.json"
# Extract keys
BUILDER_PRIVKEY=$(jq -r '.builder.privkey' "$KEYS_FILE")
THROWER_A_PRIVKEY=$(jq -r '.thrower_a.privkey' "$KEYS_FILE")
THROWER_A_PUBKEY=$(jq -r '.thrower_a.pubkey' "$KEYS_FILE")
THROWER_B_PRIVKEY=$(jq -r '.thrower_b.privkey' "$KEYS_FILE")
THROWER_B_PUBKEY=$(jq -r '.thrower_b.pubkey' "$KEYS_FILE")
THROWER_C_PRIVKEY=$(jq -r '.thrower_c.privkey' "$KEYS_FILE")
THROWER_C_PUBKEY=$(jq -r '.thrower_c.pubkey' "$KEYS_FILE")
# Extract relays
THROWER_A_RELAY=$(jq -r '.test_scenarios.multi_hop_3.thrower_a_relay' "$RELAYS_FILE")
THROWER_B_RELAY=$(jq -r '.test_scenarios.multi_hop_3.thrower_b_relay' "$RELAYS_FILE")
THROWER_C_RELAY=$(jq -r '.test_scenarios.multi_hop_3.thrower_c_relay' "$RELAYS_FILE")
FINAL_RELAY=$(jq -r '.test_scenarios.multi_hop_3.final_relay' "$RELAYS_FILE")
echo "=== SUP-02: Multi-Hop Routing Test (3 hops) ==="
echo "Thrower A: $THROWER_A_PUBKEY$THROWER_A_RELAY"
echo "Thrower B: $THROWER_B_PUBKEY$THROWER_B_RELAY"
echo "Thrower C: $THROWER_C_PUBKEY$THROWER_C_RELAY"
echo "Final Relay: $FINAL_RELAY"
echo ""
# Test parameters
DELAY_A=2
DELAY_B=2
DELAY_C=2
TOTAL_DELAY=$((DELAY_A + DELAY_B + DELAY_C))
AUDIT_TAG="test-multi-hop-3-$(date +%s)"
TEST_CONTENT="Multi-hop test message at $(date)"
echo "Step 1: Create innermost kind 1 event"
INNER_EVENT=$(create_test_event "$BUILDER_PRIVKEY" "$TEST_CONTENT")
INNER_EVENT_ID=$(echo "$INNER_EVENT" | jq -r '.id')
echo "Created inner event: $INNER_EVENT_ID"
echo ""
echo "Step 2: Build onion routing layers (inside-out)"
echo ""
# Layer 3 (innermost): Routing from C to final relay
echo "Layer 3: Thrower C → Final Relay"
ROUTING_C=$(create_routing_payload "$INNER_EVENT" "$FINAL_RELAY" "$DELAY_C" "null" "$AUDIT_TAG")
ENCRYPTED_C=$(encrypt_payload "$BUILDER_PRIVKEY" "$THROWER_C_PUBKEY" "$ROUTING_C")
WRAPPER_C=$(create_routing_event "$BUILDER_PRIVKEY" "$THROWER_C_PUBKEY" "$ENCRYPTED_C")
echo " Delay: ${DELAY_C}s"
echo ""
# Layer 2: Routing from B to C
echo "Layer 2: Thrower B → Thrower C"
ROUTING_B=$(create_routing_payload "$WRAPPER_C" "$THROWER_C_RELAY" "$DELAY_B" "$THROWER_C_PUBKEY" "$AUDIT_TAG")
ENCRYPTED_B=$(encrypt_payload "$BUILDER_PRIVKEY" "$THROWER_B_PUBKEY" "$ROUTING_B")
WRAPPER_B=$(create_routing_event "$BUILDER_PRIVKEY" "$THROWER_B_PUBKEY" "$ENCRYPTED_B")
echo " Delay: ${DELAY_B}s"
echo ""
# Layer 1 (outermost): Routing from A to B
echo "Layer 1: Thrower A → Thrower B"
ROUTING_A=$(create_routing_payload "$WRAPPER_B" "$THROWER_B_RELAY" "$DELAY_A" "$THROWER_B_PUBKEY" "$AUDIT_TAG")
ENCRYPTED_A=$(encrypt_payload "$BUILDER_PRIVKEY" "$THROWER_A_PUBKEY" "$ROUTING_A")
WRAPPER_A=$(create_routing_event "$BUILDER_PRIVKEY" "$THROWER_A_PUBKEY" "$ENCRYPTED_A")
WRAPPER_A_ID=$(echo "$WRAPPER_A" | jq -r '.id')
echo " Delay: ${DELAY_A}s"
echo " Routing event ID: $WRAPPER_A_ID"
echo ""
echo "Step 3: Publish initial routing event to Thrower A"
PUBLISH_TIME=$(get_timestamp)
publish_event "$WRAPPER_A" "$THROWER_A_RELAY"
echo "Published at: $(date -d @$PUBLISH_TIME)"
echo ""
echo "Step 4: Monitor routing chain"
echo "Expected total delay: ${TOTAL_DELAY}s (minimum)"
echo "Monitoring for inner event on final relay..."
echo ""
# Monitor for the inner event on final relay
TIMEOUT=$((TOTAL_DELAY + 60)) # Total delay + 60 seconds buffer
FOUND=false
START_MONITOR=$(get_timestamp)
while [ $(($(get_timestamp) - START_MONITOR)) -lt $TIMEOUT ]; do
if query_event "$INNER_EVENT_ID" "$FINAL_RELAY" 2 | grep -q "$INNER_EVENT_ID"; then
ARRIVAL_TIME=$(get_timestamp)
FOUND=true
break
fi
# Show progress every 5 seconds
ELAPSED=$(($(get_timestamp) - PUBLISH_TIME))
if [ $((ELAPSED % 5)) -eq 0 ]; then
echo " Elapsed: ${ELAPSED}s / Expected: ${TOTAL_DELAY}s+"
fi
sleep 1
done
if [ "$FOUND" = false ]; then
echo "ERROR: Inner event not found on final relay within ${TIMEOUT}s"
echo "This could indicate:"
echo " - One or more throwers are not running"
echo " - Routing chain is broken"
echo " - Network connectivity issues"
exit 1
fi
echo ""
echo "Step 5: Verify timing"
ACTUAL_DELAY=$((ARRIVAL_TIME - PUBLISH_TIME))
echo "Actual total delay: ${ACTUAL_DELAY}s"
echo "Expected minimum: ${TOTAL_DELAY}s"
if [ $ACTUAL_DELAY -lt $TOTAL_DELAY ]; then
echo "ERROR: Event arrived too early!"
echo "Expected at least ${TOTAL_DELAY}s, got ${ACTUAL_DELAY}s"
exit 1
fi
# Check if delay is reasonable (not more than 3x expected + 30s buffer)
MAX_DELAY=$((TOTAL_DELAY * 3 + 30))
if [ $ACTUAL_DELAY -gt $MAX_DELAY ]; then
echo "WARNING: Event took much longer than expected"
echo "Actual: ${ACTUAL_DELAY}s, Maximum expected: ${MAX_DELAY}s"
fi
echo ""
echo "Step 6: Verify event content"
FINAL_EVENT=$(query_event "$INNER_EVENT_ID" "$FINAL_RELAY" 5)
FINAL_CONTENT=$(echo "$FINAL_EVENT" | jq -r '.content')
if [ "$FINAL_CONTENT" != "$TEST_CONTENT" ]; then
echo "ERROR: Content mismatch!"
echo "Expected: $TEST_CONTENT"
echo "Got: $FINAL_CONTENT"
exit 1
fi
echo "Content verified: $FINAL_CONTENT"
echo ""
echo "Step 7: Verify hop sequence (optional - requires relay monitoring)"
echo "Note: Full hop verification requires monitoring intermediate relays"
echo "This test verifies end-to-end delivery through 3 hops"
echo ""
echo "=== TEST PASSED ==="
echo "✓ 3-hop routing successful"
echo "✓ Total delay constraint respected (${ACTUAL_DELAY}s >= ${TOTAL_DELAY}s)"
echo "✓ Event content preserved through all hops"
echo "✓ Onion routing layers properly unwrapped"
echo "✓ Event published to correct final relay"
echo ""
exit 0