Skip to content

prof-faustus/cardtable-zh

Repository files navigation

cardtable — 基于 BSV 的无荷官分布式纸牌游戏协议

CI License: MIT

研究代码,处于早期脚手架阶段。 本仓库实现了 PROJECT_SPEC.md 以及 spec/ 下规范文档所 指定的协议。按照本项目的代币模型,代币不具有任何外部货币价值,本系统 也不是受监管的赌博产品。参见 LICENSE

这是什么

cardtable 是一个面向 Bitcoin SV(Genesis 升级之后)的多人纸牌游戏协议, 具有交易原生、点对点、非托管的特性。每一个游戏事件都是一笔经过签名的 BSV 交易;每一个游戏状态都是一个已承诺的 UTXO,它有一个协作型后继分支和一个 超时默认后继分支;每一种失败模式都解析为一个确定性的链上后果,而不是依赖 人工运营层面的判断。

首个生产目标:In-Between(Acey-Deucey)。

权威来源

文件 作用
PROJECT_SPEC.md 实施构建规范;编码标准;项目结构;构建顺序;禁止事项清单
spec/ 按方面划分的协议规范(状态机、交易类型、脚本模板、超时规则、恢复规则、序列化、排序、纸牌协议、线路协议、对手方发现)
spec/test-vectors/ 将每个实现绑定到完全一致行为的权威输入/输出向量
docs/adr/ 架构决策记录,涵盖在不确定性下做出的每一项设计选择

技术栈(依据 PROJECT_SPEC.md §Technology Stack)

  • 客户端: TypeScript(strict 模式)、React 18、Vite、Zustand、Dexie、Web Crypto、BSV TypeScript SDK
  • 后端: Go 1.22+、WebSocket 中继、Aerospike、Kafka、BSV Go SDK
  • 不在范围内: 链下支付网络、二层 rollup、替代性脚本扩展、用于游戏状态的 Postgres/Redis、ORM、GraphQL、由服务器托管的游戏状态。每一次状态转换都在链上进行。

构建阶段(依据 PROJECT_SPEC.md §Build Order)

  1. 规范 + protocol-types — 编写 spec/ 以及 protocol-types
  2. 状态引擎 + 脚本模板 — 确定性规则 + BSV 脚本构造
  3. 公开信息原型 — 不含隐藏牌的桌面流程
  4. 隐藏单张牌 — 熵的承诺/揭示、加密的纸牌 UTXO
  5. 多张牌 In-Between — 完整游戏、预签名的回退图、对局记录重放
  6. 对抗性加固 — 全部 14 个命名场景 + 确定性重放

在本次提交时,本仓库处于 Phase 0(仅有骨架)。后续提交将依次填充 每个阶段。

仓库布局(依据 PROJECT_SPEC.md §Project Structure)

cardtable/
├── PROJECT_SPEC.md, README.md, LICENSE
├── spec/                # 协议规范(协议行为的权威来源)
├── packages/            # 共享的 TypeScript 包
│   ├── protocol-types/
│   ├── state-engine/
│   ├── script-templates/
│   └── crypto-cards/
├── apps/                # 可运行的服务
│   ├── client-web/      # React + Vite 浏览器客户端
│   ├── relay-go/        # Go WebSocket 中继
│   ├── indexer-go/      # Go 索引器服务
│   └── spv-service-go/  # Go SPV 证明 / 区块头服务
├── tests/               # 跨包测试与对抗性测试
├── tools/               # 模拟器、对局记录校验器
└── docs/                # 架构说明、ADR、运维手册

空的子目录会用一个 .gitkeep 文件保持被追踪状态,直到对应阶段将其填充。

关键规则(摘自 PROJECT_SPEC.md,在此重复以便醒目)

  • 依据 BSV 共识与 Genesis 升级之后的操作码集合进行构建。 仅使用 BSV TypeScript / Go SDK。
  • 在 BSV Genesis 升级之后,Script 是图灵完备的。 时间锁位于交易层级(nLockTime、输入的 nSequence);任何 cardtable 模板都不使用脚本内的时间锁操作码。
  • 代币不具有外部价值。 本系统不是受监管的赌博产品。
  • 零虚构。 每一个数字、论断和技术陈述都可追溯到某个来源,否则就被标记 为一项假设并附带可追踪的责任项。
  • 无隐性假设。 隐藏的假设即为缺陷;必须在文档表面明确声明。

快速上手

# 1. 安装
pnpm install

# 2. 在本地运行全部 TS + Go 测试套件(离线)
pnpm ci                                       # 工作区构建 + 测试
(cd apps/relay-go && go test -v ./...)        # Go 测试套件

