-
Notifications
You must be signed in to change notification settings - Fork 44
/
invariants.go
204 lines (164 loc) · 6.35 KB
/
invariants.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
package keeper
import (
"fmt"
sdk "github.com/cosmos/cosmos-sdk/types"
"github.com/desmos-labs/desmos/v5/x/reactions/types"
subspaceskeeper "github.com/desmos-labs/desmos/v5/x/subspaces/keeper"
subspacestypes "github.com/desmos-labs/desmos/v5/x/subspaces/types"
)
// RegisterInvariants registers all reactions invariants
func RegisterInvariants(ir sdk.InvariantRegistry, keeper Keeper) {
ir.RegisterRoute(types.ModuleName, "valid-subspaces",
ValidSubspacesInvariant(keeper))
ir.RegisterRoute(types.ModuleName, "valid-registered-reactions",
ValidRegisteredReactionsInvariant(keeper))
ir.RegisterRoute(types.ModuleName, "valid-reactions",
ValidReactionsInvariant(keeper))
ir.RegisterRoute(types.ModuleName, "valid-reactions-params",
ValidReactionsParamsInvariant(keeper))
}
// --------------------------------------------------------------------------------------------------------------------
// ValidSubspacesInvariant checks that all the subspaces have a valid registered reaction id and reaction params
func ValidSubspacesInvariant(k Keeper) sdk.Invariant {
return func(ctx sdk.Context) (message string, broken bool) {
var invalidSubspaces []subspacestypes.Subspace
k.sk.IterateSubspaces(ctx, func(subspace subspacestypes.Subspace) (stop bool) {
invalid := false
// Make sure the next registered reaction id exists
if !k.HasNextRegisteredReactionID(ctx, subspace.ID) {
invalid = true
}
// Make sure the reactions params exist
if !k.HasSubspaceReactionsParams(ctx, subspace.ID) {
invalid = true
}
if invalid {
invalidSubspaces = append(invalidSubspaces, subspace)
}
return false
})
return sdk.FormatInvariant(types.ModuleName, "invalid subspaces",
fmt.Sprintf("the following subspaces are invalid:\n%s", subspaceskeeper.FormatOutputSubspaces(invalidSubspaces)),
), invalidSubspaces != nil
}
}
// --------------------------------------------------------------------------------------------------------------------
// ValidRegisteredReactionsInvariant checks that all the stored registered reactions are valid
func ValidRegisteredReactionsInvariant(k Keeper) sdk.Invariant {
return func(ctx sdk.Context) (string, bool) {
var invalidReactions []types.RegisteredReaction
k.IterateRegisteredReactions(ctx, func(reaction types.RegisteredReaction) (stop bool) {
invalid := false
// Make sure the subspace exists
if !k.HasSubspace(ctx, reaction.SubspaceID) {
invalid = true
}
nextRegisteredReactionID, err := k.GetNextRegisteredReactionID(ctx, reaction.SubspaceID)
if err != nil {
invalid = true
}
// Make sure the registered reaction id is always less than the next one
if reaction.ID >= nextRegisteredReactionID {
invalid = true
}
// Validate the reaction
err = reaction.Validate()
if err != nil {
invalid = true
}
if invalid {
invalidReactions = append(invalidReactions, reaction)
}
return false
})
return sdk.FormatInvariant(types.ModuleName, "invalid registered reactions",
fmt.Sprintf("the following registered reactions are invalid:\n%s", formatOutputRegisteredReactions(invalidReactions)),
), invalidReactions != nil
}
}
// formatOutputRegisteredReactions concatenates the given registered reactions information into a string
func formatOutputRegisteredReactions(reactions []types.RegisteredReaction) (output string) {
for _, reaction := range reactions {
output += fmt.Sprintf("SuspaceID: %d, RegisteredReactionID: %d\n", reaction.SubspaceID, reaction.ID)
}
return output
}
// --------------------------------------------------------------------------------------------------------------------
// ValidReactionsInvariant checks that all the stored reactions are valid
func ValidReactionsInvariant(k Keeper) sdk.Invariant {
return func(ctx sdk.Context) (string, bool) {
var invalidReactions []types.Reaction
k.IterateReactions(ctx, func(reaction types.Reaction) (stop bool) {
invalid := false
// Make sure the subspace exists
if !k.HasSubspace(ctx, reaction.SubspaceID) {
invalid = true
}
// Make sure the post exists
if !k.HasPost(ctx, reaction.SubspaceID, reaction.PostID) {
invalid = true
}
nextReactionID, err := k.GetNextReactionID(ctx, reaction.SubspaceID, reaction.PostID)
if err != nil {
invalid = true
}
// Make sure the reaction id is always less than the next one
if reaction.ID >= nextReactionID {
invalid = true
}
// Validate the reaction
err = reaction.Validate()
if err != nil {
invalid = true
}
if invalid {
invalidReactions = append(invalidReactions, reaction)
}
return false
})
return sdk.FormatInvariant(types.ModuleName, "invalid reactions",
fmt.Sprintf("the following reactions are invalid:\n%s", formatOutputReactions(invalidReactions)),
), invalidReactions != nil
}
}
// formatOutputReactions concatenates the given reactions information into a string
func formatOutputReactions(reactions []types.Reaction) (output string) {
for _, reaction := range reactions {
output += fmt.Sprintf("SuspaceID: %d, PostID: %d, ReactionID: %d\n",
reaction.SubspaceID, reaction.PostID, reaction.ID)
}
return output
}
// --------------------------------------------------------------------------------------------------------------------
// ValidReactionsParamsInvariant checks that all the stored reactions params are valid
func ValidReactionsParamsInvariant(k Keeper) sdk.Invariant {
return func(ctx sdk.Context) (string, bool) {
var invalidParams []types.SubspaceReactionsParams
k.IterateReactionsParams(ctx, func(params types.SubspaceReactionsParams) (stop bool) {
invalid := false
// Make sure the subspace exists
if !k.HasSubspace(ctx, params.SubspaceID) {
invalid = true
}
// Validate the params
err := params.Validate()
if err != nil {
invalid = true
}
if invalid {
invalidParams = append(invalidParams, params)
}
return false
})
return sdk.FormatInvariant(types.ModuleName, "invalid reactions params",
fmt.Sprintf("the following reactions params are invalid:\n%s", formatOutputParams(invalidParams)),
), invalidParams != nil
}
}
// formatOutputParams concatenates the given reactions params information into a string
func formatOutputParams(reasons []types.SubspaceReactionsParams) (output string) {
for _, reason := range reasons {
output += fmt.Sprintf("SuspaceID: %d\n", reason.SubspaceID)
}
return output
}