0% ont trouvé ce document utile (0 vote)
95 vues55 pages

Tutoriel Python Blockchain

Ce tutoriel Python sur la blockchain explique comment créer une blockchain en utilisant Python, en se concentrant sur les composants essentiels tels que le client, le mineur et la blockchain elle-même. Il guide les développeurs à travers le processus de création d'une monnaie numérique, TPCoin, en détaillant la mise en œuvre des classes Client et Transaction nécessaires pour gérer les transactions. Le document inclut également des exemples de code et des explications sur les bibliothèques Python requises pour la cryptographie et la gestion des transactions.

Transféré par

daryl emani
Copyright
© © All Rights Reserved
Nous prenons très au sérieux les droits relatifs au contenu. Si vous pensez qu’il s’agit de votre contenu, signalez une atteinte au droit d’auteur ici.
Formats disponibles
Téléchargez aux formats DOCX, PDF, TXT ou lisez en ligne sur Scribd
0% ont trouvé ce document utile (0 vote)
95 vues55 pages

Tutoriel Python Blockchain

Ce tutoriel Python sur la blockchain explique comment créer une blockchain en utilisant Python, en se concentrant sur les composants essentiels tels que le client, le mineur et la blockchain elle-même. Il guide les développeurs à travers le processus de création d'une monnaie numérique, TPCoin, en détaillant la mise en œuvre des classes Client et Transaction nécessaires pour gérer les transactions. Le document inclut également des exemples de code et des explications sur les bibliothèques Python requises pour la cryptographie et la gestion des transactions.

Transféré par

daryl emani
Copyright
© © All Rights Reserved
Nous prenons très au sérieux les droits relatifs au contenu. Si vous pensez qu’il s’agit de votre contenu, signalez une atteinte au droit d’auteur ici.
Formats disponibles
Téléchargez aux formats DOCX, PDF, TXT ou lisez en ligne sur Scribd

Tutoriel Python Blockchain

La blockchain est le buzz actuel qui domine les tendances du développement logiciel. Le
développement et la conception de Blockchain impliquent trois composants majeurs: le client, le
mineur et la blockchain. Ce tutoriel vise à vous donner une compréhension précise du processus
de création de votre propre blockchain.
Tout passionné de programmation qui souhaite suivre le rythme de la récente tendance du
développement de la Blockchain peut tirer parti de ce tutoriel. Si vous êtes un apprenant
intéressé à apprendre les bases du développement Blockchain, ce didacticiel répond
parfaitement à vos besoins.
Ce tutoriel est écrit en supposant que l'apprenant a une idée sur la programmation en Python et
une idée de base sur la Blockchain. Si vous êtes nouveau dans l'un de ces concepts, nous vous
suggérons de choisir des tutoriels basés sur ces concepts avant de vous plonger dans ce tutoriel.

Blockchain Python - Introduction


Dans le tutoriel sur la blockchain, nous avons appris en détail la théorie derrière la blockchain. La
blockchain est la pierre angulaire de la monnaie numérique Bitcoin la plus populaire au monde.
Le tutoriel traitait en profondeur des subtilités de Bitcoin en expliquant pleinement l'architecture
de la blockchain. La prochaine étape consiste à créer notre propre blockchain.
Satoshi Nakamoto a créé la première monnaie virtuelle au monde appelée Bitcoin. En regardant
le succès de Bitcoin, de nombreux autres ont créé leurs propres monnaies virtuelles. Pour n'en
nommer que quelques-uns - Litecoin, Zcash, etc.
Maintenant, vous pouvez également lancer votre propre devise. Appelons cela comme TPCoin
(TutorialsPoint Coin). Vous écrirez une blockchain pour enregistrer toutes les transactions qui
traitent de TPCoin. Le TPCoin peut être utilisé pour acheter des pizzas, des hamburgers, des
salades, etc. Les possibilités sont infinies.
Dans ce tutoriel, laissez-nous comprendre comment construire un tel système et lancer votre
propre monnaie numérique sur le marché.

Composants impliqués dans le développement de


projets Blockchain
L'ensemble du développement du projet blockchain se compose de trois composants principaux -
 Client
 Miners
 Blockchain

Client
Le client est celui qui achètera des marchandises auprès d'autres vendeurs. Le client lui-même
peut devenir vendeur et acceptera de l'argent de tiers contre les marchandises qu'il fournit. Nous
supposons ici que le client peut à la fois être un fournisseur et un destinataire de TPCoins. Ainsi,
nous allons créer une classe de client dans notre code qui a la capacité d'envoyer et de recevoir
de l'argent.

Mineur
Le mineur est celui qui récupère les transactions d'un pool de transactions et les assemble dans
un bloc. Le mineur doit fournir une preuve de travail valide pour obtenir la récompense minière.
Tout l'argent que le mineur perçoit à titre de redevance lui appartiendra. Il peut dépenser cet
argent pour acheter des biens ou des services auprès d'autres fournisseurs enregistrés sur le
réseau, tout comme le fait un client décrit ci-dessus.

Blockchain
Enfin, une Blockchain est une structure de données qui enchaîne tous les blocs extraits dans un
ordre chronologique. Cette chaîne est immuable et donc résistante aux intempéries.
Vous pouvez suivre ce didacticiel en tapant le code présenté à chaque étape dans un nouveau
bloc-notes Jupyter. Vous pouvez également télécharger l'intégralité du notebook Jupyter
sur www.anaconda.com .
Dans le prochain chapitre, nous développerons un client qui utilise notre système blockchain.

Python Blockchain - Client en


développement
Un client est une personne qui détient des TPCoins et qui les transige contre des biens / services
d'autres fournisseurs sur le réseau, y compris le sien. Nous devrions définir unClientclasse à cet
effet. Pour créer une identification unique au monde pour le client, nous utilisons PKI (Public Key
Infrastructure). Dans ce chapitre, parlons-en en détail.
Le client doit pouvoir envoyer de l'argent de son portefeuille à une autre personne connue. De
même, le client doit pouvoir accepter de l'argent d'un tiers. Pour dépenser de l'argent, le client
créerait une transaction spécifiant le nom de l'expéditeur et le montant à payer. Pour recevoir de
l'argent, le client fournira son identité au tiers - essentiellement un expéditeur de l'argent. Nous ne
stockons pas le solde d'argent que le client détient dans son portefeuille. Lors d'une transaction,
nous calculerons le solde réel pour nous assurer que le client dispose d'un solde suffisant pour
effectuer le paiement.
Pour développer le Clientclasse et pour le reste du code du projet, nous devrons importer de
nombreuses bibliothèques Python. Ceux-ci sont énumérés ci-dessous -

# import libraries
import hashlib
import random
import string
import json
import binascii
import numpy as np
import pandas as pd
import pylab as pl
import logging
import datetime
import collections
En plus des bibliothèques standard ci-dessus, nous allons signer nos transactions, créer le
hachage des objets, etc. Pour cela, vous devrez importer les bibliothèques suivantes -

# following imports are required by PKI


import Crypto
import Crypto.Random
from Crypto.Hash import SHA
from Crypto.PublicKey import RSA
from Crypto.Signature import PKCS1_v1_5

Dans le chapitre suivant, parlons de la classe client.

Blockchain Python - Classe client


le Client classe génère le private et public clés en utilisant le Python intégré RSAalgorithme. Le
lecteur intéressé peut se référer àthis tutorialpour la mise en œuvre de RSA. Lors de
l'initialisation de l'objet, nous créons des clés privées et publiques et stockons leurs valeurs dans
la variable d'instance.

self._private_key = RSA.generate(1024, random)


self._public_key = self._private_key.publickey()

Notez que vous ne devez jamais perdre votre clé privée. Pour la tenue de registres, la clé privée
générée peut être copiée sur un stockage externe sécurisé ou vous pouvez simplement écrire la
représentation ASCII de celle-ci sur un morceau de papier.
Le généré publicLa clé sera utilisée comme identité du client. Pour cela, nous définissons une
propriété appeléeidentity qui renvoie la représentation HEX de la clé publique.

@property
def identity(self):
return
binascii.hexlify(self._public_key.exportKey(format='DER'))
.decode('ascii')

le identityest unique à chaque client et peut être rendu public. N'importe qui pourrait vous
envoyer de la monnaie virtuelle en utilisant ceidentity et il sera ajouté à votre portefeuille.
Le code complet du Client la classe est affichée ici -

class Client:
def __init__(self):
random = Crypto.Random.new().read
self._private_key = RSA.generate(1024, random)
self._public_key = self._private_key.publickey()
self._signer = PKCS1_v1_5.new(self._private_key)
@property
def identity(self):
return
binascii.hexlify(self._public_key.exportKey(format='DER')).decode('ascii')

Client de test
Maintenant, nous allons écrire du code qui illustrera comment utiliser le Client classe -

Dinesh = Client()
print (Dinesh.identity)

Le code ci-dessus crée une instance de Client et l'affecte à la variable Dinesh. Nous imprimons
la clé publique deDinesh en appelant son identityméthode. La sortie est affichée ici -

30819f300d06092a864886f70d010101050003818d0030818902818100b547fafceeb131e07
0166a6b23fec473cce22c3f55c35ce535b31d4c74754fecd820aa94c1166643a49ea5f49f72
3181ff943eb3fdc5b2cb2db12d21c06c880ccf493e14dd3e93f3a9e175325790004954c34d3
c7bc2ccc9f0eb5332014937f9e49bca9b7856d351a553d9812367dc8f2ac734992a4e6a6ff6
6f347bd411d07f0203010001

Maintenant, nous allons passer à la création d'une transaction dans le chapitre suivant.

Python Blockchain - Classe de transaction


Dans ce chapitre, créons un Transactionclasse afin qu'un client puisse envoyer de l'argent à
quelqu'un. Notez qu'un client peut être à la fois un expéditeur ou un destinataire de l'argent.
Lorsque vous souhaitez recevoir de l'argent, un autre expéditeur crée une transaction et spécifie
votrepublicadresse dedans. Nous définissons l'initialisation d'une classe de transaction comme
suit -

def __init__(self, sender, recipient, value):


self.sender = sender
self.recipient = recipient
self.value = value
self.time = datetime.datetime.now()

le init La méthode prend trois paramètres - l'expéditeur public clé, le destinataire publicet le
montant à envoyer. Ceux-ci sont stockés dans les variables d'instance pour être utilisés par
d'autres méthodes. De plus, nous créons une autre variable pour stocker l'heure de la
transaction.
Ensuite, nous écrivons une méthode utilitaire appelée to_dictqui combine les quatre variables
d'instance mentionnées ci-dessus dans un objet dictionnaire. Il s'agit simplement de mettre toutes
les informations de transaction accessibles via une seule variable.
Comme vous le savez dans le tutoriel précédent, le premier bloc de la blockchain est
un Genesisbloquer. Le bloc Genesis contient la première transaction initiée par le créateur de la
blockchain. L'identité de cette personne peut être gardée secrète comme dans le cas des
Bitcoins. Ainsi, lorsque cette première transaction est créée, le créateur peut simplement envoyer
son identité en tant queGenesis. Ainsi, lors de la création du dictionnaire, nous vérifions si
l'expéditeur estGenesiset si c'est le cas, nous attribuons simplement une valeur de chaîne à la
variable d'identité; sinon, nous attribuons l'identité de l'expéditeur auidentity variable.

if self.sender == "Genesis":
identity = "Genesis"
else:
identity = self.sender.identity

Nous construisons le dictionnaire en utilisant la ligne de code suivante

return collections.OrderedDict({
'sender': identity,
'recipient': self.recipient,
'value': self.value,
'time' : self.time})

L'ensemble du code pour le to_dict méthode est montrée ci-dessous -

def to_dict(self):
if self.sender == "Genesis":
identity = "Genesis"
else:
identity = self.sender.identity

return collections.OrderedDict({
'sender': identity,
'recipient': self.recipient,
'value': self.value,
'time' : self.time})

Enfin, nous signerons cet objet dictionnaire en utilisant la clé privée de l'expéditeur. Comme
précédemment, nous utilisons la PKI intégrée avec l'algorithme SHA. La signature générée est
décodée pour obtenir la représentation ASCII pour l'impression et la stocker dans notre
blockchain. lesign_transaction le code de la méthode est affiché ici -

def sign_transaction(self):
private_key = self.sender._private_key
signer = PKCS1_v1_5.new(private_key)
h = SHA.new(str(self.to_dict()).encode('utf8'))
return binascii.hexlify(signer.sign(h)).decode('ascii')