# 3. 在本地运行中继
(cd apps/relay-go && go build -o ../../bin/relay ./cmd/relay)
./bin/relay --addr :8080 --ws-addr :8081 \
  --game 00000000000000000000000000000000000000000000000000000000000000aa \
  --start-height 100

# 4. 对运行中的中继执行一整轮心智扑克(mental poker)
CARDTABLE_RUN_LIVE=1 \
CARDTABLE_RUN_FULL_ROUND=1 \
CARDTABLE_WS_URL=ws://localhost:8081/ws \
CARDTABLE_GAME_ID=00000000000000000000000000000000000000000000000000000000000000aa \
  pnpm --filter @cardtable/integration-tests test

# 5. 或使用 Docker
docker compose up --build relay               # 本地构建
docker run -p 8080:8080 -p 8081:8081 \
  ghcr.io/prof-faustus/cardtable-relay:latest # 已发布的多架构镜像

浏览器客户端:

(cd apps/client-web && pnpm vite build && pnpm vite preview --port 4173)
# 然后打开 http://localhost:4173 并点击 “Connect to relay”

录制一份对局记录并离线校验它:

node ./tools/transcript-recorder/dist/index.js \
  --ws ws://localhost:8081/ws \
  --game-id 00000000000000000000000000000000000000000000000000000000000000aa \
  --out ./session.jsonl

node ./tools/transcript-verifier/dist/index.js \
  --transcript ./session.jsonl \
  --game-id 00000000000000000000000000000000000000000000000000000000000000aa

# 或使用 Go 侧的审计工具:
(cd apps/relay-go && go build -o ../../bin/indexer ./cmd/indexer)
./bin/indexer --transcript ./session.jsonl \
  --game-id 00000000000000000000000000000000000000000000000000000000000000aa

在 Windows 上构建

快速上手流程在 Linux/macOS 以及 CI 中可直接使用。在 Windows 主机上会遇到 几个环境上的怪癖;应用以下方法后,所有测试套件即可通过:

  • pnpm install 报错 UNABLE_TO_VERIFY_LEAF_SIGNATURE —— 这是由企业 TLS 检查对 npm registry 重新签名所致。通过 Node 的系统 CA 标志信任 Windows 根证书库(Node ≥ 22):

    $env:NODE_OPTIONS = "--use-system-ca"
    pnpm install

    在执行 pnpm install/build/test 时保持设置 NODE_OPTIONS=--use-system-ca

  • go test ./... 报告 ... contains a virus or potentially unwanted software 并失败 —— 这是主机杀毒软件(例如 Norton/Defender)将刚刚链接 生成的 Go *.test.exe 二进制文件隔离所产生的误报(通常由 pkg/wire 测试二进制文件触发)。代码本身没有问题。使用 -trimpath 构建测试二进制 文件即可——它对链接产物的改动足以避开该启发式检测——并将其设为默认:

    go env -w GOFLAGS=-trimpath
    go test ./...                 # 现在一条命令即可全绿

    一次冷启动的完整重链接(先 go clean -testcachego test ./...)在 杀毒软件同时扫描每个新二进制文件时,仍可能间歇性地使一个时序敏感的测试 (internal/spv/TestHTTPHeightSource_TracksLatest,一个 2 秒的 HTTP 轮询 截止期限)出现偶发失败。热重跑是稳定的。要彻底消除该问题,请在杀毒软件中 为 Go 的临时目录添加文件夹排除项(用 go env -w GOTMPDIR=C:\Users\<you>\go-tmp 设定一个稳定的目录并排除该文件夹)。

  • 端口 8081 已被占用 —— 在运行 WSL 的机器上,wslrelay.exe 会绑定 127.0.0.1:8081。请在另一个端口上运行中继,并让集成测试指向该端口:

    .\bin\relay.exe --addr :8092 --ws-addr :8091 `
      --game 00000000000000000000000000000000000000000000000000000000000000aa --start-height 100
    $env:CARDTABLE_WS_URL = "ws://127.0.0.1:8091/ws"

    live-full-round 集成测试与在线浏览器冒烟测试都各自需要一个全新的中继 (中继在内存中保存对局状态,因此复用的座位会发生冲突)。请在两次运行之间 重启中继。

如何贡献

完整通读 PROJECT_SPEC.md 以及 spec/ 下按方面划分的规范文档。然后查看 STATUS.md 了解当前阶段以及尚存的实质性缺口。测试与其代码放在一起: packages/*/__tests__/apps/relay-go/**/_test.go,以及位于 tests/integration/tests/browser-smoke/ 下的跨系统测试套件。

About

cardtable(基于 BSV 的无荷官扑克/纸牌对局系统)简体中文翻译版:文档与代码注释全部译为简体中文,代码逻辑不变。Simplified-Chinese localization of the cardtable BSV dealerless poker project (docs + code comments translated; code unchanged).

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors