Jak vytvořit blockchain s Pythonem?

Tušili jste, že základem bitcoinu je blockchain? Dnes si krok za krokem vytvoříme vlastní blockchain s využitím Pythonu.

Co je to Blockchain?

V roce 2008 byl publikován Bitcoinový whitepaper od neznámé osoby nebo skupiny s pseudonymem Satoshi Nakamoto. Bitcoin se objevil jako peer-to-peer elektronická měna, která umožňovala transakce bez účasti centralizovaných institucí (bank). Nicméně, málokdo ví, že ve stejném dokumentu Satoshi definoval distribuovaný způsob ukládání informací, který dnes známe jako blockchain.

Technologie blockchain

Jednoduše řečeno, blockchain je sdílená, neměnná digitální účetní kniha, která uchovává záznamy o transakcích v decentralizované síti počítačů.

Blockchain můžeme rozdělit na dva základní koncepty:

  • Blok: Prostor pro ukládání transakcí.
  • Řetězec: Sled vzájemně propojených záznamů.

Z toho vyplývá, že blockchain je řetězec propojených bloků, kde každý blok obsahuje transakce s definovanými parametry.

Každý blok je navázán na předchozí, čímž se vytváří nevratný řetězec. Jinými slovy, každý blok je závislý na tom, který mu předcházel. Výsledkem je robustní a neměnný systém, jehož integritu může ověřit kdokoli s příslušnými oprávněními.

Blockchain nabízí řadu pozoruhodných vlastností:

  • Neměnnost historie záznamů
  • Trvalost informací
  • Absence chyb v uložených datech

Mnoho moderních systémů se v současné době spoléhá na blockchain, například kryptoměny, převod digitálních aktiv (NFT) a možná v budoucnosti i systémy pro hlasování.

Je důležité poznamenat, že Python blockchain nemusí být komplikovaný program s tisíci řádky kódu. V podstatě je to seznam vzájemně propojených transakcí.

Toto byl stručný úvod, ale pokud chcete hlubší pochopení, připravili jsme komplexní návod pro začátečníky. Určitě se na něj podívejte.

Bez dalších průtahů se pustíme do vytváření jednoduchého blockchainu pomocí Pythonu.

Tvorba blockchainu v Pythonu

Před samotným kódováním si definujme cíle tohoto tutoriálu:

  • Vytvoříme základní blockchainový systém v Pythonu.
  • Budeme používat náš blockchain s předdefinovanými transakcemi, které budeme reprezentovat jako textové řetězce.
  • Ověříme neměnnost našeho blockchainu.

Nechceme používat JSON, ale seznamy Pythonu. To nám umožní zjednodušit proces a soustředit se na základní principy blockchainu.

Co budete potřebovat pro tento návod:

Vytvoření třídy Block

Otevřete si svůj oblíbený textový editor a založte soubor main.py. Zde budeme psát náš kód.

Nyní importujeme modul hashlib, který umožňuje generovat jednosměrné šifrované zprávy. Kryptografické techniky, jako je hashování, jsou klíčové pro bezpečnost transakcí v blockchainu.

Hašovací funkce je algoritmus, který vezme vstupní data (nejčastěji zakódovaný řetězec) a vrátí unikátní identifikátor, často označovaný jako „hash“ nebo „otisk“. Důležité je, že i malá změna ve vstupních datech vygeneruje radikálně odlišný hash. Tuto vlastnost si později prakticky ověříme.

Prozatím postačí importovat vestavěný modul hashlib:

# main.py file
"""
Jednoduchý Blockchain v Pythonu
"""

import hashlib

Tento modul obsahuje většinu hašovacích algoritmů, které budeme potřebovat. My konkrétně použijeme funkci hashlib.sha256().

Teď se podíváme na třídu GeekCoinBlock, což je název naší ukázky blockchainu.

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()

Vím, že to může vypadat komplikovaně. Pojďme si jednotlivé části podrobněji vysvětlit.

Vysvětlení GeekCoinBlock

Začneme vytvořením třídy GeekCoinBlock, která slouží jako obal pro objekty s definovanými vlastnostmi (atributy) a funkcemi (metodami).

