本文深入探讨了一种通用的Plasma架构,强调了可以使用链下数据影响链上状态的能力。文章详细介绍了更新的逻辑、核心思想及如何利用'谓词'实现功能扩展,展示了在不重新部署整个合约的情况下如何引入新的状态转换逻辑,还提供了Python实现示例,最后展望了Plasma未来的研究方向和标准化潜力。
我们最近发表了一篇文章,描述了我们在更广义的 plasma 架构方面的新工作。这篇文章深入探讨了对架构感兴趣的人背后的工作原理。 我们将高层次地讨论所有内容如何结合在一起,然后跳入样本实现的 Python 实现。如果你已经对 plasma 非常熟悉,可以直接滚动到图示部分。
我们之前文章的主要要点是:
因此,我们开始着手创建一个平台,使构建可扩展的区块链应用变得简单,无需成为 plasma 专家。最后,我们得到了一个通用的 plasma 链,你可以在其上构建应用(或称为“plapps”)。听起来奇怪吗?Plapp。Plaaapp。Plappp。没错。
瑞克和莫提在跟上 plasma 研究方面遇到麻烦。
“第二层”的核心理念是,我们可以使用主区块链之外的数据(“链外数据”)来提供关于主区块链上资产(“链上数据”)的保证。例如,这些链外数据可能赋予你提取存放在以太坊的链上托管合约中的资产的权利。但是,该资产的所有权在未触及以太坊的情况下已经转移。
当然,链外数据是无用的,除非有可能发生与主区块链的某些事情。这通常通过允许用户向存放声索资产的链上智能合约提交关于链外数据的“声明”来实现。这项声claim可能是:“我有这个签过名的信息,表明我可以提取资产 X。”
但是,如果在提交声明后,做出上述声明的人也发出一条信息将资产 X 转给其他人呢?这将使上述提取无效。为了确保任何此类无效的提取都不成功,我们为每个声明添加一个争议期。任何人可以在争议期结束之前对该声明提出质疑。否则,该声明被视为有效。够简单了吧!
让我们快速将这与 plasma 联系起来。Plasma 链由一系列区块组成,每个区块又由一系列交易组成。每当创建新的 plasma 链块时,都会将该块的 加密承诺 发布到主链。这些承诺可用于证明某些内容在该区块内部。在我们的案例中,这份承诺是由区块中的所有状态更新创建的梅克尔根。
以太坊上的 plasma 智能合约记录 plasma 块被操作员提交的顺序,并防止承诺被覆盖。因此,这些块承诺给我们提供了一种时间感。当用户想对发生在 plasma 链上的事情进行声明时,他们还必须参考该事情发生的时间,通过区块号。例如,用户可能会说:“这是区块 Y 中的交易 X,将我资产 Z 转移给我。”这个额外的时间维度在争议中也很重要,因为你有时想知道某件事是在其他事情之前还是之后发生的!
正如我们刚刚看到的,第二层主要是使用某种链外数据影响链上的事物。到目前为止,链外数据主要用于表示所有权——谁拥有什么,以及是否发生了转移。
Alice将一项资产存入以太坊的智能合约,她将成为该资产的所有者。然后她可以签署一条链外信息,将资产的所有权转移给Bob。Bob可以通过使用那条签过名的信息提出声明,来再以太坊上提取这项资产。
我们还可以表示比所有权更复杂的事物。假设Alice存入了一只 CryptoKitty,并签署了一堆信息,改变这只小猫的毛色。就像之前的例子一样,她最终可以利用她签署的最后一条信息在以太坊上对这只小猫的毛色提出声明!
兑换小猫的毛色或眼睛颜色,无论是哪种情况,返回以太坊的智能合约必须有办法理解这些变化。每一项新功能或者新的“状态转换”类型都需要对 plasma 合约逻辑进行修改。在之前的 plasma 规范中,添加这样的功能意味着必须重新部署整个plasma合约,并将每个人的资产从旧的 plasma 链迁移到新的 plasma 链。这既不安全,也不具扩展性,更不具可升级性。
在我们深入 plasma 链设计足够远,想要添加新功能时,我们遇到了这升级性问题。经过一些头脑风暴,我们意识到,实际上有一种简单的方法可以在不改变主要 plasma 链合约的情况下添加新功能。
到目前为止,我们谈到的各种场景有一个共同点——链外数据总是用于“争议”无效的链上声明。特定声明的争议基本上只是一些证明,用于证明该声明所引用的状态已过期。有关所有权的争议证明,提出声明的用户后来将所有权转移给了其他人。关于小猫毛色的争议需要证明小猫的毛色已被更改。
我们的主要突破是意识到争议条件不需要在主智能合约中检查。相反,我们可以让其他智能合约实现一个功能,以告诉我们该争议是否有效。我们可以通过创建一个新合约来实现该功能所需的逻辑,并让我们的主合约引用新的合约。我们将这些外部合约称为“Predicates”。
现在添加新功能变得非常简单,但我们仍然需要一种方法来知道_哪个_Predicates适用于特定状态更新。关于小猫毛色的声明不能被改变小猫眼睛颜色的变化争议。那么我们怎么知道应该使用哪个Predicates呢?
简单!我们只需附加要求,使状态更新也说明其所受Predicates。现在,更改小猫毛色的更新消息可以是:“我将这只小猫的毛色改为蓝色,争议可以由位于(0x123...
)的Predicates处理。”
因为用户可以指定他们想要的任何Predicates地址,任何人都可以通过在以太坊上部署新的Predicates来随时向 plasma 链添加新功能。Predicates的内容不仅仅局限于处理争议,但我们稍后将深入探讨。重要的是,Predicates只需实现一个标准接口,这在下一部分定义。
现在,让我们深入探讨这些所有在实践中是如何工作的。我们 plasma 链设计的基本构建块是“状态对象”。 一个状态对象只是具有两个属性的数据片段:
predicateAddress
:控制对象的链上地址。parameters
:描述对象的任意数据块。plasma 状态对象的结构。
状态对象实际上是资产——对 Plasma Cash 中非同质“币”概念的一种推广。就像每个唯一的币在 Cash 中都有一个 coinID
一样,每个状态对象都有一个 stateID
。
就这样!stateID
是根据存款顺序分配的,但对 parameters
或 predicate
没有任何规则。每个 plasma 区块是一组“状态更新”,这些状态更新在特定 stateID
上定义新 stateObjects
。
在区块 0 中提交的状态更新:“Alice在区块 0 拥有 ID 为 0 的状态对象”
由于我们使用的是 基于范围的 Cash 变体,stateUpdate
实际上是在状态对象 ID 的范围内指定的:
stateUpdate = {
start: uint,
end: uint,
plasmaBlockNumber: uint,
stateObject: stateObject
}
在以太坊上的 plasma 链合约中,操作员提交 plasma 区块哈希,实现 verifyUpdate(update: stateUpdate, updateWitness:bytes[]) -> bool
,以检查梅克尔包含证明 (updateWitness
),证明该状态更新确实已被提交。
Predicates需要实现一个标准合约接口。让我们来看一下这些功能。
plasma 合约最重要的功能是确定状态更新的有效性。特别是,我们需要防止拥有完全控制块的操作员能够“悄悄引入”一个有效的状态更新,其中 stateObject.parameters.owner == operator
——这将是盗窃!
为此,我们引入“状态弃用”的概念。我们说,对于给定的 stateID
,有效状态是尚未被“弃用”的最早更新。状态弃用类似于未花费交易输出变为已花费交易输出的 UTXO 区块链。
这样,即使操作员伪装成稍后更新状态,使 stateObject.parameters.owner == operator
,带有 stateObject.parameters.owner == alice
的早期更新将会优先,因为只有她能弃用状态。
因此,Predicates中最重要的功能是定义该状态可能被弃用的依据:
verifyDeprecation(stateID: uint, update: stateUpdate, deprecationWitness: bytes)
verifyDeprecation
返回 true
或 false
,取决于提交的 stateUpdate
是否已被特定的 stateID
弃用。deprecationWitness
是Predicates用于检查 stateObject
是否已被弃用的任意数据。例如,通过要求 deprecationWitness
包含来自 update.stateObject.parameters.owner
的有效签名,我们可以保证只有所有者能够批准弃用。
请记住,此功能实际上并不执行任何弃用,因为它涉及 plasma 的退出游戏、争议等。相反,当 plasma 合约需要知道某个 stateObject
是否弃用以评估争议时,会调用该函数。
Predicates接口中还有另外三个函数——按重要性顺序排列,它们是:
finalizeExit(exit: bytes)
当退出被赎回时,plasma 合约将与声明相关联的资产发送到Predicates地址,然后调用此函数。
canInitiateExit(stateUpdate: bytes, initiationWitness: bytes) -> bool
此功能允许Predicates限制谁可以对提交的状态提出声明。例如,所有权Predicates可能希望将 canInitiateExit
限制为资产的所有者。
getAdditionalDisputePeriod(stateUpdate: bytes) -> uint
此功能允许Predicates延长声明的争议期。我们通常只对可能需要更长争议解决过程的复杂Predicates(例如,原子交换)使用此功能。此函数通常只返回 0
。
有了示例,一切都变得更加简单,让我们来看一个。最简单的Predicates是所有权Predicates。这个状态允许其当前的 parameters.owner
在任何时候退出,或批准任何状态更新。
创建我们Predicates的第一步是设计我们的状态对象。幸运的是,这很简单,状态对象的 parameters
里面唯一的数据是当前所有者的地址。使用所有权Predicates的状态对象可能如下所示:
OwnedByAlice = {
parameters: {
owner: '0xAliceAddress...',
},
predicate: '0xOwnershipPredicateAddress...'
}
实现的最重要功能是 verifyDeprecated
,它接收一些任意的 deprecationWitness
。在所有权Predicates的情况下,有效的 deprecationWitness
由以下内容组成:
state.parameters.owner
的签名同意新的 stateUpdate
。stateUpdate
在后来的 plasma 块中已被提交的证明。verifyDeprecated
需要检查这些东西是否有效,这意味着需要检查签名和梅克尔证明。
所有权状态被弃用的条件。
把所有内容结合在一起,我们看到所有者可以通过批准一个新的更新来弃用其所有权状态:
单一所有权Predicates流程。Alice将 stateID
0 发送给Bob,弃用了来自区块 0 的更新。
剩下的功能相对简单。canInitiateExit
需要检查提出声明者是否为所有者,finalizeExit
将资产转发给所有者,而 getAdditionalDisputePeriod
可以返回 0
。
这在代码中实际是怎样的!下面我们附上了简单所有权Predicates的 Python 实现。我们使用 Python 进行纯粹的简化,但在 Solidity 或 Vyper 中做到这一点也很简单。
正如你所看到的,我们实现了上述描述的整个接口。并不是太难 :-)。
这就是我们所拥有的!一个表示资产可转让所有权的Predicates。这里的大部分逻辑与之前在 plasma 合约中执行的逻辑相同。我们甚至设法在ETHDenver期间完成了这一变更的原型开发。这主要是调整我们已经编写的代码而已。
该架构在我们对 plasma 的理解上是一个重要进步。其类似于从支付通道到广义状态通道的转变——我们能够在不升级 plasma 协议的情况下在 plasma 架构中适应新特性和功能。
此外,我们相信Predicates设计空间为 plasma 提供了一个丰富的新研究领域。尽管仍然是早期阶段,但我们认为一些可能的Predicates包括:
然而,记住Predicates并不是万灵药——它们仍然受限于 plasma 设计空间。更广泛的普通化可能尚待发现。尽管如此,Predicates非常强大,似乎对几乎所有 plasma 实现都很有用——包括那些不是基于 Plasma Cash 的实现。
我们认为这为整个 plasma 生态系统的标准化提供了机会。任何共享这种状态弃用架构的 plasma 实现都可以共享Predicates并以新的方式互通。
第二层扩展解决方案的核心是使用链外数据来保证未来的链上状态。无论旧状态是通过签名(状态通道)、承诺(plasma)或其他方式弃用,这些工具最终达成的目标都是相同的。我们希望这一进展是朝着一个统一、共享的语言迈出的一步,涵盖所有第二层解决方案。我们设想一个未来,钱包可以通过利用标准接口连接到任何第二层解决方案,而不是每次编写自定义集成。所有这些都是为了互操作性,互操作性服务于所有人!
Python 模拟:
https://github.com/plasma-group/research/tree/master/gen-plasma
技术规范:https://pigi.readthedocs.io/en/latest/src/specs/generalized-plasma-state.html
- 原文链接: medium.com/plasma-group/...
- 登链社区 AI 助手,为大家转译优秀英文文章,如有翻译不通的地方,还请包涵~
如果觉得我的文章对您有用,请随意打赏。你的支持将鼓励我继续创作!