OSDN Git Service

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