-
Notifications
You must be signed in to change notification settings - Fork 1
/
store.go
337 lines (282 loc) · 10.4 KB
/
store.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
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
package v6
import (
"fmt"
codectypes "github.com/cosmos/cosmos-sdk/codec/types"
cryptotypes "github.com/cosmos/cosmos-sdk/crypto/types"
v5types "github.com/gridiron-zone/huddle/x/profiles/legacy/v5/types"
"github.com/cosmos/cosmos-sdk/store/prefix"
"github.com/cosmos/cosmos-sdk/codec"
sdk "github.com/cosmos/cosmos-sdk/types"
authkeeper "github.com/cosmos/cosmos-sdk/x/auth/keeper"
authtypes "github.com/cosmos/cosmos-sdk/x/auth/types"
"github.com/cosmos/cosmos-sdk/types/tx/signing"
"github.com/gridiron-zone/huddle/x/profiles/types"
)
// MigrateStore performs in-place store migrations from v6 to v7.
// The migration includes:
//
// - migrating all the profiles to have the proper Protobuf type
// - add the expiration date to all application links
// - set the default external address to oldest chain link of each chain for each owner
func MigrateStore(ctx sdk.Context, ak authkeeper.AccountKeeper, storeKey sdk.StoreKey, amino *codec.LegacyAmino, cdc codec.BinaryCodec) error {
store := ctx.KVStore(storeKey)
// Migrate the profiles
err := migrateProfiles(ctx, ak)
if err != nil {
return err
}
// Migrate all the application links
err = migrateApplicationLinks(store, cdc)
if err != nil {
return err
}
// Migrate all the chain links
err = migrateChainLinks(store, cdc)
if err != nil {
return err
}
// Set the default external addresses
err = setDefaultExternalAddresses(store, cdc)
if err != nil {
return err
}
return nil
}
// migrateProfiles migrates the profiles from v5 to v7 to properly update the Protobuf name.
// The migration from v5 to v6 is skipped because the two types are identical (from v5 to v6 no changes were made).
func migrateProfiles(ctx sdk.Context, ak authkeeper.AccountKeeper) error {
var profiles []*v5types.Profile
ak.IterateAccounts(ctx, func(account authtypes.AccountI) (stop bool) {
if profile, ok := account.(*v5types.Profile); ok {
profiles = append(profiles, profile)
}
return false
})
for _, profile := range profiles {
// Convert the profile
v7Profile, err := types.NewProfile(
profile.DTag,
profile.Nickname,
profile.Bio,
types.NewPictures(profile.Pictures.Profile, profile.Pictures.Cover),
profile.CreationDate,
profile.GetAccount(),
)
if err != nil {
return err
}
// Set the account
ak.SetAccount(ctx, v7Profile)
}
return nil
}
// migrateApplicationLinks migrates the application links from v5 to v7 adding the expiration date properly.
// The migration from v5 to v6 is skipped because the two types are identical (from v5 to v6 no changes were made).
func migrateApplicationLinks(store sdk.KVStore, cdc codec.BinaryCodec) error {
appLinksStore := prefix.NewStore(store, types.ApplicationLinkPrefix)
iterator := appLinksStore.Iterator(nil, nil)
var applicationLinks []v5types.ApplicationLink
for ; iterator.Valid(); iterator.Next() {
var applicationLink v5types.ApplicationLink
err := cdc.Unmarshal(iterator.Value(), &applicationLink)
if err != nil {
return err
}
applicationLinks = append(applicationLinks, applicationLink)
}
for _, v5Link := range applicationLinks {
// Migrate the link
v7Link := types.NewApplicationLink(
v5Link.User,
convertApplicationLinkData(v5Link.Data),
convertApplicationLinkState(v5Link.State),
convertApplicationLinkOracleRequest(v5Link.OracleRequest),
convertApplicationLinkResult(v5Link.Result),
v5Link.CreationTime,
v5Link.CreationTime.Add(types.DefaultAppLinksValidityDuration),
)
// Store the application link
userApplicationLinkKey := types.UserApplicationLinkKey(v7Link.User, v7Link.Data.Application, v7Link.Data.Username)
store.Set(userApplicationLinkKey, cdc.MustMarshal(&v7Link))
// Store the expiration time
applicationLinkExpiringTimeKey := types.ApplicationLinkExpiringTimeKey(v7Link.ExpirationTime, v7Link.OracleRequest.ClientID)
store.Set(applicationLinkExpiringTimeKey, []byte(v7Link.OracleRequest.ClientID))
}
return nil
}
func convertApplicationLinkData(v5Data v5types.Data) types.Data {
return types.NewData(v5Data.Application, v5Data.Username)
}
func convertApplicationLinkState(v5State v5types.ApplicationLinkState) types.ApplicationLinkState {
switch v5State {
case v5types.ApplicationLinkStateInitialized:
return types.ApplicationLinkStateInitialized
case v5types.AppLinkStateVerificationStarted:
return types.AppLinkStateVerificationStarted
case v5types.AppLinkStateVerificationError:
return types.AppLinkStateVerificationError
case v5types.AppLinkStateVerificationSuccess:
return types.AppLinkStateVerificationSuccess
case v5types.AppLinkStateVerificationTimedOut:
return types.AppLinkStateVerificationTimedOut
default:
panic(fmt.Errorf("invalid application link state: %s", v5State))
}
}
func convertApplicationLinkOracleRequest(v5Request v5types.OracleRequest) types.OracleRequest {
return types.NewOracleRequest(
v5Request.ID,
v5Request.OracleScriptID,
types.NewOracleRequestCallData(v5Request.CallData.Application, v5Request.CallData.CallData),
v5Request.ClientID,
)
}
func convertApplicationLinkResult(v5Result *v5types.Result) *types.Result {
if v5Result == nil {
return nil
}
switch result := v5Result.Sum.(type) {
case *v5types.Result_Success_:
return types.NewSuccessResult(result.Success.Value, result.Success.Signature)
case *v5types.Result_Failed_:
return types.NewErrorResult(result.Failed.Error)
default:
panic(fmt.Errorf("invalid result type: %T", v5Result.Sum))
}
}
// migrateChainLinks migrates the chain links from v5 to v7 by changing the various Protobuf interface types.
// The migration from v5 to v6 is skipped because the two types are identical (from v5 to v6 no changes were made).
func migrateChainLinks(store sdk.KVStore, cdc codec.BinaryCodec) error {
appLinksStore := prefix.NewStore(store, types.ChainLinksPrefix)
iterator := appLinksStore.Iterator(nil, nil)
var applicationLinks []v5types.ChainLink
for ; iterator.Valid(); iterator.Next() {
var applicationLink v5types.ChainLink
err := cdc.Unmarshal(iterator.Value(), &applicationLink)
if err != nil {
return err
}
applicationLinks = append(applicationLinks, applicationLink)
}
for _, v5Link := range applicationLinks {
// Migrate the link
v7Link := types.NewChainLink(
v5Link.User,
convertChainLinkAddressData(v5Link.GetAddressData()),
convertChainLinkProof(v5Link.Proof, cdc),
types.NewChainConfig(v5Link.ChainConfig.Name),
v5Link.CreationTime,
)
// Store the chain link
userApplicationLinkKey := types.ChainLinksStoreKey(v7Link.User, v7Link.ChainConfig.Name, v7Link.GetAddressData().GetValue())
store.Set(userApplicationLinkKey, cdc.MustMarshal(&v7Link))
}
return nil
}
func convertChainLinkAddressData(v5Signature v5types.AddressData) types.AddressData {
switch address := v5Signature.(type) {
case *v5types.Bech32Address:
return types.NewBech32Address(address.Value, address.Prefix)
case *v5types.Base58Address:
return types.NewBase58Address(address.Value)
case *v5types.HexAddress:
return types.NewHexAddress(address.Value, address.Prefix)
default:
panic(fmt.Errorf("invalid signature type: %T", v5Signature))
}
}
func convertChainLinkProof(v5Proof v5types.Proof, cdc codec.BinaryCodec) types.Proof {
var pubKey cryptotypes.PubKey
err := cdc.UnpackAny(v5Proof.PubKey, &pubKey)
if err != nil {
panic(err)
}
var v6Signature types.Signature
v6SignatureAny := convertChainLinkSignatureData(v5Proof.Signature, cdc)
err = cdc.UnpackAny(v6SignatureAny, &v6Signature)
if err != nil {
panic(err)
}
return types.NewProof(pubKey, v6Signature, v5Proof.PlainText)
}
func convertChainLinkSignatureData(data *codectypes.Any, cdc codec.BinaryCodec) *codectypes.Any {
var v5Signature v5types.SignatureData
err := cdc.UnpackAny(data, &v5Signature)
if err != nil {
panic(err)
}
var signatureAny *codectypes.Any
switch signature := v5Signature.(type) {
case *v5types.SingleSignatureData:
var signingMode types.SignatureValueType
switch signature.Mode {
case signing.SignMode_SIGN_MODE_DIRECT:
signingMode = types.SIGNATURE_VALUE_TYPE_COSMOS_DIRECT
case signing.SignMode_SIGN_MODE_LEGACY_AMINO_JSON:
signingMode = types.SIGNATURE_VALUE_TYPE_COSMOS_AMINO
case signing.SignMode_SIGN_MODE_TEXTUAL:
signingMode = types.SIGNATURE_VALUE_TYPE_RAW
default:
panic(fmt.Sprintf("unsupported signing mode: %s", signature.Mode))
}
v6Signature := types.NewSingleSignature(signingMode, signature.Signature)
signatureAny, err = codectypes.NewAnyWithValue(v6Signature)
if err != nil {
panic(err)
}
case *v5types.MultiSignatureData:
signatures := make([]types.Signature, len(signature.Signatures))
for i, sig := range signature.Signatures {
// Recursively convert the signature any
sigAny := convertChainLinkSignatureData(sig, cdc)
// Unpack the signature
var cosmosSig types.Signature
err = cdc.UnpackAny(sigAny, &cosmosSig)
if err != nil {
panic(err)
}
signatures[i] = cosmosSig
}
// Build the signature
v6Signature := types.NewCosmosMultiSignature(signature.BitArray, signatures)
// Convert it as an Any
signatureAny, err = codectypes.NewAnyWithValue(v6Signature)
if err != nil {
panic(err)
}
}
return signatureAny
}
// setDefaultExternalAddresses set the default external address of each chain for each owner
func setDefaultExternalAddresses(store sdk.KVStore, cdc codec.BinaryCodec) error {
chainLinkStore := prefix.NewStore(store, types.ChainLinksPrefix)
chainLinksIterator := chainLinkStore.Iterator(nil, nil)
defer chainLinksIterator.Close()
for ; chainLinksIterator.Valid(); chainLinksIterator.Next() {
var link types.ChainLink
err := cdc.Unmarshal(chainLinksIterator.Value(), &link)
if err != nil {
return err
}
// Validate the source address
srcAddrData, err := types.UnpackAddressData(cdc, link.Address)
if err != nil {
return err
}
// Update default external address if the key exists
if store.Has(types.DefaultExternalAddressKey(link.User, link.ChainConfig.Name)) {
addrBz := store.Get(types.DefaultExternalAddressKey(link.User, link.ChainConfig.Name))
var defaultLink types.ChainLink
err := cdc.Unmarshal(store.Get(types.ChainLinksStoreKey(link.User, link.ChainConfig.Name, string(addrBz))), &defaultLink)
if err != nil {
return err
}
// Skip if the new link is after the default one
if link.CreationTime.After(defaultLink.CreationTime) {
continue
}
}
store.Set(types.DefaultExternalAddressKey(link.User, link.ChainConfig.Name), []byte(srcAddrData.GetValue()))
}
return nil
}