Skip to content

Latest commit

 

History

History
648 lines (543 loc) · 27.8 KB

File metadata and controls

648 lines (543 loc) · 27.8 KB

Architecture Overview: High-Performance Decentralized Indexing

System Architecture

Core Components

┌─────────────────┐    ┌─────────────────┐    ┌─────────────────┐
│  Customer API   │    │  Query Router   │    │ Network Nodes   │
│                 │───▶│                 │───▶│ (Racing Pool)   │
│ - REST/GraphQL  │    │ - Load Balance  │    │ - 3-5 per query │
│ - WebSocket     │    │ - Node Selection│    │ - Independent   │
│ - Performance   │    │ - SLA Enforce   │    │ - Specialized   │
│   Guarantees    │    │ - Rate Limiting │    │ - Competitive   │
└─────────────────┘    └─────────────────┘    └─────────────────┘
                                │                        │
                                ▼                        ▼
┌─────────────────┐    ┌─────────────────┐    ┌─────────────────┐
│   Settlement    │    │   Consensus     │    │ Distributed     │
│    Engine       │◀───│    Engine       │◀───│ Query Engine    │
│                 │    │                 │    │                 │
│ - Token Payment │    │ - Result Verify │    │ - Sub-queries   │
│ - Node Rewards  │    │ - Racing Judge  │    │ - Result Merge  │
│ - Batch Solana  │    │ - Fraud Detect  │    │ - Cache Coord   │
└─────────────────┘    └─────────────────┘    └─────────────────┘

Data Flow Architecture

Customer Query Request
        │
        ▼
┌─────────────────┐
│ Query Router    │ ──── Authenticate Customer
│                 │ ──── Analyze Query Complexity
│                 │ ──── Select Racing Nodes
└─────────────────┘
        │
        ▼
┌─────────────────┐
│ Distributed     │ ──── Generate Sub-queries
│ Query Planner   │ ──── Find Data Locations
│                 │ ──── Optimize Execution Plan
└─────────────────┘
        │
        ▼
┌─────────────────┐
│ Racing Nodes    │ ──── Execute Sub-queries in Parallel
│ (3-5 nodes)     │ ──── Merge Partial Results
│                 │ ──── Race for Best Response
└─────────────────┘
        │
        ▼
┌─────────────────┐
│ Consensus       │ ──── Verify Results Match
│ Verification    │ ──── Check Performance Target
│                 │ ──── Detect Anomalies
└─────────────────┘
        │
        ▼
┌─────────────────┐
│ Economic        │ ──── Distribute Rewards
│ Settlement      │ ──── Process Customer Payment
│                 │ ──── Update Reputation Scores
└─────────────────┘
        │
        ▼
    Customer Response

Core Technical Components

1. Query Router

pub struct QueryRouter {
    // Customer-facing interface
    customer_api: CustomerAPI,

    // Performance and load management
    performance_monitor: PerformanceMonitor,
    load_balancer: IntelligentLoadBalancer,
    rate_limiter: CustomerRateLimiter,

    // Node selection and routing
    node_registry: NodeRegistry,
    routing_algorithm: RoutingAlgorithm,

    // SLA enforcement
    sla_manager: SLAManager,
    timeout_manager: TimeoutManager,
}

impl QueryRouter {
    pub async fn route_customer_query(&self, request: CustomerRequest) -> RoutingDecision {
        // 1. Authenticate and validate customer
        let auth_result = self.customer_api.authenticate(&request).await?;

        // 2. Analyze query requirements
        let query_analysis = self.analyze_query_requirements(&request.query).await;

        // 3. Select optimal racing nodes
        let racing_nodes = self.select_racing_nodes(&query_analysis).await;

        // 4. Create execution plan
        RoutingDecision {
            selected_nodes: racing_nodes,
            execution_strategy: query_analysis.execution_strategy,
            performance_target: request.performance_requirements,
            timeout_config: self.timeout_manager.for_query(&query_analysis),
        }
    }

    async fn select_racing_nodes(&self, analysis: &QueryAnalysis) -> Vec<NodeId> {
        // Find nodes capable of handling this query type
        let capable_nodes = self.node_registry
            .find_capable_nodes(&analysis.requirements).await;

        // Weight by reputation, performance, and current load
        let weighted_nodes = capable_nodes.iter()
            .map(|node| (node.id, self.calculate_selection_weight(node)))
            .collect();

        // Select 3-5 nodes for racing based on weights
        self.routing_algorithm.weighted_selection(weighted_nodes, 5)
    }
}

