Entendendo Blockchain e implementando em Python – Willian Gabriel
Acima estamos utilizando os blocos para armazenar nomes e apelidos de algumas pessoas, o interessante é que mesmo que alguém queira mudar seu apelido isso será possível, não será feita nenhuma alteração no bloco que continha o apelido inicial mas será adicionando um outro bloco ao final da corrente:
Explicando cada um dos campos: O Índice e o Timestamp são campos bem comuns em bancos de dados, o índice representa a “posição” do bloco na cadeia e o timestamp é uma representação temporal do momento exato em que o bloco foi gerado. O hash é a “impressão digital” do bloco e serve para manter a integridade de cada bloco e também da corrente como um todo, o HashAnterior é a ligação entre cada bloco, formando assim uma corrente.
Se quisermos saber qual o apelido atual do Roger é só percorrer a blockchain e pesquisar pelo apelido mais recente. É basicamente assim que podem ser realizadas as transações em criptomoedas, são adicionados novos blocos contendo informações sobre as transações e criando uma espécie de linha do tempo, o saldo de uma carteira virtual na verdade não é subtraído ou adicionado diretamente, a blockchain da criptomoeda é essencialmente uma linha do tempo de transações, através dessa linha do tempo é que calcula-se o valor disponível em uma determinada carteira (saldo).
IMPLEMENTAÇÃO EM PYTHON
Criar uma blockchain não é tarefa difícil, considerando as funcionalidade básicas claro, portanto, irei fazer a criação de uma blockchain básica em Python e demonstrar seu uso e funcionamento. Primeiro é necessário entender como funciona uma função hash e como ela pode garantir a integridade da corrente de blocos.
A função hash recebe como entrada uma quantidade variável de dados, podendo ser uma sequência de bytes, um arquivo de texto, e por aí vai, no nosso caso vai ser uma sequência de dados (indice, timestamp, dados, hash_anterior), ao processar esses dados a função gera uma saída de tamanho fixo. Se pensarmos de maneira matemática temos a função hash(x) = y em que y terá um tamanho definido (a depender da função hash utilizada), obter x a partir de y é uma tarefa computacionalmente e matematicamente “impossível”. A função hash sempre retorna o mesmo y para um dado x, no nosso exemplo vamos usar o algoritmo sha256 para gerar o hash dos blocos. Para exemplificar o funcionamento de uma função hash, vejamos qual saída o sha256 produz para a string “Willian Rocha”:
6b7923e27cff678d524e7e429735fff32efa43d6b29d96b4829d7ef2287664f1 (“Willian Rocha”)
Legal, mas o que acontece se eu alterar apenas um caractere da string que é passada para a função hash?
c86e339c76c8970d04bc08d39e4c3e5988d69232b38f5337fda9fcf2e24c38b7 (“WillianRocha”)
Veja que o resultado da função é completamente diferente, eu só removi o espaço entre as palavras. Isso é verdadeiro para qualquer que seja o tamanho da variável de entrada, se eu tiver um conjunto de 1 milhão de caracteres e alterar apenas um deles a função retornará um valor completamente diferente. Na Blockchain temos o seguinte:
hash(indice, timestamp, hash_anterior, dados)
Veja que o hash de um bloco utiliza como uma das entradas o hash do bloco anterior, isso significa que se um único caractere for alterado em algum bloco, toda a corrente a partir dele se tornará inválida. Mas nada impede alguém de modificar um bloco e todos os demais a partir dele para tornar a corrente válida certo? Bom, na prática não é bem assim, existe um conceito chamado Proof Of Work (prova de trabalho), não pretendo que esse post fique muito extenso e por isso serei superficial, se quiser aprofundar os estudos sobre Blockchain tem links no final do post.
A prova de trabalho garante que alguém que quer incluir um novo bloco na corrente tenha realizado algum trabalho para isso (nesse caso, trabalho é processamento computacional), ou seja, não será permitido a ninguém adicionar ou modificar blocos livremente sem realizar algum processamento para isso. Para não deixar confuso vou tentar simplificar inserindo uma regra para inclusão de novos blocos na nossa blockchain: só será permitida a inclusão de blocos cujo hash inicia-se em “aaaa”, para isso precisaremos incluir no cálculo do hash um valor aleatório (chamarei de valor_pow):
hash(indice, timestamp, hash_anterior, dados, valor_pow)
Para inserir um novo bloco será necessário modificar o valor_pow até que o hash inicie-se com “aaaa”.
Vamos à parte mais legal, que é transformar todos esses conceitos em códigos, começamos fazendo os imports necessários, datetime é para obtenção dos timestamps e hashlib para calcular os hashs dos blocos:
Feitos os imports vamos criar a classe Bloco. Como estamos fazendo uma blockchain básica esta classe terá apenas as propriedades já citadas (índice, timestamp, dados, hash_anterior, hash e valor_pow), esses dados já serão inicializados no construtor da classe. Teremos também o método calcular_hash para criar um hash válido (iniciado em “aaaa”) e o método print_bloco para nos mostrar cada bloco quando quisermos:
Veja que é bem simples, o timestamp será calculado no momento em que o objeto for criado e os demais dados serão atribuídos de acordo com os argumentos passados ao construtor.
Vamos agora à criação de uma classe Blockchain, também faremos ela com as funcionalidade básicas, que são: adicionar bloco (add_bloco), retornar o último índice (get_ultimo_indice) e retornar o último hash (get_ultimo_hash). Além destes eu também defini o método print_blocos que nos mostra toda a blockchain, o método bloco_valido, que é chamado na adição de um novo bloco à corrente para verificar se ele é válido para ser adicionado e o criar_bloco_genesis que é chamado pelo construtor da classe para inicializá-la:
A construção daquele exemplo que dei lá no início sobre os nomes e apelidos ficaria da seguinte maneira:
E como saída teremos:
CONCLUSÃO
Pois é, aqui já temos uma Blockchain básica em funcionamento, não implementei nenhuma verificação de integridade da corrente, ela não é descentralizada, a checagem de validade dos blocos é bem simples, não implementa nenhuma prova de trabalho elaborada e também não é nem de longe comercialmente utilizável mas acredito que por ser um post de caráter introdutório e educativo está de bom tamanho. Esta é uma tecnologia maravilhosa, tem evoluído muito nos últimos anos e combinada com ferramentas de Big Data e Data Science tem um grande potencial para mudar a forma como armazenamos e analisamos dados. Além disso é sempre bom aprender algo novo!
O código completo está disponível no github!
Obrigado pela atenção e até a próxima!
Published at Mon, 03 Feb 2020 17:35:00 +0000
{flickr|100|campaign}
