在上一篇文章《1、如何保证 DAS 帐户的惟一性》中的最后,咱们提到了仍然存在的 Cell 竞争问题。具体问题以下:服务器
假定链上已经注册有 a.bit、b.bit、z.bit 三个帐户,如今有两个用户分别想要注册 c.bit,d.bit,且注册时间很靠近。按照规则,注册发生时,他们使用的注册服务会分别构造交易让用户签名,交易的内容为将要注册的帐户插入到 b.bit 以后。网络
问题在于,两笔交易都会试图将 AccountCell(b.bit) 消费掉,而一个 Live Cell 只能被消费一次,那么就会致使必然其中一笔交易会失败。假定注册 c.bit 的交易成功了,而注册 d.bit 的交易失败了。注册 d.bit 的用户不得不被他所使用的注册服务要求从新签名交易。这是因为注册 d.bit 时,本来须要将 AccountCell(b.bit) 消费掉,而如今须要改成消费 AccountCell(c.bit),交易结构内容发生了变化,必须从新签名。架构
这将致使很是糟糕的用户体验。事实上,当注册的用户数量变多时,大部分用户不得不一次又一次的签名交易,直到他能注册成功。 <br/>框架
澄清问题
要解决问题,首要的是澄清问题
上面的问题之因此是个问题,根本之处在于什么呢?是在于引用了相同的 Cell 致使的交易失败吗?若是是这样,咱们就会将思考聚焦在如何避免交易引用相同的 Cell。进一步思考下去,咱们可能就要推翻有序链表这个设计了。函数
那若是咱们把问题归结为,交易失败并非问题,用户须要不断签名交易才是问题,会怎么样呢?那咱们就会将思考聚焦在如何避免用户不断地签名。而这彷佛并不困难。url
Keeper
咱们引入 Keeper 这个机制来解决这个问题。.net
Keeper 是: 1) 一个有任何人均可以无需许可运行的链下程序。 2) Keeper 是 dApp 的一部分,不一样的 Keeper 服务于不一样的 dApp。 3) 它会根据 CKB 链上的状态,发出交易,修改 CKB 的链上状态。
引入 Keeper 以后,多个用户同时注册 DAS 帐户的技术过程就变成了:设计
- 用户发起一笔交易,释放一个包含注册信息的指令Cell,好比「我要注册 c.bit」,「我要注册 d.bit」。同时,这些 Cell 的 lock 是 always_success,任何人均可以消费它们。这笔交易并不会将用户要注册的帐户插入到有序链表中。
- Keeper 经过监听链上状态,会发出一笔交易。将这两个指令Cell,做为 input,并在 output 中建立对应的 AccountCell(c.bit),AccountCell(d.bit),一块儿将他们插入到有序链表中合适的位置。
能够看到,经过这种将多个帐户注册请求打包一块儿插入链表的方式,能够有效地避免用户屡次签名的问题。那咱们对 Keeper 的理解,应仅仅是将注册请求打包处理来避免 Cell 竞争吗?其实否则。3d
因为 Keeper 是任何人均可以无需许可来运行(他理应被设计为如此)的链下程序,那么当多我的运行 Keeper 时,Keeper 之间又会出现 Cell 竞争问题:每一个 Keeper 都在作相同的工做,将用户的指令Cell 变成对应的 AccountCell 插入到链表中合适的位置,它们又要去竞争 Cell 了。code
这彷佛让人沮丧,Cell 竞争无处不在。但仔细思考,这压根就再也不是问题了。Keeper 是程序啊,它们发出的交易失败了 ,有必要的话,它们能够自动签名新的交易。交易失败不会让它们烦躁,也不会让它们有任何损失。而这,正好解决了咱们想要解决的问题:如何避免用户不断的签名。
至此,咱们便完全解决了上一篇文章遗留的,由 Cell 竞争所带来的问题。
对 Keeper 的进一步思考:
- Keeper 更像是一个可执行函数集合,用户的指令Cell 就是对其中某个函数的调用信息。Keeper + 链上验证脚本,构成了完整的以太坊思惟框架下的 dApp:与 dApp 交互, 就是发送一笔交易,调用 dApp 暴露出来的函数接口,传入对应的参数。
- Keeper 模块是 CKB 上 dApp 不可或缺的模块 ——「链下计算」模块。
- 运行 Keeper 毕竟须要服务器成本,那么谁又会来运行 Keeper 呢?若是没有人运行 Keeper 了,那 dApp 不就没法工做了吗?
- 做为 dApp 开发者有充分的理由和动力去保障 dApp 的正常工做,因此他们会去运行,但也不是绝对的。甚至若是只有 dApp 开发者运行,那开发者的链下服务稳定性,会直接影响 dApp 的可用性。
- 因此,咱们更建议从经济激励的角度去思考如何鼓励你们来运行 Keeper。这也正是 DAS 的作法:任何将用户的指令Cell 转变为 AccountCell,从而帮用户完成注册的 Keeper,均可以分享到必定比例的注册费用。事实上,在 DAS 中,大量的逻辑处理都是以这样的方式去激励 Keeper 完成的。
- 再结合 Keeper 是可执行函数集合这个理解,少许的(也可能为 0) Keeper 奖励 + CKB网络矿工费,二者合并到一块儿,就是用户与合约交互所须要付出的整体成本。更进一步,Keeper 奖励能够理解为「链下计算」相关的费用,CKB 网络矿工费可理解为「链上验证」相关的费用。 对于以太坊而言,验证和计算都是在链上进行,但咱们仍能够从逻辑上将其费用拆分红计算和验证两部分。因此从细节上看,CKB 和 ETH 差异很大,但在某个抽象层级来看,他们又具有一致性。
DAS 创始人 TimYang (杨敏)在 Nervos CKB 上开发了 DAS 去中心化帐户服务。借着此次的产品开发,TimYang 经过《从 DAS 开始了解 CKB 应用开发》系列文章,向你们阐述他的设计思路和开发历程,让你们了解如何在世界上第一个基于 UTXO 架构的公链 CKB 上构建产品级应用。
推荐阅读:从 DAS 开始了解 CKB 应用开发(一)—— 如何保证 DAS 帐户的惟一性
如若您有更多关于 DAS 产品的使用心得,以及在 CKB 上开发的看法,欢迎前往 Nervos Talk 论坛讨论: