verifier.gno
3.01 Kb · 106 lines
1package chunk
2
3// This file manages chunk data for integrity verification.
4// Verifier storage: BTree(worldID -> *BTree(chunkKey -> verifier)).
5
6import (
7 "gno.land/p/akkadia/v0/accesscontrol"
8 "gno.land/r/akkadia/v0/admin"
9)
10
11// ==================== Chunk Verifier ====================
12
13// SetChunkVerifier stores verifier for a specific chunk key of a world.
14func SetChunkVerifier(cur realm, worldID uint32, chunkKey string, verifier string) {
15 assertNotFrozen()
16 accesscontrol.AssertIsAdminOrOperator(0, cur, admin.IsAdmin, admin.IsOperator)
17
18 canonicalChunkKey := normalizeChunkKey(worldID, chunkKey)
19 verifierStore.Set(worldID, canonicalChunkKey, verifier)
20}
21
22// SetChunkVerifiers sets multiple chunk verifiers at once using direct string traversal.
23// chunkKeys and verifiers are comma-separated strings with matching item counts.
24// Example: chunkKeys="100000002:0_0,100000002:0_1", verifiers="a1b2c3d4,e5f6a7b8"
25func SetChunkVerifiers(cur realm, worldID uint32, chunkKeys string, verifiers string) {
26 assertNotFrozen()
27 accesscontrol.AssertIsAdminOrOperator(0, cur, admin.IsAdmin, admin.IsOperator)
28
29 if chunkKeys == "" {
30 panic("chunkKeys must not be empty")
31 }
32 if verifiers == "" {
33 panic("verifiers must not be empty")
34 }
35
36 keyStart, valStart := 0, 0
37 keyIdx, valIdx := 0, 0
38 count := 0
39
40 for {
41 for keyIdx < len(chunkKeys) && chunkKeys[keyIdx] != ',' {
42 keyIdx++
43 }
44 for valIdx < len(verifiers) && verifiers[valIdx] != ',' {
45 valIdx++
46 }
47
48 key := chunkKeys[keyStart:keyIdx]
49 val := verifiers[valStart:valIdx]
50
51 if val == "" {
52 panic("empty verifier not allowed")
53 }
54
55 // Keep this loop streaming. Building temporary []string values for every
56 // key/verifier pair increases gas sharply on large batch calls.
57 count++
58 assertBatchLimit("chunkKeys", count)
59 canonicalChunkKey := normalizeChunkKey(worldID, key)
60 verifierStore.Set(worldID, canonicalChunkKey, val)
61
62 keyEnd := keyIdx >= len(chunkKeys)
63 valEnd := valIdx >= len(verifiers)
64
65 if keyEnd != valEnd {
66 panic("chunkKeys and verifiers count mismatch")
67 }
68 if keyEnd {
69 break
70 }
71
72 keyIdx++
73 valIdx++
74 keyStart = keyIdx
75 valStart = valIdx
76 }
77}
78
79// GetChunkVerifier retrieves verifier for a specific chunk key of a world.
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
90// ListChunkVerifiers retrieves verifiers for multiple chunk keys of a world.
91func ListChunkVerifiers(worldID uint32, chunkKeys ...string) []map[string]string {
92 assertMigrationStateAvailable()
93 assertListLimit("chunkKeys", len(chunkKeys))
94 result := []map[string]string{}
95 for _, chunkKey := range chunkKeys {
96 canonicalChunkKey := normalizeChunkKey(worldID, chunkKey)
97 verifier, found := verifierStore.Get(worldID, canonicalChunkKey)
98 if found {
99 result = append(result, map[string]string{
100 "chunkKey": canonicalChunkKey,
101 "verifier": verifier,
102 })
103 }
104 }
105 return result
106}