Light node smoldot: la solution idéale pour du vrai p2p (sans tiers de confiance)

smoldot est une ré-implémentation du client substrate, dont le développement a commencé très récemment, mais qui promet rien de moins que la possibilité d’avoir un light node embarqué dans le navigateur !!

Historique

J’avais entendu parler de ce projet de parity (l’entreprise qui développe substrate) il y a plusieurs mois à l’une des conférences de leur évènement sub0 2021: https://sub0.substrate.io/ (j’ai d’ailleurs 2 collègues de boulot qui sont intervenus dans 2 autres conférences), mais je ne l’avais encore jamais testé.

Lorsque @vit a relancé la question du p2p et du multi-nœud lors de notre réunion mensuelle, ça m’a rappelé ce projet et j’en ai parlé, car je pense que ce serait de très loin « the best solution ».

Test

Je me suis motivé à tester smoldot hier soir, j’ai eu 2 problèmes et donc ouvert 2 issues, et j’ai été agréablement surpris aujourd’hui de constater que l’un des développeurs de smoldot m’a déjà répondu et a déjà réalisé une PR qui corrige l’un des 2 problèmes (le plus bloquant, l’autre étant contournable).

J’ai testé sa PR ce soir et ça fonctionne, j’arrive à synchroniser un light node smoldot avec Duniter-v2s, à connnecter polkadotjs à mon light node smoldot, et même à soumettre des transactions, qui sont alors bien transmises à Duniter-v2s et inscrites en blockchain.

Toutefois, ça ne fonctionne que si je lance smoldot pendant la 1er epoch, si je lance smoldot plus tard, les transactions soumises ne sont jamais inscrites en blockchain.

Il faut savoir que smoldot est un projet récent, et pas encore utilisé en production, mais les développeurs avancent très vite et il est déjà quasiment pleinement fonctionnel, j’ai l’impression qu’il manque surtout de la stabilisation.

Je suis certain que smoldot (du moins la partie light node, la seule qui m’intéresse) sera stable d’ici que l’on migre la Ğ1, j’aimerais donc que nous l’utilisions, ce qui à de nombreuses implications, principalement positives mais pas que.

substrate-connect

Actuellement en tout cas, le développement de smoldot est principalement orienté pour répondre aux besoins de substrate-connect, une extension web qui permet d’avoir un light node smoldot embarqué dans son navigateur.

Attention, substrate-connect ne peut pas fonctionner avec Duniter-v2s en l’état, il faudrait y ajouter nos blockchains avec nos chain spec lorsqu’elles seront lancées, on pourrait peut-être le faire, mais je pense que ce ne serait pas une bonne idée.

je pense qu’il est préférable qui nous développions notre propre extension Ğ1-connect, en se basant sur le code de substrate-connect ainsi que de polkadotls extension, je vais créer un sujet dédié la dessus pour m’expliquer et donner plus de détails.

smoldot js

Smoldot propose directement un paquet npm, qui contient du js qui wrappe smoldot compilé en wasm.

C’est ce paquet npm qui est utilisé par substrate-connect, et dans ma vision c’est ce paquet npm qu’on utiliserait dans notre extension g1-connect (enfin au début notre propre fork de ce paquet pour gérer les instabilités mais ce serait temporaire).

Pour mes tests, ne sachant pas encore développer une extension web, j’ai utilisé le paquet npm de smoldot enfin de mon fork), dans un mini serveur websocket en nodejs.

Contraintes pour la compatibilité entre Duniter-v2s et smoldot.

Si l’on souhaite pouvoir utiliser smoldot, cela implique quelques contraintes sur duniter-v2s :

  • On ne pourra pas créer nos propres externalités, sauf à les intégrer dans smoldot, mais ça peut être refusé, et je ne vais pas maintenir un fork de smoldot sur le long-terme, donc si jamais on à besoin d’externalités supplémentaires il faudra expliquer aux développeurs de smoldot notre besoin et prier pour qu’ils acceptent de l’adresser, ou qu’il nous suggère une autre solution sans externalité custom.

  • On pourra développer des méthodes RPC custom, mais elles ne seront pas disponibles via l’API RPC de smoldot, ce qui n’est pas forcément gênant selon le besoin et le cas d’usage, mais il faut garder cette limitation à l’esprit.

  • On ne pourra pas modifier la partie réseau de notre mécanisme de consensus, en effet la partie réseau est gérée par le Client et non par le runtime, or smoldot ne gère que le consensus BABE/GRANDPA pour le moment (Je simplifie, ils gèrent aussi AURA mais ce n’est pas utilisable en prod pour une blockchain primaire comme la nôtre).

  • Et peut-être d’autres limitations que je n’ai pas encore réalisé.

