通过资源使用计量提供公平的gas费

Sui的并行处理与传统区块链的gas费计算方法不同,传统区块链每次只处理一笔交易。

通过资源使用计量提供公平的gas费

Sui的大规模并行处理需要新的方式思考gas费,即网络上处理交易的成本。在我们的工作中,我们研究计算成本和指令处理,以设计一种最佳的gas费机制。准确评估gas费不仅可以提供公平的网络分摊成本和健康的运营业务模型,还鼓励开发人员使用最佳实践来确保适当的资源使用。

Sui的gas模型利用验证节点调查来设置gas价格,并确保链上交易的成本受到网络运营成本的约束。然而,定义Sui交易的具体成本因以下原因而变得复杂:每个交易包含多个指令,而网络可以同时处理多个交易。换句话说,每个交易应该花费多少gas费呢?

如果像其他只能按顺序处理交易的区块链一样对每笔交易应用一次gas费,可能会对Sui用户进行过度收费。我们的模型涉及测量指令数量、堆栈深度和内存使用,以更准确地表示网络资源使用情况。总的来说,我们的持续工作包括模拟和现实世界测试,以提供基于市场的gas价格和基于资源的gas计划,从而提供有效的gas费机制,以服务Sui的用户和网络健康。

总之,我们通过以下广泛步骤开发了Sui的gas费机制:

  • 确定计算资源使用的最佳方式
  • 设计计算成本的方法
  • 基于不同负载假设分析gas费模型

在并行处理网络上的资源使用 

由于区块链是一种共享资源,gas费用反映了该资源的使用情况,以补偿验证节点维护网络的运营成本。此外,gas费会影响用户行为,鼓励谨慎使用网络,并希望阻止滥用。

许多区块链语言,如Solidity和EVM,以及Move的某些语言,使用基于字节码的计量方法,将每个独立字节码指令与特定成本相关联。在这些设置中,每个字节码成本与底层计算成本(即CPU周期)的数量精确匹配的重要性不如这些指令成本的相对大小重要。例如,如果Add指令的运行时间为1毫秒,而Div的运行时间为2毫秒,重要的是gas_cost(Div)/gas_cost(Add) ~= 2,而为gas_cost(Add)和gas_cost(Div)分配的实际底层数字则不那么重要。

在传统的区块链中,执行的总顺序是协议的一部分,将一笔交易视为对网络的独占使用是有道理的。特别是,如果一个用户运行了某些计算,那么另一个用户在前一个计算完成之前就不能运行自己的计算。在这种情况下,gas成本需要高度反映交易运行时间的相对大小,因为交易处理是一个零和游戏——我有时间,所以其他人没有。

将一笔交易的定价视为单独运行可能并不准确,实际上很可能会向用户收取大量费用。

然而,在Sui上,协议包括大规模并行处理,使资源使用成为非独占。将一笔交易的定价视为单独运行可能并不准确,实际上很可能会大幅向用户收费。交易处理不再一定是零和游戏——我可以有时间,成千上万甚至数十万人也可以分享相同的时间来处理他们的交易。

Sui的并行性要求我们退后一步,审查执行期间的传统基于指令的gas计量方法,以及它们是否适合这个新协议。特别是,并行性给资源使用成本增加了波动性,这要求我们采用一种模型,将类似的事物归在一起,而不是应用特定于指令的定价。例如,特定于将两个整数相加的成本和特定于将两个整数相除的成本变得不那么重要,由于并行效应,实际运行成本更难以预测。

在这个基础上,我们着手设计了一个gas费模型,旨在捕捉执行新的并行处理,使得结果模型尽可能易于理解和合理,并且最重要的是将这些收益返还给Sui的用户。开发这个模型使我们拒绝采用本质上是串行和历史的基于字节码的gas机制(该机制试图测量每个计算周期),而是设计了一个基于曲线或分层的执行gas模型。 

设计Sui的gas费模型

为了得出一个准确的计算成本模型,使gas费更加公平,需要放弃可能相对容易的路径,比如测量交易时间,并研究其他计算因素。除了得到一个合理的模型,我们还需要考虑Sui的存储费用,这允许长期的链上存储。

