Election合约
名词解释
Candidate
候选人
抵押(被有人代为抵押)了10万个ELF的aelf账户,在合约内存储为公钥
BP
区块生产者
成功当选出块节点的候选人
Elector
选民
为候选人投票的aelf账户
Admin
候选人的管理员
管理员有权替换候选人公钥;这个角色在候选人参选的时候指定。保存某个BP公钥的Admin:State.CandidateAdmins保存某个Admin名下的公钥:State.ManagedCandidatePubkeysMap
Sponsor
候选人的赞助者
替候选人抵押了10万个ELF的aelf账户;当候选人退选的时候,10万个ELF会回到Sponsor账户中保存某个BP公钥的Sponsor:State.CandidateSponsorMap
Profit Receiver
分红受益者
当BP的账号不方便登录钱包领取节点收益的时候,可以指定另外一个aelf账号登录钱包领取自己的收益
候选人
参选 - AnnounceElection
会获取(虽然方法名为Recover...)Sender的Pubkey,并以此为凭据记录信息。因为Pubkey是能生成Address的,而Address无法推出Pubkey。
’如今在声明竞选的时候,需要手动指定自己的Admin角色(该方法唯一的参数)。而且候选人本身不能是其他候选人的Admin。
不默认使用Context.Sender作为Admin的原因是,如果Admin设置为BP账号,未来就无法进行Pubkey的替换了。
Election合约把Pubkey列为竞选的投票项目的选项之一,扣掉Sender的10万个ELF,打入一个独属于Sender的虚拟地址里(这样可以防止资金搞混了)。
最后将候选人添加为Backup Subsidy分红方案的受益者。
使用初始的节点进行参选。
Initial miner cannot announce election.
提供的Pubkey已经参选过了。
This public key already announced election.
提供的Pubkey此前因为作恶被拉黑了。
This candidate already banned before.
参数为空(没有指定Admin)。
Admin is needed while announcing election.
指定的Admin自己也是个候选人。
Candidate cannot be others' admin.
替他人参选 - AnnounceElectionFor
逻辑和AnnounceElection基本一致,只是Pubkey改为输入。
10万个ELF依然扣的是Sender。
另外,如果Admin参数为空,可以默认为Context.Sender。
我们称为他人垫付10万个ELF参选的账号为Sponsor,Sponsor和Admin身份重合挺合理的。报错信息同AnnounceElection。
设置Admin - SetCandidateAdmin
在老版本的Election合约中,没有设置Admin的要求。
在合约升级之前竞选成功的BP,可以调用这个方法来为自己设置一个Admin。BP自己设置的Admin一经设置,无法更改。
但是某个BP的Admin依然可以通过议会提案进行修改。
传入的BP的Pubkey不是当前候选人,也不是初始的节点(就是初始的五个)。
Pubkey is neither a current candidate nor an initial miner.
传入的BP的Pubkey之前已经因为作恶被拉黑了。
Pubkey is already banned.
这个BP的Admin没有设置过,或者Sender不是Admin
No permission.
退出竞选 - QuitElection
只有Admin可以操作让自己名下的候选人进行退选。而且如果这个候选人当前已经是BP,暂时无法退选。(得通过投票把他投下去。)
要退选的Pubkey没有参选过。
Target is not a candidate.
要退选的Pubkey是现任BP。
Current miners cannot quit election.
Sender不是BP的Admin。
Only admin can quit election.
选民
投票 - Vote
用户可以使用ELF为自己支持的候选人投指定票数,每次投票都需要两个参数:
amount:投票数量,对应要付出多少个ELF,这个数量会加到对应节点的总票数上;
t:锁仓时间,指定付出的ELF要锁定多长时间,范围目前设定为3个月到3年,到期后可赎回,且无法继续获得收益(但是如果不及时赎回的话,权重依然在总权重中,所以会影响他人收益)。
每一笔投票都可以算出一笔权重:
其中,interest和k都分别有Controller地址,分别通过SetVoteWeightInterest和SetVoteWeightProportion方法进行设置。
Treasury下的Citizen Welfare分红方案就按以上的权重进行分配。另外,在用户锁定ELF的同时,Election合约会为用户打入相同数量的VOTE和SHARE代币。
换投 - ChangeVotingOption
这里以feature/change-voting-option-profits分支为准。在完成一笔投票,且这笔投票还没有到期(就是还不能赎回)的情况下,出于某种原因,想把这笔投票转移给其他候选人,则可以调用ChangeVotingOption方法,需要提供三个参数:
vote_id:要换投哪一笔投票,因为一个账户可能之前投过多笔;
candidate_pubkey:要换投给哪个候选人;
is_reset_voting_time:是否重置投票时间,如果为true,相当于此刻同时完成赎回和重新投票(放在同一笔交易里),重新计算锁仓时间;如果为false,就是仅仅把票数加到别的候选人头上,没有其他影响。
赎回 - Withdraw
当某一笔投票锁仓时间到了,就通过Withdraw方法(网站上的Redeem按钮)把ELF赎回。
但是要注意,赎回ELF的同时,必须返还同等数量的VOTE和SHARE代币,否则无法完成这一笔交易。
如果VOTE和SHARE代币被用来做其他事情,在赎回ELF的时候需要拿回来。
在赎回的同时,被投的候选人的票数会减少。
维护节点竞选
快照 - TakeSnapshot
该方法调用者只能是共识合约,调用的交易为NextTerm交易,时机为换届的时候。
每逢换届,都需要对这一届的投票结果做一次快照,存下每一届的选举情况。
实际上,这个方法会进一步调用Vote合约中的TakeSnapshot方法,而快照本身也是存储在Vote合约中的。
不过由于该方法的调用时机正好是换届,因此多余做了一些事情:
更新上一节各个BP的出块信息(作为声誉的参考);
释放Backup Subsidy分红;
释放Citizen Welfare分红。
替换BP公钥 - ReplaceCandidatePubkey
BP的aelf节点是可能出现私钥泄露的情况的。这也是加入Admin这一角色的原因。Admin可以通过调用ReplaceCandidatePubkey方法替换自己名下某个BP的Pubkey:
通知共识合约执行
RecordCandidateReplacement,这样BP的Pubkey可以立刻生效(使用新的私钥配置的aelf节点能出块);在这里,会进一步通知Treasury合约执行RecordMinerReplacement,修改相应的分红受益人信息。
通知Vote合约修改选举投票项目的选项,把老的Pubkey替换为新的;
更新Sponsor信息(把老的Sponsor加到新的Pubkey下);
更新Admin信息(更新双向绑定);
更新候选人列表;
更新节点排名情况;
更新Backup Subsidy分红信息;
更新BP出块详情信息(把老的详情直接添加给新的Pubkey);
把老的Pubkey给禁用掉(因为很有可能已经泄露);
更新Profit Receiver信息。
设置分红受益者 - SetProfitsReceiver
这个方案只有Treasury合约能够触发。其实当候选人的分红受益者需要发生变化的时候,理应让Treasury合约完成一切设置。
只不过Backup Subsidy和Citizen Welfare这两个分红池的Manager是Election合约,因此只能加一个方法,让Treasury合约进行调用。
其他
RegisterElectionVotingEvent:调用Vote合约,注册节点选举这一投票项目,仅调用一次
UpdateCandidateInformation & UpdateMultipleCandidateInformation:更新候选人(BP)最近的出块情况,如果发生BP作恶的情况(比如三天不出块),也使用该方法标记作恶(然后把这个BP禁用一下)
SetTreasurySchemeIds:用来初始化分红方案的Id
UpdateMinersCount:设置BP数量上限RemoveEvilNode:移除作恶节点
Last updated