OSDN Git Service

send standby node reward (#358)
[bytom/vapor.git] / toolbar / consensusreward / consensusreward.go
1 package consensusreward
2
3 import (
4         "math/big"
5
6         "github.com/vapor/consensus"
7         "github.com/vapor/errors"
8         "github.com/vapor/toolbar/apinode"
9         "github.com/vapor/toolbar/common"
10         "github.com/vapor/toolbar/consensusreward/config"
11 )
12
13 const standbyNodesRewardForConsensusCycle = 7610350076 // 400000000000000 / (365 * 24 * 60 / (500 * 1200 / 1000 / 60))
14
15 type StandbyNodeReward struct {
16         cfg         *config.Config
17         node        *apinode.Node
18         xpubRewards map[string]uint64
19         startHeight uint64
20         endHeight   uint64
21 }
22
23 func NewStandbyNodeReward(cfg *config.Config, startHeight, endHeight uint64) *StandbyNodeReward {
24         return &StandbyNodeReward{
25                 cfg:         cfg,
26                 node:        apinode.NewNode(cfg.NodeIP),
27                 xpubRewards: make(map[string]uint64),
28                 startHeight: startHeight,
29                 endHeight:   endHeight,
30         }
31 }
32
33 func (s *StandbyNodeReward) getStandbyNodeReward(height uint64) error {
34         voteInfos, err := s.node.GetVoteByHeight(height)
35         if err != nil {
36                 return errors.Wrapf(err, "get alternative node reward")
37         }
38
39         voteInfos = common.CalcStandByNodes(voteInfos)
40         totalVoteNum := uint64(0)
41         for _, voteInfo := range voteInfos {
42                 totalVoteNum += voteInfo.VoteNum
43         }
44
45         total := big.NewInt(0).SetUint64(totalVoteNum)
46         for _, voteInfo := range voteInfos {
47                 amount := big.NewInt(0).SetUint64(standbyNodesRewardForConsensusCycle)
48                 voteNum := big.NewInt(0).SetUint64(voteInfo.VoteNum)
49                 s.xpubRewards[voteInfo.Vote] += amount.Mul(amount, voteNum).Div(amount, total).Uint64()
50         }
51         return nil
52 }
53
54 func (s *StandbyNodeReward) Settlement() error {
55         for height := s.startHeight; height <= s.endHeight; height += consensus.ActiveNetParams.RoundVoteBlockNums {
56                 if err := s.getStandbyNodeReward(height - consensus.ActiveNetParams.RoundVoteBlockNums); err != nil {
57                         return err
58                 }
59         }
60         rewards := map[string]uint64{}
61         for _, item := range s.cfg.RewardConf.Node {
62                 if reward, ok := s.xpubRewards[item.XPub]; ok {
63                         rewards[item.Address] = reward
64                 }
65         }
66
67         if len(rewards) == 0 {
68                 return nil
69         }
70         return s.node.BatchSendBTM(s.cfg.RewardConf.AccountID, s.cfg.RewardConf.Password, rewards)
71 }