-
Notifications
You must be signed in to change notification settings - Fork 145
/
Copy pathdistribution.go
184 lines (157 loc) · 6.45 KB
/
distribution.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
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
package keeper
import (
"strconv"
sdk "github.com/cosmos/cosmos-sdk/types"
sdkerrors "github.com/cosmos/cosmos-sdk/types/errors"
transfertypes "github.com/cosmos/ibc-go/v3/modules/apps/transfer/types"
clienttypes "github.com/cosmos/ibc-go/v3/modules/core/02-client/types"
channeltypes "github.com/cosmos/ibc-go/v3/modules/core/04-channel/types"
"github.com/cosmos/interchain-security/x/ccv/consumer/types"
ccv "github.com/cosmos/interchain-security/x/ccv/types"
)
// Simple model, send tokens to the fee pool of the provider validator set
// reference: cosmos/ibc-go/v3/modules/apps/transfer/keeper/msg_server.go
func (k Keeper) DistributeToProviderValidatorSet(ctx sdk.Context) error {
ltbh, err := k.GetLastTransmissionBlockHeight(ctx)
if err != nil {
return err
}
consumerFeePoolAddr := k.authKeeper.GetModuleAccount(ctx, k.feeCollectorName).GetAddress()
fpTokens := k.bankKeeper.GetAllBalances(ctx, consumerFeePoolAddr)
// split the fee pool, send the consumer's fraction to the consumer redistribution address
frac, err := sdk.NewDecFromStr(k.GetConsumerRedistributionFrac(ctx))
if err != nil {
return err
}
decFPTokens := sdk.NewDecCoinsFromCoins(fpTokens...)
// NOTE the truncated decimal remainder will be sent to the provider fee pool
consRedistrTokens, _ := decFPTokens.MulDec(frac).TruncateDecimal()
err = k.bankKeeper.SendCoinsFromModuleToModule(ctx, k.feeCollectorName,
types.ConsumerRedistributeName, consRedistrTokens)
if err != nil {
return err
}
// Send the remainder to the Provider fee pool over ibc. Buffer these
// through a secondary address on the consumer chain to ensure that the
// tokens do not go through the consumer redistribute split twice in the
// event that the transfer fails the tokens are returned to the consumer
// chain.
remainingTokens := fpTokens.Sub(consRedistrTokens)
err = k.bankKeeper.SendCoinsFromModuleToModule(ctx, k.feeCollectorName,
types.ConsumerToSendToProviderName, remainingTokens)
if err != nil {
return err
}
bpdt := k.GetBlocksPerDistributionTransmission(ctx)
curHeight := ctx.BlockHeight()
if (curHeight - ltbh.Height) < bpdt {
// not enough blocks have passed for a transmission to occur
return nil
}
// empty out the toSendToProviderTokens address
ch := k.GetDistributionTransmissionChannel(ctx)
transferChannel, found := k.channelKeeper.GetChannel(ctx, transfertypes.PortID, ch)
if found && transferChannel.State == channeltypes.OPEN {
tstProviderAddr := k.authKeeper.GetModuleAccount(ctx,
types.ConsumerToSendToProviderName).GetAddress()
tstProviderTokens := k.bankKeeper.GetAllBalances(ctx, tstProviderAddr)
providerAddr := k.GetProviderFeePoolAddrStr(ctx)
timeoutHeight := clienttypes.ZeroHeight()
transferTimeoutPeriod := k.GetTransferTimeoutPeriod(ctx)
timeoutTimestamp := uint64(ctx.BlockTime().Add(transferTimeoutPeriod).UnixNano())
for _, token := range tstProviderTokens {
err := k.ibcTransferKeeper.SendTransfer(ctx,
transfertypes.PortID,
ch,
token,
tstProviderAddr,
providerAddr,
timeoutHeight,
timeoutTimestamp,
)
if err != nil {
return err
}
}
}
newLtbh := types.LastTransmissionBlockHeight{
Height: ctx.BlockHeight(),
}
ctx.EventManager().EmitEvent(
sdk.NewEvent(
ccv.EventTypeFeeDistribution,
sdk.NewAttribute(sdk.AttributeKeyModule, types.ModuleName),
sdk.NewAttribute(ccv.AttributeDistributionCurrentHeight, strconv.Itoa(int(curHeight))),
sdk.NewAttribute(ccv.AttributeDistributionNextHeight, strconv.Itoa(int(curHeight+k.GetBlocksPerDistributionTransmission(ctx)))),
sdk.NewAttribute(ccv.AttributeDistributionFraction, (k.GetConsumerRedistributionFrac(ctx))),
sdk.NewAttribute(ccv.AttributeDistributionTotal, fpTokens.String()),
sdk.NewAttribute(ccv.AttributeDistributionToConsumer, consRedistrTokens.String()),
sdk.NewAttribute(ccv.AttributeDistributionToProvider, remainingTokens.String()),
),
)
return k.SetLastTransmissionBlockHeight(ctx, newLtbh)
}
func (k Keeper) GetLastTransmissionBlockHeight(ctx sdk.Context) (
*types.LastTransmissionBlockHeight, error) {
store := ctx.KVStore(k.storeKey)
bz := store.Get(types.LastDistributionTransmissionKey())
ltbh := &types.LastTransmissionBlockHeight{}
if bz != nil {
err := ltbh.Unmarshal(bz)
if err != nil {
return ltbh, err
}
}
return ltbh, nil
}
func (k Keeper) SetLastTransmissionBlockHeight(ctx sdk.Context,
ltbh types.LastTransmissionBlockHeight) error {
store := ctx.KVStore(k.storeKey)
bz, err := ltbh.Marshal()
if err != nil {
return err
}
store.Set(types.LastDistributionTransmissionKey(), bz)
return nil
}
func (k Keeper) ChannelOpenInit(ctx sdk.Context, msg *channeltypes.MsgChannelOpenInit) (
*channeltypes.MsgChannelOpenInitResponse, error) {
return k.ibcCoreKeeper.ChannelOpenInit(sdk.WrapSDKContext(ctx), msg)
}
func (k Keeper) GetConnectionHops(ctx sdk.Context, srcPort, srcChan string) ([]string, error) {
ch, found := k.channelKeeper.GetChannel(ctx, srcPort, srcChan)
if !found {
return []string{}, sdkerrors.Wrapf(ccv.ErrChannelNotFound,
"cannot get connection hops from non-existent channel")
}
return ch.ConnectionHops, nil
}
// GetEstimatedNextFeeDistribution returns data about next fee distribution. Data represents an estimation of
// accumulated fees at the current block height.
func (k Keeper) GetEstimatedNextFeeDistribution(ctx sdk.Context) (types.NextFeeDistributionEstimate, error) {
lastH, err := k.GetLastTransmissionBlockHeight(ctx)
if err != nil {
return types.NextFeeDistributionEstimate{}, err
}
nextH := lastH.GetHeight() + k.GetBlocksPerDistributionTransmission(ctx)
consumerFeePoolAddr := k.authKeeper.GetModuleAccount(ctx, k.feeCollectorName).GetAddress()
total := k.bankKeeper.GetAllBalances(ctx, consumerFeePoolAddr)
fracParam := k.GetConsumerRedistributionFrac(ctx)
frac, err := sdk.NewDecFromStr(fracParam)
if err != nil {
return types.NextFeeDistributionEstimate{}, err
}
totalTokens := sdk.NewDecCoinsFromCoins(total...)
// truncated decimals are implicitly added to provider
consumerTokens, _ := totalTokens.MulDec(frac).TruncateDecimal()
providerTokens := total.Sub(consumerTokens)
return types.NextFeeDistributionEstimate{
CurrentHeight: ctx.BlockHeight(),
LastHeight: lastH.GetHeight(),
NextHeight: nextH,
DistributionFraction: fracParam,
Total: totalTokens.String(),
ToProvider: sdk.NewDecCoinsFromCoins(providerTokens...).String(),
ToConsumer: sdk.NewDecCoinsFromCoins(consumerTokens...).String(),
}, nil
}