Saviez-vous que Bitcoin est construit sur Blockchain ? Aujourd'hui, nous allons créer une Blockchain avec Python à partir de zéro.

What is Blockchain?

Dans le 2008 Papier Bitcoin a été publié par un individu ou un groupe inconnu nommé Satoshi Nakamoto. Bitcoin est sorti comme une version peer-to-peer de la monnaie électronique qui permettait des transactions sans passer par des institutions centralisées (banques). La plupart des gens ne savent pas que dans ce même article, Satoshi a défini une méthode distribuée de stockage d'informations, connue aujourd'hui sous le nom de Blockchain.

la technologie Blockchain
la technologie Blockchain

Pour faire simple, Blockchain est un grand livre numérique partagé et immuable qui stocke les transactions sur un réseau décentralisé d'ordinateurs.

Nous pouvons diviser Blockchain en deux termes simples :

  • Block : Un espace où nous stockons les transactions
  • Chaîne : un ensemble d'enregistrements liés

Cela définit Blockchain comme une chaîne de blocs liés, où chaque bloc stocke une transaction effectuée avec des paramètres spécifiques.

Chaque bloc est construit sur un autre bloc, créant une chaîne irréversible de blocs. En d'autres termes, chaque bloc dépend d'un autre. Cela s'avère être un système robuste et immuable dans lequel toute personne disposant des autorisations appropriées peut vérifier l'intégrité.

Blockchain introduit un ensemble intéressant de fonctionnalités :

  • Immuabilité de l'histoire
  • Persistance des informations
  • Aucune erreur avec les données stockées

De nombreux systèmes reposent actuellement sur Blockchain, tels que cryptocurrencies, transfert d'actifs (NFTs), et peut-être dans un avenir proche, le vote.

Il convient de mentionner qu'un Python Blockchain ne doit pas être un programme complexe avec des milliers de lignes de code. À la base, il s'agirait d'une liste de transactions liées les unes aux autres.

Bien sûr, c'était une brève explication, mais si vous voulez un guide complet, nous avons produit un tutoriel complet sur Blockchain pour les débutants. Assurez-vous de le vérifier.

Sans plus tarder, construisons une Blockchain simple avec Python.

Building a Blockchain With Python

Avant de commencer, définissons ce que nous allons faire dans ce tutoriel :

  • Construire un système Blockchain simple écrit en Python
  • Utilisez notre Blockchain avec des transactions préétablies représentées sous forme de chaînes
  • Testez l'immuabilité de notre Blockchain

nous n'allons pas utiliser JSON mais les listes Python. Cela nous permettra de simplifier le processus et de nous concentrer sur l'application des concepts clés d'une blockchain.

Ce dont vous aurez besoin pour suivre ce tutoriel :

Création de la classe Block

Ouvrez votre éditeur de code préféré et créez un main.py déposer. Ce sera le fichier avec lequel nous travaillerons.

Maintenant, importez hashlib, un module qui nous permet de créer des messages cryptés à sens unique. Les techniques de cryptographie comme le hachage font que Blockchain crée des transactions sécurisées.

Une fonction de hachage est un algorithme qui prend des données (généralement une chaîne encodée) et renvoie un identifiant unique, souvent nommé « condensé » ou « signature ». Cette dernière partie est vitale ; avec une fonction de hachage, une légère différence dans l'entrée produit un identifiant radicalement différent en sortie. Nous verrons cela en action plus tard.

Pour l'instant, importez simplement le module intégré hashlib :

# main.py file
"""
A simple Blockchain in Python
"""

import hashlib

Ce module comprend la plupart des algorithmes de hachage dont vous aurez besoin. N'oubliez pas que nous utiliserons le hashlib.sha256() la fonction.

Passons maintenant au GeekCoinBlock, notre nom de blockchain totalement original.

class GeekCoinBlock:
    
    def __init__(self, previous_block_hash, transaction_list):

        self.previous_block_hash = previous_block_hash
        self.transaction_list = transaction_list

        self.block_data = f"{' - '.join(transaction_list)} - {previous_block_hash}"
        self.block_hash = hashlib.sha256(self.block_data.encode()).hexdigest()

Je sais que cela peut entraîner un morceau de code maladroit. Décomposons chaque partie dans la section suivante.

Explication GeekCoinBlock

Tout d'abord, nous créons une classe nommée GeekCoinBloc, un wrapper pour les objets qui auront certaines caractéristiques (attributs) et comportements (méthodes).

Ensuite, nous définissons le __init__ méthode (également nommée constructeur), qui est invoquée chaque fois qu'un objet GeekCoinBlock est créé.