计算成本

由于Sui 本身具有并行性和高效计算功能,执行单条指令的相对开销对整个执行时间或事务持续时间的影响变得不那么重要。取而代之的是,执行指令的数量对于确定准确的开销最为重要。只有在执行大量字节码指令后,每条指令的实际运行时间成本差异才会对事务的整体运行时间产生重大影响。

此外,为了建立一个准确反映执行实际成本的成本模型,即使对于串行执行系统,也需要克服许多挑战: 

  • 繁琐和高度复杂的gas费机制难以理解、编程和准确实施 
  • 一条指令的gas成本几乎可能与实际指令的执行一样昂贵 
  • 同一条指令的执行时间可能会因未考虑在模型中的环境而发生显著变化(从理论上来说,这是不可能合理建模的),无论gas模型的复杂程度如何。Daniel Perez和Benjamin Livshits的研究EVM中的资源计量攻击深入探讨了这些挑战。

考虑到这些问题,我们开始探讨在Sui中是否有更好的gas计算成本模型。我们检查了通过计算的不同维度来粗略化成本模型的方法,而不是依赖于指令和内存的精确离散计数。此外,我们的目标是尽可能使生成的模型简单易懂,同时确保对用户公平和准确。

通过这一探索,我们得出了一个模型,根据执行期间的三个因素同时跟踪计算成本的多个不同维度: 

  • 指令计数
  • 堆栈深度 
  • 内存使用 

每个维度都以不同的方式对交易资源使用产生影响,具有不同的权重,每个单位(例如执行单个指令,分配单个字节)的成本都会随着在交易执行过程中使用更多这些资源而增加。每个维度在执行过程中的成本会与步骤函数相结合。

这个新模型的核心思想是,我们不追求精确的、精确的周期计数方式,而是为交易成本定义一个相似的范围。此外,单个指令成本的重要性不如执行交易的所有指令的总成本重要。因此,这个新设计对资源成本采取更加动态的视角,即在交易中使用资源越多,资源的成本就越高。我们从Chen Ting、Li Xiaoqi、Wang Ying等研究人员的论文面向以太坊的自适应gas成本机制,以抵御DoS攻击中汲取了一些灵感。

通过以这种方式动态定价指令和资源使用,我们可以在一定范围内对资源使用进行低价定价,因为我们知道,如果超过这些界限(例如,在攻击情况下),执行过程中这些资源的动态定价最终将导致计算成本过于昂贵,以至于无法合理地利用。这种在计算使用较低的端口下低价定价资源使用的能力(例如,不到100,000条指令,不到1兆字节的总分配)允许我们鼓励“有意识的计算”的概念,同时最大程度地减少复杂性,无论是在实施、解释还是推理方面。

这个设计使得为了gas成本而优化代码的需求不那么重要。

由于在计算复杂性较低的模型下的简单性(在该模型中,每个指令的成本都是一个gas单位,每个分配都是一个gas单位),该模型易于理解并且成本低廉。这个设计使得为了gas成本而优化代码的需求不那么重要。因为每个指令的成本都是相同的,几乎不可能这样做。 

通过这种方式,使用我们的gas模型来鼓励正确的编程设计,摆脱对细节、单一字节码指令和晦涩的优化的关注,这些优化通常会对程序有害。同时,我们希望开发人员能够意识到他们的计算和他们在资源方面的使用,同时在计算他们的资源使用时也要公平计算。

非计算成本

除了上面描述的计算成本外,还有其他与在Sui上执行交易的总成本有关的额外成本。这些额外成本的两个主要来源是长期存储成本和gas成本舍入。 

存储成本通过Sui的存储基金以一种独特的方式处理。一旦我们完成执行交易,我们计算要分配给长期存储的数据,这个额外成本将被添加到执行交易的总成本中。此外,如果有人删除存储,将提供存储退款,可以减少交易的总成本,甚至可能会退款。然而,这些类型的存储退款仅在执行交易之后才会计算,因此不能对交易执行过程中可以使用的总gas成本产生影响。 

gas成本的舍入是由于gas计量中的步骤函数而发生的,我们将计算单元放入从1,000到5,000,000的桶中。使用不到1,000个计算单元的任何交易将被舍入到1,000个,从而产生微不足道的额外成本。