2. Distributed Query Engine

pub struct DistributedQueryEngine {
    // Local database instance
    local_db: DuckDBConnection,

    // Query planning and optimization
    query_planner: DistributedQueryPlanner,
    query_optimizer: QueryOptimizer,

    // Inter-node communication
    network_interface: NNGNetworkInterface,

    // Result processing
    result_merger: ResultMerger,
    cache_manager: CacheManager,
}

impl DistributedQueryEngine {
    pub async fn execute_distributed_query(&self, query: NetworkQuery) -> QueryResult {
        // 1. Plan query execution across available data
        let execution_plan = self.query_planner.plan_execution(&query).await?;

        match execution_plan {
            ExecutionPlan::LocalOnly(local_query) => {
                // All required data is local
                self.execute_local_query(local_query).await
            },

            ExecutionPlan::Distributed { local_part, remote_parts } => {
                // Need to coordinate with other nodes
                self.execute_coordinated_query(local_part, remote_parts).await
            },

            ExecutionPlan::CacheOptimized { cache_query, fallback } => {
                // Try cache first, fallback if needed
                match self.cache_manager.try_cache_query(&cache_query).await {
                    Some(cached_result) => Ok(cached_result),
                    None => self.execute_distributed_query(*fallback).await,
                }
            }
        }
    }

    async fn execute_coordinated_query(
        &self,
        local_part: Option<LocalQuery>,
        remote_parts: Vec<(NodeId, SubQuery)>
    ) -> QueryResult {

        let mut all_results = Vec::new();

        // Execute local part if exists
        if let Some(local_query) = local_part {
            let local_result = self.execute_local_query(local_query).await?;
            all_results.push(local_result);
        }

        // Execute remote parts in parallel
        let remote_futures = remote_parts.into_iter().map(|(node_id, sub_query)| {
            self.network_interface.execute_remote_query(node_id, sub_query)
        });

        let remote_results = join_all(remote_futures).await;

        // Filter successful results
        for result in remote_results {
            if let Ok(sub_result) = result {
                all_results.push(sub_result);
            }
        }

        // Merge all partial results
        self.result_merger.merge_partial_results(all_results).await
    }
}

3. NNG Network Communication

pub struct NNGNetworkInterface {
    // Different socket types for different communication patterns
    query_sockets: HashMap<NodeId, Socket>,      // REQ/REP for queries
    broadcast_socket: Socket,                    // PUB/SUB for announcements
    discovery_socket: Socket,                    // For node discovery

    // Connection management
    connection_manager: ConnectionManager,
    health_monitor: NetworkHealthMonitor,

    // Message serialization
    message_codec: MessageCodec,
}

impl NNGNetworkInterface {
    pub async fn execute_remote_query(&self, node_id: NodeId, sub_query: SubQuery) -> Result<PartialResult, NetworkError> {
        // Get or create connection to target node
        let socket = self.connection_manager.get_connection(node_id).await?;

        // Serialize and send query
        let query_message = self.message_codec.encode_sub_query(&sub_query)?;
        socket.send(query_message).await
            .map_err(|e| NetworkError::SendFailed(e))?;

        // Receive and deserialize response with timeout
        let response_message = timeout(
            Duration::from_millis(15), // 15ms timeout for sub-queries
            socket.recv()
        ).await
            .map_err(|_| NetworkError::Timeout)?
            .map_err(|e| NetworkError::ReceiveFailed(e))?;

        let partial_result = self.message_codec.decode_partial_result(&response_message)?;

        Ok(partial_result)
    }

    pub async fn broadcast_network_announcement(&self, announcement: NetworkAnnouncement) -> Result<(), NetworkError> {
        let message = self.message_codec.encode_announcement(&announcement)?;

        self.broadcast_socket.send(message).await
            .map_err(|e| NetworkError::BroadcastFailed(e))?;

        Ok(())
    }

