EOS可以执行system合约的regproducer或者unregprod动作,实现生产者注册或者取消生产者注册。
1,合约中生产者注册表定义
其中:
owner :生产者账号名称。
total_votes :获得的投票总数量。
producer_key :生产者公私钥。
is_active :是否是激活状态。
url :生产者的url地址。
unpaid_blocks :该生产者未获取生产者奖励的生产的区块数量。
last_claim_time :上次获得生产者奖励的时间。
location :最近邻调度的相对位置。(未使用)
2,设置节点生产者账户
3,生产者注册
注册生产者:
如果该生产者已存在于生产者注册表,则修改生产者的公钥、URL地址,获得投票置0、激活该生产者。
如果不存在于生产者注册表,则添加该生产者记录,激活该生产者。
4,取消生产者注册
取消注册生产者:
将该生产者对应生产者注册表的记录修改,生产者的公钥置空、激活状态为false。
该生产者记录并不删除。
rmvproducer同样可以取消生产者注册,需要系统管理员权限。
二,生产者选举投票
所有账户可以对已经注册的生产者进行选举投票,选举出可以生产区块的生产者列表。
1,合约中账户投票表定义
其中:
owner :投票者账户名称。
proxy :代理账户名称。
producers :投票者投票的生产者列表,一个投票者可以同时对最多30个生产者进行投票。
staked :投票者质押资源(NET&CPU)的货币总额。
last_vote_weight:该投票者上次的投票的权重。
proxied_vote_weight:该账户如果是投票代理账户,该值为代理的投票权重。
is_proxy :该账户是否是投票代理账户。
- 一个账户只能拥有一个投票代理人。
- 投票代理人可为多个账户代理投票。
- 代理人不允许再被代理。
- 账户一旦指定代理就不能直接投票生产者。(proxy 或者producers必须有一个为空)
- 该表中对应账号的记录仅在相关账号质押资源或者注册代理人时被添加。
2,资源质押投票者权重累计
投票者拥有的投票权重来自于投票者帐户对资源质押的货币总额的计算。
在质押资源动作完成时,根据质押人账户质押资源(NET&CPU)的总金额,修改账户投票表。
- 资源质押的金额只影响质押人投票权重,与受益人无关。
- 质押人账户如存在于账户投票表中,则累计该表中该账号下的资源质押总金额。
- 质押人账户如不存在,则在该表中创建该账号的记录,对其质押总金额赋值。
- N(b1)预留开发者投票账户。(未使用)
- 如果该账户已经投过票或者设置过代理,重新计算资源质押对应的投票权重。
3,投票权重的计算
- 投标权重系数 = (2的(当前时间距离2000年的年数)次方)。
- 投票权重 = 质押金额*投标权重系数;
- 即投票时间或者指定代理人时间越新投票权重系数越大。(鼓励用户不断投票)
4,投票代理人注册
一个账户需要被注册为投票代理人后才能具备代理其他账户进行选举投票的能力。
regproxy注册代理人动作:
如注册的代理人存在于账户投票表中,将注册的代理人在对应账户投票表的记录的is_proxy置为true或者false;对其质押资源可产生的投票权重进行投票。
如注册的代理人不存在于账户投票表中,添加该账户记录is_proxy置为true或者false。
5,投票
投票人通过voteproducer的动作,可以执行生产者选举投票或者指定投票代理人投票的操作,但2个操作不能同时执行。即执行该函数的参数proxy或者producers必须有一个为空。
proxy不为空,表示执行指定代理人操作,根据投票人资源质押金额计算出的投票权重会累积到代理人的proxied_vote_weight的代理权重中;并将代理人的代理权重增量累积到选举的生产者列表对应生产者的生产者注册表的记录total_votes生产者投票累计权重中。
producers不为空,表示执行投票操作,根据投票人资源质押金额计算出的投票权重增量累积到选举的生产者列表对应生产者的生产者注册表的记录total_votes生产者投票累计权重中;如果投票者是代理人,则增量需要计算proxied_vote_weight代理的投票权重。
propagate_weight_change函数完成对选举生产者的投票权重累计,即p.total_votes += delta;并累计所有投票的权重,_gstate.total_producer_vote_weight += delta。
三,生产者列表状态
EOS系统中的生产者列表有3个状态,选举产生的新的生产者列表依次过渡,最终成为可轮替生产区块的生产者序列。
active schedule : 当前生产者列表,存放在当前生产区块的block_header_state记录中。
pending schedule : 待定生产者列表,存放在当前生产区块的block_header_state记录中。
proposed schedule: 提议生产者列表,存放在chainbase的global_property_object表中:
proposed_schedule_block_num:提议的生产者列表产生对应区块的块号。
1,proposed schedule生产者列表的产生
对生产者的选举投票不是直接产生结果,需要在区块生产者奖励计数函数onblock中,判断选举是否有效。
选举有效的条件 :
- total_activated_stake系统激活的债卷(参与投票的对应资源质押的货币总金额)总量超过或等于min_activated_stake(150‘000‘000‘0000)。
- 距离上次生产者选举投票结果变化超过120个区块的生产周期(1分钟)。
更新生产者选举结果 :
- 从选举的生产者中选出前最多21个,生产者为激活状态且获得投票权重大于0的生产者。
- 新的选举结果,只能增加生产者个数不允许减少。
- 选举出的新的生产者列表按照名称排序。
- 调用set_proposed_producers注入函数,将选举出的新的生产者列表置为proposed。
设置proposed schedule生产者列表 :
将新的选举结果置为proposed schedule,需要:
- 上一个proposed schedule已经转换为pending schedule。
- 新的选举结果与上一个proposed schedule不相同。
- 如果正在生产的区块的pending_schedule存在,则新的选举结果与pending_schedule不相同。
- 如果正在生产的区块的pending_schedule不存在,则新的选举结果与active_schedule不相同。
2,pending schedule生产者列表的替换
EOS中将proposed schedule切换至pending schedule的处理,在controller::start_block中:
将proposed schedule切换至pending schedule需要:
- 提案生产者列表有效。
- 提案生产者列表产生的对应的区块已经变为不可逆。
- pending schedule已经为空,即上一次pending schedule已经转换为active schedule。
设置pending schedule:
- 记录新的pending schedule生产者列表的hash,确保其不会被修改。
- 记录设置pending schedule对应的区块块号。
将proposed schedule切换至pending schedule后,proposed schedule的记录对象将被清空。
3,active schedule生产者列表的替换
创建一个新的正在生产区块时,next会调用新区快对象的maybe_promote_pending,处理是否需要将pending schedule切换为active schedule。
这时调用set_new_producers,是当pending schedule不为空且没有切换过active schedule,将pending schedule中的生产者列表传递给下一个区块。
将pending schedule切换至active schedule的条件:
- pending schedule不为空。
- 设置pending schedule的区块已经不可逆。
切换操作:
-
将pending schedule中的内容移至active schedule,pending schedule的内容被清空。
-
遍历新的生产者列表,如该生产者在老的生产者列表里存在,则保留原生产者的区块生产信息;如不存在,用当前不可逆块号赋值给新的生产者的区块生产信息。(producer_to_last_produced:生产者生产区块表;producer_to_last_implied_irb:生产者生产不可逆区块表。)
- 将当前区块号赋给该块的生产者对应的producer_to_last_produced。
四,节点生产区块
1,节点状态
EOS中节点的状态根据是否准备好出块可以分为两个:
producer_plugin_impl对象的_production_enabled属性为false:同步状态,即当前节点正在接收其他节点发来的区块做同步操作。
producer_plugin_impl对象的_production_enabled属性为true:生产状态,即当前节点已经完成所有的区块同步操作,可以生产区块。
主节点初始启动时,"enable-stale-production”选项必须为true,_production_enabled为true。
所有其他节点,在完成所有区块同步后,_production_enabled被置为true。(如果下一个块的截止时间大于当前时间,意味着同步完成)
2,节点生产区块的条件
- _production_enabled为true,本节点已经完成同步可以出块。
- _producers中包含了当前时间该出块的生产者,即本节点是超级节点且轮到本节点出块顺序。
- 生产者出块的签名公私钥存在。
- 距离本节点最后一个不可逆块的时间小于_max_irreversible_block_age_us限制,_max_irreversible_block_age_us默认-1(不限制)。
- 生产者对应的水印值小于当前生产区块的块号+1,区块生产顺序无错误。
四 ,链接
星河公链
了解最新更多区块链相关文章
敬请关注星链微信公众号,星链与你共成长