Skip to content

Commit 6d502c0

Browse files
keanji-xclaude
andcommitted
docs(arch): add greenfield v2 architecture doc (research-grounded, review loop 收敛)
新增 docs/architecture.md——把 v2 的系统架构讲清楚,采 greenfield 路线: 全新部署一套自洽合约,不改造、不迁移任何 v1 合约(旧 GameEngine/GTreasury/ CardLedger/ArenaEngine 继续服务 v1),新赛季起。 内容:为什么 greenfield(核心 5 合约两路都得写,改造只多叠迁移税;且旧 A 路 不可行——GameEngine hex mapping 无外部 setter);四层栈 Market→AP→Action 循环; 合约全景(V2Router/V2Treasury/PME+内嵌QuestionRegistry/MarketSettlementResolver/ APLedger/V2World/RNGProvider/HexGrid,复用 AgentRegistry 身份);一次完整数据流; 关键决策+依据;7 条经济铁律;权限边界;MVP 范围;仅剩待定(§12 数值 + M7 ORACLE)。 所有事实论断已对真实合约核验(GameEngine:76-78 无 setter、GTreasury creditG 泛 onlyOperator/spendG escrow 漏/withdrawSurplus onlyOwner、全链无 VRF、agentId 从1起)。 独立 review 后修正 §2 合约图箭头方向(PME 不驱动 V2World;creditFromMarket 起自 PME 非 Resolver)+ AgentRegistry/V2Router/Treasury 措辞 + RNG 活性兜底说明。 Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
1 parent 8e9c271 commit 6d502c0

1 file changed

Lines changed: 185 additions & 0 deletions

File tree

docs/architecture.md

