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