1 package consensusreward
6 "github.com/vapor/consensus"
7 "github.com/vapor/errors"
8 apinode "github.com/vapor/toolbar/apinode"
9 "github.com/vapor/toolbar/common"
10 "github.com/vapor/toolbar/consensusreward/config"
14 errNotStandbyNode = errors.New("No Standby Node")
15 errNotRewardTx = errors.New("No reward transaction")
18 const standbyNodesRewardForConsensusCycle = 7610350076 // 400000000000000 / (365 * 24 * 60 / (500 * 1200 / 1000 / 60))
20 type StandbyNodeReward struct {
23 rewards map[string]uint64
24 xpubAddress map[string]string
29 func NewStandbyNodeReward(cfg *config.Config, startHeight, endHeight uint64) *StandbyNodeReward {
30 s := &StandbyNodeReward{
32 node: apinode.NewNode(cfg.NodeIP),
33 rewards: make(map[string]uint64),
34 xpubAddress: make(map[string]string),
35 startHeight: startHeight,
38 for _, item := range cfg.RewardConf.Node {
39 s.xpubAddress[item.XPub] = item.Address
44 func (s *StandbyNodeReward) getStandbyNodeReward(height uint64) (map[string]uint64, error) {
45 voteInfos, err := s.node.GetVoteByHeight(height)
47 return nil, errors.Wrapf(err, "get alternative node reward")
49 voteInfos = common.CalcStandByNodes(voteInfos)
50 if len(voteInfos) == 0 {
51 return nil, errNotStandbyNode
53 totalVoteNum := uint64(0)
54 for _, voteInfo := range voteInfos {
55 totalVoteNum += voteInfo.VoteNum
57 total := big.NewInt(0).SetUint64(totalVoteNum)
58 xpubReward := make(map[string]uint64)
59 for _, voteInfo := range voteInfos {
60 amount := big.NewInt(0).SetUint64(standbyNodesRewardForConsensusCycle)
61 voteNum := big.NewInt(0).SetUint64(voteInfo.VoteNum)
62 xpubReward[voteInfo.Vote] = amount.Mul(amount, voteNum).Div(amount, total).Uint64()
64 return xpubReward, nil
67 func (s *StandbyNodeReward) Settlement() error {
68 if err := s.calcAllReward(); err != nil {
71 return s.node.BatchSendBTM(s.cfg.RewardConf.AccountID, s.cfg.RewardConf.Password, s.rewards)
74 func (s *StandbyNodeReward) calcAllReward() error {
75 for height := s.startHeight; height <= s.endHeight; height += consensus.ActiveNetParams.RoundVoteBlockNums {
76 xpubReward, err := s.getStandbyNodeReward(height - consensus.ActiveNetParams.RoundVoteBlockNums)
77 if err == errNotStandbyNode {
83 for xpub, amount := range xpubReward {
84 if address, ok := s.xpubAddress[xpub]; ok {
85 s.rewards[address] += amount
89 if len(s.rewards) == 0 {