以太坊交易、gas、EVM

2022.2.20

主要内容

交易详解,EVM简介

交易与gas

交易的本质

• 交易是由外部拥有的账户发起的签名消息,由以太坊网络传输,并被 序列化后记录在以太坊区块链上。

• 交易是唯一可以触发状态更改或导致合约在EVM中执行的事物。

• 以太坊是一个全局单例状态机,交易是唯一可以改变其状态的东西。

• 合约不是自己运行的,以太坊也不会“在后台”运行。以太坊上的一 切变化都始于交易。

交易数据结构

交易是包含以下数据的序列化二进制消息:

交易中的nonce

并发和nonce

• 以太坊是一个允许操作(节点,客户端,DApps)并发的系统,但强制执行单例状态。例如,出块的时候只有一个系统状态。

• 假如我们有多个独立的钱包应用或客户端,比如 MetaMask和Geth,它们可以使用相同的地址生成交易。如果我们希望它们都够同时发送交易,该 怎么设置交易的nonce呢?

• 用一台服务器为各个应用分配nonce,先来先服务——可能出现单点故障,并且失败的交易会将后续交易阻塞。

• 生成交易后不分配nonce,也不签名,而是把它放入一个队列等待。另起一个节点跟踪nonce并签名交易。同样会有单点故障的可能,而且跟踪nonce和签名的节点是无法实现真正并发的。

交易中的gas

• 当由于交易或消息触发 EVM 运行时,每个指令都会在网络的每个节点上执行。这具有成本:对于每个执行的操作,都存在固定的成本,我们把这个成本用一定量的 gas 表示。

• gas是交易发起人需要为EVM上的每项操作支付的成本名称。发起交易时,我们需要从执行代码的矿工那里用以太币购买gas。

• gas 与消耗的系统资源对应,这是具有自然成本的。因此在设计上 gas 和 ether 有意地解耦,消耗的 gas 数量代表了对资源的占用,而对应的交易费用则还跟 gas 对以太的单价有关。这两者是由自由市场调节的:gas 的价格实际上是由矿工决定的,他们可以拒绝处理 gas 价格低于最低限额的交易。我们不需要专门购买 gas ,只需将以太币添加到帐户即可,客户端在 发送交易时会自动用以太币购买汽油。而以太币本身的价格通常由于市场力量而波动。

gas的计算

交易的接收者(to)

• 交易接收者在to字段中指定,是一个20字节的以太坊地址。地址可以是EOA或合约地址。

• 以太坊没有进一步的验证,任何20字节的值都被认为是有效的。如果20字节值对应于没有相应私钥的地址,或不存在的合约,则该交易仍然有效。以太坊无法知道地址是否是从公钥正确派生的。

• 如果将交易发送到无效地址,将销毁发送的以太,使其永远无法访问。

• 验证接收人地址是否有效的工作,应该在用户界面一层完成。

交易的 value 和 data

向 EOA 或合约传递 data

特殊交易:创建(部署)合约

EVM以太坊虚拟机

以太坊虚拟机(EVM)

EVM和账户

• 以太坊中有两类账户: 外部账户和合约账户,它们共用EVM中同一个地址空间

• 无论帐户是否存储代码,这两类账户对 EVM 来说处理方式是完全一样的

• 每个账户在EVM中都有一个键值对形式的持久化存储。其中 key 和 value 的长度都是256位,称之为存储空间 (storage)

EVM和交易

• 交易可以看作是从一个帐户发送到另一个帐户的消息,它可以包含二进制数据(payload)和以太币

如果目标账户含有代码,此代码会在EVM中执行,并以 payload 作为入参,这就是合约的调用

如果目标账户是零账户(账户地址为 0 ),此交易就将创建一个新合约 ,这个用来创建合约的交易的 payload 会被转换为 EVM字节码并执行,执行的输出作为合约代码永久存储

EVM和gas

EVM数据存储

EVM指令集

消息调用( Message Calls )

• 合约可以通过消息调用的方式来调用其它合约或者发送以太币到非合约账户

• 合约可以决定在其内部的消息调用中,对于剩余的 gas ,应发送和保留多少

• 如果在内部消息调用时发生了 out-of-gas 异常(或其他任何异常),这将由一个被压入栈顶的错误值所指明;此时只有与该内部消息调用一起发送的 gas 会被消耗掉

委托调用(Delegatecall)

• 一种特殊类型的消息调用

• 目标地址的代码将在发起调用的合约的上下文中执行,并且 msg.sender 和 msg.value 不变

• 可以由此实现“库”(library):可复用的代码库可以放在一个合约的存储上,通过委托调用引入相应代码

合约的创建和自毁

• 通过一个特殊的消息调用 create calls合约可以创建其他合约(不是简单的调用零地址)

• 合约代码从区块链上移除的唯一方式是合约在合约地址上的执行自毁操作 selfdestruct ;合约账户上剩余的以太币会发送给指定的目标,然后其存储和代码从状态中被移除