Nous allons maintenant tester ceci Transaction classe.

Test de la classe de transaction


Pour cela, nous allons créer deux utilisateurs, appelés Dinesh et Ramesh. Dinesh enverra 5
TPCoins à Ramesh. Pour cela, nous créons les clients appelés Dinesh et Ramesh.

Dinesh = Client()
Ramesh = Client()

N'oubliez pas que lorsque vous instanciez un Client classe, le public anddes clés privées
uniques au client seraient créées. Comme Dinesh envoie le paiement à Ramesh, il aura besoin
de la clé publique de Ramesh qui est obtenue en utilisant la propriété d'identité du client.
Ainsi, nous allons créer l'instance de transaction en utilisant le code suivant -

t = Transaction(
Dinesh,
Ramesh.identity,
5.0
)

Notez que le premier paramètre est l'expéditeur, le deuxième paramètre est la clé publique du
destinataire et le troisième paramètre est le montant à transférer. lesign_transaction La
méthode récupère la clé privée de l'expéditeur à partir du premier paramètre pour chanter la
transaction.
Une fois l'objet de transaction créé, vous le signerez en appelant son sign_transactionméthode.
Cette méthode renvoie la signature générée au format imprimable. Nous générons et imprimons
la signature en utilisant les deux lignes de code suivantes -

signature = t.sign_transaction()
print (signature)

Lorsque vous exécutez le code ci-dessus, vous verrez la sortie similaire à celle-ci -

7c7e3c97629b218e9ec6e86b01f9abd8e361fd69e7d373c38420790b655b9abe3b575e343c7
13703ca1aee781acd7157a0624db3d57d7c2f1172730ee3f45af943338157f899965856f6b0
0e34db240b62673ad5a08c8e490f880b568efbc36035cae2e748f1d802d5e8e66298be826f5
c6363dc511222fb2416036ac04eb972

Maintenant que notre infrastructure de base de création d'un client et d'une transaction est prête,
nous aurons maintenant plusieurs clients effectuant plusieurs transactions comme dans une
situation réelle.
Créer plusieurs transactions
Les transactions effectuées par différents clients sont mises en file d'attente dans le système; les
mineurs récupèrent les transactions de cette file d'attente et les ajoutent au bloc. Ils exploiteront
ensuite le bloc et le mineur gagnant aurait le privilège d'ajouter le bloc à la blockchain et ainsi
gagner de l'argent pour lui-même.
Nous décrirons ce processus de minage plus tard lorsque nous discuterons de la création de la
blockchain. Avant d'écrire le code pour plusieurs transactions, ajoutons une petite fonction
utilitaire pour imprimer le contenu d'une transaction donnée.

Affichage de la transaction
le display_transactionLa fonction accepte un seul paramètre de type transaction. L'objet
dictionnaire dans la transaction reçue est copié dans une variable temporaire appeléedict et à
l'aide des touches de dictionnaire, les différentes valeurs sont imprimées sur la console.

def display_transaction(transaction):
#for transaction in transactions:
dict = transaction.to_dict()
print ("sender: " + dict['sender'])
print ('-----')
print ("recipient: " + dict['recipient'])
print ('-----')
print ("value: " + str(dict['value']))
print ('-----')
print ("time: " + str(dict['time']))
print ('-----')

Ensuite, nous définissons une file d'attente de transactions pour stocker nos objets de
transaction.

File d'attente de transaction


Pour créer une file d'attente, nous déclarons un global list variable appelée transactions comme
suit -

transactions = []

Nous ajouterons simplement chaque transaction nouvellement créée à cette file d'attente.
Veuillez noter que par souci de concision, nous n'implémenterons pas la logique de gestion des
files d'attente dans ce didacticiel.

Création de plusieurs clients


Maintenant, nous allons commencer à créer des transactions. Premièrement, nous allons créer
quatre clients qui s'enverront de l'argent pour obtenir divers services ou biens de tiers.
Dinesh = Client()
Ramesh = Client()
Seema = Client()
Vijay = Client()

À ce stade, nous avons quatre clients appelés Dinesh, Ramesh, Seema et Vijay. Nous
supposons actuellement que chacun de ces clients détient des TPCoins dans son portefeuille
pour effectuer des transactions. L'identité de chacun de ces clients serait spécifiée à l'aide de la
propriété d'identité de ces objets.

Création de la première transaction


Maintenant, nous lançons notre première transaction comme suit -

t1 = Transaction(
Dinesh,
Ramesh.identity,
15.0
)

Dans cette transaction, Dinesh envoie 5 TPCoins à Ramesh. Pour que la transaction réussisse,
nous devrons nous assurer que Dinesh a suffisamment d'argent dans son portefeuille pour ce
paiement. Notez que nous aurons besoin d'une transaction genesis pour démarrer la circulation
de TPCoin dans le système. Vous écrirez le code de transaction pour cette transaction de
genèse très rapidement au fur et à mesure que vous lirez.
Nous signerons cette transaction en utilisant la clé privée de Dinesh et l'ajouterons à la file
d'attente des transactions comme suit -

t1.sign_transaction()
transactions.append(t1)

Après la première transaction effectuée par Dinesh, nous créerons plusieurs autres transactions
entre différents clients que nous avons créées ci-dessus.

Ajouter plus de transactions


Nous allons maintenant créer plusieurs autres transactions, chaque transaction donnant
quelques TPCoins à une autre partie. Quand quelqu'un dépense de l'argent, il n'est pas
nécessaire qu'il doive vérifier les soldes suffisants dans ce portefeuille. De toute façon, le mineur
validerait chaque transaction pour le solde de l'expéditeur lors du lancement de la transaction.
En cas de solde insuffisant, le mineur marquera cette transaction comme invalide et ne l'ajoutera
pas à ce bloc.
Le code suivant crée et ajoute neuf autres transactions à notre file d'attente.

t2 = Transaction(
Dinesh,
Seema.identity,
6.0
)
t2.sign_transaction()
transactions.append(t2)
t3 = Transaction(
Ramesh,
Vijay.identity,
2.0
)
t3.sign_transaction()
transactions.append(t3)
t4 = Transaction(
Seema,
Ramesh.identity,
4.0
)
t4.sign_transaction()
transactions.append(t4)
t5 = Transaction(
Vijay,
Seema.identity,
7.0
)
t5.sign_transaction()
transactions.append(t5)
t6 = Transaction(
Ramesh,
Seema.identity,
3.0
)
t6.sign_transaction()
transactions.append(t6)
t7 = Transaction(
Seema,
Dinesh.identity,
8.0
)
t7.sign_transaction()
transactions.append(t7)
t8 = Transaction(
Seema,
Ramesh.identity,
1.0
)
t8.sign_transaction()
transactions.append(t8)
t9 = Transaction(
Vijay,
Dinesh.identity,
5.0
)
t9.sign_transaction()
transactions.append(t9)
t10 = Transaction(
Vijay,
Ramesh.identity,
3.0
)
t10.sign_transaction()
transactions.append(t10)

Lorsque vous exécutez le code ci-dessus, vous aurez dix transactions dans la file d'attente pour
que les mineurs créent leurs blocs.

Opérations de dumping
En tant que gestionnaire de blockchain, vous pouvez périodiquement souhaiter revoir le contenu
de la file d'attente de transactions. Pour cela, vous pouvez utiliser ledisplay_transactionfonction
que nous avons développée plus tôt. Pour vider toutes les transactions de la file d'attente, il suffit
d'itérer la liste des transactions et pour chaque transaction référencée, appelez
ledisplay_transaction fonction comme indiqué ici -

for transaction in transactions:


display_transaction (transaction)
print ('--------------')

Les transactions sont séparées par une ligne pointillée pour les distinguer. Si vous exécutez le
code ci-dessus, vous verrez la liste des transactions comme indiqué ci-dessous -

sender:
30819f300d06092a864886f70d010101050003818d0030818902818100bb064c99c49214
4a9f463480273aba93ac1db1f0da3cb9f3c1f9d058cf499fd8e54d244da0a8dd6ddd329e
c86794b04d773eb4841c9f935ea4d9ccc2821c7a1082d23b6c928d59863407f52fa05d8b
47e5157f8fe56c2ce3279c657f9c6a80500073b0be8093f748aef667c03e64f04f84d311
c4d866c12d79d3fc3034563dfb0203010001
-----
recipient:
30819f300d06092a864886f70d010101050003818d0030818902818100be93b516b28c6e
674abe7abdb11ce0fdf5bb728b75216b73f37a6432e4b402b3ad8139b8c0ba541a72c8ad
d126b6e1a1308fb98b727beb63c6060356bb177bb7d54b54dbe87aee7353d0a6baa93977
04de625d1836d3f42c7ee5683f6703259592cc24b09699376807f28fe0e00ff882974484
d805f874260dfc2d1627473b910203010001
-----
value: 15.0
-----
time: 2019-01-14 16:18:01.859915
-----
--------------
sender:
30819f300d06092a864886f70d010101050003818d0030818902818100bb064c99c49214
4a9f463480273aba93ac1db1f0da3cb9f3c1f9d058cf499fd8e54d244da0a8dd6ddd329e
c86794b04d773eb4841c9f935ea4d9ccc2821c7a1082d23b6c928d59863407f52fa05d8b
47e5157f8fe56c2ce3279c657f9c6a80500073b0be8093f748aef667c03e64f04f84d311
c4d866c12d79d3fc3034563dfb0203010001
-----
recipient:
30819f300d06092a864886f70d010101050003818d0030818902818100a070c82b34ae14
3cbe59b3a2afde7186e9d5bc274955d8112d87a00256a35369acc4d0edfe65e8f9dc93fb
d9ee74b9e7ea12334da38c8c9900e6ced1c4ce93f86e06611e656521a1eab561892b7db0
961b4f212d1fd5b5e49ae09cf8c603a068f9b723aa8a651032ff6f24e5de00387e4d0623
75799742a359b8f22c5362e5650203010001
-----
value: 6.0
-----
time: 2019-01-14 16:18:01.860966
-----
--------------
sender:
30819f300d06092a864886f70d010101050003818d0030818902818100be93b516b28c6e
674abe7abdb11ce0fdf5bb728b75216b73f37a6432e4b402b3ad8139b8c0ba541a72c8ad
d126b6e1a1308fb98b727beb63c6060356bb177bb7d54b54dbe87aee7353d0a6baa93977
04de625d1836d3f42c7ee5683f6703259592cc24b09699376807f28fe0e00ff882974484
d805f874260dfc2d1627473b910203010001
-----
recipient:
30819f300d06092a864886f70d010101050003818d0030818902818100cba097c0854876
f41338c62598c658f545182cfa4acebce147aedf328181f9c4930f14498fd03c0af6b0cc
e25be99452a81df4fa30a53eddbb7bb7b203adf8764a0ccd9db6913a576d68d642d8fd47
452590137869c25d9ff83d68ebe6d616056a8425b85b52e69715b8b85ae807b84638d8f0
0e321b65e4c33acaf6469e18e30203010001
-----
value: 2.0
-----
time: 2019-01-14 16:18:01.861958
-----
--------------

Par souci de concision, je n'ai imprimé que les premières transactions de la liste. Dans le code ci-
dessus, nous imprimons toutes les transactions commençant par la toute première transaction à
l'exception de la transaction genesis qui n'a jamais été ajoutée à cette liste. Comme les
transactions sont ajoutées périodiquement aux blocs, vous serez généralement intéressé à
afficher uniquement la liste des transactions qui doivent encore être exploitées. Dans ce cas,
vous devrez créer un fichier appropriéfor boucle pour parcourir les transactions qui ne sont pas
encore minées.
Jusqu'à présent, vous avez appris à créer des clients, à les laisser entre eux et à maintenir une
file d'attente des transactions en attente qui doivent être exploitées. Maintenant, vient la partie la
plus importante de ce tutoriel et c'est la création d'une blockchain elle-même. Vous apprendrez
cela dans la prochaine leçon.

Blockchain Python - Classe de blocs


Un bloc se compose d'un nombre variable de transactions. Pour simplifier, dans notre cas, nous
supposerons que le bloc est constitué d'un nombre fixe de transactions, qui est de trois dans ce
cas. Comme le bloc a besoin de stocker la liste de ces trois transactions, nous déclarerons une
variable d'instance appeléeverified_transactions comme suit -

self.verified_transactions = []

