TL;DR

Cet article présente une implémentation pratique de la vie associative dans le contexte Covid-19. La technologie sous-jacente utilisée est une blockchain privée de type Ethereum dont les aspects réglementaires et sécuritaires sont discutés fonctionnellement et techniquement. L’objectif est de fournir une alternative digitale sûre pour la gestion des associations et plus spécifiquement des syndicats de copropriété.

Quelques éléments de contexte

Cet article est la suite Cas d’usage pratique des Smart Contract Ethereum - La communauté des Curieux et vise à montrer comment déployer et gérer une blockchain Ethereum. Avec comme cas d’application, le réseau Ethereum de test que nous allons utiliser pour la communauté des curieux.

Pour revenir au premier volet de cette série et comprendre comment utiliser cette application de blockchain comme un citoyen lambda, il faut choisir le chemin 1. du paragraphe suivant. Pour revenir au deuxième volet de cette série et comprendre comment les smart contrats fonctionnent et nous aider à gérer la communauté, il faut aller au volet 2 du paragraphe suivant.

La blockchain dont vous êtes le héros

A partir de maintenant, je vous propose trois chemins de technicité croissante selon ce que vous êtes venu chercher sur cet article.

  1. Je ne suis pas du tout un technicien et je veux faire partie de la copropriété de la communauté des Curieux. Suivez ce chemin
  2. J’ai des connaissances techniques et je souhaite les approfondir en comprenant comment cette copropriété est construite et les bases technologiques derrière. Suivez ce chemin
  3. J’ai de bonnes connaissances d’administration système et je veux contribuer au réseau qui est construit. Vous êtes sur le bon chemin, keep going

Resume

Points importants à noter

  1. N’ayant pas le droit de disposer d’unités de compte à l’étranger, et considérant que la monnaie d’Ethereum - l’éther - en est une, nous n’utiliserons pas la version mondiale publique d’Ethereum mais une version marocaine contrôlée par des marocains. A savoir moi comme initiateur et toute personne qui souhaite rejoindre le réseau par la suite
  2. La crypto-monnaie “marocaine” naturellement générée par la blockchain étant sujette à caution de la part des autorités réglementaires (CF Communiqué de l’AMMC de 2017), nous allons neutraliser sa valeur en générant une quantité très importante au tout début de manière artificielle. Ainsi, ce qui était un asset devient worthless et me semble un bon compromis entre l’adoption de la technologie et les contraintes réglementaires qui visent avant tout à nous protéger des acteurs peu scrupuleux.

Ces points sont également discutés dans les points importants du 1er article.

La génèse

Toute blockchain commence par un bloc initial, un seed sur lequel elle va construire ses blocs. Pour une blockchain Ethereum, il prend la forme d’un fichier genesis.json

{
 "config": {
   "chainId": 985459,
   "homesteadBlock": 0,
   "eip150Block": 0,
   "eip155Block": 0,
   "eip158Block": 0,
   "byzantiumBlock": 0,
   "constantinopleBlock": 0,
   "petersburgBlock": 0,
   "clique": {
     "period": 5,
     "epoch": 30000
   }
 },
 "difficulty": "1",
 "gasLimit": "8000000",
 "extradata": "0x0000000000000000000000000000000000000000000000000000000000000000F72eF0d377515c11056660be5D65A3B4070952540000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
 "alloc": {
   "Cd573CAfe4Ded7F71AC094F2b21C0cB42B592E8a": {
     "balance": "1000000000000000000000000000"
   },
   "F72eF0d377515c11056660be5D65A3B407095254": {
     "balance": "1000000000000000000000000000"
   },
   "485d493EB472E10469F14bADa83c33941c018A76": {
     "balance": "1000000000000000000000000000"
   }
 }
}

Les informations importantes à retenir sur ce fichier est qu’il nécessite de définir un id de blockchain afin que les différentes blockchains publiques ethereum (puisqu’elles communiquent le même langage) ne s’emmêlent pas les pinceaux et que des transactions sur un réseau soient rejouées sur un autre si une personne utilisait par exemple les mêmes clés de wallet.

Le deuxième point important est le consensus. Plusieurs types de consensus existent mais deux sont plutôt mainstream :

  • Le PoW (proof of work) : consistant à ouvrir le réseau à toute personne ayant de la puissance de calcul disponible, et à distribuer le travail à travers non pas une whitelist de noeuds validés mais à travers un algorithme difficile à exécuter
  • La PoA (proof of authority ou “clique”) : à savoir un réseau entièrement privé qui ne peut être rejoint que après un vote majoritaire des noeuds existants dans le réseau. Les miners deviennent des signers car le travail est remplacé par une confiance préalable hors protocole blockchain

D’autres types de consensus existent, notamment le PoS (proof of stake) qui promet une scalabilité importante du réseau sans algorithme énergivoire et qui vient d’être déployé en production dans Ethereum 2.