Je pense que ça vaut le coup malgré ces limitations, qui ne me semble pas bloquantes dans la vision que j’ai pour le moment.

Je pense que le plus important sera de maintenir une bonne communication avec les développeurs de smoldot, et de leur exposer sincèrement nos besoins. s’ils comprennent nos besoins je pense qu’ils accepteront à minima que l’on contribue à smoldot pour y ajouter ce dont on a besoin (voir peut -être de l’implémenter eux-mêmes).

Avantages

Un light node tel que smoldot permet à l’utilisateur final de ne pas avoir à faire confiance à un nœud extérieur installé sur un ordinateur auquel il n’a pas accès.

Le light node local va se charger de vérifier les merkel proof de toutes les données, et va lui-même gérer toute la couche p2p via libp2p.

Les clients/wallet et autres applications qui se baseront sur smoldot (via l’extension g1-connect pour les app web) n’auront pas besoin de gérer du multi-nœud ni de vérifier les données, smoldot le fera pour eux.

Dans les cas ou smoldot (où l’extension g1-connect) n’est pas installé, l’application pourra fallback dans un mode naïf ou elle fait confiance à un endpoint RPC d’un nœud distant, avec un message d’avertissement invitant à installer smoldot (où l’extension en contexte web) pour plus de sécurité.
L’application pourra également choisir de forcer l’installation de smoldot (où de l’extension en contexte web), où se contenter de bloquer uniquement certaines fonctionnalités critiques.

Si l’extension g1-connect gère aussi les clés privées (et donc les signatures de transaction) comme le fait l’extension polkadotjs, on pourrait de nouveau avoir un Cesium complet en site web, et ça ne poserait alors aucun problème de sécurité.

Bref, il faut vraiment qu’on prenne un temps pour parler de tout ça avec les dev des wallet, cc @kimamila @poka @vit et @Moul :slight_smile:

3 Likes

Si je comprends bien, et pour comparer avec ce que je suis en train de faire. Une transaction aujourd’hui c’est :
site web → g1-compagnon → noeud duniter → blockchain
avec smoldot, ce serait :
site web → g1-connect → blockchain

Ça parait génial !
Est-ce que c’est relié en permanence à la couche p2p ? Il ne faudrait pas que l’extension gère ou génère des tonnes de connexion juste pour faire une transaction de temps en temps.
Et pour les apps natives ou en Flutter ou autre ? Il faudrait aussi qu’elles embarquent smoldot ou elles ne pourront se connecter seulement qu’aux noeuds ?

1 Like

C’est à peu près ça oui :slight_smile:

Idéalement ce serait configurable dans le menu de l’extension, on doit pouvoir décider si smoldot est lancé au démarrage du navigateur ou non, et pouvoir le mettre en “pause” via un simple bouton bien visible dans l’UI, mais ça dépendrait des choix de ceux qui développeraient l’extension g1-connect, pas de smoldot :slight_smile:

EDIT: et évidemment il ne faudrait pas employer le terme “smoldot” dans l’UI c’est un terme technique, il faut réfléchir à quels termes employer et même idéalement faire d’abord l’UX dans un outil comme figma (j’ai vu d’ailleurs que les dev de substrate-connect utilisent figma).

Smoldot c’est du pur Rust, or je sais binder du rust avec flutter, donc oui il est tout à fait possible d’embarquer smoldot dans une app fluter :slight_smile:

1 Like

Avec ou sans smoldot, je penses qu’il faut d’abord se concentrer sur des clients qui se connecteront a l’API RPC, et donc faire eux même un ne lecture du réseau.
En effet, beaucoup de choses sont encore à évaluer avant de se prononcer sur smoldot. Notamment, les performances sur un téléphone, et le gain réel pour un simple cas d’utilisation (CU) : sortir son téléphone pour faire un paiement rapide. C’est le gros enjeu aujourd’hui que nous avons a solutionner pour les utilisateurs finaux, avec cette v2 de Duniter. Ils se fichent pas mal d’avoir un mini-noeud.

