package chunk // This file manages chunk verifier data for integrity verification. import ( "chain/runtime" "gno.land/p/nt/avl" "gno.land/p/nt/ufmt" ) var ( chunkVerifiers = avl.NewTree() // worldID -> map[chunkKey]verifier ) // ==================== Chunk Verifier ==================== // SetChunkVerifier stores verifier for a specific chunk key of a world. // Verifier includes hash for integrity verification. func SetChunkVerifier(cur realm, worldID uint32, chunkKey string, verifier string) { caller := runtime.PreviousRealm().Address() assertIsAdminOrOperator(caller) setChunkVerifierInternal(worldID, chunkKey, verifier) } // SetChunkVerifiers sets multiple chunk verifiers at once using direct string traversal. // chunkKeys and verifiers are comma-separated strings with matching item counts. // Example: chunkKeys="0_0,0_1,1_0", verifiers="hash1,hash2,hash3" func SetChunkVerifiers(cur realm, worldID uint32, chunkKeys string, verifiers string) { caller := runtime.PreviousRealm().Address() assertIsAdminOrOperator(caller) if chunkKeys == "" { panic("chunkKeys must not be empty") } if verifiers == "" { panic("verifiers must not be empty") } worldIDStr := ufmt.Sprintf("%d", worldID) var chunkMap map[string]string if value, exists := chunkVerifiers.Get(worldIDStr); exists { chunkMap = value.(map[string]string) } else { chunkMap = make(map[string]string) chunkVerifiers.Set(worldIDStr, chunkMap) } // Direct string traversal parsing (no strings.Split) keyStart, valStart := 0, 0 keyIdx, valIdx := 0, 0 count := 0 for { // Find next delimiter or end for keys for keyIdx < len(chunkKeys) && chunkKeys[keyIdx] != ',' { keyIdx++ } // Find next delimiter or end for values for valIdx < len(verifiers) && verifiers[valIdx] != ',' { valIdx++ } // Extract key and value key := chunkKeys[keyStart:keyIdx] val := verifiers[valStart:valIdx] // Validate: no empty keys or values allowed if key == "" { panic("empty chunkKey not allowed") } if val == "" { panic("empty verifier not allowed") } chunkMap[key] = val count++ if count > batchLimit { panic("items exceed batchLimit") } // Check end conditions keyEnd := keyIdx >= len(chunkKeys) valEnd := valIdx >= len(verifiers) // Validate: both must end at the same time (same item count) if keyEnd != valEnd { panic("chunkKeys and verifiers count mismatch") } if keyEnd { break } // Move past the delimiter keyIdx++ valIdx++ keyStart = keyIdx valStart = valIdx } } func setChunkVerifierInternal(worldID uint32, chunkKey string, verifier string) { worldIDStr := ufmt.Sprintf("%d", worldID) var chunkMap map[string]string if value, exists := chunkVerifiers.Get(worldIDStr); exists { chunkMap = value.(map[string]string) } else { chunkMap = make(map[string]string) chunkVerifiers.Set(worldIDStr, chunkMap) } chunkMap[chunkKey] = verifier } // GetChunkVerifier retrieves verifier for a specific chunk key of a world. func GetChunkVerifier(worldID uint32, chunkKey string) string { worldIDStr := ufmt.Sprintf("%d", worldID) if value, exists := chunkVerifiers.Get(worldIDStr); exists { chunkMap := value.(map[string]string) return chunkMap[chunkKey] } return "" } // ListChunkVerifiers retrieves verifiers for multiple chunk keys of a world. func ListChunkVerifiers(worldID uint32, chunkKeys ...string) []map[string]string { if len(chunkKeys) > batchLimit { panic("chunkKeys exceeds batchLimit") } result := []map[string]string{} if len(chunkKeys) == 0 { return result } for _, chunkKey := range chunkKeys { verifier := GetChunkVerifier(worldID, chunkKey) if verifier != "" { result = append(result, map[string]string{ "chunkKey": chunkKey, "status": "found", "verifier": verifier, }) } else { result = append(result, map[string]string{ "chunkKey": chunkKey, "status": "not_found", }) } } return result }