Como fazer uma blockchain usando Maizena e Javascript

Thiago Cerutti
Way2rocks
Published in
6 min readOct 28, 2021

Blockchain é uma das buzzwords do momento, e por isso é alvo daquela fatídica ideia do “a tecnologia tal é bacana, vamos arranjar um problema para podermos usar blockchain para resolver” 🤨

Pois então, blockchain não é uma tecnologia revolucionária que nasceu ontem. Na verdade o conceito foi criado a partir de um problema comum porém complexo de ser resolvido: como garantir que registros de data e hora (os famosos "timestamps") fossem imutáveis em um conjunto de dados. Stuart Haber e W. Scott Stornetta escreveram este paper em 1991 a respeito, e foi a partir dali que a ideia de cadeia de blocos, ou a buzzword "blockchain", começou a engatinhar em direção ao hype de hoje.

Simplificando a complexidade

Como o termo já diz, blockchain é uma cadeia de blocos (de dados). Simples assim. Porém ela conta com uma propriedade "mágica" muito especial: cada bloco guarda a hash dos dados do bloco anterior. E é aí que mora a magia da coisa!

Blockchain é tão mágica quanto este indivíduo (…)

Batatinha frita, hash, hash, hash

Uma hash é calculada de acordo com uma lógica específica, e os dados que passam pelo processo de “hashing” não podem mais ser recuperados. Tá, mas pra que diabos então eu iria querer uma hash de um dado?

???

Uma hash é como uma impressão digital dos dados, e hashing é o processo de “embaralhar” os dados de forma que eles não possam mais ser recompostos. Porém sempre que temos o mesmo dado de entrada, ao passar pelo processo de hashing a saída será sempre a mesma. A hash assegura que uma vez que aquele dado foi criado e passado pelo processo de hashing, ele não foi alterado posteriormente, pois caso seja alterado a hash resultante será diferente da original.

Em distros Linux por exemplo é muito comum que a ISO do sistema operacional seja distribuída juntamente com a hash gerada a partir da imagem original, para que a integridade dos dados do sistema possa ser verificada:

Imagem ISO do Ubuntu 20.04 com sua hash de verificação, em https://releases.ubuntu.com/20.04/

Hashing na prática

Digamos que eu quero mandar a seguinte mensagem pra minha mãe: “mãe, traz pão”. Passando este texto (dado) por um algoritmo de hashing SHA256 eu tenho o seguinte resultado:

90fd2aaa7aba0979cf6b7b088e6360ef597717ed9cf2e34026fc0b5780d0ffcd

Você mesmo pode fazer o teste, passando o texto original neste site e verificando que a hash acima será gerada a partir dele. Se eu mudar minha mensagem original para “mãe, traz queijo”, a hash resultante será:

6aad84468d3654b733c8228e01137a82d7be5ecef95f9c9a8c6caae2cd878767

Minha mãe, trazendo pão e me ouvindo falar em hashes

Ou seja, a segunda hash gerada foi totalmente diferente da primeira. Então a única maneira de eu gerar a primeira hash é com o texto exato “mãe, traz pão”. E é virtualmente impossível por tentativa e erro eu aplicar alguma engenharia reversa a ponto de encontrar o texto original a partir da primeira hash. Pronto, já temos um dos principais elementos de uma blockchain!

Acorrentando os blocos com as hashes

Ótimo, já sabemos o que são e pra que servem hashes, agora é hora de usá-las para "amarrar" os blocos, garantindo assim a integridade dos dados.

[Bad Joke Alert] Alguém pegou a referência? O nome dessa banda é Alice in Chains 😜

Digamos que eu venda o produto X para o Pedro por R$100, ou seja, Pedro fica com meu produto e eu fico com os R$ 100. Um bom exemplo de dados da transação seria:

“de:Pedro;para:Thiago;valor:100.00;data_hora:18/10/2021 21:59:13”

Passando esse dado em um algoritmo SHA256, temos a seguinte hash:

cd33edf387e6e2db35741f5308f784fdf8d4185f449392343dc016f3f9cbc597

