【以太坊源码】3.Block结构

区块(Block)是以太坊的核心数据结构之一,一个个Block通过链表的形式相互关联起来,构建起了整个区块链系统,这也是区块链的名字由来。

上面是以太坊中Block结构体及其相关的UML图例

Block中主要字段的含义如下:

header:block的header指向的是一个的结构体,其中带有该block的所有属性信息

uncles:一个包含该block的叔块block的数组。叔块指的是在某些节点高度上,可能会有多个矿工挖出该高度上的区块,比特币由于平均出块时间间隔在10分钟左右,出现叔块的概率比较小,所以当初比特币的设定是叔块不会获得任何奖励,做的都是无用功。而以太坊为了将出块时间缩短到10秒,产生叔块的概率就会比较高,如果很多矿工由于生产了叔块而无法获得奖励,矿工挖矿的积极性就会受到打击。所以在以太坊的block中可以将叔块信息打包进去,生产叔块的矿工以及打包该叔块信息的矿工都将获得奖励。该数组最多包含2个叔块的header信息。

transactions:该block中包含的交易列表,Transactions是一个`Transaction`结构的数组。在以太坊中,转账、创建智能合约、调用智能合约这些都称作交易(transaction)。后面会分析`Transaction`结构的内容。

hash:该block的hash值。对header进行rlp编码后计算其Keccak256(即SHA3)得到的一个hash值。

td:total difficulty,当前区块总共的难度值=前一个区块的td+当前区块header中的difficulty。

Block的Header定义:

ParentHash:该block的父区块hash值。通过这种前向指针的方式将一个个block关联起来成为一个BlockChain。

UncleHash:该block的叔区块hash值。对前面block中的uncles进行rlp编码后计算其Keccak256得到的hash值。

Coinbase:矿工的账户地址。挖出来该区块后,将奖励的eth打给该账户名下。

Root:表示stateRoot的hash值。执行区块中的交易后,账户余额以及账户中的智能合约等会产生变动,在以太坊中账户相关的内容是通过MPT树组织在一起,称为状态树,该状态树会有一个根节点,这里的Root指的就是这个根节点的hash值。MPT树的结构请参考MPT的章节。

TxHash:表示transactionsRoot的hash值。将该block中所包含的transactions交易列表组织在一起成为一棵交易树,TxHash指的是该交易树的根节点hash值。交易树叶为1棵MPT树,与上面的状态树有所不同的是,交易树的数据来源是来自transactions这个数组,每个block的交易树是独立存在的,不会像状态树那样前后存在联系。因为MPT树是用来存储key-value形式的数据,而如何把一个transactions数组当做key-value来保存在MPT树中呢?其实代码中是把该数组中每个元素的索引作为key。

ReceiptHash:表示交易收据树的hash值。在执行一个Transaction后会得到一个Receipt交易收据,Receipt中包含了该交易的执行结果等信息。将该block中包含的transactions都执行完毕后将得到一组Receipt列表,把这些交易收据组织在一起成为一棵收据树,ReceiptHash指的是该收据树的根节点hash值。收据树具体的表现形式与上面的交易树类似。

Bloom:布隆过滤器。通过该过滤器可以快速查找你查询的信息是否在该block上。

Difficulty:该block的Difficulty值。从创世节点开始到该区块可以累积计算一个total difficulty值,在某个节点出现分支的时候,以太坊会选择total difficulty最大的那条链做为主链,不在该条链上的区块即为叔块。

Number:区块编号。创世区块的number为0,后续区块的编号在其父区块的编号基础上加1。

GasLimit:该区块所能消耗的gas上限。

GasUsed:该区块实际消耗的gas总量。

Time:区块的时间戳。

Extra:该区块的附加数据。如DAO分叉等信息。

MixDigestNonce:这两个值用来验证矿工挖矿,证明此区块是否已经执行足够多的计算工作。Nonce是一个64-bit的值。

从上面的Block及其Header的定义,可以对以太坊中的区块有一个总体的认识,在这里可以总结一下:

Block包含一组transactions。一个transaction可以是一次转账或者是创建合约等操作。

Block可以将其叔块打包进来,这样生产叔块和打包叔块的矿工都将获得额外的奖励。

Block中的Header信息包括:父区块hash、叔块uncles的rlp编码hash值、矿工账户地址、三棵树(状态树/交易树/收据树)的rootHash值、Bloom过滤器、difficulty值、number区块编号、gasLimit以及gasUsed、用于验证挖矿的mixDigest和nonce、time时间戳。以太坊中的轻节点只需要通过header中的这些信息即可来验证交易是否在区块链上,而全节点则保存交易详情数据来提供更多的接口。

Header中的状态树记录着以太坊中所有账户的当前状态。所有账户以MPT的形式组织在一起,通过该树的root可查找到当前区块下某个账户的余额等信息。

Header中的交易树保存着当前block中所包含的交易,通过该交易树的root可以查找到当前block中的交易信息。

收据树保存了交易完成后的收据信息。

Bloom过滤器用于快速查找交易是否在该block中。

每个block都会根据其父区块计算一个difficulty值,从创世区块开始可以累积一个当前区块的total difficulty,以太坊会选择total difficulty最大的那条链作为主链。

每个block有一个number编号,值是其父区块的number+1。

Header中的MixDigest和Nonce用于验证矿工挖矿。

Transaction

Block除了Header外,还有另外一个很重要的属性就是Transactions,而Transactions从源码中可以看到被定义为Transaction的数据,Transaction的定义见以上UML或者直接看下面的代码。

从上面的定义可以看到,Transaction中的信息都在txdata这个结构体中,其他的几个属性hash、size以及from只是为了避免重复计算,用来缓存该交易经常用到的一些信息,hash是这个交易的rlpHash值,size是这笔交易经过rlp编码后所占用的存储空间大小,from指的是该笔交易的发起者。下面就来看一下txdata中包含哪些内容。

AccountNonce:该nonce值表示在执行该transaction时,这笔交易的发起者账户中的nonce值。在执行交易时会校验这个。AccountNonce是否与发起者账户的nonce值相同。nonce值具体含义指的是该账户下发起交易的次数(当该账户为外部账户时),或者是该账户下智能合约的数量(当该账户为合约账户时),参见`stateObject`。

Price:gasPrice,表示发起交易的gas价格,价格越高矿工就会优先打包来赚取更多的手续费。

GasLimit:该交易使用的gas数量上限。

Recipient:收款账户地址。当该地址为空时表示该笔交易为创建合约。

Amount:转账金额

Payload:合约代码或者输入参数

V、R、S:签名。从签名中可以恢复出结构中的from属性。

了解完前面以及这篇文章中的这些结构体后,下一篇会继续分析以太坊中交易的具体执行过程。

  • 发表于:
  • 原文链接:https://kuaibao.qq.com/s/20181102G0FIBI00?refer=cp_1026
  • 腾讯「云+社区」是腾讯内容开放平台帐号(企鹅号)传播渠道之一,根据《腾讯内容开放平台服务协议》转载发布内容。

同媒体快讯

扫码关注云+社区

领取腾讯云代金券