区块链教程

Chapter 4 CryptoCurrencies

| 关于   «  4.3. 以太坊   ::   目录   ::   4.5. 加密货币攻击  »

4.4. 以太坊虚拟机与 Gas

4.4.1. 以太坊虚拟机

4.4.1.1. 简介

什么是以太坊虚拟机(EVM)?EVM 充当一个分布式计算机,运行着以太坊操作系统的底层框架。你可以将以太坊想象成一个由数千台连接的计算机维护的一个单一实体,这些计算机运行着 EVM 的副本。这个实体是一个区块链,我们可以将链上的任意一个区块描述为更新到该点区块链的“状态”所定义的“状态”。从一个区块到另一个区块改变状态的规则由 EVM 定义,并且将在本节的其余部分中讨论。

4.4.1.2. 以太坊状态

在开始之前,我们先定义几个术语:

1. 交易:区块链内数据变化的某事物。 常见的例子包括更改账户余额(向他人发送 ETH)或在某个区块内编辑数据。

区块:区块链由区块组成,每个区块都填充 了交易。

  1. 以太坊状态(Ethereum State):以太坊区块链在某一时刻的快照。

全局以太坊状态:由 最新版本的 EVM 实例所达成的以太坊共识状态。

关于以太坊状态的详细说明 - 所有的数据都存储在一个 enormous data structure 中。数据结构存储每个账户的数据:当前余额、历史交易笔数、智能合约代码等。它还存储其他数据,如先前的区块以及与这些区块相关的所有数据。所有正在运行的 EVM 实例都下载并持有这份巨大数据结构的一个本地副本。理想情况下,它与当前共识状态相同,但一些实例可能略微落后,因为它们尚未通过网络接收最新的更新。这是因为每个 EVM 实例从其他 EVM 实例接收一个新的状态。这个新状态将传播到整个网络,这需要时间。

那么,这个全局状态更新过程如何?一旦一个区块被提交,这意味着它被采纳为区块链中最新的一块,全球以太坊状态将从之前已知的状态过渡到新的状态(有关如何提交的详细信息见 区块如何提交 )。一个区块被提交意味着它所包含的所有交易都被认为是合法的,因此,包含以太坊状态的巨大数据结构已经通过新区块的信息进行了更新。所有正在运行的 EVM 实例必须通过将新数据下载到它们本地数据结构的巨大副本中来采用这个新的全局状态。因此,一些账户余额将会有所变化,一些智能合约交易也将已经完成,所有这些机器必须集体同意这些操作。一旦完成,区块将最终提交到区块链,以太坊的状态将更新。

需要注意的是,对于以太坊而言,将新区块提交到区块链的过程大约需要 15 秒。 因此,与任何分布式账本一样,交易并非即时完成。 每个区块只能容纳几十到几百笔交易,一笔交易只有在被包含进某个区块中后才算完成。 那么为什么是 15 秒,而不是看起来更合理、似乎足以在网络中传播的 1 秒或 2 秒呢? 这是因为,在所有运行中的 EVM 实例之间传播新数据的平均时间是 12.6 秒。 此外,还必须执行区块提议过程(此前这是一种工作量证明形式,但在 2020 年 12 月,以太坊将其共识算法改为了权益证明)。

因此,我们可以将以太坊描述为具有状态转换函数 Y(S, T)= S'。给定一个旧的有效状态 (S) 和一个有效交易块 (T),以太坊状态转换函数 Y(S, T) 会产生一个新的有效输出状态 S'。所有正在运行的 EVM 实例将采用这个新状态,并继续处理交易。

庞大数据结构的简要说明:

修改后的 Merkle-Patricia 树存储以太坊状态。该树本质上是一个巨大的键值映射,其中每个键都是以太坊地址,值是一个包含账户数据数组的数组。具体来说,它包含了账户余额、前 n 笔交易数以及两个哈希字段,这些字段仅适用于 smart contract 账户。对于普通账户,这些字段将为空。对于智能合约,一个字段是智能合约代码片段的哈希值,如果账户接收到一条消息调用(只读操作),则会执行这个字段。另一个字段是另一个 Merkle-Patricia 树的根哈希值,称为账户存储树。在这个树中存储了所有智能合约数据。

4.4.1.3. 智能合约复习

区块链上,账户分为两种:大多数人用于发送和接收以太坊的外部所有账户,以及包含编译成字节码的智能合约的合约账户。这两种账户类型都具有地址,可以接收、持有和发送以太币和0,并且可以与智能合约进行交互。智能合约是用专用编程语言编写的。一种流行的语言是Solidity。以下是一个Solidity代码片段示例。

https://arpitmathur.files.wordpress.com/2018/04/solidity.png

这个代码片段是一个智能合约的示例,其中的函数允许用户设置一个局部变量并读取它。 它可以被视为一个存储,因此合约名为"SimpleStorage"。 在真实的智能合约中,有人可能会存储某个同意法律文件的当事方。

