LOADING...
LOADING...
LOADING...
当前位置: 玩币族首页 > 行情分析 > 【EOS源码分析】34 - EOS系统如何更新区块生产节点?

【EOS源码分析】34 - EOS系统如何更新区块生产节点?

2020-06-08 松果 来源:区块链网络


上一篇文章介绍了EOS系统合约eosio.system的整体概况,这篇文章开始介绍eosio.system合约中的一些业务细节。

EOS系统如何更新区块生产节点?

EOS系统使用的共识机制是DPOS,EOS代币持有者通过投票选出21个节点作为区块生产者,投票时刻都在进行,因此前21个生产节点也是处于不断变化中的。

区块生产节点的更新是通过system_contract类中声明的私有成员函数update_elected_producers实现的,update_elected_producers函数在onblock这个Action中被调用,onblock是一个由系统调用的Action,用于管理出块动作、更新生产者区块信息和链上的短账户名拍卖信息。

update_elected_producers函数声明如下:

void update_elected_producers( const block_timestamp& timestamp );

定义在voting.cpp中:


首先更新全局参数(global表)中的last_producer_schedule_update字段,它记录上次区块生产计划更新时间,每隔60.5秒更新一次;

然后从producers表查询EOS链上的所有已注册节点,这里使用了二级索引prototalvote,后者在eosio.system.hpp中的定义如下:

typedef eosio::multi_index< "producers"_n, producer_info, indexed_by<"prototalvote"_n, const_mem_fun<producer_info, double, &producer_info::by_votes> > > producers_table;

使用prototalvote可以让节点按照当前投票顺序排名,定义一个集合top_producers,它保存投票数最高的前21个节点。

通过遍历二级索引的查询结构,把投票数最高的21个节点添加到top_producers中,遍历过程中包含对节点的数据验证:

for ( auto it = idx.cbegin(); it != idx.cend() && top_producers.size() < 21 && 0 < it->total_votes && it->active(); ++it ) { top_producers.emplace_back( std::pair<eosio::producer_key,uint16_t>({{it->owner, it->producer_key}, it->location}) ); }

检测完top_producers中的节点数量是否符合last_producer_schedule_size(21个)后,调用sort函数把选出的前21个节点按照名称排序:

std::sort( top_producers.begin(), top_producers.end() );

接下来新建一个向量集合producers,拷贝top_producers的部分数据(producer_key)到producers中,再调用:

set_proposed_producers( producers )

完成21个区块生产节点的更新,同时更新全局参数last_producer_schedule_size。

set_proposed_producers函数定义在eosio.cdt的eosiolib.cpp(eosio.cdt/libraries/eosiolib/eosiolib.cpp)中:


内部调用了CAPI的set_proposed_producers函数:

__attribute__((eosio_wasm_import)) int64_t set_proposed_producers( char *producer_data, uint32_t producer_data_size );

这是一个eosio_wasm_import属性的函数,在wasm_interface.cpp(eos/libraries/chain/wasm_interface.cpp)中实现:


经过一系列数据验证后,调用了controller的set_proposed_producers函数:

context.control.set_proposed_producers( std::move(producers) );

定义在controller.cpp(eos/libraries/chain/controller.cpp)中,关键代码如下:


sch是一个shared_producer_schedule_type类型对象,有一个成员变量producers;

sch被赋值给gp.proposed_schedule,gp是一个global_property_object类型对象,有一个shared_producer_schedule_type类型的成员变量;

db是一个chainbase::database类型对象,调用其modify方法更新了数据中的gpo表,它保存global_property_object类型对象;

到这里,新的21个区块生产节点被更新到EOS系统数据库。

更多内容

币圈信息站开发目录

EOS开发系列目录

—-

编译者/作者:松果

玩币族申明:玩币族作为开放的资讯翻译/分享平台,所提供的所有资讯仅代表作者个人观点,与玩币族平台立场无关,且不构成任何投资理财建议。文章版权归原作者所有。

LOADING...
LOADING...