Uma rápida revisão sobre blockchain

Ricardo Araujo
6 min readJun 8, 2021

Imagine que queremos ter um registro público sobre transações, financeiras ou de qualquer outra forma. Este registro conterá coisas como Bob pagou 2 reais para Alice. Para simplificar, considere que este registro existe em um único local e que todos os atores podem ler e escrever neste registro.

Na imagem, cinco silhuetas de pessoas se conectam por meio de setas bidirecionais a uma representação de um banco de dados.

Alice, antes de aceitar a transação, deve verificar se Bob possui 2 reais para pagar. Esta informação também está neste registro público e ela pode verificar isso lendo a informação ali presente — Alice pode verificar se Bob recebeu os 2 reais que ele quer gastar. No momento que a transação é aceita, ela é escrita no registro e idealmente deve ser imutável, isto é, não pode ser revertida ou alterada.

Podemos pensar em uma estrutura simples para este registro. Uma lista encadeada poderia ser utilizada, com cada bloco registrando uma transação. Assim, cada nova transação adiciona um novo bloco na lista (ignore condições de corrida e afins). Se Alice deseja verificar se Bob possui 2 reais, ela começa do início da lista e soma tudo que Bob recebeu e gastou; se a soma resultante for maior que 2 reais, é porque ele possui aquele montante para gastar.

Uma lista encadeada com três blocos. Primeiro bloco diz “Eve pagou 4 reais para Bob”. Segundo bloco diz “Bob pagou 1 real para Eve”. Terceiro bloco diz “Bob pagou 2 reais para Alice”.

Porém, uma lista encadeada é uma estrutura de dados que permite fácil alteração de qualquer elemento. Como Bob tem acesso a lista, ele pode alterar qualquer bloco para garantir que ele terá os 2 reais que quer gastar. Se ele fizer esta alteração, Alice não terá como saber que ela foi feita. Um ator malicioso, interessado em alterar um dado em um bloco específico, apenas precisa acessar aquele bloco e fazer a alteração.

Mesma imagem de uma lista encadeada, mas o primeiro bloco diz “Eve pagou 4000 reais para Bob”.

Uma alternativa é utilizar uma blockchain. Esta estrutura adiciona em cada bloco um novo elemento, contendo a hash da totalidade do conteúdo do bloco anterior (dado, ponteiro e hash). Isto permite que a integridade da lista como um todo seja verificada. Para tanto, basta recalcular a hash de cada bloco e comparar com a hash armazenada. Uma diferença nesses valores indica que alguma alteração ocorreu, seja no conteúdo do bloco, seja no valor da hash.

Representação de um blockchain básico, com três blocos. Cada bloco possui um conteúdo e um hash do bloco anterior.

Para um atacante gerar uma alteração indetectável, ele terá que não apenas alterar o conteúdo do bloco alvo, mas também todos os blocos posteriores, recalculando e atualizando todas hashes. Do contrário, a blockchain se encontrará em um estado inconsistente. No entanto, isso não é algo difícil de fazer pois as funções hashes são computacionalmente pouco custosas. Mesmo uma lista muito longa pode ser trivialmente alterada. Ainda assim, esta estrutura pode ser útil em situações em que alterações são ocasionadas por erros e não ataques maliciosos.

Um caminho para inibir estes ataques é tornar alterações excessivamente custosas. Para isso, podemos estabelecer que apenas hashes com certas propriedades são aceitas — por exemplo, que na representação hexadecimal a hash tenha que ter um certo número de zeros no início. Para permitir isso, é necessário que exista um campo adicional no bloco que possa ser alterado livremente e que permita que diferentes hashes sejam geradas — este campo é tipicamente chamado de nonce. Assim, para gerar uma hash válida é necessário testar diferentes valores para este campo e calcular, junto com todas as demais informações do bloco, a hash resultante, verificando se ela satisfaz as restrições impostas. Uma vez que se encontre este valor, o novo bloco com a hash resultante pode ser escrito e esta hash é copiada no bloco posterior quando este for criado.

Mesma imagem anterior, mas cada bloco possui um elemento adicional denominado “nonce”.

