以太坊的数据结构

1 引言

区块链的技术基础是去中心化的数据共识,我们首先面临的问题以何种的形式去组织数据,实现一个分布式的数据库。本文对以太坊的实现机制,进行分析。
在这里插入图片描述

在常规的互联网应用中,用户数据和交易数据都存放在应用提供者的中心服务器上,通过IOE、MySQL集群等进行持久化的存储,当普通节点进行交易时,会向中心节点发出请求,中心节点进行各种增删改查的操作后,将结果返给用户节点。
在以太坊中并不存在中心服务器,取而代之的是多个通过p2p协议连接起来的平等节点,在众多节点中存储了所有的数据。当用户发起一笔交易,会通过p2p协议将交易广播出去,矿工节点对此进行验证、打包并进一步广播至全网,在区块链内确认后,此操作即认为是不可更改的。
在网络上关于区块链的文章中,都提到了分布式(distributed)和去中心化(decentralization)这两个词,有时候略有区别,有时侯又混用。笔者认为如果要精确区分的话,分布式强调系统的是多个组件通过发送消息协同工作,去中心化强调的是不存在一个中央节点控制整个系统的运行。因此我们认为以太坊兼具去中心化和分布式,或者说在一个分布式平台上运行了一个去中心化的程序

2 区块链(BlockChain)

在单个节点中,数据是以区块链(BlockChain)的形式来存储的。区块链由一个个串在一起的块(Block)组成。以太坊大概每十几秒会生成一个新块,记录了这个段时间内的各种信息。
以太坊被描述为为一个交易驱动的状态机,它在某个状态下接受一些输入后,会确定的转移到一个新的状态。具体来说,在一个以太坊的状态下,每个账户上有确定的余额和存储信息,当接收到一组交易,被影响账户上的余额和存储信息会发生变动。从第一个创世块开始,不断的收到交易,由此能进入一连串新的状态。
在这里插入图片描述

按照这个思路,以太坊每隔一段时间把交易数据和验证信息打包在一个块里,依次串接起来,就成为一个链。块越新,块号(BlockNumber,或叫块高度)便越大。
在这里插入图片描述

3 块(Block)

每个块包含块头和交易,其中块头的结构如下图所示。

在这里插入图片描述
几个关键字段的含义如下:

ParentHash:父块的哈希值
Number:块编号
Timestamp:块产生的时间戳
GasUsed:交易消耗的Gas
GasLimit:Gas限制
Difficulty:POW的难度值
Beneficiary:块打包手续费的受益人,也称矿工
Nonce:一个随机数,使得块头哈希满足POW需求
StateRoot:状态树的根哈希值
TransactionsRoot:交易树的根哈希值
ReceiptsRoot:收据树的根哈希值
每个矿工在把交易打包成块的时候,会组织三颗树:

  1. 交易树,树叶里是交易
  2. 收据树,树叶里是交易生成的收据
  3. 状态树,树叶里是交易影响到的账户状态

三棵树求取根哈希,可以得到区块头中的StateRoot,TransactionsRoot,ReceiptsRoot三个字段。这样就建立了交易和区块头字段的映射。当其他用户收到块,根据块里的交易可以计算出收据和状态,计算三个根哈希后和区块头的三个字段进行验证,判断这是否为合法的块。
在这里插入图片描述
其中交易树和收据树是Merkle树,如上图所示。状态树是Merkle Patricia Tree**???**
默克尔树所指向数据的任何改动都会引起节点哈希的变化。由于每一个父节点中所保存的哈希值都取决于子节点所包含的数据,所以子节点中数据的变更都会引起父节点哈希的变化。并且这样的影响是连锁反应,从叶子节点直达根节点的。因此对叶子节点所指向数据的改动会引起根节点所保存哈希的变化。由上述结构特征,我们可以引申出两条重要的属性:

  • 在判断两棵默克尔树所指向数据是否完全相同时,我们不需要比较每个叶子节点,而只需比较根节点所保存的哈希。
  • 在判断特定数据是否被树所指向时,我们可以使用 默克尔证明 技术。此处不对该技术作过多介绍,只需知道这是证明数据存在于默克尔树中的一种简单、高效的方法。

第一种属性的重要之处在于,我们能够仅利用根节点的哈希值,就标示某一时刻整棵树所指向的数据。这意味着仅通过保存根节点的哈希值就能标示区块(无需储存区块链中所有的数据),且维护数据的不可篡改。

至此我们理清了默克尔树中根节点哈希的作用,下面来介绍以太坊中的主要对象。

4 世界状态

