CKB 上公共状态更新的实现方案

背景

目前大多数智能合约公链的状态存储都是基于账户的。其优点是编程模型与传统编程模型一致,交易发起侧设计简单等。但缺点也非常明显,基于账户的模型难以区分每个用户独立的状态空间,导致状态租用的公地悲剧问题。Nervos CKB 提出了类似 UTXO 的 Cell 模型,用来保存用户独立的状态空间,并实现链上验证、链下计算的分离,可以较好地解决区块链状态爆炸、空间租用、并行化、长期激励等一系列问题。

但是 Cell Model 的编程模式相对于传统的账户模型有着较大区别,它将计算搬到链外,在链上仅实现确定性状态变更的验证。直观上对智能合约的施展空间做了限制,例如在 CKB 上直接实现一个投票合约就比较困难——你发送一条交易的时候并不知道有没有其他人同时投票,也就无法锁定一个现有的状态(Cell)去更新它。

思路

CKB 强调的功能并不是“全球计算机”,而是共识知识平台(Common Knowledge Base)。公共状态更新(下面以投票合约为例,它需要实现任意用户对一个单一记票变量更新)本质上需要实现统计过程,这是一个计算行为,而不是一个验证行为。所以正确解决这个问题的思路应该是如何把统计运算实现在链外,并在链上验证统计结果。

但是链外收集选票并统计然后提交到链上验证这一流程存在着几个问题,首先,如何保证每个投票人都被记入了投票。其次,如何保证投票人的投票没有被篡改。最后,如何向主链证明。

Open TX

进一步介绍实现方案之前,我们需要引入 Cell 模型中的一个交易类型。Open TX 是一种不完备的交易,它无法通过 CKB-VM 的交易验证,因此无法被矿工打包。但是 Open TX 包含了交易发起人指定的 inputs、outputs 以及发起人通过 lock script 或者 type script 指定的交易生成规则。任何人都可以在这个规则的约束下对 Open TX 补充 inputs、outputs 来使它成为一个完整的交易,从而通过 CKB-VM 的验证。

Open TX 使得交易发起者有能力发起一个自己部分控制的交易,TA 可以确认交易的最终结果是按照自己约束的方式实现。Open TX 有很多应用,例如 Nervos CKB 应用层优势1:自由的手续费模型

实现一个投票合约

接下来我们利用 Open TX 来实现 CKB 上的投票合约。

STEP1:用户发起 Open TX 对候选人投票,该交易包含用户的押金或筹码作为 inputs,并且该交易指定 output 的 type script(但不指定 output 的其他信息)

STEP2:上述交易将大量积累在矿工的交易池,候选人或其他用户甚至矿工自己对这些投票进行统计,生成一个指定 type 的 output,并添加足够的手续费,使之成为一个标准交易进入区块

STEP3:考虑到投票人提交大量的投票,可能无法将所有的 Open TX 合成一个,因此可以分多次统计

该方案实际上利用某个非特定中间人收集所有的投票信息,在合约的约束下进行统计,然后把结果提交。考虑到不同矿工对 Open TX 合并的实现程度不同,可以由候选人搭建中心化服务器收集投票人的交易签名,并由 TA 对这些交易进行合并统计再发送到 CKB。这样矿工处理的就是标准的交易,可以直接打包。

小结

本文只是解决公共变量/状态更新的大致思路,但带来了编程思路上的启发。在 CKB,也就是 Nervos Layer1 上,我们应该关注状态如何被验证,任何关于状态如何得出这样的问题都应该尽量交给 Layer2 实现。前文给出的中心化统计方案就是 Layer2 的一种,它虽然通过中心方实现计算,但是 Layer1 上的合约脚本确保了统计的完整性和正确性。

PS:本文得到了 @rink1969 @doitian 大力帮助

5 Likes

Open TX 有文档吗,能否给个传送门?

另外,你的完整性指的是什么?在我看来,这个方案只确保了不合法的投票不会被统计,但是无法保证合法的投票一定会被统计。假设 Open TX 的模型可以实现上述所有功能(尽管我对它是如何运作的非常好奇),中心化的服务器在投票这样的场景下肯定是信不过的,因为服务器提供者有足够的动机去可以忽视某些投票。

可以保证合法的票一定会被统计的,两种方法。方法一,假设矿池足够去中心化,那么统计更多票的矿池可以获得更多手续费,当然矿池也没有非要100%统计的动力,就是说它并没有负向激励。方法二更靠谱一些,就是候选人自己去统计,他们没有理由不对自己的票做 100% 统计。

文档还没有,但实现方法可以简单透露一下。就是在 cell 的锁定脚本合约中增加签名覆盖字段的信息参数,然后解锁的时候用这个参数指定解锁签名对哪些信息做限制。而受限制的信息可以是未来被包含进来的 output。例如我可以限制一个 TX 包含且仅包含 4 个 type hash = 0x1234 的 output,但并不限制这4 个 output 的其他信息。

对,每个候选人分别统计自己的票是没有问题的,我以为你的意思是候选人搭建服务器统计所有票数。。。