详细的Sui gas成本分析

我们设计的gas成本模型需要在实践中运作,同时也需要在理论中运作。测试涉及到查看不同合成工作负载的交易成本。特别是,给定N个指令,针对成本模型中每个指令的分配、推送和弹出的不同值,成本会是怎样的。

合成案例1:没有分配的指令

我们首先看一下最合成的工作负载,即没有分配并且不影响堆栈的指令。每个指令本质上都是一个NoP指令。下面我们可以看到随着在x轴上执行越来越多的指令,执行成本在y轴上的变化。

右上升图
没有分配的指令会在某些阈值处开始上升,而不是线性增加。我们的模型使包含过多指令的交易变得昂贵,这应该会限制那些资源需求大的应用程序。

从这次测试中可以看出,正如之前讨论的,每个指令的成本不是线性的。在达到一定阈值后,收费将被乘以一个常数,使最终成本更昂贵。目标是尽可能长时间地保持成本,并同时避免拒绝服务攻击或使用网络导致类似效果的情况。

这种成本的非线性增加让我们可以在网络的大多数常见使用情况下保持成本,同时允许用户愿意支付更高费用时执行大量交易。最后,必须有一个点,资源使用不再合理,可能对系统和其他用户进行惩罚。因此,对于某些资源的使用和消耗,我们希望使成本变得非常昂贵(而不是设置严格的上限)。

合成案例2:纯分配

在第二个合成测试案例中,我们研究了一种理想情况,在这种情况下,我们在执行过程中成功地分配了内存字节,而没有执行任何指令。下图显示了沿y轴的成本,可分配多达43兆字节的内存。 

直线向右上升
纯粹的内存分配成本在某些阈值处上升,与我们之前仅使用指令的测试案例类似。然而,在这里,随着内存使用的增加,成本增加得更快。

再次,正如我们在前一个案例中看到的,随着执行过程中分配内存的增加,成本是非线性增长的。然而,与指令执行不同,内存分配的非线性扩大要高得多,因为成本的上限被触及。

在单独查看不同主要维度之后,我们现在可以看一些更加真实(但仍然是合成的)工作负载。

合成案例3:具有不同分配数量的指令 

在单独查看指令和内存成本以及随着执行的指令数量的增加或内存分配的增加成本如何变化之后,我们现在可以分析当我们开始将它们放在一起时的成本情况。下图显示了不同指令计数的情况下,y轴上的成本,以及x轴上的指令数量。

五条不同颜色的直线以不同角度向右上升
在这些合成负载中,最有可能模拟真实世界使用的是内存加指令(橙色)和内存加指令(明亮蓝色)。gas成本在特定阈值之后显着增加。

值得注意的一点是,成本在一段时间内(指令数量)非常受控制,然后从那里呈指数增长。这与我们之前提到的一致,我们可以处理计算使用范围较低端的低价或高价成本,因为随着交易中的计算使用增加,计算成本将随之大幅增加,从而抵消了任何可能的低价或成本模型未考虑的计算问题。

现实世界的测试和调整

Sui gas模型的调整和演进,无论是对于计算还是对于系统的非计算方面,都是一个不断进行的过程,在这个过程中,我们需要不断评估当前模型在现实世界中的行为,并确定开发人员和用户的痛点在哪里。我们计划继续开发一个公平而易于理解的模型,可以轻松地进行编程,尽可能不会阻碍良好的编程习惯,并激励良好的行为。 

展望未来,机会成本的概念以及gas费和gas模型如何与Sui的执行并行性相关,意味着我们需要思考与交互或使用共享对象,这些对象创建了计算序列化部分的额外成本。

此外,我们将希望增加额外的成本,以涵盖交易的非计算成本,例如网络带宽。我们将研究交易大小、输入对象的数量和大小以及输入参数的数量和大小如何纳入执行交易的总成本。

Sui gas费故事的不断演进是一个持续进行的过程,我们重视社区反馈,不仅关于gas模型可以改进的地方,还有关于工具和更大的可见性以及有关交易如何使用gas的信息将是有用的地方。