verifier.gno
2.85 Kb · 105 lines
1package personal_world
2
3import (
4 "gno.land/p/akkadia/v0/accesscontrol"
5 "gno.land/r/akkadia/v0/admin"
6)
7
8// SetChunkVerifier stores verifier for a specific chunk key of a world.
9func SetChunkVerifier(cur realm, worldID uint32, chunkKey string, verifier string) {
10 assertNotFrozen()
11 accesscontrol.AssertIsAdminOrOperator(0, cur, admin.IsAdmin, admin.IsOperator)
12
13 canonicalChunkKey := normalizeChunkKey(worldID, chunkKey)
14 verifierStore.Set(worldID, canonicalChunkKey, verifier)
15}
16
17// SetChunkVerifiers sets multiple chunk verifiers at once using direct string traversal.
18// chunkKeys and verifiers are comma-separated strings with matching item counts.
19// Example: chunkKeys="1:0_0,1:0_1", verifiers="a1b2c3d4,e5f6a7b8"
20func SetChunkVerifiers(cur realm, worldID uint32, chunkKeys string, verifiers string) {
21 assertNotFrozen()
22 accesscontrol.AssertIsAdminOrOperator(0, cur, admin.IsAdmin, admin.IsOperator)
23
24 if chunkKeys == "" {
25 panic("chunkKeys must not be empty")
26 }
27 if verifiers == "" {
28 panic("verifiers must not be empty")
29 }
30
31 // Direct string traversal parsing (no strings.Split)
32 keyStart, valStart := 0, 0
33 keyIdx, valIdx := 0, 0
34 count := 0
35
36 for {
37 // Find next delimiter or end for keys
38 for keyIdx < len(chunkKeys) && chunkKeys[keyIdx] != ',' {
39 keyIdx++
40 }
41 // Find next delimiter or end for values
42 for valIdx < len(verifiers) && verifiers[valIdx] != ',' {
43 valIdx++
44 }
45
46 // Extract key and value
47 key := chunkKeys[keyStart:keyIdx]
48 val := verifiers[valStart:valIdx]
49
50 // Validate: no empty keys or values allowed
51 if val == "" {
52 panic("empty verifier not allowed")
53 }
54
55 count++
56 assertBatchLimit("chunkKeys", count)
57 canonicalChunkKey := normalizeChunkKey(worldID, key)
58 verifierStore.Set(worldID, canonicalChunkKey, val)
59
60 // Check end conditions
61 keyEnd := keyIdx >= len(chunkKeys)
62 valEnd := valIdx >= len(verifiers)
63
64 // Validate: both must end at the same time (same item count)
65 if keyEnd != valEnd {
66 panic("chunkKeys and verifiers count mismatch")
67 }
68 if keyEnd {
69 break
70 }
71
72 // Move past the delimiter
73 keyIdx++
74 valIdx++
75 keyStart = keyIdx
76 valStart = valIdx
77 }
78}
79
80func GetChunkVerifier(worldID uint32, chunkKey string) string {
81 assertMigrationStateAvailable()
82 canonicalChunkKey := normalizeChunkKey(worldID, chunkKey)
83 verifier, found := verifierStore.Get(worldID, canonicalChunkKey)
84 if !found {
85 return ""
86 }
87 return verifier
88}
89
90func ListChunkVerifiers(worldID uint32, chunkKeys ...string) []map[string]string {
91 assertMigrationStateAvailable()
92 assertListLimit("chunkKeys", len(chunkKeys))
93 result := []map[string]string{}
94 for _, chunkKey := range chunkKeys {
95 canonicalChunkKey := normalizeChunkKey(worldID, chunkKey)
96 verifier, found := verifierStore.Get(worldID, canonicalChunkKey)
97 if found {
98 result = append(result, map[string]string{
99 "chunkKey": canonicalChunkKey,
100 "verifier": verifier,
101 })
102 }
103 }
104 return result
105}