GAS:Vitalik:存储的定价应该独立于执行吗?

特别感谢@barnabe在早些时候提出了类似的想法。

正如我关于资源定价的旧文章里详细讨论的那样,以太坊的gas实际上是为三种不同的资源付费。

带宽(事务中必须被下载的数据)

计算(验证和执行事务所需时间)

存储(历史记录,但更重要的是状态,例如账户余额、nonces、合约代码和合约存储)

存储不同于其他两项开销。带宽和计算消耗的都是短暂开销,它触碰到短暂存储界限是这样的情况:一个节点在一个区块内能做多少计算或数据下载是有限度的,一旦该区块被打包了,下载和验证该区块的开销基本上都会消失(未来只有少数同步节点需要处理它)。另一方面,存储则是一项永久的开销。如果一个区块的状态大小增加100MB,这个区块在当下被处理没有问题,但当一系列这样的区块持续生成一个月后,整个以太坊会变得不可用。一时严重的状态增长带来的突发影响是可以忽略不计的,但长期的影响则是最严重的,因为每生成一个状态都永久地增加网络的负荷。

采用了stateexpiry和弱无状态方案后,长期来说状态的影响肯定会大大减少:状态不再永久成为网络的负担,一个状态将只会在一年内增加网络负荷,而且即使在那一年里,也只有少数节点需要实际存储该状态。但即使如此,这个长期开销还是会存在的,且仍然需要被定价。

存储大小的一般情况vs最坏情况

无论是在当前的协议(普遍认为是不可持续的),还是有stateexpiry的改良方案,对状态建模的一个弱点是状态膨胀的一般与最坏情况间有巨大差异。想想当前的协议。当前状态的总容量是大约5.5亿个对象,或约32GB(不包括trie的开销)。如果我们把在前一年没有被触及的状态都拿走,状态总容量很容易下降一半。

那最坏的情况是什么?创建合约代码按每字节200gas来收费,如果我们把一个区块分为三个事务,每个事务创建一个合约,我们可以用"12334800gas+3*55000gas"作为合约创建开销来创建三个20558字节的合约。假设平均出块时间是13.1秒,那么每年会出31556925/13.1=2408925个区块,因此,一年的状态大小增长是~61800*2408925=148871600381.67938字节,或大约138GB。

这接近10倍的差异是非常显著的!而且16GB特别符合现实消费者的硬件RAM(如果不行,我们可以修改gas价格或状态失活期使其可行),但138GB是办不到的。如果我们可以使最坏的情况更接近于一般情况,那就更好了。

基于EIP1559的两个方案

解决这个问题的一个自然方法是,用EIP-1559对短暂和永久开销定价,但使调整期(adjustmentperiod)不一样。对于短暂的开销,在单个区块里会有10%的变化幅度。但是对于永久的开销,我们会让价格调整得更慢。如果我们以AMM开销曲线机制作为基础,对于存储,我们可以考虑有一个条曲线代表每个月的目标比率是1GB,开销增长取决于我们比目标高出多少。例如,每超出目标1GB,存储开销可能翻倍。在这个参数里,最坏情况区块的存储价格可能需要大约3天时间才会翻倍。如果存储增长超过目标10GB,存储开销会比正常情况下高出1000倍,使得进一步填充存储在经济上变得不可行。

实现这点有两个方法:

用gas购买存储。也就是说,用SSTORE创建一个新的存储槽,这会像今天一样消耗gas,但消耗gas的数量是会变的。这有一个缺点,即保留了时间点的错误激励(用户会选择在周末gas价格低的时候增加存储,尽管这样对网络并没有好处)。

用ETH购买存储。事务(和调用)会需要提供gas以外的另一种资源(我们会称之为mana?),这种资源除了用不同的参数,会以与gas相似的机制进行收费。这个方法的缺点是它使调用规则变得复杂,且要求新增一个操作码CALL。

还有两个混合选项:

我们可以用ETH来定价存储,但以gas来收费。(因此,如果基本费用上涨2倍,然后填充一个存储槽所需的gas会自动减半)。我们可以把用来扩大存储的ETH从EIP-1559的gas价格更新规则、甚至区块gaslimit里排除出去。

对gas进行更全面的改革,把它拆分为三个概念:gas、执行点、和存储点。1gas=1wei;一个分配gas的事务只意味着它把一些wei转化为一种特殊形式,可用于支付各种资源。在它如何在调用和子调用间的传递方式上,这种形式的运作形式与gas一样。但是,现在有两种开销是由AMM来管理的:执行点的开销和存储点的开销。不同于执行处理一个操作码现在消耗的是Ngas,它消耗的是N执行点,意味着对N*execution_point_costgas收费。填充一个存储槽消耗1个存储点,因此storage_point_costgas会被收费。

还需注意的是,stateexpiry的路线图是包括移除gas返还的。这是由于技术原因,存储槽不能“变空”然后可用于返还;它们只能被设为0,而0的记录必须保留在状态里,直到该epoch结束且该状态失活。这大大减少了以前存储租金方案尝试的困扰。

来源|?ethresear.ch

作者|VitalikButerin

郑重声明: 本文版权归原作者所有, 转载文章仅为传播更多信息之目的, 如作者信息标记有误, 请第一时间联系我们修改或删除, 多谢。

链链资讯

[0:15ms0-4:256ms