# vox1000 spec —— 协议形态与演进锚

六边形 p2p 连接框架。本卷 = 协议形态定谳 + 升级演进锚:每个可换维度
钉一条**不变式**,升级换内脏不破消费方。纪律底卷见
[const.md](const.md)(必须/禁止句式);本卷记协议事实与承诺。

## 一、三层定谳(自研边界)

| 层 | 立场 | 内容 |
|---|---|---|
| 算法层 | **遵循** | Ed25519 / AES-GCM / SHA-256 / HKDF——唯一"不可任意改"的层,单一真源 mooncry,标准测试向量对拍即门 |
| 协议层 | **全自研** | wire 帧 / 握手消息 / relay 协议 / 发现记录 / 协议 id 词表,全部自定义 |
| 架构层 | **自由** | MagicSocket 状态机形状、事件集、Endpoint 抽象、Router 形,按编排需求定 |

不变式:算法层改法 = 换算法(升版本位),不存在"改格式";架构层改的
边界只有一个——不倒退回 libp2p 形(每流协议 / 可插拔传输 / 多轮协商)。

## 二、身份面:PeerId 与签名环

- **PeerId = 32 字节 ed25519 公钥**。无 CA、无中心注册;身份即公钥,
  包装形与文本编码全自定义(`to_bytes` 先行,base32 族后议)。
- **呼叫签名环**:发起方 A 签
  `"vox1000-dial-v1" ‖ 握手消息 ‖ 对端身份 ‖ 协议串`(版本位钉在
  签名串内),应答方 B 以**对端宣称公钥**(= 其 PeerId)验签;验签
  通过后才进授权闸。

不变式:签名面钉规范化编码(确定性字节),非规范序列化不签;验签先
于授权;签名串版本位升级 = 身份绑定语义升级,旧串永不改义。

## 三、授权面:CallGate 方言

- 呼叫准入 = 回调链 **resolve → admit → audit**(verify 由保密面
  内建);`Caller{peer, protocol, from, token}` 一册全供给;
  `DIAL_OPEN` 帧携 token 段,准入拒 = 拒码 0。
- `mount_gate` 为**沉没槽**:None = 全放(测试/单机缺省);生产挂
  真闸。现成 adapter `adapter/gate_moongard`:moongard access token
  校验 + `sub == hex(PeerId)` 互核(签发方与验证方同一函数出 sub)。

不变式:授权面失效不连带身份面与保密面;政策错独立报错,禁止污染
协议错误语义;闸看不到记录层明文以外的对端内部状态。

## 四、保密面:secchan PSK-CR + 记录层

- 连接建立 = PSK-CR 三消息握手(HELLO / SALT / AUTH):HKDF 出
  **方向密钥**,记录层 AES-GCM(seq 确定性 nonce + 滑窗防重放)。
  本体住 moonkcp/secchan,本仓只座调用面——算法对拍门在 mooncry 与
  moonkcp 两处,本仓零自带密码学。
- **连接建立即已认证**:`connect` 返回即建立或报错,不存在未认证
  可收发的连接态;PSK 不符 = 拒码 2。
- 明文回放形 = `psk` 缺省沉没槽(显式 None),仅测试/回放用;生产
  必配。PSK 伸展(口令 → 种子)用 Argon2/PBKDF2 于启动期一次性
  完成,永不进每连接路径。

不变式:记录层密钥每连接独立;重放窗由滑窗原语保证;保密面可整体
替换(换 AEAD = 换 moonkcp 版本位),wire 上层零感。

## 五、wire 帧词表

缝上包格式最小族:**帧首字节 = lane**(0 = 可靠信令;余位媒体道
演进),**次字节 = 帧型**;解析带**逐型长度门**,非法/未知 = 静默弃
(best-effort 口径)。

| 型 | 名 | 载荷 |
|---|---|---|
| 1 | PROBE_REQ | nonce 8B(直连探针关联) |
| 2 | PROBE_RESP | nonce 8B(回声同 nonce) |
| 3 | DIAL_OPEN | peer 32B ‖ u16be proto_len ‖ proto ‖ u16be token_len ‖ token ‖ pskcr Hello |
| 4 | DIAL_SALT | pskcr Salt |
| 5 | DIAL_AUTH | pskcr Auth ‖ ed25519 签名 64B |
| 6 | DIAL_ACCEPT | 空(记录层密钥两侧已各自导出) |
| 7 | DIAL_REFUSE | 1B 码:0 准入拒 / 1 签名坏 / 2 PSK 误 |

不变式:帧族演进 = 追加新型不挪旧型(旧型字节含义永不变);长度门
随型走;lane≠0 的包在控制面静默弃,媒体道词汇另立不混表。

## 六、双泳道(lane 策略)

- **lane 0 可靠有序** = KCP(KcpLane 驱动 moonkcp 纯核:纯核零 IO
  零时钟,`tick(now)` 由宿主泵步进)。KCP 会话号 conv 自分配,分配
  器分诊规则:**conv 低字节非 0**(0 与 256 倍数跳过——0 留作
  demux 哨兵)。
