Co-authored-by: Cursor <cursoragent@cursor.com>
7.0 KiB
HyperNode-AI 说明
HyperNode-AI 是算力节点的控制面。节点程序部署在各处,本服务负责登记节点、接收心跳、下发模拟任务、按天计算积分,并记录提现。
时间全部使用 UTC。每日清算的触发时刻是北京时间 00:05,入账的是上一个已经结束的 UTC 日。
本地开发直接启动时监听 8000。服务器按 部署.md 安装后监听 33333。
pip install -r requirements.txt
python -m app
目录
| 路径 | 内容 |
|---|---|
app/models.py |
数据表 |
app/api.py |
HTTP 接口 |
app/services/heartbeat.py |
心跳与离线判断 |
app/services/tasks.py |
任务下发与 nonce 校验 |
app/services/yield_engine.py |
产出公式与按日入账 |
app/jobs/daily_yield.py |
凌晨清算入口 |
app/scheduler.py |
进程内定时任务 |
app/settle.py |
可单独执行的清算命令 |
frontend/ |
Vue 3 控制台源码。改完后在该目录执行 npm run build |
web/ |
控制台构建结果,服务启动后打开 / |
deploy/manage.sh |
Ubuntu 22.04 交互式部署,支持 curl | bash |
数据表
业务表:
users:钱包地址、可选用户名和密码、角色user/admin、注册时间。compute_nodes:节点 SN、购买金额、12 个月授权、online/offline、最后心跳。可选callback_url用来推送任务。node_yields:每日算力产出和积分。同一节点同一天只有一条。withdrawal_logs:提现金额、资产符号、链上哈希、状态。
计算用的表:
uptime_intervals:一段连续在线时间。compute_tasks:下发的模拟任务和回传结果。scheduler_locks:多台服务实例同时跑定时任务时互斥。
产出公式
授权金额按授权起止日期的天数线性释放,再乘当天表现系数。单节点累计积分不超过购买金额。
- 在线率 = 当天授权窗口内的在线秒数 / 当天授权有效秒数
- 任务响应率 = 校验通过且执行成功的任务数 / 当天下发任务数
- 当天没有下发任务时,表现系数 = 在线率
- 有任务时,表现系数 =
0.7 × 在线率 + 0.3 × 响应率 - 算力产出 = 购买金额 × 表现系数
- 当日积分 = 算力产出 / 授权天数
开放的在线区间如果最后心跳已超过 15 分钟,只计算到最后一次心跳。
权重可用环境变量 ONLINE_WEIGHT、TASK_WEIGHT 修改,默认 0.7 和 0.3。
运行中的三件事
服务进程里有三个定时任务:
- 每 5 分钟检查心跳。超过 15 分钟没有心跳,或授权到期,节点改为
offline,在线区间结束在最后一次心跳。 - 每 5 分钟向在线、授权仍有效、且没有未完成任务的节点随机下发任务,每轮最多 20 台。任务带
task_id和一次性nonce。节点若配置了callback_url,会额外 POST 一次;否则节点用拉取接口领取。 - 北京时间 00:05 结算上一个已结束的 UTC 日,写入
node_yields。同一天已有记录则跳过。
回传必须带上任务里的 nonce。超时、重复回传、nonce 不匹配都不算成功。
登录
普通用户可以注册钱包、用户名和密码。之后用钱包地址,或用户名加密码登录。管理员只能用账号密码。
新部署会在安装结束时打印管理员账号 admin 和随机密码,并写入 /opt/hypernode/.env 的 ADMIN_PASSWORD。已经部署过的机器如果 .env 里没有这两项,服务第一次启动会在日志里写一次初始密码:
journalctl -u hypernode.service | grep 初始密码
页面路由:
/login登录和注册/dashboard用户自己的节点、今日预计积分、提现申请/admin管理员看总用户、总节点、总产出、节点在线率和提现审核
节点心跳、拉任务、回传任务不需要登录。查看全网数据、清算、确认提现需要管理员令牌。
接口
前缀都是 /api/v1。金额在 JSON 里是字符串。浏览器登录后带 Authorization: Bearer <token>。
| 方法 | 路径 | 作用 |
|---|---|---|
| POST | /auth/register |
注册钱包,可带用户名和密码,返回令牌 |
| POST | /auth/login |
钱包地址,或用户名加密码 |
| GET | /me/dashboard |
当前用户的节点、积分和提现 |
| POST | /me/nodes |
给当前钱包登记节点 |
| POST | /me/withdrawals |
当前用户申请提现 |
| GET | /admin/summary |
管理员:用户数、节点数、总产出 |
| GET | /admin/users |
管理员:全网用户 |
| GET | /admin/nodes |
管理员:节点状态与今日在线率 |
| GET | /admin/withdrawals |
管理员:提现审核列表 |
| POST | /admin/withdrawals/{id}/confirm |
管理员:写入链上哈希并完成 |
| POST | /admin/withdrawals/{id}/reject |
管理员:拒绝并释放占用的积分 |
| POST | /users |
只登记钱包,不设置密码 |
| POST | /nodes |
登记节点,必须是该钱包本人或管理员 |
| GET | /nodes/{sn} |
查看节点 |
| POST | /node/heartbeat |
心跳,请求体 {"sn":"..."} |
| GET | /node/{sn}/tasks |
拉取未完成任务 |
| POST | /node/task/report |
回传 sn、task_id、success、nonce |
| GET | /nodes/{sn}/contribution?yield_date=YYYY-MM-DD |
预览某日产出,不入账 |
| POST | /yield/settle?yield_date=YYYY-MM-DD |
手动清算,不传日期则清算昨天 |
| GET | /nodes/{sn}/yields |
节点流水 |
| GET | /users/{wallet}/balance |
可用积分 |
| POST | /withdrawals |
申请提现 |
| POST | /withdrawals/{id}/confirm |
写入 tx_hash 并完成 |
| POST | /withdrawals/{id}/reject |
拒绝并释放占用的积分 |
可用积分 = 已入账积分 − 待处理提现 − 已完成提现。
健康检查是 /health,不在 /api/v1 下面。
配置
生产环境的配置在 /opt/hypernode/.env。也可以在启动前用同名环境变量覆盖。
| 变量 | 默认值 | 含义 |
|---|---|---|
DATABASE_URL |
部署后指向 /var/lib/hypernode/hypernode.db |
数据库。可改为 PostgreSQL 连接串 |
HEARTBEAT_TIMEOUT_MINUTES |
15 |
心跳超时 |
OFFLINE_CHECK_MINUTES |
5 |
离线巡检间隔 |
TASK_DISPATCH_MINUTES |
5 |
任务下发间隔 |
DISPATCH_BATCH_SIZE |
20 |
每轮最多下发数量 |
TASK_DEADLINE_MINUTES |
10 |
任务回传时限 |
ONLINE_WEIGHT / TASK_WEIGHT |
0.7 / 0.3 |
有任务时的表现系数权重 |
YIELD_TIMEZONE |
Asia/Shanghai |
清算触发时区 |
YIELD_HOUR / YIELD_MINUTE |
0 / 5 |
清算时刻 |
LICENSE_MONTHS |
12 |
新节点授权月数 |
DISABLE_SCHEDULER |
false |
设为 true 时不启动定时任务 |
JWT_SECRET |
空则自动生成并写入数据库 | 登录令牌签名 |
JWT_EXPIRE_MINUTES |
1440 |
令牌有效分钟数 |
ADMIN_USERNAME |
admin |
初始管理员用户名 |
ADMIN_PASSWORD |
空则首次启动随机生成并写入日志 | 初始管理员密码 |
ADMIN_WALLET |
admin-root |
初始管理员钱包地址 |
修改 .env 后执行 systemctl restart hypernode。