源代码解读 [EOS 源码分析] 20 - EOS 区块的数据结构 (上)

Admin · 2019年12月21日 · 122 次阅读
本帖已被设为精华帖!

EOS 源码分析系列文章,由技术作者松果撰写。为帮助更多开发者了解,特获授权转载至此。感谢松果兄支持。

img

上一篇文章介绍了默克尔树(Merkle Tree)以及比特币、以太坊、EOS的区块数据结构,说明了它们之间的共同点,这篇文章详细介绍EOS区块的数据结构。

EOS区块的数据结构

EOS区块的数据结构可以分为区块头(Block Header)交易列表(Transactions),交易列表中的每个交易又可以分为交易头(Transaction Header)Action列表(Actions),Action是EOS区块链的基本业务逻辑处理单元。

block_header

EOS区块的数据结构使用了继承关系,基类是block_header(区块头),定义在eos/libraries/chain/include/eosio/chain/block_header.hpp:

img

block_header各字段的含义如下:

1、timestamp(时间戳)

时间戳类型block_timestamp_type定义如下:

typedef block_timestamp<config::block_interval_ms,config::block_timestamp_epoch> block_timestamp_type;

block_timestamp是一个类模板:

template<uint16_t IntervalMs, uint64_t EpochMs>
class block_timestamp { //... }

模板参数的定义如下:

const static int      block_interval_ms = 500;
const static uint64_t block_timestamp_epoch = 946684800000ll; // epoch is year 2000.

可以看出,EOS的时间戳是从格林威治时间2000/1/1 0:0:0开始计算(注意这里只是计算方式,最终显示的时间戳仍然是从UNIX纪元1970/1/1 0:0:0开始的),区块间隔是500毫秒

2、producer(区块生产者)

account_name类型本质上是name类型:

using account_name     = name;

name类型可以实现uint64_t(64位无符号整型)和string类型的相互转换。

3、confirmed(当前区块生产者需要确认的最新区块数量)

** **

4、previous(区块链上前一个区块的ID)

block_id_type是一个sha256类型,即使用SHA-256哈希算法生成的哈希值:

using block_id_type       = fc::sha256;

5、transaction_mroot(交易的默克尔树根哈希)

EOS区块体中会包含交易列表(transactions)字段,transactions中包含多笔交易,这些交易以默克尔树的数据结构进行存储,transaction_mroot就是这些交易的默克尔树根节点哈希。

根据默克尔树的性质,transaction_mroot可用来验证每笔交易的正确性,同时可以方便节点同步数据时,对交易数据进行并行下载和校验;

如果区块中不包含任何交易,则transaction_mroot的值为0。

checksum256_type和block_id_type类型相同,也是一个SHA-256哈希值:

using checksum256_type    = fc::sha256;

6、action_mroot(Action的默克尔树根哈希)

EOS中Action表示一个操作,一笔交易(Transaction)通常包含多个Action,action_mroot是所有已分发Action的默克尔树根哈希,用于在区块内应用交易时进行评估、IBC证明和轻客户端校验。

action_mroot和transaction_mroot使用相同的数据类型:checksum256_type。

7、schedule_version(区块生产者计划的版本)

schedule_version用于验证此区块,表明之前包含new_producers->version的区块被标记为不可逆,并且新的生产者计划在此区块生效。

8、new_producers(下一轮区块生产者)

EOS区块由21个超级节点生产,每0.5秒生产一个区块,每个节点连续生产12个区块耗时6秒;

21个节点按照区块生产者计划的顺序依次生产区块,一轮耗时6*21=126秒,然后进入下一轮生产,生产者顺序会发生变化。

producer_schedule_type类型的定义如下:

struct producer_schedule_type {
  uint32_t                                       version = 0; ///< sequentially incrementing version number
  vector<producer_key>                           producers;

  public_key_type get_producer_key( account_name p )const {
     for( const auto& i : producers )
        if( i.producer_name == p ) 
           return i.block_signing_key;
     return public_key_type();
  }
};

version字段是按顺序递增的版本号,producers保存了一组生产者公钥。

producer_key保存生产者账户名(producer_name)和区块签名公钥(block_signing_key)的映射关系:

struct producer_key {
  account_name      producer_name;
  public_key_type   block_signing_key;
  //...
};

9、header_extensions(区块头内容扩展)

EOS的区块头还允许保存一些扩展内容,extensions_type类型的声明如下:

typedef vector<std::pair<uint16_t,vector<char>>> extensions_type;

是一个std::pair类型的数组,std::pair保存的就是单项的扩展内容,std::pair是一个结构体模板,其可以存储两个相异对象于一个单元。

时间有限,EOS区块的数据结构没有介绍完,下半部分放到下一篇文章中介绍。

更多内容

币圈信息站开发目录

EOS开发系列目录

共收到 0 条回复
Admin 将本帖设为了精华贴 12月21日 17:49
需要 登录 后方可回复, 如果你还没有账号请点击这里 注册