在以太坊黄皮书学习笔记系列的前两篇中,我们探讨了以太坊的基本模型、账户体系以及交易的核心概念,我们将深入到以太坊的“心脏”——区块(Block)以及驱动整个网络状态变化的引擎——状态转换函数(State Transition Function, Δ),理解这两者,是掌握以太坊如何实现去中心化账本和智能合约执行的关键。
区块:以太坊的“账本页”
如果说以太坊的状态是一个不断变化的数据库,那么每一个区块就是这个数据库的一页“账本”,它记录了特定时间段内发生的所有交易,并包含了前一个区块的“指纹”,从而形成了不可篡改的链式结构。
黄皮书(Ethereum Yellow Paper, v4)中对区块的定义是一个递归的数据结构,核心由以下几个部分组成:
-
parentHash(父区块哈希):- 作用:这是区块的“锚点”,它指向了当前区块的前一个区块的哈希值,正是这个简单的指针,将一个个独立的区块链接起来,形成了“区块链”,网络中的所有节点都通过验证
parentHash来确保它们遵循的是同一条最长的有效链。
- 作用:这是区块的“锚点”,它指向了当前区块的前一个区块的哈希值,正是这个简单的指针,将一个个独立的区块链接起来,形成了“区块链”,网络中的所有节点都通过验证
-
number(区块号):- 作用:一个从0开始的整数,代表了区块在链中的位置,创世区块(Genesis Block)的
number为0,每个后续区块的number都比其父区块大1,区块号是确定区块“新旧”和“高度”的直接依据。
- 作用:一个从0开始的整数,代表了区块在链中的位置,创世区块(Genesis Block)的
-
stateRoot(状态根哈希):- 作用:这是整个区块中最重要的字段之一,它不是交易或区块数据的哈希,而是执行完该区块内所有交易后,整个世界状态(World State)的Merkle Patricia Trie根哈希。
- 意义:
stateRoot为以太坊的状态提供了一个简洁的、防篡改的“快照”,节点不需要下载整个世界状态数据库,只需验证stateRoot,就能高效地确认某个区块执行完毕后,系统状态是否正确,这是以太坊实现状态同步和轻客户端(Light Clients)的基础。
-
transactionsRoot(交易列表根哈希):- 作用:该区块包含的所有交易经过哈希后,构建成一个Merkle Patricia Trie,其根哈希值就是
transactionsRoot,任何一笔交易是否存在、是否被篡改,都可以通过这个根哈希高效地验证。
- 作用:该区块包含的所有交易经过哈希后,构建成一个Merkle Patricia Trie,其根哈希值就是
-
**receiptsRoot(收据根哈希)**:- 作用:与
transactionsRoot类似,它记录了该区块内每一笔交易执行后产生的收据的Merkle Patricia Trie根哈希,收据包含了交易执行的结果,例如是否成功、消耗了多少Gas、日志输出等,这对于DApp开发者查询历史交易状态至关重要。
- 作用:与
-
bloom(布隆过滤器):- 作用:一个位图数据结构,用于高效地判断某个地址或主题是否出现在该区块的日志中,虽然它有一定概率的误报,但能快速筛选出可能相关的日志,极大地提高了日志查询的效率。
-
timestamp(时间戳):- 作用:记录区块被创建的大致时间戳,它用于防止“时间戳攻击”,并确保区块的生成速度大致符合预期。
-
extraData(附加数据):- 作用:一个可变长的字段,矿工可以写入任意数据,它通常用于写入矿池信息、预留数据或进行其他实验性用途。
-
gasLimit(Gas限制):- 作用:设定了本区块内所有交易消耗的Gas总量上限,这是以太坊防止单个区块过大或执行恶意代码导致网络拥堵的关键机制。
-
gasUsed(已用Gas):- 作用:记录本区块内所有交易实际消耗的Gas总量。
gasUsed必须小于或等于gasLimit。
- 作用:记录本区块内所有交易实际消耗的Gas总量。
-
difficulty(难度):- 作用:在工作量证明机制下,这个值决定了寻找有效区块头的哈希所需的计算难度,网络会根据出块时间动态调整难度,以维持出块时间的稳定。
-
mixHash与nonce(谜题解):- 作用:这两个值是矿工通过大量计算(哈希运算)找到的“谜底”,用于证明矿工完成了相应难度的计算工作,从而获得出块权。
区块不仅仅是交易的容器,它更是一个包含了执行结果、状态快照和网络共识信息的完整数据单元。stateRoot、transactionsRoot和receiptsRoot这三个根哈希,构成了区块的“三重校验机制”,确保了数据的一致性和可验证性。
状态转换函数 Δ:以太坊的“状态机引擎”
如果说区块是账本,那么状态转换函数 Δ 就是驱动账本不断翻页、内容不断更新的“引擎”,它是一个数学函数,定义了给定一个前一个状态 S 和一笔有效的交易 T,如何计算出新的状态 S'。
其核心定义可以表示为: S' = Δ(S, T)
这个函数的执行过程,就是以太坊虚拟机的工作流程,让我们一步步分解它:
-
初始化:
- 从当前区块的
parentHash找到其父区块。 - 从父区块中读取
stateRoot,加载出完整的世界状态S,如果节点是同步的,S就是最新的状态。
- 从当前区块的
-
交易预处理:
- 从区块的交易列表中取出下一笔交易
T。 - 验证交易签名:确保交易发起者(
sender)的私钥确实签署了该交易。 - 检查Nonce:验证交易的
nonce值是否与发送方账户在状态S中的nonce值完全匹配,这是防止交易重放攻击的关键。 - 检查Gas:确保发送方账户有足够的ETH来支付交易费(
gasPrice * gasLimit)以及执行交易所需的Gas。
- 从区块的交易列表中取出下一笔交易
-
执行交易(EVM核心):