开发者可以在智能合约中放入任何他们想要的数据和函数。 一旦智能合约被部署到区块链上,其中的代码就不可更改了。 不过,可以通过第三方软件调用这些函数。 如果这些函数更改了智能合约中的数据,它们就会改变区块链的状态,因此被视为交易。 在上面的示例中,调用"set"函数会被视为交易,因为它修改了智能合约中的数据。 而调用"get"则不会,因为它只读取数据。

由于智能合约的可定制性如此之高,已经衍生出多种多样的应用。 例如,智能合约最常见的用途之一是转让非同质化代币(NFT)。 最流行的用于此目的的智能合约是 ERC-721,它是 NFT 的标准。 它包含诸如 transfer(current_owner, new_owner, NFT_id)、ownerOf(NFT_id) 等函数。 当有人购买 NFT 时,就会调用 transfer 函数将 NFT 的所有权转让给新地址。 这会修改智能合约内的数据,因此被视为交易。 如果你调用 ownerOf 函数查询某个 NFT 的所有者,它不会修改区块链数据,因此不会被视作交易。

智能合约也是将可替代代币所有权纳入区块链的方式。 可替代代币与 NFT 相反——也就是说,每个代币都是一样的。 以太币、比特币或区块链上的任何其他代币都是如此。 你可以用一种代币兑换另一种代币,因为它们价值相同。 实现此类代币最流行的标准是 ERC-20,一种代币必须实现特定的方法才能被认定为 ERC-20 代币。 这些代币中的任何一种都会有元数据,例如代币总供应量、代币符号、铸币是否已完成等。 它还会有一个在地址之间转移代币的函数,这些地址要么与以太坊地址相同,要么是某个以太坊地址的映射。 其中一些代币包括 $USDT(Tether)、$SHIB(Shiba Inu)、$USDC(USD Coin)、$UNI(Uniswap)等。 你可以在此处查看所有构建在区块链之上的代币: https://coinmarketcap.com/tokens/views/all/

4.4.1.4. EVM 做什么?

在开始之前,我先定义一下什么是以太坊节点。 节点是一台运行着某个 EVM 实例的计算机,由某人搭建用于验证每个区块中的所有交易。 这意味着节点会确保没有格式错误的请求、所有账户都合法有效等。 那么节点和矿工有什么区别呢? 所有矿工都是节点,但并非所有节点都是矿工。 矿工能够通过工作量证明共识算法整体验证区块,而普通节点则不能。 请注意,这只是针对工作量证明协议而言。

2020 年 12 月,以太坊改为了权益证明协议。因此,以下描述与之前的工作量证明协议相关。一旦在以太坊网络上进行交易,该交易将被发送到一个节点。该节点将将该交易广播给所有其他节点,并将其添加到每个节点的待处理交易列表中。这称为节点的内存池:所有尚未提交到区块的交易请求列表。在某个时间点,单个矿工将从其本地内存池中收集一到几百个交易,以一种方式将这些交易收集到一个潜在的区块中,以最大化每个交易的 gas_费用。然后,矿工将验证每个交易,执行其字节码以在本地版本的 EVM 上执行交易,然后收集交易的 gas 费用。最后,矿工将开始工作量证明过程,生成一个证书,显示该区块是有效的。一旦由矿工完成,该矿工将将新区块、证书和新 EVM 状态的校验和广播给所有其他节点。然后,所有其他节点将验证工作量证明证书并重新批准区块中的所有交易。这包括支付给矿工其从区块中收集的 gas 费用的交易。一旦验证完成,节点的本地状态将更新为包括新区块,并继续在网络中传播。一般来说,一旦节点在网络中传播至少 51% 的节点,我们可以说以太坊的全球状态将过渡到包括新区块。

在权益证明协议中,所有提及由矿工收取 Gas 之处,相应地改为由验证者收取。 添加新区块的过程基本保持不变。 先前的工作量证明协议与新的权益证明协议之间的区别,在于提议下一个区块的具体过程。

4.4.2. Gas

4.4.2.1. 简介

Gas 保障以太坊区块链的安全。 它也使(此前是)矿工(如今是)验证者能够获利,并为执行必要的、为区块链提议下一批交易区块的工作提供激励。 那么,Gas 究竟是什么,它又是如何运作的呢?

交易费用是基于以太坊网络上的任何交易的,这种费用直接支付给矿工或验证者,他们正在努力验证和执行交易字节码。交易费用还通过阻止攻击者通过大量交易过载以太坊网络来保护网络,详情见此处。

4.4.2.2. Gas 的成本

决定一笔交易所需 Gas 数量的因素有两个:
  1. 交易的复杂度

(静态区块链交易 vs 智能合约)
  1. 以太坊网络的当前负载