Nous avons nommé cette variable comme verified_transactionspour indiquer que seules les
transactions valides vérifiées seront ajoutées au bloc. Chaque bloc contient également la valeur
de hachage du bloc précédent, de sorte que la chaîne de blocs devient immuable.
Pour stocker le hachage précédent, nous déclarons une variable d'instance comme suit -

self.previous_block_hash = ""

Enfin, nous déclarons une autre variable appelée Nonce pour stocker le nonce créé par le
mineur pendant le processus d'extraction.

self.Nonce = ""

La définition complète du Block la classe est donnée ci-dessous -

class Block:
def __init__(self):
self.verified_transactions = []
self.previous_block_hash = ""
self.Nonce = ""

Comme chaque bloc a besoin de la valeur du hachage du bloc précédent, nous déclarons une
variable globale appelée last_block_hash comme suit -

last_block_hash = ""

Créons maintenant notre premier bloc dans la blockchain.

Python Blockchain - Création d'un bloc


Genesis
Nous supposons que l'auteur des TPCoins distribue initialement 500 TPCoins à un client
connu Dinesh. Pour cela, il crée d'abord une instance Dinesh -

Dinesh = Client()

Nous créons ensuite une transaction genesis et envoyons 500 TPCoins à l'adresse publique de
Dinesh.

t0 = Transaction (
"Genesis",
Dinesh.identity,
500.0
)

Maintenant, nous créons une instance de Block classe et appelle-le block0.

block0 = Block()

Nous initialisons le previous_block_hash et Nonce variables d'instance à None, car il s'agit de


la toute première transaction à être stockée dans notre blockchain.

block0.previous_block_hash = None
Nonce = None

Ensuite, nous ajouterons la transaction t0 ci-dessus au verified_transactions liste maintenue


dans le bloc -

block0.verified_transactions.append (t0)

À ce stade, le bloc est complètement initialisé et est prêt à être ajouté à notre blockchain. Nous
allons créer la blockchain à cet effet. Avant d'ajouter le bloc à la blockchain, nous allons hacher le
bloc et stocker sa valeur dans la variable globale appeléelast_block_hashque nous avons
déclaré précédemment. Cette valeur sera utilisée par le prochain mineur de son bloc.
Nous utilisons les deux lignes de codage suivantes pour hacher le bloc et stocker la valeur de
résumé.

digest = hash (block0)


last_block_hash = digest

Enfin, nous créons une blockchain comme nous le verrons dans le chapitre suivant.

Python Création de Blockchain


Une blockchain contient une liste de blocs enchaînés les uns aux autres. Pour stocker la liste
entière, nous allons créer une variable de liste appelée TPCoins -

TPCoins = []

Nous écrirons également une méthode utilitaire appelée dump_blockchainpour vider le contenu
de la blockchain entière. Nous imprimons d'abord la longueur de la blockchain afin de savoir
combien de blocs sont actuellement présents dans la blockchain.

def dump_blockchain (self):


print ("Number of blocks in the chain: " + str(len (self)))

Notez qu'avec le temps, le nombre de blocs dans la blockchain serait extraordinairement élevé
pour l'impression. Ainsi, lorsque vous imprimez le contenu de la blockchain, vous devrez peut-
être décider de la plage que vous souhaitez examiner. Dans le code ci-dessous, nous avons
imprimé la blockchain entière car nous n'ajouterions pas trop de blocs dans la démo actuelle.
Pour parcourir la chaîne, nous avons mis en place un for boucle comme suit -
for x in range (len(TPCoins)):
block_temp = TPCoins[x]

Chaque bloc référencé est copié dans une variable temporaire appelée block_temp.
Nous imprimons le numéro de bloc comme en-tête pour chaque bloc. Notez que les nombres
commenceraient par zéro, le premier bloc est un bloc de genèse numéroté zéro.

print ("block # " + str(x))

Dans chaque bloc, nous avons stocké une liste de trois transactions (à l'exception du bloc
genesis) dans une variable appelée verified_transactions. Nous itérons cette liste dans
unfor boucle et pour chaque élément récupéré, nous appelons display_transaction fonction
pour afficher les détails de la transaction.

for transaction in block_temp.verified_transactions:


display_transaction (transaction)

La définition complète de la fonction est présentée ci-dessous -

def dump_blockchain (self):


print ("Number of blocks in the chain: " + str(len (self)))
for x in range (len(TPCoins)):
block_temp = TPCoins[x]
print ("block # " + str(x))
for transaction in block_temp.verified_transactions:
display_transaction (transaction)
print ('--------------')
print ('=====================================')

Notez qu'ici nous avons inséré les séparateurs aux points appropriés dans le code pour délimiter
les blocs et les transactions qu'il contient.
Comme nous avons maintenant créé une blockchain pour stocker des blocs, notre tâche suivante
est de créer des blocs et de commencer à les ajouter à la blockchain. Pour cela, nous ajouterons
un bloc de genèse que vous avez déjà créé à l'étape précédente.

Python Blockchain - Ajout d'un bloc


Genesis
L'ajout d'un bloc à la blockchain implique l'ajout du bloc créé à notre TPCoins liste.

TPCoins.append (block0)

Notez que contrairement au reste des blocs du système, le bloc genesis ne contient qu'une seule
transaction qui est initiée par l'expéditeur du système TPCoins. Maintenant, vous allez vider le
contenu de la blockchain en appelant notre fonction globaledump_blockchain -
dump_blockchain(TPCoins)

Lorsque vous exécutez cette fonction, vous verrez la sortie suivante -

Number of blocks in the chain: 1


block # 0
sender: Genesis
-----
recipient:
30819f300d06092a864886f70d010101050003818d0030818902818100ed272b52ccb539
e2cd779c6cc10ed1dfadf5d97c6ab6de90ed0372b2655626fb79f62d0e01081c163b0864
cc68d426bbe9438e8566303bb77414d4bfcaa3468ab7febac099294de10273a816f7047d
4087b4bafa11f141544d48e2f10b842cab91faf33153900c7bf6c08c9e47a7df8aa7e60d
c9e0798fb2ba3484bbdad2e4430203010001
-----
value: 500.0
-----
time: 2019-01-14 16:18:02.042739
-----
--------------
=====================================

À ce stade, le système blockchain est prêt à être utilisé. Nous allons maintenant permettre aux
clients intéressés de devenir des mineurs en leur fournissant une fonctionnalité de minage.

Blockchain Python - Création de mineurs


Pour permettre l'exploitation minière, nous devons développer une fonction minière. La
fonctionnalité d'exploration de données doit générer un résumé sur une chaîne de message
donnée et fournir une preuve de travail. Discutons-en dans ce chapitre.

Fonction de résumé de message


Nous écrirons une fonction utilitaire appelée sha256 pour créer un condensé sur un message
donné -

def sha256(message):
return hashlib.sha256(message.encode('ascii')).hexdigest()

le sha256 fonction prend un message en tant que paramètre, l'encode en ASCII, génère un
condensé hexadécimal et renvoie la valeur à l'appelant.

Fonction minière
Nous développons maintenant le minefonction qui met en œuvre notre propre stratégie minière.
Notre stratégie dans ce cas serait de générer un hachage sur le message donné qui est préfixé
avec un nombre donné de 1. Le nombre donné de 1 est spécifié comme paramètre
pourmine fonction spécifiée comme niveau de difficulté.
Par exemple, si vous spécifiez un niveau de difficulté de 2, le hachage généré sur un message
donné doit commencer par deux 1 - comme 11xxxxxxxx. Si le niveau de difficulté est 3, le
hachage généré doit commencer par trois 1 - comme 111xxxxxxxx. Compte tenu de ces
exigences, nous allons maintenant développer la fonction d'extraction comme indiqué dans les
étapes ci-dessous.

Étape 1
La fonction d'exploration de données prend deux paramètres - le message et le niveau de
difficulté.

def mine(message, difficulty=1):

Étape 2
Le niveau de difficulté doit être supérieur ou égal à 1, nous nous en assurons avec la déclaration
d'assertion suivante -

assert difficulty >= 1

Étape 3
Nous créons un prefix variable en utilisant le niveau de difficulté défini.

prefix = '1' * difficulty

Notez que si le niveau de difficulté est 2, le préfixe sera «11» et si le niveau de difficulté est 3, le
préfixe sera «111», et ainsi de suite. Nous vérifierons si ce préfixe existe dans le résumé généré
du message. Pour digérer le message lui-même, nous utilisons les deux lignes de code suivantes
-

for i in range(1000):
digest = sha256(str(hash(message)) + str(i))

Nous continuons d'ajouter un nouveau numéro iau hachage du message à chaque itération et
générer un nouveau condensé sur le message combiné. En tant qu'entrée dusha256 fonction
change à chaque itération, le digestla valeur changerait également. Nous vérifions si
celadigest la valeur a dépassé prefix.

if digest.startswith(prefix):

Si la condition est remplie, nous mettrons fin au for boucle et retourne le digest valeur pour
l'appelant.
L'ensemble mine le code est affiché ici -
def mine(message, difficulty=1):
assert difficulty >= 1
prefix = '1' * difficulty
for i in range(1000):
digest = sha256(str(hash(message)) + str(i))
if digest.startswith(prefix):
print ("after " + str(i) + " iterations found nonce: "+ digest)
return digest

Pour votre compréhension, nous avons ajouté le print instruction qui imprime la valeur de
résumé et le nombre d'itérations nécessaires pour remplir la condition avant de revenir de la
fonction.

Test de la fonction minière


Pour tester notre fonction d'exploration de données, exécutez simplement l'instruction suivante -

mine ("test message", 2)

Lorsque vous exécutez le code ci-dessus, vous verrez la sortie similaire à celle ci-dessous -

after 138 iterations found nonce:


11008a740eb2fa6bf8d55baecda42a41993ca65ce66b2d3889477e6bfad1484c

Notez que le résumé généré commence par «11». Si vous changez le niveau de difficulté à 3, le
résumé généré commencera par «111», et bien sûr, il nécessitera probablement plus d'itérations.
Comme vous pouvez le voir, un mineur avec plus de puissance de traitement pourra extraire un
message donné plus tôt. C'est ainsi que les mineurs se font concurrence pour gagner leurs
revenus.
Maintenant, nous sommes prêts à ajouter plus de blocs à notre blockchain. Apprenons cela dans
notre prochain chapitre.

Blockchain Python - Ajout de blocs


Chaque mineur récupérera les transactions d'un pool de transactions précédemment créé. Pour
suivre le nombre de messages déjà extraits, nous devons créer une variable globale -

last_transaction_index = 0

Nous allons maintenant demander à notre premier mineur d'ajouter un bloc à la blockchain.

Ajout du premier bloc


Pour ajouter un nouveau bloc, nous créons d'abord une instance du Block classe.

block = Block()

Nous récupérons les 3 principales transactions de la file d'attente -


for i in range(3):
temp_transaction = transactions[last_transaction_index]
# validate transaction

Avant d'ajouter la transaction au bloc, le mineur vérifiera la validité de la transaction. La validité


de la transaction est vérifiée en testant l'égalité du hachage fourni par l'expéditeur par rapport au
hachage généré par le mineur à l'aide de la clé publique de l'expéditeur. En outre, le mineur
vérifiera que l'expéditeur dispose d'un solde suffisant pour payer la transaction en cours.
Par souci de concision, nous n'avons pas inclus cette fonctionnalité dans le didacticiel. Une fois
la transaction validée, nous l'ajoutons auverified_transactions liste dans le block exemple.

block.verified_transactions.append (temp_transaction)

Nous incrémentons le dernier index de transaction afin que le prochain mineur récupère les
transactions suivantes dans la file d'attente.

last_transaction_index += 1

Nous ajoutons exactement trois transactions au bloc. Une fois cela fait, nous initialiserons le reste
des variables d'instance duBlockclasse. Nous ajoutons d'abord le hachage du dernier bloc.

block.previous_block_hash = last_block_hash

Ensuite, nous exploitons le bloc avec un niveau de difficulté de 2.

block.Nonce = mine (block, 2)

Notez que le premier paramètre du minefunction est un objet binaire. Nous hachons maintenant
le bloc entier et créons un condensé dessus.

digest = hash (block)

Enfin, nous ajoutons le bloc créé à la blockchain et réinitialisons la variable


globale last_block_hash pour l'utilisation dans le bloc suivant.
Le code complet pour ajouter le bloc est montré ci-dessous -

block = Block()
for i in range(3):
temp_transaction = transactions[last_transaction_index]
# validate transaction
# if valid
block.verified_transactions.append (temp_transaction)
last_transaction_index += 1

