Première rédaction de cet article le 12 septembre 2015
Je viens de me lancer dans Ethereum et j'ai envie de partager avec vous (partager mon expérience, pas mon argent virtuel, faut pas rêver).
Ethereum est souvent présenté par rapport à Bitcoin : « Bitcoin 2.0 », « the next Bitcoin », « Bitcoin on steroids », etc. Il est vrai qu'il s'inspire très fortement de Bitcoin mais, en le présentant ainsi, on peut le confondre avec tous les autres machins qui ont été faits à partir de Bitcoin comme Dogecoin, Litecoin ou encore Namecoin. À part ce dernier, ces comparaisons peuvent amener à conclure qu'Ethereum n'est qu'« une nouvelle monnaie virtuelle et cryptographique (alt coin) ». Alors qu'il est bien plus que cela.
Ceci dit, c'est vrai que, pour expliquer Ethereum, partir de Bitcoin est pratique. Avant Bitcoin, on considérait que, pour établir et exécuter des contrats (oui, une monnaie est une forme de contrat : je te donne des billets en échange de quelque chose), il n'y avait que deux solutions :
Bitcoin a montré qu'il existait une troisième solution : une structure de données publique, le livre des opérations ou blockchain, que tout le monde peut voir et vérifier. Cette structure liste toutes les transactions et est protégée par la magie de la cryptographie, de façon à ce qu'elle soit validable. C'est le grand mérite de Bitcoin, et l'invention géniale de Satoshi Nakamoto : prouver théoriquement et expérimentalement qu'un système complètement pair à pair pouvait fonctionner, ce qui était loin d'être évident (par exemple, j'étais personnellement persuadé que c'était impossible).
Bitcoin est spécialisé : on ne peut s'en servir que pour la monnaie. Si on veut, par exemple, enregistrer des noms et non pas échanger de l'argent, il faut copier le code de Bitcoin (il est libre), faire des modifications et créer sa propre infrastructure (sa blockchain à soi, ses mineurs, ses explorateurs de blockchain, etc). Ce choix n'est pas un oubli ou une erreur des concepteurs de Bitcoin : c'est parce que faire un système équivalent, mais généraliste, est non trivial, notamment du point de vue de la sécurité.
Ethereum reprend plusieurs concepts importants de Bitcoin, notamment la blockchain et la preuve de travail (il n'est donc pas plus écologiste que Bitcoin). Mais le code est radicalement différent, réécrit de zéro (contrairement à la plupart des alt coins). Il existe en outre plusieurs implémentations, avec une spécification commune (contrairement à Bitcoin où le code est la spécification, le papier original de Nakamoto ne descendant pas dans les détails). Mais le gros changement par rapport à Bitcoin est que les transactions stockées dans la blockchain ne sont pas limitées à envoyer et recevoir de l'argent. Ethereum dispose d'un quasi-langage de Turing et est donc un système de calcul réparti : les pairs dans le réseau Ethereum ne se contentent pas de vérifier l'intégrité de la blockchain et d'ajouter de la monnaie, ils exécutent du code arbitraire, celui des applications que vous ou moi développons et envoyons sur le réseau.
Cela permet d'écrire des contrats (appelés, dans le style marketing fréquent dans le monde Ethereum, des smart contracts) qui sont la description, dans un langage de programmation, des règles qui s'imposent aux parties contractantes. Un prêt d'argent, par exemple, peut se programmer dans un contrat et s'exécuter automatiquement, sans intervention humaine, et donc sans possibilité de triche. (Question philosophique : quel est le pourcentage des contrats entre humains qui peuvent s'automatiser, c'est-à-dire ne plus accepter d'arrangement, de cas particuliers, etc ?) Les applications d'Ethereum ne sont donc limitées que par votre imagination.
Ces contrats sont la nouveauté importante d'Ethereum. Comme
leur exécution peut potentiellement consommer des ressources
importantes (imaginez une boucle sans fin dans un contrat...), il
faut payer pour leur exécution, ce qu'Ethereum nomme
l'essence (gas). Cette
essence est payée avec la monnaie de base d'Ethereum,
l'ether. (D'ailleurs, si vous voulez
m'envoyer des ethers, mon adresse actuelle est
0xbe1f2ac71a9703275a4d3ea01a340f378c931740
.)
Si vous tombez à court d'essence, l'application s'arrête. C'est
cette limite qui fait qu'Ethereum n'est pas une vraie
machine de Turing : celle-ci a des
ressources infinies.
Bon, vous trouverez des articles généraux et théoriques sur Ethereum un peu partout. Passons plutôt à la pratique. D'abord, un sérieux avertissement, Ethereum est encore vraiment expérimental. Le premier bloc de la blockchain, la genèse, n'a été générée que fin juillet 2015. Le code ne marche pas toujours, les compétences humaines sont encore rares et, surtout, tout évolue vite et les documentations qu'on trouve en ligne sont presque toujours fausses ou dépassées (ou les deux à la fois). Les interfaces utilisateurs d'accès facile manquent (il n'existe pas encore d'équivalent des nombreux portefeuilles Bitcoin, par exemple). Contrairement à Bitcoin, on n'est donc pas encore en production. Ne vous plaignez pas qu'on ne vous a pas prévenus ! Et, comme avec Bitcoin, vous êtes entièrement responsable de votre sécurité. Un bon exemple d'erreur de sécurité faite par un utilisateur et de ses conséquences a été raconté sur Reddit.
Donc, installons un nœud Ethereum pour commencer. J'ai dit que, contrairement à Bitcoin, Ethereum n'est heureusement pas défini par une seule implémentation. Deux sont souvent citées pour l'usage pratique d'Ethereum, eth (écrit en C++) et geth (écrit en Go). Essayons avec geth (je dirais plus loin pourquoi eth ne m'a pas satisfait). La voie officielle pour installer un exécutable binaire de geth sur une Debian est :
% curl https://install-geth.ethereum.org -L > install-geth.sh % sudo bash install-geth.sh
Cela ne fonctionne pas (rappelez-vous ce que j'ai dit sur le côté
expérimental de la chose). Contrairement à ce que prétend la documentation,
le code ne marche que sur Ubuntu et il
faut, pour Debian, modifier
la liste des sources apt. J'édite donc
/etc/apt/sources.list.d/ethereum-ethereum-jessie.list
et je remplace « jessie » (Debian) par « vivid » (Ubuntu). Après,
cela fonctionne. Si vous n'aimez pas installer du binaire sans
comprendre, le source est disponible en ligne.
Une fois geth installé, on le lance :
% geth console ... I0912 15:05:24.430701 6306 chain_manager.go:237] Last block (#223283) f374ff2948430d05acc4a14684924d78d6ade385116c9541eec6e40994785dd7 TD=899026925409268704 ... I0912 15:05:25.966841 6306 backend.go:557] Server started ... instance: Geth/v1.1.3/linux/go1.5 >
(Le dernier caractère, le >
est l'invite de la
console Ethereum.) La console est, par défaut, très bavarde. Le moyen
le plus simple de travailler tranquillement est de lancer un autre
terminal :
% geth attach
(Vous pouvez avoir toutes les options de geth en tapant geth
--help
ou bien en
ligne.)
Au premier lancement (WARNING: No etherbase set and no
accounts found as default et WARNING: Wrote default
ethereum genesis block), vous en aurez pour plusieurs heures
(en septembre 2015) avant que
votre nœud Ethereum soit synchronisé avec la
blockchain. (eth est bien plus long que geth pour
cette tâche, et il passe en outre du temps à nous prévenir qu'il
construit un énorme DAG, nécessaire pour le
minage.) À noter que la chaîne de blocs ne fait que s'allonger et, en
mars 2016, ce temps était passé à 36 h, sur le même PC... En attendant cette synchronisation, vos transactions ne
seront pas visibles localement, puisque votre nœud sera encore dans le
passé de la blockchain. Pour voir où en est cette
synchronisation :
> eth.blockNumber 223298
Et vous allez voir sur un explorateur public de la blockchain si vous vous en approchez. Par exemple, si EtherChain ou Eth status me disent sur leur page d'accueil qu'on vient de faire le bloc 223299, j'en déduis que je suis quasi-synchronisé (un seul bloc de retard).
La syntaxe de la ligne de commandes de geth peut paraître bizarre
mais elle vient du fait qu'elle s'inspire de
l'API JavaScript
accessible aux programmes Ethereum (et cette API est
documentée, c'est ainsi que vous pouvez apprendre à utiliser la console). Vous pouvez donc, non seulement
taper des commandes, mais aussi écrire du JavaScript dans la
console. Une documentation plus complète (mais pas toujours correcte)
est disponible
sous le nom d'« Ethereum Frontier Guide ». Il y a aussi une
bonne
documentation de la console interactive (pensez juste à
remplacer web3.eth.
par
eth.
).
Bien, maintenant que geth est lancé et a fini par se synchroniser (rappelez-vous, plusieurs heures, la première fois), on peut se créer un compte, pour envoyer et recevoir des ethers :
> personal.newAccount("Tu ne sauras pas mon mot de passe") "0xbe1f2ac71a9703275a4d3ea01a340f378c931740" > eth.getBalance(eth.accounts[0]) 0
Il peut y avoir plusieurs comptes et
eth.accounts[0]
est le premier créé. Son adresse
est
0xbe1f2ac71a9703275a4d3ea01a340f378c931740
. C'est
là où vous pouvez m'envoyer des ethers. Puisqu'Ethereum, comme Bitcoin,
est transparent, vous pouvez regardez sur un explorateur public toute
l'activité de ce compte.
La commande getBalance
indiquait mon niveau de
pauvreté. Aucun ether disponible. Je pourrais en miner en faisant
tourner mon CPU (et donc mes ventilateurs) à
fond mais j'ai préféré en acheter des tout faits, chez Kraken où on peut désormais acheter et
vendre des ethers. Menu Trade / New order, j'ai
acheté deux ethers. Attention, les interfaces Ethereum comptent
parfois en ethers mais parfois aussi dans leurs subdivisions, portant
des noms pittoresque comme « szabo » (un millionième d'ether) ou
« lovelace » (un millionième de milliardième d'ether). Une fois mes
ethers obtenus, je les envoie depuis Kraken vers mon compte, en
indiquant l'adresse de celui-ci (menu Funding /
Withdraw). Attention, si vous utilisez Kraken pour d'autres
monnaies que l'ether, la fonction permettant d'enregistrer une adresse
est par compte Kraken et pas par monnaie. Si vous avez enregistré une
adresse Bitcoin sous le nom « Maison », vous ne pourrez pas nommer
l'adresse Ethereum de la même façon (« duplicate withdrawal
information » est le peu utile message d'erreur de Kraken).
Rapidement, les ethers se retrouvent sur votre compte :
> eth.getBalance(eth.accounts[0]) 1995000000000000000
(Le montant est indiqué en weis, voir plus haut l'avertissement sur les subdivisions de l'ether. Ici, cela fait 1,995 ethers soit même pas deux euros au cours actuel.) Notez bien qu'Ethereum est aussi transparent que Bitcoin : tout le monde peut voir les retraits effectués depuis Kraken (essayez avec un autre explorateur public, Blockchain).
Jusqu'à présent, rien d'extraordinaire, on a fait exactement la même chose qu'avec Bitcoin. Quel intérêt d'utiliser Ethereum ? Le client est plus perfectionné et permet de faire du JavaScript pour automatiser certaines tâches. Par exemple, ce code :
function cab() { var i =0; eth.accounts.forEach(function(e){ console.log(" eth.accounts["+i+"]: " + e + " \tbalance: " + web3.fromWei(eth.getBalance(e), "ether") + " ether"); i++; }) };
va itérer sur tous vos comptes et afficher le nombre d'ethers :
> cab() eth.accounts[0]: 0xbe1f2ac71a9703275a4d3ea01a340f378c931740 balance: 1.9833824 ether undefined
Mais la vraie puissance d'Ethereum n'est pas là. Elle est dans les contrats. Ceux-ci sont des programmes exécutés par la machine Ethereum. Celle-ci exécute un langage machine nommé EVM. Il est de trop bas niveau pour le programmeur normal, qui écrit en général ses contrats dans un langage de plus haut niveau qu'il compilera. Le plus répandu de ces langages est Solidity (qui ressemble à JavaScript) mais on trouve aussi Serpent (inspiré de Python) ou LLL (dont la syntaxe ressemble à Lisp mais qui est en fait un langage de bas niveau, très proche du langage machine, Serpent peut d'ailleurs produire du LLL). Comme je suis paresseux, je vais utiliser un contrat en Solidity que j'ai récupéré chez Ethereum.org. C'est le Hello, World des contrats. Voyons d'abord si on a bien un compilateur Solidity :
> eth.getCompilers() [""]
Non, rien. Installons-le (le script d'installation a mis la bonne source dans ma configuration d'apt) :
% sudo apt-get install solc ... (Retour à geth) > admin.setSolc("/usr/bin/solc") "solc v0.1.1\nSolidity Compiler: /usr/bin/solc\n" > eth.getCompilers() ["Solidity"]
On peut alors rédiger le contrat (je ne le recopie pas ici, il est en ligne) :
... (Appel à greeterContract.new()...) ... Unlock account be1f2ac71a9703275a4d3ea01a340f378c931740 Passphrase: Contract transaction send: TransactionHash: 0x07dc92c133a433ad58946a7acf8a6f3ccf0352f34882158cc4745c17636ee81e waiting to be mined... undefined
La demande de phrase de passe est due au fait que la création du contrat et son exécution nécessitent de l'essence. Cette transaction a nécessité plus de 200 000 unités d'essence et m'a couté en tout 0,0116 ethers, ce que reflète mon portefeuille :
> eth.getBalance(eth.accounts[0]) 1983382400000000000
Une fois validée par les mineurs, le contrat a une adresse :
> Contract mined! Address: 0xf0b64c321e9db6bf9164eae8be44443e1e2834a5 [object Object]
On peut voir le contrat en ligne, récupérer le code compilé :
> greeter.address; "0xf0b64c321e9db6bf9164eae8be44443e1e2834a5" > eth.getCode(greeter.address) "0x60606040526000357c0100000..."
Et, bien sûr, l'exécuter :
> greeter.greet(); "Mon contrat à moi"
La méthode créée par le code est visible dans la définition de l'ABI, ce que les autres utilisateurs devront connaître pour interagir avec « mes » contrats :
> greeterCompiled.greeter.info.abiDefinition; [ ... { constant: true, inputs: [], name: "greet", outputs: [{ name: "", type: "string" }], type: "function" ...
C'est évidemment un tout petit contrat, sans grand intérêt. Au fur et à mesure que je progresse en programmation, j'espère en faire des meilleurs. En attendant, il existe plein d'exemples en ligne, comme le DAO qui prétend outrageusement implémenter... la démocratie en Solidity et clame même « This is exactly how a democracy should work. ». Ce contrat met en œuvre un mécanisme de vote entre « actionnaires » sur l'allocation de ressources. Ce vote est censitaire « The rules of your organization are very simple: anyone with at least one token [la monnaie du DAO] can create proposals to send funds from the country's account. After a week of debate and votes, if it has received votes worth a total of 100 tokens or more and has more approvals than rejections, the funds will be sent. If the quorum hasn't been met or it ends on a tie, then voting is kept until it's resolved. Otherwise, the proposal is locked and kept for historical purposes. ». Cela peut être une façon intéressante de gérer certaines organisations mais appeler ça « démocratie » est franchement fort de café. Inutile de dire que je ne partage pas leur délire libertarien.
Un exemple plus simple de contrat, facile à étudier mais illustrant la plupart des possibilités d'Ethereum, est la Pyramide, décrite dans mon article suivant.
Revenons à l'autre mise en œuvre d'Ethereum, eth, écrite en C++. C'est en fait par celle là que j'avais commencé mais j'ai arrêté car je n'arrivais pas à lui faire accepter mes contrats. L'installation ressemble beaucoup à celle de geth :
% curl https://install-eth.ethereum.org -L > install-eth.txt % sudo bash -x install-eth.txt
On lance eth, par exemple, ainsi :
% eth -j --frontier -i --verbosity 2
Et sa console n'a pas l'air de comprendre le Contrôle-D de fin de
session, il faut faire
web3.admin.eth.exit()
. Pour de l'aide, on peut
faire eth --help
(ou bien voir la
doc en ligne) et juste taper
web3
dans la console.
J'ai créé plusieurs comptes avec eth (l'objet de référence est
web3.eth
, et pas eth
comme
c'était le cas avec geth) :
> web3.eth.accounts ['0x003653c3b972ede82f621ac322c6e430493eeb8c', '0x0007ca35a2680425974312233a59a74c00d3c040', '0x00740378b6046b199f7197fabe21484787648d24'] > web3.eth.getBalance(web3.eth.accounts[1]) 1995000000000000000'
J'avais ensuite essayé de créer un contrat depuis eth mais sans succès. eth a tous les compilateurs :
> web3.eth.getCompilers() ['lll', 'solidity', 'serpent']
J'ai utilisé le même contrat qu'avec geth, une transaction était bien générée (0xffc8450fd29e6dc26b7df84328913df16dad4b29b3fbd1df9df2a5d12dabc251) mais apparemment jamais validée :
20:51:34|eth New transaction ffc8450f…{[CREATE]/788$0+300000@50000000000<-0007ca35… #0} 'Contract transaction send: TransactionHash: 0xffc8450fd29e6dc26b7df84328913df16dad4b29b3fbd1df9df2a5d12dabc251 waiting to be mined...'
Cela illustre bien qu'Ethereum n'est pas encore prêt pour un usage généralisé. C'est une technique expérimentale mais très prometteuse techniquement et très intéressante politiquement.
Quelques lectures supplémentaires :
Version PDF de cette page (mais vous pouvez aussi imprimer depuis votre navigateur, il y a une feuille de style prévue pour cela)
Source XML de cette page (cette page est distribuée sous les termes de la licence GFDL)