Como criar um Blockchain com Python?

Você sabia que o Bitcoin é construído em cima do Blockchain? Hoje vamos construir um Blockchain com Python do zero.

O que é Blockchain?

Em 2008 o papel bitcoin foi publicado por um indivíduo ou grupo desconhecido chamado Satoshi Nakamoto. O Bitcoin surgiu como uma versão peer-to-peer de dinheiro eletrônico que permitia transações sem passar por instituições centralizadas (bancos). A maioria das pessoas não sabe que nesse mesmo artigo, Satoshi definiu uma forma distribuída de armazenamento de informações, hoje conhecida como Blockchain.

Tecnologia Blockchain

Simplificando, o Blockchain é um livro digital compartilhado e imutável que armazena transações em uma rede descentralizada de computadores.

Podemos dividir o Blockchain em dois termos simples:

  • Bloco: Um espaço onde armazenamos transações
  • Cadeia: Um conjunto de registros vinculados

Isso define Blockchain como uma cadeia de blocos vinculados, onde cada bloco armazena uma transação feita com parâmetros específicos.

Cada bloco é construído em cima de outro bloco, criando uma cadeia irreversível de blocos. Em outras palavras, cada bloco depende do outro. Isso resulta em um sistema robusto e imutável no qual qualquer pessoa com as permissões corretas pode revisar a integridade.

Blockchain apresenta um conjunto interessante de recursos:

  • Imutabilidade da história
  • persistência da informação
  • Sem erros com dados armazenados

Atualmente, muitos sistemas dependem do Blockchain, como criptomoedas, transferência de ativos (NFTs) e, possivelmente, no futuro próximo, votação.

Vale ressaltar que um Python Blockchain não precisa ser um programa complexo com milhares de linhas de código. Em sua essência, seria uma lista de transações vinculadas umas às outras.

Claro, esta foi uma breve explicação, mas se você quiser um guia completo, produzimos um tutorial completo sobre Blockchain para iniciantes. Certifique-se de verificar.

Sem mais delongas, vamos construir um Blockchain simples com Python.

Construindo um Blockchain com Python

Antes de começar, vamos definir o que vamos fazer neste tutorial:

  • Construa um sistema Blockchain simples escrito em Python
  • Use nosso Blockchain com transações pré-estabelecidas representadas como strings
  • Teste a imutabilidade do nosso Blockchain

Não vamos usar JSON, mas listas Python. Isso nos permitirá simplificar o processo e focar na aplicação dos principais conceitos de um Blockchain.

O que você precisa para seguir este tutorial:

Criando a classe Bloco

Abra seu editor de código favorito e crie um arquivo main.py. Este será o arquivo com o qual trabalharemos.

  Como fazer o pré-registro para o Tekken Mobile

Agora, importe hashlib, um módulo que nos permite criar mensagens criptografadas unidirecionais. Técnicas de criptografia como hashing fazem com que o Blockchain crie transações seguras.

Uma função hash é um algoritmo que pega alguns dados (geralmente uma string codificada) e retorna um identificador exclusivo, geralmente chamado de “resumo” ou “assinatura”. Esta última parte é vital; com uma função hash, uma pequena diferença na entrada produz um identificador radicalmente diferente como saída. Veremos isso em ação mais adiante.

Por enquanto, apenas importe o módulo embutido hashlib:

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

import hashlib

Este módulo inclui a maioria dos algoritmos de hash necessários. Lembre-se de que usaremos a função hashlib.sha256().

Agora, vamos entrar no GeekCoinBlock, nosso nome blockchain totalmente 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()

Eu sei que isso pode resultar em um pedaço desajeitado de código. Vamos detalhar cada parte na próxima seção.

Explicação GeekCoinBlock

Primeiramente, criamos uma classe chamada GeekCoinBlock, um wrapper para objetos que terão determinadas características (atributos) e comportamentos (métodos).

Em seguida, definimos o método __init__ (também chamado de construtor), que é invocado sempre que um objeto GeekCoinBlock é criado.

Este método tem três parâmetros:

  • self (a instância de cada objeto)
  • Previous_block_hash (uma referência ao bloco anterior)
  • transaction_list (uma lista de transações feitas no bloco atual).

Armazenamos o hash anterior e a lista de transações e criamos uma variável de instância block_data como uma string. Isso não acontece com criptomoedas reais, nas quais armazenamos esse tipo de dados como outro hash, mas, para simplificar, armazenaremos cada bloco de dados como uma string.

