使用本页可以正确读取 rand_getSupply,并推断发行情况:RAND 从何而来、流向何处,以及使屏蔽链的供应量在无人能对票据求和的情况下仍然精确的恒等式。
RAND 的来源与去向
屏蔽链无法对自己的资金求和:票据的价值藏在其承诺之内。公开的是每一次跨越屏蔽池边界的流动。共有五类,在带有程序金库的链上(RPL-2,自链 20 起)为七类;在链 21(fullnode v0.8.0,自 2026-10-12 起上线)上,多签账户与永续合约引擎又各自增加了自己的流动类型:
| 方向 | 跨越边界的流动 | 时间 |
|---|---|---|
| 流入 | 创世存入票据(创世文件中的 alloc,自链 14 起公开其打开信息) | 区块 0 |
| 流入 | 水龙头铸造(Mint,最多 100 RAND,由验证节点签名,自链 14 起附带票据的打开信息) | 设有 "faucet": true 的 testnet 链;自链 20 起仅限 16 个白名单钱包,由 18 个创世列明的铸造者之一签名,每个 1,000 区块的纪元至多 10,000 RAND |
| 流入 | 验证节点的 Withdraw,将已释放的质押与奖励支付到一张票据中 | 任何时间 |
| 流出 | 一个捆绑包的 fee:至链 20 为止全部进入区块提议者的 rewards;在链 21 上,费用下限被销毁(burned,计入 base_fees_burned),只有小费归提议者 | 每个捆绑包 |
| 流出 | 一个捆绑包的 burn_r:Bond 将质押销毁并计入某验证节点的公开 stake | 每次绑定 |
| 流出 | 一个 Invoke 的 burn_r:存入某程序公开金库的 RAND | 自链 20(v0.6.8)起 |
| 流入 | 金库支付:Invoke 从程序金库中以票据形式支付出的 RAND,其数额与接收方公开 | 自链 20(v0.6.8)起 |
| 流出 | CreateMultisig 或 MultisigDeposit 的 burn_r:支付到多签账户公开余额中的 RAND(multisig_rand_in) | 链 21,自 v0.8.0 起 |
| 流入 | MultisigPay 的票据:账户支付出的 RAND,数额与接收方公开(multisig_rand_out) | 链 21,自 v0.8.0 起 |
| 流出 / 流入 | PerpDeposit 向交易账户的销毁,以及由链计算的永续合约支付票据(perps_rand_out、perps_rand_held);在链 21 上,唯一市场的抵押品是 zUSD,因此这些计数器在该链上读数为 0 | 链 21,自 v0.8.0 起 |
在创世文件设置了 tokens.burn_registration_fee 的链上(链 21 即如此,自链 15 起每条链亦然),代币注册的 1 RAND registration_fee 同样通过 burned 离开屏蔽池,但不进入任何登记项:它被销毁,提议者只保留捆绑包的基础费用。在链 21 上,创世的 fees 部分(burn_base 与 burn_floor)对每个捆绑包已结算的费用下限同样如此处理——转账的 0.001 RAND 基础费用、部署的按字计费项、调用的 gas 与字节计费项、桥销毁的 0.01 RAND——因此提议者只保留小费,即 fee − floor,fees_paid 也只按此变动(费用)。
屏蔽池之外还有验证节点登记表,其中的数额是明文,因为共识权重必须公开。登记表中的质押是真实的 RAND:可以解除绑定,并提取回一张票据。自链 20 起,程序金库是其旁的第二个公开余额:Invoke 存入的 RAND 在其中保持可计量,直到一次支付将其以票据形式送回屏蔽池。链 21 增加了第三个,即多签账户(交易):按资产分列的余额,由达到阈值数量的 Dilithium2 密钥共同支配,创世时存入基金会国库,并向任何人的 CreateMultisig 开放,费用为 1 RAND。
链 21 上没有区块奖励,也没有通胀。该链首个计划中的发行是区块聚合补贴——每个已封存区块发行的新 RAND 数额递减,支付给其证明覆盖该区块的聚合者——它在链 21 上并未启用(证明);v0.8.0 还带有它的一种以美元计价的形式(fees.usd_subsidy,按验证节点集合通过 SetRandPrice 投票得出的 RAND/USD 价格折算),链 21 同样没有开启它。链 21 是一条全新的链,自 2026-10-12 起上线(创世于 10:22 UTC 切出,26 个验证节点于 10:31 UTC 完成切换),由链 20 切出(fullnode v0.8.0,一次硬分叉)。其创世共发行 129,938.879078887 RAND:26 个创世验证节点共质押 26,000,七张存入票据中有 3,938.879078887(即从链 20 沿用的七个运营方钱包的余额,来自对链 20 屏蔽池在高度 822,056 至 822,229 的一次扫描),以及基金会国库中 100,000 RAND 的新发行,该国库是一个 2-of-3 签名者的多签账户(id 为 d5fd1883…1958,即 rand_getSupply.multisig_issued)。其他钱包在链 20 上持有的约 36,025 RAND(其中 35,040 RAND 为向白名单接收方的水龙头铸造,即付给用户的款项)没有被沿用,因为没有所有者的地址就无法重建票据;2.606 RAND 未提取的验证节点奖励同样没有沿用。另有三张创世票据承载桥的 100.001999 zUSD(10、89.002999 和 0.999),等于锁定在其四种抵押背书上的托管额,它不是 RAND,不在本次审计范围之内。链 21 上的 rand_getSupply 读数为:genesis_deposited 3,938,879,078,887 单位,genesis_staked 26,000,000,000,000,multisig_issued 100,000,000,000,000,且 invariant_holds: true(高度 2,178,2026-10-12)。链 20 于 2026-10-01 在高度 7,258 处由链 19 的状态切出,共发行 31,184.243719258 RAND:同样是 26,000 的质押,以及七张票据中的 5,184.243719258,另有两张共 99 zUSD 的票据。链 15 于 2026-09-26 切出,创世发行 23,000 RAND,其中 18 个验证节点共质押 18,000,五张票据中为 5,000;其后的八个验证节点由现有票据绑定而来,未发行任何新币。此后每一次水龙头铸造都会增加已发行数额,每一笔被销毁的费用都会减少它。
代币不在本次审计范围内
上述流动属于 RAND。RPL 代币,无论是桥接的还是原生的,从不跨越 RAND 的边界:资产索引 0 为 RAND 保留,代币登记表从不分配它,因此 BridgeAttest、TokenMint 或注册时的初始铸造总是存入某种其他资产的票据,而 BridgeBurn 或 TokenBurn 的 burn_a 总是销毁一张其他资产的票据(通过 burn_a 销毁 RAND 会被拒绝)。fees_paid 与 burned 仅依据捆绑包的 fee 与 burn_r 计数,而屏蔽池内部的代币转账完全不移动任何计数器,因为其资产甚至不公开。自链 20 起,Invoke 还可以通过 burn_a 接收一种代币:存入程序的金库(deposit),其供应量不变;或将其销毁(burn),且仅限程序自身的代币。桥的费用票据(自链 20 起,每笔 zUSD 存入和销毁收取 10 bps,付至一个国库地址)是 zUSD,绝不是 RAND:已发行且有背书,因此一笔存入的背书与供应量按总额变动,而一笔销毁的则按 amount − fee 减少。代币自身的供应量是登记表的公开计数:rand_getTokenSupply 返回 total_supply,对于桥接代币,还返回各背书的 locked 数额,二者之和等于总供应量(RPL 代币)。在链 21 上,永续合约引擎的抵押品同样是 zUSD,因此交易账户的存入与支付属于代币流动,在本次审计之外(perps_rand_* 计数器是为以 RAND 作抵押的市场而设,读数为 0)。
审计恒等式
六个单调递增的计数器,以单位计(1 RAND = 10⁹),其中三个记录被销毁的部分,两个用于程序金库(自链 20 起),在链 21 上另有五个用于多签账户、两个用于永续合约引擎:
| 计数器 | 累计内容 |
|---|---|
genesis_deposited | 创世文件中 alloc 存入的票据 |
genesis_staked | 创世时写入登记簿的质押 |
faucet_minted | 每一笔被接受的 Mint |
withdraw_deposited | 被接受的 Withdraw 所创建的票据(每笔 amount − 0.001 RAND) |
fees_paid | 每个交易包的手续费 |
burned | 每个交易包的 burn_r(Bond 的质押;自 chain 20 起还包括 invoke 的金库存入,在 chain 21 上还包括多签创建或存入),每笔被销毁的注册费,以及在 chain 21 上每笔被销毁的费用底价 |
slashed | 被罚没的聚合器保证金(区块聚合;关闭时为 0) |
registration_fees_burned | 依据 tokens.burn_registration_fee 销毁的注册费,同时也计入 burned |
base_fees_burned | 依据创世 fees 部分销毁的交易包底价(chain 21:burn_base 搭配 burn_floor),同时也计入 burned;此前的每条链上为 "0" |
program_rand_out | 程序金库已付出的 RAND 票据(RPL-2;没有 program_state 部分时为 0) |
program_rand_held | 金库仍持有的 RAND:每次 invoke 的 burn_r 减去 program_rand_out。它是经由 burned 进入的,因此是该计数器在金库一侧的对应项 |
multisig_issued | 多签账户的创世余额(chain 21:100,000 RAND 的金库)——属于发行,与 genesis_staked 并列 |
multisig_rand_in | CreateMultisig 或 MultisigDeposit 存入的每一笔 burn_r;包含在 burned 之内,从池到登记簿 |
multisig_rand_out | MultisigPay 创建的每一张 RAND 票据:进入池的价值,与 withdraw_deposited 并列 |
multisig_base_out | 支付时从账户付给提议者 rewards 的 0.001 RAND 基础费:从登记簿到登记簿,不构成跨越 |
multisig_rand_held | issued + rand_in − rand_out − base_out:账户所持有的数额,即 total_supply 在登记簿一侧的部分 |
perps_rand_out, perps_rand_held | 永续合约引擎交易账户的同一对计数器,适用于以 RAND 作抵押的市场;在 chain 21 上为 0,其市场以 zUSD 计价 |
pool_value = genesis_deposited + faucet_minted + withdraw_deposited
+ program_rand_out + multisig_rand_out + perps_rand_out − fees_paid − burned
register_total = Σ over the register of (stake + pending + rewards)
total_supply = pool_value + register_total + program_rand_held + multisig_rand_held + perps_rand_held
issued = genesis_deposited + genesis_staked + faucet_minted + multisig_issued
invariant: total_supply == issued − slashed − registration_fees_burned − base_fees_burned
pool_value 是进入的数额减去离开的数额——与票据总和是同一个数,而票据总和无人能够计算。withdraw 的 0.001 RAND 基础费不构成跨越:它从登记簿的一行移到提议者的一行,只有票据发生了跨越。invariant_holds 为 false,意味着共识缺陷或数据库损坏,绝不是合法状态。在没有 program_state、multisig 或 perps 部分的链上,程序、多签和永续合约项为零;没有 fees 部分时 base_fees_burned 为零,因此该恒等式与 chain 19 的相同;在 chain 20 上只有程序项生效,在 chain 21 上则全部生效。创世 vesting 部分(至今没有任何一条链使用过)将以同样的方式再增加一个公开登记簿(JSON-RPC)。
以一笔 bond 和一笔 1,000 RAND 的 withdraw 为例,在一条存入 2,000、质押 4,000 的链上逐步跟踪:
| 之后 | burned | withdraw_deposited | fees_paid | pool_value | register_total | total_supply |
|---|---|---|---|---|---|---|
| 创世 | 0 | 0 | 0 | 2,000 | 4,000 | 6,000 |
| 一笔 1,000 的 bond(手续费 0.001) | 1,000 | 0 | 0.001 | 999.999 | 5,000.001 | 6,000 |
| 其 unbond | 1,000 | 0 | 0.001 | 999.999 | 5,000.001 | 6,000 |
| 其 1,000 的 withdraw | 1,000 | 999.999 | 0.001 | 1,999.998 | 4,000.002 | 6,000 |
如何读取
curl -s http://127.0.0.1:8545 -H 'content-type: application/json' \
-d '{"jsonrpc":"2.0","id":1,"method":"rand_getSupply","params":[]}'
{ "height": 1998,
"genesis_deposited": "2000000000000", "genesis_staked": "4000000000000",
"faucet_minted": "0", "withdraw_deposited": "999999000000",
"fees_paid": "1000000", "burned": "1000000000000",
"slashed": "0", "registration_fees_burned": "0", "base_fees_burned": "0",
"pool_value": "1999998000000", "register_total": "4000002000000",
"total_supply": "6000000000000", "invariant_holds": true }
每个数额都是以单位计的十进制字符串,因为超过 2⁵³ 之后,JSON 数字不再是精确的整数。完整对象包含的字段比此处所示更多,其中有水龙头的每纪元一对计数器 faucet_epoch 和 faucet_minted_in_epoch(chain 21 据此对照其预算进行检查)、program_rand_out 和 program_rand_held(自 v0.6.8 起)、base_fees_burned、五个 multisig_* 和两个 perps_* 计数器(自 v0.8.0 起),以及四个 vesting_* 计数器,它们在 chain 21 上读数为 "0",因为其创世没有 vesting 部分(JSON-RPC)。浏览器在 GET /supply 提供同一对象,在 GET /stats 提供其中的主要数字。
精确到什么程度
对于链自身完成的一切,这些计数器是精确的:每一个都在应用相应操作的代码路径中递增,取值来自该操作自身的公开字段。
曾有两项依赖于一种声明,chain 14 将两者都变成了检查(审计 v3,POOL-1):
- 水龙头
Mint携带票据的打开信息。 除cm和amount之外,该操作还公布pk、time和r。准入时会重新计算(pk, no sender, amount, asset 0, time, r)的承诺,若不一致则以the mint's commitment does not open to its published note and amount拒绝,并将time限定在交易包的时间窗口内。铸造者在域rand-mint-2下对全部七个字段签名。在此之前,验证者可以公布一个数额,却封存价值另一个数额的票据。代价是水龙头票据的所有者pk是公开的,正如 withdraw 的支付对象一样;rand_mint的参数不变。 - 创世
alloc票据同样携带其打开信息。 在带有tokens部分的链上,每一行都是{ cm, envelope, amount, opening: { pk, time, r } },节点会重新计算承诺——除非打开信息指明了所列代币的asset,否则按 asset 0 计算——并拒绝cm不匹配的创世文件。只有 asset 0 的行才计入genesis_deposited。不透明的cm曾是创世作者将无担保票据(任何资产的)放入池中而无人能够核查的唯一途径。因此,创世票据的所有者和数额在文件发布后即按设计公开;只有它之后何时被花费、被花费到何处仍然保持私密。rand-node genesis总是写入打开信息。
在不带 tokens 部分而创建的链上,旧规则依然适用:genesis_deposited 是所声明 amount 字段之和,取信于创世文件。无论哪种情形,两种创世数额都包含在创世哈希之中,因此每个节点对它们的认定都一致。
这些计数器有意不属于共识状态——状态根不对它们做哈希——而 rand-node verify --mode quick 通过重放链来重新计算每一个计数器,若存储的快照与之不符则报告不匹配。