/
store.go
101 lines (82 loc) · 2.99 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
package v3
import (
"github.com/cosmos/cosmos-sdk/codec"
"github.com/cosmos/cosmos-sdk/store/prefix"
storetypes "github.com/cosmos/cosmos-sdk/store/types"
sdk "github.com/cosmos/cosmos-sdk/types"
poststypes "github.com/desmos-labs/desmos/v6/x/posts/types"
"github.com/desmos-labs/desmos/v6/x/reactions/types"
)
// MigrateStore performs in-place store migrations from v2 to v3
// It removes all the duplicated reactions and fix missing reaction ids.
func MigrateStore(ctx sdk.Context, storeKey storetypes.StoreKey, pk types.PostsKeeper, cdc codec.BinaryCodec) error {
err := RemoveDuplicatedReactions(ctx, storeKey, cdc)
if err != nil {
return err
}
return FixMissingNextReactionIDs(ctx, storeKey, pk, cdc)
}
// RemoveDuplicatedReactions removes all the duplicated reactions
func RemoveDuplicatedReactions(ctx sdk.Context, storeKey storetypes.StoreKey, cdc codec.BinaryCodec) error {
store := ctx.KVStore(storeKey)
reactionsStore := prefix.NewStore(store, types.ReactionPrefix)
iter := reactionsStore.Iterator(nil, nil)
defer iter.Close()
// Get duplicated reactions
var reactions []types.Reaction
var duplicatedReactions []types.Reaction
for ; iter.Valid(); iter.Next() {
var reaction types.Reaction
err := cdc.Unmarshal(iter.Value(), &reaction)
if err != nil {
return err
}
reactions = append(reactions, reaction)
if contains(reactions, reaction) {
duplicatedReactions = append(duplicatedReactions, reaction)
}
}
// Remove duplicated reactions
for _, reaction := range duplicatedReactions {
store.Delete(types.ReactionStoreKey(reaction.SubspaceID, reaction.PostID, reaction.ID))
}
return nil
}
func contains(reactions []types.Reaction, reaction types.Reaction) bool {
var count = 0
for _, r := range reactions {
if r.SubspaceID == reaction.SubspaceID &&
r.PostID == reaction.PostID &&
r.Author == reaction.Author &&
r.Value.Equal(reaction.Value) {
count++
}
}
return count > 1
}
// --------------------------------------------------------------------------------------------------------------------
// FixMissingNextReactionIDs fixes the missing next reaction ids for existing posts
func FixMissingNextReactionIDs(ctx sdk.Context, storeKey storetypes.StoreKey, pk types.PostsKeeper, cdc codec.BinaryCodec) error {
store := ctx.KVStore(storeKey)
pk.IteratePosts(ctx, func(post poststypes.Post) bool {
// Skip if the next reaction ID key exists
if store.Has(types.NextReactionIDStoreKey(post.SubspaceID, post.ID)) {
return false
}
// Get max reaction ID of the post
iter := sdk.KVStorePrefixIterator(store, types.PostReactionsPrefix(post.SubspaceID, post.ID))
maxReactionID := uint32(0)
for ; iter.Valid(); iter.Next() {
var reaction types.Reaction
cdc.MustUnmarshal(iter.Value(), &reaction)
if reaction.ID > maxReactionID {
maxReactionID = reaction.ID
}
}
iter.Close()
// Set next reaction id
store.Set(types.NextReactionIDStoreKey(post.SubspaceID, post.ID), types.GetReactionIDBytes(maxReactionID+1))
return false
})
return nil
}