Dans ce genre de CU, passer par l’API de noeud connus ou pre-configurés me paraît plus optimale, d’autant que la notion UTX n’oblige plus a une synchro.

Voilà pour mon avis : bien mais pas prioritaire en ce qui concerne les travaux de migration

1 Like

Smoldot expose la même API RPC que Duniter-v2s, donc dans tout les cas vous devez effectivement vous concentrer sur l’usag ede l’API RPC :slight_smile:

Ça par contre je pense que c’est une erreur de design issue des habitudes de Duniter v1.

Gérer correctement, de manière fiable et optimisée, la découverte d’un réseau et la connexion p2p à celui-ci, c’est quelque chose de très complexe que l’on fait mal et qui est loin de notre coeur de métier qu’est la monnaie libre.
L’une des raisons pour migrer sur substrate est justement d’arrêter de réinventer la roue en moins bien, et d’utiliser ce que d’autres font mieux que nous, pour nous concentrer sur les spécificités de la monnaie libre :wink:

Si tu veux faire du p2p, il faut utiliser l’api libp2p de substrate, elle est faite pour ça, mais smoldot le fait déjà de la manière la plus optimisée et secure possible, donc tu vas juste perdre ton temps à recoder smoldot en moins bien.

je pense que ce serait tout de même très rapide avec smoldot, après ou forcément un client naïf sera toujours plus rapide qu’un client p2p, c’est le prix à payer pour ne pas dépendre d’une tierce partie.
Merci de rappeler que la centralisation c’est plus rapide, mais on savait déjà :wink:

Et quel rapport avec la choucroute ? Tu sais très bien que Duniter-v2s permet déjà un paiement beaucoup plus rapide, mais qu’on ne peut pas migrer la Ğ1 comme ça, ça va prendre du temps.
Cet enjeu là est déjà réglé techniquement, alors qu’il y a plein d’autres enjeux à discuter.

Ce n’est pas un argument, ce n’ait pas parce qu’ils n’ont pas conscience des risques liés à la centralisation et à l’usage des clients naïfs que l’on ne doit rien faire pour les protéger.

Ça me semble prioritaire dans le cadre de nos choix d’architecture pour notre nouvel écosystème technique, car ça rend caduque et inutile toute implémentation multi-nœud custom qui sera forcément beaucoup moins bien faite et moins sécurisée (contacter plusieurs nœuds n’est pas aussi robuste que de vérifier soi-même les merkel proof).

Pour moi la priorité actuelle c’est de réfléchir à l’architecture de notre nouvel éco-système technique à construire, c’est pour cela que j’étudie et teste plein de choses différentes en ce moment.

Ben justement, cela reste à démontrer. Avant tout choix d’architecture qui incluerait smoldot il faut valider ce point. Si une synchro est fait entre deux lancement de l’APP sur téléphone, alors mon CU “paiement rapide” tombe à l’eau. Ca te parait peut-etre évident, mais je préfère le préciser, pour éviter trop d’optimisme (que ton titre peut laisser entendre).

non, je parle d’un mode mixte, et évidemment pas comparable avec de la centralisation. Il s’agit de faire dialoguer le client avec un ou plusieurs nœuds “UP et synchro”, pour décharger le client d’opérations gourmandes.

Il y 2 problématiques, pour ce CU :

  • le lancement de l’App, avec tout ce qu’il faut pour que l’écran de paiement soit opérationnel (c’est à dire au moins le solde à jour, de un ou plusieurs comptes)
  • Puis l’exécution du paiement, une fois qu’il a été envoyé.
    la rapidité de SubStrate n’en adresse qu’un seul : le dernier point est réglé, je suis d’accord, mais le 1er reste entier…

Cela te parait évident et simple ? Pas moi.
Faire un scan complet du réseau prend du temps. Faire une synchro prend du temps. etc.
La rapidité, c’est souvent une histoire de “mise en cache”, et de compromis avec l’indépendance totale (ici, la décentralisation totale).

