================================================================================ OC-DISCOVERY : ARCHITECTURE CIBLE — RÉSEAU DHT SANS NATIFS Vision d'évolution long terme, issue d'une analyse comparative ================================================================================ Rédigé à partir de l'analyse de l'architecture actuelle et de la discussion comparative avec Tapestry, Kademlia, EigenTrust et les systèmes de réputation distribués. Référence : DECENTRALIZED_SYSTEMS_COMPARISON.txt §9 ================================================================================ 1. MOTIVATION ================================================================================ L'architecture actuelle (node → indexer → native indexer) est robuste et bien adaptée à une phase précoce du réseau. Ses limites à l'échelle sont : - Pool de natives statique au démarrage → dépendance à la configuration - Cache local des natives = point de défaillance unique (perte = pool vide) - Consensus inter-natives bloquant (~7s) déclenché à chaque bootstrap node - État O(N indexers) par native → croît linéairement avec le réseau - Nœuds privilégiés structurellement → SPOFs relatifs La cible décrite ici supprime la notion de native indexer en tant que tier architectural. Le réseau devient plat : indexers et nodes sont des acteurs de même nature, différenciés uniquement par leur rôle volontaire. ================================================================================ 2. PRINCIPES FONDAMENTAUX ================================================================================ P1. Aucun nœud n'est structurellement privilégié. P2. La confiance est un produit du temps et de la vérification, pas d'un arbitre. P3. Les claims d'un acteur sont vérifiables indépendamment par tout pair. P4. La réputation émerge du comportement collectif, pas d'un signalement central. P5. La DHT est une infrastructure neutre — elle stocke des faits, pas des jugements. P6. La configuration statique n'existe plus au runtime — seulement au bootstrap. ================================================================================ 3. RÔLES ================================================================================ 3.1 Node -------- Consommateur du réseau. Démarre, sélectionne un pool d'indexers via DHT, heartbeat ses indexers, accumule des scores localement. Ne publie rien en routine. Participe aux challenges de consensus à la demande. 3.2 Indexer ----------- Acteur volontaire. S'inscrit dans la DHT à la naissance, maintient son record, sert le trafic des nodes (heartbeat, Publish, Get). Déclare ses métriques dans chaque réponse heartbeat. Maintient un score agrégé depuis ses nodes connectés. Différence avec l'actuel : l'indexer n'a plus de lien avec une native. Il est autonome. Son existence dans le réseau est prouvée par son record DHT et par les nodes qui le contactent directement. 3.3 Nœud DHT infrastructure (ex-native) ---------------------------------------- N'importe quel nœud suffisamment stable peut maintenir la DHT sans être un indexer. C'est une configuration, pas un type architectural : `dht_mode: server`. Ces nœuds maintiennent les k-buckets Kademlia et stockent les records des indexers. Ils ne connaissent pas le trafic node↔indexer et ne l'orchestrent pas. ================================================================================ 4. BOOTSTRAP D'UN NODE ================================================================================ 4.1 Entrée dans le réseau ------------------------- Le node démarre avec 1 à 3 adresses de nœuds DHT connus (bootstrap peers). Ce sont les seules informations statiques nécessaires. Ces peers n'ont pas de rôle sémantique — ils servent uniquement à entrer dans l'overlay DHT. 4.2 Découverte du pool d'indexers ---------------------------------- Node → DHT.FindProviders(hash("/opencloud/indexers")) → reçoit une liste de N candidats avec leurs records Sélection du pool initial : 1. Filtre latence : ping < seuil → proximité réseau réelle 2. Filtre fill rate : préférer les indexers moins chargés 3. Tirage pondéré : probabilité ∝ (1 - fill_rate), courbe w(F) = F×(1-F) indexer à 20% charge → très probable indexer à 80% charge → peu probable 4. Filtre diversité : subnet /24 différent pour chaque entrée du pool Aucun consensus nécessaire à cette étape. Le node démarre avec une tolérance basse (voir §7) — il accepte des indexers imparfaits et les évalue au fil du temps. ================================================================================ 5. REGISTRATION D'UN INDEXER DANS LA DHT ================================================================================ À la naissance, l'indexer publie son record DHT : clé : hash("/opencloud/indexers") ← clé fixe, connue de tous valeur: { multiaddr : , region : , capacity : , fill_rate : , ← auto-déclaré, vérifiable peer_count : , ← auto-déclaré, vérifiable peers : [hash(nodeID1), ...], ← liste hashée des nodes connectés born_at : , sig : , ← non-forgeable (PSK context) } Le record est rafraîchi toutes les ~60s (avant expiration du TTL). Si l'indexer tombe : TTL expire → disparaît de la DHT automatiquement. La peer list est hashée pour la confidentialité mais reste vérifiable : un challenger peut demander directement à un node s'il est connecté à cet indexer. ================================================================================ 6. PROTOCOLE HEARTBEAT — QUESTION ET RÉPONSE ================================================================================ Le heartbeat devient bidirectionnel : le node pose des questions, l'indexer répond avec ses déclarations courantes. 6.1 Structure ------------- Node → Indexer : { ts : now, challenge : } Indexer → Node : { ts : now, fill_rate : 0.42, peer_count : 87, cached_score : 0.74, ← score agrégé depuis tous ses nodes connectés challenge_response : {...} ← si challenge présent dans la requête } Le heartbeat normal (sans challenge) est quasi-identique à l'actuel en poids. Le cached_score indexer est mis à jour progressivement par les feedbacks reçus. 6.2 Le cached_score de l'indexer --------------------------------- L'indexer agrège les scores que ses nodes connectés lui communiquent (implicitement via le fait qu'ils restent connectés, ou explicitement lors d'un consensus). Ce score lui donne une vision de sa propre qualité réseau. Un node peut comparer son score local de l'indexer avec le cached_score déclaré. Une forte divergence est un signal d'alerte. Score local node : 0.40 ← cet indexer est médiocre pour moi Cached score : 0.91 ← il se prétend excellent globalement → déclenche un challenge de vérification ================================================================================ 7. MODÈLE DE CONFIANCE PROGRESSIVE ================================================================================ 7.1 Cycle de vie d'un node --------------------------- Naissance → tolérance basse : accepte presque n'importe quel indexer du DHT → switching cost faible : peu de contexte accumulé → minScore ≈ 20% (dynamicMinScore existant, conservé) Quelques heures → uptime s'accumule sur chaque indexer connu → scores se stabilisent → seuil de remplacement qui monte progressivement Long terme (jours) → pool stable, confiance élevée sur les indexers connus → switching coûteux mais déclenché sur déception franche → minScore ≈ 80% (maturité) 7.2 Modèle sous-jacent : beta distribution implicite ------------------------------------------------------ α = succès cumulés (heartbeats OK, probes OK, challenges réussis) β = échecs cumulés (timeouts, probes échoués, challenges ratés) confiance = α / (α + β) Nouveau indexer : α=0, β=0 → prior neutre, tolérance basse Après 10 jours : α élevé → confiance stable, seuil de switch élevé Déception franche : β monte → confiance chute → switch déclenché 7.3 Ce que "décevoir" signifie -------------------------------- Heartbeat rate → trop de timeouts → fiabilité en baisse Bandwidth probe → chute sous déclaré → dégradation ou mensonge Fill rate réel → supérieur au déclaré → indexer surchargé ou malhonnête Challenge échoué → peer déclaré absent du réseau → claim invalide Latence → dérive progressive → qualité réseau dégradée Cached_score gonflé → divergence forte avec score local → suspicion ================================================================================ 8. VÉRIFICATION DES CLAIMS — TROIS COUCHES ================================================================================ 8.1 Couche 1 : passive (chaque heartbeat, 60s) ----------------------------------------------- Mesures automatiques, zéro coût supplémentaire. - RTT du heartbeat → latence directe - fill_rate déclaré → tiny payload dans la réponse - peer_count déclaré → tiny payload - cached_score indexer → comparé au score local 8.2 Couche 2 : sampling actif (1 heartbeat sur N) -------------------------------------------------- Vérifications périodiques, asynchrones, légères. Tous les 5 HB (~5min) : spot-check 1 peer aléatoire (voir §8.4) Tous les 10 HB (~10min): vérification diversité subnet (lookups DHT légers) Tous les 15 HB (~15min): bandwidth probe (transfert réel, protocole dédié) 8.3 Couche 3 : consensus (événementiel) ----------------------------------------- Déclenché sur : admission d'un nouvel indexer dans le pool, ou suspicion détectée. Node sélectionne une claim vérifiable de l'indexer cible X Node vérifie lui-même Node demande à ses indexers de confiance : "vérifiez cette claim sur X" Chaque indexer vérifie indépendamment Convergence des résultats → X est honnête → admission Divergence → X est suspect → rejet ou probation Le consensus est léger : quelques contacts out-of-band, pas de round bloquant. Il n'est pas continu — il est événementiel. 8.4 Vérification out-of-band (pas de DHT writes par les nodes) ---------------------------------------------------------------- Les nodes ne publient PAS de contact records continus dans la DHT. Cela éviterait N×M records à rafraîchir (coût DHT élevé à l'échelle). À la place, lors d'un challenge : Challenger sélectionne 2-3 peers dans la peer list déclarée par X → contacte ces peers directement : "es-tu connecté à indexer X ?" → réponse directe (out-of-band, pas via DHT) → vérification sans écriture DHT L'indexer ne peut pas faire répondre "oui" à des peers qui ne lui sont pas connectés. La vérification est non-falsifiable et sans coût DHT. 8.5 Pourquoi X ne peut pas tricher ------------------------------------ X ne peut pas coordonner des réponses différentes vers des challengers simultanés. Chaque challenger contacte indépendamment les mêmes peers. Si X ment sur sa peer list : - Challenger A contacte peer P → "non, pas connecté à X" - Challenger B contacte peer P → "non, pas connecté à X" - Consensus : X ment → score chute chez tous les challengers - Effet réseau : progressivement, X perd ses connections - Peer list DHT se vide → claims futures encore moins crédibles ================================================================================ 9. EFFET RÉSEAU SANS SIGNALEMENT CENTRAL ================================================================================ Un node qui pénalise un indexer n'envoie aucun "rapport" à quiconque. Ses actions locales produisent l'effet réseau par agrégation : Node baisse le score de X → X reçoit moins de trafic de ce node Node switche vers Y → X perd un client Node refuse les challenges X → X ne peut plus participer aux consensus Si 200 nodes font pareil : X perd la majorité de ses connections Sa peer list DHT se vide (peers contactés directement disent "non") Son cached_score s'effondre (peu de nodes restent) Les nouveaux nodes qui voient X dans la DHT obtiennent des challenges échoués X est naturellement exclu sans aucune décision centrale Inversement, un indexer honnête voit ses scores monter sur tous ses nodes connectés, sa peer list se densifier, ses challenges réussis systématiquement. Sa réputation est un produit observable et vérifiable. ================================================================================ 10. RÉSUMÉ DE L'ARCHITECTURE ================================================================================ DHT → annuaire neutre, vérité des records indexers maintenu par tout nœud stable (dht_mode: server) Indexer → acteur volontaire, s'inscrit, maintient ses claims, sert le trafic, accumule son propre score agrégé Node → consommateur, score passif + sampling + consensus léger, confiance progressive, switching adaptatif Heartbeat → métronome 60s + vecteur de déclarations légères + challenge optionnel Consensus → événementiel, multi-challengers indépendants, vérification out-of-band sur claims DHT Confiance → beta implicite, progressive, switching cost croissant avec l'âge Réputation → émerge du comportement collectif, aucun arbitre central Bootstrap → 1-3 peers DHT connus → seule configuration statique nécessaire ================================================================================ 11. TRAJECTOIRE DE MIGRATION ================================================================================ Phase 1 (actuel) Natives statiques, pool indexers dynamique, consensus inter-natives → robuste, adapté à la phase précoce Phase 2 (intermédiaire) Pool de natives dynamique via DHT (bootstrap + gossip) Même protocole natif, juste la découverte devient dynamique → supprime la dépendance à la configuration statique des natives → voir DECENTRALIZED_SYSTEMS_COMPARISON.txt §9.2 Phase 3 (cible) Architecture décrite dans ce document Natives disparaissent en tant que tier architectural DHT = infrastructure, indexers = acteurs autonomes Scoring et consensus entièrement côté node → aucun nœud privilégié, scalabilité O(log N) La migration Phase 2 → Phase 3 est une refonte du plan de contrôle. Le plan de données (heartbeat node↔indexer, Publish, Get) est inchangé. Les primitives libp2p (Kademlia DHT, GossipSub) sont déjà présentes. ================================================================================ 12. PROPRIÉTÉS DU SYSTÈME CIBLE ================================================================================ Scalabilité O(log N) — routage DHT Kademlia Résilience Pas de SPOF structurel, TTL = seule source de vérité Confiance Progressive, vérifiable, émergente Sybil resistance PSK — seuls les nœuds avec la clé peuvent publier Cold start Tolérance basse initiale, montée progressive (existant) Honnêteté Claims vérifiables out-of-band, non-falsifiables Décentralisation Aucun nœud ne connaît l'état global complet ================================================================================