English

从一条数据到一份资产

协议 · · George (工程师) · 15 分钟阅读

你向一家 AI 公司交付了 10 万条标注数据。按照约定,只要这些数据被使用了,你就能够从中获取一部分收益。你对未来充满了期待,因为你相信你提供的数据质量是非常高的,应该可以给你带来不错的收益。

然而,事情却并不像想象中那么乐观。在接下来的半年里,你的数据只是被少量地使用,每次使用也只是用到了其中一部分而已,因此你所得到的收益比预想中少很多。你不知道怎么回事,你所知道的所有信息都是那家AI公司告诉你的,你只能够选择相信。

又过了一段时间,你偶然从一篇行业报道里看到,另一家公司竟然也有你的数据,而且不仅仅是自己使用,还提供给别的公司,并从中获取收益。你很吃惊,因为此前你并没有听说过此事,于是你去找到了签约的那家AI公司。

公司的回复滴水不漏:那家公司的数据”来源合规”,与你签的合同”不涉及第三方披露义务”;至于收益偏低,“按实际使用结算,市场行情如此”。你想核实其中任何一句——你的数据到底被用了几次、有没有被再次授权出去、那家公司手里的是不是你这一批——都做不到。使用记录在他们的数据库里,授权合同在他们的柜子里,你手里只有几笔打款流水。

你顺着报道又查了一下:那家公司对外卖的是一个 40 万条的数据集。如果你的 10 万条真的在里面,它们和另外 30 万条混在一起,连你自己都指认不出来——更不用说拿它去对质。

到这里,你甚至分不清发生的是哪一种:是公司隐瞒了交易,把该分给你的收益截留了;还是数据在某个环节被泄漏,对方根本没付过钱。前者是违约,后者是失控,两者的意义完全不同——而你连区分它们的手段都没有。

你可能会想,下次找一家更靠谱一点的公司,这种事情就能够避免。确实,有些平台会给你报表——用了几次、分你多少,列得清清楚楚。但出报表的和欠你钱的是同一方:报表之外有没有别的交易、数据集里你的条目还在不在、授权撤没撤,你没有任何独立于平台去核对的手段。逐条的指纹、成员表、授权记录,从来只在平台自己的数据库里。贡献不可证,归属不可查,授权不可撤回,这是这套记账方式的结构决定的,换谁签约都一样。要改变它,需要换一套记账的规则——这正是 XnY Protocol 要做的事。

这套新规则的关键在于颗粒度。给整个数据集留一个总的存证是不够的——那只证明某个时刻有过这么一批数据,你的条目在不在、混入的那批按什么比例稀释,这些关键信息并没有记录。XnY Protocol 把账算到每一条 sample:每条贡献有自己的指纹,数据集是一批指纹的公开聚合,在一批数据中你占了多少份额,都是公开记录的,任何人都可以使用这些公开信息进行查验。

左右对照:今天,一个 40 万条的数据集是个黑箱,你手里只有一份写着按贡献比例分配的合同;在 XnY 里,同一个数据集是一张公开的成员表,每行一条 sample,带 cfId、贡献者 DID 和权重,你的条目逐条可辨。任何人都能重算这张表,与链上公布的 Merkle root 比对,改动任何一行两个 root 就对不上。份额是你的权重之和除以 totalShares。
图 1 · 同一个 40 万条数据集:黑箱,或一张带指纹和权重的公开成员表

数据资产的三个条件

数据要成为可持续产生收益的资产,必须同时解决三件事。

可证明——这资产是什么,归谁所有。它有两个方向:往回追,我的贡献从哪来、被谁改过、被谁审核;往前追,它进了哪个数据集、对应哪份收益。

可拥有——所有权必须是可行使的权利,不是合同里的一句声明。可行使意味着四件事:

可访问——资产可以流动,但是数据本身不可以。谁能拿到数据,凭什么拿,授权怎么撤销——这三个问题的答案得由机制保证,说到做到,而不是写在条款里的承诺。

三者缺一即不成立:不可证则无从确权,不可拥有则无从交易,使用不可控则没人敢把数据放出来。我们再看看开篇,这三个条件一个都不具备,所以分成也只能是合同里的一句话而已。

