深刻理解Plasma(四)Plasma Cash

本文首发于深刻浅出区块链社区 原文连接:深刻理解Plasma(四)Plasma Cash原文已更新,请读者前往原文阅读git

这一系列文章将围绕以太坊的二层扩容框架 Plasma,介绍其基本运行原理,具体操做细节,安全性讨论以及将来研究方向等。本篇文章主要介绍在 Plasma 框架下的项目 Plasma Cash。github

上一篇文章中咱们已经理解了 Plasma 的最小实现 Plasma MVP 如何使用 UTXO 模型实现 Plasma 链下扩容的核心思想。但因为 Plasma MVP 自己过于简单,并不能用于实际的生产环境中。2018 年 3 月,在巴黎举行的以太坊开发者大会上,Vitalik 发布了 Plasma Cash 模型[1],能够视为对 Plasma MVP 的改进。Plasma Cash 与 Plasma MVP 的主要区别是每次存款操做都会产生一个惟一的 coin ID 对应转移到侧链上的资产,并使用一种称为稀疏梅克尔树(Sparse Merkle Tree)的数据结构存储交易历史。由此带来的好处是用户不须要关注子链上的每一个动态,只须要关注跟本身的 token 有关的动态。在下文中将介绍具体细节。安全

存款(Deposits)

Plasma Cash 中的每次存款操做都会对应产生一个 NFT(non-fungible token)[2]。NFT 能够简单理解为“不可互换的 token”,即每一个 token 都是独一无二的,由惟一的 ID 标记。以太坊官方为 NFT 提供了 ERC721 标准[3],在以前火爆到阻塞以太坊的 CryptoKitties 就是由 ERC721 合约实现的。数据结构

在 Plasma Cash 中,当用户向 Plasma 合约发送存款交易时,合约会生成一个与存款等值的 token,并给这个 token 分配一个惟一的 ID。若是一个用户分别执行两次存款操做,且每次存款都是 5 ETH,那么他将获得相等价值的两个彻底不一样的 token。和 Plasma MVP 同样,每次存款操做都会使得 Plasma 合约产生一个只包含这个存款交易的区块。框架

Plasma Cash 区块

Plasma Cash 中的每一个 token 都被分配惟一的 ID,所以能够按 ID 的顺序存储每一个 token 的交易历史。Plasma Cash 的区块按 token ID 的顺序给每一个 token 分配了一个插槽(slot),每一个插槽会记录这个 token 是否被交易的信息。例如在下图(来源[4])的区块中,包含 4 个 token,id 分别是 #1,#2,#3,#4。其中 #1,#2,#3 被标记为没有被花费,而 #4 由用户 A 发送给用户 B。less

<img src="https://raw.githubusercontent.com/gitferry/mastering-ethereum/master/Plasma-in-depth/images/pc-block.png" width="600" height="190" alt="Plasma Cash Block" />学习

从上面这个例子中咱们能够看到,每一个插槽记录了其所对应的 token 在当前区块中的交易状态,全部存储了某个 token 的交易状态的区块按时间顺序连在一块儿就构成了这个 token 的所有交易历史。每当一个 token 被分配了一个 id,以后的全部交易状态都会被保存在每一个区块相同的插槽中,也不会被其它 token 取代。所以,用户只须要关注每一个区块中存储属于本身的 token 的状态,彻底不用关心别的插槽存储的内容。区块链

交易与验证

因为 Plasma Cash 中的节点只追踪属于本身的 token 的交易历史,所以当有交易发生时,token 的发送者要向接收者提供关于这个 token 全部的交易历史(从存款交易开始)以便接收者验证。从下图(来源[4])的例子中能够看到 4 个区块中所记录的 4 个 token 的交易历史。spa

<img src="https://raw.githubusercontent.com/gitferry/mastering-ethereum/master/Plasma-in-depth/images/pc-tx.png" width="400" height="500" alt="Plasma Cash TXs" />code

截止到区块 #4,能够看到token #1 和 token #3 始终没有被交易。token #2 在区块 #2 被 E 发送给了 F,在区块 #4 被 F 发送给了 G,在其它区块没有发生交易,token #2 的最终全部权归 G。token #4 在区块 #1 被 A 发送给了 B,在区块 #3 被 B 发送给了 C,在其它区块没有发生交易,token #4 的最终全部权归 C。F 为了向 G 证实 token #2 的合法性,须要向 G 提供 token #2 在前 4 个区块中的全部交易历史,也就是说不只须要包括区块 #2 中 E => F 的交易证实、区块 #4中 F => G 的交易证实,还要包括在区块 #1 和 #3 中没有被交易的证实。到这里可能感受有点奇怪,为何还要包括没有被交易的证实?这是为了防止双花,由于 G 并不知道在区块 #1 和 #3 中 token #2 是否被交易给了其它人。假如 F 在区块 #3 中将 token #2 发送给了 H,而且对 G 隐瞒了这个交易,那么发生在区块 #4 中的 F => G 就是非法(双花)的。所以,在 Plasma Cash 中,完整且合法的交易历史是一个 token 被安全交易的前提。

