/
adapter.go
165 lines (140 loc) · 6.15 KB
/
adapter.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
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
package keeper
import (
"cosmossdk.io/math"
sdk "github.com/cosmos/cosmos-sdk/types"
evidencetypes "github.com/cosmos/cosmos-sdk/x/evidence/types"
slashingtypes "github.com/cosmos/cosmos-sdk/x/slashing/types"
stakingtypes "github.com/cosmos/cosmos-sdk/x/staking/types"
"github.com/osmosis-labs/mesh-security-sdk/x/meshsecurity/types"
)
var _ types.XBankKeeper = &BankKeeperAdapter{}
// BankKeeperAdapter adapter to vanilla SDK bank keeper
type BankKeeperAdapter struct {
types.SDKBankKeeper
}
// NewBankKeeperAdapter constructor
func NewBankKeeperAdapter(k types.SDKBankKeeper) *BankKeeperAdapter {
return &BankKeeperAdapter{SDKBankKeeper: k}
}
// AddSupplyOffset noop
func (b BankKeeperAdapter) AddSupplyOffset(ctx sdk.Context, denom string, offsetAmount math.Int) {
}
var _ types.XStakingKeeper = &StakingKeeperAdapter{}
// StakingKeeperAdapter is an adapter to enhance the vanilla sdk staking keeper with additional functionality
// required for MS. The methods match Osmosis SDK fork.
type StakingKeeperAdapter struct {
types.SDKStakingKeeper
bank types.SDKBankKeeper
}
// NewStakingKeeperAdapter constructor
func NewStakingKeeperAdapter(k types.SDKStakingKeeper, b types.SDKBankKeeper) *StakingKeeperAdapter {
return &StakingKeeperAdapter{SDKStakingKeeper: k, bank: b}
}
// InstantUndelegate allows another module account to undelegate while bypassing unbonding time.
// This function is a combination of Undelegate and CompleteUnbonding,
// but skips the creation and deletion of UnbondingDelegationEntry
//
// The code is copied from the Osmosis SDK fork https://github.com/osmosis-labs/cosmos-sdk/blob/v0.45.0x-osmo-v9.3/x/staking/keeper/delegation.go#L757
func (s StakingKeeperAdapter) InstantUndelegate(ctx sdk.Context, delAddr sdk.AccAddress, valAddr sdk.ValAddress, sharesAmount sdk.Dec) (sdk.Coins, error) {
validator, found := s.GetValidator(ctx, valAddr)
if !found {
return nil, stakingtypes.ErrNoDelegatorForAddress
}
returnAmount, err := s.Unbond(ctx, delAddr, valAddr, sharesAmount)
if err != nil {
return nil, err
}
bondDenom := s.BondDenom(ctx)
amt := sdk.NewCoin(bondDenom, returnAmount)
res := sdk.NewCoins(amt)
moduleName := stakingtypes.NotBondedPoolName
if validator.IsBonded() {
moduleName = stakingtypes.BondedPoolName
}
err = s.bank.UndelegateCoinsFromModuleToAccount(ctx, moduleName, delAddr, res)
if err != nil {
return nil, err
}
return res, nil
}
var _ evidencetypes.SlashingKeeper = SlashingKeeperDecorator{}
// SlashingKeeperDecorator to capture tombstone events
type SlashingKeeperDecorator struct {
evidencetypes.SlashingKeeper
stakingKeeper types.SDKStakingKeeper
k *Keeper
}
// CaptureTombstoneDecorator constructor
func CaptureTombstoneDecorator(k *Keeper, slashingKeeper evidencetypes.SlashingKeeper, stakingKeeper types.SDKStakingKeeper) *SlashingKeeperDecorator {
return &SlashingKeeperDecorator{SlashingKeeper: slashingKeeper, stakingKeeper: stakingKeeper, k: k}
}
// Tombstone is executed in the end-blocker by the evidence module
func (e SlashingKeeperDecorator) Tombstone(ctx sdk.Context, address sdk.ConsAddress) {
v, ok := e.stakingKeeper.GetValidatorByConsAddr(ctx, address)
if !ok {
ModuleLogger(ctx).
Error("can not propagate tompstone: validator not found", "validator", address.String())
} else if err := e.k.ScheduleTombstoned(ctx, v.GetOperator()); err != nil {
ModuleLogger(ctx).
Error("can not propagate tompstone: scheduler",
"cause", err,
"validator", address.String())
}
e.SlashingKeeper.Tombstone(ctx, address)
}
// StakingDecorator decorate vanilla staking keeper to capture the jail and unjail events
type StakingDecorator struct {
slashingtypes.StakingKeeper
k *Keeper
}
// NewStakingDecorator constructor
func NewStakingDecorator(stakingKeeper slashingtypes.StakingKeeper, k *Keeper) *StakingDecorator {
return &StakingDecorator{StakingKeeper: stakingKeeper, k: k}
}
// Slash captures the slash event and calls the decorated staking keeper slash method
func (s StakingDecorator) Slash(ctx sdk.Context, consAddr sdk.ConsAddress, power int64, height int64, slashRatio sdk.Dec) math.Int {
val := s.StakingKeeper.ValidatorByConsAddr(ctx, consAddr)
totalSlashAmount := s.StakingKeeper.Slash(ctx, consAddr, power, height, slashRatio)
if val == nil {
ModuleLogger(ctx).
Error("can not propagate slash: validator not found", "validator", consAddr.String())
} else if err := s.k.ScheduleSlashed(ctx, val.GetOperator(), power, height, totalSlashAmount, slashRatio); err != nil {
ModuleLogger(ctx).
Error("can not propagate slash: schedule event",
"cause", err,
"validator", consAddr.String())
}
return totalSlashAmount
}
// SlashWithInfractionReason implementation doesn't require the infraction (types.Infraction) to work but is required by Interchain Security.
func (s StakingDecorator) SlashWithInfractionReason(ctx sdk.Context, consAddr sdk.ConsAddress, infractionHeight int64, power int64, slashFactor sdk.Dec, _ stakingtypes.Infraction) math.Int {
return s.Slash(ctx, consAddr, infractionHeight, power, slashFactor)
}
// Jail captures the jail event and calls the decorated staking keeper jail method
func (s StakingDecorator) Jail(ctx sdk.Context, consAddr sdk.ConsAddress) {
val := s.StakingKeeper.ValidatorByConsAddr(ctx, consAddr)
if val == nil {
ModuleLogger(ctx).
Error("can not propagate jail: validator not found", "validator", consAddr.String())
} else if err := s.k.ScheduleJailed(ctx, val.GetOperator()); err != nil {
ModuleLogger(ctx).
Error("can not propagate jail: schedule event",
"cause", err,
"validator", consAddr.String())
}
s.StakingKeeper.Jail(ctx, consAddr)
}
// Unjail captures the unjail event and calls the decorated staking keeper unjail method
func (s StakingDecorator) Unjail(ctx sdk.Context, consAddr sdk.ConsAddress) {
val := s.StakingKeeper.ValidatorByConsAddr(ctx, consAddr)
if val == nil {
ModuleLogger(ctx).
Error("can not propagate unjail: validator not found", "validator", consAddr.String())
} else if err := s.k.ScheduleUnjailed(ctx, val.GetOperator()); err != nil {
ModuleLogger(ctx).
Error("can not propagate unjail: schedule event",
"cause", err,
"validator", consAddr.String())
}
s.StakingKeeper.Unjail(ctx, consAddr)
}