Následně definujeme metodu __init__ (tzv. konstruktor), která se vyvolá při každém vytvoření objektu GeekCoinBlock.

Tato metoda má tři parametry:

  • self (instance každého objektu)
  • previous_block_hash (odkaz na hash předchozího bloku)
  • transaction_list (seznam transakcí provedených v aktuálním bloku)

Uložíme hash předchozího bloku a seznam transakcí. Vytvoříme proměnnou block_data jako textový řetězec. Ve skutečných kryptoměnách se data ukládají jako další hash, ale pro zjednodušení budeme ukládat data každého bloku jako řetězec.

Nakonec vygenerujeme block_hash, který bude použit pro navázání dalších bloků v řetězci. Zde se hodí modul hashlib. Místo vytváření vlastní hashovací funkce použijeme předpřipravenou sha256 k vytvoření neměnných bloků.

Tato funkce přijímá zakódované řetězce (nebo bajty) jako vstupní parametry. Proto používáme metodu block_data.encode(). Následně voláme hexdigest(), abychom data převedli do hexadecimálního formátu.

Vím, že to všechno může být zpočátku matoucí, tak si pojďme pohrát s modulem hashlib v interaktivní konzoli Pythonu.

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'

Jak vidíte, drobná změna ve vstupu, například změna „Python is great“ na „Python is not great“, vede k vytvoření zcela odlišného hashe. Právě toto má spojitost s integritou blockchainu. Jakákoli malá změna v datech bloku má za následek drastickou změnu jeho hashe. To je důvod, proč se říká, že „blockchain nelze zfalšovat“.

Použití třídy Block

Později vytvoříme celou třídu Blockchain, ale prozatím použijeme třídu Block k vytvoření řetězce bloků (blockchainu).

Ve stejném souboru vytvořte několik transakcí reprezentovaných jednoduchými textovými řetězci, například:

class GeekCoinBlock:
    ...

t1 = "Noah posílá 5 GC Markovi"
t2 = "Mark posílá 2.3 GC Jamesovi"
t3 = "James posílá 4.2 GC Alisson"
t4 = "Alisson posílá 1.1 GC Noahovi"

GC, samozřejmě, znamená GeekCoin.

Nyní vytvořte první blok našeho blockchainu pomocí třídy GeekCoinBlock a vytiskněte jeho atributy. Parametr previous_hash u genesis bloku (první blok v řetězci) bude vždy nějaký libovolný řetězec nebo hash, v tomto případě „firstblock“.

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

print(f"Data bloku 1: {block1.block_data}")
print(f"Hash bloku 1: {block1.block_hash}")

Následně vytvoříme druhý blok, ale jako parametr previous_hash použijeme hash prvního bloku.

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

print(f"Data bloku 2: {block2.block_data}")
print(f"Hash bloku 2: {block2.block_hash}")

Pojďme spustit kód a analyzovat výstup. Zadejte v terminálu:

❯ python main.py
Data bloku 1: Noah posílá 5 GC Markovi - Mark posílá 2.3 GC Jamesovi - firstblock
Hash bloku 1: 01e4e15242a9601725f4a86ca01fbddaaec7105b442955bb0efcadbfc759806d
Data bloku 2: James posílá 4.2 GC Alisson - Alisson posílá 1.1 GC Noahovi - 01e4e15242a9601725f4a86ca01fbddaaec7105b442955bb0efcadbfc759806d
Hash bloku 2: 448c4306caf7f6937b0307f92f27fbea3bb73b3470363dee5026a1209dadcfa8

Zatím vidíte pouze text a 64znakové hashe, ale toto je v podstatě mechanismus blockchainu.

Začínáte genesis blokem, základem pro všechny ostatní bloky.

Integritu řetězce si může ověřit kdokoliv, a proto je blockchain tak bezpečný. Pokud například mírně upravíme transakci, třeba:

t2 = "Mark posílá 2.3 GC Jamesovi" -> t2 = "Mark posílá 3.2 GC Jamesovi"

Vidíme dramatickou změnu v hashi bloku.