对于这三个条件,XnY Protocol 各设计了一个机制,后面三节分别展开。机制里出现的协议对象,都放到它们第一次出场的地方解释;只有身份需要先交代——它贯穿所有机制。

身份:DID

DID——全称 Decentralized Identifier,去中心化身份标识,一个 W3C 标准。贡献者的链上身份,写作 did:xny:<uuid>,链上存为一个 uint128。它是个假名标识,不含任何真实身份信息。协议里所有的写操作都绑定 did 而不是钱包地址——身份和签名钱包是解耦的,钱包可以换,身份不变,这一点在后面讲收益领取时会再出现。

区块链在协议中的意义

协议把需要公开验证的事实都”锚在链上”——后文每个机制都会这么做。值得先停下来讲清楚:为什么要使用链,它到底提供什么。

文中说的链,都是指区块链。在这套协议里,它就是那本”不属于任何一方的账本”。它提供三样东西:

这正是开篇故事里缺的东西:出报表的和欠你钱的不再是同一方,因为账本不在任何一方手里。

同样重要的是链不负责什么。它不知道一条数据的内容对不对——那是审核签名的事;它也不保密——链上的一切都是公开且永久的。所以什么该上链、什么不该,有一条清楚的分界:

这样一来,你可以证明一份内容没被改过,而不必把内容给任何人看。

不可篡改也有代价:写错的东西改不掉,只能追加更正。协议为此把”追加更正”做成了一等公民——下一节会看到,有一类记录 (AMENDS) 专门干这件事,修正和原始记录都留在账上,谁改的、改了什么,一并可查。

一条贯穿所有实体的通则:链上对象有一个 id,通常还有内容的 metadataHash 和 metadataUri,再加上它自己类型需要的少数字段。内容本身留在链下,两边靠 hash 对上,要验完整性就取回内容重算一遍。这个划分的含义会在存储一节展开。

最后,协议的链上对象和它们的上下文,图 2 给出一张总览——每个对象都会在后文第一次干活的地方展开。

协议核心对象总览:DID 是身份,通过 contributorDid 指向 CF(贡献指纹),通过 assemblerDid 指向 DatasetVersion;一批 CF 按权重聚合成 DatasetVersion,DatasetVersion 的 datasetId 被 Grant 授权锚点引用;Frontier、Campaign、Task 三层是上下文锚,只有 taskId 进入 CF,它们不参与所有权、收益和授权。
图 2 · 协议核心对象与上下文锚

可证明

可证明分两层:单条贡献的来源可追溯,和跨数据集的所有权可确认。先讲第一层。

每一条贡献有自己的指纹

协议不定义”提交”和”审核”的流程——那是各家平台自己的事。它定义的是两个可签名、可上链的产物。

第一个是内容指纹,协议里叫 CF——全称 Contribution Fingerprint。每条贡献登记为一条 CF,它就是这条贡献的锚。CF 的 id 是这样算的:

cfId = keccak256(metadataHash, contributorDid, taskId)          // 无父级
cfId = keccak256(metadataHash, contributorDid, taskId, parentCf) // 有父级

内容动一个字,metadataHash 就变,cfId 就完全不同——像给内容按了个手印。注意这个公式里刻意没有 metadataUri:一条贡献由它的内容定义,不由它存放的位置定义。位置坏了可以修——合约为此提供了 updateCFMetadataUri,只有贡献者本人或已授权的审核员能够调用——但 cfId 永远不变。

CF 里还有一个 taskId,指向链上登记的一个 Task——它参与 CF 的 id 计算,是协议的一部分。Task 之上另有 Campaign 和 Frontier 两层策展层级,这三层对所有权和收益来说只是上下文锚:链上承诺它们存在、元数据可验,但是它们不参与所有权、收益、授权的任何机制——数据集的组装甚至是跨 Frontier 的,一个版本可以聚合来自任意任务的 CF。本文不展开这三层的业务含义。

parentCf 是血缘的关键。每条 CF 带一个类型 AtomicKind,一共四种:

标注、修正、审核这些后续动作,都通过 parentCf 挂到它们所作用的那条数据上。这就是血缘在链上的最小形态:顺着 parentCf 链往回走,追到起源;反过来查引用,追到下游。