    pub async fn maintain_network_health(&mut self) {
        loop {
            // Check all connections health
            self.health_monitor.check_all_connections().await;

            // Drop unhealthy connections
            let unhealthy_nodes = self.health_monitor.get_unhealthy_nodes();
            for node_id in unhealthy_nodes {
                self.connection_manager.drop_connection(node_id).await;
            }

            // Discover new nodes
            self.discover_new_nodes().await;

            sleep(Duration::from_secs(30)).await;
        }
    }
}

4. Consensus and Verification Engine

pub struct ConsensusEngine {
    // Racing result verification
    racing_verifier: RacingResultVerifier,

    // Fraud detection
    fraud_detector: FraudDetectionEngine,

    // Reputation management
    reputation_manager: ReputationManager,

    // Performance verification
    performance_verifier: PerformanceVerifier,
}

impl ConsensusEngine {
    pub async fn verify_racing_results(&self, race_results: Vec<RaceResult>) -> ConsensusResult {
        // 1. Quick consensus check - do majority agree?
        if let Some(consensus_result) = self.racing_verifier.find_quick_consensus(&race_results) {
            return ConsensusResult::QuickConsensus(consensus_result);
        }

        // 2. Detailed verification for disagreements
        let detailed_verification = self.detailed_result_verification(&race_results).await;

        // 3. Fraud detection
        let fraud_analysis = self.fraud_detector.analyze_results(&race_results).await;

        if fraud_analysis.fraud_detected {
            // Handle fraud cases
            self.handle_fraud_detection(fraud_analysis).await;
            return ConsensusResult::FraudDetected(fraud_analysis);
        }

        // 4. Reputation-weighted consensus
        let weighted_consensus = self.reputation_manager
            .weighted_consensus_resolution(&race_results).await;

        ConsensusResult::ReputationWeightedConsensus(weighted_consensus)
    }

    async fn detailed_result_verification(&self, results: &[RaceResult]) -> VerificationResult {
        // Check each result for internal consistency
        let consistency_checks = results.iter().map(|result| {
            self.verify_result_consistency(result)
        });

        let consistency_results = join_all(consistency_checks).await;

        // Check for systematic discrepancies
        let discrepancy_analysis = self.analyze_result_discrepancies(results);

        VerificationResult {
            consistency_scores: consistency_results,
            discrepancy_analysis,
            recommended_action: self.recommend_consensus_action(&consistency_results, &discrepancy_analysis),
        }
    }
}

5. Economic Settlement Engine

pub struct SettlementEngine {
    // Solana integration for token operations
    solana_client: SolanaClient,
    token_program: TokenProgram,

    // Payment processing
    payment_processor: PaymentProcessor,
    credit_manager: CustomerCreditManager,

    // Node reward distribution
    reward_distributor: NodeRewardDistributor,
    reputation_tracker: ReputationTracker,

    // Batching for efficiency
    settlement_batcher: SettlementBatcher,
}

impl SettlementEngine {
    pub async fn process_query_settlement(&mut self, query_result: QueryResult, race_info: RaceInfo) -> SettlementResult {
        // 1. Determine payment outcome based on performance
        let payment_outcome = self.determine_payment_outcome(&query_result, &race_info);

        match payment_outcome {
            PaymentOutcome::TargetMet { customer_payment, node_rewards } => {
                // Customer pays, nodes get rewarded
                self.credit_manager.deduct_credits(race_info.customer_id, customer_payment).await?;

                for (node_id, reward) in node_rewards {
                    self.reward_distributor.queue_reward(node_id, reward).await;
                    self.reputation_tracker.record_successful_query(node_id, &query_result).await;
                }

                SettlementResult::Successful { customer_charged: customer_payment, nodes_rewarded: node_rewards }
            },

            PaymentOutcome::TargetMissed { performance_penalty } => {
                // Customer pays nothing, nodes get penalized
                self.credit_manager.refund_credits(race_info.customer_id, race_info.original_payment).await?;

                for (node_id, penalty) in performance_penalty {
                    self.reward_distributor.apply_penalty(node_id, penalty).await;
                    self.reputation_tracker.record_performance_miss(node_id, &query_result).await;
                }

                SettlementResult::PerformanceMiss { customer_refunded: race_info.original_payment, nodes_penalized: performance_penalty }
            },

            PaymentOutcome::QueryFailed => {
                // Query failed completely, customer pays nothing
                self.credit_manager.refund_credits(race_info.customer_id, race_info.original_payment).await?;

                SettlementResult::QueryFailed { customer_refunded: race_info.original_payment }
            }
        }
    }

