-
Notifications
You must be signed in to change notification settings - Fork 11
/
penalty.go
137 lines (115 loc) · 3.75 KB
/
penalty.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
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
package types
import (
"fmt"
"strings"
"github.com/celer-network/goutils/log"
"github.com/celer-network/sgn/common"
"github.com/celer-network/sgn/mainchain"
"github.com/celer-network/sgn/proto/sgn"
sdk "github.com/cosmos/cosmos-sdk/types"
"github.com/golang/protobuf/proto"
)
const (
expireTime = ^uint64(0)
)
type AccountAmtPair struct {
Account string `json:"account"`
Amount sdk.Int `json:"amount"`
}
func NewAccountAmtPair(account string, amount sdk.Int) AccountAmtPair {
return AccountAmtPair{
Account: mainchain.FormatAddrHex(account),
Amount: amount,
}
}
func (amp AccountAmtPair) String() string {
return strings.TrimSpace(fmt.Sprintf(`Account: %s, Amount: %v`, amp.Account, amp.Amount))
}
type AccountFractionPair struct {
Account string `json:"account"`
Fraction sdk.Dec `json:"percent"`
}
func NewAccountFractionPair(account string, fraction sdk.Dec) AccountFractionPair {
return AccountFractionPair{
Account: mainchain.FormatAddrHex(account),
Fraction: fraction,
}
}
type Penalty struct {
Nonce uint64 `json:"nonce"`
ValidatorAddr string `json:"validator_addr"`
Reason string `json:"reason"`
PenalizedDelegators []AccountAmtPair `json:"penalized_delegators"`
Beneficiaries []AccountFractionPair `json:"beneficiaries"`
PenaltyProtoBytes []byte `json:"penalty_proto_bytes"`
Sigs []common.Sig `json:"sigs"`
}
func NewPenalty(nonce uint64, reason string, validatorAddr string) Penalty {
return Penalty{
Nonce: nonce,
Reason: reason,
ValidatorAddr: mainchain.FormatAddrHex(validatorAddr),
}
}
// implement fmt.Stringer
func (p Penalty) String() string {
return strings.TrimSpace(fmt.Sprintf(`Nonce: %d, ValidatorAddr: %s, Reason: %s`, p.Nonce, p.ValidatorAddr, p.Reason))
}
func (p *Penalty) GenerateProtoBytes() {
var penalizedDelegators []*sgn.AccountAmtPair
var beneficiaries []*sgn.AccountAmtPair
totalPenalty := sdk.ZeroInt()
totalBeneficiary := sdk.ZeroInt()
for _, penalizedDelegator := range p.PenalizedDelegators {
totalPenalty = totalPenalty.Add(penalizedDelegator.Amount)
penalizedDelegators = append(penalizedDelegators, &sgn.AccountAmtPair{
Account: mainchain.Hex2Addr(penalizedDelegator.Account).Bytes(),
Amt: penalizedDelegator.Amount.BigInt().Bytes(),
})
}
for _, beneficiary := range p.Beneficiaries {
amt := beneficiary.Fraction.MulInt(totalPenalty).TruncateInt()
totalBeneficiary = totalBeneficiary.Add(amt)
beneficiaries = append(beneficiaries, &sgn.AccountAmtPair{
Account: mainchain.Hex2Addr(beneficiary.Account).Bytes(),
Amt: amt.BigInt().Bytes(),
})
}
restPenalty := totalPenalty.Sub(totalBeneficiary)
if restPenalty.IsPositive() {
beneficiaries = append(beneficiaries, &sgn.AccountAmtPair{
Account: mainchain.ZeroAddr.Bytes(),
Amt: restPenalty.BigInt().Bytes(),
})
}
penaltyBytes, _ := proto.Marshal(&sgn.Penalty{
Nonce: p.Nonce,
ExpireTime: expireTime,
ValidatorAddress: mainchain.Hex2Addr(p.ValidatorAddr).Bytes(),
PenalizedDelegators: penalizedDelegators,
Beneficiaries: beneficiaries,
})
p.PenaltyProtoBytes = penaltyBytes
}
// Add signature to penalty sigs
func (p *Penalty) AddSig(sig []byte, expectedSigner string) error {
sigs, err := common.AddSig(p.Sigs, p.PenaltyProtoBytes, sig, expectedSigner)
if err != nil {
log.Error(err)
return err
}
p.Sigs = sigs
return nil
}
// Generate penaltyRequest msg
func (p Penalty) GetPenaltyRequest() []byte {
var sigs [][]byte
for _, sig := range p.Sigs {
sigs = append(sigs, sig.Sig)
}
penaltyRequestBytes, _ := proto.Marshal(&sgn.PenaltyRequest{
Penalty: p.PenaltyProtoBytes,
Sigs: sigs,
})
return penaltyRequestBytes
}