Witness是什么
在steem区块链的网络中,节点分为两种角色,Witness
和非Witness
。
非Witness
是steem区块链网络的普通参与者,可以从其他节点接受数据、传播数据。
Witness
则是steem区块链网络的维持者,他们通常要保持24小时在线,是steem区块链的基石,负责区块链的收集交易、打包交易和出块工作,同时还运行着steem的经济学相关的工作。正应为他们要不断的在线、工作,会消耗一定的资金来维持服务,因此,在他们出块后会得到一定的STEEM Power
作为回报。
在steem区块链的网络中,对Witness
进行不停的调度,在每一调度轮次中,会抽获取投票最高的前20个Witness
节点和一个随机抽取的Witness
节点组成一个21节点的集合(有些地方讲的是19个投票最高的节点和1个矿工节点和1个随机节点,这是比较老的算法,从第17次硬分叉后,删除了矿工节点,投票最高的节点变为20个),在洗牌后依次负责出块,每3秒钟出一个块。如果负责出块的Witness
节点在自己负责的时间范围内没有进行出块,不影响负责下一个时间区间的Witness
节点进行出块,但是没有及时出块的Witness
节点不会获得报酬并且可能被投票出局1。
关于选举
每个steem用户可以给30个Witness
进行投票。会使用steemd客户端的用户,可以通过steemd客户端进行投票。其他用户还可以在steemit.com网站上进行投票。
另外用户还可以设置代理投票,然后将自己投票权重转义给代理人,代理人负责投票。
出块
当用户自身成为Witness
后,在自己节点启动时,可以开启witness_plugin
,在启动后,witness_plugin
会启动一个定时器来定期调用block_production_loop
函数来判断,是否轮到自己出块。(注意:其中判断时,会调用get_slot_time(1)
,其意义为获取下一次该出块的时间)。如果当前时间对应的Witness
是自己,则进行出块。
调度
当网络中第一个节点启动后,会创建出一个创世块
进行冷启动,此后在每一次接受一个新块后,都会调用update_witness_schedule
进行一次调度的更新。当当前块高度能被21整除时,意味着,一个调度周期的结束。其会重新挑选出一批Witness
,进行下一周期的出块。这里同时意味着,如果在一个周期内有Witness
没能成功出块时,会有一些Witness
在一个调度周期内能出块多次。我认为这是一个BUG,因为在同一个周期内,Witness
之间收益是不相等的。
当一个周期开始是,首先按投票数进行排序,取出投票数最高的20个节点,然后根据虚拟调度时间来选取一个备份节点。选取好足够节点后,然后进行洗牌。
同时再调度的过程中,还会计算一些基本数据,比如:
- 选中的
Witness
中,主流版本是什么,因为steem是通过硬分叉进程升级的,不同版本的各种逻辑会有不同,当某些策略可能需要等到网络中的多数Witness
都升级到某个版本后才能开始生效,因此在每一轮调度中,都会刷新当前的主流版本。 - 更新一些与
Witness
相关的经济学数据
总结
可以看出与Witness
相关逻辑都比较简单,加起来一共可能只有几百行代码而已,整体上跟最前面算法描述一致,没有特别多的细节需要注意。
注意:在调度与出块之间存在数据竞态,出块时可能访问的已经释放的内存,从而崩溃。