Peu importe l’algo (libp2p ou autre) : avant tout il y a forcément un envoi de requête à faire. La question est donc : vers quel nœud de départ ?
On parle d’utiliser une API graphQL qui indexe la blockchain, qui serait sur accessible certain noeuds. Reste a savoir lequels ? Smoldot ne résoudra as cela. Le merkle Tree non plus : le noeud SUbstrate peut etre à jour, et l’indexeur dans les choux !

Et puis, pourquoi s’empêcher d’utiliser un nœud de confiance (par exemple déjà accéder récemment) pour éviter toute synchro ? Je ne vois pas bien ce qui justifierait de NE PAS s’appuyer sur des nœuds connus, si l’utilisateur y gagne en rapidité, et que le risque de centralisation est quasi nul, si un basculement automatique est prévu.

Est-ce que ces points te paraissent inutiles ? évident ? sans intérêt ?
Pas moi.

Au sujet des limitations et contraintes que Duniter v2s devrait assumer pour être compatible avec smoldot, je trouve cela dommage après s’être affranchi des contraintes pour être compatible avec les rasperrypi.

Vouloir absolument disposer d’un nœud sur toute plateforme est une philosophie qui peut s’entendre, mais qui exige de nombreuses contraintes. Pour le web, le tout js dans le navigateur est en train de ralentir et des retours aux calculs serveur en hybrid se font ( svelte, htmx ) pour profiter du meilleur des deux mondes.

En tout cas je réfléchis au sujet et même si on restreint les capacités de duniter v2s pour tourner partout avec smoldot, en cas de problème, il faudra toujours une solution de repli « gracefully » de scan réseau moins sécure et plus lent. Avec un bémol, car n’ayant plus la piscine, on aura bien moins de données aberrantes dans les clients.

L’autre argument que je voix de ne pas se contraindre avec smoldot, c’est que les clients/wallets devront toujours être plus complets et performants et ne pourront l’être qu’avec l’aide d’indexeur puissants. Ces serveurs ne seront pas légions et devraient être maintenus par les différents collectifs ML disposant d’informaticiens qui garantiront la fiabilité et la sécurité de ces serveurs. On sera donc obligés d’avoir une pseudo centralisation des points d’entrée pour permettre aux clients/wallets d’être complets.

Il faut qu’on en discute tous en visio pour bien se comprendre et partager nos visions et nos doutes.

Ce que je constate autour de moi, c’est que aujourd’hui les smartphones sont connectés en permanence.
Je pense que l’idéal, se serait que chaque smartphone est un light client qui tourne en fond en permanence, ça consomme beaucoup moins que de nombreuses autres app qui tournent déjà en permanence en fond sans que l’utilisateur s’en rende compte.

Smoldot fourni des metrics, lors de mes tests le constate un usage ram de seulement 36 Mo, et un usage réseau moyen de l’ordre de 150Ko/s , c’est dérisoire.

Et je n’ai jamais dit que les light node devait être obligatoire, mais privilégiées lorsque c’est possible. l’API RPC exposée étant la même que celle d’un full node, les développeurs des wallet peuvent facilement de fall back en mode full node distant si besoin.

Pour ton cas de paiement rapide par exemple, lorsque utilisateur ouvre l’app, tu peux choisir selon le cas:

  1. l’app tournait déjà en fond avec son light node: tu utilises le light node
  2. l’app ne tournait pas en fond: tu te connectes à un full node au hasard parmi les endpoint connus

Je pense que tu es inquiet, car tu ne connais pas le fonctionnement des light node, ils ne font pas un scan complet du réseau, ils n’en ont pas besoin, ce n’est pas ud multi-noeud, c’est beaucoup plus robuste que ça:

Le light node par d’un checkpoint (hash d’un block et set des autorités), qui peut être le block genesis, où un block plus récent inscrit en dur dans le code par les développeurs, ça peut être fait par exemple tout les 6 mois.

Le light node va alors récupérer tout les headers depuis ce checkpoint et recalculer les hash pour s’assurer que toutes les preuves de changement d’état sons valides.
cette tache peut (et doit de préférence), être exécuté en tache de fond sur la machine de l’utilisateur final, ça ne demande que de récupérer quelques centaines d’octets toutes les 6 secondes.

Lorsque le light node a besoin d’une donnée dans le storage, il lui suffit de requeter un seul full node, vu qu’il a les merkel root de chaque bloc, il est impossible de uli mentir.

