作者:Uni,Annchain核心开发成员。英国计算机专业海归硕士,曾担任金融机构区块链技术研究员,发表多篇技术文章。对区块链共识,P2P网络,底层存储处理等有较深入研究。现annchain核心开发人员,主要负责交易核心处理逻辑及数据存储模块。
(本文一切著作权归annchain技术团队所有,未经许可,不得转载。若需转载请联系页尾二维码。)
上次我们讲到 StateDB 和 Trie 的基本结构,这篇将重点关注两者在以太坊中是如何运用的。
整体结构
在以太坊中,数据的最上层就是上图中的StateDB。StateDB负责将数据做最初步的记录。往下一层是
Trie层,Trie负责将所有数据结构化,方便后续的存储查询回滚等操作。Trie分两种,State Trie和
Storage Trie。前者是世界状态树,记录了了所有账号的余额nonce等基本信息。后者用于记录各种合
约数据。世界状态树只有一棵,合约状态树有很多棵,因为每个合约都有棵属于自己的合约状态树。
Trie再往后就是TrieDB,TrieDB将Trie中的节点序列列化后存储在内存中。TrieDB的主要作用是做为最终
插入硬盘数据之前的缓存层。整个结构中最后一环就是最终硬盘上的数据库。
StateDB
以太坊中,StateDB的主要数据结构是StateObject。每个StateObject代表一个地址的状态。在
StateObject中主要有两个结构,data 和 dirtyStorage。data 用于存储账号的基本信息如余额
nonce等,dirtyStorage用于存储该账号地址下的合约的数据。具体实现可以参考以太坊 core/state/ 目录下的 state_object.go 文件。
状态更更新流程
1.当收到一个区块时,以太坊会根据区块内body的内容逐条执行里面的交易。在执行过程中,会确认此交易是否调用合约。
2. 如果是合约相关的交易易,则创建一个新的EVM对象并根据交易易中Data字段的执行码执行行约。
3. 执行期间所有的合约状态更改都会记录到合约的StateObject 的 dirtyStorage 中。
4. 执行完成后更新 From,To 俩地址的 StateObject 的 data 字段。主要更新 Balance 和 Nonce。
到第四步执行完,所有此交易相关的状态更改就都记录到 StateDB 中了了。之后在所有的区块交易都执行
完后,StateDB就保存了了此区块造成的所有状态更新。
执行完所有区块交易后,程序会调用 StateDB.Commit() 方法,将StateDB中的脏状态更更新到Trie上:
func (s *StateDB) Commit(deleteEmptyObjects bool) (root common.Hash, err
error) {
for 每个被更更改过的stateObject {
// 将此object中的dirtyStorage更更新到对应的StorageTrie上,并把更更新后
StorageTrie的 root 更更新到此object中data字段的root字段上。
stateObject.commitTrie()
// 将最终的object更更新到世界状态树上。
s.updateStateObject(stateObject)
}
// 这个for循环结束后,所有的trie就已经得到了了更更新。下⼀一步就是调⽤用trie.Commit()将 trie
中的节点映射到 TrieDB 上
s.trie.Commit()
}
需要注意的是,trie 更更新并不不会从0开始重新构建一个新的trie。因为trie的数据结构特点只需要将更更改
路路径上的节点更更新即可。如下图所示:
左边是原来的trie,右边是更更新后的trie。假设新的数据不不涉及节点2和节点4,那么只需要在更更节点中将
其中一个叶子节点设置成节点2即可。同时原来的trie中不被继续使用的节点不不会被删掉,⽽而是继续存在
db中,⽅方便便后续回滚操作。
通过调用 trie.Commit() 将新产生的映射到 TrieDB 的过程中,首先会将新的节点转化成cachedNode。
在我们的例子中,就是节点 1,3,5,6,7。cachedNode 存储了了节点的本体以及它的叶子节点
hash,用于最终落盘时的序列列化。此处具体可以参考以太坊 trie ⽬目录下的 database.go 文件。
StateDB.Commit() 完成后,程序会执行最后的落盘步骤,将 TrieDB 中的脏节点写入磁盘数据库中:
这⼀一步就是调用 TrieDB.Commit() ,将所有的脏节点(1,3,5,6,7)序列列化成 []byte 结构,然后用hash做为 key,[]byte 结构做为 value,存储到最终的磁盘数据中。到这一步落盘步骤完成后,整个状态数据的更新就算完成了。
回滚
data 字段保存账户的余额,Nonce等信息。同时,在后续落盘 MPT 的过程中,主要存储的内容就是经过编码序列化后的 data 字段
我们前面提到过,更更新trie结构时,旧trie中的不不需要的节点并不不会被从db中删除。所以在回滚时,我们只需要知道要回滚到的状态树的根节点,然后从磁盘数据库中以此跟节点会源头,重新加载出这个跟节点对应的整棵树就可以还原出当时的状态了。在以太坊中,这个跟节点的hash都会存在每个区块的header中,所以假设我们要回滚到区块高度为 n 的状态,那么只需要读取出区块 n 的 header 中的root hash,然后可以用这个hash为源头从数据库还原整棵树。
Annchain是由众安科技、众安-复旦区块链与信息安全联合实验室研发, 支持智能合约的高性能通用区块链协议。作为工信部指导的中国区块链技术和产业发展论坛两大开源项目之一,Annchain立足于中国,致力于助力中国抢占区块链全球话语权。
Annchain专注于解决扩展性、去中心化、安全三者平衡问题,做通用的分布式应用计算平台。目前已在数十家生态伙伴的商业场景中落地,场景涵盖农业溯源、珠宝溯源、资产通证化、公益、数据开放计算、广告分发平台和供应链金融等,开发者可基于Annchain高效构建适合自身的区块链应用。
Annchain当前包含两个子项目Annchain.Genesis和Annchain.OG。
Annchain.Genesis作为基于链表式结构的第一代区块链基础协议,其主要特征是模块化、高可靠、易用,支持多种智能合约引擎,开发者可根据具体业务需求选用共识与合约引擎,达到企业级使用需求。
Annchain.OG作为基于DAG账本结构的第二代区块链基础协议,其拥有DAG高效,强扩展特点的同时,又通过基于贡献的多维共识解决其安全可靠问题,同时Annchain.OG支持多种智能合约引擎及计算引擎,具有了更强计算和存储能力。
众安科技
众安信息技术服务有限公司(简称“众安科技”)成立于2016年11月2日,是由蚂蚁金服、腾讯、中国平安发起设立的众安保险旗下的全资科技子公司,专注于区块链、人工智能、密码学、物联网等前沿技术研究。众安科技汇聚了行业内的顶尖科研人才,其中区块链团队规模近200人,多数来自于各顶尖区块链团队。
众安-复旦区块链与信息安全联合实验室
众安-复旦区块链与信息安全联合实验室是国内首个高校与企业联合组建的区块链与信息安全实验室,专注于区块链核心技术研究,探索应用落地。
上海市区块链工程技术研究中心
上海市区块链工程技术研究中心由科委主导,依托复旦大学,联合众安在线财产保险股份有限公司,上海众人信息技术有限公司共同设立。专注分布式账本前沿共性技术与成果转化研究,推动工程落地。
更多关于Annchain:
官网: www.annchain.io
Github: http://Github: github.com/annchain
Facebook: https://www.facebook.com/Annchain-295110641341258
扫码备注昵称+研发方向
加入annchain技术社群