稀疏梅克尔树(Sparse Merkle Tree)

在上文中咱们已经了解到一个交易的成功的前提是须要发送方提供关于一个 token 的完整交易历史。完整的交易历史既包括这个 token 在哪些区块被交易的信息,也包括这个 token 在哪些区块没有被交易的信息。咱们都知道,在区块链中,使用梅克尔树(Merkle Tree,MT)构造梅克尔证实(Merkel Proof, MP)能够在 O(logN)的时间复杂度验证一个交易是否存在一个区块中。但想要证实一个交易没有存在一个区块中,使用标准的梅克尔树却没那么容易。所以,Plasma Cash 中使用了一种称为稀疏梅克尔树(Sparse Merkle Tree,SMT)的数据结构存储交易数据,可以在O(logN)的时间复杂度验证一个交易不存在。

SMT 实际上一点都不复杂,它的叶子节点是按数据集中的元素序号顺序排列的。若是某个叶子节点对应的元素为空,那么该叶子节点将存储一个特定的值(例如 0 的哈希值)。一个简单的 SMT 示例以下图(来源[5])所示。

<img src="https://raw.githubusercontent.com/gitferry/mastering-ethereum/master/Plasma-in-depth/images/SMT.png" width="400" height="400" alt="Sparse Merkle Tree" />

扩展到 Plasma Cash 中,SMT 的叶子节点对应了区块中给每一个 token 分配的插槽,按照每一个 token 的 ID 排序。每一个叶子节点存储对应的 token 的交易信息,若是 token 在这个区块中没有被交易,则相应的叶子节点存储的值为 null

以上图为例,若是须要证实交易 A 存在,就像在标准的 MT 中同样,须要构造 MP:H(null) 和 H(H(null) + H(D))。若是须要证实 B 不存在,一样很简单,咱们已经知道 B 的位置是第二个叶子节点,若是 B 不存在,那么该节点存储的值应该为 null。所以就像在标准的 MT 中证实存在的 MP 同样,只不过须要加上 H(null) 做为 MP 的一部分,即 MP:H(null)、H(A)和 H(H(null)+H(D))。

取款/退出(Withdrawl/Exit)

Plasma Cash 中的取款操做在流程上跟 Plasma MVP 大致相同,都要从提交取款申请开始,经历争议期以后才能完成。因为 Plasma Cash 中采用的数据结构不一样,在取款时须要提交的 token 全部权证实不一样,所以当争议发生时须要提交的争议证实也不一样。

提交取款申请

在向 Plasma 合约提交关于某个 token 的取款申请时,须要提供关于这个 token 最近的两次交易证实。例如,在上图中,假如 G 想要取走 token #2 到主链,那么他须要提交关于 F => G 以及 E => F 的 Merkle Proof。

提交争议

取款者在提交了取款申请以后一样须要支付必定的保证金,并等待一段时间的争议期。在这期间若是有其它节点提交了有效的争议证实,那么取款者不但没法完成取款操做,也会损失所有或部分的保证金。

目前 Plasma Cash 支持三种争议证实,分别应对三种不一样的攻击场景(具体会在后文分析):

  1. 已花费证实。若是能证实正在取款的 token 已经被花费,那么取款当即被取消;
  2. 双花证实。若是能证实取款申请中提供的两次交易证实中间还有别的交易,即发生了双花,那么取款当即被取消;
  3. 非法交易历史证实。用户还能够对正在取款的 token 的其它交易历史提出争议。这种争议不会马上阻断取款,而是强制取款者提交其它交易证实来反驳争议,若是没有在规定时间内反驳,则取款被取消。

攻击场景

在这一节将讨论已有的 3 种攻击场景以及如何构造争议分别应对这些攻击[6]。在这里假设 Plasma Cash 中存在不可信的 operator 接收全部的交易并构造区块。

发送交易后当即退出