第二个是审核判定。审核员对一条结构化消息签名——用的是 EIP-712,以太坊通行的结构化签名标准,签的是字段本身而不是一段自由文本,所以每个字段都被签名锁定。消息里有八个字段:

审核员必须是链上已授权的身份,验签对普通钱包和合约钱包都支持——后者走 ERC-1271 标准接口。签名进链之后,“这条数据被谁认可过、评了几级”就不再是平台数据库里的一行记录,而是谁都能验的密码学事实。

一个值得说清的细节:协议里提交 CF 是 permissionless 的——无需许可,任何人都能调——链本身不在提交时验证”调用者控制这个 DID”。所以严格地说,链上锚定证明的是”这份内容 × 这个身份 × 这个时间”的绑定被公开记录了,且此后无人能改;“确实是本人所为”的背书来自审核签名,以及一个朴素的事实——真正的贡献者手里有原始内容,冒名者没有。协议不多承诺,但这已经足够支撑验证: 给你一份元数据文档和一个 cfId,三步即可完成验证:

  1. 算文档的 hash;
  2. 按公式拼出 cfId;
  3. 到链上查这个 id 存在、绑的是谁的 DID 和哪个任务。

验证所需要的,只有这份文档和公开的链上记录,整个过程完全不依赖平台。

上半部分:cfId 由 metadataHash、contributorDid、taskId 和可选的 parentCf 一起做 keccak256 得到,公式刻意不含 metadataUri,所以位置可修而 id 不变。下半部分:血缘是一条 parentCf 链,SAMPLE 原始样本被 LABEL 标注引用,LABEL 被 AMENDS 修正引用,AMENDS 被 VALIDATION 审核背书引用,每条各有自己的 cfId。
图 3 · cfId 的构成与 parentCf 血缘链

所有权长在数据集上

这里有个容易混的层次,值得单独说清:CF 和 Dataset 是两层,所有权在 dataset 层面,不在单条 CF 层面。

一条 CF 的作用有两件:

单独一条 CF 不是资产:它不被持有,不被转让,也没人会买一条标注。

Dataset 才是资产的单位:把一批 CF 聚合成一个可持有、可流转、可定价、可退出的整体。这个分层是协议设计里最关键的一步——把所有权放在单条数据上,颗粒太细,交易不成立;放在数据集上,“我持有这个数据集 3% 的份额”是可计量、可转让的。而追溯的颗粒度保持在单条,两层各干各的事。

协议里,一个数据集版本由 (assemblerDid, manifestId, versionNumber) 三元组唯一确定,链上存三样东西:成员表的 Merkle root、总份额 totalShares、指向元数据的 URI。

组装是这样发生的:组装者——就是 Dataset 三元组里那个 assemblerDid——选定一批 CF,给每条一个权重,权重之和固定为 totalShares。全部成员和权重的列表发布在链下的元数据里,链上只存这张表的 Merkle root。于是开篇那个”混入 30 万条”的黑箱,变成一张公开的成员表:每一条是谁的、权重多少,都在表里;表的完整性由链上的 root 保证,谁也不能事后偷改。你的份额就是你那些条目的权重之和除以 totalShares——一道自己能重算的算术题。

组装不改变 CF 本身的任何东西。没被选进数据集的 CF 不会失效——指纹、归属、审核签名都还在链上,只是暂时没有份额挂在上面,将来照样可以被选进新的版本;被选进去的 CF 也不是被”消耗”了——它只是多了一个”被聚合进 X”的关联,源 cfId 永远可以独立验证,同一条 CF 还可以进别的数据集。组装本身也是 permissionless 的:任何注册了 DID 的用户都可以发布数据集版本,协议不把这个权力留给任何人。

这里要把两种”拥有”分开:组装者发布版本之后,就是这个数据集在协议里的管理者——合约里称它为 owner,后面讲的授权签发、撤销都由它执行;而份额持有人拿的是经济权益——分收益、可转让。管理权和收益权从组装那一刻起就是分开的:持有人不参与每一次授权的决策,但也不会被一个停摆的管理者锁死——组装是 permissionless 的,同一批 CF 任何人都可以重新组装成新的数据集版本。

