From 058c5b6f787f36811446825bba0aa64ea2babf50 Mon Sep 17 00:00:00 2001 From: fallofpheonix Date: Thu, 21 May 2026 19:49:33 +0530 Subject: [PATCH] feat(arbiter): Implement Byzantine-Resistant Quorum [Issue #707] --- agents/internal/swarm/go.mod | 1 + agents/internal/swarm/reputation.go | 31 +++++++++++++ agents/internal/swarm/reputation_test.go | 12 +++++ phoenix_os/arbiter/consensus.go | 59 ++++++++++++++++++++++++ phoenix_os/arbiter/consensus_test.go | 23 +++++++++ phoenix_os/arbiter/go.mod | 2 - 6 files changed, 126 insertions(+), 2 deletions(-) create mode 100644 agents/internal/swarm/go.mod create mode 100644 agents/internal/swarm/reputation.go create mode 100644 agents/internal/swarm/reputation_test.go create mode 100644 phoenix_os/arbiter/consensus.go create mode 100644 phoenix_os/arbiter/consensus_test.go diff --git a/agents/internal/swarm/go.mod b/agents/internal/swarm/go.mod new file mode 100644 index 000000000..771d62732 --- /dev/null +++ b/agents/internal/swarm/go.mod @@ -0,0 +1 @@ +module phoenix/swarm diff --git a/agents/internal/swarm/reputation.go b/agents/internal/swarm/reputation.go new file mode 100644 index 000000000..08c2cdc92 --- /dev/null +++ b/agents/internal/swarm/reputation.go @@ -0,0 +1,31 @@ +package swarm + +import ( + "sync" +) + +type ReputationStore struct { + mu sync.RWMutex + reputation map[string]float64 +} + +func NewReputationStore() *ReputationStore { + return &ReputationStore{ + reputation: make(map[string]float64), + } +} + +func (s *ReputationStore) UpdateReputation(nodeID string, delta float64) { + s.mu.Lock() + defer s.mu.Unlock() + s.reputation[nodeID] += delta + if s.reputation[nodeID] < 0 { + s.reputation[nodeID] = 0 + } +} + +func (s *ReputationStore) GetReputation(nodeID string) float64 { + s.mu.RLock() + defer s.mu.RUnlock() + return s.reputation[nodeID] +} diff --git a/agents/internal/swarm/reputation_test.go b/agents/internal/swarm/reputation_test.go new file mode 100644 index 000000000..1c0554d5c --- /dev/null +++ b/agents/internal/swarm/reputation_test.go @@ -0,0 +1,12 @@ +package swarm + +import "testing" + +func TestReputationStore(t *testing.T) { + store := NewReputationStore() + store.UpdateReputation("node1", 10.0) + + if store.GetReputation("node1") != 10.0 { + t.Errorf("Expected 10.0, got %f", store.GetReputation("node1")) + } +} diff --git a/phoenix_os/arbiter/consensus.go b/phoenix_os/arbiter/consensus.go new file mode 100644 index 000000000..bb9e03bea --- /dev/null +++ b/phoenix_os/arbiter/consensus.go @@ -0,0 +1,59 @@ +package arbiter + +import ( + "sync" + "time" + + "phoenix/agents/internal/swarm" +) + +type Vote struct { + NodeID string + Decision bool + Confidence float64 +} + +type ConsensusEngine struct { + mu sync.Mutex + reputation *swarm.ReputationStore + votes []Vote + threshold float64 +} + +func NewConsensusEngine(rep *swarm.ReputationStore, threshold float64) *ConsensusEngine { + return &ConsensusEngine{ + reputation: rep, + votes: make([]Vote, 0), + threshold: threshold, + } +} + +func (e *ConsensusEngine) SubmitVote(v Vote) { + e.mu.Lock() + defer e.mu.Unlock() + e.votes = append(e.votes, v) +} + +func (e *ConsensusEngine) EvaluateQuorum() bool { + e.mu.Lock() + defer e.mu.Unlock() + + var weightedTotal float64 + var totalReputation float64 + + for _, v := range e.votes { + rep := e.reputation.GetReputation(v.NodeID) + if rep == 0 { rep = 1.0 } // Default minimal rep + + if v.Decision { + weightedTotal += rep * v.Confidence + } + totalReputation += rep + } + + if totalReputation == 0 { + return false + } + + return (weightedTotal / totalReputation) > e.threshold +} diff --git a/phoenix_os/arbiter/consensus_test.go b/phoenix_os/arbiter/consensus_test.go new file mode 100644 index 000000000..58a8b32f0 --- /dev/null +++ b/phoenix_os/arbiter/consensus_test.go @@ -0,0 +1,23 @@ +package arbiter + +import ( + "phoenix/agents/internal/swarm" + "testing" +) + +func TestConsensusEngine(t *testing.T) { + rep := swarm.NewReputationStore() + rep.UpdateReputation("node1", 10.0) // High trust + rep.UpdateReputation("node2", 1.0) // Low trust + + engine := NewConsensusEngine(rep, 0.5) + + // High trust node votes true + engine.SubmitVote(Vote{"node1", true, 0.9}) + // Low trust node votes false + engine.SubmitVote(Vote{"node2", false, 0.9}) + + if !engine.EvaluateQuorum() { + t.Error("Expected quorum to be true based on high trust node") + } +} diff --git a/phoenix_os/arbiter/go.mod b/phoenix_os/arbiter/go.mod index f3f500bf9..22be29322 100644 --- a/phoenix_os/arbiter/go.mod +++ b/phoenix_os/arbiter/go.mod @@ -1,3 +1 @@ module phoenix/arbiter - -go 1.25.0