Devido à natureza das funções hash, não há uma maneira eficiente de descobrir algum dos valores que gera a hash desejada. Quanto maiores as restrições sobre a hash (e.g. quanto mais zeros exigirmos), mais difícil é esta tarefa.

Ainda que seja um problema significativamente mais difícil, considerando uma blockchain estática é apenas questão de tempo até que um atacante consiga fazer as alterações necessárias. Porém, em uma lista que esteja constantemente crescendo o atacante possui um problema mais difícil: ele precisa alterar hashes em uma velocidade superior à velocidade de adição de novos blocos.

Cada novo bloco adicionado precisa também encontrar o valor que leva a uma hash correta. Para incentivar que esses blocos com as hashes corretas sejam encontrados, processo chamado de mineração, o primeiro ator que encontrar uma hash correta é recompensado (é permitido que ele escreva uma transação no bloco que dá a si algum valor pré-determinado). Este incentivo faz com que muitos atores tentem simultaneamente minerar cada bloco novo.

Um atacante precisa agora possuir capacidade computacional maior do que a soma das capacidades computacionais de quem está minerando novos blocos. Do contrário, ele jamais conseguirá chegar à cabeça da lista, pois novos blocos já terão sido adicionados e que também precisarão ser alterados. Todas as modificações que ele conseguir fazer serão, portanto, detectadas e podem ser revertidas. Quanto mais para trás na lista (quanto mais profundo) estiver o bloco sendo alterado, mais difícil é a alteração.

A blockchain fornece uma estrutura e um protocolo de uso que essencialmente cria um banco de dados de registros imutáveis. Ao contrário de como assumimos aqui, a blockchain pode ser utilizada, e comumente o é, de forma totalmente distribuída — cada ator possui uma cópia que permanece sincronizada com a cópia de todos os demais. A blockchain “verdadeira” é aquela mais comum entre todos os atores envolvidos.

A criptomoeda Bitcoin é construída sobre uma estrutura de blockchain semelhante à descrita acima. Um bloco pode conter um número variável de transações, e não apenas uma como assumimos. O número é variável pois o tamanho do bloco é limitado e diferentes tipos de transações ocupam espaços diferentes. Por exemplo, uma transação muitos para muitos ocupará muito mais espaço do que uma transação um para um.

Transações são transferências de valores (bitcoins) entre endereços Bitcoin. Estes endereços são identificadores únicos, anônimos, criados pelos atores, que funcionam como contas em bancos.

Um ator que deseja transferir bitcoins irá enviar para uma rede peer-to-peer sua transação. Cada nó da rede (que são outros atores) repassa as transações que recebe para outros nós. Qualquer nó pode iniciar um processo de criação de um novo bloco coletando transações recebidas e, então, minerando este bloco. O primeiro ator a minerar com sucesso transmite este bloco para toda a rede; cada nó verifica a hash e, se estiver correta, adiciona o bloco na sua cópia local da blockchain. Com o novo bloco no lugar, mineradores coletam novas transações e repetem o processo.

O protocolo Bitcoin possui um processo automático de controle de dificuldade de mineração, de forma que a média de tempo entre blocos novos seja de dez minutos. A dificuldade é controlada essencialmente aumentando ou reduzindo as restrições nos hashes aceitos durante o processo de mineração (isto é, o número de zeros na frente da hash).

Naturalmente, é necessário que se garanta que apenas os donos dos endereços possam criar transações que envolvam tirar bitcoins daquele endereço; do contrário, seria trivial gastar bitcoins de terceiros. Isso é feito por meio de criptografia de chave pública, com a RSA.

Cada endereço bitcoin é derivado de uma chave pública. Ao criar uma transação, é necessário que dono dessa chave assine a transação com sua chave privada e forneça a chave pública. Assim, é possível que qualquer um verifique que a transação foi criada pelo próprio dono do endereço — basta usar a chave pública para decodificar a assinatura e verificar que o endereço pode ser derivado desta chave.

--

--

Ricardo Araujo

Computer Science professor at UFPel. Machine Learning and Artificial Intelligence practitioner and researcher.