如果发送方没有提供这笔交易足够的gas,那么这笔交易会由于“out of gas”而失效。出现这种情况,这笔交易会被中止,以一条失败的记录记录在以太坊中,同时所有的状态都会回滚到交易开始之前的初始状态。而且由于在“out of gas”前已经投入了计算资源,按理来说,gas已经被消耗了,不会被退还给发送方。
你可能会好奇,gas这笔钱跑到哪里去了呢?答案是这笔钱会被发送到矿工地址上去。因为这笔交易是由矿工们参与了计算,从而验证了交易的合法性。所以gas应该奖励给矿工们。
通常来说,如果发送方付出更高的gas,那么矿工们因为能得到更高的奖励,所以会优选选择验证这笔交易。如果gas费用太低,矿工也可能会主动忽视这笔交易。为了指导发送方设置一个合理的gas价格,矿工们可以选择公布他们将执行交易的最低gas价格。
存储费用
gas并不仅仅是上文提到的,只会在交易计算时消耗,它同时也用于支付存储费用。存储的总费用与使用的 32 字节的最小倍数成正比。
存储费用的计算有较多的细节。比如,增加的存储空间会同时增加以太坊上所有的节点的存储空间,所以努力保持更小的存储空间是更有利的。由于这个原因,如果一个交易有着释放存储空间的操作,那么执行这个操作的计算费用将会被免除,这笔计算将退还并释放存储控件。
费用的作用是什么?
我们知道,在以太坊网络中任何一个交易的执行都会同时影响所有的节点。然而,在EVM上的计算成本是十分高的。所以,以太坊的智能合约理应用来执行一些简单的工作,例如运行一个简单的业务逻辑、验证签名或者其他加密场景,而不应该用来执行像是存储数据、发送邮件,或者是机器学习这样的可能会花费巨大的计算资源,让整个以太坊网络超负荷的工作。费用就是因为这个原因而被设计出来的。
以太坊是一个图灵完备的区块链,要知道一个图灵机是无法判断一段代码是否最终会结束。但是在以太坊中运行的智能合约又能够执行循环操作,所以如果计算没有费用的话,智能合约的开发者可能会写出一个无限循环的代码段,这会拖垮整个以太坊网络。因此,费用的设计能够保证整个网络不会陷入这样的恶意攻击。
您可能还会想:“为什么我们还要为存储付费呢?”。其实就像计算一样,以太坊网络上的存储也是整个网络必须承担的成本。
交易和消息
上文有提到,以太坊是一个基于交易的状态机。在不同账户之间发生交易后,整个以太坊网络会从一个状态转移到另一个状态。
交易本质上是外部账户生成的一条加密签名指令,这条指令序列化后然后提交到区块链。
交易分为两类:消息调用和合约创建。
这两类交易由以下字段组成:
- nonce:发件人发送的交易数量
- gasPrice:发送方想要执行这笔交易,愿意付出的每单位gas价格
- gasLimit:发送方愿意为执行此交易支付的最大 gas 量。 该金额需要在交易执行前预先设定并支付
- to:接收方的地址。在合约创建类型的交易中,合约账户地址还没有生成,这个时候这个字段为空值
- value:发送方项接收方发送的以太币数量(单位Wei)。在合约创建类型的交易中,这个值是新合约地址的余额值。
- v,r,s:用于生成标识交易发送方的签名
- init(仅存在于创建合约的交易中):用于初始化新合约账户的 EVM 代码片段。 init 只运行一次,然后被丢弃。 首次运行 init 时,它会返回账户代码的主体,这是与合约账户永久关联的一段代码
- data(仅存在于消息调用的可选字段):消息调用的输入数据(即参数)。 例如,如果智能合约用作域注册服务,则对该合约的调用可能需要输入字段,例如域名和 IP 地址。
我们在上面“账户”章节了解到,交易 始终是由外部账户发起并提交到区块链,消息调用和合约创建这两个交易分类都是如此。 我们可以说,交易是外部世界与以太坊内部状态的桥梁。