Le sharding, la solution d'Ethereum pour passer à l'échelle
La scalabilité, ou la capacité à passer à l'échelle, est l'un des enjeux les plus importants quand on parle de protocoles crypto-économiques tels que Bitcoin et Ethereum. En effet, pour rester pertinents ces protocoles ne peuvent pas permettre que leurs réseaux respectifs subissent une charge transactionnelle trop grande et deviennent, ce faisant, trop centralisés. La question que l'on doit se poser quand on parle de passage à l'échelle est donc : Comment le réseau peut-il augmenter sa capacité de traitement de manière sécurisée tout en conservant une décentralisation suffisante ?
Pour le moment, les réseaux de Bitcoin et d'Ethereum ont du mal à suivre la demande et peuvent subir des congestions caractérisées par des temps de confirmation plus longs et des frais de transactions plus élevés. Pour Ethereum, l'épisode le plus emblématique de ce problème est sans doute celui des Cryptokitties, l'application décentralisée permettant de collectionner et d'échanger des chats virtuels, qui a monopolisé le réseau en décembre 2017.
Le sharding, ou partitionnement est la solution envisagée par les développeurs d'Ethereum pour remédier au problème. Cette technique n'est pas nouvelle et est utilisée pour les bases de données : il s'agit de partionner les données de manière horizontale afin de répartir le stockage en mémoire. Pour Ethereum, dont l'ambition est d'être un ordinateur mondial, la sharding consisterait à paralléliser à la fois le stockage et l'exécution des contrats autonomes sans perdre en sécurité.
Avec Casper et eWASM, ce partitionnement constitue l’un des principaux éléments de Ethereum 2.0, l’évolution d’Ethereum vers plus d’efficacité et de scalabilité qui devrait voir le jour avec la mise à niveau Serenity.
Quel est le problème ?
Le systèmes crypto-économiques reposant sur des chaînes de blocs sont, par conception, des systèmes assez inefficients. Pour fonctionner sans autorité centrale, pour résister aux attaques extérieures, ils se doivent d'être suffisamment distribués.
C'est pour cela qu'ils sont soumis à un principe ce qu'on appelle le « trilemme des chaînes de blocs » formalisé par Vitalik Buterin. Ce trilemme stipule qu'un système de chaîne de blocs ne peut posséder que 2 des 3 propriétés suivantes :
- La décentralisation : le système peut fonctionner dans le cas où chaque participant n'a accès qu'à une quantité donnée de ressources informatiques (comme un ordinateur portable ou un petit serveur virtuel).
- La scalabilité : le système peut traiter des transactions dans un ordre de grandeur strictement plus grand que ce que permettent les ressources possédées par un seul participant.
- La sécurité : le système est sécurisé contre un attaquant possédant moins de ressources que celles correspondant au niveau transactionnel du réseau.
Des solutions dites « naïves » ont été envisagées pour remédier au problème, sans pour autant le résoudre complètement :
- Séparer l'activité entre des chaînes différentes (« altcoins »). En répartissant les validateurs sur différents réseaux, cette solution fait baisser la sécurité globale du système.
- Augmenter la taille limite des blocs. Après un certain seuil (qu'il faudrait déterminer), cette solution diminue la décentralisation du réseau en augmentant le niveau de ressources informatiques nécessaires au maintien d'un nœud.
- Procéder à du minage combiné (merged mining) sur différentes chaînes. Pour Vitalik Buterin, il s'agit d'une forme déguisée d'augmentation de la taille limite des blocs qui fait baisser la décentralisation en imposant aux validateurs de gérer d'autres chaînes pour rester rentables.
D'autres solutions plus ingénieuses mais aussi plus complexes ont été imaginées. C'est notamment le cas des solutions dites « de seconde couche ». Pour Ethereum, il s'agit du réseau Raiden, qui est un réseau de canaux d'état et qui se base sur les mêmes principes que le réseau Lightning, et de Plasma, le système de chaînes latérales. Ces solutions ont leurs problèmes propres que l'on ne détaillera pas ici.
C'est dans ce contexte qu'intervient le partitionnement, qui constitue la solution privilégiée par les développeurs pour qu'Ethereum passe à l'échelle sans perte au niveau de sa décentralisation ou de sa sécurité.
En quoi consiste le partitionnement, ou sharding ?
Ethereum est un ordinateur mondial décentralisé dont l'état global est mis à jour par tous les nœuds du réseau. Cet état est changé en permanence par l'intermédiaire de transactions (aussi appelées opérations). La chaîne de blocs, l'historique qui liste toutes ces transactions depuis la création du système, permet aux nœuds du réseau de se synchroniser.
Ethereum est donc caractérisé par deux choses : son état et son historique. Dans Ethereum, l'état est la cartographie liant les adresses (0x...
) à leur solde, à leur nonce, ainsi qu'à leur code et leurs données s'il s'agit de contrats autonomes. L'état suffit pour déterminer si une transaction est valide ou non.
Aujourd'hui, l'état et l'historique pèsent respectivement 215 Go et 2.4 To. Beaucoup de nœuds du réseau se contentent de ne stocker que l'état du système (pruned mode). Seuls les nœuds dits « archiveurs » prennent la peine de conserver l'intégralité de la chaîne de blocs.
L'idée derrière le partitionnement, c'est d'éclater à la fois l'historique et l'état d'Ethereum en une multitude de fragments (shards) indépendants. Chacun de ces fragments est validé par une partie (variable) du réseau ce qui permet de paralléliser les opérations et de répartir la charge totale du système. Le nombre de fragments dépend du ratio entre les ressources informatiques minimales requises pour chaque participant et du nombre moyen de transactions effectuées sur le réseau.
D'une part, chaque fragment se comporte alors comme une chaîne à part entière : il possède son propre état local, a son propre historique, et emploie une partie du réseau être validé. D'autre part, l'ensemble des fragments doit se comporter de la même manière que le système global, ce qui rend l'application de l'idée assez difficile comme on le verra dans la partie suivante.
D'autres propositions ressemblant au partionnement proposé par les équipes de développement d'Ethereum existent. Zilliqa a notamment implémenté une forme de partitionnement qui répartit les tâches de calcul entre plusieurs sous-réseaux, mais conserve un état unique. De même, l'utilisation d'un arbre Merklix (aussi appelé arbre de Merkle-Patricia), présent sur la feuille de route de Bitcoin Cash, devra permettre à l'avenir de partitionner la validation des blocs.
Comment ça marche ?
Le partitionnement repose tout d'abord sur la création d'une chaîne principale appelée « chaîne balise » (beacon chain) qui permet de gérer la répartition des tâches dans Ethereum. Sur cette chaîne, les validateurs sont choisis au hasard pour avoir le droit de créer des blocs sur un fragment donné. De même, pour chaque fragment une centaine d'attestataires est choisie pour certifier la validité du bloc : pour que le bloc soit valide et que la récompense soit distribuée, au moins 67 d'entre eux doivent publier leur signature sur la chaîne balise. La chaîne balise a donc ici un rôle d'intermédiaire entre les fragments et le système global.
De plus, le partitionnement de la chaîne d'Ethereum nécessite un passage à la preuve d'enjeu. En particulier, il a besoin de l'algorithme de preuve d'enjeu actuellement en développement appelé Casper. Même si le sharding peut être utilisé dans un système à preuve de travail, deux raisons essentielles font que cet algorithme est préférable :
- Dans un modèle de preuve de travail, un fragment spécifique pourrait être plus facilement attaquable.
- Dans Casper qui impose de lister les validateurs ayant réalisé un dépôt de sécurité, il est bien plus facile de sélectionner ces validateurs pour les répartir entre les différents fragments.
Lors du fonctionnement du système, chaque groupe de transactions est assigné à un fragment spécifique. Un exemple grossier de répartition serait celui de 256 fragments se partageant les transactions en fonction de leur identifiant. De cette manière, toutes les transactions dont l'identifiant commence par 0x00
seraient traitées par le fragment 1, celles commençant par 0x01
iraient dans le fragment 2, etc.
Bien évidemment, une transaction traitée dans un fragment peut impacter un contrat se trouvant dans un autre fragment. Ainsi, le partitionnement nécessite un système de communication entre les fragments (cross-shard communication) servant à harmoniser l'état global d'Ethereum. Ce système de communication fait intervenir des reçus (receipts) qui sont des objets représentant l'effet d'une transaction qui ne sont pas stockées directement dans l'état, mais tout de même conservés à un autre endroit. Ces reçus sont déjà utilisés par Ethereum en tant que journaux d'évènements (logs).
Conclusion
Permettre aux chaînes de blocs de passer à l'échelle n'est pas une chose facile, mais le partitionnement semble en bonne voie d'améliorer grandement la scalabilité d'Ethereum. Selon Vitalik Buterin, il permettrait de multiplier la capacité transactionnelle d'Ethereum par 100 et, associé au réseau de chaînes latérales Plasma, par 10 000 !
Même si le développement du partitionnement avance (Prysmatic Labs a déjà créé un client fonctionnel), sa mise en place dans Ethereum ne risque pas de voir le jour avant 2020, voire 2021. Une mise à niveau pour créer la chaîne balise et implémenter Casper devra, de toute façon, précéder cette mise en place.