Notre blockchain devant être la plus privée et contrôlée possible, l’algorithme de Clique sera utilisé comme indiqué dans le fichier genesis.json.

Le deuxième point important est la clé alloc qui permet de pré-allouer une quantité d’ether à des adresses. A des fins de test, je m’en suis octroyé une quantité quasi infinie, que ce soit pour l’adresse de mon noeud miner 0xCd573CAfe4Ded7F71AC094F2b21C0cB42B592E8a, mon noeud exposé sur internet 0xF72eF0d377515c11056660be5D65A3B407095254 ou ma wallet MetaMask 0x485d493EB472E10469F14bADa83c33941c018A76.

Enfin, notons qu’une adresse figure dans extradata. C’est celle de la wallet qui signe les transactions de mon noeud au départ et définie par défaut pour bootstraper le réseau. Nous verrons par la suite comment ajouter d’autres miner/signer.

L’instanciation de mon noeud

Le fichier genesis.json en poche, nous pouvons instancier notre miner avec la commande suivante :

/usr/bin/geth init --datadir /home/ethereum/node/data /home/ethereum/node/genesis.json
# Noeud exposé sur interner (node)
/usr/bin/geth --datadir /home/ethereum/node/data --nodiscover --networkid 985459 --http --http.addr 0.0.0.0 --http.corsdomain "curieux.ma" --http.api web3,personal,eth,net --port 30303 --syncmode full --http.vhosts '*' 
# Noeud miner/signer (distributor)
/usr/bin/geth --datadir /home/ethereum/distributor/data --nodiscover --networkid 985459 --port 30305 --unlock 0xF72eF0d377515c11056660be5D65A3B407095254 --password /home/ethereum/distributor/password.txt --mine --syncmode full  --miner.gasprice 0 --txpool.pricelimit 0 

Ce noeud expose les API http pour MetaMask, expose le port 30303 pour d’éventuels noeuds qui aimeraient s’ajouter au réseau et n’autorise de requêtes CORS que pour le domaine curieux.ma.

Il existe un autre nœud que j’appelle le distributor non exposé sur internet. Ce noeud me sert à valider les transactions et à servir une petite application node qui sert de manière automatique le 1ETH à travers le bouton Recevoir de l’ether.

Une fois ces commandes exécutées, le premier noeud qui est exposé est prêt à travailler et se synchronisera avec tout autre noeud avec lequel il serait connecté.

Déployer votre propre noeud

Je décris les différentes étapes dans le fichier instructions_ethnode.txt ici. Elles sont un peu pêle-mêle, donc voici les macro-étapes pour rejoindre le noeud existant :

1. Sysadmin classique

Je passe les étapes classiques de configuration d’un vps. Je part en général sur la dernière distribution Ubuntu et je déroule le grand classique first 5 minutes of essentials and security.

  • Update et Upgrade
  • Fail2ban
  • User dédié
  • Nettoyage des accès SSH

2. Préparation Ethereum

Une fois tout cela fait, il faut ouvrir le port 30303 de votre machine pour préparer le terrain à la communication des nœuds Ethereum.

On installe Geth :

apt-get install software-properties-common
add-apt-repository -y ppa:ethereum/ethereum
apt-get update
apt-get install ethereum

Puis on configure une wallet qui servira de base au miner :

/usr/bin/geth account new --datadir /home/ethereum/node/data

Cette adresse vous servira plus tard pour miner des blocs.

3. Instanciation du noeud Ethereum

Lorsque les prérequis sont là, on récupère le fichier genesis.json qui sera le seed du noeud

wget https://raw.githubusercontent.com/AshtonIzmev/ethereum-association/master/eth/genesis.json

Puis on initialise le noeud avant de le lancer

/usr/bin/geth init --datadir /home/ethereum/node/data /home/ethereum/node/genesis.json
/usr/bin/geth --nodiscover --datadir /home/ethereum/node/data --networkid 985459 --syncmode full

Rien de plus simple, le nœud est fonctionnel mais sans être connecté au réseau. Pour réaliser cette opération, il faut récupérer l’enode d’un nœud exposé et l’utiliser. Par exemple, mon noeud exposé a comme enode “enode://e3ebe55885…[email protected]:55132” récupérée sur ma machine avec la commande :

issam:~$ geth attach /home/ethereum/node/data/geth.ipc --exec admin.nodeInfo.enode

Il faut donc exécuter sur votre noeud

ENODE="enode://e3ebe5588575899fc25c2597ed5c3b7dfe05f26dd6a82f1f5b398d89830b4957ee30481beff7521c5da9794b8bbf5792c9c7be97ab11d7aff37804bdd0ba7a8d@209.250.236.210:30303"
geth attach /home/ethereum/node/data/geth.ipc --exec "admin.addPeer('${ENODE}')"
geth attach /home/ethereum/node/data/geth.ipc --exec "admin.peers"

