阅读约 7 分钟
一条记录覆盖成千上万个文件:Merkle 批处理
一个 Merkle 根能让单条 Label 309 记录对成千上万、乃至上百万个文件哈希做出承诺,之后再用一份小巧的包含证明就能证明其中任意一项——无需把每一项都放到链上。

单条 Label 309 记录就能证明成千上万、乃至上百万个文件在某一时刻已经存在。
你不必为每个文件发布一笔区块链交易,而是对每个文件计算哈希,把这些哈希折叠进一棵 Merkle 树,再发布单个 32 字节的 Merkle 根。之后,你只需一份小巧的包含证明,就能证明某个文件曾属于这一批——既不暴露其余文件,也不必把每一项都放到链上。
存在性证明正是这样从一份文档扩展到任意规模的集合。
Merkle 批处理解决了什么问题?
区块链并不适合存放长列表。每一个字节都要付费,而 Cardano 交易又有硬性的体积上限。
如果一个系统持续产出制品——日志、模型输出、发布构建、发票、报告、证据条目——把每个哈希都作为独立的链上记录发布,很快就会变得昂贵又嘈杂。
Merkle 批处理把一个有序的哈希列表压缩成单个根承诺。根的大小固定(32 字节),批的规模可以无上限,而任意单项的证明都保持小巧——它只随批大小的对数增长。这让高频工作流也能切实地定期做出承诺。
什么是 Merkle 根?
Merkle 根是一个对整个有序列表做出承诺的单一哈希。
先从一份叶子列表开始。在存在性证明的工作流里,每个叶子通常是某个文件、某个事件或某条清单条目的哈希。这些叶子沿着一棵二叉树两两组合向上,树顶的哈希就是 Merkle 根。
这份承诺在三个方面都是精确的:
- 只要有任何一个叶子发生变化,根就会变化。
- 只要叶子的顺序发生变化,根就会变化。
- 承诺还记录了叶子的数量,因此一个规模不同的列表无法冒充同一批。
发布这个根,就如同为整个有序列表发布一枚指纹。
到底有什么会上链?
只有根上链。完整的叶子列表留在链下。
Label 309 记录用一个专门的 merkle 字段来承载这份承诺,与普通的逐文件哈希分开存放。每份承诺都是一个小巧、固定的结构:
- 承诺算法(Label 309 v1 注册了
rfc9162-sha256:即 RFC 9162 中基于 SHA-256 的 Merkle Tree Hash); - 32 字节的根;
- 叶子数量,它将根与链下列表的规模绑定在一起;
- 可选的内容寻址 URI(
ar://或ipfs://),指向那份叶子列表文件。
链上记录始终保持极小——单个根以 32 字节的固定成本对一个无上限的列表做出承诺。细节都存放在链下那份有序的叶子列表里。(关于一条记录其余部分存放在哪里,参见区块链上存了什么。)
之后如何证明某一个文件?
你需要拿出一份包含证明。
包含证明是从某个叶子向上到根这条路径上的一小串兄弟哈希。验证方把该叶子与这些兄弟哈希重新沿树折叠向上,只有当重算出的根与已发布的根完全相等时,才接受这份证明。
实际操作中,这项检查有四个输入:
- 你要证明的那个文件或条目的哈希;
- 包含证明(即兄弟路径);
- Label 309 记录中的 Merkle 根;
- 承载这条记录的那笔 Cardano 交易的区块时间。
如果折叠的结果重现了已发布的根,那么该项就确实在被承诺的列表里——而区块时间则见证了这份列表存在的时刻。验证方只需要那一项及其证明,根本不需要这一批里的其他文件。
有两个细节值得分清。这套构造对顺序敏感,因此叶子必须保持与发布时一致的次序。还有,单叶子的「树」并不是有用的时间戳:单叶子树的根并不等于叶子本身,所以要证明单个文件,你应当发布一个普通的内容哈希,而不是一份只含一项的 Merkle 承诺。
为什么完全离线地构建与验证是一种优势?
因为唯一需要接触服务器的步骤,只有发布根这一步。
构建树、推导包含证明、对其进行验证,都是纯粹的计算。任何持有那份有序叶子列表的人都能重算出根、重新推导出任意证明——不需要账户、不需要网关、不需要网络,也不需要最初发布者的配合。在验证环节,发布者从不参与其中。
这对那些必须比工具和供应商活得更久的证据意义重大。一份你能离线对照公开 Cardano 浏览器核验的证明,会在任何具体服务消失很久之后仍然有效。你可以用验证任意 Label 309 记录的同一套方法来验证一份批承诺,也可以借助开源的 cardanowall 命令行工具,把包含检查直接接入 CI(用 merkle-build 把一个文件夹折叠成一个根,用 merkle-verify 确认某一项是否属于它)。
这为什么对高频工作流有用?
因为现实中许多证明本就是批的形状,而非单文件的形状。一个团队可能需要表明:
- 某条 CI/CD 流水线构建了什么,以及一次发布中交付了哪些制品;
- 在某个漏洞被披露之前,存在哪份软件物料清单(SBOM);
- 某一天产出了哪些 AI 输出;
- 在一次训练运行之前,存在哪份数据集快照;
- 在一次审计之前,存在哪些合规日志;
- 在一项证据保全令之前,保存了哪些法律证据文件;
- 某份资产负债表在某一时刻对哪些储备做出了承诺。
上述任何一种都不太契合「一文件一交易」的模型。Merkle 批处理让你为每一批只发布单个承诺——既不暴露每一项私有内容,也不会产生随批大小线性增长的链上元数据。
叶子列表能保持私密吗?
可以。已发布的根不会泄露它所承诺的那些叶子的任何信息。
你可以把叶子列表留在自己的证据系统、发布归档、数据室或合规库里,之后只揭示你需要揭示的内容:
- 某个文件及其包含证明;
- 某一行数据集记录、某份文档或某个发布制品;
- 某条审计日志条目;
- 列表的一个子集;
- 或者整份叶子列表。
当你想要一个公开的、带时间戳的承诺,却又不想把底层数据公开时,用的就是这种模式——它与不公开文件的机密披露以及用 Merkle 根做储备金证明密切相关。
代价在于责任。根能证明某个已知规模的列表在某个已知时间存在过;但根本身并不能让任何人证明其中具体有哪些项。如果你让叶子列表保持私密,就必须把它妥善保存。一旦同时丢失了叶子列表和所有已保存的包含证明,你保住的是时间戳,却失去了证明某一具体项曾被承诺的能力。
一个叶子应该是什么?
一个叶子应当恰好代表你之后可能需要证明的那个东西。
对于文件,叶子就是文件字节的哈希。对于结构化数据,叶子通常是某条规范化清单条目的哈希。对于 CI/CD,一个叶子可能是制品摘要、SBOM 摘要、构建日志摘要、提交引用,或一条已签名的发布清单条目。对于 AI 来源溯源,一个叶子可能是输出文件的哈希、一条提示/输出清单条目、一份数据集项承诺,或一份内容来源溯源清单的哈希。
真正重要的纪律是一致性。如果叶子在不同的运行中以不同方式生成,之后的包含证明就会变得难以采信。把叶子的定义和规范化方式一次性固定下来,并每次都以同样的方式套用。
你应该发布叶子列表,还是让它保持私密?
这取决于你要证明什么,以及谁该看到它。
发布叶子列表让第三方验证变得轻而易举:任何人都能取回列表、重算根,并查看被承诺的集合。让它保持私密则带来机密性与选择性披露——你只在需要时才揭示包含证明。许多工作流两者兼用:开源发布用公开的叶子列表,内部合规日志用私密的,敏感证据则用封存的。
根是公开的承诺。叶子列表的策略,是叠加在其上的另一个独立选择。
你应该多久发布一次根?
让发布节奏与工作流相匹配。
CI/CD 系统可能每次发布、每次构建或每个部署窗口发布一个根。合规系统可能每小时、每天或每个控制周期发布一个根。AI 平台可能每批生成内容、每个训练快照或每个模型版本事件发布若干根。法律证据系统可能为每个案件卷宗、每个受理窗口或每个证据保管链里程碑发布一个根。
合适的节奏要在成本、运营简洁度,以及你之后可能需要证明的时间线精度之间取得平衡。
Merkle 根不能证明什么?
Merkle 根能证明某一时刻对某个列表的承诺。它不能证明围绕该列表的那些业务主张。和任何存在性证明一样,它表明特定字节在某个公开时间之前已经存在——而不证明这些字节为真、合法、由某人撰写,或归属于某人(参见证明不能证明什么)。
具体而言:
- 它不能证明一次软件构建是安全的。它能证明一次发布中包含了哪些制品或清单。
- 它不能证明一份数据集是合法采集的。它能证明某份数据集承诺在某个时间之前已经存在。
- 它不能证明一条日志条目为真。它能证明这条条目曾是某个已承诺批次的一部分。
- 它不能证明作者身份——除非记录本身,或围绕它的流程,加入了签名与身份控制。
在 Label 309 中,作者身份是可选且显式的:一条记录可以携带分离式签名,但它们从不是必需的,而单凭一份 Merkle 承诺,对谁产出了这份列表不作任何主张。根给出的是带时间戳的承诺,围绕它的流程才赋予其业务含义。
Label 309 在其中扮演什么角色?
Label 309 是面向 Cardano 上存在性证明的开放、厂商中立标准;它已提交至 Cardano 的 CIP 流程,作为一项元数据类别的提案,正由 CIP 编辑评审中。Merkle 批处理并不是一个单独的产品——它是内建于该标准之中的扩展层。
一份批承诺所用的记录,以及所走的验证路径,都与单文件证明完全相同。元数据 label 309 下的一条记录可以携带一个 Merkle 根,并在其旁附上任何记录都支持的那些可选部件:普通的逐文件哈希、内容寻址存储 URI、指向更早记录的取代指针,以及作者身份签名。因此,批证明继承了单条证明所拥有的一切:
- 一份 Cardano 区块时间见证;
- 一套标准、封闭的记录结构;
- 对照公开浏览器的独立、离线验证;
- 跨语言一致的同一套开源工具、库与 CLI。
对每一项计算哈希,构建一棵有序的 Merkle 树,在一条 Label 309 记录里发布单个根,并保存好叶子列表与你之后可能需要的任何证明。之后,你就能证明任意单项曾属于那个被承诺的批次——无需把每一项都放到链上。正是这一点,让存在性证明在 CI/CD、AI 来源溯源、数据集、合规、法律证据以及其他高频工作流中切实可用。
延伸阅读
- Label 309 的工作原理——批承诺所接入的记录结构。
- 在不泄露训练数据的前提下证明它——从一份私密叶子列表出发的端到端选择性披露。
- Label 309 与 OpenTimestamps 的对比——另一种把众多哈希聚合到单个锚点的协议。
- 标准、开源 SDK 与 CLI,以及规范文本:label309.org 与 github.com/cardanowall。
- RFC 9162——Label 309 用于批承诺的 Merkle Tree Hash 构造。