block.previous_block_hash = last_block_hash
block.Nonce = mine (block, 2)
digest = hash (block)
TPCoins.append (block)
last_block_hash = digest

Ajouter plus de blocs


Nous allons maintenant ajouter deux blocs supplémentaires à notre blockchain. Le code pour
ajouter les deux blocs suivants est donné ci-dessous -

# Miner 2 adds a block


block = Block()

for i in range(3):
temp_transaction = transactions[last_transaction_index]
# validate transaction
# if valid
block.verified_transactions.append (temp_transaction)
last_transaction_index += 1
block.previous_block_hash = last_block_hash
block.Nonce = mine (block, 2)digest = hash (block)
TPCoins.append (block)last_block_hash = digest
# Miner 3 adds a block
block = Block()

for i in range(3):
temp_transaction = transactions[last_transaction_index]
#display_transaction (temp_transaction)
# validate transaction
# if valid
block.verified_transactions.append (temp_transaction)
last_transaction_index += 1

block.previous_block_hash = last_block_hash
block.Nonce = mine (block, 2)
digest = hash (block)

TPCoins.append (block)
last_block_hash = digest

Lorsque vous ajoutez ces deux blocs, vous verrez également le nombre d'itérations nécessaires
pour trouver le Nonce. À ce stade, notre blockchain se compose au total de 4 blocs, y compris le
bloc de genèse.

Décharger la blockchain entière


Vous pouvez vérifier le contenu de l'ensemble de la blockchain en utilisant la déclaration suivante
-

dump_blockchain(TPCoins)

Vous verriez la sortie similaire à celle illustrée ci-dessous -

Number of blocks in the chain: 4


block # 0
sender: Genesis
-----
recipient:
30819f300d06092a864886f70d010101050003818d0030818902818100ed272b52ccb539e2c
d779
c6cc10ed1dfadf5d97c6ab6de90ed0372b2655626fb79f62d0e01081c163b0864cc68d426bb
e943
8e8566303bb77414d4bfcaa3468ab7febac099294de10273a816f7047d4087b4bafa11f1415
44d4
8e2f10b842cab91faf33153900c7bf6c08c9e47a7df8aa7e60dc9e0798fb2ba3484bbdad2e4
4302
03010001
-----
value: 500.0
-----
time: 2019-01-14 16:18:02.042739
-----
--------------
=====================================
block # 1
sender:
30819f300d06092a864886f70d010101050003818d0030818902818100bb064c99c492144a9
f463
480273aba93ac1db1f0da3cb9f3c1f9d058cf499fd8e54d244da0a8dd6ddd329ec86794b04d
773e
b4841c9f935ea4d9ccc2821c7a1082d23b6c928d59863407f52fa05d8b47e5157f8fe56c2ce
3279
c657f9c6a80500073b0be8093f748aef667c03e64f04f84d311c4d866c12d79d3fc3034563d
fb02
03010001
-----
recipient:
30819f300d06092a864886f70d010101050003818d0030818902818100be93b516b28c6e674
abe7
abdb11ce0fdf5bb728b75216b73f37a6432e4b402b3ad8139b8c0ba541a72c8add126b6e1a1
308f
b98b727beb63c6060356bb177bb7d54b54dbe87aee7353d0a6baa9397704de625d1836d3f42
c7ee
5683f6703259592cc24b09699376807f28fe0e00ff882974484d805f874260dfc2d1627473b
9102
03010001
-----
value: 15.0
-----
time: 2019-01-14 16:18:01.859915
-----
--------------
sender:
30819f300d06092a864886f70d010101050003818d0030818902818100bb064c99c492144a9
f463
480273aba93ac1db1f0da3cb9f3c1f9d058cf499fd8e54d244da0a8dd6ddd329ec86794b04d
773e
b4841c9f935ea4d9ccc2821c7a1082d23b6c928d59863407f52fa05d8b47e5157f8fe56c2ce
3279
c657f9c6a80500073b0be8093f748aef667c03e64f04f84d311c4d866c12d79d3fc3034563d
fb02
03010001
-----
recipient:
30819f300d06092a864886f70d010101050003818d0030818902818100a070c82b34ae143cb
e59b
3a2afde7186e9d5bc274955d8112d87a00256a35369acc4d0edfe65e8f9dc93fbd9ee74b9e7
ea12
334da38c8c9900e6ced1c4ce93f86e06611e656521a1eab561892b7db0961b4f212d1fd5b5e
49ae
09cf8c603a068f9b723aa8a651032ff6f24e5de00387e4d062375799742a359b8f22c5362e5
6502
03010001
-----
value: 6.0
-----
time: 2019-01-14 16:18:01.860966
-----
--------------
sender:
30819f300d06092a864886f70d010101050003818d0030818902818100be93b516b28c6e674
abe7
abdb11ce0fdf5bb728b75216b73f37a6432e4b402b3ad8139b8c0ba541a72c8add126b6e1a1
308f
b98b727beb63c6060356bb177bb7d54b54dbe87aee7353d0a6baa9397704de625d1836d3f42
c7ee
5683f6703259592cc24b09699376807f28fe0e00ff882974484d805f874260dfc2d1627473b
9102
03010001
-----
recipient:
30819f300d06092a864886f70d010101050003818d0030818902818100cba097c0854876f41
338c
62598c658f545182cfa4acebce147aedf328181f9c4930f14498fd03c0af6b0cce25be99452
a81d
f4fa30a53eddbb7bb7b203adf8764a0ccd9db6913a576d68d642d8fd47452590137869c25d9
ff83
d68ebe6d616056a8425b85b52e69715b8b85ae807b84638d8f00e321b65e4c33acaf6469e18
e302
03010001
-----
value: 2.0
-----
time: 2019-01-14 16:18:01.861958
-----
--------------
=====================================
block # 2
sender:
30819f300d06092a864886f70d010101050003818d0030818902818100a070c82b34ae143cb
e59b
3a2afde7186e9d5bc274955d8112d87a00256a35369acc4d0edfe65e8f9dc93fbd9ee74b9e7
ea12
334da38c8c9900e6ced1c4ce93f86e06611e656521a1eab561892b7db0961b4f212d1fd5b5e
49ae
09cf8c603a068f9b723aa8a651032ff6f24e5de00387e4d062375799742a359b8f22c5362e5
6502
03010001
-----
recipient:
30819f300d06092a864886f70d010101050003818d0030818902818100be93b516b28c6e674
abe7
abdb11ce0fdf5bb728b75216b73f37a6432e4b402b3ad8139b8c0ba541a72c8add126b6e1a1
308f
b98b727beb63c6060356bb177bb7d54b54dbe87aee7353d0a6baa9397704de625d1836d3f42
c7ee
5683f6703259592cc24b09699376807f28fe0e00ff882974484d805f874260dfc2d1627473b
9102
03010001
-----
value: 4.0
-----
time: 2019-01-14 16:18:01.862946
-----
--------------
sender:
30819f300d06092a864886f70d010101050003818d0030818902818100cba097c0854876f41
338c
62598c658f545182cfa4acebce147aedf328181f9c4930f14498fd03c0af6b0cce25be99452
a81d
f4fa30a53eddbb7bb7b203adf8764a0ccd9db6913a576d68d642d8fd47452590137869c25d9
ff83
d68ebe6d616056a8425b85b52e69715b8b85ae807b84638d8f00e321b65e4c33acaf6469e18
e302
03010001
-----
recipient:
30819f300d06092a864886f70d010101050003818d0030818902818100a070c82b34ae143cb
e59b
3a2afde7186e9d5bc274955d8112d87a00256a35369acc4d0edfe65e8f9dc93fbd9ee74b9e7
ea12
334da38c8c9900e6ced1c4ce93f86e06611e656521a1eab561892b7db0961b4f212d1fd5b5e
49ae
09cf8c603a068f9b723aa8a651032ff6f24e5de00387e4d062375799742a359b8f22c5362e5
6502
03010001
-----
value: 7.0
-----
time: 2019-01-14 16:18:01.863932
-----
--------------
sender:
30819f300d06092a864886f70d010101050003818d0030818902818100be93b516b28c6e674
abe7
abdb11ce0fdf5bb728b75216b73f37a6432e4b402b3ad8139b8c0ba541a72c8add126b6e1a1
308f
b98b727beb63c6060356bb177bb7d54b54dbe87aee7353d0a6baa9397704de625d1836d3f42
c7ee
5683f6703259592cc24b09699376807f28fe0e00ff882974484d805f874260dfc2d1627473b
9102
03010001
-----
recipient:
30819f300d06092a864886f70d010101050003818d0030818902818100a070c82b34ae143cb
e59b
3a2afde7186e9d5bc274955d8112d87a00256a35369acc4d0edfe65e8f9dc93fbd9ee74b9e7
ea12
334da38c8c9900e6ced1c4ce93f86e06611e656521a1eab561892b7db0961b4f212d1fd5b5e
49ae
09cf8c603a068f9b723aa8a651032ff6f24e5de00387e4d062375799742a359b8f22c5362e5
6502
03010001
-----
value: 3.0
-----
time: 2019-01-14 16:18:01.865099
-----
--------------
=====================================
block # 3
sender:
30819f300d06092a864886f70d010101050003818d0030818902818100a070c82b34ae143cb
e59b
3a2afde7186e9d5bc274955d8112d87a00256a35369acc4d0edfe65e8f9dc93fbd9ee74b9e7
ea12
334da38c8c9900e6ced1c4ce93f86e06611e656521a1eab561892b7db0961b4f212d1fd5b5e
49ae
09cf8c603a068f9b723aa8a651032ff6f24e5de00387e4d062375799742a359b8f22c5362e5
6502
03010001
-----
recipient:
30819f300d06092a864886f70d010101050003818d0030818902818100bb064c99c492144a9
f463
480273aba93ac1db1f0da3cb9f3c1f9d058cf499fd8e54d244da0a8dd6ddd329ec86794b04d
773e
b4841c9f935ea4d9ccc2821c7a1082d23b6c928d59863407f52fa05d8b47e5157f8fe56c2ce
3279
c657f9c6a80500073b0be8093f748aef667c03e64f04f84d311c4d866c12d79d3fc3034563d
fb02
03010001
-----
value: 8.0
-----
time: 2019-01-14 16:18:01.866219
-----
--------------
sender:
30819f300d06092a864886f70d010101050003818d0030818902818100a070c82b34ae143cb
e59b
3a2afde7186e9d5bc274955d8112d87a00256a35369acc4d0edfe65e8f9dc93fbd9ee74b9e7
ea12
334da38c8c9900e6ced1c4ce93f86e06611e656521a1eab561892b7db0961b4f212d1fd5b5e
49ae
09cf8c603a068f9b723aa8a651032ff6f24e5de00387e4d062375799742a359b8f22c5362e5
6502
03010001
-----
recipient:
30819f300d06092a864886f70d010101050003818d0030818902818100be93b516b28c6e674
abe7
abdb11ce0fdf5bb728b75216b73f37a6432e4b402b3ad8139b8c0ba541a72c8add126b6e1a1
308f
b98b727beb63c6060356bb177bb7d54b54dbe87aee7353d0a6baa9397704de625d1836d3f42
c7ee
5683f6703259592cc24b09699376807f28fe0e00ff882974484d805f874260dfc2d1627473b
9102
03010001
-----
value: 1.0
-----
time: 2019-01-14 16:18:01.867223
-----
--------------
sender:
30819f300d06092a864886f70d010101050003818d0030818902818100cba097c0854876f41
338c
62598c658f545182cfa4acebce147aedf328181f9c4930f14498fd03c0af6b0cce25be99452
a81d
f4fa30a53eddbb7bb7b203adf8764a0ccd9db6913a576d68d642d8fd47452590137869c25d9
ff83
d68ebe6d616056a8425b85b52e69715b8b85ae807b84638d8f00e321b65e4c33acaf6469e18
e302
03010001
-----
recipient:
30819f300d06092a864886f70d010101050003818d0030818902818100bb064c99c492144a9
f463
480273aba93ac1db1f0da3cb9f3c1f9d058cf499fd8e54d244da0a8dd6ddd329ec86794b04d
773e
b4841c9f935ea4d9ccc2821c7a1082d23b6c928d59863407f52fa05d8b47e5157f8fe56c2ce
3279
c657f9c6a80500073b0be8093f748aef667c03e64f04f84d311c4d866c12d79d3fc3034563d
fb02
03010001
-----
value: 5.0
-----
time: 2019-01-14 16:18:01.868241
-----
--------------
=====================================