    pub async fn execute_batch_settlement(&mut self) -> BatchSettlementResult {
        // Collect all pending rewards and penalties
        let pending_settlements = self.settlement_batcher.collect_pending_settlements().await;

        if pending_settlements.is_empty() {
            return BatchSettlementResult::NothingToSettle;
        }

        // Create batch Solana transaction
        let settlement_transaction = self.create_batch_settlement_transaction(&pending_settlements).await?;

        // Execute on Solana
        let transaction_signature = self.solana_client
            .send_and_confirm_transaction(&settlement_transaction).await?;

        // Clear pending settlements
        self.settlement_batcher.clear_settled(&pending_settlements).await;

        BatchSettlementResult::Success {
            transaction_signature,
            nodes_settled: pending_settlements.len(),
            total_amount_settled: pending_settlements.iter().map(|s| s.amount).sum(),
        }
    }
}

Data Architecture

Distributed DuckDB Design

pub struct DistributedDuckDBLayer {
    // Local DuckDB instance
    local_db: DuckDBConnection,

    // Data partition management
    partition_manager: DataPartitionManager,

    // Data synchronization
    sync_manager: DataSyncManager,

    // Query optimization for distributed data
    distributed_optimizer: DistributedQueryOptimizer,
}

pub enum DataPartitionStrategy {
    // Partition by account address ranges
    AccountRange { start: Pubkey, end: Pubkey },

    // Partition by program/token
    ProgramData { programs: Vec<Pubkey> },

    // Partition by time
    TimeRange { start_slot: u64, end_slot: u64 },

    // Partition by query frequency (hot/cold data)
    AccessFrequency { tier: AccessTier },
}

impl DistributedDuckDBLayer {
    pub async fn optimize_data_distribution(&mut self) -> OptimizationResult {
        // Analyze query patterns
        let query_patterns = self.analyze_recent_query_patterns().await;

        // Identify hot/cold data splits
        let data_temperature_analysis = self.analyze_data_access_patterns().await;

        // Optimize partitioning strategy
        let new_partitioning = self.distributed_optimizer
            .optimize_partitioning(&query_patterns, &data_temperature_analysis).await;

        // Execute data rebalancing if beneficial
        if new_partitioning.improvement_score > 0.2 {
            self.execute_data_rebalancing(new_partitioning).await
        } else {
            OptimizationResult::NoChangeNeeded
        }
    }
}

This architecture provides:

  • High performance through racing and specialization
  • Economic incentives aligned with performance
  • Fault tolerance through redundancy and consensus
  • Scalability through distributed data and computation
  • Flexibility for various query types and performance requirements

Gossip Protocol Architecture

Network Topology Management

┌─────────────────┐    ┌─────────────────┐    ┌─────────────────┐
│   Node A        │───▶│   Node B        │───▶│   Node C        │
│                 │◀───│                 │◀───│                 │
│ Gossip Manager  │    │ Gossip Manager  │    │ Gossip Manager  │
│ - Peer tracking │    │ - Peer tracking │    │ - Peer tracking │
│ - Heartbeats    │    │ - Heartbeats    │    │ - Heartbeats    │
└─────────────────┘    └─────────────────┘    └─────────────────┘
        │                      │                      │
        ▼                      ▼                      ▼
┌─────────────────────────────────────────────────────────────┐
│                  Gossip Message Flow                         │
│                                                              │
│  Push: "Here's my peer list" ──────────────────────────────▶│
│  Pull: "What peers do you know?" ◀──────────────────────────│
│  PushPull: Combined for efficiency ◀───────────────────────▶│
│  Heartbeat: "I'm alive" ────────────────────────────────────▶│
└─────────────────────────────────────────────────────────────┘

Gossip Message Types

pub enum GossipMessage {
    Push(GossipPush),         // Share our peer list
    Pull(GossipPull),         // Request peer list
    PushPull(GossipPushPull), // Combined for efficiency
    Heartbeat(GossipHeartbeat), // Liveness check
    StateSync(GossipStateSync), // Configuration sync
}