Em uma blockchain, chamamos o primeiro bloco de “genesis block”, pois ele não tem referência ao bloco anterior, porque… não existe um bloco anterior (soa Bíblico, não?!). Mesmo assim colocaremos a data em que o bloco genesis foi gerado como dado daquele bloco, para a partir desse dado gerarmos uma hash, que será utilizada no primeiro bloco de dados (Bloco 1). Então ao adicionarmos o nosso primeiro bloco com os dados da transação que acabou de ocorrer, temos:

Além da confiabilidade provida pela hash, uma blockchain é distribuída, então a mesma cópia desse bloco é enviada para centenas ou até milhares de computadores, e uma vez que esses computadores registram essa informação, ela não pode mais ser alterada.

Se eu fizer outra venda, agora recebo o pagamento da Maria no valor de R$ 50 e registro mais uma operação na blockchain:

“de:Maria;para:Thiago;valor:50.00;data_hora:19/10/2021 09:13:55”

Esses dados gerarão a seguinte hash:

5e4632938a72ec5697fdfc497e4d4b89a8dc110421f42aab72378df14b7407c7

Agora já podemos registrar mais um bloco na nossa blockchain, com a transação que acabou de ocorrer:

Se pegarmos todas as vendas que fiz tanto para o Pedro (R$100) quanto para a Maria (R$ 50), chego a um saldo de R$ 150 em vendas. Mas malandramente eu quero alterar este primeiro registro de venda, pois se eu alterasse de R$ 100 para R$ 130, a diferença nem seria tão grande, ninguém iria perceber, e eu teria um saldo final em conta de R$ 180, certo? 👀

Se eu conseguir alterar esse primeiro registro de R$ 100 para R$ 130, a hash resultante deste bloco seria;

809c49ace79a00ad50bc6c222d5a97a28a15e4066fb82f088e45a4089bad63c3

Mesmo que eu consiga alterar este registro em todos os computadores que fazem parte da blockchain, o Bloco 2 ainda diz que a hash do bloco anterior é:

c3f79d1133f9993e86cc8ca1d449c96e12a96d4e951d4b77bcee3c5d23edb5bd

Ou seja, eu teria que atualizar todos os blocos dali pra frente, recalculando todas as hashes a partir do meu bloco alterado. E essa é a definição de "o crime não compensa" em uma blockchain, porque é virtualmente impossível recalcular todas as hashes de todos os blocos a partir de uma alteração, e replicar isso em todos os computadores da blockchain.

E o JavaScript? E a Maizena?

Agora que entendemos o conceito por trás de uma blockchain, podemos colocar a mão na massa! Vamos implementar a nossa própria blockchain com Maizena (…) e Javascript. 😎

Para adiantar as coisas, deixei o código pronto lá no meu GitHub. Mas basicamente o que faço é definir uma classe (sim, JS moderno é uma linguagem de classe 😏), com um construtor que vai gerar o nosso "Genesis Block", e criamos o atributo chain que receberá um array com um único elemento, o nosso Genesis Block:

Depois da blockchain criada já com o Genesis Block, podemos adicionar dados a ela:

Neste caso adicionei dois registros, um com meu cargo e o Peter com o cargo dele, e chamei o método de validação da nossa blockchain, que verifica cada hash e compara com a hash do bloco anterior, e o método me retornou informando que o estado da blockchain até aqui é válido. 🌟

Depois eu altero o primeiro registro, mudando a minha função de “dev” para "manager", e chamo novamente o método de validação da blockchain:

Como a informação do bloco 1 foi alterada, a referência de hashes entre o Bloco 2 e a hash do Bloco 1 já não batem, e assim o estado da blockchain é considerado inválido. 😐

E é por isso que pode-se considerar uma blockchain como um "insert only database", só que distribuído, o que garante que, uma vez que uma informação foi inserida lá, jamais será apagada nem alterada sem que o estado da blockchain como um todo se torne inválido.

Muito possivelmente exploraremos mais sobre quais problemas reais uma blockchain pode resolver, especialmente focado no mercado de energia, em um futuro não muito distante. Stay tunned!😉

--

--