术语表
凭证、折叠(fold)、跳过、保证金、定序器、强制路径。其中有几个在这里的含义比在别处更窄,还有几个命名的事件,是多数链根本没有词可称呼的。
这个协议所用的词汇,以及它使用这些词的确切含义。其中有几个词 在这里的意思比在别处更窄,而其中两个 — 跳过 和 丢弃 — 命名的事件是多数链根本没有词可称呼的,因为它们没有 对应的东西。
凭证#
Zycord 中唯一的交易类型。一份凭证携带着它读过的状态和它写过的状态,外加把两者连接起来的程序、为它授权的各个签名、一笔保证金、一个 TTL,以及在两个手续费市场中各自的一个出价。因为它自带自己的输入和输出,所以核查它是否有效根本不需要任何状态。
折叠(fold)#
推进账本前进的那个确定性循环。它按一个规范顺序遍历一个区块的各份凭证 — 先是 fill,然后是每一份普通凭证,然后是强制凭证 — 并对每一份核查它所声明的读取是否仍然成立:成立就提交那些写入,不成立就跳过。折叠在一个热的键值工作集上执行比较、相加和写入 — 不执行代码,不验证签名,不重新执行,也没有椭圆曲线运算。它是这个系统中唯一不能并行化的阶段。
跳过#
一份凭证在以下情形中会发生什么:它所声明的读取不再成立,它的增量会超出 256 位范围,或者它会在一个已花费地址之下写入。不写入任何东西,从其保证金中烧掉一笔 1,000,000 drops(0.01 ZCD)的固定跳过费,这笔钱不付给任何人,保证金的其余部分退回,而区块保持有效。谁指定了保证金,谁就付费:普通凭证的作者,因为读取是他选的;或者 fill 的定序器。用户从不为 fill 的跳过付费。跳过是语义,不是失败:打包与应用是两个不同的事件,因此区块生产者绝不可能因为打包了一份过时的凭证而产出一个无效区块。
丢弃#
一种不收费的非事件。一份保证金无法被预留的凭证 — 保证金存储单元已被花费,或其持有的金额少于该凭证所预留的金额 — 会被丢弃:它被携带在区块中,不收费,不标记为已见,可以针对一笔新的保证金自由重新提交。因此诚实的用户不会因为自己那个保证金存储单元上的竞争而损失任何东西。
保证金#
为一份凭证负责的那个存储单元:某个用户地址的一个原生余额存储单元、从中预留的金额,以及剩余部分退回的找零槽位。没有一份凭证可以没有保证金,而且保证金存储单元总是带有签名。跳过不能是免费的,否则内存池会被淹没;正是保证金让每一次冲突都有一个归属者。fill 的保证金出自其定序器的持久余额,这就是为什么 fill 被跳过时付费的是定序器而不是用户;而强制凭证则改由其开放意图的付款支付。白皮书 v1.0 中的承保人和有保险的凭证已经不复存在;保证金就是取代它们的东西。
存储单元#
一个槽位上的值 — 一个以大端序存放在 32 字节中的无符号 256 位整数。零就是不存在:一个从未被写过的槽位和一个被写成零的槽位是同一个槽位。这是一项共识要求,不是图省事:它让状态根成为状态的函数,而不是产生出该状态的那段历史的函数。
一次性地址(0x01)#
一个其签名权限会被它的第一次借记永久烧毁的地址。向一个新派生出来的一次性地址付款是零争用的快速路径,而每笔付款都派生一个全新的地址,正是让一笔付款与下一笔无法被关联起来的原因。代价是“花掉其中一部分”不是一个一次性地址能做的事 — 请看钱包规则 1。
持久地址(0x02)#
一个可重复使用的地址。它永远不会进入已花费注册表,因此它完全没有被恶意烧毁的可乘之机。商户、捐赠地址、定序器的保证金和挖矿收益支付都使用这种地址;zycordd --payout 会拒绝其他任何类型。
已花费地址注册表#
由签名权限已被烧毁的一次性地址构成的、永久性的共识集合。已花费地址之下的存储单元值可以在回滚视界之后被剪除,但注册表条目永远不会 — 正是它阻止了地址被复活。每个地址约 33 字节,永远保留:这个协议诚实承认的尚未解决的问题,在结构上与每一种作废符集合设计共有。
有效 vs. 可应用#
两个被传统链混为一谈的谓词。有效是无状态的、可并行的,任何人仅凭凭证的字节就能核查。可应用是有状态的、串行的,只由在账本中的位置来裁定。两份有效的凭证可能为同一个槽位声明同一个输入值;其中至多有一份能是可应用的。
带守卫增量#
一种访问纪律:凭证对一个槽位断言一个谓词 — balance ≥ 10 — 而不把该值读入计算,并写入一个带符号的增量。对同一个槽位的任意多次带守卫的借记和贷记都是可交换的,所以只有在真正透支时才会发生跳过,而不会仅仅因为余额变了就跳过。这一条纪律就覆盖了转账、有供给上限的铸造、授权额度和金库份额,而且它从不受定序器的限制:一个定序代币仍然接受来自任何人的每一笔转账。
纯增量#
一个不带守卫的带符号增量。它永远不会冲突,也永远不会跳过。打赏、计数器、累加器、奖励统计。
精确读取#
SLOAD 式的纪律:读取会把槽位的值送入计算,并把凭证钉死在这个值上。可以承载任意逻辑,会在热门槽位上发生冲突,是定序器的用武之地。
定序器#
合约选择用来串行化其精确读取流量的一项链下服务。每个合约的记录都持有一把定序器密钥:当它非零时,对该合约存储单元的精确读取、相等守卫或设置都需要该密钥的签名;当它为零时,合约是开放的,只受其代码保护。定序器执行用户的意图,并把结果作为 fill 发布。它在活性上受信任,在安全性上从不受信任:它不能改变一个意图做什么,只能改变何时做,而一份建立在谎言之上的 fill 会被跳过,费用由定序器承担。如果它停止服务,强制路径依然存在。
意图(intent)#
用户为调用一个定序合约而签署的、代替凭证的东西:目标与 calldata、一份并行预算、一个 nonce、一个至多 8 个区块的窗口、定序器的持久地址、对结果的界限、应付给每个定序器的款项、为它出资的一次性付款地址,以及找零输出。界限是对该调用所写入的某个存储单元的谓词 — final-at-least、final-at-most、delta-at-least 或 delta-at-most — 且至少有一个必须指定该调用所写入的存储单元。意图就是用户的全部授权,其付款只有在 fill 被应用时才会结算。
Fill#
定序器为一个意图发布的凭证。它的程序就是该意图,它的保证金出自定序器自己的持久余额,它的 id 是该意图的哈希,因此同一意图的两份 fill 共用一个 id,只有一份能被收费。fill 在折叠顺序中排在最前,每一份在它所在的每一条流水线都就绪时立即进入。
回执#
定序器对一个意图作出的签名答复,在几毫秒内返回,远早于区块的出现:意图 id、流水线 seq 以及结果。它是一种预确认 — 是定序器的承诺,不是链的承诺,只有在 fill 被应用时才是最终的。因为回执是签名的,所以同一把密钥签出的两份回执,如果把同一个 seq 给了不同的意图,或者给同一个意图不同的结果,就构成任何人都能从字节核查的证明。共识不惩罚这种行为;用户会离开。
流水线#
链为每一对定序器密钥与合约记录最后一个已应用的 seq。一份 fill 只有在该计数器恰好比它的 seq 小一时才能进入,而计数器只有在 fill 被应用时才前进,因此定序器的各份 fill 按它签署的顺序提交,无论生产者以什么顺序收到它们。一份被跳过的 fill 会挡住排在它后面构建的 fill,直到定序器从同一个序号重新构建。
fence 计数器#
每个合约记录中的一个计数器。一份 fill 声明它所基于的各合约的 fence 计数器,只要其中一个变动了,它就无法进入。当一份落地的强制凭证设置了该合约的某个存储单元时,以及当该合约的定序器存储单元被写入时,它会前进 — 因此强制路径和定序器的更换,会使建立在它们所改变的状态之上的每一份 fill 失效,且不向任何人收费。读取或增量不会推进它,失败的强制凭证也不会。定序器重新构建,只损失延迟。
联合定序#
一次跨越绑定到不同定序器的多个合约的调用,会作为一份 fill 落地,它携带其精确路径所触及的每一个定序器的签名,至多 16 个,每个定序器在自己的流水线中各有一个 seq,并各自获得意图为其指定的款项。它们如何协调是链下的事,按设计不受约束;链看到的是一份凭证,按构造即是原子的。
定序器目录#
定序器通告其服务的地方:一份来自其持久地址的目录凭证,把它的密钥绑定到一个 1 到 256 字节的可打印 ASCII 字符串上,通常是一个 URL。除非续期,该条目在通告凭证的 TTL 之后 259,200 个区块(约 90 天)失效,而一次撤回会立即将其移除。共识存储这个字符串,但从不解释它 — 它是发现,而不是授权。节点在 /directory 上提供它。
强制路径#
不需要定序器的慢路径。用户签署一个开放意图并把它转发到网络;区块生产者以区块末尾的状态执行它所选择的开放意图,并把结果作为强制凭证追加上去,成为区块的最后几份凭证。打包即应用:没有队列、租约、配额或截止期限。一个区块至多携带 16 份强制凭证,每份至多有 4,000 个派生单位的并行预算(200,000 机器 gas),这就是为什么合约提供的每一个退出操作都必须符合这个预算。一份调用回滚的强制凭证照样落地,结果为 FORCED_FAILED:它的付款地址付费,找零退回给用户,此外不写入任何东西。
开放意图#
一个未指定定序器、也没有联合定序器的意图,由用户自己的一次性付款地址出资。它在内存池中作为意图而不是凭证传播,其付款支付强制凭证的费用:基础费部分被烧掉,其余归生产者。zcd wallet open-intent 会签署一个开放意图,而当定序器不为原意图服务时,zcd wallet intent --fallback 也会签署一个。
cEVM#
唯一的虚拟机:一种为凭证改造的以太坊虚拟机方言。存储是声明的而不是在运行时发现的,新增了用于守卫、增量和设置合约定序器的操作码,在这里没有对应物的操作码被移除,而 NUMBER 和 TIMESTAMP 从纪元信标作答。自 Era 1 起启用,并在已知地址上预部署了一个增量优先的标准库。Solidity 及其工具链可以沿用。
纪元信标#
协议每个纪元写入一次的保留存储单元:纪元编号、开启该纪元的区块头的高度、一个熵字,以及自 Era 1 起该区块头的时间。程序不得直接读取时间戳或高度这类环境值 — 那会让执行成为所声明读取之外的某种东西的函数 — 所以它们像读取任何其他槽位一样读取信标,最好带上一个范围守卫。它的值在整个纪元内保持不变。熵字是工作量证明的输出,不适合高价值的抽奖。
纪元#
2,880 个区块 — 在 30 秒出块时约为一天;从切换到权益证明起为 17,280 个 5 秒的时隙,仍是一天。补贴据以递减、串行容量目标据以移动、信标据以刷新的单位。
TTL#
一份凭证必须在其之前被提交才能有效的高度。由共识限定为 240 个区块(约两小时),从切换到权益证明起为 1,440 个区块,正是这一点让已见集合可以被剪除。打包一份已见过或已过期的凭证会让区块无效 — 因此一个签名至多只能被计费一次,而且只能在其签署者通过签名所接受的位置上计费。
串行 gas 与并行 gas#
手续费拆成两个市场:一个用于串行的状态变更,它是稀缺的;另一个用于并行的验证,它并不稀缺。因此一次签名核查不会与一次存储写入在同一场拍卖中竞价,正是这一点让繁重的密码学在设计上就是便宜的。在两个市场中,基础费都被烧掉,优先费支付给生产者,这只发生在被应用的凭证上,且仅限于它们;被跳过的凭证,其费用全额烧掉。
时代#
协议的一个阶段,由编译进公开发行版的高度把关,在 Era 2 中还由在高度界限内于链上测得的权益把关 — 从不由日历日期或投票决定。Era 0,自区块 0 起上线:挖矿、原生资产、两个手续费市场、补贴划分以及国库,持续累积且处于封存状态。Era 1 在 mainnet 的高度 80,640(约 2026年11月4日)启用,在公共 testnet 上自高度 2,880 起启用:cEVM、定序器、意图与 fill、定序器目录以及强制路径。Era 2,权益证明:质押在纪元 182(约 2027年4月7日)开启;当活跃权益在 30 个纪元内持有供应量的 10% 时,权益爬坡期开始,最迟在纪元 273;权益爬坡期完成时,随之而来的是向单靠权益的切换。Era S 将会加入机密支付,只在独立审计之后,并且不属于当前规范。Era 2 和 Era S 各自以硬分叉方式作为其自己的发行版交付。质押不属于 Era 1。
权益证明#
Era 2 的共识:在其中,生产下一个区块的权利按权益抽取,而不是以哈希换取,出块间隔从 30 秒降至 5 秒。其余一切保持不变:每个节点都根据字节核查每一份凭证,折叠和两个手续费市场都不变,而区块中的一份无效凭证仍会让该区块无效。矿工花在哈希上的计算,生产者花在验证上。它经由一段权益爬坡期和一次切换进入,在切换之前,区块都是挖出来的。规定于白皮书 §11。
权益(stake)#
质押到区块生产中的原生币。BOND 把余额从一个持久地址转入一个与该地址绑定的权益存储单元,该地址的密钥就是签署区块的密钥;UNBOND 在一段长于回滚视界的退出延迟之后将其退回。一份权益在质押一个纪元之后才变为活跃,因此权益无法被成串地创建和废弃。最低质押额为 1,000 ZCD;一把密钥,一份权益。质押随 Era 2 在纪元 182 开启。
权益池与委托#
权益池是接受委托的权益。DELEGATE 把一份质押指向一个权益池的密钥,其最低额小于用于生产的质押,而余额从不离开委托者,委托者可以在同样的退出延迟下改投或解除质押。权益池在抽取中的权重是它自己的质押加上委托给它的数额,而折叠每个纪元一次,在权益池(按其声明的抽成比例)与其委托者(按权益比例)之间拆分其奖励。委托者永远不会被罚没:如果一个权益池双重签名,只有它自己的质押会被烧掉。这不是矿池,矿池在链下,在共识之外。
时隙(slot)#
在权益证明下,一个可以生产一个区块的 5 秒间隔,由为它抽中的生产者生产,抽中的概率与权益成正比,所用种子在上一个纪元固定。一个纪元为 17,280 个时隙。没有区块的时隙保持为空,不支付任何东西;在各条有效链中,占据最多时隙的那条胜出。在其他场合,slot 指的是一个存储位置,即槽位 (address, word),其值是一个存储单元。
权益爬坡期(ramp)#
Era 2 的入口:90 个纪元,其间每个区块仍然是挖出来的,同时还带有为其高度抽中的权益的签名。质押者获得生产者份额的 k/180,其中 k 从 1 开始,每有一个纪元通过闸门就加一:闸门即该纪元至少 90% 的区块带有签名,且活跃权益至少为供应量的 10%。一个不带该签名而被挖出的区块是有效的,且不付给任何人:其生产者份额和其优先费被烧掉。当活跃权益在 30 个纪元内持有供应量的 10% 时,权益爬坡期开始,最迟在纪元 273。这不是 30 天的发行爬坡期;见发行。
切换(switch)#
工作量证明结束的那个区块:在第 90 个通过权益爬坡期闸门的纪元之后的那个纪元的第一个区块;如果闸门从不暂停,最迟在纪元 363,约 2027年10月5日。从它开始,区块以 5 秒的时隙到来,一个纪元为 17,280 个时隙,每个区块支付该纪元速率的六分之一;每区块上限除以六,每一个度量时间的区块计数乘以六,因此每天的容量和时长保持不变。此后一个区块在 120 个区块的深度上即为最终,即 10 分钟,而工作量证明要求的是 20 个。
双重签名(equivocation)#
同一把密钥为同一个时隙签署的两个区块头:在权益证明下共识中唯一受惩罚的过错。与一份无效凭证一样,它是任何人都能从字节核查的单消息证明。一份举报凭证携带这两个区块头,而折叠烧掉签署者自己的质押,把它的密钥移出活跃集合,并向举报者支付一部分。生产者所做的任何事都触及不到任何其他人的币:权益池的委托会退回给其委托者。
发行#
ZCD 只以区块补贴的形式存在,区块 0 不支付任何补贴。其速率从每个区块 21 ZCD 开始,并在每个纪元边界按精确的整数算术递减 — E(n) = max(tail, E(n−1) − floor(E(n−1) / 1054)) — 大约每两年减半,直到在纪元 4,376(约第 12 年)达到每个区块 0.33 ZCD 的永久尾部。最初的 86,400 个区块(30 天)是一段发行爬坡期:区块 h 支付区块 86,400 所支付速率的 h/86,400,而爬坡期扣留的部分,约 907,917 ZCD,永远不会补发。从切换到权益证明起,每个区块支付该纪元速率的六分之一,因此一天支付的数额相同。zcd emission --height N 会打印任意高度上的补贴。
补贴划分#
每一笔区块补贴,而从不包括手续费,自区块 0 起由共识按 94 / 3 / 3 划分:94% 在两小时的成熟期(240 个区块,在权益证明下为 1,440 个)之后付给该区块的生产者,3% 付给创始人的持久地址,直到纪元 1,095(三年),3% 付给国库,此后国库还会拿走创始人的那 3%。在权益证明爬坡期中,生产者的 94% 本身在矿工与被抽中的质押者之间划分。它是一条适用于每一个被挖出区块的规则,而不是在创世时的一次分配:没有预挖。
国库#
协议地址的原生余额。没有任何密钥哈希成它,没有任何凭证能从中扣款,创世也没有指定任何法定人数。它从区块 1 起获得每一笔区块补贴的 3% 入账,从纪元 1,095 起为 6%。协议中不存在任何动用途径:只能由日后的一次升级加入,其签署者由社区而不是由创始人选出,而发布承诺是:它不早于高度 259,200(约 2027年1月5日)到来。
管理提案#
一份供社区审议的提案,不是共识规则。它建议国库在最初三年里可以如何花费:五个席位,各有公开章程 — 首席开发者、审查开发者、矿工、社区、公众代表 — 其中 5 取 3 即可花费;而更换持有人、轮换密钥、动用储备或修改章程则需要 5 取 4,并在生效前公示 20,160 个区块。预算是国库流入的份额,从不是固定金额。在国库升级固定某个密钥集合之前,其中的任何内容都不具约束力。全文见配套文档。
RandomX#
工作量证明函数,为通用 CPU 做过优化,好让普通硬件保持竞争力;mainnet 和公共 testnet 运行的是 randomx-v2。它是一个共识参数,不是一项设置:一个无法计算某网络 pow_engine 的二进制文件会拒绝启动,而不是回退。
状态根#
对某一高度上全部状态的承诺。节点启动时会重新计算它,若与存下来的那个不符便拒绝运行;它同时兼作生产环境中节点之间的差分守卫:两个实现从同一段区块序列得出不同的根,说明其中之一有缺陷。
每个术语在何处被规范性地定义#
本页是一份阅读辅助。具有约束力的定义在 规范文件与黄金向量里;推理过程在 v2.0 版白皮书及其配套文档《启动、时代与参数》里,后者规定了 发行、各个时代以及每一个参数取值。实现自身的词汇章节 在 docs/ARCHITECTURE.md 里。