saved
This commit is contained in:
362
docs/FUTURE_DHT_ARCHITECTURE.txt
Normal file
362
docs/FUTURE_DHT_ARCHITECTURE.txt
Normal file
@@ -0,0 +1,362 @@
|
||||
================================================================================
|
||||
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 : <adresse réseau>,
|
||||
region : <subnet /24>,
|
||||
capacity : <maxNodesConn>,
|
||||
fill_rate : <float 0-1>, ← auto-déclaré, vérifiable
|
||||
peer_count : <int>, ← auto-déclaré, vérifiable
|
||||
peers : [hash(nodeID1), ...], ← liste hashée des nodes connectés
|
||||
born_at : <timestamp>,
|
||||
sig : <signature clé indexer>, ← 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 : <optionnel, voir §8>
|
||||
}
|
||||
|
||||
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
|
||||
|
||||
================================================================================
|
||||
Reference in New Issue
Block a user