Pourquoi les blockchains testnet sont importantes ? Quels sont leurs rôles ?

Dans le cadre de l’évolution d’Ethereum, plusieurs jalons importants sont définis. Chaque évolution ayant un impact plus ou moins important sur le système, il est primordial de s’assurer que l’impact d’une évolution sera bien celui souhaité.

Comme dans tout logiciel, lorsque l’on fait une modification, cela peut avoir des conséquences inattendues. Quand il s’agit d’une évolution d’un jeu, cela a finalement peu d’importance, lorsqu’il s’agit d’une blockchain cela prend une toute autre dimension : la moindre conséquence inattendue, le moindre bug ou la moindre faille dans le système peut amener à la ruine de centaines d’individus voir même du système. On se souviendra notamment des failles affectant certains smart contracts comme ceux de The DAO ou encore le wallet multi-signatures de Parity.

Afin d’éviter au maximum ces problèmes, les développeurs ont créés des chaînes de test que l’on appelle testnet. Ces chaînes implémentent les modifications avant la chaîne principale (mainnet) afin de vérifier que le comportement réel est bien celui attendu.

Le 13 octobre dernier, un hard fork nommé Constantinople a eu lieu sur la blockchain testnet nommée Ropsten (au bloc 4 230 000). Cependant ce fork ne s’est pas passé comme prévu, laissant coexister à minima trois chaînes dans le même temps. C’est ce fork qui m’a amené à écrire cet article.

Quel est le comportement attendu lorsqu’un fork se passe bien ?

  1. Les utilisateurs du réseau mettent à jour leurs nœuds à une version supportant les évolutions amenées par le fork
  2. Le fork a lieu à un bloc prédéfini dans le code des nœuds. Lors de ce fork les nœuds commencent à utiliser les nouvelles règles et les transactions utilisant ces règles sont donc acceptées. Lorsque le fork a lieu, il crée alors une nouvelle chaîne laissant l’ancienne à l’abandon.
  3. Les utilisateurs n’ayant alors pas mis à jour leurs nœuds continuent sur l’ancienne chaîne jusqu’à l’abandon total de cette chaîne lorsque plus aucun mineur ne l’utilise, ne créant ainsi plus aucun bloc. Ces utilisateurs finissent alors par mettre à jour leurs noeuds et se retrouvent donc sur la bonne chaine.
Tweet de Afri Schoedon (@5chdn), développeur du client Parity, au moment du problème de consensus

Mais alors pourquoi ce hard fork ne s’est pas passé comme prévu ? Plusieurs raisons ont mené à cet échec.

  1. Les deux clients Ethereum principaux (parity et go-ethereum) ont été mis à jour tardivement (moins d’une semaine) par rapport à la date prévue pour le fork, ne laissant ainsi pas le temps aux possesseurs de noeuds de faire les mises à jour nécessaires.
  2. Un problème de consensus a eu lieu entre les deux clients principaux suite à un bug dans le code de parity créant ainsi deux chaînes distinctes après le fork.
  3. Aucun mineur ne possédait un client à jour sur la chaîne forkée afin de miner des blocs. Il a en effet fallu attendre plus de deux heures avant de voir apparaître un bloc sur cette chaîne. Le fork ayant eu lieu un week end il était aussi plus difficile de contacter les personnes compétentes pour faire les mises à jours des nœuds nécessaires

Vous pouvez imaginer l’impact qu’un tel scénario aurait eu sur le réseau principal.

Cet échec de fork a créé de vives réactions. Certains utilisateurs se sont plaint de la non stabilité de ce testnet. Il semble en effet que la définition d’une testnet n’est pas la même pour tout le monde, cela soulève une question !

Qu’est ce qu’une blockchain de test ? Est-ce un environnement de pré-production qui se doit d’être stable comme le serait le mainnet ou est-ce vraiment un bac à sable où l’on peut effectuer librement des tests quitte à éventuellement “casser” ou rendre inutilisable la chaîne ? La réponse est entre les deux, il s’agit vraisemblablement d’un réseau de pré-production servant de bac à sable. Etant donné ce statut particulier il peut disparaître à tout moment. Par définition il est important de ne pas mettre d’application critique sur cette chaîne.

Suite à ce fork nous avons pu effectuer un constat : la communication avec la communauté par rapport à ce fork n’a pas été claire. Il s’agit en effet d’un réseau de testnet, ce fork ayant donc moins d’impact que s’il avait eu lieu sur le mainnet mais ne serait-il pas judicieux d’avoir un lieu de discussion privilégié pour que les acteurs principaux puissent se rassembler lors de ces problèmes majeurs ? Il existe à ce jour un channel gitter joignable par le grand public mais il apparaît que ce n’est pas le meilleur moyen de discussion pour les développeurs dans ce cas précis. Ne serait-il pas important lors d’un événement comme celui-ci de le traiter de la même façon que s’il avait lieu sur le réseau principal ?

A l’heure actuelle d’autres questions restent en suspens:

  1. Faut-il définir une stratégie de hard fork ? On peut par exemple éviter les hard fork le week-end car cela semble être une mauvaise période. Il est cependant difficile de définir précisément une date car un hard fork est effectué à un bloc précis, la puissance de hachage du réseau influence donc le moment du fork. Il est certainement prudent de planifier les hard forks en milieu de semaine afin que le fork se passe en semaine sauf grand changement de la puissance de hachage.
  2. Quel temps minimum est-il nécessaire d’attendre avec un réseau testnet fonctionnel après un hard fork avant de passer ce même hard fork sur le réseau mainnet ?

Cependant ce hard fork a été l’occasion de vérifier le fonctionnement de certaines fonctionnalités des nœuds Ethereum.

Nous avons pu par exemple voir qu’une fois sur un mauvais fork pendant trop longtemps, les nœuds, même si ils sont mis à jour avec une version compatible avec le fork, ne reviennent pas sur la bonne chaine d’eux-même. Ces nœuds ont plutôt tendance à soulever des erreurs mais dans la mesure où chaîne sur laquelle ils sont soit trop loin du bloc de fork les empêche de réorganiser leur chaîne. Il serait donc ici intéressant de re-développer cette partie des noeuds.

Nous avons aussi pu voir qu’il n’est pas facile dans ce cas de synchroniser un noeud depuis zéro lorsqu’il existe beaucoup d’autres noeuds qui sont sur une mauvaise chaîne. Le noeud en cours de synchronisation a alors tendance à partir sur une de ces mauvaises chaînes et à y rester. Le client go-ethereum permet dans ces cas d’utiliser la fonction debug_setHead pour revenir à un bloc antérieur et retenter une synchronisation correcte sans recommencer. Cependant, Parity ne propose aucune fonction de ce type, obligeant alors une reprise à zéro de la synchronisation.

Rendez-vous courant janvier au plus tôt pour le hard fork sur le mainnet.