STEEM 见证人的选择方法

in #witness7 years ago

我们都知道STEEM每出21个块,重新选择一组(21个见证人),那么这组见证人是如何产生的呢?今天我们就来粗略地探究一下。


(图源 :pixabay)

每当出完一个块时,见证人选择函数都被调用update_witness_schedule,然后程序中判断是否是21的整数倍if( (db.head_block_num() % STEEM_MAX_WITNESSES) == 0 ),如果是则更新见证人列表 update_witness_schedule4,所以我们来看看这个函数内都做了什么就可以了。

这个函数结构很清晰,第一步就是选择见证人,代码上看这步可以分为三个部分

选择TOP 20见证人

亦即按得票数多少,选择20名见证人。

有人可能会问,如果前二十名见证人有人占着位子,但是见证人离线(OFF LINE)了,被选上岂不是耽误事啦?别怕,以下代码表示如果有见证人离线,那么会略过,直到选够为止:

其中这句:

db.modify( *itr, [&]( witness_object& wo ) { wo.schedule = witness_object::top19; } );

其实应该是wo.type = XXXX,代表见证人类型,定义如下:

但是需要说明的是HF17之后,已经没有挖矿一说了,另外TOP19变成了TOP20,别被名字误导了。

选择矿工见证人

说到矿工见证人,之前我们说过HF17之后,没有挖矿一说,这个是如何体现的呢?

其实就是在HF17的代码 case STEEM_HARDFORK_0_17 分支下设置了如下数据:

上边三个常量分别对应20、0、1
我们可以获取witness_schedule_object来验证一下此事

所以尽管选择见证人时,选择矿工的代码还在,实际上是啥也不做的。

选择轮值见证人

这个玩意该翻译成啥,我有点纠结,叫随机不合适,叫备选也不合适,代码中有的地方叫running,有的地方叫timeshare,我先翻译成轮值吧,这块是挺有意思的,也是我最关心的地方。


以上代码挺好理解,就是按拍好的顺序(by_schedule_time),选择一个见证人出来。当然必要的检查还得做做,比如看看是不是和TOP20或者矿工重复了、看看是不是离线,选出来还要设置一下类型等等。

但是,最最关键的问题是,这个schedule_time是咋排出来的? 接下来的代码就来解答疑问了:

也就是说备选见证人有个排序的时间表,当然了,这里时间不是真正的时间,而是数轴上的一个点。用一个大数除以见证人的得票数,得到一个数,就是这个见证人下次轮值的时间。然后每次取这个数轴上的第一个点,也就是排在最前边的见证人了。

再回头看前边的代码:

每个被处理过的见证人,都会被重新排序,相当于你轮值过了再给你排下一班。

从以上代码不难看出,得票数越多,每次排序的点间距越小,那么被轮到的概率越高,所以我们之前说过的轮值见证人收益和得票数成比例,从代码上看是成立的。


总结

  • 每21个块重新选一组见证人
  • 见证人由TOP20 (20) + 轮值 (1) 组成
  • 轮值见证人排到的概率和得票数成比例

在这之后的把选的这组见证人(21个)随机打乱的算法我实在是看不懂,不过我只需知道他打乱了一下就可以了,其它的我就不关心啦。好了,就写这么多啦!

Sort:  

关注了。虽然不是很了解程序,但是还是收藏了,不断的学习才能进步。

虽然不是很懂,但我还是来学习学习

大佬,可以带动我么

謝謝你的分享 還不是很懂 剛加入還要研究研究

什么是见证人啊,小白啥也不懂呢

欢迎到steemh.org查询,上面有很多新手需要了解到的知识点

O哥,我在这儿打个《steem指南》的广告会不会被你打😂

我觉得不会被打……

可以给出具体的章节链接,见我对楼上的回复,markdown 源文本是:

关于什么是见证人,请参阅[《Steem 指南》]https://bookdown.org/baydap/steemh/section-10.html#steem_jzr)。

如何获取各章节的链接?在书稿网页版左侧的文档结构图里,鼠标放到某个标题,点右键,复制链接即可。

赞👍
我下次会注意直接发准确的章节链接的,嘿嘿

关于什么是见证人,请参阅《Steem 指南》