Peer Status State Machine

                 ┌──────────────┐
                 │   Unknown    │
                 └──────┬───────┘
                        │ First contact
                        ▼
                 ┌──────────────┐
            ┌────│   Healthy    │◀──────────────┐
            │    └──────┬───────┘               │
            │           │ Missed heartbeat      │ Heartbeat received
            │           ▼                       │
            │    ┌──────────────┐               │
            │    │   Degraded   │───────────────┘
            │    └──────┬───────┘
            │           │ Multiple missed
            │           ▼
            │    ┌──────────────┐
            │    │ Unavailable  │
            │    └──────┬───────┘
            │           │ Timeout exceeded
            │           ▼
            │    ┌──────────────┐
            └────│    Down      │────▶ Remove from pool
                 └──────────────┘

Health Monitoring Architecture

Cluster Health Check Flow

┌─────────────────────────────────────────────────────────────┐
│                   Shard Manager                              │
│                                                              │
│  ┌────────────────┐    ┌────────────────┐                   │
│  │ Health Check   │───▶│ Node Status    │                   │
│  │ Task           │    │ Tracker        │                   │
│  └────────────────┘    └────────────────┘                   │
│          │                     │                             │
│          ▼                     ▼                             │
│  ┌────────────────┐    ┌────────────────┐                   │
│  │ Heartbeat      │    │ Metrics        │                   │
│  │ Intervals      │    │ Recorder       │                   │
│  └────────────────┘    └────────────────┘                   │
└─────────────────────────────────────────────────────────────┘
                         │
                         ▼
┌─────────────────────────────────────────────────────────────┐
│                   Status Transitions                         │
│                                                              │
│  time_since_heartbeat < timeout        → Healthy            │
│  timeout < time < timeout*2            → Degraded           │
│  timeout*2 < time < timeout*5          → Unavailable        │
│  time > timeout*5                      → Failed             │
└─────────────────────────────────────────────────────────────┘

Rebalancing Architecture

┌─────────────────────────────────────────────────────────────┐
│                 Cluster Rebalancing                          │
│                                                              │
│  Step 1: Calculate Load Distribution                        │
│  ┌────────────┐ ┌────────────┐ ┌────────────┐              │
│  │ Node A: 40%│ │ Node B: 35%│ │ Node C: 25%│              │
│  └────────────┘ └────────────┘ └────────────┘              │
│                                                              │
│  Step 2: Identify Imbalance                                 │
│  Target: 33% each                                           │
│  Node A: +7% (overloaded)                                   │
│  Node C: -8% (underloaded)                                  │
│                                                              │
│  Step 3: Plan Migrations                                    │
│  ┌────────────────────────────────────────────────────┐     │
│  │  Move 7 vnodes: Node A ────────────────▶ Node C    │     │
│  └────────────────────────────────────────────────────┘     │
│                                                              │
│  Step 4: Execute with Minimal Disruption                    │
│  - Replicate data first                                     │
│  - Update hash ring                                         │
│  - Remove old replicas                                      │
└─────────────────────────────────────────────────────────────┘

Node Specialization Architecture

Specialization Types

pub enum NodeSpecialization {
    SpeedRunner {
        target_latency_ms: 1,        // Sub-millisecond queries
        cache_strategy: CacheStrategy::Aggressive,
    },
    ReconstructionSpec {
        zk_capability: ZKCapability::Full,
        merkle_cache_size: 1_000_000,
    },
    CacheOptimizer {
        hot_data_threshold: 10_000,
        eviction_policy: EvictionPolicy::LRU,
    },
    ArchiveNode {
        retention_days: 365,
        compression_level: 9,
    },
}

Query Routing by Specialization

                    ┌─────────────┐
                    │Query Router │
                    └──────┬──────┘
                           │
          ┌────────────────┼────────────────┐
          ▼                ▼                ▼
   ┌─────────────┐  ┌─────────────┐  ┌─────────────┐
   │ Real-time   │  │ Historical  │  │ Compressed  │
   │ Query       │  │ Query       │  │ Account     │
   └──────┬──────┘  └──────┬──────┘  └──────┬──────┘
          │                │                │
          ▼                ▼                ▼
   ┌─────────────┐  ┌─────────────┐  ┌─────────────┐
   │SpeedRunners │  │ArchiveNodes │  │Reconstruction│
   │             │  │             │  │Specialists  │
   └─────────────┘  └─────────────┘  └─────────────┘