验证同样是机械的:拿元数据里的权重表重建 Merkle 树,和链上 root 比对;任何持有人拿自己的叶子和证明去调合约领份额,领得到就说明份额属实。

链下公开的权重表每行是 cfId、贡献者和权重,权重之和是 totalShares,这里是 10;每行哈希成叶,四个叶子两两哈希成 H12 和 H34,再合成 root,链上只存 root 和 totalShares。你的叶子是 L1 和 L3,份额是 3 加 1 除以 10,等于百分之四十。图中高亮了 L1 到 root 的路径,L1 的证明只需两个兄弟哈希 L2 和 H34。验证方式是拿权重表重建整棵树与链上 root 比对,或拿自己的叶子和证明直接向合约领份额。
图 4 · 权重表 → Merkle 树 → 链上 root,份额是一道可重算的算术

可拥有:让所有权可以行使

份额铸成 ERC-1155 代币——以太坊的多资产代币标准,同一份合约里每个数据集版本各是一种 token。前面说的四件事在这里逐一落地。

可计量,上一节已经讲了:份额从公开权重表算出,任何人可重算。

可流转:份额可以自由点对点转让,链上随时可查”现在归谁”。转让触发一个结算钩子,收益按转让前的持仓结清给转出方,转入方从新持仓开始累计——已经分给你的钱不会因为你把份额卖了而被追走。

可定价:使用数据要付费,付费换到的是访问授权。协议要求的是“能定价”这件事成立;至于定价高低、卖给谁,它不做规定——那属于具体实现和市场,不属于协议。它托底的是授权这个事实链上可查、可撤销。

可退出:收益进来时,合约执行 distribute(datasetId, token, amount),按当时的持仓快照把钱记到每个持有人的待领账上。这里有两条硬规则:

  1. 分母固定为 totalShares,不是”已被领取的份额数”——晚来领份额的人不吃亏,早领的人也占不到便宜。
  2. 收益归谁,看 distribute 那一刻份额在谁手里;之后再转让,已经记到你账上的钱不会跟着份额转给买方。这条规则是防纠纷的:份额开放转让之后,“这笔钱算谁的”必须有唯一答案。领取时,钱付给 DID 当前的 owner 地址——记账跟着身份走,钱包丢了换一个,待领的收益还在。

平台费在 distribute 时按固定比例切出,单独提取。费率是一个公开参数,可以为零;收取的每一笔在链上都是可见的流出——对账时它不是一个模糊的”运营成本”,是一条能逐笔核对的记录。

份额生命周期时间轴——组装、领取份额、distribute、转让份额、领取收益——下方是一份示例账本:你领取 10 份中的 4 份;一次 1,000 的分配给你入账 400,因为分母固定为 totalShares,晚领不吃亏早领不占便宜;你转出 2 份,400 仍归你,因为转让前收益先结清给转出方;之后你领取收益,400 付到 DID 当前 owner 地址,换了钱包也一样。
图 5 · 份额生命周期:卖掉份额,已入账的收益还是你的

可访问:谁能看到明文

前面所有机制处理的都是”账本”;数据的访问是另一回事。原始数据不公开存放,谁能取到,由授权决定。至于用访问控制挡住还是加密锁住,是实现的选择,协议不规定手段,只规定放行的条件。

授权分两层:

因此,“是否有效、是否已撤销”是任何人可查、赖不掉的链上事实;而”授权的具体条款”保持在链下的灵活和私密。两层各取所长。

把数据放给请求方之前,验证方必须全部通过五道检查:

  1. 请求方证明自己控制凭证里的那个 DID;
  2. 凭证签名有效,且签发者必须是这个数据集在链上的 owner DID——否则任何人都能自签一份”授权”;
  3. 凭证与授权方批准时留存的摘要一致;
  4. 请求方和数据集与链上锚点匹配;
  5. 锚点状态是 ACTIVE 且未到期。

五道检查全部通过才放行,锚点有效只是必要条件之一。

第二道检查里的 owner 是单数——就是前面说过的管理者 assemblerDid:授权由它签发和撤销;份额持有人的收益权不受影响,每一次授权带来的收入照样按份额分。

