Scan du réseau Duniter v2 pour Cesium2

Pourrais-tu détailler l’algorithme utilisé ? Tu check le duniter_peerings(RPC) puis, à partir de la réponse, tu vérifie récursivement les endpoints de type rpc ?

J’essaie de me remettre dans le sujet et je me demande s’il faut aussi que j’implémente une découverte RPC comme que je le faisais ici : Liste des endpoints - #19 by cgeek .

1 Like

Durt2 fait une découverte récursive des peerings Duniter avec fallback du repo GitLab.

Il commence par interroger le cache local (6h de validité), puis le cache étendu (24h), puis les fichiers de configuration locaux. En parallèle, il lance un fetch en arrière-plan vers les URLs GitLab pour récupérer les configurations réseau à jour. L’algorithme principal appelle duniter_peerings RPC sur les endpoints bootstrap connus, extrait récursivement tous les endpoints RPC découverts et les interroge à nouveau en parallèle (max 8 nœuds simultanés) pour découvrir l’ensemble du réseau.

Pour Squid, il utilise les RPC découverts pour interroger les peerings et extraire les endpoints de type squid. Chaque endpoint découvert est testé en parallèle avec validation du genesis hash, ainsi qu’un match sur une correspondance des 3 derniers blocs height et hash (qu’il y ait au moins 1 match sur les 3 derniers blocs, car squid peut être légèrement en retard sur la sync, mais avec 3 bloc de marge on est large), déduplication et sélection du plus rapide. Les résultats sont mis en cache (5min pour fast cache, 24h pour bootstrap) et les listes Networks sont mises à jour.

4 Likes

Ok, je n’irai pas aussi loin pour Cesium au moins dans une 1ère version.

Je compte juste proposer le scan réseau au moment de choisir un nœud, puis l’utilisateur choisit celui qui lui convient et ensuite on passe en mode “mono-nœud/squid”.

Si l’on veut sortir quelque chose sans trop traîner, ça me semble être la bonne approche. Et vu le nombre de nœuds que l’on aura au début, c’est-à-dire très peu, cela devrait être largement suffisant. On pourra comparer les résultats avec Ğecko, ce sera intéressant :slight_smile:

1 Like

Il faut considérer le choix manuel d’un noeud comme une fonctionnalité avancé qui ne devrait pas être utilisé par la plupart des gens.

Le but est de s’assurer qu’au démarrage de l’app un noeud fiable et sur le fork majoritaire est choisi, et très rapidement, sans délais. C’est là toute la difficulté, dans ce délais :wink:

Réflexion personnelle

Ce n’est pas du tout une question facile. C’est la question du consensus réseau qui est au-delà de la blockchain. Car on l’a bien vu sur la Ğ1 avec Duniter v1 par exemple, mais aussi sur Ethereum : ce n’est pas forcément la chaîne la plus “légitime” du point de vue du protocole qui est suivie. Il y a un sur-système humain incontrôlable qui décide de ce qui est la “bonne blockchain” ou pas (situation très similaire aux systèmes “démocratiques” qui peuvent se prendre un coup d’Etat).

En plus chaque nœud peut bien nous répondre ce qu’il veut : difficile de leur faire confiance, même celui qu’on héberge pourrait se retrouver isolé malgré lui (cas du light-node local par ailleurs).

J’ai beau y penser, pour moi le problème est insoluble. On ne peut qu’approcher une certaine confiance dans l’état du réseau, pas plus.

Partant de là, je me dis qu’au mieux un wallet ne peut que définir une “échelle de confiance” dans le réseau à mesure que celui-ci est scanné et que l’on constate que “tous les nœuds sont d’accord” (si ce n’est pas le cas, gros warning dans l’application). Mais en soi, pour une confiance la plus élevée, il faut être au courant de ce qui se passe au niveau humain et suivre l’actualité.

Donc je me dis qu’il y a deux approches :

  1. mode “confiance en un tiers” : un seul nœud (+ ses API tierces genre indexeur) que l’on peut seulement monitorer sur ses données blockchain pour établir une métrique de confiance (heure, participation des smiths, etc) : en cas de suspicion, proposer la solution 2 à l’utilisateur
  2. mode “confiance dans la vue globale” : tout scanner et être fortement connecté pour observer le réseau, appliquer en plus les règles du “confiance en tiers” sus-citées sur chaque “fork” observable

Sur un petit réseau comme la Ğ1 sur Duniter v2 je me dis que la solution 1 est tout à fait acceptable et permet d’être le plus rapide.

2 Likes

Pour ta première approche, je reformule pour être sûr de bien comprendre : il s’agit de ne pas scanner quoi que ce soit et de se connecter directement à un nœud dit « de confiance » inscrit en dur, choisi par le développeur ? Genre g1.duniter.org par exemple ?

