观点

Jeff Coleman:为什么要使用 CREATE2?

Ajian   |     |   3279 次阅读

编者注:君士坦丁堡升级引入了 CREATE2 操作码,这个操作码不像 CREATE 那样根据合约创建交易的发起地址和 Nonce 来产生合约地址,而是根据合约的初始化代码(init code)来产生。前段时间,有人认为 CREATE2 会给合约引入新的风险因素,但 Jeff Coleman 坚持认为,CREATE2 绝不完美,但所谓的风险其实并不来源于 CREATE2 本身,而是来自于 CREATE 的遗留问题。本文是他对 CREATE2 的解释和辩护。也许读完之后,你也会同意 Hudson 说的:“应该像看待 CALL 和 DELEGATECALL 带来的风险那样来看到 CREATE2 带来的风险”。

总结一下,PSA 有两点结论:

CREATE 函数在将来会让人们越来越难以验证一个合约的身份。

CREATE2 函数会帮助缓解这个问题,尽管如此,我们仍需仔细检查合约初始话代码(init code),这将变得与验证合约代码同等重要,以下是原因:

1)就像硬件钱包,冷钱包,以及各种嵌入式或者离线设备的开发者们已经意识到的一样,CREATE 函数让合约代码和合约地址之间的关系变得过于多样。当你使用 CREATE 时,你无法提前预测哪段代码将处于某个给定的地址上。你也无法在合约部署之后容易地 “验证” 这段代码,除非你有区块链的直接访问权限,或者使用某些非常复杂的技巧。这些技巧可能包括与无密钥地址(即合约地址)进行非常混乱的多重转账操作,并且需要提前预付未来的手续费用等等。

2)CREATE2 函数则让地址变成了对合约代码的一种承诺,并且相比之下可能的状态更少。但是我们在这里讨论的是 “初始化代码(init code)”,它的哈希值(hash)和盐(salt)共同决定了这个合约的地址。这实际上是一个巨大的优势,只要人们确实 “验证” 了初始代码。因为它意味着人们可以检查代码工厂与它们所创合约之间的关系,甚至完全无需知晓网络的状态,也可以判断正在部署的合约。所以硬件钱包,冷钱包之类的服务都能很好地运行。

3)但是尤其值得注意的是,这不能使你免受故意造成的不确定性的伤害。如果没有作出严格的限制,一段使用 DELEGATECALL 或者 CALLCODE 的合约初始代码,可以产生无数种结果。这就是人们口中所说的 “偷梁换柱(replace a contract)”。你不可能真的替换那些 CREATE2 所创地址中的 “初始化代码”,但是如果初始化代码本身具有不确定性,你可能会破坏并使用不同的代码重新创建这个合约,这就像你后来将 DELECATECALL 指向新地址一样。这与每个人 (特别是硬件钱包和冷钱包解决方案) 今天在尚无法确认某个合约已经部署时候的处境都是一样的。CREATE2 使得合约的创建环境更加公平,每个人都能确认初始代码的有效性。但是它却并不能保护合约不受初始代码不确定性的伤害。

4)CREATE2 是极为富有远见的,因为用硬编码的椭圆曲线生成的 EOA 地址(即用户地址)可能最终会消亡,取而代之的是各式各样的签名方法。CREATE 函数对地址身份所作的假设在未来可能比现在君士坦丁堡 (Constantinople)阶段更加不切合实际,而 CREATE 函数的一些带有状态的假设已经开始调整了 。这和 CREATE2 函数没有任何关系,它更多是暴露了 CREATE 函数的缺陷,这些缺陷已经在链下以及实际确证之前有所体现。

5)如果你将初始代码检验工作视为验证地址 “里面是什么” 的手段、视为 CREATE2 本身的一部分,那么你就基本不会遇上 CREATE 函数的旧问题。但是如果你同时使用这两个函数,可能就会遇上 @jasoncarver 一直在讨论的奇怪代码表现。这并不是 CREATE2 函数的问题,反而更有可能是当我们逐渐摒弃 CREATE 函数时,CREATE 函数被暴露出越来越多的问题。我意识到很多人并没有意识到 CREATE 函数的问题,所以将其归因于另一个函数。实际上,我们有迫切的需求立刻停用 CREATE 函数。

6)实际上,这意味着:网站,用户,开发者和合约都需要通过 “初始化代码” 来验证合约的身份,而不是通过字节码。如果我们标准化它们的初始模式,这将使得标准部署流程和标准生产流程更加容易。而且,这也比现行的、让人们受困于试图将合约验证向后兼容进 CREATE 模型的非标准化技术好很多。CREATE2 更便宜、更快速、无状态,而且能够面向未来。

7)如果你绝对必须在君士坦丁堡 (Constantinople)之后使用 CREATE 函数,请必须采取特定的步骤确保你合约的功能能够被用户信任,并且将你采用的步骤告诉用户。现在在 CREATE 函数中已经存在一些奇怪的陷阱,使用的时间越长,它可能产生的问题就越多。请尽快转移到 CREATE2 函数中来。

我可能也应该指出,已有的工厂验证模式已经很容易被初始代码不确定性影响,所以这是一个现存的缺陷,而不是新出现的。离线或硬件钱包也总是容易受到初始代码不确定性的损害。目前,大多数初始代码都处于合理范围,因此大大减轻了这种风险。当我们在未来使用 CREATE2 的各项优势功能的同时,我们也需要不断验证合约来保证我们的安全。

我认为,关于 CREATE 函数讨论的最终解决方案如下:基本上我们需要基于内容来为合约赋予地址(这包括确定构造器参数以及多重实例化,做法分别是对初始代码进行哈希(hash)和加盐(salt)),取消自我销毁(self-destruct),并且使用租金存储和恢复机制来处理存储恢复。这意味着合约 nonce 将不再存在而且 CREATE 函数将消失。比起在君士坦丁堡 (Constantinople)阶段部署 CREATE2 函数,如果任何人有一个更好的的方法,来使我们摆脱合约不确定性的影响,我将诚挚地期待。


原文链接: https://twitter.com/technocrypto/status/1095854769183358976
作者: Jeff Coleman
翻译&校对: TrumanW & 阿剑


你可能还会喜欢:

通告 | 以太坊君士坦丁堡(Constantinople)升级公告

 
0 人喜欢