协议也支持撤销授权,其语义是停止新的访问。授权方随时可以撤销授权,链上状态切换为 REVOKED,立刻生效,之后的访问请求全部被拒。但已经到了别人手里的数据,协议是没有办法追回的——我们目前是通过水印溯源和许可条款来约束二次分发。

四条泳道:授权方 owner 在链下签发 VC 并把它锚定到链上,锚点状态为 ACTIVE,VC 本身交给被授权方;请求方带着 VC 和 DID 认证找验证方,验证方跑五步检查——请求方确实控制 VC 里的 DID、VC 签名有效且签发者是数据集 owner DID、VC 与批准时留存的摘要一致、请求方和数据集与锚点匹配、锚点 ACTIVE 且未到期——并向链上查状态,五步全过才放行数据。授权方随时可以撤销,链上状态切换为 REVOKED,此后的请求在第五步被拒。
图 6 · 授权与撤销:链下 VC + 链上锚点,五步全过才放行

数据存储

数据存储非常重要,因为它是上面三件事共同的地基。整个存储体系是一个混合存储架构,一条数据的信息分放在三个地方:

链上的记录指向元数据,元数据里再写着数据本体的 hash 和地址。任何人顺着这条链就能够取回内容,然后按照公式重算 hash,跟链上的记录对比,就能验证数据没被改过。当然,能随意取回的只到元数据这一层;最后一步——取数据本体——要经过前面所说的授权通道,而不是随意获取的。

在这个架构上,协议只管两条硬规则:

  1. 内容寻址:每个地址都配一个 hash;取回内容必须重算 hash,对不上必须拒绝。存储方是谁不重要——云存储也好,去中心化网络也好,内容对不对可以自证。对地址本身的要求也只有两条:一是任何人都能远程取回——不是只有存它的那台机器能读,所以本地路径不算数;二是内容不可变——同一地址永远返回同一内容。
  2. 位置可修,身份不变:地址失效可以更新,因为 id 和地址是解耦的。存储迁移、加副本、换供应商,都不触动链上的任何事实。

除这两条之外——存在哪、几份副本、保留多久、谁付钱——协议一概不规定,这些是实现方的工程和经济问题,不同的实现可以给出不同的答案。

尾声

你终止了和那家 AI 公司的合同,这一次,把数据交给了跑在 XnY Protocol 上的平台。

提交数据的那一刻,你的每一条数据都有了自己的指纹,并绑定着你的DID,记在那本不属于任何一方的账本上。审核员的判定和签名也进了账本——这条数据是你的、被谁认可过、评了几级,从此不需要你自己保存证据。

后来这些数据被组装进一个数据集,其中还有别人的 30 万条数据。但这次,混合是一张公开的成员表:哪些条目是你的、各占多少权重,你随时可以打开来对;你的份额是你那些条目的权重之和除以 totalShares,一道自己能重算的算术。

数据集卖出去了。每一次授权都留下链上锚点——授给谁的摘要、有效期、撤没撤,谁都能查。再看到”另一家公司也有这批数据”的报道,你一查便知是正常授权还是泄漏:有锚点,去对账;没锚点,拿着指纹和血缘去追责。开篇那个你无法区分的问题,现在有了判据。

每次收入进来,合约按那一刻的持仓把钱记到你的待领账上,数字你自己能读;想提就提,打到你身份对应的地址。分成不再是合同 PDF 里的一句话,是代码执行的确定性逻辑。

哪天这家平台自己倒了呢?你的指纹、份额、待领的收益都不在它的数据库里,在链上,换一家运营方接着跑,它们还在——每一个承诺的成立,都不依赖任何一家公司还活着。

当然,协议有自己清楚的边界。数据本身的质量,协议不背书——那由审核员的签名和市场来回答;数据集能不能卖出好价钱,也不是协议的事。真正还在路上的是明文的控制权:今天数据本体托管在运营方的存储里,而让数据所有者自己掌握密钥、运营方也碰不到明文,是协议正在推进的下一步。


本文描述 XnY Protocol v2 的协议定义,链上数据与实现进展见 explorer.xny.ai,文档见 docs.xny.ai。

相关文章