Avec un light node, il est donc possible d’avoir la rapidité ET la décentralisation réelle, le seul compromis n’est pas la lenteur, mais le fait de laisser de light node tourner en tache de fond.

tu penses bien que les développeurs de blockchain ont déja réfléchi y ce problème depuis des années, c’est pour cela que les light node ont été inventés, ils n’ont pas besoin de truster les bootnodes.

La différence c’est que les données d’un indexeur sont beaucoup moins critiques, c’est pratique pour afficher des stat où afficher l’historique d’un compte, mais il faut garder en tête qu’un indexeur c’est centralisé, et qu’il ne faut donc pas se baser sur les informations qu’il donne pour prendre des décisions importantes, il faut vérifier sur un full node archive la donnée au numéro de bloc concerné.

Je n’ai jamais dit qu’il fallait s’en empêcher, reste à définir ce qu’est un nœud de confiance, ce n’est pas parce qu’un full node distant a été utilisé récemment qu’il est de confiance.

  1. l’utilisateur ni gagnera pas forcément en rapidité, car le full node contacté peut être débordé. S’il a déjà un light node en tache de fond, il sera plus rapide d’utiliser le light node.
  2. Comment détermine tu que le risque de centralisation est quasi nul ? Et qu’entend tu par “nœuds connus” ?

Ce que je n’ai pas précisé, c’est qu’un light node local permet également plus de fonctionnalités, qu’un full node ne peut pas exposer publiquement pour des raisons de sécurité.

Comme le light node récupère le runtime onchain localement, il peut exécuter n’importe-quelle runtime API, ce qui inclus le dry run d’un extrinsic.

Ça permet à l’application de tester l’exécution de l’extrinsic avant de le soumettre, ce qui permet d’éviter d’inscrire en blockchain un extrinsic qui échoue et qui fait consommer des frais ou quota pour rien.

Et plus généralement, c’est préférable de déplacer les traitements cotés utilisateur, plutôt que coté serveur, ça permet une meilleure montée en charge, et une meilleure décentralisation.

Je pense que vous ne vous rendez pas compte car dans la Ğ1 on a pas de charge, 5000 utilisateurs dont beaucoup sont tors peu actif, peut être l’équivalent de 500 utilisateurs quotidiens en termes de charge.

On a dimensionné les paramètre de la toile de confiance Ğ1 pour 1 million d’utilisateurs, ce qui signifie une charge de l’ordre de 10.000 fois supérieure à aujourd’hui.

Moi je vois ce que c’est tous les jours au boulot que de gérer une crypto avec forte charge, et c’est l’enfer pour les fulls node qui exposent une API RPC publique.
Ça induit de fortes contraintes techniques sur la capacité à proposer des fulls node RPC publics, peu d’acteurs peuvent gérer la charge, ce qui induit plus de centralisation mais également plus de fragilité et cas de panne chez l’un des acteurs.

Si une grande partie des utilisateurs avait un light node local, les fulls node RPC publics seraient beaucoup moins surchargés, et il en faudrait peu, ce qui réduit le besoin en datacenter.

On parle souvent de lowtech et de soutenabilité, c’est facile sous faible charge, mais sous forte charge c’est impossible sans light nodes.


Les contraintes que pose la compatibilité avec smoldot sons infiniment plus simple à satisfaire que les contraintes que pose le support des rpi.

Duniter-v2s ne restera livré que pour du linux x86_64.
Seul smoldot à besoin d’être compatible sur toutes les plateformes des utilisateurs, et les développeurs de smoldot ont déjà fait en sorte que ce soit le cas. Ça ne nous donne donc pas plus de travail de notre côté.

Hum je pense que tu n’as pas compris, duniter-v2s ne va pas tourner partout, ça reste un logiciel différent qui ne tourne que sous linux x86_64.
Un full node doit faire beaucoup de choses qu’un light node n’a pas besoin de faire, c’est donc 2 logiciels différents, on doit juste s’assurer de leur compatibilité.

Et grâce au système ultra générique de runtime spécifique à substrate, on a pas besoin de faire des développements spécifiques coté light node, le light node smoldot de base fonctionne déjà avec notre blockchain.

Si on adopte le système de stockage libre que je propose, alors on peut vérifier toutes les données fournies par l’indexeur, donc pas besoin de lui faire confiance, et si on a un light node pour vérifier la présence des hash en blockchain, on n’a pas besoin de faire confiance non-plus au full nodes.