Cette méthode a trois paramètres :

  • soi (l'instance de chaque objet)
  • précédent_block_hash (une référence au bloc précédent)
  • liste_de_transactions (une liste des transactions effectuées dans le bloc actuel).

Nous stockons la liste de hachage et de transaction précédente et créons une variable d'instance données_bloc comme une chaîne. Cela ne se produit pas avec les vraies crypto-monnaies, dans lesquelles nous stockons ce type de données sous forme d'un autre hachage, mais pour des raisons de simplicité, nous stockerons chaque bloc de données sous forme de chaîne.

Enfin, nous créons le block_hash, que les autres blocs utiliseront pour continuer la chaîne. Voici où hashlib est utile; au lieu de créer une fonction de hachage personnalisée, nous pouvons utiliser le pré-construit sha256 pour faire des blocs immuables.

Cette fonction reçoit des chaînes encodées (ou octets) en tant que paramètres. C'est pourquoi nous utilisons le bloc_données.encode() méthode. Après cela, nous appelons hexdigest() pour renvoyer les données encodées au format hexadécimal.

Je sais que tout cela peut être accablant, alors jouons avec hashlib sur un shell Python.

In [1]: import hashlib

In [2]: message = "Python is great"

In [3]: h1 = hashlib.sha256(message.encode())

In [4]: h1
Out[4]: <sha256 ... object @ 0x7efcd55bfbf0>

In [5]: h1.hexdigest()
Out[5]: 'a40cf9cca ... 42ab97'

In [6]: h2 = hashlib.sha256(b"Python is not great")

In [7]: h2
Out[7]: <sha256 ... object @ 0x7efcd55bfc90>

In [8]: h2.hexdigest()
Out[8]: 'fefe510a6a ... 97e010c0ea34'

Comme vous pouvez le voir, un léger changement dans l'entrée comme « Python est génial » en « Python n'est pas génial » peut produire un hachage totalement différent. Tout cela a à voir avec l'intégrité de la Blockchain. Si vous introduisez un petit changement dans une blockchain, son hachage changera radicalement. C'est la raison pour laquelle le dicton « Vous ne pouvez pas corrompre une Blockchain » est vrai.

Utiliser notre classe Block

Nous construirons une classe Blockchain entière plus tard, mais pour l'instant, utilisons notre classe Block pour créer une chaîne de blocs (Blockchain).

Dans le même fichier, créez quelques transactions composées de chaînes simples stockées dans des variables, par exemple :

class GeekCoinBlock:
    ...

t1 = "Noah sends 5 GC to Mark"
t2 = "Mark sends 2.3 GC to James"
t3 = "James sends 4.2 GC to Alisson"
t4 = "Alisson sends 1.1 GC to Noah"

Bien sûr, GC fait référence à GeekCoin

Maintenant, construisez le premier bloc de notre Blockchain en utilisant la classe GeekCoinBlock et imprimez ses attributs. Tenez compte du fait que le précédent_hachage Le paramètre du bloc genesis (premier bloc qui précède les autres blocs) sera toujours une chaîne ou un hachage arbitraire, dans ce cas, « premier bloc ».

block1 = GeekCoinBlock('firstblock', [t1, t2])

print(f"Block 1 data: {block1.block_data}")
print(f"Block 1 hash: {block1.block_hash}")

Ensuite, nous faisons la même chose avec le deuxième bloc, mais en passant le hachage du premier bloc comme précédent_hachage argument.

block2 = GeekCoinBlock(block1.block_hash, [t3, t4])

print(f"Block 2 data: {block2.block_data}")
print(f"Block 2 hash: {block2.block_hash}")

Exécutons et analysons la sortie que nous obtenons de ce morceau de code. Encore une fois, tapez dans votre terminal :

❯ python main.py
Block 1 data: Noah sends 5 GC to Mark - Mark sends 2.3 GC to James - firstblock
Block 1 hash: 01e4e15242a9601725f4a86ca01fbddaaec7105b442955bb0efcadbfc759806d
Block 2 data: James sends 4.2 GC to Alisson - Alisson sends 1.1 GC to Noah - 01e4e15242a9601725f4a86ca01fbddaaec7105b442955bb0efcadbfc759806d
Block 2 hash: 448c4306caf7f6937b0307f92f27fbea3bb73b3470363dee5026a1209dadcfa8

Pour l'instant, vous ne voyez que du texte et quelques hachages de 64 caractères, mais cela reprend à peu près le mécanisme d'une Blockchain.

Vous commencez avec un bloc de genèse, la base de tous les autres blocs.

Tout le monde peut valider l'intégrité de la chaîne, et c'est pourquoi une Blockchain est un système si sécurisé. Par exemple, si nous modifions légèrement le contenu d'une transaction, disons :

t2 = "Mark sends 2.3 GC to James" -> t2 = "Mark sends 3.2 GC to James" 

Nous voyons un changement spectaculaire dans le hachage des blocs.

Block 1 data: Noah sends 5 GC to Mark - Mark sends 3.2 GC to James - firstblock
Block 1 hash: 7a990bf1d70230bf2dad6160496c0b3046da7a17b1281fd1d4c63d4eac58e78c
Block 2 data: James sends 4.2 GC to Alisson - Alisson sends 1.1 GC to Noah - 7a990bf1d70230bf2dad6160496c0b3046da7a17b1281fd1d4c63d4eac58e78c
Block 2 hash: 569b977306ce88b53e001dca7ba00c03a51c60d6df4650e7657dcd136f2da0ac

Vous pouvez voir le projet en cours sur ce GitHub repo.

Codage d'une blockchain

Il n'est pas si intelligent de baser l'intégrité de notre système sur des variables codées à la main, nous avons donc besoin d'une autre approche.

Nous avons les blocs. Il est temps de créer une classe qui les rejoint dans une Blockchain.

Commençons par supprimer nos précédentes transactions et objets de blocage, puis en utilisant le code ci-dessous.

# main.py

class Blockchain:
    def __init__(self):
        self.chain = []
        self.generate_genesis_block()

    def generate_genesis_block(self):
        self.chain.append(GeekCoinBlock("0", ['Genesis Block']))
    
    def create_block_from_transaction(self, transaction_list):
        previous_block_hash = self.last_block.block_hash
        self.chain.append(GeekCoinBlock(previous_block_hash, transaction_list))

    def display_chain(self):
        for i in range(len(self.chain)):
            print(f"Data {i + 1}: {self.chain[i].block_data}")
            print(f"Hash {i + 1}: {self.chain[i].block_hash}\n")

    @property
    def last_block(self):
        return self.chain[-1]

C'est encore un énorme morceau de code. Décomposons chaque partie :

  • self.chain — La liste où tous les blocs sont enregistrés. Nous pouvons accéder à chaque bloc via des index de liste.
  • generate_genesis_block — Ajoutez la genèse ou le premier bloc à la chaîne. Le hachage précédent du bloc est « 0 », et la liste des transactions est simplement « Genesis Block ».
  • create_block_from_transaction — Cela nous permet d'ajouter des blocs à la chaîne avec juste une liste de transactions. Il serait très ennuyeux de créer un bloc manuellement à chaque fois que l'on veut enregistrer une transaction
  • chaîne_affichage — Imprime la chaîne de blocs avec une boucle for
  • dernier_bloc — Une propriété qui nous permet d'accéder au dernier élément de la chaîne. Nous l'avons utilisé sur le create_block_from_transaction méthode.

Testons cette Blockchain.

# main.py

import hashlib

class GeekCoinBlock:
    ...


class Blockchain:
    ...

t1 = "George sends 3.1 GC to Joe"
t2 = "Joe sends 2.5 GC to Adam"
t3 = "Adam sends 1.2 GC to Bob"
t4 = "Bob sends 0.5 GC to Charlie"
t5 = "Charlie sends 0.2 GC to David"
t6 = "David sends 0.1 GC to Eric"

myblockchain = Blockchain()

myblockchain.create_block_from_transaction([t1, t2])
myblockchain.create_block_from_transaction([t3, t4])
myblockchain.create_block_from_transaction([t5, t6])

myblockchain.display_chain()

Maintenant, exécutez le main.py fichier.

Data 1: Genesis Block - 0
Hash 1: 39331a6a2ea1cf31a5014b2a7c9e8dfad82df0b0666e81ce04cf8173cc5aed3e

Data 2: George sends 3.1 GC to Joe - Joe sends 2.5 GC to Adam - 39331a6a2ea1cf31a5014b2a7c9e8dfad82df0b0666e81ce04cf8173cc5aed3e
Hash 2: 98cf363aecb33989aea0425a3c1287268bd86f63851bc08c0734a31db08506d5

Data 3: Adam sends 1.2 GC to Bob - Bob sends 0.5 GC to Charlie - 98cf363aecb33989aea0425a3c1287268bd86f63851bc08c0734a31db08506d5
Hash 3: 6f1cfcc3082488b97db8fdf8ed33f9ac7519be3e285a37a6fcc2f1904f373589

Data 4: Charlie sends 0.2 GC to David - David sends 0.1 GC to Eric - 6f1cfcc3082488b97db8fdf8ed33f9ac7519be3e285a37a6fcc2f1904f373589
Hash 4: 869df2f03c9860767d35b30a46233fbeea89a3000ae5019d1491e3829d1ab929

Toutes nos félicitations! Vous venez de créer une simple blockchain Python à partir de zéro.

Vous pouvez désormais renforcer l'immuabilité de la Blockchain en utilisant des getters et des setters et implémenter d'autres fonctionnalités telles que la preuve de travail, santé respiratoire exploitation minière, ou tout autre concept que nous avons expliqué dans le Article sur les fondamentaux de Bitcoin Mining.

Conclusion

La blockchain est la technologie derrière Bitcoin, Etherium et toutes les autres crypto-monnaies disponibles. Dans cet article, vous avez appris à créer une Blockchain avec Python en utilisant des algorithmes de hachage comme sha256, classes et objets.

Votre défi est de créer un système de minage, et pourquoi pas, de l'implémenter avec une API REST en utilisant des frameworks comme Django or Flacon.

Beaucoup de gens font fortune grâce aux crypto-monnaies. Imaginez ce que vous pourriez faire si vous en créez un vous-même. ??

Continuez à coder ! ??