我们先来看第一个因素。 更新区块链的常规方式是:一个装满交易的区块被提议并被接受进区块链(通过共识算法过程)。 对于其中每一笔交易,矿工/验证者都必须对其进行验证并执行其字节码,字节码由若干指令组成。 让一笔交易通过验证的基础费用是 21000 gwei,其中 1 gwei 等于十亿分之一,即 0.000000001 ETH。 然后,在基础费用之上还会附加一笔额外费用,其数额由要执行的指令数量决定。 每个操作码都关联一个 Gas 成本,执行时就会消耗相应数量的 Gas (参见 https://github.com/djrtwo/evm-opcode-gas-costs/blob/master/opcode-gas-costs_EIP-150_revision-1e18248_2017-04-12.csv )。 当涉及智能合约交易中更复杂的字节码时,需要执行的指令数量会急剧增加,这就是智能合约的 Gas 费用高于静态交易的原因。

决定交易价格的第二个因素是当前负载,也就是以太坊网络的拥堵程度。 计算 Gas 的公式如下: Gas price = Gas units * (Base fee + Tip), 我们刚才已经讨论了 Gas units 是如何计算的。 基础费用的价格由以太坊网络的拥堵程度决定。 小费(Tip)是一种优先费用,大多数钱包会自动设置它,以加快你交易的完成速度,因此在计算 Gas 时它并不太重要。 当前区块的基础费用是根据先前区块计算得出的。 当一个新区块被添加到区块链上时,它有一定量的 Gas 容量,称为已包含 Gas(included gas),即该区块内所有交易 Gas 费用之和。 在基础费用最低(100 gwei)的 1 号区块中,已包含 Gas 为 15M gwei。 如果已包含 Gas 被完全填满,基础费用每个区块最多会增加 12.5%,同时区块编号会增加。

https://i.gyazo.com/ed985a9f020ea31379ef0901dbbb9249.png

这种增长是复利式的,当网络在较长时间内高度拥堵时,可能导致非常高的基础费用。 当已包含 Gas 未被完全填满时,区块编号还会减 1,从而造成 Gas 价格的波动。

不过,这并不是高拥堵期间 Gas 价格上涨的唯一原因。 矿工会贪婪地优先处理支付更多 Gas 的交易,因此你支付的 Gas 越多,你的交易被包含进下一个区块的可能性就越大。 执行交易时,你可以选择低、中或高优先级的 Gas 费用。 费用越低,矿工选中的可能性就越低,交易被纳入区块链所需的时间也就越长。 这也意味着,如果你支付的 Gas 过少,交易可能会卡住。 在这种情况下,你可以取消交易(损失已支付的 Gas),也可以追加 Gas 来加快交易。

4.4.2.3. 示例

总结一下,我们来看一个示例交易场景。 给定公式

Gas price = Gas units * (Base fee + Tip)

假设一笔普通交易的小费为 0、Gas 数量为 21000。 那么根据基础费用的不同,Gas 价格将如下所示:

https://i.gyazo.com/b5a61de74c49f9a66e78ff599577cf99.png

回想一下,基础费用越高意味着网络拥堵越严重。 因此,你可能仅仅因为当时网络拥堵,就要支付一大笔 ETH! 基础费用是计算 Gas 时波动最大的数值,因此所有真实的 Gas 价格都会与这张图相当吻合。

所以你可能想知道,在费用如此之高的情况下,为什么还会有人使用以太坊。 以太坊的一大优势在于其费用是固定的——发送 10 美元与发送 100,000 美元的费用相同。 此外,以太坊往往保持在 1 到 10 个区块之间,所以 Gas 价格很少会飙升到离谱的数值。 从历史上看,Gas 价格的飙升发生在某个热门 NFT 同时向公众发布、成千上万个智能合约被同时尝试铸造的时候。

4.4.2.4. 结论

总而言之,Gas 是促使以太坊因挖矿利润而走向去中心化的巨大推动因素。 以太坊挖矿比比特币挖矿更有利可图,因为在网络高度拥堵时期 Gas 费用高昂,加上以太坊每天的交易量约为比特币的 5-6 倍,而以太坊向区块链添加新区块所需的时间要短得多(通常为 15 秒),比特币则需要 10 分钟。 这意味着网络更有可能高度拥堵,矿工验证交易获得的报酬也更多。 Gas 还消除了发起攻击并用交易使网络过载的动机,因为 Gas 费用会迅速消耗攻击者的资金。 如果有人想让网络停滞 15 秒,他们需要放入足够多的交易来填满一个区块。 所有区块(1 号和 2 号区块除外)的 Gas 上限为 30M gwei,相当于 0.03 ETH。 如果你想让网络停滞 1 小时(3600 秒),你需要填满 3600/15 = 240 个区块。 这相当于花费 240 × 0.03 = 7.2 ETH,约合 31,000 美元(截至 2021 年 12 月 5 日)。 攻击者通常都会认为,仅仅为了让网络停滞 1 小时就花费这么多钱,并不合理。 可以想见,让网络长时间宕机根本不值得。 如果不存在 Gas,攻击者的交易就可以一次又一次地填满区块,使其他任何交易都无法被添加进区块。 这会让以太坊网络停滞到无法使用的地步。 总而言之,Gas 是以太坊不可或缺的一部分,对于保持区块链的去中心化和顺畅运行必不可少。

   «  4.3. 以太坊   ::   目录   ::   4.5. 加密货币攻击  »

关闭窗口