Skip to content

Instantly share code, notes, and snippets.

@fcecin
Last active June 17, 2026 18:11
Show Gist options
  • Select an option

  • Save fcecin/49f414e46ebf8dea4cda0119e229b25a to your computer and use it in GitHub Desktop.

Select an option

Save fcecin/49f414e46ebf8dea4cda0119e229b25a to your computer and use it in GitHub Desktop.
How to simulate QUIC over logos-delivery

How to simulate QUIC over logos-delivery

A from-scratch recipe to bring up a local multi-node logos-delivery network that talks QUIC, push traffic through it, and extract proof that QUIC actually carried the messages.

Prerequisites

  • Docker + Docker Compose v2 (docker compose version).
  • A QUIC-capable logos-delivery image — i.e. a build whose wakunode2 exposes --quic-support. (QUIC landed in logos-delivery PR #3951.)
  • The simulator with the QUIC_SUPPORT toggle — from PR #123 (branch feat/quic-support); on master once it merges.

Assumed already done: Docker works, and the logos-delivery image is pulled/built.

1. Get the simulator

git clone https://github.com/logos-messaging/logos-delivery-simulator.git
cd logos-delivery-simulator

2. Point at a QUIC-capable image

Pick the image (CI build, e.g. quay.io/wakuorg/nwaku-pr:3951, or a local build from docker/binaries/Dockerfile.bn.amd64). Verify it has the flag:

docker run --rm --entrypoint /usr/local/bin/wakunode2 quay.io/wakuorg/nwaku-pr:3951 --help | grep quic
# --quic-support   Enable QUIC transport: true|false [=false]
# --quic-port      QUIC (UDP) listening port. [=60000]

3. Configure .env

Compose auto-loads .env. QUIC_SUPPORT defaults to true, so QUIC is on without setting anything.

cat > .env <<'EOF'
LD_IMAGE=quay.io/wakuorg/nwaku-pr:3951
NUM_LD_NODES=5
WATCHTOWER_ENABLED=false
RPC_URL=http://foundry:8545
PRIVATE_KEY=0xac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80
ETH_FROM=0xf39fd6e51aad88f6f4ce6ab8827279cfffb92266
RLN_RELAY_MSG_LIMIT=100
RLN_RELAY_EPOCH_SEC=600
RLN_CONTRACT_REPO_COMMIT=e75ac913e579ad872f54b2225eec35d1de3d98b0
EOF

4. Bring it up

QUIC is a transport, independent of RLN, so disable RLN to keep the run focused on QUIC.

Disable RLN in run_nwaku.sh (bind-mounted; no rebuild): in the final exec /usr/bin/wakunode block, drop the --rln-relay* lines and replace the generateRlnKeystore call with true.

Bring up the QUIC pieces (RLN services skipped with --no-deps):

docker compose up -d foundry
docker compose up -d --no-deps bootstrap nwaku
docker compose up -d --no-deps rest-traffic

Give it ~40s for discovery + the gossip mesh to form.

5. Prove QUIC carried the traffic

All four checks read the node logs.

Nodes announce a QUIC address (/udp/<port>/quic-v1):

docker compose logs nwaku bootstrap | grep "Announcing addresses" | grep quic-v1
# .../ip4/10.2.0.8/tcp/60000/...  AND  .../ip4/10.2.0.8/udp/60000/quic-v1/...

Peers dial each other QUIC-first (QUIC sorted ahead of TCP):

docker compose logs nwaku | grep "Dialing peer" | grep quic-v1
# Dialing peer ... addrs="[/ip4/10.2.0.x/udp/60000/quic-v1, /ip4/10.2.0.x/tcp/60000]"

Connections are established over QUIC (identify reports the QUIC address):

docker compose logs nwaku | grep "identify: info received" | grep "observable_address=ok(/ip4/[^)]*quic-v1"

Traffic relays across the QUIC mesh — rest-traffic POSTs messages (from_peer_id=rest) that propagate node→node:

docker compose logs rest-traffic | grep "status:200"            # injector reaching nodes
docker compose logs nwaku | grep -c "received relay message"     # messages propagated

Health (should be zero):

docker compose logs nwaku | grep -ciE 'Dial failed|Unhandled exception|SIGSEGV'

Or read it from the metrics — Grafana visualizes these; query Prometheus directly:

curl -s 'http://localhost:9090/api/v1/query?query=libp2p_peers'                    # mesh: peers per node
curl -s 'http://localhost:9090/api/v1/query?query=libp2p_gossipsub_received_total'  # relay msgs per node

Grafana dashboard nwaku-monitoring: http://localhost:3001 (admin/admin).

6. Prove it's really QUIC (toggle it off and contrast)

Flip QUIC off and confirm the QUIC addresses disappear (nodes fall back to TCP and still relay):

echo "QUIC_SUPPORT=false" >> .env
docker compose up -d --no-deps --force-recreate bootstrap nwaku
sleep 35
docker compose logs --since 40s nwaku | grep "Announcing addresses" | grep -c quic-v1   # -> 0

Remove that line (or set true) and recreate to bring QUIC back. The before/after is the cleanest proof the --quic-support flag is what put QUIC on the wire.

Cleanup

docker compose down -v

Notes

  • Each container is its own network namespace, so every node uses the same default ports (TCP+QUIC on 60000, REST 8645, discv5 9000) with no collisions.
  • QUIC_SUPPORT=false also lets the sim run images that predate --quic-support (the flag is simply omitted).
  • This validates QUIC functionally at small scale. Large-connection / scaling behavior is not in this scope.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment