D-20260815-03|Canonical fold 自包含比賽結算¶
背景與驅動力¶
OrbitDB public-write ledger 允許節點直接 append 已超過 live 時戳窗的事件。舊模型只在首播 live gate 依事件指定的 baseLogHeadCids 回查歷史 state、驗證 anchor CID 與重算事件內 economySettlement;timeless fold 則只驗名單、loadout 與外層多簽。攻擊者因此可用自控 roster 與語法合法的假 anchor/base,讓舊時戳事件跳過 live 重算,再由 reducer 直接套用自選 payout。舊月硬頂也只在「套用前已達頂」時擋住事件,未把本次 incoming mint 納入判定。
根因不是單一漏判,而是 D-20260703-08 的 live-only 回查、D-20260708-05 的 timeless 邊界與 D-20260709-01 的事後硬頂組合後,沒有形成歷史 append 可安全重放的完整 trust model。
考慮過的選項¶
- 把
deriveStateAt(baseLogHeadCids)搬進 fold:拒絕。fold 不可執行外部/非同步查詢,也不能讓事件自行選擇其經濟前態。 - 把
economyConfigEpoch或 rating snapshot 寫進事件:拒絕。這仍讓事件選擇計算基準,並擴大可操控與同步面。 - 保留事件 payout,再以更多 bounds 防守:拒絕。bounds 無法證明金額來自 canonical 前態,且容易再次漏掉跨欄位聚合。
- MatchResult 只承載可聯署事實,canonical fold 於事件位置以前態重算:採納。
決定¶
MatchResultEvent移除economySettlement、baseLogHeadCids與roundAnchorCids;提案、review 與 takeover 同步移除 frontier/payout。外層 roster 多簽只背書比賽事實。- 每回合改內嵌
RaceConsensusAnchorEvent | null。非 null 證書須驗 match、round、terminal tail、anchor 時間、當時 present roster、chain-domain 多簽,以及與外層 start-grid proof 相同的gridContextDigest + gridSeed。anchor 不重複完整 commitment/reveal proof,確保 8 人 × 5 回合 × 全簽事件仍低於 65,536-byte admission 上限。 - 經濟 reducer 以事件 canonical 位置的
DerivedState為唯一權威,讀取當時economyConfig、state-derived UGC rating、rolling windows 與 UGC lineage,純函數產生 settlement;事件不能提供或覆寫金額。 - economy、reputation 與相關 rolling windows 統一使用單調
state.derivedAt,不使用可倒填的事件時間。ordinary genesis 將公開 receipt 的正整數genesisTimestamp注入derivedAt與 UTC 月錨;正式部署與 pinning replica 缺值或不一致時 fail closed。rebirth 延續 checkpoint state。 - 月硬頂採 incoming-inclusive 判定:
monthMinted + incomingMint > month_hard_cap_minor時不入帳。事件仍留下MatchRecord與economyOutcome: monthly-hard-cap,且 reputation、TrueSkill、斷線效果與settledMatchIds只套用一次。 - 專案仍為 pre-launch,不提供舊 wire、checkpoint 或本機資料的 dual-read/migration。
後果與影響¶
歷史 append 與 live 首播走同一組自包含 timeless 證明;任何節點重放同一 canonical log 都由相同前態算出相同 payout。移除 frontier 暖身、重算 LRU 與事件 payout 後,收件路徑更小,也不再因本機同步速度產生 settlement accept/defer 差異。
代價是 MatchResult 變大,且缺任一回合 anchor 的場次仍可記錄競技結果但 mintEligible=false。尺寸回歸測試鎖定正式上限;若未來擴大 roster、回合數或 proof,必須先重新評估 wire 大小,不得提高 admission 上限掩蓋重複資料。