valopers_test.gno
22.06 Kb · 699 lines
1package valopers
2
3import (
4 "chain"
5 "strings"
6 "testing"
7
8 "gno.land/p/nt/avl/v0"
9 "gno.land/p/nt/bptree/v0"
10 "gno.land/p/nt/ownable/v0/exts/authorizable"
11 "gno.land/p/nt/testutils/v0"
12 "gno.land/p/nt/uassert/v0"
13 "gno.land/p/nt/ufmt/v0"
14)
15
16// Test-local fee constant. Production reads register_fee from sysparams;
17// these tests use this value as a reference Coin for OriginSend setup
18// and (when needed) seed it via testing.SetSysParamUint64.
19var minFee = chain.NewCoin("ugnot", 20*1_000_000)
20
21// cur is a zero-value realm used as a placeholder when forwarding to
22// uassert dispatch helpers that gained an `rlm realm` param. These tests
23// pass `func()` callbacks (no crossing inside the callback), so rlm is
24// ignored — a nil realm here is safe.
25var cur realm
26
27// resetState clears realm-level state and zeroes the valoper sys-params
28// so subtests don't leak through valopers (operator slots),
29// signingRegistry (signing-address uniqueness), or sys-param values.
30func resetState() {
31 valopers = avl.NewTree()
32 signingRegistry = bptree.NewBPTree32()
33 testing.SetSysParamUint64("node", "valoper", "register_fee", 0)
34 testing.SetSysParamUint64("node", "valoper", "rotation_fee", 0)
35 testing.SetSysParamInt64("node", "valoper", "rotation_period_blocks", 600)
36}
37
38// enableRegisterFee seeds register_fee = minFee.Amount in sysparams
39// so the Register fee path fires. Subtests that exercise fee
40// rejection or sufficient-fee acceptance call this after resetState.
41func enableRegisterFee() {
42 testing.SetSysParamUint64("node", "valoper", "register_fee", uint64(minFee.Amount))
43}
44
45func validValidatorInfo(t *testing.T) struct {
46 Moniker string
47 Description string
48 ServerType string
49 Address address
50 PubKey string
51} {
52 t.Helper()
53
54 return struct {
55 Moniker string
56 Description string
57 ServerType string
58 Address address
59 PubKey string
60 }{
61 Moniker: "test-1",
62 Description: "test-1's description",
63 ServerType: ServerTypeOnPrem,
64 Address: address("g1sp8v98h2gadm5jggtzz9w5ksexqn68ympsd68h"),
65 PubKey: "gpub1pggj7ard9eg82cjtv4u52epjx56nzwgjyg9zqwpdwpd0f9fvqla089ndw5g9hcsufad77fml2vlu73fk8q8sh8v72cza5p",
66 }
67}
68
69func TestValopers_Register(cur realm, t *testing.T) {
70 t.Run("already a valoper", func(cur realm, t *testing.T) {
71 resetState()
72
73 info := validValidatorInfo(t)
74 testing.SetRealm(testing.NewUserRealm(info.Address))
75
76 v := Valoper{
77 Moniker: info.Moniker,
78 Description: info.Description,
79 ServerType: info.ServerType,
80 OperatorAddress: info.Address,
81 SigningPubKey: info.PubKey,
82 KeepRunning: true,
83 }
84
85 // Add the valoper directly to the slot.
86 valopers.Set(v.OperatorAddress.String(), v)
87
88 // Send coins.
89 testing.SetOriginSend(chain.Coins{minFee})
90
91 uassert.AbortsWithMessage(t, cur, ErrValoperExists.Error(), func() {
92 Register(cross(cur), info.Moniker, info.Description, info.ServerType, info.Address, info.PubKey)
93 })
94 })
95
96 t.Run("no coins deposited", func(cur realm, t *testing.T) {
97 resetState()
98 enableRegisterFee()
99
100 info := validValidatorInfo(t)
101 testing.SetRealm(testing.NewUserRealm(info.Address))
102
103 // Send no coins.
104 testing.SetOriginSend(chain.Coins{chain.NewCoin("ugnot", 0)})
105
106 uassert.AbortsWithMessage(t, cur, ufmt.Sprintf("payment must not be less than %d%s", minFee.Amount, minFee.Denom), func() {
107 Register(cross(cur), info.Moniker, info.Description, info.ServerType, info.Address, info.PubKey)
108 })
109 })
110
111 t.Run("insufficient coins amount deposited", func(cur realm, t *testing.T) {
112 resetState()
113 enableRegisterFee()
114
115 info := validValidatorInfo(t)
116 testing.SetRealm(testing.NewUserRealm(info.Address))
117
118 // Send invalid coins.
119 testing.SetOriginSend(chain.Coins{chain.NewCoin("ugnot", minFee.Amount-1)})
120
121 uassert.AbortsWithMessage(t, cur, ufmt.Sprintf("payment must not be less than %d%s", minFee.Amount, minFee.Denom), func() {
122 Register(cross(cur), info.Moniker, info.Description, info.ServerType, info.Address, info.PubKey)
123 })
124 })
125
126 t.Run("coin amount deposited is not ugnot", func(cur realm, t *testing.T) {
127 resetState()
128 enableRegisterFee()
129
130 info := validValidatorInfo(t)
131 testing.SetRealm(testing.NewUserRealm(info.Address))
132
133 // Send invalid coins.
134 testing.SetOriginSend(chain.Coins{chain.NewCoin("gnogno", minFee.Amount)})
135
136 uassert.AbortsWithMessage(t, cur, "incompatible coin denominations: gnogno, ugnot", func() {
137 Register(cross(cur), info.Moniker, info.Description, info.ServerType, info.Address, info.PubKey)
138 })
139 })
140
141 t.Run("squat guard rejects mismatched OriginCaller", func(cur realm, t *testing.T) {
142 resetState()
143
144 info := validValidatorInfo(t)
145 // Caller is NOT info.Address: post-genesis squat guard fires.
146 testing.SetRealm(testing.NewUserRealm(testutils.TestAddress("attacker")))
147 testing.SetOriginSend(chain.Coins{minFee})
148
149 uassert.AbortsWithMessage(t, cur, ErrOperatorSquatGuard.Error(), func() {
150 Register(cross(cur), info.Moniker, info.Description, info.ServerType, info.Address, info.PubKey)
151 })
152 })
153
154 t.Run("successful registration", func(cur realm, t *testing.T) {
155 resetState()
156
157 info := validValidatorInfo(t)
158 testing.SetRealm(testing.NewUserRealm(info.Address))
159
160 // Send coins.
161 testing.SetOriginSend(chain.Coins{minFee})
162
163 uassert.NotAborts(t, cur, func() {
164 Register(cross(cur), info.Moniker, info.Description, info.ServerType, info.Address, info.PubKey)
165 })
166
167 uassert.NotPanics(t, cur, func() {
168 valoper := GetByAddr(info.Address)
169
170 uassert.Equal(t, info.Moniker, valoper.Moniker)
171 uassert.Equal(t, info.Description, valoper.Description)
172 uassert.Equal(t, info.ServerType, valoper.ServerType)
173 uassert.Equal(t, info.Address, valoper.OperatorAddress)
174 uassert.Equal(t, info.PubKey, valoper.SigningPubKey)
175 uassert.Equal(t, true, valoper.KeepRunning)
176
177 // SigningAddress is derived from the pubkey and present.
178 derived, err := chain.PubKeyAddress(info.PubKey)
179 uassert.NoError(t, err)
180 uassert.Equal(t, derived, valoper.SigningAddress)
181
182 // signingRegistry tracks the active entry.
183 _, exists := signingRegistry.Get(derived.String())
184 uassert.True(t, exists, "signingRegistry must contain the active entry")
185 })
186 })
187
188 t.Run("signing-key reuse rejected", func(cur realm, t *testing.T) {
189 resetState()
190
191 info := validValidatorInfo(t)
192 testing.SetRealm(testing.NewUserRealm(info.Address))
193 testing.SetOriginSend(chain.Coins{minFee})
194
195 // First registration succeeds.
196 uassert.NotAborts(t, cur, func() {
197 Register(cross(cur), info.Moniker, info.Description, info.ServerType, info.Address, info.PubKey)
198 })
199
200 // Second attempt with a different operator addr but the same
201 // pubkey must fail signingRegistry uniqueness.
202 other := testutils.TestAddress("other-op")
203 testing.SetRealm(testing.NewUserRealm(other))
204 testing.SetOriginSend(chain.Coins{minFee})
205
206 uassert.AbortsWithMessage(t, cur, ErrSigningKeyTaken.Error(), func() {
207 Register(cross(cur), info.Moniker, info.Description, info.ServerType, other, info.PubKey)
208 })
209 })
210
211 t.Run("front-running guard rejects post-genesis if signing addr already validates", func(cur realm, t *testing.T) {
212 resetState()
213
214 info := validValidatorInfo(t)
215 // Seed v3's valset:current with the very signing address that
216 // `info.PubKey` derives to (g1sp8v98...). Any post-genesis
217 // Register attempting the same pubkey now trips
218 // `ChainHeight()>0 && validators.IsValidator(signingAddr)`.
219 testing.SetSysParamStrings("node", "valset", "current", []string{info.PubKey + ":1"})
220
221 testing.SetRealm(testing.NewUserRealm(info.Address))
222 testing.SetOriginSend(chain.Coins{minFee})
223
224 uassert.AbortsWithMessage(t, cur, ErrFrontrunValidator.Error(), func() {
225 Register(cross(cur), info.Moniker, info.Description, info.ServerType, info.Address, info.PubKey)
226 })
227
228 // Cleanup: clear the seeded valset to avoid leaking into
229 // later subtests if the package state isn't reset between
230 // them in this test runner mode.
231 testing.SetSysParamStrings("node", "valset", "current", []string{})
232 })
233}
234
235func TestValopers_Register_AuthOwnerIsOperatorAddress(cur realm, t *testing.T) {
236 // Pin: the Authorizable owner is bound to the OperatorAddress
237 // (the addr arg), NOT to OriginCaller. This matters in the
238 // genesis-mode deployer pattern: one signer (e.g., the hardfork
239 // ceremony deployer) registers profiles for many operators.
240 // Each operator must end up on their own profile's auth list
241 // so they can manage it post-genesis without depending on the
242 // deployer.
243 t.Run("genesis deployer pattern: operator (not deployer) is owner", func(cur realm, t *testing.T) {
244 resetState()
245
246 info := validValidatorInfo(t)
247 deployer := testutils.TestAddress("deployer")
248
249 // Genesis mode: ChainHeight()==0 bypasses the squat guard so
250 // deployer (OriginCaller) can register a profile for a
251 // different operator addr.
252 testing.SetHeight(0)
253 testing.SetRealm(testing.NewUserRealm(deployer))
254 testing.SetOriginCaller(deployer)
255 testing.SetOriginSend(chain.Coins{minFee})
256
257 uassert.NotPanics(t, cur, func() {
258 Register(cross(cur), info.Moniker, info.Description, info.ServerType, info.Address, info.PubKey)
259 })
260
261 // Auth owner must be the operator addr (info.Address), NOT
262 // the deployer.
263 v := GetByAddr(info.Address)
264 uassert.Equal(t, info.Address.String(), v.Auth().Owner().String(),
265 "auth owner must equal OperatorAddress, not OriginCaller")
266
267 // Operator can manage their own profile post-genesis.
268 testing.SetHeight(100)
269 testing.SetRealm(testing.NewUserRealm(info.Address))
270 testing.SetOriginCaller(info.Address)
271 uassert.NotPanics(t, cur, func() {
272 UpdateMoniker(cross(cur), info.Address, "operator-renamed")
273 })
274 uassert.Equal(t, "operator-renamed", GetByAddr(info.Address).Moniker)
275
276 // Deployer cannot manage the operator's profile (not on the
277 // auth list).
278 testing.SetRealm(testing.NewUserRealm(deployer))
279 testing.SetOriginCaller(deployer)
280 uassert.AbortsContains(t, cur, "caller is not in authorized list", func() {
281 UpdateMoniker(cross(cur), info.Address, "deployer-attempt")
282 })
283 })
284
285 t.Run("post-genesis self-Register: operator is owner", func(cur realm, t *testing.T) {
286 // At H>0 the squat guard forces OriginCaller==addr, so owner
287 // would be the same regardless. This subtest pins that the
288 // post-genesis behavior is unchanged.
289 resetState()
290
291 info := validValidatorInfo(t)
292 testing.SetHeight(100)
293 testing.SetRealm(testing.NewUserRealm(info.Address))
294 testing.SetOriginCaller(info.Address)
295 testing.SetOriginSend(chain.Coins{minFee})
296
297 uassert.NotPanics(t, cur, func() {
298 Register(cross(cur), info.Moniker, info.Description, info.ServerType, info.Address, info.PubKey)
299 })
300
301 v := GetByAddr(info.Address)
302 uassert.Equal(t, info.Address.String(), v.Auth().Owner().String())
303 })
304}
305
306func TestValopers_UpdateAuthMembers(cur realm, t *testing.T) {
307 test2Address := testutils.TestAddress("test2")
308
309 t.Run("unauthorized member adds member", func(cur realm, t *testing.T) {
310 resetState()
311
312 info := validValidatorInfo(t)
313 testing.SetRealm(testing.NewUserRealm(info.Address))
314 testing.SetOriginSend(chain.Coins{minFee})
315
316 // Add the valoper.
317 uassert.NotPanics(t, cur, func() {
318 Register(cross(cur), info.Moniker, info.Description, info.ServerType, info.Address, info.PubKey)
319 })
320
321 // A different caller (not on the auth list) tries to add a member.
322 testing.SetRealm(testing.NewUserRealm(test2Address))
323
324 uassert.AbortsWithMessage(t, cur, authorizable.ErrNotSuperuser.Error(), func() {
325 AddToAuthList(cross(cur), info.Address, test2Address)
326 })
327 })
328
329 t.Run("unauthorized member deletes member", func(cur realm, t *testing.T) {
330 resetState()
331
332 info := validValidatorInfo(t)
333 testing.SetRealm(testing.NewUserRealm(info.Address))
334 testing.SetOriginSend(chain.Coins{minFee})
335
336 uassert.NotPanics(t, cur, func() {
337 Register(cross(cur), info.Moniker, info.Description, info.ServerType, info.Address, info.PubKey)
338 })
339
340 uassert.NotPanics(t, cur, func() {
341 AddToAuthList(cross(cur), info.Address, test2Address)
342 })
343
344 // A different caller tries to delete a member.
345 testing.SetRealm(testing.NewUserRealm(testutils.TestAddress("attacker")))
346
347 uassert.AbortsWithMessage(t, cur, authorizable.ErrNotSuperuser.Error(), func() {
348 DeleteFromAuthList(cross(cur), info.Address, test2Address)
349 })
350 })
351
352 t.Run("authorized member adds member", func(cur realm, t *testing.T) {
353 resetState()
354
355 info := validValidatorInfo(t)
356 testing.SetRealm(testing.NewUserRealm(info.Address))
357 testing.SetOriginSend(chain.Coins{minFee})
358
359 uassert.NotPanics(t, cur, func() {
360 Register(cross(cur), info.Moniker, info.Description, info.ServerType, info.Address, info.PubKey)
361 })
362
363 uassert.NotPanics(t, cur, func() {
364 AddToAuthList(cross(cur), info.Address, test2Address)
365 })
366
367 testing.SetRealm(testing.NewUserRealm(test2Address))
368
369 newMoniker := "new moniker"
370 uassert.NotPanics(t, cur, func() {
371 UpdateMoniker(cross(cur), info.Address, newMoniker)
372 })
373
374 uassert.NotPanics(t, cur, func() {
375 valoper := GetByAddr(info.Address)
376 uassert.Equal(t, newMoniker, valoper.Moniker)
377 })
378 })
379}
380
381func TestValopers_UpdateMoniker(cur realm, t *testing.T) {
382 test2Address := testutils.TestAddress("test2")
383
384 t.Run("non-existing valoper", func(cur realm, t *testing.T) {
385 resetState()
386
387 info := validValidatorInfo(t)
388
389 uassert.AbortsWithMessage(t, cur, ErrValoperMissing.Error(), func() {
390 UpdateMoniker(cross(cur), info.Address, "new moniker")
391 })
392 })
393
394 t.Run("invalid caller", func(cur realm, t *testing.T) {
395 resetState()
396
397 info := validValidatorInfo(t)
398 testing.SetRealm(testing.NewUserRealm(info.Address))
399 testing.SetOriginSend(chain.Coins{minFee})
400
401 uassert.NotPanics(t, cur, func() {
402 Register(cross(cur), info.Moniker, info.Description, info.ServerType, info.Address, info.PubKey)
403 })
404
405 // Change the caller to someone not on the auth list.
406 testing.SetRealm(testing.NewUserRealm(test2Address))
407
408 uassert.AbortsWithMessage(t, cur, authorizable.ErrNotInAuthList.Error(), func() {
409 UpdateMoniker(cross(cur), info.Address, "new moniker")
410 })
411 })
412
413 t.Run("invalid moniker", func(cur realm, t *testing.T) {
414 resetState()
415
416 info := validValidatorInfo(t)
417 testing.SetRealm(testing.NewUserRealm(info.Address))
418 testing.SetOriginSend(chain.Coins{minFee})
419
420 uassert.NotPanics(t, cur, func() {
421 Register(cross(cur), info.Moniker, info.Description, info.ServerType, info.Address, info.PubKey)
422 })
423
424 invalidMonikers := []string{
425 "", // Empty
426 " ", // Whitespace
427 "a", // Too short
428 "a very long moniker that is longer than 32 characters", // Too long
429 "!@#$%^&*()+{}|:<>?/.,;'", // Invalid characters
430 " space in front",
431 "space in back ",
432 }
433
434 for _, invalidMoniker := range invalidMonikers {
435 uassert.AbortsWithMessage(t, cur, ErrInvalidMoniker.Error(), func() {
436 UpdateMoniker(cross(cur), info.Address, invalidMoniker)
437 })
438 }
439 })
440
441 t.Run("too long moniker", func(cur realm, t *testing.T) {
442 resetState()
443
444 info := validValidatorInfo(t)
445 testing.SetRealm(testing.NewUserRealm(info.Address))
446 testing.SetOriginSend(chain.Coins{minFee})
447
448 uassert.NotPanics(t, cur, func() {
449 Register(cross(cur), info.Moniker, info.Description, info.ServerType, info.Address, info.PubKey)
450 })
451
452 uassert.AbortsWithMessage(t, cur, ErrInvalidMoniker.Error(), func() {
453 UpdateMoniker(cross(cur), info.Address, strings.Repeat("a", MonikerMaxLength+1))
454 })
455 })
456
457 t.Run("successful update", func(cur realm, t *testing.T) {
458 resetState()
459
460 info := validValidatorInfo(t)
461 testing.SetRealm(testing.NewUserRealm(info.Address))
462 testing.SetOriginSend(chain.Coins{minFee})
463
464 uassert.NotPanics(t, cur, func() {
465 Register(cross(cur), info.Moniker, info.Description, info.ServerType, info.Address, info.PubKey)
466 })
467
468 newMoniker := "new moniker"
469 uassert.NotPanics(t, cur, func() {
470 UpdateMoniker(cross(cur), info.Address, newMoniker)
471 })
472
473 uassert.NotPanics(t, cur, func() {
474 valoper := GetByAddr(info.Address)
475 uassert.Equal(t, newMoniker, valoper.Moniker)
476 })
477 })
478}
479
480func TestValopers_UpdateDescription(cur realm, t *testing.T) {
481 test2Address := testutils.TestAddress("test2")
482
483 t.Run("non-existing valoper", func(cur realm, t *testing.T) {
484 resetState()
485
486 uassert.AbortsWithMessage(t, cur, ErrValoperMissing.Error(), func() {
487 UpdateDescription(cross(cur), validValidatorInfo(t).Address, "new description")
488 })
489 })
490
491 t.Run("invalid caller", func(cur realm, t *testing.T) {
492 resetState()
493
494 info := validValidatorInfo(t)
495 testing.SetRealm(testing.NewUserRealm(info.Address))
496 testing.SetOriginSend(chain.Coins{minFee})
497
498 uassert.NotPanics(t, cur, func() {
499 Register(cross(cur), info.Moniker, info.Description, info.ServerType, info.Address, info.PubKey)
500 })
501
502 testing.SetRealm(testing.NewUserRealm(test2Address))
503
504 uassert.AbortsWithMessage(t, cur, authorizable.ErrNotInAuthList.Error(), func() {
505 UpdateDescription(cross(cur), info.Address, "new description")
506 })
507 })
508
509 t.Run("empty description", func(cur realm, t *testing.T) {
510 resetState()
511
512 info := validValidatorInfo(t)
513 testing.SetRealm(testing.NewUserRealm(info.Address))
514 testing.SetOriginSend(chain.Coins{minFee})
515
516 uassert.NotPanics(t, cur, func() {
517 Register(cross(cur), info.Moniker, info.Description, info.ServerType, info.Address, info.PubKey)
518 })
519
520 uassert.AbortsWithMessage(t, cur, ErrInvalidDescription.Error(), func() {
521 UpdateDescription(cross(cur), info.Address, "")
522 })
523 })
524
525 t.Run("too long description", func(cur realm, t *testing.T) {
526 resetState()
527
528 info := validValidatorInfo(t)
529 testing.SetRealm(testing.NewUserRealm(info.Address))
530 testing.SetOriginSend(chain.Coins{minFee})
531
532 uassert.NotPanics(t, cur, func() {
533 Register(cross(cur), info.Moniker, info.Description, info.ServerType, info.Address, info.PubKey)
534 })
535
536 uassert.AbortsWithMessage(t, cur, ErrInvalidDescription.Error(), func() {
537 UpdateDescription(cross(cur), info.Address, strings.Repeat("a", DescriptionMaxLength+1))
538 })
539 })
540
541 t.Run("successful update", func(cur realm, t *testing.T) {
542 resetState()
543
544 info := validValidatorInfo(t)
545 testing.SetRealm(testing.NewUserRealm(info.Address))
546 testing.SetOriginSend(chain.Coins{minFee})
547
548 uassert.NotPanics(t, cur, func() {
549 Register(cross(cur), info.Moniker, info.Description, info.ServerType, info.Address, info.PubKey)
550 })
551
552 newDescription := "new description"
553 uassert.NotPanics(t, cur, func() {
554 UpdateDescription(cross(cur), info.Address, newDescription)
555 })
556
557 uassert.NotPanics(t, cur, func() {
558 valoper := GetByAddr(info.Address)
559 uassert.Equal(t, newDescription, valoper.Description)
560 })
561 })
562}
563
564func TestValopers_UpdateKeepRunning(cur realm, t *testing.T) {
565 test2Address := testutils.TestAddress("test2")
566
567 t.Run("non-existing valoper", func(cur realm, t *testing.T) {
568 resetState()
569
570 uassert.AbortsWithMessage(t, cur, ErrValoperMissing.Error(), func() {
571 UpdateKeepRunning(cross(cur), validValidatorInfo(t).Address, false)
572 })
573 })
574
575 t.Run("invalid caller", func(cur realm, t *testing.T) {
576 resetState()
577
578 info := validValidatorInfo(t)
579 testing.SetRealm(testing.NewUserRealm(info.Address))
580 testing.SetOriginSend(chain.Coins{minFee})
581
582 uassert.NotPanics(t, cur, func() {
583 Register(cross(cur), info.Moniker, info.Description, info.ServerType, info.Address, info.PubKey)
584 })
585
586 testing.SetRealm(testing.NewUserRealm(test2Address))
587
588 uassert.AbortsWithMessage(t, cur, authorizable.ErrNotInAuthList.Error(), func() {
589 UpdateKeepRunning(cross(cur), info.Address, false)
590 })
591 })
592
593 t.Run("successful update", func(cur realm, t *testing.T) {
594 resetState()
595
596 info := validValidatorInfo(t)
597 testing.SetRealm(testing.NewUserRealm(info.Address))
598 testing.SetOriginSend(chain.Coins{minFee})
599
600 uassert.NotPanics(t, cur, func() {
601 Register(cross(cur), info.Moniker, info.Description, info.ServerType, info.Address, info.PubKey)
602 })
603
604 uassert.NotPanics(t, cur, func() {
605 UpdateKeepRunning(cross(cur), info.Address, false)
606 })
607
608 uassert.NotPanics(t, cur, func() {
609 valoper := GetByAddr(info.Address)
610 uassert.Equal(t, false, valoper.KeepRunning)
611 })
612 })
613}
614
615func TestValopers_UpdateServerType(cur realm, t *testing.T) {
616 test2Address := testutils.TestAddress("test2")
617
618 t.Run("non-existing valoper", func(cur realm, t *testing.T) {
619 resetState()
620
621 uassert.AbortsWithMessage(t, cur, ErrValoperMissing.Error(), func() {
622 UpdateServerType(cross(cur), validValidatorInfo(t).Address, ServerTypeCloud)
623 })
624 })
625
626 t.Run("invalid caller", func(cur realm, t *testing.T) {
627 resetState()
628
629 info := validValidatorInfo(t)
630 testing.SetRealm(testing.NewUserRealm(info.Address))
631 testing.SetOriginSend(chain.Coins{minFee})
632
633 uassert.NotPanics(t, cur, func() {
634 Register(cross(cur), info.Moniker, info.Description, info.ServerType, info.Address, info.PubKey)
635 })
636
637 testing.SetRealm(testing.NewUserRealm(test2Address))
638
639 uassert.AbortsWithMessage(t, cur, authorizable.ErrNotInAuthList.Error(), func() {
640 UpdateServerType(cross(cur), info.Address, ServerTypeCloud)
641 })
642 })
643
644 t.Run("invalid server type", func(cur realm, t *testing.T) {
645 resetState()
646
647 info := validValidatorInfo(t)
648 testing.SetRealm(testing.NewUserRealm(info.Address))
649 testing.SetOriginSend(chain.Coins{minFee})
650
651 uassert.NotPanics(t, cur, func() {
652 Register(cross(cur), info.Moniker, info.Description, info.ServerType, info.Address, info.PubKey)
653 })
654
655 invalidServerTypes := []string{
656 "",
657 "invalid",
658 "Cloud", // case sensitive
659 "ON-PREM", // case sensitive
660 "datacenter", // wrong format
661 }
662
663 for _, invalidType := range invalidServerTypes {
664 uassert.AbortsWithMessage(t, cur, ErrInvalidServerType.Error(), func() {
665 UpdateServerType(cross(cur), info.Address, invalidType)
666 })
667 }
668 })
669
670 t.Run("successful update", func(cur realm, t *testing.T) {
671 resetState()
672
673 info := validValidatorInfo(t)
674 testing.SetRealm(testing.NewUserRealm(info.Address))
675 testing.SetOriginSend(chain.Coins{minFee})
676
677 uassert.NotPanics(t, cur, func() {
678 Register(cross(cur), info.Moniker, info.Description, info.ServerType, info.Address, info.PubKey)
679 })
680
681 uassert.NotPanics(t, cur, func() {
682 UpdateServerType(cross(cur), info.Address, ServerTypeCloud)
683 })
684
685 uassert.NotPanics(t, cur, func() {
686 valoper := GetByAddr(info.Address)
687 uassert.Equal(t, ServerTypeCloud, valoper.ServerType)
688 })
689
690 uassert.NotPanics(t, cur, func() {
691 UpdateServerType(cross(cur), info.Address, ServerTypeDataCenter)
692 })
693
694 uassert.NotPanics(t, cur, func() {
695 valoper := GetByAddr(info.Address)
696 uassert.Equal(t, ServerTypeDataCenter, valoper.ServerType)
697 })
698 })
699}