Passer au contenu principal

Introduction à Ethereum pour développeurs Python, partie 1

pythonweb3.py
Débutant
Marc Garreau
Snake charmers(opens in a new tab)
8 septembre 2020
13 minutes de lecture minute read

Vous avez donc entendu parler d'Ethereum et êtes prêts à passer de l'autre côté du miroir ? Cet article couvrira rapidement certaines fonctionnalités de base propres aux blockchains, puis vous permettra d'interagir avec une simulation de nœud Ethereum - lecture des données de blocs, vérification des soldes de comptes et envoi de transactions. En cours de route, nous soulignerons les différences entre les méthodes classiques de création d'application et ce nouveau paradigme décentralisé.

Prérequis (simple)

Ce post se veut accessible à une large catégorie de développeurs. L'emploi d'outils Python sera réalisé, mais ils ne serviront qu'à véhiculer les idées – Ne vous inquiétez pas si vous n'êtes pas développeur Python. Toutefois, je vais faire quelques hypothèses sur ce que vous savez déjà, afin que nous puissions rapidement passer aux sujets spécifiques à Ethereum.

Hypothèses:

  • Vous êtes en mesure d'utiliser un terminal,
  • Vous avez déjà écrit quelques lignes de code Python,
  • La version 3.6 ou supérieure de Python est installée sur votre machine (l'utilisation d'un environnement virtuel(opens in a new tab) est fortement recommandée), et
  • vous avez déjà utilisé pip, l'installateur de paquets de Python. Encore une fois, si l'un de ces éléments n'est pas vrai, ou si vous ne prévoyez pas de reproduire le code de cet article, vous resterez capable de comprendre son contenu sans grande difficulté.

Blockchains, en bref

Il y a de nombreuses façons de décrire Ethereum, mais son cœur repose sur la Blockchain. Les Blockchains sont constituées d'une série de blocs, alors commençons par là. En termes simples, chaque bloc de la blockchain Ethereum n'est qu'un ensemble de métadonnées et de transactions. Dans le format JSON, cela ressemble à ceci :

1{
2 "number": 1234567,
3 "hash": "0xabc123...",
4 "parentHash": "0xdef456...",
5 ...,
6 "transactions": [...]
7}
Copier

Chaque bloc possède une référence du bloc l'ayant précédé ; le parentHash est simplement le hash du bloc précédent.

Note : le réseau Ethereum utilise régulièrement des fonctions de hachage(opens in a new tab) pour produire des valeurs de taille fixe (« hashes »). Les hachages (« hashes ») jouent un rôle important dans le réseau Ethereum, vous pouvez les considérer comme des identifiants uniques pour le moment.

Un diagramme décrivant la blockchain ainsi que les données internes de chaque bloc

Une blockchain est essentiellement une liste liée ; chaque bloc a une référence au bloc précédent.

Cette structure de données n'est pas nouvelle, mais les règles (c'est-à-dire les protocoles « peer-to-peer ») qui régissent le réseau le sont. Il n’y a pas d’autorité centrale; le réseau d'utilisateurs (pairs) doit collaborer pour pérenniser le réseau et s'affronter pour décider quelles transactions inclure dans le bloc suivant. Donc, quand vous voulez envoyer de l'argent à un ami, vous devrez diffuser cette transaction sur le réseau, puis attendre qu'elle soit incluse dans un bloc à venir.

La seule façon pour la chaîne de blocs de vérifier que l'argent a vraiment été envoyé d'un utilisateur à un autre est d'utiliser une devise native à (à savoir créée et régie par) la blockchain. Sur le réseau Ethereum, cette devise est appelée « ether », et la blockchain Ethereum contient le seul enregistrement officiel des soldes de compte.

Un nouveau paradigme

Cette nouvelle pile de technologies décentralisées a créé de nouveaux outils de développement. De tels outils existent dans de nombreux langages de programmation, mais nous allons les explorer via le language Python. Encore une fois : même si Python n’est pas votre langage de choix, il ne devrait pas être difficile de le comprendre.

Les développeurs Python qui veulent interagir avec le réseau Ethereum sont encouragés à utiliser Web3.py(opens in a new tab). Web3.py est une bibliothèque qui simplifie grandement la façon dont vous vous connectez à un nœud Ethereum, et par la suite envoyer et recevoir des données.

Note : Les notions de « noeud Ethereum » et de « client Ethereum » sont utilisées de façon interchangeable. Dans les deux cas, il se réfère au logiciel qu'un participant au réseau Ethereum exécute. Ce logiciel peut lire les données de bloc, recevoir des mises à jour lorsque de nouveaux blocs sont ajoutés à la chaîne, diffuser de nouvelles transactions, et encore bien davantage. Techniquement, le client est le logiciel , le nœud est l'ordinateur qui exécute le logiciel.

