Peer Discovery¶
文件角色:implementation flow 投影;圖與步驟不得另建產品規則或參數 authority。
| Implementation authority | 產品 canon/流程 | 全域索引 |
|---|---|---|
| peer-discovery.md | 配對 | 流程.md §2 |
啟動探索¶
flowchart TD
Start[App 啟動] --> KM[KeyManager 解鎖]
KM --> CreatePeer[建立 libp2p node<br/>peerId from KeyPair]
CreatePeer --> LoadBootstrap[載入玩家選定的 Bootstrap entries]
LoadBootstrap --> Source{來源}
Source -->|手動| Manual[玩家輸入]
Source -->|session| Session[邀請內 hint]
Source -->|registry| Registry[社群 registry<br/>由玩家明確選取]
Manual --> Connect[嘗試連線]
Session --> Connect
Registry --> Connect
Connect --> JoinDHT[加入 Kademlia DHT]
JoinDHT --> Subscribe[訂閱 Topics]
Subscribe --> Topics["/open4wd/CHAIN_ID/rooms/v1<br/>+動態 signaling topics"]
Topics --> Ready[Discovery 就緒]
房間發現流程¶
sequenceDiagram
participant Host as 房主
participant Pubsub as GossipSub Mesh
participant Player as 找房玩家
participant DHT
Host->>Host: 建立房間
Host->>Pubsub: publish RoomAnnouncement<br/>topic=/open4wd/CHAIN_ID/rooms/v1
Pubsub->>Player: 廣播 RoomAnnouncement
Player->>Player: 驗簽 + TTL 檢查
Player->>Player: 加入本地房間清單
Note over Player: 玩家點選房間
Player->>DHT: findPeer(host.peerId)
DHT->>Player: multiaddr
Player->>Host: WebRTC 握手 (via Signaling)
Host->>Player: DataChannel 建立
Note over Host,Player: 之後完全 P2P
NAT 穿透三層¶
flowchart TD
Peer[玩家 A] --> Try1[嘗試直連]
Try1 -->|公開 IP| Direct[Direct]
Try1 -->|私網| Try2[WebRTC + STUN]
Try2 -->|多數 NAT| Stun[STUN 穿透]
Try2 -->|嚴格 NAT| Try3[Circuit Relay v2]
Try3 --> Reserve[到 Relay node 預訂 slot]
Reserve --> Hairpin[Relay 中繼訊息]
Direct --> P2P[直接 P2P]
Stun --> P2P
Hairpin --> P2PRelay[P2P 經 Relay]
classDef local fill:#e8f3ec,stroke:#3f8f5f,stroke-width:1.4px,color:#173525;
classDef consensus fill:#fdf3df,stroke:#c08a2d,stroke-width:1.4px,color:#3d2c0d;
class Direct,Stun local
class Hairpin consensus
Peer Scoring 流程¶
graph TB
Msg[GossipSub 收到訊息] --> Score{計算 PeerScore}
Score --> Topic[topic-specific 分數]
Score --> App[appSpecificScore]
Score --> IP[ipColocationFactor]
Score --> Penalty[behaviourPenalty]
App --> Reputation[查 reputation]
App --> RepScore[依本機 reputation 注入分數]
Topic --> Sum[總分]
App --> Sum
IP --> Sum
Penalty --> Sum
Sum --> Decide{總分可接受?}
Decide -->|是| Forward[轉發 + 處理]
Decide -->|否| RateLimit[降速處理]
Decide -->|遠低於門檻| Drop[拒絕訊息/連線<br/>不自動寫入封鎖清單]
classDef local fill:#e8f3ec,stroke:#3f8f5f,stroke-width:1.4px,color:#173525;
classDef consensus fill:#fdf3df,stroke:#c08a2d,stroke-width:1.4px,color:#3d2c0d;
classDef fail fill:#fae9e7,stroke:#b4544a,stroke-width:1.4px,color:#471d18;
class Forward local
class RateLimit consensus
class Drop fail
Quick Match 房間探索¶
sequenceDiagram
participant Host as 既有房主
participant Rooms as Topic.Rooms
participant Player as Quick Match 玩家
Host->>Rooms: publish RoomAnnouncement<br/>{visibility, quickMatchEnabled,<br/>state, capacity, version, rules, ratingAnchor}
Rooms->>Player: 已驗簽 rooms snapshot
Player->>Player: 只選 public+enabled+waiting<br/>+無參賽密碼+相容 rating
Player->>Host: 一般 participant admission
Host->>Host: 最新狀態與容量 reservation 重驗
alt 成功
Host-->>Player: 進入既有 RoomId
else 競爭失敗
Host-->>Player: 拒絕
Player->>Player: 持續探索至 timeout
end
DHT 查找¶
sequenceDiagram
participant Me
participant Bucket as 我的 Routing Table
participant Peer as 鄰近 peers
participant Target
Me->>Bucket: findPeer(targetPeerId)
Bucket->>Bucket: 找最近的 K 個
Me->>Peer: 詢問 closer peers
Peer->>Me: 回傳更近的 K
loop 收斂
Me->>Peer: 再問
Peer->>Me: 更近的 K
end
Me->>Target: 找到 multiaddr
Target->>Me: 回應
Topic 訊息驗簽¶
flowchart TD
Receive[GossipSub 訊息] --> Parse{canonical DAG-CBOR decode}
Parse -->|fail| Drop1[丟棄]
Parse -->|ok| Verify{驗簽}
Verify -->|fail| Drop2[丟棄 + 扣分]
Verify -->|ok| Time{timestamp 在允許窗內?}
Time -->|fail| Drop3[丟棄 replay]
Time -->|ok| Rate{Rate limit}
Rate -->|超限| Drop4[丟棄 + 扣分]
Rate -->|ok| App{app-specific 檢查}
App -->|fail| Drop5[丟棄]
App -->|ok| Handle[處理訊息]
classDef local fill:#e8f3ec,stroke:#3f8f5f,stroke-width:1.4px,color:#173525;
classDef fail fill:#fae9e7,stroke:#b4544a,stroke-width:1.4px,color:#471d18;
class Handle local
class Drop1,Drop2,Drop3,Drop4,Drop5 fail
Bootstrap 故障切換¶
graph LR
Boot1[Bootstrap A<br/>down]
Boot2[Bootstrap B<br/>up]
Boot3[Bootstrap C<br/>up]
Selected[玩家選定的其他節點<br/>up]
Peer[新加入玩家] --> Try1
Try1 -.X.-> Boot1
Try1 --> Try2
Try2 --> Boot2
Boot2 --> Joined[加入 DHT]
Joined --> Discover[發現 Boot3 + Selected]
Discover --> Healthy[多源連線]
classDef local fill:#e8f3ec,stroke:#3f8f5f,stroke-width:1.4px,color:#173525;
classDef fail fill:#fae9e7,stroke:#b4544a,stroke-width:1.4px,color:#471d18;
class Boot2,Boot3,Selected local
class Boot1 fail
Topic 結構¶
graph TB
Root[open4wd/]
Root --> Rooms[rooms/v1<br/>RoomAnnounce/RoomClose<br/>RoomPresence/PresenceLeft]
Root --> Signal[signaling/v1/<canonical-scope><br/>signed signal-v1]
classDef consensus fill:#fdf3df,stroke:#c08a2d,stroke-width:1.4px,color:#3d2c0d;
classDef chain fill:#e7eefb,stroke:#3f6bb0,stroke-width:1.4px,color:#152848;
class Rooms chain
class Signal consensus