4. Rejoindre la clique

Vous avez à présent un nœud parfaitement connecté et synchronisé par la blockchain initiale. Il peut interagir, envoyer des transactions et être le relais avec une Dapp par exemple à travers les API HTTP-RPC. Par contre, il n’est pas encore autorisé à signer des transactions car notre réseau est privé.

Vous devez relancer votre noeud avec une commande spéciale unlock et un fichier PASSWORDFILE qui contient la passphrase de votre wallet

/usr/bin/geth --nodiscover --datadir /home/ethereum/node/data --networkid 985459 --syncmode full --unlock VOTREADRESSE --password PASSWORDFILE

Le champ VOTREADRESSE doit être rempli avec l’adresse publique que vous avez obtenu en créant une nouvelle wallet.

La clique permet d’autoriser un nouveau miner à travers un protocole de vote majoritaire. A ce stade là, vous devez envoyer l’adresse que vous utilisez à toute personne existantes dans le réseau en tant que miner/signer. Et éventuellement les convaincre de votre sérieux :)

Pour ma part, je dois ensuite voter pour vous sur mes propres noeuds :

issam:~$ geth attach /home/ethereum/node/data/geth.ipc --exec clique.propose("VOTREADRESSE", true)

Si suffisamment de personnes votent pour vous, vous êtes admis dans la clique et autorisé à signer des transactions.

Votre nœud ayant été éteint pour ajouter unlock et password, il faut relancer le peer add et lancer un miner également.

ENODE="enode://e3ebe5588575899fc25c2597ed5c3b7dfe05f26dd6a82f1f5b398d89830b4957ee30481beff7521c5da9794b8bbf5792c9c7be97ab11d7aff37804bdd0ba7a8d@209.250.236.210:30303"
geth attach /home/ethereum/node/data/geth.ipc --exec "admin.addPeer('${ENODE}')"
geth attach /home/ethereum/node/data/geth.ipc --exec "admin.peers"
 
geth attach /home/ethereum/node/data/geth.ipc --exec "miner.start()"

Nos nœuds sont désormais synchronisés et interdépendants. Si l’un d’entre nous devait disparaître, le réseau serait alors arrêté car un des signataires absents. Devenir miner traduit une relation de confiance dans le réseau et ne se fait pas à la légère. C’est la différence principale entre une blockchain privée et une blockchain publique où seul le travail algorithmique et la dépense énergétique comptent.

Si vous désirez quitter le réseau, une majorité de 51% des autres signers doivent voter votre exclusion afin de rétablir le bon fonctionnement du réseau :

issam:~$ geth attach /home/ethereum/node/data/geth.ipc --exec clique.propose("VOTREADRESSE", false)
ali:~$ geth attach /home/ethereum/node/data/geth.ipc --exec clique.propose("VOTREADRESSE", false)
...

Si vous pensez avoir assez de stabilité sur quelques mois, devenez un signer. Sinon, soyez simplement un relai du réseau sans être signer de transaction.

Quelques bonnes pratiques

Je lance mes noeuds dans des services systemd. Voici un exemple au cas où ce serait utile :

[Service]
User=ethereum
Group=ethereum
Environment=HOME=/home/ethereum
Type=simple
ExecStart=/usr/bin/geth --datadir /home/ethereum/node/data --nodiscover --networkid 985459 --http --http.addr 0.0.0.0 --http.corsdomain "curieux.ma" --http.api web3,personal,eth,net --port 30303 --syncmode full --miner.gasprice 0 --txpool.pricelimit 0 --http.vhosts '*' 
KillMode=process
KillSignal=SIGINT
TimeoutStopSec=90
Restart=on-failure
RestartSec=10s
 
[Install]
WantedBy=multi-user.target

Pour les passphrase et les mots de passe en général, j’aime bien utiliser pwgen

pwgen -s -y 30

Si $5 par mois n’est pas beaucoup pour vous et que vous voulez jouer avec le réseau Ethereum, je vous suggère d’aller chercher un VPS sur vultr.com localisé en Europe (pour un ping faible) sur une Ubuntu 20.04 LTS. Ces instances se lancer en quelques minutes et sont facturées à l’heure. Je me retrouve parfois à payer moins de quelques centimes pour des expérimentations de quelques heures.

Conclusion

Cet article clôt la série des 2 autres articles avec une plongée dans le déploiement d’un nœud ethereum. Comme vous pouvez le constater, les étapes ne sont pas nombreuses pour devenir un miner mais il faut bien comprendre les subtilités des algorithmes de consensus et de la ligne de commande geth.

J’ai bon espoir que plusieurs lecteurs trouvent ce tutoriel utile et se connectent à mon nœud exposé afin de simuler un vrai réseau privé marocain. Pour les plus courageux, je vous attends.

Liens vers les photos

Photo by Isaac Davis on Unsplash