以下图(来源[7])所示,假设攻击者 Alice 向 Bob 发送了一个 token A,且 Bob 已经验证了 A 的交易历史没有问题,交易在区块 N+X 获得确认。在这以后,Alice 当即提交取款申请,企图将 token A 取回主链,并提交 A 在区块 N 以及以前的交易证实。为了应对这种状况,Bob 必须及时发现 Alice 的取款行为,而且在争议期结束前提交在区块 N+X 中 token A 被 Alice 发送给 Bob 的证实。这里须要注意的是,若是 Bob 在区块 N+Y 将 token A 发送给 Charlie 的交易是不能被当作争议证实的,只有最接近被争议的交易的下一个交易证实有效。

<img src="https://raw.githubusercontent.com/gitferry/mastering-ethereum/master/Plasma-in-depth/images/attack1.png" width="700" height="220" alt="attack1" />

双花攻击

双花攻击须要 operator 配合,将含有已经被花费的 token 的交易打包入下一个区块中。以下图所示(来源[7]),攻击者 Alice 和 Charlie 是同谋,Alice 向 Bob 发送一个 token A 在区块 N+X 被确认,以后 Alice 又将 token A 发送给 Charlie,并在区块 N+Y 被确认。这时在主链看来,Bob 和 Charlie 都是 token A 的合法拥有者。接下来,Charlie 当即提交取款申请,企图取走 token A。Bob 为了防止本身的 token 被盗,能够在争议期内提交在区块 N+X 被确认的交易,代表本身在 Charlie 以前已经拥有了 token A。

<img src="https://raw.githubusercontent.com/gitferry/mastering-ethereum/master/Plasma-in-depth/images/attack2.png" width="700" height="300" alt="attack2" />

取款包含非法交易历史

这种攻击须要联合比较多的同谋者。以下图所示,Alice 在区块 N 拥有 token A。Bob 联合 operator、Charlie 以及 Dylan 企图盗走 Alice 的 token。首先,operator 伪造 Alice 将 token A 发送给 Bob 的交易,并在区块 N+X 获得确认,以后 Bob 将 token 发送给 Charlie,在区块 N+Y 确认。一样地,Charlie 接着将 token 发送给 Dylan,在区块 N+Z 确认。这是,Dylan 提出取款申请,企图取走 token A。Dylan 用于取款申请的两个交易证实 Charlie => Dylan 和 Bob => Charlie 都是合法的,但 token A 的交易历史中有一部分是伪造的。Alice 为了证实本身是 token A 的最新合法拥有者,能够提出争议,要求 Dylan 提供 Alice => Bob 的交易证实,同时 Alice 须要提交一部分保证金(不然任何人均可以随便提出争议)。Dylan 必须在必定的时间内提供合法的交易证实,不然取款失效。

<img src="https://raw.githubusercontent.com/gitferry/mastering-ethereum/master/Plasma-in-depth/images/attack3.png" width="900" height="250" alt="attack3" />

相关项目

Talk is cheap, show me your code.

目前已经有许多机构和公司已经实现了 Plasma Cash,但实现的语言和细节有所不一样:

总结

本篇介绍了 Plasma 框架下的基于 NFT 的项目 Plasma Cash。Plasma Cash 给每一个新转移的 token 分配一个惟一的 token ID,而且用稀疏梅克尔树存储交易,使得用户能够只关注跟本身的 token 有关的动态,而不须要关注其它 token。Plasma Cash 能够被看做 Plasma 逐渐迈向成熟的一步,已经有不少公司使用 Plasma Cash 搭建本身的平台和应用,例如 Loomnetwork 公司搭建了本身的 Plasma Cash 子链而且编写了 SDK 支撑开发者在上面开发新的应用。然而 Plasma Cash 自己仍然存在较多的问题,例如 token 没法被分隔合并、须要提交的证实过长等。在接下来的文章中还会继续跟进 Plasma 最新的进展。

相关资源

  1. https://ethresear.ch/t/plasma-cash-plasma-with-much-less-per-user-data-checking/1298
  2. https://en.wikipedia.org/wiki/Non-fungible_token
  3. http://erc721.org/
  4. https://github.com/ethsociety/learn-plasma
  5. https://medium.com/@kelvinfichter/whats-a-sparse-merkle-tree-acda70aeb837
  6. https://karl.tech/plasma-cash-simple-spec/
  7. https://github.com/loomnetwork/plasma-paper/blob/master/plasma_cash.pdf
  8. https://github.com/loomnetwork/plasma-cash
  9. https://github.com/omisego/plasma-cash
  10. https://github.com/wolkdb/deepblockchains/tree/master/Plasmacash
  11. https://github.com/luciditytech/lucidity-plasma-cash

本文的做者是盖盖,他的公众号: chainlab

深刻浅出区块链 - 系统学习区块链,打造最好的区块链技术博客。

相关文章
相关标签/搜索