Mais tu sembles spécifier ton fallback uniquement sous le critère de la suspicion (que j’ai un peu du mal à déterminer là comme ça).
C’est probablement parce que c’est trop évident que tu ne le précises pas, mais le critère de fallback numéro un est la non-disponibilité du nœud principal, ou son mauvais fonctionnement, qui est le cas qui pourra arriver le plus souvent, au-delà d’une attaque ou d’un fork isolé.

Pour le reste on retombe sur le théorème de CAP si cher à notre Fred national. Donc oui, sachant ça, on est bien d’accord qu’il n’y a pas de solution absolue, simplement un best as we can.

Je crois qu’on est globalement sur la même approche (de toute façon je n’en vois pas beaucoup d’autres possibles), simplement je choisis de systématiser le scan réseau, mais en arrière-plan. C’est-à-dire que l’app se connecte très rapidement à un nœud bootstrap ou mis en cache, mais en arrière-plan un scan se fait pour peupler le cache Network. Si un meilleur nœud est trouvé (fork majoritaire), alors l’app switch simplement de endpoint (et doit relancer le scan de Squid du coup, toujours en arrière-plan, pour être sûre de toujours être sur une paire Duniter/Squid cohérente).

Tout mon système de différentes couches est un peu compliqué (et pourrait probablement être simplifié/clarifié) mais est simplement là pour garantir le meilleur compromis possible entre rapidité de connexion et confiance du réseau.


Par contre, en te lisant j’ai l’impression que tu comptes afficher à l’utilisateur un choix à faire en cas d’incertitude ?
Je mets un gros warning là-dessus : il faut oublier l’idée de proposer à l’utilisateur de choisir quoi que ce soit, il n’en saura rien. Il ne faut absolument pas reproduire ce que fait Cesium v1 avec ses pop-ups de demande de confirmation de fallback sur un autre nœud en cascade, c’est un véritable enfer qui a été grandement critiqué par beaucoup de gens — je pense que tous les utilisateurs passant par là seront d’accord là-dessus.

Je pense qu’il faut rendre l’intégralité du flux totalement transparente, en arrière-plan, juste une petite notification qui indique en gros si le réseau est en ligne ou hors ligne, ou s’il y a un problème de réseau.
Laisser la possibilité aux utilisateurs avancés de choisir eux-mêmes le nœud, mais dans un sous-menu un peu planqué, et ne pas se focaliser sur ce flux du tout.


Il faudra songer à un système de backlist si un noeud connu est corrompu.

2 Likes

Oui c’est ça. La vérification que “tout va bien” se fait alors au fil de l’eau par rapport au contenu de la blockchain (ou bien sûr en cas d’indisponibilité du nœud) : par exemple on peut voir que l’heure n’avance pas, que les validateurs ne sont plus du tout les mêmes depuis la dernière fois, que l’on a une forte proportion de blocs secondaires, etc. Et dans le cas où ça va mal (ou simplement un doute) il faut effectivement aller rechercher un autre nœud.

Mais effectivement je suppose qu’on a toutes les raisons de vouloir effectuer régulièrement un scan réseau en parallèle ne serait-ce que pour basculer si le nœud courant devient problématique. Et une fois que ce mécanisme est déjà présent, ça devient très facile de juste se reposer dessus.

Je vais probablement partir là-dessus et m’éviter le suivi du fil de l’eau.

Je n’étais pas encore rendu jusque-là dans ma réflexion, c’est noté :slight_smile:

Oui ça m’a l’air d’être le plus simple, surtout au début où le réseau sera tout petit. Va pour cette approche :+1:

3 Likes

Pour info, j’ai dû faire aussi un scan pour g1companion. Je découvre juste les peerings du endpoint choisis.
J’ai une fonction fetchPeerings dans g1-papi, mais je scan si les endpoints sont bons dans g1companion ici.

Et dans ce composant Vue, j’ai du code pour mesurer le temps de réponse.

Si on laisse la souris un instant, ça donne ça :

Testable ici : Ğ1 Companion dans les réseaux.

Il faudrait que je rassemble tout ça dans g1-papi : les fonctions dans le composants et dans usePapi.ts …

2 Likes

D’ailleurs, je trouve ça extrêmement regrettable qu’aucun effort n’ait été fait pour que les devs de CS2 contribuent à une lib commune comme g1-papi. Toujours le même paradigme de chacun qui fait son truc dans son coin. C’est triste.

Ce genre de fonctionnalité n’aurait rien à faire côté wallet, mais côté lib, à mutualiser, pour unir nos forces sur ces éléments fondamentaux.
Bref. Je me demande parfois pourquoi je me suis embêté à faire Durt et Durt2.
Ah bah si, je sais.

4 Likes

Oui ! Il faut faire des libs communes.
Ce que tu as fait avec Durt2 à permis Ginkgo. Génial !
Ça m’aurais bien aidé d’avoir une lib comme ça pour du js. Je passe plus de temps à faire g1-papi que g1companion au final…

3 Likes

Oui moi c’est pareil avec Durt, la majorité du temps est sur l’isolation en lib.
Après ya quand même pas mal de boulo d’UX et deboguage d’interface quand même aussi.

3 Likes