在上文中我们提到,以太坊是基于状态的。多个账户的状态共同组成了以太坊的全局状态。世界状态可以被视作为随着交易的执行而持续更新的全局状态。以太坊就像一个去中心化的计算机,世界状态则是这台电脑的硬盘。账户分为两种:

  • 外部账户(Externally owned account),被私钥控制且没有任何代码与之关联。一个外部账户可以创建交易,来发送消息给另一个外部账户或合约账户,以此来触发转账交易和智能合约的调用、创建
  • 合约账户(Contract account),被它们的合约代码控制且有代码与之关联。合约账户不可以自己发起一个交易,只能被外部账户调用。
    在这里插入图片描述
    每个账户包含了以下的字段:
  • Balance:该账户的余额
  • Nonce:该账户为外部账户时候,表示该账户创建的交易序号,每做一次交易都会加1。该账户为合约账户时候,表示该账户创建的合约序号,每创建一次会加1。
  • CodeHash:该账户为合约账户时候,表示合约的哈希值,否则为空字符串的哈希
  • StorageRoot:该账户的存储内容组成Merkle树后求得的根哈希值,存储内容为智能合约相关内容

账户状态中不容忽视的一个细节是,上述对象在内的所有对象都可变(除了 codeHash)。举例来说,当一个账户向其他账户发送以太币时,除了 nonce 会增加,账户的余额也会相应改变。而 codeHash 的不可变性使得,如果部署了有漏洞的智能合约,也无法修复更新此合约。对应的,只能部署一个新合约(而有漏洞的版本会一直存在于区块链上)。这也是为什么使用 Truffle 进行智能合约的开发和部署十分必要,并且用 Solidity 编程时要遵循 最佳实践 的要求。

账户存储树是保存与账户相关联数据的结构。该项只有合约账户才有,而在 EOA 中, storageRoot 留空、 codeHash 则是一串空字符串的哈希值。所有智能合约的数据都以 32 字节映射的形式保存在账户存储树中。此处不再赘述账户状态树如何维持合约数据。如果读者对其内部实现感兴趣,强烈建议阅读这篇文章。账户状态中的 storageRoot 区域负责维持账户存储树根节点哈希值。在这里插入图片描述
多个块的MPT树共享了账户状态,子块状态树和父块状态树的差别在于它指向了在子区块中被改变了的账户。这样节省了总的存储空间,方便了块的回滚操作。
在这里插入图片描述

5 交易

交易推动当前状态到下一状态的转变。在以太坊中有三种交易:

  1. EOA 之间传输值的交易(例如,改变发送方和接收方余额大小)
  2. 发送消息来调用合约的交易(例如,通过发送消息调用来触发 setter 方法,以设置合约中的值)。
  3. 用于部署合约的交易(由此创建了合约账户)。

(从技术角度来讲,前两种交易是一样的…它们都是通过消息调用来改变账户状态的交易,只不过一个是 EOA 账户,一个是合约账户。此处将交易分为三种是为了方便读者的理解。)
交易由以下部分组成:

  • nonce: 此账户发出的交易序号数(校对注:可以粗略理解为“这是该账户的第几笔交易”)。
  • gasPrice: 执行此交易、进行计算时为每单位 gas 所支付的费用(以 Wei 计量)。
  • gasLimit: 执行此交易时可以使用的最大 gas 数量。
  • to: 如果此交易用于传送以太币,此处为接收以太币的 EOA 地址。如果此交易用于向合约发送消息(例如,调用智能合约中的方法),此处为合约的地址。如果此交易用于创建合约,此处值为空。
  • value: 如果此交易用于收发以太币,此处为接收账户以 Wei 计量的代币数量。如果此交易用于发送对合约的消息调用,此处为向接收此消息智能合约所给付的 Wei 数量。如果此交易用于创建合约,此处为合约初始化时账户存放的以 Wei 计量的以太币数量。
  • v, r, s: 在交易的密码学签名中用到的值,可以用于确定交易的发送方。
  • data:(只用于价值传输以及向智能合约发送消息调用)发送消息调用时附带的输入数据(例如,假设你想要执行智能合约中的 setter 方法,数据区就应该包括 setter 方法的标识符,以及你想要设定的参数值)。
  • init(只用于合约创建)用于初始化合约的 EVM 代码。

区块中所有的交易也是存储在默克尔树中的。并且这棵树的根节点哈希值由区块头保存。

6 收据

账户创建交易并向其它节点广播后,会被其它节点执行并放入准备打包的区块。在这个过程中会生成一个收据。收据的主要字段有:

blockHash: 交易所在块的哈希值
blockNumber: 交易在块的序号
transactionHash: 交易的哈希值
transactionIndex: 交易在块中的序号
from: 发送者地址
to: 接受者地址,为空时候表示创建合约
cumulativeGasUsed: 执行完此交易时候,块内消耗的总的gas值
gasUsed:本交易所消耗的gas
contractAddress: 当此交易为创建合约时,表示所创建合约的地址,否则为空
logs: 此交易的日志
需要注意的是,在不同的节点之间并不会发送状态和收据,后两者在可以通过交易计算得到。

最后用一张图来表示文中提及的各种概念信息。
在这里插入图片描述

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值