本文将介绍自我结构对以太坊生态弊大于利的一些原因。正是由于这些原因,我们应该以某种方式消除自我结构;。鉴于有些合同已经使用了自检,我提出了一些方法,以最小的成本消除自检的危害。
一段历史:自我建构不再必要
自毁(最初称为自杀)是在以太坊的早期引入的。事实上,它出现在2013年12月发布的以太坊协议“规范”通知中。当时,很少有人认真考虑国家规模经营的长期问题。但是,有一个想法,我有一些印象,为了防止无用的垃圾状态不受限制地扩展,我们需要使任何创建的对象都可以被销毁。具体思路是,当外部自有账户余额为零时,就会触发自毁行为。当不使用契约时,可以调用代码中的一行自毁语句来触发自毁。还有一种退气机制,鼓励人们破坏无用状态。
2014年1月,Andrew Miller指出了一个非常严重的问题:在2013年12月的规范设计中,EOA很容易被重放。如果我有100个硬币,我会通过一次交易给你10个硬币,你只需在链上重复交易10次,就可以转移我所有的余额。这个问题很快就解决了,所以我们添加了nonce字段。然而,nonce字段的引入完全消除了删除EOA的愿望:nonce不能重置为零。
2015年,有人提出了一些建议,试图绕过这一问题,以便安全地删除余额为零的账户。不过,当时很明显,几乎没有合同开发者真正使用自毁功能:很难搞清楚何时自毁,奖励也太少。
到2019-21年,我们需要的显然是其他形式的国家管理,例如长期没有改变的租金机制或“到期”(即“部分无国籍状态”)。如果我们采用这两种方案中的任何一种,只要是有效的,合同是否具有自我删除的能力都无关紧要。
自毁是唯一能破坏重要不变量的操作码
自毁不仅无用,而且有害。它破坏了一些重要的常量属性,这些属性非常好,但是我们失去它们仅仅是因为这个操作码。
Selfdstruct是唯一可以在单个块中更改无限多个状态对象的操作码
所有其他操作码只能操作帐户中的单个值或存储树中的单个键,因此它们可以更改的固定大小对象的数量是有限制的(通常,通过调用一个操作码只能更改一个对象)。但是,selfdstruct可以删除整个存储树。
在当前的状态树结构中,这是可以容忍的。但是,考虑一种特殊情况:当调用selfdstruct删除多个存储插槽时,下一个事务将在相同的地址创建一个协定并访问相同的存储插槽。为了应对这种情况,我们需要设计一种复杂的缓存机制。此外,selfdstruct阻止我们更改状态存储格式。
以selfdstruct将阻止的两种状态存储格式为例:
任何“单层”方案(使用单个树或单个HashMap来存储所有合同帐户的数据,而不是每个合同帐户都有一个存储树的当前设计)
存储槽可以存储在“附近”的某个地址中,而不是存储在合同中(这对于优化见证大小可能很有用,例如在ERC20传输或Uniswap事务场景中)
请注意,这不是幻想。关于从根本上改变状态存储格式(如使用二叉树、verkle树等)的讨论已经开始。如果状态存储的数据结构可以接近单个键/值存储结构,并且在单个块中可以改变的状态数有一个上下限,那么我们的选择空间将大大扩展。
自毁是唯一导致合同代码更改的操作码
如果一段代码存储在特定的地址,它将永远留在链上。这种恒常性非常有用,因为在构建应用程序时不需要担心代码更改。
帐户抽象在很大程度上依赖于这个常量属性来支持库调用。因为代码可能会更改,应用程序的安全性将变得更加复杂:2017年,parity的多重签名钱包完全瘫痪,因为它引用的库代码合同被意外删除。
而唯一破坏代码不变性的操作码是自毁,这是奇偶校验猝死的主要原因。
自毁是唯一可以不经账户同意修改账户余额的操作码
Selfdestract有一个内置的“传输”功能,它不遵循正常的传输过程,因此它可以绕过保护功能,避免从合同地址接收以太坊,并记录传输事件。这为智能合约钱包埋下了隐患,使得一些潜在有用的技能无法获得,并增加了开发人员和审计人员的心理负担(需要考虑更多例外情况)。
Selfdstruct当前用例
如今,自毁有两个重要的应用:
加斯托克:当天然气价格较低时,你可以通过签订合同来使用天然气。当天然气价格较高时,您可以致电selfconstruct获得天然气退款(对于几乎不占用空间的合同,您可以退还大约60%的创建成本)。
使用selfdestruct实现动态代码更改:这可以用于DAPP或Dao的“升级”和其他类似的用例。
(1) 它可以安全地销毁。Gastoken开发者已经发出警告,“尽管对以太坊的变更将导致Gastoken无法使用、不可赎回、不可交换和/或一文不值,但Gastoken开发者可能会支持这一变更。”。取消自毁退款只会使一些操作更加昂贵(超过2倍)。
从长远来看,(2)这是不必要的,还有其他广泛使用的范例可以用来支持动态代码更改。最简单的实现方法是委托呼叫应答器,合同从存储槽中获取一个代码地址,然后调用相应地址的代码;修改存储槽可以更新代码。然而,在短期内,已经使用了一些应用程序(2)。
建议1:完全消除自我建构
从一个块开始(带有标志)。例如,block是指从pow链和信标链合并的块开始,完全停止自毁;。在该块和后续块中,如果EVM在执行期间遇到0xff操作码,它可以简单地抛出异常并直接退出,就像EVM在执行期间遇到不存在的操作码一样。
为了提醒用户避免使用自建,我们可以在完全停止使用之前逐步增加燃气成本:如果;块编号+10**6gt;=标志区块,则自建的天然气成本将增加至10**10//(标志区块-块编号)nbsp
提议2:**
我们也可以保留操作码,但改变其行为。一方面,我们可以消除它对状态树的破坏。另一方面,我们可以添加一个新的特性,使契约被标记为不可自毁的,从而确保代码是不变的。
新提出的行为包括:
当合同调用selfconstruct时,不会删除合同帐户,但会清除代码并将nonce值增加2**40;。不退款。
合同中的ETH通过调用(transfer)转移到目标地址(要么父调用提供所需的所有gas,要么父调用不提供任何gas)。
可以在代码为空的地址(例如已清除的地址)上创建合同。
在实际操作中,slaa的地址称为偏移量=(a+a.nonce//2**40)%2**160。
请注意,从eip-2929的角度来看,需要可以访问偏移量。如果该帐户不在可达帐户中心化,将额外支付2600汽油以加入可达帐户集。
另一个选项是调整将存储密钥转换为树密钥的哈希函数,使用Sha3(存储密钥)ukey+contractunonce//2**40)而不是Sha3(存储密钥)。应该注意的是,在任何情况下,需要进行一些类似的调整,以促进在合同级别上扩展关键空间状态。
契约可以指定0xa8作为代码中的第一个字节,EVM会将其识别为无操作,但在执行过程中使用它来打开标志并完全禁用selfstruct的功能(注意:这类似于set)对于索引建议也是如此。
这两种解决方案也可以结合起来:现在**,将来完全切除。或者,这个操作码永远不可能被完全删除,但只保留一个函数,即将合同的所有当前ETH余额发送到目标地址。我们可以将此操作码重命名为clear;。
文章标题:为什么自我建构对以太坊弊大于利
文章链接:https://www.btchangqing.cn/215234.html
更新时间:2021年03月20日
本站大部分内容均收集于网络,若内容若侵犯到您的权益,请联系我们,我们将第一时间处理。