- **lane 1 有损媒体** = 裸缝直发 + 截止即弃(过期帧不重传不排队)。
- 队头阻塞按道绕行:媒体丢包堵不住信令,信令重传不压媒体时效。

不变式:泳道是帧头位不是新连接;可靠道的确定性(纯核 + 注入钟)使
丢包重传全程可回放断言。

## 七、路径与保底(relay-bootstrap)

- **Endpoint 三分类**:Local / Public / Relay × v4/v6(表驱动
  parse/校验);直连探针以 8B nonce 关联,RTT 出 `PathQuality`。
- **保底在前**:先经 relay 通(relay-bootstrap)、直连并行打洞、
  成则静默换道(`PathSwitched` 事件)、败则 relay 续流——文案与
  实现不得标反成"直连优先"。
- 路径选择 = **纯函数** `path_select(policy, paths)`,策略可配
  (direct_bias / good_rtt_ms / degraded_rtt_ms / reject_unknown);
  决策面全同步纯函数,IO 面(收发/切道)全 async。

不变式:编排面吃 `P2pEvent` **事件集十拍**事件流(resolved /
probed / selected / established / switched / failed / closed /
announced + **punch_established / punch_abandoned**——打洞进度感知,
役2 扩:追加拍不挪旧拍,与帧族演进同律),不暴露轮询式路径查询作
编排原语(`paths()` 仅供诊断);时间一律 `now : Int64` 毫秒注入,
核心零取钟。

### 七.一、承载介质自由(役10 小憩定谳;carrier_swap_review_ming)

- **双 port 各司其职**:`SeamNet`(直连缝,包级哑管道)与
  `RelayCarrier`(中继承载,establish/send_to/recv_packet)是仅有的
  两个传输触点;引擎/归约器/流面对介质(UDP/KCP/TCP)感知 = 0,
  `Endpoint::Relay(url)` 方案表不含介质。
- **三径裁定**:直连径双桩自由(sim ↔ UdpSeam 互换,绿门三实证);
  中继径 port 边界干净、介质参数化在 moonrelay 仓内(宪修形①候役
  ——vox 消费面零改);打洞径 STUN 本质 UDP 不属换桩话题。
- **换桩纪律**:换介质 = adapter 新增一桩 + moonrelay 仓内底座
  参数化,帧线型与 version 位不动(八、0.x 兼容律);禁止介质词
  (tcp/kcp/udp)渗入 core 与事件词表。

## 八、版本位与演进承诺(0.x)

1. 每个自研协议的握手/帧头带 **version 位**;版本协商不上 = **断连
   报错,不猜**。
2. 改 wire = 升 version,**旧字节含义永不变**(追加可选、旧义不改
   ——全仓一致的家法)。
3. **0.x 兼容窗口:同 minor 内 wire 兼容;跨 minor 可断**(随
   CHANGELOG 逐版声明)。1.0 起再议长期承诺——iroh 对其生态的义务
   不是我们的义务。
4. 弃用纪律:签名串/握手版本位先行,消费方可探测后再切换。

## 九、互通立场

**明确不与 iroh / libp2p / 任何 QUIC 实现线级互通。** 禁入词表:
multiaddr / multihash / multibase / base58btc / libp2p protocol-id
路径形 / gossipsub protobuf 线格式。将来若桥接某生态:**网关层适配**
(对方协议转成连接/流面),禁止污染内核。

合规检查可加一行:内核包 grep 零外部协议词表。

## 十、依赖账与层界守卫

| 包 | 依赖白名单 |
|---|---|
| `core/` | `moonbitlang/async`(+`aqueue`,T2.3b 收执队列与 async 色)· `mooncry/lib`(律 4.1 算法层单一真源)· `moonkcp/secchan`(2026-10-30 补账裁定:PSK 挑战-响应帧安全通道——帧 E2E 安全属安全算法层,非传输介质,与 mooncry 同款豁免逻辑;实据 = gate(§十四 verify 内建)/dial(T3.3 握手)/socket(PskCrServer+SecSession)三处) |
| `adapter/kcp/` | core + moonkcp |
| `adapter/gate_moongard/` | core + moongard + mooncry |
| `adapter/sim/` | core |

不变式:**依赖审计即六边形守卫,破层即红**;核心禁止依赖具体传输、
发现实现或密码学实现;错误面 `P2pError = pub(all) suberror`,政策错
与协议错分面互不污染。依赖白名单与实际 `moon.pkg` 的对账是审计测试
的输入——白名单外新增依赖 = 先修本表再动代码。

## 十一、官方边缘端口(役28 定谳,2026-10-29)

t5 公网黄金门起的 vox1000 nat/relay 官方部署端口 = **21016-21019**
(TCP/UDP 双开成对,当前宿主 203.25.214.90):

| 端口 | 协议 | 用途 |
|---|---|---|
| 21016 | TCP | moonrelay 中继台(RelayCarrier 线面) |
| 21017 | UDP | mini-STUN 应答(NAT 探测/打洞前置) |
| 21018 | 预留 | (未来:中继 v2 / 疏散通道;役29 曾作 β 门 B 侧定口) |
| 21019 | UDP | netcheck 协调面(役30:REG/QUERY/PEER 对账表,映射交换) |

