前面的笔记本提到,maybe_produce_block函数是witeness 插件尝试生成新块的函数。该函数会先执行一些必要的检查,如本地机器中是否保存有该轮见证人的私钥,时间是否正确。该函数依赖于前面提到的chain::database 类型的全局db对象提供的接口。主要接口有以下几个:
1、get_slot_time
2、get_slot_at_time
3、head_block_time
4、get_secheduled_witness
5、witness_participation_rate
6、generate_block
以上接口的功能,顾名思义就可以了,后期有机会在详细分析下,这里先专注于当前函数的逻辑。

按照bitshares的规则,每3秒就要产生一个块,见证人轮流产生新块,如果一个见证人由于意外而不能按时产生区块则需要跳过此见证人,并由排在他后面的一个见证人来产生区块。

schedule_production_loop 每秒都唤醒一次,并最后进入到maybe_produce_block中,而在maybe_produce_block中,只有当下个区块的正常产生时间与当前时间之间的差值在500ms以内,才会调用generate_block产生区块。

llabs((scheduled_time – now).count()) > fc::milliseconds( 500 ).count()
从这个函数中不能发现,如果一个见证人由于意外不能产生新的区块时,程序会如何处理。chain::database中的get_scheduled_witness 函数

witness_id_type database::get_scheduled_witness( uint32_t slot_num )const
{
const dynamic_global_property_object& dpo = get_dynamic_global_properties();
const witness_schedule_object& wso = witness_schedule_id_type()(*this);
uint64_t current_aslot = dpo.current_aslot + slot_num;
return wso.current_shuffled_witnesses[ current_aslot % wso.current_shuffled_witnesses.size() ];
}
只是简单地返回见证人数组中与slot_num对应的元素,而并没有考虑到元素所代表的见证人是否正常工作。
slot的含义是将要产生的第几个区块,比如 slot=1就代表下一个区块,slot==2就代表下下个区块。

程序到底如何应对见证人不能正常出块的情况呢?在

database::update_witness_schedule()
中我们看到似乎有相关的代码在打乱wso.current_shuffled_witnesses这人数组的顺序。那么我们的猜测到底正不正确呢?由于我们目前关注的控制流,还没有流到这个函数中,先暂时搁置这个问题。

发表回复

您的电子邮箱地址不会被公开。 必填项已用 * 标注

此站点使用Akismet来减少垃圾评论。了解我们如何处理您的评论数据