一个基于服务端出题的 PoW 竞速游戏(多赛道、全局轮次、共享奖励池),后端使用 Node.js + Express + SQLite,前端为静态页面并带 WebSocket 实时状态。
- 多赛道独立轮次(每条赛道同时只有一个
open轮次) - 按 IP 发放挑战并使用
ip_lock保证单 IP 同时仅有一个有效挑战 - 提交成功后原子结算:关轮次、发奖励、记账、开启下一轮
- 奖池按时间持续补充(按毫秒累计),并在结算时按比例发放
/submit具备并发与频率保护(全局 + 每 IP)- WebSocket 提供实时网络算力统计、轮次事件与提交密钥下发
- 支持本地提现请求与一键兑换码(可选远程 MySQL 持久化)
- 服务器端优先使用 WASM 验证器(有导出时)加速重型谜题校验
在默认配置下,启用赛道由 computeEnabledTracks() 计算,且 DISABLED_TRACKS 默认禁用了 CPU_HASH(测试环境除外)。
可用赛道定义见 ALL_TRACKS:
CPU_HASHMEM_WORKCHAINBRANCHY_MIXTINY_VMVM_CHAINARGON2D_CHAIN
说明:文档中若出现“3 赛道”描述,属于早期设计稿。实际运行以
CONFIG.tracks为准。
- Node.js 22+
- Express 5
- better-sqlite3
- ws (WebSocket)
- zod
- 可选:mysql2(用于
withdraw_code远端写入)
参见 package.json。
npm install复制并编辑 .env.example:
cp .env.example .env核心变量:
PORT:服务端口(默认8080)DB_PATH:SQLite 路径(默认./data/powloot.sqlite)TRUST_PROXY:反向代理信任策略(默认1)
一键兑换(可选)MySQL 变量:
REDEEM_MYSQL_HOSTREDEEM_MYSQL_PORTREDEEM_MYSQL_USERREDEEM_MYSQL_PASSWORDREDEEM_MYSQL_DATABASE
npm start启动入口见 src/server.js。
npm test- 客户端请求
GET /challenge - 服务端按 IP 选择赛道并返回当前轮次参数
- 客户端本地搜索
nonce - 客户端提交
POST /submit - 服务端验证通过后进行原子结算并轮转下一轮
关键逻辑:
- 挑战签发:
getChallengeForIp() - 强制轮转:
maybeForceRotate() - 提交处理:
app.post('/submit') - 难度更新:
updateDifficultyOnSolve()
基于默认配置(见 CONFIG):
- 奖池补充:
1000单位 / 24 小时(微单位累计) - 单次奖励:奖池的
0.1%(payoutBps = 10) - 轮次超时强制轮转:
30分钟 - “慢解”阈值:
10秒(用于难度更新分支)
奖池补充函数见 applyPoolTopup()。
实现位于 createApp()。
GET /challenge:获取挑战POST /submit:提交证明GET /balance:查询当前 IP 余额POST /withdraw:创建提现请求(本地记账)POST /withdraw_code:生成兑换码并尝试写入远端 MySQLGET /withdraw_history:查询本地兑换历史GET /admin/state:调试状态
更详细说明见 docs/API.md。
端点:/ws,实现见 WebSocketServer。
服务端推送:
stats:网络算力与在线矿工数secret:提交密钥(用于/submit请求头)round_solved:轮次被解出事件kicked:同 IP 新连接挤掉旧连接
客户端上报:
hashrate:当前算力(可带 track)
/submit可要求x-pow-secret(默认生产/开发启用,测试关闭),校验见verifyIpSecret()- 全局 HTTP 并发上限(默认 100),见
HTTP_MAX_INFLIGHT - 验证器并发上限(默认 2),见
VERIFY_MAX_INFLIGHT - 每 IP 提交限制:
- 最小提交间隔 1 秒
- 并发提交上限 1
- 错误证明触发 10 秒禁提
SQLite schema 迁移见 migrate(),主要表:
rounds,current_round,ip_lockip_track_times,global_track_timesbalances,reward_poolpool_ledger,ip_ledgerwithdraw_requests,redemption_codes
数据模型文档见 docs/DATA_MODEL.md。
设置奖池余额脚本:scripts/set_reward_pool.js
npm run set:pool -- 500 --units
npm run set:pool -- 123000000 --micro
npm run set:pool -- 500 --units --db ./data/powloot.sqlite- 运行指南:
docs/RUN.md - API:
docs/API.md - 设计说明:
docs/DESIGN.md - 数据模型:
docs/DATA_MODEL.md - 难度与评分:
docs/DIFFICULTY_AND_SCORING.md - VM/链式细节:
docs/VM_CHAIN.md