以太坊state模块分析
条评论前言
正如以太坊官方黄皮书所描述的一样:以太坊是一个巨大的状态机,每次交易的执行、区块的产生都是状态的迁移变化。
本文就将围绕以太坊的state模块进行讨论以太坊状态的变化。
关于以太坊中的“状态”
状态的定义
一个账户对应一个状态,而以太坊是所有状态的集合。
比如,最开始的状态是:{A有10元,B有0元},后来A发起了交易,给B2元,状态变成{A有8元,B有2元},这中间的过程就是状态转移。
在以太坊中,从创世状态开始,每次执行block的交易后,状态被修改成最新的的最终状态,在任何时刻这个最终状态都代表着以太坊当前的最新状态。
状态转换示意如下图:

状态的表示
以太坊中用root来表示某一时刻的状态。
以太坊使用Trie组织状态,Trie可以理解为是字典树和默克尔树的结合,它有一个树根root,有这个root,你就可以访问所有的状态数据,即每个账户的信息,所以用root来表示一个状态。
状态存在哪
状态不存在区块中。区块头中存放了root,这只是一个地址,从区块中并不能找到状态的数据。
每一个新的区块都关联以前的区块信息。
状态只是临时的数据,可以再生成。创世块是最初的状态,把第一个区块中的交易都执行一遍,就得到了一个新的状态,把这个状态的root存到第一个区块头的Root中。如果有所有的区块,就可以把所有的交易都执行,然后生成最新区块中的状态。
状态存放在外部数据库。以太坊底层的数据库是LevelDB(k-v),区块存放在里面,状态也存放在里面。但状态是一个Trie,不能直接存在LevelDB里面。
状态的转变
从不同的角度看,以太坊的状态分为交易级别的状态转换和区块级别的状态转换。
图片来源:以太坊状态转换流程分析


关于以太坊存储的设计
以太坊存储模块的架构图:

state所在的目录是:core/state,它的文件和每个文件的主要功能如下:
1 | core/state |
我们先介绍它的设计思路,然后再介绍一些它的骨干实现。
stateObject.go
stateObject代表最小粒度的状态,它是一个账户的状态信息。
1 | // 帐户的结构 |
stateObject保存了2个重要信息:
- 账户的信息:Account、Address、Code。创建账户之后,这些数据就不变了。
- 账户的数据:trie。对于合约账户,trie用来存储数据,因此trie是经常变化的。比如,有新的转账交易,就有新的数据(余额)产生和改变,trie也就发生改变。
database.go
statedb.go
- 存储所有的账户信息(stateObject)。
- 提供增删、修改账户的状态数据(stateObject)的接口。
- Finalise和提交修改的账户信息(stateObject)。
- 对每个状态数据改变记录日志,创建快照,实现回滚。
文章作者:米兰
原始链接:https://blog.milanchen.site/posts/ethereum-state.html
版权声明:转载请声明出处