Blockchain Python - Portée et conclusion


Dans ce tutoriel, nous avons appris à construire un projet blockchain en Python. Il existe de
nombreux domaines dans lesquels vous devez ajouter des fonctionnalités supplémentaires à ce
projet.
Par exemple, vous devrez écrire des fonctions pour gérer la file d'attente des transactions. Une
fois les transactions minées et le bloc miné accepté par le système, elles n'ont plus besoin d'être
stockées.
En outre, les mineurs préféreraient certainement récupérer les transactions avec les frais les plus
élevés. Dans le même temps, vous devrez vous assurer que les transactions avec des frais
faibles ou sans frais ne mourront pas de faim pour toujours.
Vous devrez développer des algorithmes pour gérer la file d'attente. En outre, le didacticiel actuel
n'inclut pas le code de l'interface client. Vous devrez développer cela pour les clients normaux et
les mineurs. Le projet de blockchain à part entière se heurterait à plusieurs autres lignes de code
et dépasse le cadre de ce didacticiel. Le lecteur intéressé peut télécharger la source Bitcoin pour
une étude plus approfondie.

Conclusions
Ce didacticiel précis devrait vous aider à créer votre propre projet de blockchain.
Pour le développement de projets blockchain à part entière, vous pouvez en apprendre
davantage sur la source Bitcoin .
Pour les projets commerciaux ou non commerciaux plus importants, vous pouvez envisager
d'utiliser Ethereum - une plate-forme d'application blockchain prête à l'emploi.

ICHI.PRO
Blockchain Python - Guide rapide
Dans le tutoriel sur la blockchain, nous avons appris en détail la théorie derrière la blockchain. La
blockchain est la pierre angulaire de la monnaie numérique Bitcoin la plus populaire au monde. Le
didacticiel traitait en profondeur des subtilités de Bitcoin en expliquant pleinement l'architecture de
la blockchain. La prochaine étape consiste à créer notre propre blockchain.
Satoshi Nakamoto a créé la première monnaie virtuelle au monde appelée Bitcoin. En regardant le
succès de Bitcoin, beaucoup d'autres ont créé leurs propres monnaies virtuelles. Pour n'en
nommer que quelques-uns - Litecoin, Zcash, etc.
Maintenant, vous pouvez également lancer votre propre devise. Appelons cela comme TPCoin
(TutorialsPoint Coin). Vous écrirez une blockchain pour enregistrer toutes les transactions qui
traitent de TPCoin. Le TPCoin peut être utilisé pour acheter des pizzas, des hamburgers, des
salades, etc. Les possibilités sont infinies.
Dans ce tutoriel, laissez-nous comprendre comment construire un tel système et lancer votre
propre monnaie numérique sur le marché.

Composants impliqués dans le développement de


projets Blockchain
L'ensemble du développement du projet blockchain se compose de trois composants principaux -
 Client
 Miners
 Blockchain

Client
Le client est celui qui achètera des marchandises auprès d'autres vendeurs. Le client lui-même
peut devenir un vendeur et acceptera de l'argent d'autrui contre les marchandises qu'il fournit.
Nous supposons ici que le client peut à la fois être un fournisseur et un destinataire de TPCoins.
Ainsi, nous allons créer une classe de client dans notre code qui a la capacité d'envoyer et de
recevoir de l'argent.

Mineur
Le mineur est celui qui récupère les transactions d'un pool de transactions et les assemble dans un
bloc. Le mineur doit fournir une preuve de travail valide pour obtenir la récompense minière. Tout
l'argent que le mineur perçoit à titre de redevance lui appartiendra. Il peut dépenser cet argent pour
acheter des biens ou des services auprès d'autres fournisseurs enregistrés sur le réseau, comme
le fait un client décrit ci-dessus.

Blockchain
Enfin, une Blockchain est une structure de données qui enchaîne tous les blocs extraits dans un
ordre chronologique. Cette chaîne est immuable et donc résistante aux intempéries.
Vous pouvez suivre ce didacticiel en tapant le code présenté à chaque étape dans un nouveau
bloc-notes Jupyter. Vous pouvez également télécharger l'intégralité du notebook Jupyter
sur www.anaconda.com .
Dans le prochain chapitre, nous développerons un client qui utilise notre système blockchain.
Un client est une personne qui détient des TPCoins et qui les transige contre des biens / services
d'autres fournisseurs sur le réseau, y compris le sien. Nous devrions définir unClientclasse à cet
effet. Pour créer une identification unique au monde pour le client, nous utilisons PKI (Public Key
Infrastructure). Dans ce chapitre, parlons-en en détail.
Le client doit pouvoir envoyer de l'argent de son portefeuille à une autre personne connue. De
même, le client doit pouvoir accepter de l'argent d'un tiers. Pour dépenser de l'argent, le client
créerait une transaction spécifiant le nom de l'expéditeur et le montant à payer. Pour recevoir de
l'argent, le client fournira son identité au tiers - essentiellement un expéditeur de l'argent. Nous ne
stockons pas le solde d'argent que le client détient dans son portefeuille. Lors d'une transaction,
nous calculerons le solde réel pour nous assurer que le client dispose d'un solde suffisant pour
effectuer le paiement.
Pour développer le Clientclasse et pour le reste du code du projet, nous devrons importer de
nombreuses bibliothèques Python. Ceux-ci sont énumérés ci-dessous -

# import libraries
import hashlib
import random
import string
import json
import binascii
import numpy as np
import pandas as pd
import pylab as pl
import logging
import datetime
import collections

En plus des bibliothèques standard ci-dessus, nous allons signer nos transactions, créer le
hachage des objets, etc. Pour cela, vous devrez importer les bibliothèques suivantes -

# following imports are required by PKI


import Crypto
import Crypto.Random
from Crypto.Hash import SHA
from Crypto.PublicKey import RSA
from Crypto.Signature import PKCS1_v1_5

Dans le chapitre suivant, parlons de la classe client.


le Client classe génère le private et public clés en utilisant le Python intégré RSAalgorithme. Le
lecteur intéressé peut se référer àthis tutorialpour la mise en œuvre de RSA. Lors de l'initialisation
de l'objet, nous créons des clés privées et publiques et stockons leurs valeurs dans la variable
d'instance.

self._private_key = RSA.generate(1024, random)


self._public_key = self._private_key.publickey()

Notez que vous ne devez jamais perdre votre clé privée. Pour la tenue de registres, la clé privée
générée peut être copiée sur un stockage externe sécurisé ou vous pouvez simplement écrire la
représentation ASCII de celle-ci sur un morceau de papier.
Le généré publicLa clé sera utilisée comme identité du client. Pour cela, nous définissons une
propriété appeléeidentity qui renvoie la représentation HEX de la clé publique.

@property
def identity(self):
return
binascii.hexlify(self._public_key.exportKey(format='DER'))
.decode('ascii')

le identityest unique à chaque client et peut être rendu public. N'importe qui pourrait vous envoyer
de la monnaie virtuelle en utilisant ceidentity et il sera ajouté à votre portefeuille.
Le code complet du Client la classe est affichée ici -

class Client:
def __init__(self):
random = Crypto.Random.new().read
self._private_key = RSA.generate(1024, random)
self._public_key = self._private_key.publickey()
self._signer = PKCS1_v1_5.new(self._private_key)

@property
def identity(self):
return
binascii.hexlify(self._public_key.exportKey(format='DER')).decode('ascii')

Client de test
Maintenant, nous allons écrire du code qui illustrera comment utiliser le Client classe -

Dinesh = Client()
print (Dinesh.identity)

Le code ci-dessus crée une instance de Client et l'affecte à la variable Dinesh. Nous imprimons la
clé publique deDinesh en appelant son identityméthode. La sortie est affichée ici -
30819f300d06092a864886f70d010101050003818d0030818902818100b547fafceeb131e07
0166a6b23fec473cce22c3f55c35ce535b31d4c74754fecd820aa94c1166643a49ea5f49f72
3181ff943eb3fdc5b2cb2db12d21c06c880ccf493e14dd3e93f3a9e175325790004954c34d3
c7bc2ccc9f0eb5332014937f9e49bca9b7856d351a553d9812367dc8f2ac734992a4e6a6ff6
6f347bd411d07f0203010001

Maintenant, nous allons passer à la création d'une transaction dans le chapitre suivant.
Dans ce chapitre, créons un Transactionclasse afin qu'un client puisse envoyer de l'argent à
quelqu'un. Notez qu'un client peut être à la fois un expéditeur ou un destinataire de l'argent.
Lorsque vous souhaitez recevoir de l'argent, un autre expéditeur crée une transaction et spécifie
votrepublicadresse dedans. Nous définissons l'initialisation d'une classe de transaction comme
suit -

def __init__(self, sender, recipient, value):


self.sender = sender
self.recipient = recipient
self.value = value
self.time = datetime.datetime.now()

le init La méthode prend trois paramètres - l'expéditeur public clé, le destinataire publicet le
montant à envoyer. Ceux-ci sont stockés dans les variables d'instance pour être utilisés par
d'autres méthodes. De plus, nous créons une autre variable pour stocker l'heure de la transaction.
Ensuite, nous écrivons une méthode utilitaire appelée to_dictqui combine les quatre variables
d'instance mentionnées ci-dessus dans un objet dictionnaire. Il s'agit simplement de mettre toutes
les informations de transaction accessibles via une seule variable.
Comme vous le savez dans le tutoriel précédent, le premier bloc de la blockchain est
un Genesisbloquer. Le bloc Genesis contient la première transaction initiée par le créateur de la
blockchain. L'identité de cette personne peut être gardée secrète comme dans le cas des Bitcoins.
Ainsi, lorsque cette première transaction est créée, le créateur peut simplement envoyer son
identité en tant queGenesis. Ainsi, lors de la création du dictionnaire, nous vérifions si l'expéditeur
estGenesiset si c'est le cas, nous attribuons simplement une valeur de chaîne à la variable
d'identité; sinon, nous attribuons l'identité de l'expéditeur auidentity variable.

if self.sender == "Genesis":
identity = "Genesis"
else:
identity = self.sender.identity

Nous construisons le dictionnaire en utilisant la ligne de code suivante

return collections.OrderedDict({
'sender': identity,
'recipient': self.recipient,
'value': self.value,
'time' : self.time})

L'ensemble du code pour le to_dict méthode est montrée ci-dessous -

def to_dict(self):
if self.sender == "Genesis":
identity = "Genesis"
else:
identity = self.sender.identity

return collections.OrderedDict({
'sender': identity,
'recipient': self.recipient,
'value': self.value,
'time' : self.time})

Enfin, nous signerons cet objet dictionnaire en utilisant la clé privée de l'expéditeur. Comme
précédemment, nous utilisons la PKI intégrée avec l'algorithme SHA. La signature générée est
décodée pour obtenir la représentation ASCII pour l'impression et la stocker dans notre blockchain.
lesign_transaction le code de la méthode est affiché ici -

def sign_transaction(self):
private_key = self.sender._private_key
signer = PKCS1_v1_5.new(private_key)
h = SHA.new(str(self.to_dict()).encode('utf8'))
return binascii.hexlify(signer.sign(h)).decode('ascii')

Nous allons maintenant tester ceci Transaction classe.

Test de la classe de transaction


Pour cela, nous allons créer deux utilisateurs, appelés Dinesh et Ramesh. Dinesh enverra 5
TPCoins à Ramesh. Pour cela, nous créons les clients appelés Dinesh et Ramesh.

Dinesh = Client()
Ramesh = Client()

N'oubliez pas que lorsque vous instanciez un Client classe, le public anddes clés privées uniques
au client seraient créées. Comme Dinesh envoie le paiement à Ramesh, il aura besoin de la clé
publique de Ramesh qui est obtenue en utilisant la propriété d'identité du client.
Ainsi, nous allons créer l'instance de transaction en utilisant le code suivant -

t = Transaction(
Dinesh,
Ramesh.identity,
5.0
)

Notez que le premier paramètre est l'expéditeur, le deuxième paramètre est la clé publique du
destinataire et le troisième paramètre est le montant à transférer. lesign_transaction La méthode
récupère la clé privée de l'expéditeur à partir du premier paramètre pour chanter la transaction.
Une fois l'objet de transaction créé, vous le signerez en appelant son sign_transactionméthode.
Cette méthode renvoie la signature générée au format imprimable. Nous générons et imprimons la
signature en utilisant les deux lignes de code suivantes -

