# MOVE语言首个GAS设计：Aptos 链上的GAS 花费如何计算？

By [AptosGlobal](https://paragraph.com/@0xaptosworld) · 2022-10-23

---

**Aptos Labs 于10月14日公布了Aptos 的GAS 计划，因为MOVE 语言的上一个版本其实是打算在没有GAS 的前提下运行的，所以并没有为GAS 计划做好准备，所以Aptos labs 此次为Aptos 建立的GAS 计划是MOVE 语言首个GAS 设计，被官方称为「一场冒险」。**

**在Aptos 的GAS 计划中，Aptos Labs 表明了自己制定GAS 的原则、流程、如何计算GAS、后期GAS 费调整以及积极接受Aptos 社区的建议，本文由Aptos Global 编译。**

本文作者：Aptos labs

编译：AptosGlobal

GAS 计量是Aptos和其他很多区块链的基本概念，它定义了执行和存储链上交易所需的计算和存储资源量的抽象计算。GAS 计划将链上所有执行所消耗的成本确定，用于计算执行交易期间使用的GAS 花费。

流程
==

**为了有效的执行，我们在Aptos 链上的流程是：**

1）定义我们的原则；

2）准备一个评估框架，以确定每个执行的价格；

3）为Move建立 GAS 计量系统和安全 GAS 代数；

4）将上游 GAS 框架导入Aptos；

5）使 GAS 框架具有存储意识；

6）最后，进一步细化 GAS 计划。

原则
==

**我们的定义原则是:**

1、操作的成本应该与网络上的可用资源直接相关(例如CPU、内存、网络、存储I/O 和空间使用等)。此外，当技术和流程改进后，GAS 所需的成本应该要随之降低。

2、Gas 应该由链上治理设置，并且可以无缝配置。

3、Gas 可以防止对网络中固定资源集的DoS攻击，并且可能需要根据网络情况通过治理建议迅速进行调整。

4、Aptos 的 GAS 价格反映了Aptos基金会加速增长和保持区块链人人可及的愿望。

5、鼓励在设计中做出好的选择——例如优先考虑安全性、模块化、断言等事件。

计算GAS
=====

  

当用户提交交易时，他们还必须在事务中指定两个数量:

**Max gas amount:** 以 GAS 单位计量。这是用户(即，交易发送者)愿意为执行交易花费的最大GAS 单位数。

\*\*Gas unit price:\*\*以每单位 GAS 的八进制计算，其中1八进制=0.00000001 APT(=$10^{-8}$)。这是用户愿意支付的 GAS 价格。

**在执行过程中，交易将被收取:**

1）固定成本，固定基数加上大额交易的额外费用。

2）执行成本，用于执行Move指令。

3）读取成本，用于从持久存储读取数据。

4）写入成本，用于将数据写入持久存储。

最终的交易费用可以用消耗的 GAS 总量(以 GAS 单位计算)乘以 GAS 单价来计算。例如，如果一笔交易消耗670个 GAS 单位，而用户在交易中指定的天然气单位价格为每单位100 Octa，那么**最终的交易费用为670 \* 100 = 67000 Octa = 0.00067 APT。**

如果一个交易在执行过程中耗尽了gas，那么发送方将根据最大gas量收取费用，并且该交易所做的所有更改都将被恢复。 

建立一个GAS 计划表
===========

  

**1、基本配置**

GAS 计划中有几个组成部分与单个操作的细节无关，包括交易大小和最大 GAS 单位(不同于用户在交易中指定的最大GAS量)。

**2、交易规模** 

对于大多数交易，交易规模可能在千字节的数量级。然而，Move模块的发布很容易就有几千字节，而Aptos框架大约有100 KB。大多数用户模块的大小一般在4KB到40KB之间。最初，我们将交易规模的值设置为32KB，但根据社区的反应，要求提供更多空间以简化应用程序开发，因此我们将交易规模调整为64KB。

非常大规模的交易会导致整个网络的带宽成本提高，并可能对性能产生负面影响。如果被滥用，内存池会被鼓励忽略规模更大的交易，因此我们的方法是在最大规模交易的大小和可访问性之间取得平衡。 

**3、最大GAS单位**

GAS 计划中的的最大GAS 单位定义了一个交易最多可以执行多少操作。注意！这不同于用户在交易中指定的最大GAS量。

GAS 计划的最大GAS单位直接影响到一个交易可以执行多长时间，将其设置过高可能会导致对区块链产生负面性能影响交易。例如，用户可能忘记在while循环中有一个增量，从而导致无限循环，这是一个常见错误。我们发现，**即使我们进行了最大的框架升级，我们仍然不到 gas 计划的最大 gas 单位（设定为 1,000,000）的 90%。** 

**4、执行** 

为了评估执行成本，我们构建了一个基准框架，并在执行该框架时使用

Valgrind （[https://valgrind.org/）来分析](https://valgrind.org/%EF%BC%89%E6%9D%A5%E5%88%86%E6%9E%90) Move VM。它的输出是一组带注释的源代码，它告诉我们每行代码产生了多少机器指令。

在上述分析的帮助下，我们粗略估计了所有 Move 指令和本机函数的相对成本。然而，我们注意到这个方法与内联函数存在一些问题：它们不会自动包含在调用者的计数中。我们还看到，这只发生在我们分析某些 Move 指令时，我们可以通过将数字相加来解决这个问题。

随后，通过考虑增强系统稳健性和安全性的编码范例，团队得出了最终执行的机器指令数量。**这个数字依次与存储和最大GAS 单位进行权衡，以确定它们在 GAS 计划中的当前值。**

**5、存储**

每当访问存储在持久存储中的账本状态项或数据时，Aptos 节点都会向存储设备发出读取或写入。每秒的数据访问总数取决于存储设备的带宽和 IOPS 容量。与 gas 调度计算部分的 CPU 周期类似，数据访问是区块链用户在系统负载时通过费用市场竞争的瞬时稀缺性，此外，写入数据的磁盘占用成本在链上是永久的。Aptos 团队通过考虑这些成本来设计存储 GAS 计划。

访问和存储任何状态项都会产生与验证整个区块链状态的数据结构

水母默克尔树：

[https://github.com/aptos-labs/aptos-core/blob/main/developer-docs-site/static/papers/jellyfish-merkle-tree/2021-01-14.pdf）相关的成本。此成本与不同状态项的基数有关（$2^{256}$）。还有一个成本与每个项目的大小成正比。要对一个状态项进行操作，费用为（下一节中描述的例外情况除外）：](https://github.com/aptos-labs/aptos-core/blob/main/developer-docs-site/static/papers/jellyfish-merkle-tree/2021-01-14.pdf%EF%BC%89%E7%9B%B8%E5%85%B3%E7%9A%84%E6%88%90%E6%9C%AC%E3%80%82%E6%AD%A4%E6%88%90%E6%9C%AC%E4%B8%8E%E4%B8%8D%E5%90%8C%E7%8A%B6%E6%80%81%E9%A1%B9%E7%9A%84%E5%9F%BA%E6%95%B0%E6%9C%89%E5%85%B3%EF%BC%88$2%5E%7B256%7D$%EF%BC%89%E3%80%82%E8%BF%98%E6%9C%89%E4%B8%80%E4%B8%AA%E6%88%90%E6%9C%AC%E4%B8%8E%E6%AF%8F%E4%B8%AA%E9%A1%B9%E7%9B%AE%E7%9A%84%E5%A4%A7%E5%B0%8F%E6%88%90%E6%AD%A3%E6%AF%94%E3%80%82%E8%A6%81%E5%AF%B9%E4%B8%80%E4%B8%AA%E7%8A%B6%E6%80%81%E9%A1%B9%E8%BF%9B%E8%A1%8C%E6%93%8D%E4%BD%9C%EF%BC%8C%E8%B4%B9%E7%94%A8%E4%B8%BA%EF%BC%88%E4%B8%8B%E4%B8%80%E8%8A%82%E4%B8%AD%E6%8F%8F%E8%BF%B0%E7%9A%84%E4%BE%8B%E5%A4%96%E6%83%85%E5%86%B5%E9%99%A4%E5%A4%96%EF%BC%89%EF%BC%9A)

**存储GAS 费 = item\_fee + (byte\_fee \* bytes)**

读、创建和写
======

  

对状态项的任何访问都属于以下三种类型之一:读、创建或写。访问按项目费和字节费收费，如上面的等式所示。

读操作是最常见的操作，它只受瞬时资源稀缺的限制。因此，读取费用是根据磁盘IOPS(项目费用)和参考硬件规范的带宽容量进行校准的。

create 是在状态存储中添加一个新项。因此，create增加了身份验证数据结构，使一切都变得更昂贵，因此成本最高。创建费用是根据网络拥有的参考磁盘空间进行校准的。因此，用项目(item\_fee)和字节(byte\_fee)填满磁盘需要大量的GAS。

写操作更新状态存储中的现有项。因此，写操作不会在身份验证数据结构中产生额外的开销。然而，通过修改现有的条目到更大的字节，仍然可以破坏磁盘。因此，我们对更新项中的字节收取与创建时相同的费用。

应该注意的是，与存储相关的成本是基于每一笔交易进行评估的:即使您多次读取/写入相同的资源，也只需要支付一次费用。

**基于上述考虑，我们定义了6个 GAS 参数，它们构成了 GAS 总费用的组成部分。见以下:**

per\_item\_read:根据IOPs进行校正

per\_byte\_read:根据实际带宽校准

per\_item\_create:根据目标总项目进行校准

per\_byte\_create:根据目标总大小进行校准-每个项目包含的第一个1KB

per\_item\_write:与per\_item\_read相同

per\_byte\_write:与per\_byte\_create相同

更多信息，请访问

[https://aptos.dev/concepts/base-gas/#storage-gas。](https://aptos.dev/concepts/base-gas/#storage-gas%E3%80%82)

稳定的 GAS 单位成本
============

  

无论以 APT 或法定货币的市场价值计算执行操作的成本如何，每个操作和交易本身都需要相对于存储和执行成本的固定单位成本。固定的 gas 单位成本有助于保持 gas 计划不变，并与 APT 的自由市场价值脱钩。此外，正确选择 GAS 单位的精确位数有助于保持 GAS 计划不变。考虑到这一点，Aptos 团队以大约 3 位数的精度来表示 GAS 单位。因此，转账交易的成本大约是 700 个 gas 单位。

社区参与
====

  

即使我们对 GAS 计划投入了大量的精力，但是它还远远不够完善。作为一个社区项目，Aptos社区成员可以选择:

1）根据你的经验，找出GAS 计划不合理的地方；

2）说出你对GAS 计划的担忧，并参与社区讨论。

3）就Aptos上与 GAS 相关的治理提案进行投票。

如何调整GAS 成本？
===========

  

GAS 计划作为链上配置被存储，但是可以通过Aptos 治理提案进行更改，并且可以无缝添加新指令或原生功能。

GAS 计划被设计为可扩展的，允许通过治理提案对其进行升级。随着 Aptos 和 Aptos 社区不断改进 Move VM 并纳入用户反馈，GAS 参数可以随着时间的推移进行调整。

有时，GAS 公式可能需要超出链上配置的复杂更改。这些GAS 公式通常用 Rust 编码，并通过链上GAS 特征标志来区分。要升级这些公式，必须使用新公式更新节点软件，并以不同的GAS 特征标志进行区分。然后必须发布节点软件并为节点运营商大量采用，最后，必须发布并批准治理提案才能使用新的 gas 版本。 

未来的工作
=====

这是Move的第一个可行的 GAS 框架。它需要对Move VM和 Aptos-Core进行大量修改。我们希望这项工作为今后的工作铺平道路：

**1）降低执行成本**，拥有一个真实的 GAS 模型表明编译器和虚拟机在哪里有效率，团队可以改进其中的大部分以降低执行成本。

**2）多维GAS 计算**，允许用户为执行和存储指定单独的预算。这样，用户就不必为因为代码编写不佳的应用程序花费过长的执行时间，支付高昂的 gas 价格。它还将允许对区块链端交易的最大 Gas 价格进行更细粒度的定义；

**3）缓解臃肿状态**，目前没有简单的方法来缩小状态集，除了合约（或用户）显式删除事物。用户付钱删除数据可能会带来套利机会，用户在便宜的时候创建存储，在昂贵的时候删除它。Aptos 推迟了解决这一挑战，这可能会削弱开发人员删除链上数据的动力。该团队正在探索每个项目 TTL 的概念，该概念将在 TTL 到期时删除未访问的状态项目。

---

*Originally published on [AptosGlobal](https://paragraph.com/@0xaptosworld/move-gas-aptos-gas)*
