Files
CHORUS/internal/logging/hypercore.go
anthonyrawlins 543ab216f9 Complete BZZZ functionality port to CHORUS
🎭 CHORUS now contains full BZZZ functionality adapted for containers

Core systems ported:
- P2P networking (libp2p with DHT and PubSub)
- Task coordination (COOEE protocol)
- HMMM collaborative reasoning
- SHHH encryption and security
- SLURP admin election system
- UCXL content addressing
- UCXI server integration
- Hypercore logging system
- Health monitoring and graceful shutdown
- License validation with KACHING

Container adaptations:
- Environment variable configuration (no YAML files)
- Container-optimized logging to stdout/stderr
- Auto-generated agent IDs for container deployments
- Docker-first architecture

All proven BZZZ P2P protocols, AI integration, and collaboration
features are now available in containerized form.

Next: Build and test container deployment.

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-09-02 20:02:37 +10:00

365 lines
9.5 KiB
Go

package logging
import (
"crypto/sha256"
"encoding/hex"
"encoding/json"
"fmt"
"sync"
"time"
"github.com/libp2p/go-libp2p/core/peer"
)
// Logger interface for basic logging operations
type Logger interface {
Info(msg string, args ...interface{})
Warn(msg string, args ...interface{})
Error(msg string, args ...interface{})
}
// HypercoreLog represents a simplified Hypercore-inspired distributed log
type HypercoreLog struct {
entries []LogEntry
mutex sync.RWMutex
peerID peer.ID
// Verification chain
headHash string
// Replication
replicators map[peer.ID]*Replicator
}
// LogEntry represents a single entry in the distributed log
type LogEntry struct {
Index uint64 `json:"index"`
Timestamp time.Time `json:"timestamp"`
Author string `json:"author"` // Peer ID of the author
Type LogType `json:"type"` // Type of log entry
Data map[string]interface{} `json:"data"` // Log data
Hash string `json:"hash"` // Hash of this entry
PrevHash string `json:"prev_hash"` // Hash of previous entry
Signature string `json:"signature"` // Digital signature (simplified)
}
// LogType represents different types of log entries
type LogType string
const (
// Bzzz coordination logs
TaskAnnounced LogType = "task_announced"
TaskClaimed LogType = "task_claimed"
TaskProgress LogType = "task_progress"
TaskCompleted LogType = "task_completed"
TaskFailed LogType = "task_failed"
// HMMM meta-discussion logs
PlanProposed LogType = "plan_proposed"
ObjectionRaised LogType = "objection_raised"
Collaboration LogType = "collaboration"
ConsensusReached LogType = "consensus_reached"
Escalation LogType = "escalation"
TaskHelpRequested LogType = "task_help_requested"
TaskHelpOffered LogType = "task_help_offered"
TaskHelpReceived LogType = "task_help_received"
// System logs
PeerJoined LogType = "peer_joined"
PeerLeft LogType = "peer_left"
CapabilityBcast LogType = "capability_broadcast"
NetworkEvent LogType = "network_event"
)
// Replicator handles log replication with other peers
type Replicator struct {
peerID peer.ID
lastSyncIndex uint64
connected bool
}
// NewHypercoreLog creates a new distributed log for a peer
func NewHypercoreLog(peerID peer.ID) *HypercoreLog {
return &HypercoreLog{
entries: make([]LogEntry, 0),
peerID: peerID,
headHash: "",
replicators: make(map[peer.ID]*Replicator),
}
}
// AppendString is a convenience method for string log types (to match interface)
func (h *HypercoreLog) AppendString(logType string, data map[string]interface{}) error {
_, err := h.Append(LogType(logType), data)
return err
}
// Append adds a new entry to the log
func (h *HypercoreLog) Append(logType LogType, data map[string]interface{}) (*LogEntry, error) {
h.mutex.Lock()
defer h.mutex.Unlock()
index := uint64(len(h.entries))
entry := LogEntry{
Index: index,
Timestamp: time.Now(),
Author: h.peerID.String(),
Type: logType,
Data: data,
PrevHash: h.headHash,
}
// Calculate hash
entryHash, err := h.calculateEntryHash(entry)
if err != nil {
return nil, fmt.Errorf("failed to calculate entry hash: %w", err)
}
entry.Hash = entryHash
// Add simple signature (in production, use proper cryptographic signatures)
entry.Signature = h.createSignature(entry)
// Append to log
h.entries = append(h.entries, entry)
h.headHash = entryHash
fmt.Printf("📝 Log entry appended: %s [%d] by %s\n",
logType, index, h.peerID.ShortString())
// Trigger replication to connected peers
go h.replicateEntry(entry)
return &entry, nil
}
// Get retrieves a log entry by index
func (h *HypercoreLog) Get(index uint64) (*LogEntry, error) {
h.mutex.RLock()
defer h.mutex.RUnlock()
if index >= uint64(len(h.entries)) {
return nil, fmt.Errorf("entry %d not found", index)
}
return &h.entries[index], nil
}
// Length returns the number of entries in the log
func (h *HypercoreLog) Length() uint64 {
h.mutex.RLock()
defer h.mutex.RUnlock()
return uint64(len(h.entries))
}
// GetRange retrieves a range of log entries
func (h *HypercoreLog) GetRange(start, end uint64) ([]LogEntry, error) {
h.mutex.RLock()
defer h.mutex.RUnlock()
if start >= uint64(len(h.entries)) {
return nil, fmt.Errorf("start index %d out of range", start)
}
if end > uint64(len(h.entries)) {
end = uint64(len(h.entries))
}
if start > end {
return nil, fmt.Errorf("invalid range: start %d > end %d", start, end)
}
result := make([]LogEntry, end-start)
copy(result, h.entries[start:end])
return result, nil
}
// GetEntriesByType retrieves all entries of a specific type
func (h *HypercoreLog) GetEntriesByType(logType LogType) ([]LogEntry, error) {
h.mutex.RLock()
defer h.mutex.RUnlock()
var result []LogEntry
for _, entry := range h.entries {
if entry.Type == logType {
result = append(result, entry)
}
}
return result, nil
}
// GetEntriesByAuthor retrieves all entries by a specific author
func (h *HypercoreLog) GetEntriesByAuthor(author string) ([]LogEntry, error) {
h.mutex.RLock()
defer h.mutex.RUnlock()
var result []LogEntry
for _, entry := range h.entries {
if entry.Author == author {
result = append(result, entry)
}
}
return result, nil
}
// GetRecentEntries retrieves the most recent N entries from the log
func (h *HypercoreLog) GetRecentEntries(count int) ([]LogEntry, error) {
h.mutex.RLock()
defer h.mutex.RUnlock()
totalEntries := len(h.entries)
if count <= 0 || totalEntries == 0 {
return []LogEntry{}, nil
}
start := 0
if totalEntries > count {
start = totalEntries - count
}
result := make([]LogEntry, totalEntries-start)
copy(result, h.entries[start:])
return result, nil
}
// GetEntriesSince retrieves all entries since a given index
func (h *HypercoreLog) GetEntriesSince(sinceIndex uint64) ([]LogEntry, error) {
h.mutex.RLock()
defer h.mutex.RUnlock()
if sinceIndex >= uint64(len(h.entries)) {
return []LogEntry{}, nil
}
result := make([]LogEntry, len(h.entries)-int(sinceIndex))
copy(result, h.entries[sinceIndex:])
return result, nil
}
// VerifyIntegrity verifies the integrity of the log chain
func (h *HypercoreLog) VerifyIntegrity() error {
h.mutex.RLock()
defer h.mutex.RUnlock()
var prevHash string
for i, entry := range h.entries {
// Verify previous hash link
if entry.PrevHash != prevHash {
return fmt.Errorf("integrity error at entry %d: prev_hash mismatch", i)
}
// Verify entry hash
calculatedHash, err := h.calculateEntryHash(entry)
if err != nil {
return fmt.Errorf("failed to calculate hash for entry %d: %w", i, err)
}
if entry.Hash != calculatedHash {
return fmt.Errorf("integrity error at entry %d: hash mismatch", i)
}
prevHash = entry.Hash
}
return nil
}
// AddReplicator adds a peer for log replication
func (h *HypercoreLog) AddReplicator(peerID peer.ID) {
h.mutex.Lock()
defer h.mutex.Unlock()
h.replicators[peerID] = &Replicator{
peerID: peerID,
lastSyncIndex: 0,
connected: true,
}
fmt.Printf("🔄 Added replicator: %s\n", peerID.ShortString())
}
// RemoveReplicator removes a peer from replication
func (h *HypercoreLog) RemoveReplicator(peerID peer.ID) {
h.mutex.Lock()
defer h.mutex.Unlock()
delete(h.replicators, peerID)
fmt.Printf("🔄 Removed replicator: %s\n", peerID.ShortString())
}
// replicateEntry sends a new entry to all connected replicators
func (h *HypercoreLog) replicateEntry(entry LogEntry) {
h.mutex.RLock()
replicators := make([]*Replicator, 0, len(h.replicators))
for _, replicator := range h.replicators {
if replicator.connected {
replicators = append(replicators, replicator)
}
}
h.mutex.RUnlock()
for _, replicator := range replicators {
// In a real implementation, this would send the entry over the network
fmt.Printf("🔄 Replicating entry %d to %s\n",
entry.Index, replicator.peerID.ShortString())
}
}
// calculateEntryHash calculates the hash of a log entry
func (h *HypercoreLog) calculateEntryHash(entry LogEntry) (string, error) {
// Create a copy without the hash and signature for calculation
entryForHash := LogEntry{
Index: entry.Index,
Timestamp: entry.Timestamp,
Author: entry.Author,
Type: entry.Type,
Data: entry.Data,
PrevHash: entry.PrevHash,
}
entryBytes, err := json.Marshal(entryForHash)
if err != nil {
return "", err
}
hash := sha256.Sum256(entryBytes)
return hex.EncodeToString(hash[:]), nil
}
// createSignature creates a simplified signature for the entry
func (h *HypercoreLog) createSignature(entry LogEntry) string {
// In production, this would use proper cryptographic signatures
// For now, we use a simple hash-based signature
signatureData := fmt.Sprintf("%s:%s:%d", h.peerID.String(), entry.Hash, entry.Index)
hash := sha256.Sum256([]byte(signatureData))
return hex.EncodeToString(hash[:])[:16] // Shortened for display
}
// GetStats returns statistics about the log
func (h *HypercoreLog) GetStats() map[string]interface{} {
h.mutex.RLock()
defer h.mutex.RUnlock()
typeCount := make(map[LogType]int)
authorCount := make(map[string]int)
for _, entry := range h.entries {
typeCount[entry.Type]++
authorCount[entry.Author]++
}
return map[string]interface{}{
"total_entries": len(h.entries),
"head_hash": h.headHash,
"replicators": len(h.replicators),
"entries_by_type": typeCount,
"entries_by_author": authorCount,
"peer_id": h.peerID.String(),
}
}