多数交易所的储备证明页面,本质上只是一串钱包地址加一个绿色对勾。那只是容易的一半。真正的问题是:托管方能否证明自己控制的资产,至少等于所有用户余额之和,同时又不公开每个人的余额?

一份完整的 PoR 由两个独立的部分组成:

  1. 资产证明:托管方确实控制这些地址,并且资产是自由的——不是借来的、抵押出去的或已贷出的。
  2. 负债证明:公布的总负债等于所有用户余额之和,且每个用户都能验证自己的余额被包含在内。

只有两者同时成立,资产 ≥ 负债 才有意义。

拍下负债快照

在固定的区块高度 h(或时间点)冻结账户数据库。所有构成用户债权的账户都必须纳入:现货、杠杆、合约盈亏、理财、待提现、内部账户。负余额要净额处理,衍生品负债需要明确的盯市规则。这一步几乎没有密码学,却最容易出错:漏掉一类账户,整份证明就是假的。

把每个余额承诺成叶子

对账户 i:

1
leaf_i = H("leaf" || user_id_i || salt_i || balance_i)
  • salt_i 每个用户唯一且私密。没有它,任何人都能对已知余额做哈希暴破,从而枚举账户。
  • H 使用抗碰撞哈希,例如 SHA-256 或 Keccak-256。
  • 域分隔("leaf" 与 "node")防止把内部节点伪装成叶子进行第二原像攻击。

相邻叶子两两哈希、逐层向上,最后公布 Merkle 根 R。树的构造必须无歧义:固定的左右顺序,明确奇数节点的处理规则(上移,或与零叶子哈希)。歧义会带来重复叶子攻击和树形攻击。

n 个账户的树深度为 ceil(log2 n);一百万账户的包含证明大约只有 20 个哈希。

公布根,分发证明

运营方对 (R, h, total_liabilities) 签名。每个用户拿到 (balance, salt, user_id, sibling path),自己重算叶子、沿路径向上折叠,再与签名根比对。任何一个叶子变化,经过它的所有路径都会变化。

这证明的是包含性:我的余额在这个承诺集合里。它本身不证明集合包含所有用户,也不证明公布的总数是真实求和。那是另外两个命题。

证明资产

资产侧是另一套流程:

  • 公布持有储备的地址。
  • 每个地址用私钥对一条挑战消息签名,避免抄一份地址列表冒充所有权。
  • 在负债快照所用的同一个区块高度 h 读取余额。

资产总和必须覆盖负债,但控制地址不等于资产无负担。已经贷出、作为抵押品、参与质押,或存放在第三方托管处的币,可能仍显示在交易所控制的链上地址里,但它们不是自由储备。链下法币和应收款通常不在多数 PoR 的范围内。

各方到底能验证什么

主体可验证内容
用户叶子哈希、Merkle 路径、签名根 → 自己的余额被包含
审计方根、地址签名、数据库对账、总负债、账户类型完整性
公众根签名、时间戳、地址控制权、资产与负债总额

用户无法验证总额;公众无法验证没有账户被遗漏。这个缺口是结构性的。

PoR 会在哪里失效

  • 借储备 / 窗口粉饰:快照前借币、快照后归还。时点证明与资不抵债并不矛盾。
  • 负债不完整:隐藏账户、未披露的负余额、衍生品敞口、待提现、内部做市账户。
  • 资产有负担:已抵押或已贷出的资产仍然显示在链上。
  • 时间错配:资产取高度 h,负债取另一个时间。
  • 承诺构造薄弱:无盐 → 可枚举;无域分隔 → 可伪造证明;树形有歧义 → 重复叶子。
  • 依赖审计方:鉴证(attestation)的可信度取决于审计范围和独立性。
  • 证明过期:半年前的根说明不了今天。

更强的方案

zk-PoR / 偿付能力证明。不公布每个叶子,而是用隐藏承诺(例如 Pedersen)对余额承诺,再给出零知识证明:所有被承诺的余额之和等于公布总额,且每个余额非负(区间证明)。这能隐藏个体余额,在某些设计中不再需要给每个用户发 Merkle 路径,并且把“总额”密码学地绑定住,而不是相信运营方自己算的加法。但完整性难题仍在:除非能检查数据库,否则任何证明都无法证明“某个账户没有被排除”。

持续证明。更频繁地更新签名根、在链上公开储备地址、随机抽查用户,能压缩窗口粉饰的时间窗,但不能消除它。

币安的 PoR 实践

2022 年 11 月 FTX 崩盘后,币安是最早一批上线公开 PoR 页面的交易所,最初的版本只覆盖 BTC,用一棵普通 Merkle 树承诺用户余额。2023 年 2 月,币安把系统升级为 zk-SNARK 版本并开源,正是前面 zk-PoR 方案的落地:

  • 负债侧:每个用户余额是一个叶子,登录后可拿到自己的 Merkle 路径并重算到公布根——标准的包含性证明。
  • 总额侧:用 zk-SNARK 电路证明两件事——所有叶子之和等于公布的负债总额,且不存在负余额。这相当于用密码学锁住了"总额"和"无负余额",不再依赖运营方自己算的加法。
  • 资产侧:公布一批储备钱包地址,链上读取余额,按币种给出储备率(reserve ratio),宣称每种资产不低于 100%。
  • 频率:每月更新一次快照,覆盖币种从最初的 BTC 扩展到几十种。

但它也恰好落在本文列出的失效点上:

  • 无独立审计:早期曾聘请 Mazars 出具鉴证报告,2022 年 12 月 Mazars 暂停全部加密客户业务后,PoR 变成纯自证。
  • 范围有限:只覆盖用户表内资产,不包括公司自身的贷款、集团内部负债与法币偿付能力——资产 ≥ 负债 成立,推不出"公司有偿付能力"。
  • 时点快照:月度快照之间的 30 天,窗口粉饰无法排除。

币安的实践说明了 PoR 的真实边界:Merkle 包含证明和 zk-SNARK 总额证明是可靠的密码学部分,而账户完整性、资产是否自由、公司整体负债,仍然不在密码学覆盖范围内。

五分钟检查清单

  1. 是否有带明确时间戳和区块高度的签名根?
  2. 用拿到的盐和路径,你的叶子能否重算到该根?
  3. 储备地址是否有签名?余额是否在同一个高度读取?
  4. 总资产 ≥ 总负债 是否成立?借来或抵押的资产是否被排除?
  5. 审计报告是否写明了纳入范围的账户类型和资产类型?
  6. 证明是否足够新,是否有公开的更新频率?

PoR 是密码学包含证明加签名控制证明。密码学部分是可靠的部分;完整性和资产负担,仍然取决于流程、审计范围与信任。