signature = t.sign_transaction()
print (signature)

Lorsque vous exécutez le code ci-dessus, vous verrez la sortie similaire à celle-ci -

7c7e3c97629b218e9ec6e86b01f9abd8e361fd69e7d373c38420790b655b9abe3b575e343c7
13703ca1aee781acd7157a0624db3d57d7c2f1172730ee3f45af943338157f899965856f6b0
0e34db240b62673ad5a08c8e490f880b568efbc36035cae2e748f1d802d5e8e66298be826f5
c6363dc511222fb2416036ac04eb972

Maintenant que notre infrastructure de base de création d'un client et d'une transaction est prête,
nous aurons maintenant plusieurs clients effectuant plusieurs transactions comme dans une
situation réelle.
Les transactions effectuées par différents clients sont mises en file d'attente dans le système; les
mineurs récupèrent les transactions de cette file d'attente et les ajoutent au bloc. Ils exploiteront
ensuite le bloc et le mineur gagnant aurait le privilège d'ajouter le bloc à la blockchain et ainsi
gagner de l'argent pour lui-même.
Nous décrirons ce processus de minage plus tard lorsque nous discuterons de la création de la
blockchain. Avant d'écrire le code pour plusieurs transactions, ajoutons une petite fonction utilitaire
pour imprimer le contenu d'une transaction donnée.

Affichage de la transaction
le display_transactionLa fonction accepte un seul paramètre de type transaction. L'objet
dictionnaire dans la transaction reçue est copié dans une variable temporaire appeléedict et à
l'aide des touches de dictionnaire, les différentes valeurs sont imprimées sur la console.

def display_transaction(transaction):
#for transaction in transactions:
dict = transaction.to_dict()
print ("sender: " + dict['sender'])
print ('-----')
print ("recipient: " + dict['recipient'])
print ('-----')
print ("value: " + str(dict['value']))
print ('-----')
print ("time: " + str(dict['time']))
print ('-----')

Ensuite, nous définissons une file d'attente de transactions pour stocker nos objets de transaction.

File d'attente de transaction


Pour créer une file d'attente, nous déclarons un global list variable appelée transactions comme
suit -

transactions = []

Nous ajouterons simplement chaque transaction nouvellement créée à cette file d'attente. Veuillez
noter que par souci de concision, nous n'implémenterons pas la logique de gestion des files
d'attente dans ce tutoriel.

Création de plusieurs clients


Maintenant, nous allons commencer à créer des transactions. Premièrement, nous allons créer
quatre clients qui s'enverront de l'argent pour obtenir divers services ou biens de tiers.

Dinesh = Client()
Ramesh = Client()
Seema = Client()
Vijay = Client()

À ce stade, nous avons quatre clients appelés Dinesh, Ramesh, Seema et Vijay. Nous supposons
actuellement que chacun de ces clients détient des TPCoins dans son portefeuille pour effectuer
des transactions. L'identité de chacun de ces clients serait spécifiée à l'aide de la propriété
d'identité de ces objets.

Création de la première transaction


Maintenant, nous lançons notre première transaction comme suit -

t1 = Transaction(
Dinesh,
Ramesh.identity,
15.0
)

Dans cette transaction, Dinesh envoie 5 TPCoins à Ramesh. Pour que la transaction réussisse,
nous devrons nous assurer que Dinesh a suffisamment d'argent dans son portefeuille pour ce
paiement. Notez que nous aurons besoin d'une transaction genesis pour démarrer la circulation de
TPCoin dans le système. Vous écrirez le code de transaction pour cette transaction de genèse très
rapidement au fur et à mesure que vous lirez.
Nous signerons cette transaction en utilisant la clé privée de Dinesh et l'ajouterons à la file
d'attente des transactions comme suit -

t1.sign_transaction()
transactions.append(t1)

Après la première transaction effectuée par Dinesh, nous créerons plusieurs autres transactions
entre différents clients que nous avons créées ci-dessus.

Ajouter plus de transactions


Nous allons maintenant créer plusieurs autres transactions, chaque transaction donnant quelques
TPCoins à une autre partie. Quand quelqu'un dépense de l'argent, il n'est pas nécessaire qu'il
doive vérifier les soldes suffisants dans ce portefeuille. De toute façon, le mineur validerait chaque
transaction pour le solde de l'expéditeur lors du lancement de la transaction.
En cas de solde insuffisant, le mineur marquera cette transaction comme invalide et ne l'ajoutera
pas à ce bloc.
Le code suivant crée et ajoute neuf autres transactions à notre file d'attente.

t2 = Transaction(
Dinesh,
Seema.identity,
6.0
)
t2.sign_transaction()
transactions.append(t2)
t3 = Transaction(
Ramesh,
Vijay.identity,
2.0
)
t3.sign_transaction()
transactions.append(t3)
t4 = Transaction(
Seema,
Ramesh.identity,
4.0
)
t4.sign_transaction()
transactions.append(t4)
t5 = Transaction(
Vijay,
Seema.identity,
7.0
)
t5.sign_transaction()
transactions.append(t5)
t6 = Transaction(
Ramesh,
Seema.identity,
3.0
)
t6.sign_transaction()
transactions.append(t6)
t7 = Transaction(
Seema,
Dinesh.identity,
8.0
)
t7.sign_transaction()
transactions.append(t7)
t8 = Transaction(
Seema,
Ramesh.identity,
1.0
)
t8.sign_transaction()
transactions.append(t8)
t9 = Transaction(
Vijay,
Dinesh.identity,
5.0
)
t9.sign_transaction()
transactions.append(t9)
t10 = Transaction(
Vijay,
Ramesh.identity,
3.0
)
t10.sign_transaction()
transactions.append(t10)

Lorsque vous exécutez le code ci-dessus, vous aurez dix transactions dans la file d'attente pour
que les mineurs créent leurs blocs.

Opérations de dumping
En tant que gestionnaire de blockchain, vous pouvez périodiquement souhaiter revoir le contenu
de la file d'attente de transactions. Pour cela, vous pouvez utiliser ledisplay_transactionfonction
que nous avons développée plus tôt. Pour vider toutes les transactions de la file d'attente, il suffit
d'itérer la liste des transactions et pour chaque transaction référencée, appelez
ledisplay_transaction fonction comme indiqué ici -

for transaction in transactions:


display_transaction (transaction)
print ('--------------')

Les transactions sont séparées par une ligne pointillée pour les distinguer. Si vous exécutez le
code ci-dessus, vous verrez la liste des transactions comme indiqué ci-dessous -

sender:
30819f300d06092a864886f70d010101050003818d0030818902818100bb064c99c49214
4a9f463480273aba93ac1db1f0da3cb9f3c1f9d058cf499fd8e54d244da0a8dd6ddd329e
c86794b04d773eb4841c9f935ea4d9ccc2821c7a1082d23b6c928d59863407f52fa05d8b
47e5157f8fe56c2ce3279c657f9c6a80500073b0be8093f748aef667c03e64f04f84d311
c4d866c12d79d3fc3034563dfb0203010001
-----
recipient:
30819f300d06092a864886f70d010101050003818d0030818902818100be93b516b28c6e
674abe7abdb11ce0fdf5bb728b75216b73f37a6432e4b402b3ad8139b8c0ba541a72c8ad
d126b6e1a1308fb98b727beb63c6060356bb177bb7d54b54dbe87aee7353d0a6baa93977
04de625d1836d3f42c7ee5683f6703259592cc24b09699376807f28fe0e00ff882974484
d805f874260dfc2d1627473b910203010001
-----
value: 15.0
-----
time: 2019-01-14 16:18:01.859915
-----
--------------
sender:
30819f300d06092a864886f70d010101050003818d0030818902818100bb064c99c49214
4a9f463480273aba93ac1db1f0da3cb9f3c1f9d058cf499fd8e54d244da0a8dd6ddd329e
c86794b04d773eb4841c9f935ea4d9ccc2821c7a1082d23b6c928d59863407f52fa05d8b
47e5157f8fe56c2ce3279c657f9c6a80500073b0be8093f748aef667c03e64f04f84d311
c4d866c12d79d3fc3034563dfb0203010001
-----
recipient:
30819f300d06092a864886f70d010101050003818d0030818902818100a070c82b34ae14
3cbe59b3a2afde7186e9d5bc274955d8112d87a00256a35369acc4d0edfe65e8f9dc93fb
d9ee74b9e7ea12334da38c8c9900e6ced1c4ce93f86e06611e656521a1eab561892b7db0
961b4f212d1fd5b5e49ae09cf8c603a068f9b723aa8a651032ff6f24e5de00387e4d0623
75799742a359b8f22c5362e5650203010001
-----
value: 6.0
-----
time: 2019-01-14 16:18:01.860966
-----
--------------
sender:
30819f300d06092a864886f70d010101050003818d0030818902818100be93b516b28c6e
674abe7abdb11ce0fdf5bb728b75216b73f37a6432e4b402b3ad8139b8c0ba541a72c8ad
d126b6e1a1308fb98b727beb63c6060356bb177bb7d54b54dbe87aee7353d0a6baa93977
04de625d1836d3f42c7ee5683f6703259592cc24b09699376807f28fe0e00ff882974484
d805f874260dfc2d1627473b910203010001
-----
recipient:
30819f300d06092a864886f70d010101050003818d0030818902818100cba097c0854876
f41338c62598c658f545182cfa4acebce147aedf328181f9c4930f14498fd03c0af6b0cc
e25be99452a81df4fa30a53eddbb7bb7b203adf8764a0ccd9db6913a576d68d642d8fd47
452590137869c25d9ff83d68ebe6d616056a8425b85b52e69715b8b85ae807b84638d8f0
0e321b65e4c33acaf6469e18e30203010001
-----
value: 2.0
-----
time: 2019-01-14 16:18:01.861958
-----
--------------

Par souci de concision, je n'ai imprimé que les premières transactions de la liste. Dans le code ci-
dessus, nous imprimons toutes les transactions commençant par la toute première transaction à
l'exception de la transaction genesis qui n'a jamais été ajoutée à cette liste. Comme les
transactions sont ajoutées périodiquement aux blocs, vous serez généralement intéressé à afficher
uniquement la liste des transactions qui doivent encore être exploitées. Dans ce cas, vous devrez
créer un fichier appropriéfor boucle pour parcourir les transactions qui ne sont pas encore minées.
Jusqu'à présent, vous avez appris à créer des clients, à les laisser entre eux et à maintenir une file
d'attente des transactions en attente qui doivent être exploitées. Maintenant, vient la partie la plus
importante de ce tutoriel et c'est la création d'une blockchain elle-même. Vous apprendrez cela
dans la prochaine leçon.
Un bloc se compose d'un nombre variable de transactions. Pour simplifier, dans notre cas, nous
supposerons que le bloc est constitué d'un nombre fixe de transactions, qui est de trois dans ce
cas. Comme le bloc a besoin de stocker la liste de ces trois transactions, nous déclarerons une
variable d'instance appeléeverified_transactions comme suit -

self.verified_transactions = []

Nous avons nommé cette variable comme verified_transactionspour indiquer que seules les
transactions valides vérifiées seront ajoutées au bloc. Chaque bloc contient également la valeur de
hachage du bloc précédent, de sorte que la chaîne de blocs devient immuable.
Pour stocker le hachage précédent, nous déclarons une variable d'instance comme suit -

self.previous_block_hash = ""

Enfin, nous déclarons une autre variable appelée Nonce pour stocker le nonce créé par le mineur
pendant le processus d'extraction.

self.Nonce = ""

La définition complète du Block la classe est donnée ci-dessous -

class Block:
def __init__(self):
self.verified_transactions = []
self.previous_block_hash = ""
self.Nonce = ""

Comme chaque bloc a besoin de la valeur du hachage du bloc précédent, nous déclarons une
variable globale appelée last_block_hash comme suit -
last_block_hash = ""

Créons maintenant notre premier bloc dans la blockchain.


Nous supposons que l'auteur des TPCoins donne initialement 500 TPCoins à un client
connu Dinesh. Pour cela, il crée d'abord une instance Dinesh -

Dinesh = Client()

Nous créons ensuite une transaction genesis et envoyons 500 TPCoins à l'adresse publique de
Dinesh.

t0 = Transaction (
"Genesis",
Dinesh.identity,
500.0
)

Maintenant, nous créons une instance de Block classe et appelle-le block0.

block0 = Block()