Data bloku 1: Noah posílá 5 GC Markovi - Mark posílá 3.2 GC Jamesovi - firstblock
Hash bloku 1: 7a990bf1d70230bf2dad6160496c0b3046da7a17b1281fd1d4c63d4eac58e78c
Data bloku 2: James posílá 4.2 GC Alisson - Alisson posílá 1.1 GC Noahovi - 7a990bf1d70230bf2dad6160496c0b3046da7a17b1281fd1d4c63d4eac58e78c
Hash bloku 2: 569b977306ce88b53e001dca7ba00c03a51c60d6df4650e7657dcd136f2da0ac

Aktuální verzi projektu si můžete prohlédnout na GitHubu.

Kódování blockchainu

Zakládat integritu systému na ručně kódovaných proměnných není ideální, proto budeme potřebovat jiný přístup.

Máme bloky. Nyní je čas vytvořit třídu, která je spojí do blockchainu.

Začneme smazáním předchozích transakcí a blokových objektů a nahradíme je následujícím kódem.

# 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]

Opět je to poměrně velký kus kódu. Pojďme si ho rozdělit na menší části:

  • self.chain — Seznam, kde jsou uložené všechny bloky. K jednotlivým blokům přistupujeme pomocí indexů seznamu.
  • generate_genesis_block — Vytvoří genesis blok a přidá jej do řetězce. Hash předchozího bloku je „0“ a seznam transakcí je jednoduše „Genesis Block“.
  • create_block_from_transaction — Umožňuje nám přidávat bloky do řetězce pouze pomocí seznamu transakcí. Bylo by příliš komplikované vytvářet bloky ručně při každé transakci.
  • display_chain — Vytiskne celý řetězec bloků pomocí cyklu for.
  • last_block — Vlastnost, která nám umožňuje přistupovat k poslednímu bloku v řetězci. Použili jsme ji v metodě create_block_from_transaction.

Nyní otestujeme tento blockchain.

# main.py

import hashlib

class GeekCoinBlock:
    ...


class Blockchain:
    ...

t1 = "George posílá 3.1 GC Joeovi"
t2 = "Joe posílá 2.5 GC Adamovi"
t3 = "Adam posílá 1.2 GC Bobovi"
t4 = "Bob posílá 0.5 GC Charliemu"
t5 = "Charlie posílá 0.2 GC Davidovi"
t6 = "David posílá 0.1 GC Ericovi"

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()

Spusťte soubor main.py.

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

Data 2: George posílá 3.1 GC Joeovi - Joe posílá 2.5 GC Adamovi - 39331a6a2ea1cf31a5014b2a7c9e8dfad82df0b0666e81ce04cf8173cc5aed3e
Hash 2: 98cf363aecb33989aea0425a3c1287268bd86f63851bc08c0734a31db08506d5

Data 3: Adam posílá 1.2 GC Bobovi - Bob posílá 0.5 GC Charliemu - 98cf363aecb33989aea0425a3c1287268bd86f63851bc08c0734a31db08506d5
Hash 3: 6f1cfcc3082488b97db8fdf8ed33f9ac7519be3e285a37a6fcc2f1904f373589

Data 4: Charlie posílá 0.2 GC Davidovi - David posílá 0.1 GC Ericovi - 6f1cfcc3082488b97db8fdf8ed33f9ac7519be3e285a37a6fcc2f1904f373589
Hash 4: 869df2f03c9860767d35b30a46233fbeea89a3000ae5019d1491e3829d1ab929

Gratuluji! 🙌 Právě jste vytvořili jednoduchý blockchain v Pythonu od nuly.

Nyní můžete posílit neměnnost blockchainu pomocí getterů a setterů a implementovat další funkce, jako je proof-of-work, mining nebo jakýkoli jiný koncept, který jsme vysvětlili v článku o základech těžby bitcoinů.

Závěr

Blockchain je technologie, která stojí za bitcoinem, ethereem a dalšími kryptoměnami. V tomto článku jste se naučili, jak vytvořit blockchain pomocí Pythonu, hašovacích algoritmů, jako je sha256, tříd a objektů.

Vaším úkolem je vytvořit systém těžby a následně jej implementovat pomocí REST API s použitím frameworků jako Django nebo Flask.

Mnoho lidí zbohatlo na kryptoměnách. Představte si, co byste mohli dokázat, kdybyste si jednu vytvořili sami. 🤑

Pokračujte v kódování! 👨‍💻