Search Apps Documentation Source Content File Folder Download Copy Actions Download

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}