Ça fait déjà pas mal ! Pour une connexion fibrée OK, mais déjà en ADSL c’est beaucoup, et sur un téléphone c’est énorme, ne serait-ce que pour la batterie.

Est-ce que le light node supporte bien d’être lancé peu souvent, et se synchronise rapidement ? En général je n’allume ma 4G que quand j’en ai besoin (pour la vie privée et la conso), par exemple juste avant de payer dans un ğmarché.

1 Like

Dans mes tests je boostrappais une nouvelle monnaie, donc il devait récupérer plus d’info, il faut que je teste sur plus longue durée pour voir si l’usage réseau diminue ou pas.

Oui car smoldot est stateless, il expose une méthode permettant à son wrapper (l’extension web ou le binaire desktop) de récupérer l’intégralité de sa DB, et une autre méthode pour l’injectée au démarrage.

Donc on peut sans problème au niveau du wrapper implémenter une fonction “pause” qui:

  1. Get la db de smoldot et la sauvegarde.
  2. Demande à somldot de s’arreter.

Au prochain démarrage il suffit de lui fournir en entrée la db sauvegardée, il va la load dans sa ram puis va ce synchro à la blockchain, comme sa db contient les finalized head, il va repartir uniquement du dernier bloc finalisé connu, donc il ne va synchro que les header qui lui manque.

Après évidemment, plus il est arrêté longtemps, plus le redémarrage sera long, mais en deçà de quelques jours ça ne se sentira pas.

1 Like

De mon expérience sur les App mobile, je n’irais pas dans cette voie, à cause de la consommation et latence que ca risque d’entrainer.
Sur mobile, chaque traitement compte, et la conso réseau aussi. Après chacun est libre d’avancer comme il le sens…

je débuterai d’avantage vers une approche classique, de consommation de micro-services distants.

On le sait tous, et les dev de parity le savent aussi, leur but est bien de faire un light node qui soit également adapté aux contraintes des mobiles.
Je comprends que tu souhaites vérifier ce qu’il en est par l’expérience, je le souhaite moi aussi :slight_smile:

Théoriquement en tout cas, il y aura moins de latence qu’avec une stratégie multi-nœud “classique” comme on faisait jusque la.

Je raccroche les wagons : ça me paraît excellent cet outil smoldot ! C’est jamais qu’un proxy optionnel pour les applications clientes, qui permet une sécurité supplémentaire en plus de fournir une API pour dialoguer les nœuds du réseau.

Je vais creuser, car pour le lancement de le ĞDev 600 j’aimerais me créer un petit client sans prétentions type “Dashboard” qui permet de contrôler la cohérence de la ĞDev (scrutation du Storage).

2 Likes

Dans la terminologie Substrate, ça s’appelle un Provider. La dépendance NPM @polkadot/rpc-provider fournit une interface vers les 3 providers disponibles : HTTP (par défaut le port 9933), WS (par défaut le port 9944) et enfin SC (pour Substrate Connect – le wrapper de smoldot).

Des quelques essais en local que j’ai pu faire avec la ĞDev 600, clairement smoldot induit un coût initial très élevé à son lancement pour la ĞDev : il faut qu’il mange le Genesis et ça prend plusieurs longues secondes. Peut-être parce que le Genesis est lourd (16Mo de raw specs – les comptes Ğ1 existants).

Bref smoltdot est fait pour tourner en tâche de fond.

Mais rien n’empêche de changer à la volée de provider, et de garder smoldot en option.

edit : et en passant, d’après les tests que j’ai fait, je ne vois pas bien en quoi nous aurions besoin de développer g1-connect :

La remarque d’Eloïs était peut-être valable début 2022, aujourd’hui je n’ai pas eu le moindre problème pour me connecter à un nœud Duniter V2S pour obtenir des informations du Storage sur plusieurs pallets, dont celles propres à Duniter. Ou alors je passe à côté du sujet.

edit 2 : à mieux y regarder, il y a effectivement un problème quand je tente de brancher Smoldot sur les chain-specs de la ĞDev. Je ne vais pas creuser davantage, ça me semble être un sujet secondaire pour l’instant vu que l’API RPC suffit pour démarrer.

2 Likes