把你的算力登记进 CVIN
三条路,按规模选一条。做完你会拿到三样东西:一个全球唯一、不可反推序列号的 CVIN;一张可外链、可独立验签的机况证书;一枚能贴到自己销售页上的徽章。登记写入永久免费,不限次数。
一、先花 60 秒搞清楚:你登记的是什么
CVIN 不是一张发票,也不是一个评分。它记录三件可被任何第三方独立复核的事:
| 记录什么 | 怎么保证不是空口自报 |
|---|---|
| 这台设备存在 | CVIN 由序列号哈希派生;同一台机器重复登记得到同一个 CVIN |
| 什么时候被谁观测到 | 每条观测进 append-only 哈希链,带时间戳与来源 |
| 这段历史没有被改过 | 记录哈希 + 全局链双链,任何人可重放验证;篡改会留下断点 |
它不做什么:不出信用评分、不做残值评估、不做责任认定、不判断设备好不好。CVIN 只提供事实底座,判断留给用它的资金方和买方。
CVIN 的构成
- _ . / : # → 去掉开头的 sn / s/n / serial / serialno」,然后只上传这个 16 位哈希。我们无法从 CVIN 反推出你的资产清单,也无法把两条 CVIN 拼回你的序列号命名规律。如果你的序列号本身不规范(例如内部用 机柜-03-卡-07 这种位置编号),照样可用——规则会把它们规范化成同一个字符串再哈希。唯一要求:同一台设备永远用同一个序列号,否则会算出两个 CVIN。
二、按规模选一条路
| 你的情况 | 走哪条 | 要不要写代码 | 耗时 |
|---|---|---|---|
| 手上 1–5 台,想先看看这东西长什么样 | ① 网页表单 | 不用 | 3 分钟/台 |
| 一个机房、几十到几千台 | ② 脚本批量 | 不用写,下载即跑 | 每台约 1 秒 |
| 要拿去抵押、投保、做资产池 | ③ 设备签名升 L2 | 要在设备上跑一次 | 一次配置,之后自动 |
三、路径 ①:网页表单登记(零代码,3 分钟)
适合先试水。整个过程序列号都留在你的浏览器里,表单在本地算完哈希才提交。
| 步骤 | 做什么 | 你会看到 |
|---|---|---|
| 1 | 打开 自助登记页,填型号四要素 | 输入框已预填 nv / h100 / sxm / 80g 作为范例 |
| 2 | 填设备序列号(可为任意原始写法) | 页面提示「仅在本机计算哈希,不会上传」 |
| 3 | 填运营方名称与区域,点「生成 CVIN 并提交声明」 | 返回 201 与证书地址 |
几个字段怎么填
| 字段 | 必填 | 填什么 |
|---|---|---|
operator | 三选一 | 你的运营方名称。会公开出现在登记记录里,建议用公司/品牌名 |
region | 否 | 机房代号,如 apac-sg、cn-hk-02,自己定规则 |
cluster_size | 否 | 这批卡的总规模,帮助引用方判断集中度 |
source_url | 建议填 | 能公开打开的设备清单/销售页。有它,别人才能自己复核;没有会被标为「自助申报(未核验)」 |
source_url 即可。四、路径 ②:脚本批量登记(一个机房)
先说清楚为什么要密钥:公开写入口按 IP 限频(每小时 12 条、每分钟 3 条),这是防滥用用的,不是给你登记机房的。一个 200 台的机房靠它要排一天。
第 0 步:拿一把运营方密钥(写权限 → 5000 条/小时)
邮件 hi@cvin.org,写清机房大致规模与预计登记台数,我们签发一把绑定到你名下的密钥。之后所有请求带上请求头 x-api-key: cvink_...,按密钥计桶,不再受单 IP 自助限频约束。密钥随时可停用。
第 1 步:单条 curl 跑通
curl -X POST https://cvin.org/v1/declare \
-H 'content-type: application/json' \
-H 'x-api-key: cvink_你的运营方密钥' \
-d '{
"cvin": "cvin:nv.h100.sxm.80g:6a1kfvdo43buqm34",
"operator": "your-cloud-name",
"region": "apac-sg",
"cluster_size": 256,
"source_url": "https://your-site.com/fleet/h100"
}'
返回 201,响应里带 certificate_url 与 resolve_url,直接可拼成公开链接。
第 2 步:批量脚本(已实测,下载即跑)
把序列号写进 serials.txt(每行一个),改脚本顶部 5 行配置,然后 python3 cvin_onboard.py。它会为每台设备:算 CVIN → 提交声明 → 生成并落盘设备密钥 → 签名上报遥测 → 打印证书链接。
下载 cvin_onboard.py 依赖:Python 3.8+ 与 pip install cryptography,无其它依赖
pip install cryptography
printf 'SN-H100-001\nSN-H100-002\nSN-H100-003\n' > serials.txt
# 改 cvin_onboard.py 顶部 CONFIG:base / operator / region / api_key
python3 cvin_onboard.py
输出长这样(真实运行结果):
共 7 台待登记,已有 0 把设备密钥
[1/7] cvin:nv.h100.sxm.80g:4m9cmvze0vlh9fnx ✓ 已登记,身份 L2,证书 https://cvin.org/r/cvin:nv.h100.sxm.80g:4m9cmvze0vlh9fnx
...
完成:成功 7 / 失败 0
设备私钥已存 device_keys.json —— 务必备份,丢了无法重建(服务端不允许换密钥)
脚本里真正重要的只有 6 行
如果你要接进自己的采集系统,不需要用这个脚本,只要照抄哈希算法——它必须和服务端逐字节一致:
import hashlib, re
B36 = "0123456789abcdefghijklmnopqrstuvwxyz"
def norm_serial(s):
s = re.sub(r"[\s_\-./:#]+", "", str(s).strip().lower())
return re.sub(r"^(sn|s/n|serial|serialno)", "", s)
def serial_hash(serial, n=16):
h = hashlib.sha256(norm_serial(serial).encode()).hexdigest()
x, out = int(h, 16), ""
while x:
x, r = divmod(x, 36)
out = B36[r] + out
return out[:n].ljust(n, "0")
# 下面 4 种写法都得到同一个结果 6bw5zi5393srzm4v
for sn in ["SN-H100-001", "sn_h100_001", " H100 001 ", "serialH100001"]:
print(serial_hash(sn))
-,没去 _ 和空格,于是 SN-H100-001 与 SN_H100_001 算出两个 CVIN——同一台卡被登记两次,历史被劈成两半。五、路径 ③:升到 L2(设备自己签名)
登记本身只到 L1:你能证明「这个运营方说这台设备存在」。到了 L2,证明升级为「这台设备自己签了字」——不需要相信你。这个差别决定了它能不能用于抵押、投保、资产池入池。
| 身份等级 | 怎么来的 | 能主张什么 | 典型用途 |
|---|---|---|---|
| M 型号级 | 只登记型号,不登记具体机器 | 这个型号在市场存在,不代表某一台 | 供方挂牌、行情参考 |
| L0 挂牌指纹 | 挂牌信息生成指纹 | 同一挂牌没被改过,不能主张是同一台物理设备 | 线索去重 |
| L1 序列号可观测 | 提交序列号哈希 + 来源 | 设备存在,且跨运营方可对齐(同一序列号即同一台) | 登记、抵押物清单、租前验机 |
| L2 硬件信任根 | 设备私钥签名遥测 | 这次的遥测确实由这台设备签发 | 在押持续验证、自动理赔触发、无人值守审计 |
签名原文怎么算
import base64, hashlib, json, time
from cryptography.hazmat.primitives.asymmetric.ed25519 import Ed25519PrivateKey
from cryptography.hazmat.primitives import serialization
def canon(v): # 键排序、无空格、数组保序 —— 与服务端逐字节一致
if not isinstance(v, (dict, list)):
return json.dumps(v, separators=(",", ":"), ensure_ascii=False)
if isinstance(v, list):
return "[" + ",".join(canon(x) for x in v) + "]"
return "{" + ",".join(json.dumps(k, ensure_ascii=False) + ":" + canon(v[k])
for k in sorted(v)) + "}"
sk = Ed25519PrivateKey.generate()
pub = sk.public_key().public_bytes(
serialization.Encoding.PEM,
serialization.PublicFormat.SubjectPublicKeyInfo).decode()
CVIN = "cvin:nv.h100.sxm.80g:6bw5zi5393srzm4v"
AT = time.strftime("%Y-%m-%dT%H:%M:%SZ", time.gmtime())
T = {"hours_power_on": 12480, "ecc_errors": 2, "temp_c": 61}
msg = hashlib.sha256(canon({"cvin": CVIN, "observed_at": AT, "telemetry": T}).encode()).hexdigest()
sig = base64.b64encode(sk.sign(msg.encode())).decode()
# 把 CVIN / AT / T / pub / sig 一起 POST 到 /v1/attest,即完成 L2 签名证明
遥测只收这些字段
hours_power_on · ecc_errors · ecc_uncorrectable · temp_c · power_w · sm_count · mem_total_mb · driver_version · uuid · pcie_bdf · utilization_pct
白名单之外的字段会被丢弃。uuid 与 pcie_bdf 只存哈希(12 位),不落明文。至少要有其中一个字段,否则返回 400 empty_telemetry。
device_keys.json 一旦生成就地备份(建议进 KMS 或密码管理器)。丢了,这台设备就永远停在 L1。六、登记完,这三样东西怎么用
给人看的证据
每台设备都有一个可外链的证书页,含 CVIN、首末观测时间、观测条数、链头哈希、ed25519 签名与公钥。
/cert/cvin%3Anv.h1…
贴到销售页
一枚自动更新的 SVG:已登记显示「已登记 · 链可重放」,未登记显示「尚未登记」。买家点进去就能自己核。
/badge/<cvin>.svg
进你的系统
把 CVIN 写进报价单、租赁合同、抵押物清单、二手商品页——它是一行字符串,任何系统都能存。
GET /v1/resolve/<cvin>
徽章贴法(复制即用)
<a href="https://cvin.org/r/cvin%3Anv.h100.sxm.80g%3A6a1kfvdo43buqm34" target="_blank" rel="noopener">
<img src="https://cvin.org/badge/cvin%3Anv.h100.sxm.80g%3A6a1kfvdo43buqm34.svg"
alt="CVIN 已登记 · 机况可核验" width="340" height="72" loading="lazy">
</a>
徽章是实时渲染的:一旦这台设备被判定未登记或链有断点,它会自己变色。所以它不能靠 P 图伪造——这也是它对买家有用的原因。
七、谁该登记(以及谁不必来)
CVIN 不是给所有人用的。落到具体角色,只有三类人有理由动手:
算力运营方 / 租赁商
自建机房、卖 GPU 小时、做算力租赁。你的痛点是「买家凭什么信我这批卡是真的」。CVIN 给你一张可外链的证书和一枚徽章,报价单和销售页直接贴。
成本:$0
二手 GPU 交易 / 寄售 / 回收
一台卡几十万,看走眼一次就吃掉十单利润。你要查的是:序列号真不真、是不是同一台、有没有被别人押过、历史连不连续。按次核验报告 $2,可打印留档。
成本:$2 / 次
融资租赁 / 抵押借贷 / 保险
放款或承保前后,需要的不只是一次查询,而是整个在押周期内设备还在、还在同一台机器上。这是持续验证 + webhook 告警的场景。
成本:按在押台数月付
如果你不属于这三类——例如你只是想知道某张卡的二手行情,或者想拿 CVIN 当信用分用——那它现在帮不上你。我们不打算把「事实记录」包装成「评级」,那会让整张登记表失去被金融方引用的资格。
八、我们卖什么、什么永远不要钱
九、出错怎么自己排查
| 状态码 | error | 原因 | 怎么改 |
|---|---|---|---|
| 400 | invalid_cvin | CVIN 格式不对,或哈希不是 16 位 | 照第一节的格式核对;哈希必须是 base36 字符 |
| 400 | missing_fields | source_url / operator / attrs 一个都没有 | 至少给一项来源说明,否则记录无法被复核 |
| 400 | invalid_input | 用型号四要素现算 CVIN 时字段非法 | 四要素只能是小写字母和数字 |
| 400 | empty_telemetry | 遥测字段全被白名单滤掉了 | 至少上报 hours_power_on 或 ecc_errors 之类之一 |
| 400 | attestation_rejected | 签名验不过 | 九成是规范化不一致(键没排序 / 有空行 / 数字写成字符串) |
| 401 | write_key_required | 调了抵押、资产池等高价值写入口 | 那些接口需要受托密钥,普通登记走 /v1/declare 即可 |
| 409 | duplicate_write | 同 CVIN + 同来源 10 分钟内重复 | 等待或换 source_url;不影响后续签名上报 |
| 409 | device_key_mismatch | 这台设备已绑定另一把密钥 | 找回原 device_keys.json;找不到就只能停在 L1 |
| 429 | rate_limited | 公开写入限频(12/小时、3/分钟 per IP) | 申请运营方密钥,或按响应里的 retry_after_s 等待重试 |
十、常见问题
登记要钱吗?会一直免费吗?
登记、签名上报、证书、徽章永久免费,不限次数。这不会变——登记表的全部价值来自设备覆盖度,向写入方收费等于给网络效应上闸。
你们能看到我的资产清单和客户吗?
不能。只上传序列号的 16 位哈希,单向不可逆;遥测里的 UUID 与 PCIe 地址也只存 12 位哈希。你可以选择公开或只给特定对象看证书。
序列号算出来撞车怎么办?
16 位 base36 约 1.2×10²⁵ 的空间,实际碰撞概率可以忽略。真正会「撞」的是同一台设备用两种写法算出两个 CVIN——所以内外系统对齐同一个序列号来源很重要。
设备下线或卖掉了,记录能删吗?
单条记录不可删除(这是链的意义),但可以追加一条状态观测,说明「该设备已于某日转出」;证书页会反映最新状态。机主也可以申请隐藏公开可见性。
我自己写系统,能直接对接吗?
能。整个接入只有两个写接口:POST /v1/declare、POST /v1/attest;读是 GET /v1/resolve/{cvin}。规范见 spec v0.1,字段见 数据字典。
十一、下一步
先拿一台真机跑通路径 ①,确认证书页显示正常;再决定要不要批量。中途卡住,直接把这台机器的 CVIN 发给我们,我们可以按记录反查是哪一步没过。