Lines changed: 185 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,185 @@
1+
# Gravity Town v2 · 架构(Architecture)
2+
3+
> **本文是 v2 的架构权威**——把「这个项目是怎么搭起来的、为什么这么搭」讲清楚。
4+
> 配套:详细字段/公式见 [`game-design.md`](game-design.md)(工程规格)· 玩家视角见 [`game-design-ux.md`](game-design-ux.md)(看/做/感受)· 并行开工/lane/排期见 [`dev-plan.md`](dev-plan.md)(执行)。
5+
> **凡本文与 game-design.md 的「改造旧合约 / 迁移旧世界」措辞冲突,以本文的 greenfield 方案为准。**
6+
7+
---
8+
9+
## 0. 一句话 + 为什么是 greenfield
10+
11+
**一句话:** Gravity Town v2 是一个链上 **Market → AP → Action** 游戏——你押游戏币 **G** 赌一个会被验证对错的未来,赢了才拿到**行动力 AP**(买不到、只能赢),再花 AP 去攻击/加固/回场、改写一张链上六边形地图;地图一变又长出新的可押事件。整套循环全部记在链上、由 LLM agent 自主驱动。
12+
13+
**部署方式 = 全新(greenfield),新赛季起:** v2 **不改造、也不迁移**任何 v1 合约——全部新部署一套自洽合约,旧的 `GameEngine` / `GTreasury` / `CardLedger` / `ArenaEngine` 原样继续服务 v1/arena,v2 一行都不写它们的状态。
14+
15+
**为什么 greenfield 而不是改造旧世界(关键判断):**
16+
17+
- **核心合约两条路都得写。** Market 引擎、AP 账本、世界、RNG、结算——这 5 件是 v2 这个游戏的本体,无论改造还是全新都得从零写。
18+
- **「改造」只会**额外**叠上一笔迁移税,不会省事:**`GTreasury` 的发奖/escrow/提现权限 + 连带修被它弄坏的 `CardLedger`/`ArenaEngine`、把旧地图快照导进新世界、给共享 `Router` 上 dual-read 兼容层、三服务 feature-flag 软切……这些**全是 greenfield 不需要的**
19+
- **有的旧路根本走不通。** 想「让外部合约改 `GameEngine` 的地块归属」是不可能的:`GameEngine``hexes / agentHexKeys / hexCount``public` mapping,**只有 getter、没有外部 setter**,所有写入都锁在内部权限后。
20+
- **结论:** greenfield **工作量更小、且架构更干净**(单一新世界自持状态、不和 v1 的 ore/arsenal/happiness 经济耦合),所以直接重写更合理。
21+
22+
> 唯一前提:v2 当**新赛季**起,玩家的 G/地盘**不从 v1 继承**(v2 的 G 从 v2 自己的入金/faucet 起,地图全新空开局)。v2 玩法本就是重构(连 ore 都砍了),这个前提通常成立。
23+
24+
---
25+
26+
## 1. 四层栈:世界怎么转起来
27+
28+
整个世界是一个**自我喂养的循环**,三层首尾相接,外加一个后续才挂上来的卡牌层:
29+
30+
```text
31+
┌────────── 地图一变,长出新 Market,回到 ① ──────────┐
32+
│ │
33+
▼ ① Market ② AP ③ Action │
34+
┌─────────┐ 押 G ┌─────────┐ 赢盘 ┌─────────┐ 花 AP │
35+
│ 押未来 │ ──赌──▶ │ 才发 AP │ ──得──▶ │ 改地图 │ ────────┘
36+
│(可验证)│ │(只能赢) │ │(链上) │
37+
└─────────┘ └─────────┘ └────┬────┘
38+
┊ 攻防小加成
39+
┌────┴────┐
40+
┊ 卡牌 ┊ ← 后续(M6),不在主循环
41+
└─────────┘
42+
```
43+
44+
|| 是什么 | 产出 |
45+
|----|--------|------|
46+
| **① Market** | 世界唯一的价值来源:会被验证对错的预测盘。你押 G 赌「2h 后 Bob 还守得住 3 号地吗」 | 赢家分到输家押进来的 G |
47+
| **② AP** | 赢盘才有的行动资格。**AP 只能赢、买不到、转不走、提不出** | AP(看得越准给越多) |
48+
| **③ Action** | 花 AP 改写链上地图:攻击相邻地 / 加固己方地 / 0 地回场 | 世界变了,立刻长出新盘 |
49+
| 卡牌(M6) | 挂在 ③ 上的攻防小加成,不进循环、不引第二种币 | 给攻防 +N |
50+
51+
**两条铁律**(全局最该记住的):**(1) AP 只能赢来**——任何「用 G 买 AP」的路在合约层就不存在;**(2) 赢家一定拿得到**——赌池里的 G 锁着、协议碰不到,局一结束自动发给赢家。
52+
53+
---
54+
55+
## 2. 合约全景:组件、职责、关系
56+
57+
```text
58+
图例:→ 运行期调用(调用者 → 被调用者);⇢ 只读 view;[新]v2 新建/[复用]不改其 v1 语义。
59+
V2Router[新]解析所有 v2 合约地址;旧 Router / GameEngine / GTreasury / CardLedger / Arena 一律不碰。
60+
61+
玩家 ── 入金 depositG ─────────────────────────▶ V2Treasury[新]
62+
(G 单一托管:reservedBacking /
63+
┌── escrow + 发奖 creditG ──▶ escrow / cap / 多签提现)
64+
│ ▲ 提现(治理:多签+timelock)
65+
── Market 路径 ── │
66+
玩家 ─ 开/押/claim ─▶ PredictionMarketEngine[新](内嵌 QuestionRegistry)
67+
68+
├─ settle: 问结果 ─▶ MarketSettlementResolver[新]
69+
│ (MATH 自校验 / STATE / ORACLE M7)
70+
│ ┊ ⇢ 读 V2World.checkpoints(eventId)
71+
└─ creditFromMarket(发 AP, onlyMarket)─▶ APLedger[新]
72+
73+
── Action 路径 ── │ spendForAction
74+
玩家 ─ attackWithAP ─▶ V2World[新]─────────────────────────────────────┘(花 AP, onlyWorld)
75+
│ (hex=agentId / defense / capture / spawn / score /
76+
│ 唯一写 finalized checkpoint)
77+
├─ request/reveal ─▶ RNGProvider[新](commit-reveal)
78+
└─ 链接库 ─▶ HexGrid[新,库,不占地址槽 / 邻接·可逆键]
79+
80+
AgentRegistry[复用,身份层]:agentId↔owner、createAgent —— 被 PME / V2World ⇢ 读身份
81+
```
82+
83+
| 合约 | 职责 | 谁能写它 | 状态 |
84+
|------|------|----------|------|
85+
| **V2Router** | 解析全部 v2 合约地址(upgrade 时换实现不换地址) | lead/治理 | 🟢 新建(旧 Router 是 append-safe、本可复用;默认新建小 router 以彻底隔离 v1) |
86+
| **AgentRegistry** | agent 身份:`agentId`(从 1 起)↔ owner 地址;`createAgent``isOperator` | 玩家(建号);v2 合约只读 | ♻️ 复用(身份层;不碰其 v1 经济语义) |
87+
| **V2Treasury** | G 的**单一托管**`gBalance` 账本、`reservedBackingG`、市场 escrow 进出、`netTreasuryTakeG` cap、`onlyMarket creditG`、多签/timelock 提现 | 玩家(入金)/ only PME(发奖·escrow)/ 治理(提现) | 🟢 新建(**取代**改造 GTreasury) |
88+
| **PredictionMarketEngine** | 开盘/押注/关盘/结算/claim;escrow + eligibility;**内嵌**模板白名单 + `trivial/difficulty` 派生(QuestionRegistry 不单列) | 玩家(开/押);permissionless(settle) | 🟢 新建 |
89+
| **MarketSettlementResolver** | 判定盘的对错:`MATH` 自校验 / `STATE``V2World.checkpoints(eventId)` / `ORACLE`(M7) | PME 调 | 🟢 新建 |
90+
| **APLedger** | AP 余额;`creditFromMarket`**唯一 mint 入口**,onlyMarket);`spendForAction`**唯一花**,onlyWorld);trivial 多维 throttle | only PME(增)/ only V2World(减) | 🟢 新建 |
91+
| **V2World** | hex 归属(**agentId**,0=neutral)、`hexDefense`、capture、spawn/respawn、`v2Score`**唯一写 finalized checkpoint**`attackWithAP/reinforceHex/returnFromElimination` | 玩家(花 AP 行动) | 🟢 新建 |
92+
| **RNGProvider** | AP-gated 战斗随机数(**commit-reveal**| V2World 调 | 🟢 新建 |
93+
| **HexGrid** | 无状态几何库:`areAdjacent/toKey/fromKey/inBounds`**可逆打包键**|| 🟢 新建(库,链接进 V2World,不占地址槽) |
94+
95+
> **不碰清单(greenfield 边界):** `GameEngine` / `GTreasury` / `CardLedger` / `ArenaEngine` / 旧 `Router`——v2 不写它们的状态、不迁移它们的余额、不在 PR 里改它们(除非 v1 自身 bug)。它们继续服务 v1 与 arena 侧游戏。
96+
97+
---
98+
99+
## 3. 一个完整循环(数据流)
100+
101+
```text
102+
1. 入金 玩家把 native 充进 V2Treasury → 记 gBalance(v2 自己的 G,新赛季)
103+
2. 开盘 PredictionMarketEngine.open(question) // MATH 模板自校验 / STATE 绑定未来 checkpoint
104+
3. 押注 玩家 bet(marketId, outcome, stakeG)
105+
→ V2Treasury escrow:totalOutstandingG -= stake; reservedBackingG += stake(不漏进可提 surplus)
106+
4. 关盘 到 closeAt,停止接注;odds 早期窗口/TWAP 已快照(防 anti-snipe)
107+
5. 结算 settle(marketId)(permissionless,到期后任何人/runner 可触发)
108+
→ MarketSettlementResolver 判对错:
109+
· MATH → 链上自校验
110+
· STATE → 读 V2World.checkpoints(eventId),要求 exists && finalized
111+
6. 发奖 对每个赢家仓位:
112+
→ APLedger.creditFromMarket(agentId, winAP) // AP 唯一 mint,越难给越多
113+
→ V2Treasury.creditG(winner, payout) // 有等额具名 backing 才发;输家的 burn 进不可回流 sink
114+
7. 行动 V2World.attackWithAP(agentId, fromHex, targetHex, apSpend)
115+
→ APLedger.spendForAction(扣 AP) // 先扣,杜绝「免费试」
116+
→ RNGProvider 提交 commit → k 块后 reveal 出种子 → Tullock 判胜负
117+
→ 胜:capture,hexDefense 清零,写 battle/capture checkpoint
118+
8. 长出新盘 地图变了 → 这块新地的归属成了下一个「STATE 盘」可押的未来事件 → 回到 2
119+
```
120+
121+
**方向要点(别记反):****V2World 写 checkpoint → STATE 盘读它**。Action 是 Market 的上游生产者;Market 不驱动 Action。
122+
123+
---
124+
125+
## 4. 关键架构决策(已定,带依据)
126+
127+
这些原本是「待定」,已通过读真实合约 + 规格定稿(依据见 `dev-plan.md` §3):
128+
129+
- **世界自持(greenfield World)。** v2 的 hex/战斗/checkpoint 全在 `V2World` 内,**连旧 `GameEngine` 都不碰**(旧 `hexes/hexCount` 无外部 setter,本就改不了)。旧世界的 Tullock 数学、地图工具只作**参考或抽成库**
130+
- **hex 归属 = `agentId`(uint256,0=neutral)。** 因为 `hexCount(agentId)``v2Score(agentId)`、capture→attacker 的 agentId、STATE 盘「hex 是否归 agent A」都按 agent 粒度;钱包 `address` 只在经济层出现。
131+
- **checkpoint 键 = `bytes32 eventId` = `Question.snapshotEventId`** 创建时 `exists==false`(已存在即拒,杜绝「创建晚于事实」),结算时 `exists && finalized`,超时 void+refund,**只有 V2World 能写**
132+
- **RNG = commit-reveal。** 全链无现成 VRF;commit-reveal 自包含、无外部依赖,藏在 `RNGProvider` 接口后,将来 Gravity 有 VRF 可无缝换 adapter。`block.prevrandao` 可被 grind,**禁止**用于 AP-gated 胜负。揭示扣留/掉线由「超时 → 退还已扣 AP」兜底(AP 提交时即扣,不存在「免费试」),故无活性单点;`reveal` 窗口 `k` 等是 §12 数值。
133+
- **QuestionRegistry 内嵌 PredictionMarketEngine。** MVP 只 3 个 MATH 模板、派生本就在 create 路径里跑;不单列合约、不占地址槽,留好内部抽出缝(`Question` 已存裸 `templateId/params`),M7/治理上线时可无痛抽出。
134+
- **V2Treasury 全新(不改 GTreasury)。** 单一 G 托管、`reservedBackingG` 从第一天就在、只有 market 能 `creditG`、提现走多签/timelock——避开旧 `GTreasury` 的泛 `onlyOperator` 发奖、`spendG` escrow 泄漏、`onlyOwner` 提现后门,也不弄坏 `CardLedger`/`ArenaEngine`
135+
- **HexGrid 可逆打包键。**`toKey` 是单向 keccak(无法从 key 反推坐标做邻接校验);改用 `bytes32(uint256(uint32(q))<<32 | uint32(r))`,支持 `fromKey` + 按 key 判邻接。
136+
137+
---
138+
139+
## 5. 经济铁律 / 不变量(承重,L-T property test 守)
140+
141+
1. **AP 只能赢来。** AP 仅经 `APLedger.creditFromMarket` 增发;不可买、不可泛 operator mint、不可与 G 兑换;`spendForAction``V2World` 可调。
142+
2. **单一发奖入口。** 正式 `creditG` 只认单一 `PredictionMarketEngine`;二级卡牌卖方收款走独立 `SECONDARY_CARD_TRANSFER` 白名单(守恒)。
143+
3. **creditG 等额 backing。** 每次发 G 前都能指出已扣减/锁定的等额具名来源(losing stakes → 预存补贴池 → 已拨入 surplus);无 backing 的 payout 被拒。
144+
4. **桶隔离。** 任一时刻 `可提 surplus ≤ 余额 − 全部未结算 G 负债 − reservedBackingG − frozenG`;escrow/补贴永不被当 surplus 提走。
145+
5. **净抽水 cap。** `netTreasuryTakeG(epoch) ≤ treasuryTakeCapBps × grossPlayerPaidG`,超则拒绝或 source-neutral 回流;**burn 永不回流**
146+
6. **防御。** `0 ≤ effectiveDefense ≤ D_max`、随时间衰减、capture 后清零、满 AP 攻击成功率 `≥ p_floor`(守不死的地不存在)。
147+
7. **eligibility。** 非 trivial 盘需 ≥2 独立 owner + 真实 `losingBurnG`,单边/自对冲只退款不发 AP/G,AP throttle 锚 `realBurnedGInMarket`;trivial 盘固定 AP + 多维 throttle(agent/owner/epoch/global)。
148+
149+
> 多 EOA 同控自对赌是链上不可完全识别的**残留信任假设**——靠真实 burn 成本 + AP throttle + 可选 account 成熟度/bond 缓解,不声称已根除。
150+
151+
---
152+
153+
## 6. 权限边界(谁能调谁)
154+
155+
| 被保护的动作 | 只允许 | 拒绝 |
156+
|--------------|--------|------|
157+
| `APLedger.creditFromMarket`(发 AP) | `PredictionMarketEngine` | 其它任何地址 |
158+
| `APLedger.spendForAction`(花 AP) | `V2World` | Market、玩家直调 |
159+
| `V2Treasury.creditG`(正式发奖) | `PredictionMarketEngine` | 泛 operator/owner |
160+
| `V2Treasury` 二级卖方收款 | `SECONDARY_CARD_TRANSFER` 白名单 | 复用发奖路径 |
161+
| `V2Treasury.withdrawSurplus`(提现) | 多签 + timelock,`TreasuryUse` 枚举限用途 | 单签 owner |
162+
| 写 finalized checkpoint | `V2World` | Market、resolver、外部 adapter |
163+
164+
调用图**单向无环**`creditFromMarket` 只被 Market 调、`spendForAction` 只被 World 调(Market 永不调 spend、World 永不调 credit),故不存在回边。
165+
166+
---
167+
168+
## 7. MVP 范围与后续
169+
170+
**MVP 做(M0–M5):** Market 引擎(`MATH` + `STATE`-by-checkpoint)· AP 账本与发放 · 三个动作(攻击/加固/回场)· `V2World` minimal core · commit-reveal RNG · MCP/agent-runner/frontend 只围绕 Market→AP→Action 闭环。
171+
172+
**MVP 不做:** ore / 建造采集 / 把每个动作包装成答题 / 卡牌数值 / `ORACLE` 盘。
173+
174+
**后续:**
175+
- **M6 卡牌**:公库(V2Treasury)出资铸成就稀有卡 / 玩家自冻 G 铸白板卡;攻防 bonus 挂在 Action 上;不引第二种币、不进主循环。
176+
- **M7 ORACLE**:三类盘的第三类(链外真实世界),**deferred-not-cut**——信任模型(单签/多签/optimistic/attestation + 挑战窗 + 失败恢复)独立评审通过后才开放。
177+
178+
---
179+
180+
## 8. 仅剩的真·待定(不阻塞架构/冻接口)
181+
182+
- **§12 数值**`fixedTrivialAP`、各 cap、`taxBps/burnBps/treasuryTakeCapBps``D_max/p_floor``minAttackAP`、地图半径、`warmup/antiSnipeWindow``SCORE_PER_*`)——约束式已锁,常数经 setter 治理注入。
183+
- **M7 ORACLE 信任模型**——只 gate M7、不 gate MVP。
184+
185+
> 架构既定、合约边界既定,接口可立即冻结、lane 可立即并行(执行见 `dev-plan.md`)。要改本文任一架构决策,走一次 ADR,不走「逐项签字」门。

0 commit comments

Comments
 (0)