README: dokumentiere Full Mesh + Selective Abort

This commit is contained in:
Ole 2026-06-13 22:17:53 +02:00
parent 84a423cee5
commit e9ba5b5b46

View file

@ -10,6 +10,8 @@ Zwei bis N Spieler verbinden sich via WebRTC (simple-peer) und führen ein krypt
- **Trustless** Commit-Reveal-Protokoll mit SHA-256-Bindung, jeder verifiziert - **Trustless** Commit-Reveal-Protokoll mit SHA-256-Bindung, jeder verifiziert
- **QR-Bootstrapping** SDP-Offers/Answers werden als QR-Codes ausgetauscht - **QR-Bootstrapping** SDP-Offers/Answers werden als QR-Codes ausgetauscht
- **Multiplayer (2n)** Beliebig viele Teilnehmer in einer Runde - **Multiplayer (2n)** Beliebig viele Teilnehmer in einer Runde
- **Full Mesh** Alle Peers verbinden sich direkt per WebRTC (Host relayt nur initial SDP)
- **Selective Abort** Timeout erkennt Verweigerer, alle Teilnehmer sehen denselben Schuldigen
- **Coin-Animation** 3D-Münzwurf via CSS - **Coin-Animation** 3D-Münzwurf via CSS
- **100% Vanilla JS** Keine Build-Tools, kein npm, keine Abhängigkeiten außer CDN-Libs - **100% Vanilla JS** Keine Build-Tools, kein npm, keine Abhängigkeiten außer CDN-Libs
@ -32,27 +34,35 @@ Dann auf zwei (oder mehr) Geräten `http://localhost:8080` öffnen.
1. **"Raum erstellen"** QR-Code mit SDP Offer wird angezeigt 1. **"Raum erstellen"** QR-Code mit SDP Offer wird angezeigt
2. **"Antwort-QR scannen"** Kamera startet, scannt die Antwort-QRs der Beitreter 2. **"Antwort-QR scannen"** Kamera startet, scannt die Antwort-QRs der Beitreter
3. Jeder neue Spieler erscheint in der Liste 3. Jeder neue Spieler erscheint in der Liste
4. **"Münzwurf starten"** Übergang in den Spiel-Screen 4. Host broadcastet `roster` mit allen Peer-IDs → Peers bauen direktes Mesh untereinander auf
5. **"Münzwurf starten"** Protokoll beginnt (Commit → Reveal → Ergebnis) 5. Sobald alle Peers `mesh_ready` gemeldet haben → **"Münzwurf starten"** wird aktiv
6. **"Münzwurf starten"** Übergang in den Spiel-Screen
7. **"Münzwurf starten"** Protokoll beginnt (Commit → Reveal → Ergebnis)
### Beitreter ### Beitreter
1. **"Raum beitreten"** Kamera startet 1. **"Raum beitreten"** Kamera startet
2. QR des Hosts scannen 2. QR des Hosts scannen
3. **Antwort-QR zeigen** Host scannt diesen QR 3. **Antwort-QR zeigen** Host scannt diesen QR
4. Verbindung steht, warten auf Start 4. Verbindung steht, empfange `roster` mit anderen Peer-IDs
5. Protokoll läuft automatisch durch Ergebnis erscheint 5. Baue direkte WebRTC-Verbindung zu jedem anderen Peer auf (kleinere PeerId initiiert → kein Glare)
6. Sobald alle direkten Verbindungen stehen → automatisch `mesh_ready` an Host
7. Host startet Protokoll → alle laufen automatisch durch (Commit → Reveal → Ergebnis)
### Protokoll-Phasen ### Protokoll-Phasen
| Phase | Beschreibung | | Phase | Beschreibung |
|-------|-------------| |-------|-------------|
| **Commit** | Jeder Spieler generiert 32 Zufallsbytes und sendet den SHA-256-Hash an alle | | **Commit** | Jeder Spieler generiert 32 Zufallsbytes und sendet den SHA-256-Hash an alle |
| **Warten** | Sammle Commits aller Teilnehmer | | **Warten** | Sammle Commits aller Teilnehmer (Timeout 12s) |
| **Reveal** | Jeder sendet die rohen Zufallsbytes an alle | | **Reveal** | Jeder sendet die rohen Zufallsbytes an alle |
| **Warten** | Sammle Reveals aller Teilnehmer (Timeout 12s) |
| **Verify** | Jeder prüft: SHA-256(received) == stored_commit | | **Verify** | Jeder prüft: SHA-256(received) == stored_commit |
| **Result** | XOR aller Secrets → Parity (0=Kopf, 1=Zahl) | | **Result** | XOR aller Secrets → Parity (0=Kopf, 1=Zahl) |
Bei Timeout in einer Wartephase: **Selective Abort** `ABORTED`-Zustand, fehlende Peer-IDs werden angezeigt.
Alle Teilnehmer sehen dieselben fehlenden Peers (Mesh → jeder sieht, wer nicht sendet).
## Architektur ## Architektur
``` ```
@ -75,11 +85,44 @@ randomp2p/
## Netzwerk-Topologie ## Netzwerk-Topologie
**Best Case (gleiches WiFi):** **Phase 1 Stern (QR-Bootstrapping):**
QR-SDP-Austausch zwischen Host und jedem Peer. Host teilt IP-Liste → potentiell volles Mesh über `signal_relay`. Host tauscht via QR-Codes SDP Offers/Answers mit jedem Peer aus → jeder Peer ist direkt mit dem Host verbunden.
**Worst Case (NAT/Internet):** **Phase 2 Mesh (relayed Signaling):**
Stern-Topologie über den Host. Protokoll funktioniert trotzdem die Fairness ist nicht von der Topologie abhängig. Sobald ein Peer beitritt, broadcastet der Host ein `roster` mit allen Peer-IDs an das gesamte Netzwerk.
Jeder Peer baut zu jedem anderen Peer eine **direkte WebRTC-Verbindung** auf:
- **Initiator** ist immer der Peer mit der **kleineren PeerId** (verhindert Glare / Race-Conditions)
- SDP Offers/Answers werden über den **Host als Relay** ausgetauscht (`signal_relay`/`signal_relayed` via DataChannel)
- Nach erfolgreichem Verbindungsaufbau sendet jeder Peer `mesh_ready` an den Host
**Ergebnis:** Volles Mesh jeder Peer ist mit jedem direkt verbunden.
Broadcasts erreichen alle Teilnehmer in einem Hop. `expectedPeers` (für Timeout/Abort) ist auf allen identisch.
```
Host A ──QR── Peer B Host A ──star── Peer B
Host A ──QR── Peer C → Host A ──star── Peer C
Peer B ──mesh── Peer C (direkt, kein Relay)
```
### Signal-Relay-Detail
```
B (Initiator, peerId kleiner) Host A C (Responder)
│ │ │
├─ signal_relay(to:C, offer) ──────→│ │
│ ├─ signal_relayed(offer) ──→│
│ │ ├─ SimplePeer(non-init)
│ │ ├─ peer.signal(offer)
│ │ ├─ answer signal
│ │←─ signal_relay(to:B, answer) ─┤
│←── signal_relayed(answer) ────────┤ │
├─ peer.signal(answer) │ │
├─ BC direkt verbunden! │ ├─ BC direkt verbunden!
│ │ │
├─ mesh_ready ────────────────────→│←────────────────── mesh_ready ─┤
│ │ readyPeers={B,C} → Button enabled
```
## Warum ist das fair? ## Warum ist das fair?
@ -101,11 +144,11 @@ ipfs add -r .
## Ausblick / TODOs ## Ausblick / TODOs
- [ ] Volles Mesh: Peers verbinden sich direkt via relayed signaling - [x] Volles Mesh: Peers verbinden sich direkt via relayed signaling
- [ ] Timeout + Reconnect bei Verbindungsabbruch - [x] Selective Abort: Timeout bei Verweigerern
- [ ] Reconnect bei Verbindungsabbruch
- [ ] Raum-Code als Alternative zum QR-Scan - [ ] Raum-Code als Alternative zum QR-Scan
- [ ] TURN-Server-Konfiguration für NAT-Traversal - [ ] TURN-Server-Konfiguration für NAT-Traversal
- [ ] Mehrere Runden mit Historie
- [ ] PWA-Manifest + ServiceWorker für IPFS-Distribution - [ ] PWA-Manifest + ServiceWorker für IPFS-Distribution
## Lizenz ## Lizenz