UNPKG

@clduab11/gemini-flow

Version:

Revolutionary AI agent swarm coordination platform with Google Services integration, multimedia processing, and production-ready monitoring. Features 8 Google AI services, quantum computing capabilities, and enterprise-grade security.

523 lines (449 loc) 15 kB
/** * Byzantine Fault-Tolerant Consensus System * Implements PBFT (Practical Byzantine Fault Tolerance) algorithm * Handles up to 33% malicious agents while maintaining correctness */ import { EventEmitter } from "events"; import { createHash } from "crypto"; export interface Agent { id: string; publicKey: string; isLeader: boolean; isMalicious?: boolean; reputation: number; lastActiveTime: Date; } export interface ConsensusMessage { type: "pre-prepare" | "prepare" | "commit" | "view-change" | "new-view"; viewNumber: number; sequenceNumber: number; digest: string; payload: any; timestamp: Date; signature: string; senderId: string; } export interface ConsensusProposal { id: string; content: any; proposerId: string; timestamp: Date; hash: string; } export interface ConsensusState { currentView: number; sequenceNumber: number; phase: "pre-prepare" | "prepare" | "commit" | "view-change"; leader: string; activeAgents: Set<string>; proposals: Map<string, ConsensusProposal>; messages: Map<string, ConsensusMessage[]>; committed: Set<string>; } export class ByzantineConsensus extends EventEmitter { private agents: Map<string, Agent> = new Map(); private state: ConsensusState; private messageLog: ConsensusMessage[] = []; private faultThreshold: number; private minQuorum: number; // Byzantine: Math.floor(2*n/3)+1 private timeoutDuration: number = 30000; // 30 seconds private viewChangeTimeout: ReturnType<typeof setTimeout> | null = null; private performance: { consensusRounds: number; averageLatency: number; faultsDetected: number; successRate: number; }; constructor( private agentId: string, private totalAgents: number = 4, ) { super(); this.faultThreshold = Math.floor((totalAgents - 1) / 3); this.minQuorum = Math.floor((2 * totalAgents) / 3) + 1; // Byzantine: 2f+1 where f is fault threshold this.state = this.initializeState(); this.performance = { consensusRounds: 0, averageLatency: 0, faultsDetected: 0, successRate: 0, }; } private initializeState(): ConsensusState { return { currentView: 0, sequenceNumber: 0, phase: "pre-prepare", leader: this.selectLeader(0), activeAgents: new Set(), proposals: new Map(), messages: new Map(), committed: new Set(), }; } /** * Register an agent in the consensus network */ public registerAgent(agent: Agent): void { this.agents.set(agent.id, agent); this.state.activeAgents.add(agent.id); this.emit("agent-registered", agent); } /** * Remove an agent from the consensus network */ public removeAgent(agentId: string): void { this.agents.delete(agentId); this.state.activeAgents.delete(agentId); this.emit("agent-removed", agentId); } /** * Start consensus round for a proposal */ public async startConsensus(proposal: ConsensusProposal): Promise<boolean> { const startTime = Date.now(); try { if (!this.isLeader()) { throw new Error("Only leader can start consensus"); } this.state.sequenceNumber++; this.state.proposals.set(proposal.id, proposal); // Phase 1: Pre-prepare await this.broadcastPrePrepare(proposal); // Phase 2: Prepare const prepareSuccess = await this.collectPrepareResponses(proposal.id); if (!prepareSuccess) { await this.initiateViewChange(); return false; } // Phase 3: Commit const commitSuccess = await this.collectCommitResponses(proposal.id); if (commitSuccess) { this.state.committed.add(proposal.id); this.updatePerformance(startTime, true); this.emit("consensus-reached", proposal); return true; } else { await this.initiateViewChange(); this.updatePerformance(startTime, false); return false; } } catch (error) { this.updatePerformance(startTime, false); this.emit("consensus-error", error); return false; } } /** * Process incoming consensus message */ public async processMessage(message: ConsensusMessage): Promise<void> { if (!this.validateMessage(message)) { this.emit("invalid-message", message); return; } this.messageLog.push(message); if (!this.state.messages.has(message.digest)) { this.state.messages.set(message.digest, []); } this.state.messages.get(message.digest)!.push(message); switch (message.type) { case "pre-prepare": await this.handlePrePrepare(message); break; case "prepare": await this.handlePrepare(message); break; case "commit": await this.handleCommit(message); break; case "view-change": await this.handleViewChange(message); break; case "new-view": await this.handleNewView(message); break; } } private async broadcastPrePrepare( proposal: ConsensusProposal, ): Promise<void> { const message: ConsensusMessage = { type: "pre-prepare", viewNumber: this.state.currentView, sequenceNumber: this.state.sequenceNumber, digest: proposal.hash, payload: proposal, timestamp: new Date(), signature: this.signMessage(proposal.hash), senderId: this.agentId, }; this.state.phase = "pre-prepare"; await this.broadcastMessage(message); } private async handlePrePrepare(message: ConsensusMessage): Promise<void> { if (message.senderId !== this.state.leader) { this.emit("malicious-behavior", { type: "unauthorized-pre-prepare", agentId: message.senderId, }); return; } if (message.viewNumber === this.state.currentView) { // Send prepare message const prepareMessage: ConsensusMessage = { type: "prepare", viewNumber: this.state.currentView, sequenceNumber: message.sequenceNumber, digest: message.digest, payload: null, timestamp: new Date(), signature: this.signMessage(message.digest), senderId: this.agentId, }; await this.broadcastMessage(prepareMessage); } } private async collectPrepareResponses(proposalId: string): Promise<boolean> { return new Promise((resolve) => { const requiredResponses = 2 * this.faultThreshold; const receivedResponses = 0; const timeout = setTimeout(() => { resolve(false); }, this.timeoutDuration); const checkResponses = () => { const proposal = this.state.proposals.get(proposalId); if (!proposal) return; const prepareMessages = this.state.messages.get(proposal.hash) || []; const prepareCount = prepareMessages.filter( (m) => m.type === "prepare" && m.viewNumber === this.state.currentView, ).length; if (prepareCount >= requiredResponses) { clearTimeout(timeout); this.state.phase = "prepare"; resolve(true); } }; this.on("message-received", checkResponses); // Initial check in case messages already arrived checkResponses(); }); } private async handlePrepare(message: ConsensusMessage): Promise<void> { const requiredResponses = 2 * this.faultThreshold; const proposal = Array.from(this.state.proposals.values()).find( (p) => p.hash === message.digest, ); if (!proposal) return; const prepareMessages = this.state.messages.get(message.digest) || []; const prepareCount = prepareMessages.filter( (m) => m.type === "prepare" && m.viewNumber === this.state.currentView, ).length; if (prepareCount >= requiredResponses) { // Send commit message const commitMessage: ConsensusMessage = { type: "commit", viewNumber: this.state.currentView, sequenceNumber: message.sequenceNumber, digest: message.digest, payload: null, timestamp: new Date(), signature: this.signMessage(message.digest), senderId: this.agentId, }; await this.broadcastMessage(commitMessage); } } private async collectCommitResponses(proposalId: string): Promise<boolean> { return new Promise((resolve) => { const requiredResponses = 2 * this.faultThreshold; const timeout = setTimeout(() => { resolve(false); }, this.timeoutDuration); const checkResponses = () => { const proposal = this.state.proposals.get(proposalId); if (!proposal) return; const commitMessages = this.state.messages.get(proposal.hash) || []; const commitCount = commitMessages.filter( (m) => m.type === "commit" && m.viewNumber === this.state.currentView, ).length; if (commitCount >= requiredResponses) { clearTimeout(timeout); this.state.phase = "commit"; resolve(true); } }; this.on("message-received", checkResponses); checkResponses(); }); } private async handleCommit(message: ConsensusMessage): Promise<void> { this.emit("message-received", message); } private async initiateViewChange(): Promise<void> { this.state.currentView++; this.state.leader = this.selectLeader(this.state.currentView); const viewChangeMessage: ConsensusMessage = { type: "view-change", viewNumber: this.state.currentView, sequenceNumber: this.state.sequenceNumber, digest: "", payload: { lastCommitted: Array.from(this.state.committed), messageLog: this.messageLog.slice(-100), // Last 100 messages }, timestamp: new Date(), signature: this.signMessage(`view-change-${this.state.currentView}`), senderId: this.agentId, }; await this.broadcastMessage(viewChangeMessage); this.emit("view-change-initiated", this.state.currentView); } private async handleViewChange(message: ConsensusMessage): Promise<void> { // Collect view change messages and determine new leader const viewChangeMessages = this.messageLog.filter( (m) => m.type === "view-change" && m.viewNumber === message.viewNumber, ); if (viewChangeMessages.length >= 2 * this.faultThreshold + 1) { if (this.agentId === this.selectLeader(message.viewNumber)) { await this.sendNewView(message.viewNumber); } } } private async sendNewView(viewNumber: number): Promise<void> { const newViewMessage: ConsensusMessage = { type: "new-view", viewNumber, sequenceNumber: this.state.sequenceNumber, digest: "", payload: { viewChangeMessages: this.messageLog.filter( (m) => m.type === "view-change" && m.viewNumber === viewNumber, ), }, timestamp: new Date(), signature: this.signMessage(`new-view-${viewNumber}`), senderId: this.agentId, }; await this.broadcastMessage(newViewMessage); } private async handleNewView(message: ConsensusMessage): Promise<void> { if (message.senderId === this.selectLeader(message.viewNumber)) { this.state.currentView = message.viewNumber; this.state.leader = message.senderId; this.state.phase = "pre-prepare"; this.emit("new-view-accepted", message.viewNumber); } } private selectLeader(viewNumber: number): string { const activeAgents = Array.from(this.state.activeAgents); const leaderIndex = viewNumber % activeAgents.length; return activeAgents[leaderIndex]; } private isLeader(): boolean { return this.agentId === this.state.leader; } private validateMessage(message: ConsensusMessage): boolean { // Basic validation if (!message.senderId || !message.signature || !message.timestamp) { return false; } // Check if sender is registered if (!this.agents.has(message.senderId)) { return false; } // Validate signature (simplified - in real implementation, use proper crypto) const expectedSignature = this.signMessage(message.digest || message.type); // Additional Byzantine fault checks const agent = this.agents.get(message.senderId)!; if (agent.isMalicious) { this.performance.faultsDetected++; return false; } return true; } private signMessage(data: string): string { // Simplified signing - in production, use proper cryptographic signatures return createHash("sha256") .update(data + this.agentId) .digest("hex"); } private async broadcastMessage(message: ConsensusMessage): Promise<void> { // Simulate network broadcast this.emit("broadcast-message", message); // In a real implementation, this would send to all agents setTimeout(() => { this.emit("message-received", message); }, Math.random() * 100); // Simulate network delay } private updatePerformance(startTime: number, success: boolean): void { this.performance.consensusRounds++; const latency = Date.now() - startTime; this.performance.averageLatency = (this.performance.averageLatency * (this.performance.consensusRounds - 1) + latency) / this.performance.consensusRounds; const successCount = success ? 1 : 0; this.performance.successRate = (this.performance.successRate * (this.performance.consensusRounds - 1) + successCount) / this.performance.consensusRounds; } /** * Get current consensus state */ public getState(): ConsensusState { return { ...this.state }; } /** * Get performance metrics */ public getPerformanceMetrics(): typeof this.performance { return { ...this.performance }; } /** * Check if consensus can be reached with current network */ public canReachConsensus(): boolean { const activeCount = this.state.activeAgents.size; const maliciousCount = Array.from(this.agents.values()).filter( (a) => a.isMalicious && this.state.activeAgents.has(a.id), ).length; return ( maliciousCount <= this.faultThreshold && activeCount >= this.minQuorum ); } /** * Get minimum quorum size for Byzantine consensus */ public getMinQuorum(): number { return this.minQuorum; } /** * Check if we have sufficient nodes for quorum */ public hasQuorum(): boolean { return this.state.activeAgents.size >= this.minQuorum; } /** * Simulate network partition */ public simulatePartition(agentIds: string[]): void { agentIds.forEach((id) => this.state.activeAgents.delete(id)); this.emit("network-partition", agentIds); } /** * Heal network partition */ public healPartition(agentIds: string[]): void { agentIds.forEach((id) => { if (this.agents.has(id)) { this.state.activeAgents.add(id); } }); this.emit("network-healed", agentIds); } } export default ByzantineConsensus;