-
Notifications
You must be signed in to change notification settings - Fork 136
/
migration.go
138 lines (120 loc) · 4.64 KB
/
migration.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
package keeper
import (
"fmt"
sdktypes "github.com/cosmos/cosmos-sdk/types"
paramtypes "github.com/cosmos/cosmos-sdk/x/params/types"
providertypes "github.com/cosmos/interchain-security/v3/x/ccv/provider/types"
ccvtypes "github.com/cosmos/interchain-security/v3/x/ccv/types"
)
// Migrator is a struct for handling in-place store migrations.
type Migrator struct {
providerKeeper Keeper
paramSpace paramtypes.Subspace
}
// NewMigrator returns a new Migrator.
func NewMigrator(providerKeeper Keeper, paramSpace paramtypes.Subspace) Migrator {
return Migrator{providerKeeper: providerKeeper, paramSpace: paramSpace}
}
// Migrate2to3 migrates x/ccvprovider state from consensus version 2 to 3.
func (m Migrator) Migrate2to3(ctx sdktypes.Context) error {
return m.providerKeeper.MigrateQueuedPackets(ctx)
}
func (k Keeper) MigrateQueuedPackets(ctx sdktypes.Context) error {
for _, consumer := range k.GetAllConsumerChains(ctx) {
slashData, vscmData := k.GetAllThrottledPacketData(ctx, consumer.ChainId)
if len(slashData) > 0 {
k.Logger(ctx).Error(fmt.Sprintf("slash data being dropped: %v", slashData))
}
for _, data := range vscmData {
k.HandleVSCMaturedPacket(ctx, consumer.ChainId, data)
}
k.DeleteThrottledPacketDataForConsumer(ctx, consumer.ChainId)
}
return nil
}
// Pending packet data type enum, used to encode the type of packet data stored at each entry in the mutual queue.
// Note this type is copy/pasted from throttle v1 code.
const (
slashPacketData byte = iota
vscMaturedPacketData
)
// GetAllThrottledPacketData returns all throttled packet data for a given consumer chain, only used for 2 -> 3 migration.
// Note this method is adapted from throttle v1 code.
func (k Keeper) GetAllThrottledPacketData(ctx sdktypes.Context, consumerChainID string) (
slashData []ccvtypes.SlashPacketData, vscMaturedData []ccvtypes.VSCMaturedPacketData,
) {
slashData = []ccvtypes.SlashPacketData{}
vscMaturedData = []ccvtypes.VSCMaturedPacketData{}
store := ctx.KVStore(k.storeKey)
iteratorPrefix := providertypes.ChainIdWithLenKey(providertypes.ThrottledPacketDataBytePrefix, consumerChainID)
iterator := sdktypes.KVStorePrefixIterator(store, iteratorPrefix)
defer iterator.Close()
for ; iterator.Valid(); iterator.Next() {
bz := iterator.Value()
switch bz[0] {
case slashPacketData:
d := ccvtypes.SlashPacketData{}
if err := d.Unmarshal(bz[1:]); err != nil {
k.Logger(ctx).Error(fmt.Sprintf("failed to unmarshal slash packet data: %v", err))
continue
}
slashData = append(slashData, d)
case vscMaturedPacketData:
d := ccvtypes.VSCMaturedPacketData{}
if err := d.Unmarshal(bz[1:]); err != nil {
k.Logger(ctx).Error(fmt.Sprintf("failed to unmarshal vsc matured packet data: %v", err))
continue
}
vscMaturedData = append(vscMaturedData, d)
default:
k.Logger(ctx).Error(fmt.Sprintf("invalid packet data type: %v", bz[0]))
continue
}
}
return slashData, vscMaturedData
}
// Note this method is copy/pasted from throttle v1 code.
func (k Keeper) DeleteThrottledPacketDataForConsumer(ctx sdktypes.Context, consumerChainID string) {
store := ctx.KVStore(k.storeKey)
iteratorPrefix := providertypes.ChainIdWithLenKey(providertypes.ThrottledPacketDataBytePrefix, consumerChainID)
iterator := sdktypes.KVStorePrefixIterator(store, iteratorPrefix)
defer iterator.Close()
keysToDel := [][]byte{}
for ; iterator.Valid(); iterator.Next() {
keysToDel = append(keysToDel, iterator.Key())
}
// Delete data for this consumer
for _, key := range keysToDel {
store.Delete(key)
}
// Delete size of data queue for this consumer
store.Delete(providertypes.ThrottledPacketDataSizeKey(consumerChainID))
}
// Note this method is adapted from throttle v1 code.
func (k Keeper) QueueThrottledPacketDataOnlyForTesting(
ctx sdktypes.Context, consumerChainID string, ibcSeqNum uint64, packetData interface{},
) error {
store := ctx.KVStore(k.storeKey)
var bz []byte
var err error
switch data := packetData.(type) {
case ccvtypes.SlashPacketData:
bz, err = data.Marshal()
if err != nil {
return fmt.Errorf("failed to marshal slash packet data: %v", err)
}
bz = append([]byte{slashPacketData}, bz...)
case ccvtypes.VSCMaturedPacketData:
bz, err = data.Marshal()
if err != nil {
return fmt.Errorf("failed to marshal vsc matured packet data: %v", err)
}
bz = append([]byte{vscMaturedPacketData}, bz...)
default:
// Indicates a developer error, this method should only be called
// by tests, QueueThrottledSlashPacketData, or QueueThrottledVSCMaturedPacketData.
panic(fmt.Sprintf("unexpected packet data type: %T", data))
}
store.Set(providertypes.ThrottledPacketDataKey(consumerChainID, ibcSeqNum), bz)
return nil
}