Nous initialisons le previous_block_hash et Nonce variables d'instance à None, car il s'agit de la


toute première transaction à être stockée dans notre blockchain.

block0.previous_block_hash = None
Nonce = None

Ensuite, nous ajouterons la transaction t0 ci-dessus au verified_transactions liste maintenue


dans le bloc -

block0.verified_transactions.append (t0)

À ce stade, le bloc est complètement initialisé et est prêt à être ajouté à notre blockchain. Nous
allons créer la blockchain à cet effet. Avant d'ajouter le bloc à la blockchain, nous allons hacher le
bloc et stocker sa valeur dans la variable globale appeléelast_block_hashque nous avons déclaré
précédemment. Cette valeur sera utilisée par le prochain mineur de son bloc.
Nous utilisons les deux lignes de codage suivantes pour hacher le bloc et stocker la valeur de
résumé.

digest = hash (block0)


last_block_hash = digest

Enfin, nous créons une blockchain comme nous le verrons dans le chapitre suivant.
Une blockchain contient une liste de blocs enchaînés les uns aux autres. Pour stocker la liste
entière, nous allons créer une variable de liste appelée TPCoins -

TPCoins = []
Nous écrirons également une méthode utilitaire appelée dump_blockchainpour vider le contenu
de la blockchain entière. Nous imprimons d'abord la longueur de la blockchain afin de savoir
combien de blocs sont actuellement présents dans la blockchain.

def dump_blockchain (self):


print ("Number of blocks in the chain: " + str(len (self)))

Notez qu'avec le temps, le nombre de blocs dans la blockchain serait extraordinairement élevé
pour l'impression. Ainsi, lorsque vous imprimez le contenu de la blockchain, vous devrez peut-être
décider de la plage que vous souhaitez examiner. Dans le code ci-dessous, nous avons imprimé la
blockchain entière car nous n'ajouterions pas trop de blocs dans la démo actuelle.
Pour parcourir la chaîne, nous avons mis en place un for boucle comme suit -

for x in range (len(TPCoins)):


block_temp = TPCoins[x]

Chaque bloc référencé est copié dans une variable temporaire appelée block_temp.
Nous imprimons le numéro de bloc comme en-tête pour chaque bloc. Notez que les nombres
commenceraient par zéro, le premier bloc est un bloc de genèse numéroté zéro.

print ("block # " + str(x))

