data.gno
3.88 Kb ยท 160 lines
1package chunk
2
3// This file manages chunk verifier data for integrity verification.
4
5import (
6 "chain/runtime"
7
8 "gno.land/p/nt/avl"
9 "gno.land/p/nt/ufmt"
10)
11
12var (
13 chunkVerifiers = avl.NewTree() // worldID -> map[chunkKey]verifier
14)
15
16// ==================== Chunk Verifier ====================
17
18// SetChunkVerifier stores verifier for a specific chunk key of a world.
19// Verifier includes hash for integrity verification.
20func SetChunkVerifier(cur realm, worldID uint32, chunkKey string, verifier string) {
21 caller := runtime.PreviousRealm().Address()
22 assertIsAdminOrOperator(caller)
23
24 setChunkVerifierInternal(worldID, chunkKey, verifier)
25}
26
27// SetChunkVerifiers sets multiple chunk verifiers at once using direct string traversal.
28// chunkKeys and verifiers are comma-separated strings with matching item counts.
29// Example: chunkKeys="0_0,0_1,1_0", verifiers="hash1,hash2,hash3"
30func SetChunkVerifiers(cur realm, worldID uint32, chunkKeys string, verifiers string) {
31 caller := runtime.PreviousRealm().Address()
32 assertIsAdminOrOperator(caller)
33
34 if chunkKeys == "" {
35 panic("chunkKeys must not be empty")
36 }
37 if verifiers == "" {
38 panic("verifiers must not be empty")
39 }
40
41 worldIDStr := ufmt.Sprintf("%d", worldID)
42 var chunkMap map[string]string
43
44 if value, exists := chunkVerifiers.Get(worldIDStr); exists {
45 chunkMap = value.(map[string]string)
46 } else {
47 chunkMap = make(map[string]string)
48 chunkVerifiers.Set(worldIDStr, chunkMap)
49 }
50
51 // Direct string traversal parsing (no strings.Split)
52 keyStart, valStart := 0, 0
53 keyIdx, valIdx := 0, 0
54 count := 0
55
56 for {
57 // Find next delimiter or end for keys
58 for keyIdx < len(chunkKeys) && chunkKeys[keyIdx] != ',' {
59 keyIdx++
60 }
61 // Find next delimiter or end for values
62 for valIdx < len(verifiers) && verifiers[valIdx] != ',' {
63 valIdx++
64 }
65
66 // Extract key and value
67 key := chunkKeys[keyStart:keyIdx]
68 val := verifiers[valStart:valIdx]
69
70 // Validate: no empty keys or values allowed
71 if key == "" {
72 panic("empty chunkKey not allowed")
73 }
74 if val == "" {
75 panic("empty verifier not allowed")
76 }
77
78 chunkMap[key] = val
79 count++
80
81 if count > batchLimit {
82 panic("items exceed batchLimit")
83 }
84
85 // Check end conditions
86 keyEnd := keyIdx >= len(chunkKeys)
87 valEnd := valIdx >= len(verifiers)
88
89 // Validate: both must end at the same time (same item count)
90 if keyEnd != valEnd {
91 panic("chunkKeys and verifiers count mismatch")
92 }
93 if keyEnd {
94 break
95 }
96
97 // Move past the delimiter
98 keyIdx++
99 valIdx++
100 keyStart = keyIdx
101 valStart = valIdx
102 }
103}
104
105func setChunkVerifierInternal(worldID uint32, chunkKey string, verifier string) {
106 worldIDStr := ufmt.Sprintf("%d", worldID)
107 var chunkMap map[string]string
108
109 if value, exists := chunkVerifiers.Get(worldIDStr); exists {
110 chunkMap = value.(map[string]string)
111 } else {
112 chunkMap = make(map[string]string)
113 chunkVerifiers.Set(worldIDStr, chunkMap)
114 }
115
116 chunkMap[chunkKey] = verifier
117}
118
119// GetChunkVerifier retrieves verifier for a specific chunk key of a world.
120func GetChunkVerifier(worldID uint32, chunkKey string) string {
121 worldIDStr := ufmt.Sprintf("%d", worldID)
122
123 if value, exists := chunkVerifiers.Get(worldIDStr); exists {
124 chunkMap := value.(map[string]string)
125 return chunkMap[chunkKey]
126 }
127
128 return ""
129}
130
131// ListChunkVerifiers retrieves verifiers for multiple chunk keys of a world.
132func ListChunkVerifiers(worldID uint32, chunkKeys ...string) []map[string]string {
133 if len(chunkKeys) > batchLimit {
134 panic("chunkKeys exceeds batchLimit")
135 }
136
137 result := []map[string]string{}
138 if len(chunkKeys) == 0 {
139 return result
140 }
141
142 for _, chunkKey := range chunkKeys {
143 verifier := GetChunkVerifier(worldID, chunkKey)
144
145 if verifier != "" {
146 result = append(result, map[string]string{
147 "chunkKey": chunkKey,
148 "status": "found",
149 "verifier": verifier,
150 })
151 } else {
152 result = append(result, map[string]string{
153 "chunkKey": chunkKey,
154 "status": "not_found",
155 })
156 }
157 }
158
159 return result
160}