A Transparent and Verifiable Way to Sync the AT Protocol's PLC Directory

fix panic

+32 -8
+30 -8
bundle/manager.go
··· 265 265 prevChainHash = prevBundle.ChainHash 266 266 prevContentHash = prevBundle.Hash 267 267 268 + // Safe logging with length checks 269 + hashPreview := formatHashPreview(prevContentHash) 270 + chainPreview := formatHashPreview(prevChainHash) 271 + 268 272 m.logger.Printf("Previous bundle %06d: hash=%s, chain=%s", 269 273 prevBundle.BundleNumber, 270 - prevContentHash[:16]+"...", 271 - prevChainHash[:16]+"...") 274 + hashPreview, 275 + chainPreview) 272 276 } else { 273 277 // Try to get specific previous bundle 274 278 if prevMeta, err := m.index.GetBundle(bundle.BundleNumber - 1); err == nil { 275 279 prevChainHash = prevMeta.ChainHash 276 280 prevContentHash = prevMeta.Hash 277 281 282 + // Safe logging with length checks 283 + hashPreview := formatHashPreview(prevContentHash) 284 + chainPreview := formatHashPreview(prevChainHash) 285 + 278 286 m.logger.Printf("Found previous bundle %06d: hash=%s, chain=%s", 279 287 prevMeta.BundleNumber, 280 - prevContentHash[:16]+"...", 281 - prevChainHash[:16]+"...") 288 + hashPreview, 289 + chainPreview) 282 290 } 283 291 } 284 292 } ··· 290 298 // Calculate chain hash 291 299 bundle.ChainHash = m.operations.CalculateChainHash(prevChainHash, bundle.Hash) 292 300 301 + // Safe logging for current bundle 293 302 m.logger.Printf("Bundle %06d: hash=%s, chain=%s", 294 303 bundle.BundleNumber, 295 - bundle.Hash[:16]+"...", 296 - bundle.ChainHash[:16]+"...") 304 + formatHashPreview(bundle.Hash), 305 + formatHashPreview(bundle.ChainHash)) 297 306 298 307 // Add to index 299 308 m.index.AddBundle(bundle.ToMetadata()) ··· 303 312 return fmt.Errorf("failed to save index: %w", err) 304 313 } 305 314 306 - m.logger.Printf("Saved bundle %06d (hash: %s..., chain: %s...)", 307 - bundle.BundleNumber, bundle.Hash[:16], bundle.ChainHash[:16]) 315 + m.logger.Printf("Saved bundle %06d (hash: %s, chain: %s)", 316 + bundle.BundleNumber, 317 + formatHashPreview(bundle.Hash), 318 + formatHashPreview(bundle.ChainHash)) 308 319 309 320 // IMPORTANT: Clean up old mempool and create new one for next bundle 310 321 oldMempoolFile := m.mempool.GetFilename() ··· 328 339 nextBundle, minTimestamp.Format(time.RFC3339Nano)) 329 340 330 341 return nil 342 + } 343 + 344 + // formatHashPreview safely formats a hash for display 345 + func formatHashPreview(hash string) string { 346 + if len(hash) == 0 { 347 + return "(empty)" 348 + } 349 + if len(hash) < 16 { 350 + return hash 351 + } 352 + return hash[:16] + "..." 331 353 } 332 354 333 355 // FetchNextBundle fetches the next bundle from PLC directory
+2
bundle/types.go
··· 122 122 OperationCount: b.OperationCount(), 123 123 DIDCount: b.DIDCount, 124 124 Hash: b.Hash, 125 + ChainHash: b.ChainHash, 125 126 CompressedHash: b.CompressedHash, 126 127 CompressedSize: b.CompressedSize, 127 128 UncompressedSize: b.UncompressedSize, 128 129 Cursor: b.Cursor, 129 130 PrevBundleHash: b.PrevBundleHash, 131 + PrevChainHash: b.PrevChainHash, 130 132 CreatedAt: b.CreatedAt, 131 133 } 132 134 }