Crust采用GPoS共识机制,全称为“以存储资源做担保的PoS共识”,它实际上也是一种PoS共识机制。Crust是基于波卡生态的substrate框架实现,它也借鉴了波卡的共识机制。
传统的PoS共识有一个很大的问题,staking的币越多,以后的收益就会越高,容易形成寡头现象,也就是强者恒强。波卡开创了自己的PoS机制:NPoS,提名权益证明,将Staker分为提名人和验证人两种角色,出块奖励会大致平均分配给当前所有的验证人, 避免了马太效应。
Crust的共识机制以era为周期,每个era为6个小时。在每个周期中都会选举新一轮的验证人集合,新选出的验证人参与本周期的共识,同时也以era为周期进行奖励分配。

质押额度决定了验证人有效质押代币数量的上限,这个上限与验证人提供的存储量直接相关。验证人的存储量为他所在的组内所有member成员存储量的和。
根据验证人的质押上限和它的担保人信息,统计出该验证人的有效质押总量。每个验证人以自身的有效质押总量作为选票参与选举过程。
举例来看验证人的有效质押总量的计算过程。
如下所示,有验证人(Validator):V1, V2, V3, 其中V1的担保人(Guarantor):G1-1, G1-2, V2的担保人:G2-1, G2-2, G2-3,V3的担保人:G3-1, G3-2。

验证人和他们的担保人具体信息如下,其中验证人的质押金额表示的是验证人自身的代币数量(比如V1的质押金额是200,这里的200代表的是验证人自身的代币)。

验证人的总质押量 = 自身质押金额 + 担保金额(担保人的质押金额)
有效质押率 = 最小值((质押额度/验证人总质押量), 100%)
验证人的有效质押量 = 自身质押金额 * 有效质押率
担保人的有效质押量 = 担保人质押金额 * 有效质押率
以验证人V1演示他的有效质押总量的计算过程。
V1总质押量 = 250 = 200+20+30
V1有效质押率 = 40% = 最小值( (100/250), 100% )
V1的有效质押量 = 80 = 200*40%
G1-1的有效质押量 = 8 = 20 * 40%
G1-2的有效质押量 = 12 = 30 * 40%
V1有效质押总量 = 100 = 250 * 40%
至此计算出V1的有效质押总量为100,同时也是V1有效质押量和担保人有效质押量的和(80+8+12)。在本次era周期中,也会将验证人和担保人的有效质押量记录下来,以便后期奖励分配使用。按照同样的方法对V2和V3进行计算,得到以下数据:

本轮era周期的总有效质押量为500 = 100 + 200 + 200
验证人的有效总质押,验证人和担保人各自的有效质押如下图:

通过上面的计算,我们得知了每个验证人的有效质押总量,将质押量按照1:1兑换为选票。
验证人V1,选票100
验证人V2,选票200
验证人V3,选票200
将验证人按照选票数降序排列 V3, V2, V1,假设网络设置的验证人数量为n,则只选举前n名验证人作为本轮era周期的验证人,由他们执行pos共识,进行出块。
当n=2时,则只选择V3, V2作为本轮验证人。V1参加了竞选,但是竞选失败,身份变为候选人。

在era周期结束时会分配奖励,奖励的来源有两个部分。
第一部分:按照Crust经济模型的代币释放曲线计算当前era需要释放的奖励。比如当前era索引值为2000,也就是主网启动后的第2000个era。每个era为6个小时,每天产生4个era,每年产生4*365.25= 1461个,因此可以判断当前处在网络启动后的第2年。第二年总计会释放4,400,000个代币,平均每个era大致释放3011(4400000/1461)个。

第二部分:DSM质押池中的一部分奖励。
用户在DSM存储文件支付的资金有一部分会进入质押池。
以上两个资金求和计算出该era周期总代币奖励数量。
total_payout = era_payout + market_payout
总奖励中还需要燃烧掉一部分era_benefit
total_payout = total_payout - era_benefit
根据当前验证人的数量决定从total_payout中分配多少钱作为总出块奖励(total_authoring_payout)。

0到500人时,total_pay的20%作为总出块奖励(total_authoring_payout)。
501到1000人时,total_payout的25%作为总出块奖励(total_authoring_payout)。
……
假设总奖励为4000,验证人共2个(V2, V3),则total_authoring_payout = 800 = 4000 * 20%
根据该era周期各个验证人的得分对这800进行分配。
假设V2:300, V3:500
tips:
这部分使用的是波卡的NPoS,在这种机制下得分在每个验证人之间大致是趋向于平均的。
本轮era总质押奖励就是总奖励去掉总出块奖励剩余的部分。
total_staking_payout = total_payout - total_authoring_payout
继续使用上面的例子,total_staking_payout = 3200 = 4000 - 800
3200就是本轮era周期的总质押奖励。
核算操作需要由验证人或候选人触发,调用do_reward_stakers接口,传入参数为验证人/候选人id,era周期索引。
现根据era索引查询到该era周期的总质押奖励total_staking_payout(3200)。接下来分两种情况来讨论:验证人和候选人。
查询出该验证人的出块奖励authoring_reeard。
在核算出块奖励时得知V2的出块奖励为300
根据该验证人总有效质押占该era周期总有效质押的比例计算出该验证人的总质押奖励。 V2总质押奖励 = (200/500)*3200 = 1280
验证人总奖励为他出块奖励与质押奖励的和。
V2总奖励 = 300 + 1280 = 1580
查询验证人在该era周期担保费率,对它的担保人进行奖励分配

V2的担保总收益 = 1580*20%=316
G2-1的担保收益 = 316 * (8/200) = 12.64
G2-2的担保收益 = 316 * (12/200) = 18.96
G2-3的担保收益 = 316 * (20/200) = 31.6
V2的总收益 = 1580 - 12.64 - 18.96 - 31.6 = 1516.8
V1竞选验证人没有成功,所以和V2相比它的奖励中不包含出块奖励,只有质押奖励。分配的计算过程和V2是一样的。假设V1的担保费率为30%
V1的总质押收益 = (100/500)*3200 = 640
V1的总担保收益 = 640 * 30% = 192
G1-1的担保收益 = 192 * (8/100) = 15.36
G1-2的担保收益 = 192 * (12/100)= 23.04
V1的总收益 = 640 - 15.36 - 23.04 = 601.6