Dans chaque bloc, nous avons stocké une liste de trois transactions (à l'exception du bloc genesis)
dans une variable appelée verified_transactions. Nous itérons cette liste dans unfor boucle et
pour chaque élément récupéré, nous appelons display_transaction fonction pour afficher les
détails de la transaction.

for transaction in block_temp.verified_transactions:


display_transaction (transaction)

La définition complète de la fonction est présentée ci-dessous -

def dump_blockchain (self):


print ("Number of blocks in the chain: " + str(len (self)))
for x in range (len(TPCoins)):
block_temp = TPCoins[x]
print ("block # " + str(x))
for transaction in block_temp.verified_transactions:
display_transaction (transaction)
print ('--------------')
print ('=====================================')

Notez qu'ici nous avons inséré les séparateurs aux points appropriés dans le code pour délimiter
les blocs et les transactions qu'il contient.
Comme nous avons maintenant créé une blockchain pour stocker des blocs, notre tâche suivante
est de créer des blocs et de commencer à les ajouter à la blockchain. Pour cela, nous ajouterons
un bloc de genèse que vous avez déjà créé à l'étape précédente.
L'ajout d'un bloc à la blockchain implique l'ajout du bloc créé à notre TPCoins liste.

TPCoins.append (block0)

Notez que contrairement au reste des blocs du système, le bloc genesis ne contient qu'une seule
transaction qui est initiée par l'expéditeur du système TPCoins. Maintenant, vous allez vider le
contenu de la blockchain en appelant notre fonction globaledump_blockchain -

dump_blockchain(TPCoins)

Lorsque vous exécutez cette fonction, vous verrez la sortie suivante -

Number of blocks in the chain: 1


block # 0
sender: Genesis
-----
recipient:
30819f300d06092a864886f70d010101050003818d0030818902818100ed272b52ccb539
e2cd779c6cc10ed1dfadf5d97c6ab6de90ed0372b2655626fb79f62d0e01081c163b0864
cc68d426bbe9438e8566303bb77414d4bfcaa3468ab7febac099294de10273a816f7047d
4087b4bafa11f141544d48e2f10b842cab91faf33153900c7bf6c08c9e47a7df8aa7e60d
c9e0798fb2ba3484bbdad2e4430203010001
-----
value: 500.0
-----
time: 2019-01-14 16:18:02.042739
-----
--------------
=====================================

À ce stade, le système blockchain est prêt à être utilisé. Nous allons maintenant permettre aux
clients intéressés de devenir des mineurs en leur fournissant une fonctionnalité de minage.
Pour permettre l'exploitation minière, nous devons développer une fonction minière. La
fonctionnalité d'exploration de données doit générer un résumé sur une chaîne de message
donnée et fournir une preuve de travail. Discutons-en dans ce chapitre.

Fonction de résumé de message


Nous écrirons une fonction utilitaire appelée sha256 pour créer un condensé sur un message
donné -

def sha256(message):
return hashlib.sha256(message.encode('ascii')).hexdigest()
le sha256 fonction prend un message en tant que paramètre, l'encode en ASCII, génère un
condensé hexadécimal et renvoie la valeur à l'appelant.

Fonction minière
Nous développons maintenant le minefonction qui met en œuvre notre propre stratégie minière.
Notre stratégie dans ce cas serait de générer un hachage sur le message donné qui est préfixé
avec un nombre donné de 1. Le nombre donné de 1 est spécifié comme paramètre
pourmine fonction spécifiée comme niveau de difficulté.
Par exemple, si vous spécifiez un niveau de difficulté de 2, le hachage généré sur un message
donné doit commencer par deux 1 - comme 11xxxxxxxx. Si le niveau de difficulté est 3, le hachage
généré doit commencer par trois 1 - comme 111xxxxxxxx. Compte tenu de ces exigences, nous
allons maintenant développer la fonction d'extraction comme indiqué dans les étapes ci-dessous.

Étape 1
La fonction d'exploration de données prend deux paramètres - le message et le niveau de
difficulté.

def mine(message, difficulty=1):

Étape 2
Le niveau de difficulté doit être supérieur ou égal à 1, nous nous en assurons avec la déclaration
d'assertion suivante -

assert difficulty >= 1

Étape 3
Nous créons un prefix variable en utilisant le niveau de difficulté défini.

prefix = '1' * difficulty

Notez que si le niveau de difficulté est 2, le préfixe sera «11» et si le niveau de difficulté est 3, le
préfixe sera «111», et ainsi de suite. Nous vérifierons si ce préfixe existe dans le résumé généré
du message. Pour digérer le message lui-même, nous utilisons les deux lignes de code suivantes -

for i in range(1000):
digest = sha256(str(hash(message)) + str(i))

Nous continuons d'ajouter un nouveau numéro iau hachage du message à chaque itération et
générer un nouveau condensé sur le message combiné. En tant qu'entrée dusha256 fonction
change à chaque itération, le digestla valeur changerait également. Nous vérifions si celadigest la
valeur a dépassé prefix.

if digest.startswith(prefix):
Si la condition est remplie, nous mettrons fin au for boucle et retourne le digest valeur pour
l'appelant.
L'ensemble mine le code est affiché ici -

def mine(message, difficulty=1):


assert difficulty >= 1
prefix = '1' * difficulty
for i in range(1000):
digest = sha256(str(hash(message)) + str(i))
if digest.startswith(prefix):
print ("after " + str(i) + " iterations found nonce: "+ digest)
return digest

Pour votre compréhension, nous avons ajouté le print instruction qui imprime la valeur de résumé
et le nombre d'itérations nécessaires pour remplir la condition avant de revenir de la fonction.

Test de la fonction minière


Pour tester notre fonction d'exploration de données, exécutez simplement l'instruction suivante -

mine ("test message", 2)

Lorsque vous exécutez le code ci-dessus, vous verrez la sortie similaire à celle ci-dessous -

after 138 iterations found nonce:


11008a740eb2fa6bf8d55baecda42a41993ca65ce66b2d3889477e6bfad1484c

Notez que le résumé généré commence par «11». Si vous changez le niveau de difficulté à 3, le
résumé généré commencera par «111», et bien sûr, il nécessitera probablement plus d'itérations.
Comme vous pouvez le voir, un mineur avec plus de puissance de traitement pourra extraire un
message donné plus tôt. C'est ainsi que les mineurs se font concurrence pour gagner leurs
revenus.
Maintenant, nous sommes prêts à ajouter plus de blocs à notre blockchain. Apprenons cela dans
notre prochain chapitre.
Chaque mineur récupérera les transactions d'un pool de transactions précédemment créé. Pour
suivre le nombre de messages déjà extraits, nous devons créer une variable globale -

last_transaction_index = 0

Nous allons maintenant demander à notre premier mineur d'ajouter un bloc à la blockchain.

Ajout du premier bloc


Pour ajouter un nouveau bloc, nous créons d'abord une instance du Block classe.

block = Block()
Nous récupérons les 3 principales transactions de la file d'attente -

for i in range(3):
temp_transaction = transactions[last_transaction_index]
# validate transaction

Avant d'ajouter la transaction au bloc, le mineur vérifiera la validité de la transaction. La validité de


la transaction est vérifiée en testant l'égalité du hachage fourni par l'expéditeur par rapport au
hachage généré par le mineur à l'aide de la clé publique de l'expéditeur. En outre, le mineur
vérifiera que l'expéditeur dispose d'un solde suffisant pour payer la transaction en cours.
Par souci de concision, nous n'avons pas inclus cette fonctionnalité dans le didacticiel. Une fois la
transaction validée, nous l'ajoutons auverified_transactions liste dans le block exemple.

block.verified_transactions.append (temp_transaction)

Nous incrémentons le dernier index de transaction afin que le prochain mineur récupère les
transactions suivantes dans la file d'attente.

last_transaction_index += 1

Nous ajoutons exactement trois transactions au bloc. Une fois cela fait, nous initialiserons le reste
des variables d'instance duBlockclasse. Nous ajoutons d'abord le hachage du dernier bloc.

block.previous_block_hash = last_block_hash

Ensuite, nous exploitons le bloc avec un niveau de difficulté de 2.

block.Nonce = mine (block, 2)

Notez que le premier paramètre du minefunction est un objet binaire. Nous hachons maintenant le
bloc entier et créons un condensé dessus.

digest = hash (block)

Enfin, nous ajoutons le bloc créé à la blockchain et réinitialisons la variable


globale last_block_hash pour l'utilisation dans le bloc suivant.
Le code complet pour ajouter le bloc est montré ci-dessous -

block = Block()
for i in range(3):
temp_transaction = transactions[last_transaction_index]
# validate transaction
# if valid
block.verified_transactions.append (temp_transaction)
last_transaction_index += 1

block.previous_block_hash = last_block_hash
block.Nonce = mine (block, 2)
digest = hash (block)
TPCoins.append (block)
last_block_hash = digest

Ajouter plus de blocs


Nous allons maintenant ajouter deux blocs supplémentaires à notre blockchain. Le code pour
ajouter les deux blocs suivants est donné ci-dessous -

# Miner 2 adds a block


block = Block()

for i in range(3):
temp_transaction = transactions[last_transaction_index]
# validate transaction
# if valid
block.verified_transactions.append (temp_transaction)
last_transaction_index += 1
block.previous_block_hash = last_block_hash
block.Nonce = mine (block, 2)digest = hash (block)
TPCoins.append (block)last_block_hash = digest
# Miner 3 adds a block
block = Block()

for i in range(3):
temp_transaction = transactions[last_transaction_index]
#display_transaction (temp_transaction)
# validate transaction
# if valid
block.verified_transactions.append (temp_transaction)
last_transaction_index += 1

block.previous_block_hash = last_block_hash
block.Nonce = mine (block, 2)
digest = hash (block)
TPCoins.append (block)
last_block_hash = digest

Lorsque vous ajoutez ces deux blocs, vous verrez également le nombre d'itérations nécessaires
pour trouver le Nonce. À ce stade, notre blockchain se compose au total de 4 blocs, y compris le
bloc de genèse.

Décharger la blockchain entière


Vous pouvez vérifier le contenu de l'ensemble de la blockchain en utilisant la déclaration suivante -

dump_blockchain(TPCoins)

Vous verriez la sortie similaire à celle illustrée ci-dessous -

Number of blocks in the chain: 4


block # 0
sender: Genesis
-----
recipient:
30819f300d06092a864886f70d010101050003818d0030818902818100ed272b52ccb539e2cd
779
c6cc10ed1dfadf5d97c6ab6de90ed0372b2655626fb79f62d0e01081c163b0864cc68d426bbe
943
8e8566303bb77414d4bfcaa3468ab7febac099294de10273a816f7047d4087b4bafa11f14154
4d4
8e2f10b842cab91faf33153900c7bf6c08c9e47a7df8aa7e60dc9e0798fb2ba3484bbdad2e44
302
03010001
-----
value: 500.0
-----
time: 2019-01-14 16:18:02.042739
-----
--------------
=====================================
block # 1
sender:
30819f300d06092a864886f70d010101050003818d0030818902818100bb064c99c492144a9f
463
480273aba93ac1db1f0da3cb9f3c1f9d058cf499fd8e54d244da0a8dd6ddd329ec86794b04d7
73e
b4841c9f935ea4d9ccc2821c7a1082d23b6c928d59863407f52fa05d8b47e5157f8fe56c2ce3
279
c657f9c6a80500073b0be8093f748aef667c03e64f04f84d311c4d866c12d79d3fc3034563df
b02
03010001
-----
recipient:
30819f300d06092a864886f70d010101050003818d0030818902818100be93b516b28c6e674a
be7
abdb11ce0fdf5bb728b75216b73f37a6432e4b402b3ad8139b8c0ba541a72c8add126b6e1a13
08f
b98b727beb63c6060356bb177bb7d54b54dbe87aee7353d0a6baa9397704de625d1836d3f42c
7ee
5683f6703259592cc24b09699376807f28fe0e00ff882974484d805f874260dfc2d1627473b9
102
03010001
-----
value: 15.0
-----
time: 2019-01-14 16:18:01.859915
-----
--------------
sender:
30819f300d06092a864886f70d010101050003818d0030818902818100bb064c99c492144a9f
463
480273aba93ac1db1f0da3cb9f3c1f9d058cf499fd8e54d244da0a8dd6ddd329ec86794b04d7
73e
b4841c9f935ea4d9ccc2821c7a1082d23b6c928d59863407f52fa05d8b47e5157f8fe56c2ce3
279
c657f9c6a80500073b0be8093f748aef667c03e64f04f84d311c4d866c12d79d3fc3034563df
b02
03010001
-----
recipient:
30819f300d06092a864886f70d010101050003818d0030818902818100a070c82b34ae143cbe
59b
3a2afde7186e9d5bc274955d8112d87a00256a35369acc4d0edfe65e8f9dc93fbd9ee74b9e7e
a12
334da38c8c9900e6ced1c4ce93f86e06611e656521a1eab561892b7db0961b4f212d1fd5b5e4
9ae
09cf8c603a068f9b723aa8a651032ff6f24e5de00387e4d062375799742a359b8f22c5362e56
502
03010001
-----
value: 6.0
-----
time: 2019-01-14 16:18:01.860966
-----
--------------
sender:
30819f300d06092a864886f70d010101050003818d0030818902818100be93b516b28c6e674a
be7
abdb11ce0fdf5bb728b75216b73f37a6432e4b402b3ad8139b8c0ba541a72c8add126b6e1a13
08f
b98b727beb63c6060356bb177bb7d54b54dbe87aee7353d0a6baa9397704de625d1836d3f42c
7ee
5683f6703259592cc24b09699376807f28fe0e00ff882974484d805f874260dfc2d1627473b9
102
03010001
-----
recipient:
30819f300d06092a864886f70d010101050003818d0030818902818100cba097c0854876f413
38c
62598c658f545182cfa4acebce147aedf328181f9c4930f14498fd03c0af6b0cce25be99452a
81d
f4fa30a53eddbb7bb7b203adf8764a0ccd9db6913a576d68d642d8fd47452590137869c25d9f
f83
d68ebe6d616056a8425b85b52e69715b8b85ae807b84638d8f00e321b65e4c33acaf6469e18e
302
03010001
-----
value: 2.0
-----
time: 2019-01-14 16:18:01.861958
-----
--------------
=====================================
block # 2
sender:
30819f300d06092a864886f70d010101050003818d0030818902818100a070c82b34ae143cbe
59b
3a2afde7186e9d5bc274955d8112d87a00256a35369acc4d0edfe65e8f9dc93fbd9ee74b9e7e
a12
334da38c8c9900e6ced1c4ce93f86e06611e656521a1eab561892b7db0961b4f212d1fd5b5e4
9ae
09cf8c603a068f9b723aa8a651032ff6f24e5de00387e4d062375799742a359b8f22c5362e56
502
03010001
-----
recipient:
30819f300d06092a864886f70d010101050003818d0030818902818100be93b516b28c6e674a
be7
abdb11ce0fdf5bb728b75216b73f37a6432e4b402b3ad8139b8c0ba541a72c8add126b6e1a13
08f
b98b727beb63c6060356bb177bb7d54b54dbe87aee7353d0a6baa9397704de625d1836d3f42c
7ee
5683f6703259592cc24b09699376807f28fe0e00ff882974484d805f874260dfc2d1627473b9
102
03010001
-----
value: 4.0
-----
time: 2019-01-14 16:18:01.862946
-----
--------------
sender:
30819f300d06092a864886f70d010101050003818d0030818902818100cba097c0854876f413
38c
62598c658f545182cfa4acebce147aedf328181f9c4930f14498fd03c0af6b0cce25be99452a
81d
f4fa30a53eddbb7bb7b203adf8764a0ccd9db6913a576d68d642d8fd47452590137869c25d9f
f83
d68ebe6d616056a8425b85b52e69715b8b85ae807b84638d8f00e321b65e4c33acaf6469e18e
302
03010001
-----
recipient:
30819f300d06092a864886f70d010101050003818d0030818902818100a070c82b34ae143cbe
59b
3a2afde7186e9d5bc274955d8112d87a00256a35369acc4d0edfe65e8f9dc93fbd9ee74b9e7e
a12
334da38c8c9900e6ced1c4ce93f86e06611e656521a1eab561892b7db0961b4f212d1fd5b5e4
9ae
09cf8c603a068f9b723aa8a651032ff6f24e5de00387e4d062375799742a359b8f22c5362e56
502
03010001
-----
value: 7.0
-----
time: 2019-01-14 16:18:01.863932
-----
--------------
sender:
30819f300d06092a864886f70d010101050003818d0030818902818100be93b516b28c6e674a
be7
abdb11ce0fdf5bb728b75216b73f37a6432e4b402b3ad8139b8c0ba541a72c8add126b6e1a13
08f
b98b727beb63c6060356bb177bb7d54b54dbe87aee7353d0a6baa9397704de625d1836d3f42c
7ee
5683f6703259592cc24b09699376807f28fe0e00ff882974484d805f874260dfc2d1627473b9
102
03010001
-----
recipient:
30819f300d06092a864886f70d010101050003818d0030818902818100a070c82b34ae143cbe
59b
3a2afde7186e9d5bc274955d8112d87a00256a35369acc4d0edfe65e8f9dc93fbd9ee74b9e7e
a12
334da38c8c9900e6ced1c4ce93f86e06611e656521a1eab561892b7db0961b4f212d1fd5b5e4
9ae
09cf8c603a068f9b723aa8a651032ff6f24e5de00387e4d062375799742a359b8f22c5362e56
502
03010001
-----
value: 3.0
-----
time: 2019-01-14 16:18:01.865099
-----
--------------
=====================================
block # 3
sender:
30819f300d06092a864886f70d010101050003818d0030818902818100a070c82b34ae143cbe
59b
3a2afde7186e9d5bc274955d8112d87a00256a35369acc4d0edfe65e8f9dc93fbd9ee74b9e7e
a12
334da38c8c9900e6ced1c4ce93f86e06611e656521a1eab561892b7db0961b4f212d1fd5b5e4
9ae
09cf8c603a068f9b723aa8a651032ff6f24e5de00387e4d062375799742a359b8f22c5362e56
502
03010001
-----
recipient:
30819f300d06092a864886f70d010101050003818d0030818902818100bb064c99c492144a9f
463
480273aba93ac1db1f0da3cb9f3c1f9d058cf499fd8e54d244da0a8dd6ddd329ec86794b04d7
73e
b4841c9f935ea4d9ccc2821c7a1082d23b6c928d59863407f52fa05d8b47e5157f8fe56c2ce3
279
c657f9c6a80500073b0be8093f748aef667c03e64f04f84d311c4d866c12d79d3fc3034563df
b02
03010001
-----
value: 8.0
-----
time: 2019-01-14 16:18:01.866219
-----
--------------
sender:
30819f300d06092a864886f70d010101050003818d0030818902818100a070c82b34ae143cbe
59b
3a2afde7186e9d5bc274955d8112d87a00256a35369acc4d0edfe65e8f9dc93fbd9ee74b9e7e
a12
334da38c8c9900e6ced1c4ce93f86e06611e656521a1eab561892b7db0961b4f212d1fd5b5e4
9ae
09cf8c603a068f9b723aa8a651032ff6f24e5de00387e4d062375799742a359b8f22c5362e56
502
03010001
-----
recipient:
30819f300d06092a864886f70d010101050003818d0030818902818100be93b516b28c6e674a
be7
abdb11ce0fdf5bb728b75216b73f37a6432e4b402b3ad8139b8c0ba541a72c8add126b6e1a13
08f
b98b727beb63c6060356bb177bb7d54b54dbe87aee7353d0a6baa9397704de625d1836d3f42c
7ee
5683f6703259592cc24b09699376807f28fe0e00ff882974484d805f874260dfc2d1627473b9
102
03010001
-----
value: 1.0
-----
time: 2019-01-14 16:18:01.867223
-----
--------------
sender:
30819f300d06092a864886f70d010101050003818d0030818902818100cba097c0854876f413
38c
62598c658f545182cfa4acebce147aedf328181f9c4930f14498fd03c0af6b0cce25be99452a
81d
f4fa30a53eddbb7bb7b203adf8764a0ccd9db6913a576d68d642d8fd47452590137869c25d9f
f83
d68ebe6d616056a8425b85b52e69715b8b85ae807b84638d8f00e321b65e4c33acaf6469e18e
302
03010001
-----
recipient:
30819f300d06092a864886f70d010101050003818d0030818902818100bb064c99c492144a9f
463
480273aba93ac1db1f0da3cb9f3c1f9d058cf499fd8e54d244da0a8dd6ddd329ec86794b04d7
73e
b4841c9f935ea4d9ccc2821c7a1082d23b6c928d59863407f52fa05d8b47e5157f8fe56c2ce3
279
c657f9c6a80500073b0be8093f748aef667c03e64f04f84d311c4d866c12d79d3fc3034563df
b02
03010001
-----
value: 5.0
-----
time: 2019-01-14 16:18:01.868241
-----
--------------
=====================================

Dans ce tutoriel, nous avons appris à construire un projet blockchain en Python. Il existe de
nombreux domaines dans lesquels vous devez ajouter des fonctionnalités supplémentaires à ce
projet.
Par exemple, vous devrez écrire des fonctions pour gérer la file d'attente des transactions. Une fois
les transactions minées et le bloc miné accepté par le système, elles n'ont plus besoin d'être
stockées.
En outre, les mineurs préféreraient certainement récupérer les transactions avec les frais les plus
élevés. Dans le même temps, vous devrez vous assurer que les transactions avec des frais faibles
ou sans frais ne mourront pas de faim.
Vous devrez développer des algorithmes pour gérer la file d'attente. En outre, le didacticiel actuel
n'inclut pas le code de l'interface client. Vous devrez développer cela pour les clients normaux et
les mineurs. Le projet de blockchain à part entière se heurterait à plusieurs autres lignes de code
et dépasse le cadre de ce didacticiel. Le lecteur intéressé peut télécharger la source Bitcoin pour
une étude plus approfondie.

Conclusions
Ce didacticiel précis devrait vous aider à créer votre propre projet de blockchain.
Pour le développement de projets blockchain à part entière, vous pouvez en apprendre davantage
sur la source Bitcoin .
Pour les projets commerciaux ou non commerciaux plus importants, vous pouvez envisager
d'utiliser Ethereum - une plate-forme d'application blockchain prête à l'emploi.

Vous aimerez peut-être aussi