Les clients Ethereum peuvent être configurés pour être accessibles par IPC(opens in a new tab), HTTP ou Websockets, donc Web3. devra respecter cette configuration. Web3.py fait référence à ces options de connexion en tant que fournisseurs. Il vous faudra choisir l'un des trois fournisseurs pour lier l'instance Web3.py à votre nœud.

Un diagramme montrant comment web3.py utilise IPC pour connecter votre application à un nœud Ethereum

Configurez le noeud Ethereum et Web3.py afin qu'ils communiquent via le même protocole, par exemple via IPC dans ce diagramme.

Une fois que Web3.py est correctement configuré, vous pouvez commencer à interagir avec la blockchain. Voici quelques exemples d'utilisation de Web3.py pour avoir un aperçu de ce qui va se passer :

1# read block data:
2w3.eth.get_block('latest')
3
4# send a transaction:
5w3.eth.send_transaction({'from': ..., 'to': ..., 'value': ...})
Copier

Installation

Dans ce qui suit, nous allons juste travailler au sein de l'interpréteur Python. Nous n'allons pas créer de répertoires, fichiers, classes ou fonctions.

Note : dans les exemples ci-dessous, les commandes qui commencent par `$` sont censées être exécutées dans le terminal. (Ne tapez pas le `$`, cela signifie simplement que c'est le début de la ligne.)

Tout d'abord, installez IPython(opens in a new tab) pour avoir un environnement convivial à explorer. IPython propose entre autres une fonctionnalité d'auto-completion en appuyant sur la touche TAB, ce qui facilite la navigation dans Web3.py.

pip install ipython

Web3.py est publié sous le nom web3. Installez-le comme suit :

pip install web3

Encore une chose : nous allons simuler une blockchain plus tard, ce qui requiert quelques dépendances supplémentaires. Vous pouvez les installer via :

pip install 'web3[tester]'

C'est tout !

Note : Le package web3[tester] marche jusqu'a Python 3.10.xx

Lancer un sandbox

Ouvrez un nouvel environnement Python en exécutant ipython dans votre terminal. Ceci est comparable à l'exécution de python=, mais apporte plus d'avantages.

ipython

Cela affichera quelques informations sur les versions de Python et de IPython que vous utilisez, puis vous devriez voir une invite de saisie :

1In [1]:
Copier

Vous regardez un shell Python interactif. Essentiellement, il s'agit d'un bac à sable pour jouer. Si vous êtes arrivés jusqu’ici, il est temps d’importer Web3.py :

1In [1]: from web3 import Web3
Copier

Introduction du module Web3

En plus d'être une passerelle vers Ethereum, le module Web3(opens in a new tab) offre quelques fonctions pratiques. Examinons-en quelques-unes.

Dans une application Ethereum, vous devrez généralement convertir des libellés de devises. Le module Web3 fournit quelques méthodes juste pour cela : fromWei(opens in a new tab) et toWei(opens in a new tab).

Remarque : les ordinateurs sont notoirement peu efficaces pour la gestion des nombres décimaux. Pour contourner cela, les développeurs stockent souvent les montants en dollar en centimes. Par exemple, un article avec un prix de 5,99 $ peut être stocké dans la base de données comme 599.

Un schéma similaire est utilisé lors de la gestion des transactions en ether. Cependant, au lieu de deux décimaux, l'ether en a 18 ! La plus petite dénomination d'ether s'appelle wei, c'est la valeur spécifiée lors de l'envoi des transactions.

1 ether = 1000000000000000000 wei

1 wei = 0,00000000000001 ether

Essayez de convertir certaines valeurs depuis et vers le wei. Notez qu'il y a des noms pour un grand nombre de dénominations(opens in a new tab) entre ether et wei. L'une des plus connues est le gwei, car c'est souvent la façon dont les frais de transaction sont représentés.

1In [2]: Web3.to_wei(1, 'ether')
2Out[2]: 1000000000000000000
3
4In [3]: Web3.from_wei(500000000, 'gwei')
5Out[3]: Decimal('0.5')
Copier

Les autres méthodes utilitaires du module Web3 incluent les convertisseurs de format de données (par exemple, toHex(opens in a new tab)), les méthodes pour gérer les adresses (e. ., isAddress(opens in a new tab)), et les fonctions de hachage (par exemple, keccak(opens in a new tab)). Beaucoup d'entre elles seront étudiées plus tard dans la série. Pour afficher toutes les méthodes et propriétés disponibles, utilisez l'auto-complétion de IPython en tapant Web3. et en appuyant sur la touche tabulation deux fois après le point.

Parler à la chaîne

Ces méthodes sont très intéressantes, mais passons à la blockchain. L'étape suivante est de configurer Web3.py à des fins de communication avec un noeud Ethereum. Ici, nous avons la possibilité d'utiliser les fournisseurs IPC, HTTP, ou Websocket.

Nous n'allons pas explorer cette voie, mais un exemple de flux de travail complet en utilisant le fournisseur HTTP pourrait ressembler à ceci :

  • Télécharger un nœud Ethereum, par exemple Geth(opens in a new tab).
  • Démarrez Geth dans une seule fenêtre de terminal et attendez qu'il synchronise le réseau. Le port HTTP par défaut est 8545, mais il est configurable.
  • Dites à Web3.py de se connecter au nœud via HTTP, sur localhost:8545. w3 = Web3(Web3.HTTPProvider('http://127.0.0.1:8545'))
  • Utilisez l'instance w3 pour interagir avec le nœud.

Bien qu’il s’agisse d’une « vraie » façon de le faire, le processus de synchronisation prend des heures et est inutile si vous voulez juste un environnement de développement. Web3.py expose un quatrième fournisseur à cet effet, l'EthereumTesterProvider. Ce fournisseur de testeur est relié à un nœud Ethereum simulé avec des autorisations réduites et des fausses devises pour jouer.

Un diagramme montrant l'EthereumTesterProvider reliant votre application web3.py à un nœud Ethereum simulé

L'EthereumTesterProvider se connecte à un noeud simulé et est pratique pour des environnements de développement rapides.

Ce nœud simulé s'appelle eth-testeur(opens in a new tab) et nous l'avons installé dans le cadre de la commande pip install web3[tester]. Configurer Web3.py pour qu'il utilise ce fournisseur de testeur est aussi simple que :

1In [4]: w3 = Web3(Web3.EthereumTesterProvider())
Copier

Maintenant vous êtes prêt à surfer sur la chaîne ! Ce n'est pas une chose que les gens disent. Je viens juste de l'inventer. Faisons un tour rapide.

Le tour rapide

Tout d'abord, une vérification :

1In [5]: w3.is_connected()
2Out[5]: True
Copier

Étant donné que nous utilisons le fournisseur de testeur, ce test n'est pas très important. Toutefois, s'il échoue, il y a des chances que vous ayez mal tapé quelque chose lors de l'instanciation de la variable w3. Vérifiez bien que vous avez inclus les parenthèses intérieures, à savoir Web3.EthereumTesterProvider().

Arrêt #1 : Les comptes

Afin de faciliter les tests, le fournisseur de testeur a créé des comptes et les a préchargés avec un ether de test.

D’abord, observons une liste de ces comptes :

1In [6]: w3.eth.accounts
2Out[6]: ['0x7E5F4552091A69125d5DfCb7b8C2659029395Bdf',
3 '0x2B5AD5c4795c026514f8317c7a215E218DcCD6cF',
4 '0x6813Eb9362372EEF6200f3b1dbC3f819671cBA69', ...]
Copier

Si vous exécutez cette commande, vous devriez voir une liste de dix chaînes de caractères qui commencent par 0x. Chacune d'entre elles est une adresse publique qui est, à certains égards, similaire au numéro de compte sur un compte bancaire. Vous pourriez fournir cette adresse à quelqu'un qui voudrait vous envoyer des ethers.

Comme mentionné, le fournisseur de testeur a préchargé chacun de ces comptes avec des ethers de test. Cherchons maintenant combien d'ethers contient le premier compte :

1In [7]: w3.eth.get_balance(w3.eth.accounts[0])
2Out[7]: 1000000000000000000000000
Copier

Beaucoup de zéros ! Avant d'aller à la fausse banque et de vous remplir les poches tout le long du trajet, rappellez-vous la leçon de tout à l'heure sur les dénominations monétaires. La valeur en ether est présentée dans sa plus petite dénomination, le wei. Convertissons-la en ether :

1In [8]: w3.from_wei(1000000000000000000000000, 'ether')
2Out[8]: Decimal('1000000')
Copier

Un million d'ethers de test — ça reste toujours intéressant.

Arrêt #2 : Les données de bloc

Jetons un coup d’œil à l’état de cette blockchain simulée :

1In [9]: w3.eth.get_block('latest')
2Out[9]: AttributeDict({
3 'number': 0,
4 'hash': HexBytes('0x9469878...'),
5 'parentHash': HexBytes('0x0000000...'),
6 ...
7 'transactions': []
8})
Copier

Beaucoup d'informations sont retournées à propos d'un bloc, mais juste quelques choses à signaler ici :

  • Le numéro de bloc est zéro — peu importe depuis combien de temps vous avez configuré le fournisseur de testeur. Contrairement au véritable réseau Ethereum qui mine un nouveau bloc toutes les 12 secondes, cette simulation restera en attente jusqu'à ce que vous lui donniez une tâche à accomplir.
  • transactions est une liste vide pour la même raison : nous n’avons rien fait pour le moment. Ce premier bloc est un bloc vide, juste conçu pour démarrer la chaîne.
  • Notez que le parentHash n'est qu'un amas d'octets vides. Cela signifie qu'il s'agit du premier bloc de la chaîne, également connu sous le nom de bloc de genèse.

Arrêt #3 : Les transactions

Nous sommes coincés au bloc zéro jusqu'à ce qu'il y ait une transaction en attente, alors en voilà une. Envoyez quelques ethers de test d'un compte à un autre :

1In [10]: tx_hash = w3.eth.send_transaction({
2 'from': w3.eth.accounts[0],
3 'to': w3.eth.accounts[1],
4 'value': w3.to_wei(3, 'ether'),
5 'gas': 21000
6})
Copier

C'est généralement le moment pendant lequel vous devriez attendre pendant plusieurs secondes pour que votre transaction soit réalisée et intégrée dans un nouveau bloc. Le processus complet se déroule comme ceci :

  1. Soumettez une transaction et attendez le hachage de la transaction. Jusqu'à ce que le bloc contenant la transaction soit créé et diffusé, la transaction sera « en attente. » tx_hash = w3.eth.send_transaction({ … })
  2. Attendez que la transaction soit intégrée dans un bloc : w3.eth.wait_for_transaction_receipt(tx_hash)
  3. Continuer la logique de l'application. Pour voir la transaction réussie : w3.eth.get_transaction(tx_hash)

Notre environnement simulé ajoutera la transaction dans un nouveau bloc instantanément, de sorte que nous pouvons immédiatement voir la transaction :

1In [11]: w3.eth.get_transaction(tx_hash)
2Out[11]: AttributeDict({
3 'hash': HexBytes('0x15e9fb95dc39...'),
4 'blockNumber': 1,
5 'transactionIndex': 0,
6 'from': '0x7E5F4552091A69125d5DfCb7b8C2659029395Bdf',
7 'to': '0x2B5AD5c4795c026514f8317c7a215E218DcCD6cF',
8 'value': 3000000000000000000,
9 ...
10})
Afficher tout
Copier

Vous verrez ici quelques détails familiers : les champs from, to, et value doivent correspondre aux entrées de notre appel send_transaction. L'autre bit rassurant est que cette transaction a été incluse comme la première transaction ('transactionIndex': 0) dans le bloc numéro 1.

Nous pouvons également facilement vérifier la réussite de cette transaction en examinant les soldes des deux comptes concernés. Trois ethers sont supposés être passés de l'un à l'autre.

1Entrée [12] : w3.eth.get_balance(w3.eth.accounts[0])
2Sortie [12]: 999996999979000000000000
3
4Entrée [13] : w3.eth.get_balance(w3.eth.accounts[1])
5Sortie [13] : 1000003000000000000000000
Copier

Ce dernier semble bon ! Le solde est passé de 1 000 000 à 1 000 003 ethers. Mais qu'est-il arrivé au premier compte ? Il semble avoir perdu un peu plus que trois ethers. Hélas, rien dans la vie n'est gratuit et l'utilisation du réseau public Ethereum exige que vous compensiez vos pairs pour leur rôle de soutien. Une petite commission de transaction a été déduite du compte qui a soumis la transaction - cette commission correspond à la quantité de gaz brûlé (21 000 unités de gaz pour un transfert ETH) multipliée par une commission de base qui varie en fonction de l'activité du réseau plus un pourboire qui va au validateur qui inclut la transaction dans un bloc.

En savoir plus sur lesgaz

Remarque : sur le réseau public, les commissions de transaction sont variables en fonction de la demande du réseau et de la rapidité avec laquelle vous souhaitez que soit traitée une transaction. Si vous êtes intéressé par la façon dont les frais sont calculés, vous pouvez consulter mon précédent article sur la manière dont les transactions sont incluses dans un bloc(opens in a new tab).

Et respirez...

Nous y sommes depuis un bon moment et il semble donc intéressant de faire une pause. Le terrier du lapin est toujours ouvert et nous continuerons à l'explorer dans la deuxième partie de cette série. Quelques concepts à venir : la connexion à un vrai nœud, les contrats intelligents et les jetons. Vous avez des questions complémentaires ? Faites-le moi savoir ! Vos commentaires influenceront notre chemin à partir d’ici. Vos demandes sont les bienvenues sur Twitter(opens in a new tab).

Dernière modification: @moirauche(opens in a new tab), 25 janvier 2024

Ce tutoriel vous a été utile ?