Por fim, criamos o block_hash, que outros blocos usarão para continuar a cadeia. Aqui é onde o hashlib é útil; em vez de criar uma função de hash personalizada, podemos usar o sha256 pré-construído para criar blocos imutáveis.

Esta função recebe strings codificadas (ou bytes) como parâmetros. É por isso que estamos usando o método block_data.encode(). Depois disso, chamamos hexdigest() para retornar os dados codificados para o formato hexadecimal.

Sei que tudo isso pode ser opressor, então vamos brincar com hashlib em um 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'

Como você pode ver, uma pequena mudança na entrada como “Python é ótimo” para “Python não é ótimo” pode produzir um hash totalmente diferente. Isso tem tudo a ver com a integridade do Blockchain. Se você introduzir alguma pequena mudança em um blockchain, seu hash mudará drasticamente. Esta é a razão pela qual o ditado “Você não pode corromper um Blockchain” é verdadeiro.

  Como excluir uma linha horizontal no Word

Usando nossa classe Block

Construiremos toda uma classe Blockchain mais tarde, mas por enquanto, vamos usar nossa classe Block para criar uma cadeia de blocos (Blockchain).

No mesmo arquivo, crie algumas transações compostas por strings simples armazenadas em variáveis, por exemplo:

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"

Claro, GC refere-se a GeekCoin

Agora, construa o primeiro bloco do nosso Blockchain usando a classe GeekCoinBlock e imprima seus atributos. Leve em consideração que o parâmetro Previous_hash do bloco genesis (primeiro bloco que precede os outros blocos) sempre será alguma string ou hash arbitrário, neste caso, “firstblock”.

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

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

Em seguida, fazemos o mesmo com o segundo bloco, mas passando o hash do primeiro bloco como o argumento Previous_hash.

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

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

Vamos executar e analisar a saída que obtemos desse trecho de código. Mais uma vez, digite no seu 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

Por enquanto, você vê apenas texto e alguns hashes de 64 caracteres, mas isso resume praticamente o mecanismo de um Blockchain.

Você começa com um bloco de gênese, a base de todos os outros blocos.

Qualquer um pode validar a integridade da cadeia e é por isso que um Blockchain é um sistema tão seguro. Por exemplo, se modificarmos levemente o conteúdo de uma transação, digamos:

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

Vemos uma mudança dramática no hash dos blocos.

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

Você pode ver o projeto atual neste repositório GitHub.

Codificando um Blockchain

Não é tão inteligente basear a integridade do nosso sistema em variáveis ​​codificadas manualmente, então precisamos de outra abordagem.

  Como encontrar latitude e longitude no Apple Maps

Temos os blocos. É hora de construir uma classe que os junte em um Blockchain.

Vamos começar excluindo nossas transações anteriores e objetos de bloco e, em seguida, usando o código abaixo.

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

Este é novamente um grande pedaço de código. Vamos separar cada parte:

  • self.chain — A lista onde todos os blocos são registrados. Podemos acessar cada bloco por meio de índices de lista.
  • generate_genesis_block — Acrescenta o genesis ou primeiro bloco à cadeia. O hash anterior do bloco é “0” e a lista de transações é simplesmente “Genesis Block”.
  • create_block_from_transaction — Isso nos permite anexar blocos à cadeia com apenas uma lista de transações. Seria muito chato criar um bloco manualmente toda vez que quiséssemos registrar uma transação
  • display_chain — Imprime a cadeia de blocos com um loop for
  • last_block — Uma propriedade que nos permite acessar o último elemento da cadeia. Nós o usamos no método create_block_from_transaction.

Vamos testar este 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()

Agora, execute o arquivo main.py.

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

Parabéns! 🙌 Você acabou de criar um Python Blockchain simples do zero.

Agora você pode fortalecer a imutabilidade do Blockchain usando getters e setters e implementar outros recursos como prova de trabalho, mineração ou qualquer outro conceito que explicamos no artigo Fundamentos da Bitcoin Mining.

Conclusão

Blockchain é a tecnologia por trás do Bitcoin, Etherium e todas as outras criptomoedas por aí. Neste artigo, você aprendeu como criar um Blockchain com Python usando algoritmos de hash como sha256, classes e objetos.

Seu desafio é criar um sistema de mineração e, porque não, implementá-lo com uma API REST usando frameworks como Django ou Flask.

Muitas pessoas estão fazendo fortunas com criptomoedas. Imagine o que você poderia fazer se criasse um sozinho. 🤑

Continue codificando! 👨‍💻