`t5_edge` 缺省绑定即此(`t5_edge [tcp_addr=0.0.0.0:21016]
[stun_addr=0.0.0.0:21017] [natcheck_addr=0.0.0.0:21019]`);端口是
部署词表,核心零感知(宪法 §2:端口/台址住 Endpoint 数据,不进代码
词表)。

## 十二、直连升径策略(役34 真网定谳,2026-10-30)

netcheck(§11 21019 对账面)判出对端 NAT 形态后,直连升径按形态选
配方;中继(RelayCarrier,§七.一)从"唯一通路"降为**判死兜底**。
真网实证:对称 CGNAT × 端口受限家宽(理论最严组合)已直连闭合
(私人实验卷 `portspray/`,git 忽略不入仓——探测技法细节住该卷,
本节只立策略架构与数据契约,零技法残留)。

**判形→配方映射**(策略表第一版,数据化候选):

| 对端形态 | 径 | 要点 |
|---|---|---|
| 双侧锥形(映射可观测) | 轻量径 | 互指直发,观测即打洞 |
| 含对称侧(朝向映射不可观测) | 相交径 | 记账相交 + 保活泵,窄池全数域覆盖 |
| 出向白名单 / UDP 受限 | relay 兜底 | 判死直落,不白试 |
| 判形未知 | 保守 | 先轻量,超时降 relay |

**统一超集状态机**(控制流形状唯一,形态只影响参数与阶段退化):
`observe → bookkeeping → probe → pump → confirm → fallback`——
锥形对 = bookkeeping 退化为单口直发;对称侧 = bookkeeping 全域
展开;各阶段参数(窗宽/节律/源口数/命中阈值)住策略数据。映射漂移
铁律:对端观测值寿命 = 一个绑定周期,**当轮观测当轮用**,禁跨轮
复用与预写(役34 实证:预写必废)。

**数据化三步时序**(防过早抽象,D-17 先例:策略表第二实现稳定后
再立):① 最小骨架代码回灌(参数顶层 let 常量,netcheck 判形调用
点接 §六 事件词表 punch_established/punch_abandoned);② 真网跑出
≥2 形态变体后立 TOML 策略表契约(parser 演化纪律:新键
optional、容忍未知键、对照测试钉漂移);③ 状态机骨架**统一退化**
覆盖形态,不引入生成器分叉(一行表养不起 gen;转移语义标签按宪法
属唯一可硬编码白名单)。

### 十二.一、开源界切口(役34 裁定:策略公共、打洞机私有、port 接入)

三面切分,**依赖倒置**——私有实现公共,公共不依赖私有:

- **策略面 → core(公共,整开)**:`NatShape` 形态词表 /
  `PunchRecipe` 参数集(字段中性:mode/span/周期/阈值)/
  判形映射 / FSM 阶段——架构词表非技法;
- **执行机 → 私有卷(不开源)**:打洞机本体(阶段执行、帧形、
  数值窗、速率、观测手法)住 git 忽略的实验模块;
- **port 接入**:core 出 `PunchEngine` port + `SimPunchEngine`
  桩(可编程成败,CI 面);私有卷 import vox1000、impl 该 port、
  自带实验装配与真网门——**公共仓无私有卷照样全绿**(构建/测试/
  发布自洽),私有卷随时可接。

同构依据:§七.一 双 port 先例(PunchEngine = SeamNet/RelayCarrier
后第三个传输触点)、§十 依赖审计即层界守卫、open_source_boundary
茗篇「层界即开源界」。已知风险与缓解:port 面首版从实证配方最小
反推,泛化字段(mode/span)防破面;私有引擎自带真网门,不入公共 CI。

### 十二.二、双发行版装配(役34-R 裁定:开关 = 装配参数,非代码分叉)

两发行版共享同一份公共源码,差异收敛在装配点:

| | 开源版(registry 发布) | 自用增强本(私有 workspace) |
|---|---|---|
| 构建 | vox1000 独立构建/测试/发布 | portspray `moon.work`(members 含 ../vox1000) |
| 打洞执行 | legacy NatPump 径(PunchSession/PunchMount,adapter/nat)→ 待收编 | `SprayPunchEngine`(私有 impl PunchEngine,相交径) |
| 开关形 | 各自装配点显式注入,零条件分支;公共构建图物理不含私有模块 |

NatPump 收编**改判**(2026-10-30):attempt 契约(一次尝试返回终态)
与 PunchSession 语义(指令流尽 + node 层连接确认)不同构——socket
收执面(receipts)包私有、established 判定在 node drive,硬包
wrapper 会造出语义劈叉的双实现(双实现安放律:身份不清不并存)。
改判:**NatPump 径记 legacy 退役候选**,收编条件 = PunchEngine 契约
扩展出步进式变体或 node 确认抽象下沉;在此之前开源版打洞 = legacy
径原样,增强版打洞 = 私有引擎,互不冒充。
