在前两篇笔记中,我们梳理了以太坊的状态世界模型和账户系统,了解了以太坊如何像一个分布式的全球计算机,维护着一个不断变化的共享状态数据库,这个“全球计算机”究竟是如何执行指令、改变状态的呢?答案就在于以太坊的执行引擎——以太坊虚拟机,本篇笔记,我们将深入黄皮书(Yellow Paper)的第9章,详细解析EVM的执行模型,这是理解以太坊智能合约运行机制的核心。
EVM执行模型:一个基于栈的抽象计算机
从本质上讲,EVM是一个基于栈的、图灵完备的虚拟机,这个描述包含了几个关键概念:
- 图灵完备:意味着EVM可以执行任何可计算的算法,只要给予足够的时间和资源,这也带来了“停机问题”——我们无法预先判断一个智能合约是否会无限循环,因此需要引入Gas机制来防止合约消耗无限的计算资源。
- 基于栈:与大家更熟悉的基于寄存器(如x86架构)或基于累加器(如MIPS架构)的处理器不同,EVM的所有计算操作都发生在一个栈上,栈是一种后进先出的数据结构,就像一摞盘子,最后放上去的盘子最先被取走,EVM的栈深度被限制为1024层,以防止栈溢出攻击。
EVM的执行模型,就是一条指令接一条指令地执行,每一条指令都会根据当前的状态和栈的内容,改变栈的状态、内存的状态,并最终可能改变以太坊的全球状态。
执行的“燃料”:Gas机制
在深入指令集之前,我们必须理解贯穿整个EVM执行的灵魂——Gas。
Gas是以太坊网络中衡量计算、存储和带宽资源消耗的单位,每一笔交易发送时,发送者都需要设定一个Gas Limit( gas限制)和愿意支付的Gas Price( gas价格),Gas Limit是交易愿意消耗的最大Gas数量,而Gas Price是每个Gas单位的价格。
执行过程如下:
- Gas预支付:交易执行前,发送者账户会被扣除
Gas Limit * Gas Price的以太币,作为“预付款”。 - Gas消耗:EVM在执行每一条指令时,都会根据操作的复杂度消耗一定量的Gas,简单的加法消耗很少Gas,而写入存储或进行大量循环则会消耗大量Gas。
- Gas退款:某些操作,比如从合约中删除一个存储变量,会返还一部分Gas,这鼓励开发者清理不再需要的数据。

- 结算:
- 交易成功:所有剩余的Gas(
Gas Limit - 已消耗Gas)会按原价退还给发送者,成功执行的操作费(已消耗Gas * Gas Price)会作为矿工费(手续费)支付给打包该交易的矿工。 - 交易失败:如果在执行过程中Gas耗尽(Out of Gas),所有状态回滚到交易执行前的快照,但已消耗的Gas不会退还,这是对发送者发起无效计算的一种惩罚。
- 交易成功:所有剩余的Gas(
Gas机制确保了网络的安全性,防止了恶意合约(如无限循环)对网络造成拒绝服务攻击。
执行环境:一个结构化的上下文
EVM的执行并非在真空中进行,而是在一个精心设计的执行环境中,黄皮书用结构体 ExecutionEnvironment 定义了这个上下文,它包含了执行当前代码所需的所有信息,主要包括:
caller:调用者的地址,即发起交易的账户地址。value:随交易发送的以太币数量(以Wei为单位)。address:当前正在执行的合约的地址。code:当前正在执行的合约的字节码。data:伴随交易或调用传入的数据(Calldata)。gasprice:交易设定的Gas Price。origin:交易的原始发起者地址,用于权限控制。block相关字段:如当前区块号、时间戳、难度、Gas Limit、Coinbase(矿工地址)等,这使得智能合约能够与区块链的当前状态进行交互。
这个执行环境为每一条指令的执行提供了必要的上下文,是连接全局状态和局部计算的桥梁。
状态转换函数:从理论到实践
黄皮书中最核心、最令人望而生畏的部分之一,就是状态转换函数 S,它是一个数学化的函数,形式化地定义了从一个状态 到下一个状态 的完整过程。
σ' = S(σ, t)
t 代表一笔交易,这个函数的内部逻辑,就是EVM的执行模型,我们可以将其分解为以下几个步骤(黄皮书中的算法96):
- 初始化:从交易
t中提取caller,value,data,gasLimit等信息,验证发送者账户的 nonce 和余额。 - 创建执行环境:根据交易和当前区块信息,构建
ExecutionEnvironment结构体。 - 执行代码:这是核心循环,EVM从
code的起始位置开始,逐条执行指令:- 取指:从程序计数器指向的内存地址读取下一条指令。
- 译码与执行:根据指令的操作码,执行相应的操作。
ADD指令会从栈中弹出两个值,相加后压回栈;SLOAD指令会从存储中读取一个值并压入栈;CALL指令则会发起一次子调用。 - 修改状态:指令的执行会改变栈、内存或全局状态,每一步操作都会消耗相应的Gas。
- 处理子调用:当遇到
CALL,DELEGATECALL,CREATE等指令时,EVM会递归地创建一个新的执行环境,开始一次新的、嵌套的执行过程,这构成了以太坊强大的组合能力。 - 结算:代码执行完毕或因异常终止。
- 如果所有代码成功执行,更新所有相关账户的 nonce、余额和状态。
- 如果执行失败(如Gas耗尽、断言失败),回滚所有由该交易产生的状态变更,但Gas费用照常扣除。
这个严谨的函数定义,确保了以太坊的状态转换是确定性和可验证的,任何一个节点,只要输入相同的初始状态和交易序列,都会通过执行这个函数得到完全相同的最终状态。
总结与思考
通过学习黄皮书对EVM执行模型的描述,我们可以清晰地看到以太坊的设计哲学:
- 简洁而强大:一个基于栈的虚拟机,配合一套精心设计的指令集,以最小的复杂度实现了图灵完备的计算能力。
- 安全至上:Gas机制是整个系统的安全基石,它将无限的抽象计算限制在有限的、可计量的资源消耗之内。
- 形式化严谨:状态转换函数
S的存在,为以太坊的确定性提供了坚实的数学证明,这是其作为“世界计算机”可信度的根本保障。
理解EVM的执行模型,是从“会用”智能合约到“看懂”智能合约的关键一步,它不仅让我们明白一笔交易背后究竟发生了什么,也为我们未来深入研究智能合约安全、优化Gas消耗以及开发区块链上层应用打下了坚实的理论基础,下一章,我们将继续探索EVM的指令集,看看这些强大的原子操作是如何组合成复杂应用的。