Já tem pelo menos 5 anos que ouço falar de Blockchain. E olha que eu ouvi falar tarde.
O conceito de Blockchain é da década de 90 e vem lá dos laboratórios da Xerox, em Palo Alto, Califórnia. Sim, o mesmo laboratório que inventou o mouse e a interface gráfica na década de 70. Os caras são bons por lá, viu…
Apesar de ser um conceito “noventista”, sua primeira aplicação prática e famosa foi com a invenção do Bitcoin em 2008, por Satoshi Nakamoto. Embora o próprio Satoshi não cite o termo “blockchain” em seu white-paper de explicação do Bitcoin, os termos blocks e chain (blocos e cadeia/corrente) são citados diversas vezes, tendo originado então o termo como o conhecemos desde então.
Mas final, o que é a blockchain então? Como ela funciona? Como uma blockchain é programada?
Na tentativa de responder estas questões que escrevo este artigo que mais à frente deve se tornar um tutorial prático, logo após os fundamentos.
O conteúdo deste artigo/tutorial pode ser conferido nesta playlist.
O que é Blockchain?
A primeira coisa que você tem de entender é que blockchain é um tipo de banco de dados.
Mas não é um banco de dados comum, ele possui algumas características únicas.
A primeira delas é que ao invés de tabelas e colunas ela possui blocos que se interconectam, formando uma corrente (chain). Cada bloco possui várias informações no seu interior, que falaremos a seguir, mas principalmente, todo bloco possui uma referência ao seu bloco anterior, chamado hash. Essa referência é extremamente sensível e se o bloco anterior mudar, ela se torna “inválida”.
Se você nunca ouviu falar em hash, recomendo fortemente o meu aulão de criptografia, disponível no Youtube, onde explico os principais métodos, incluindo hashing.
Assim sendo, a segunda característica é que é um banco de dados é imutável, ou seja, você pode consultar e adicionar dados à vontade, mas jamais remover ou editar. Isso porque sendo uma corrente de blocos, qualquer tentativa de mexer em um bloco existente partiria a referência entre os blocos e consequentemente a corrente. Assim, você só pode adicionar novos blocos no final.
A terceira característica é que ela é descentralizada, ou seja, não fica em apenas um servidor, mas sim em vários nodes (nós) que atuam em cooperação para manter a blockchain no ar, segura e em funcionamento. Nós podem entrar e sair livremente da rede e enquanto ao menos um nó estiver online, a blockchain permanecerá em funcionamento. O funcionamento da blockchain consiste em adicionar novos dados continuamente (podendo ser dados de qualquer coisa) ou validar a rede. Nós que registram dados na blockchain são chamados de mineradores e eles são recompensados com tokens ou moedas da própria rede quando fazem essa atividade com sucesso.
No caso da blockchain “original”, a do Bitcoin, podemos adicionar ainda uma quarta característica que é o fato dela ser pública, mas isso não é uma regra em todas blockchains, podendo existir blockchains privadas que envolvam dados sensíveis de governos e empresas, por exemplo. Isso porque apesar da blockchain Bitcoin registrar apenas transações com a moeda de mesmo nome, blockchains como a da Etehereum e outras mais modernas permite o registro de QUALQUER tipo de informação, o que costumamos chamar de Smart Contracts (contratos inteligentes) no jargão da blockchain.
Mas Smart Contracts pode ser um assunto para o futuro.
Mas se você quiser concluir esta etapa mais teórica dando uma fuçada em uma ferramenta visual que simula todas as partes que compõem uma Blockchina, você pode usar este simulador de blockchain do Anders Brownworth. É muito legal pois ele vai desde o conceito mais elementar de hash até a blockchain distribuída, para você entender o funcionamento e principalmente a segurança envolvida.
O que tem em um bloco da Blockchain?
Para explicar de maneira que você realmente entenda, eu proponho o desafio de tentarmos implementar uma blockchain juntos, do zero, usando JavaScript. Claro, será um protótipo e apenas para fins educativos, mas tenho a certeza que vai ajudar bastante a tornar mais claro o entendimento de como uma blockchain funciona.
Para isso, é necessário que você tenha o Node.js instalado na sua máquina, que você pode baixar gratuitamente no site oficial.
Para criar o projeto é bem simples, crie uma pasta chamada blockchain e dentro dela rode o comando de inicialização de projeto.
1 2 3 |
npm init -y |
Como mencionado antes, a peça mais elementar de toda blockchain são os blocos, então é por eles que começaremos. Como vamos precisar ter vários blocos, mas todos eles possuem a mesma estrutura, faz muito sentido usarmos classes para isso. Então vamos criar uma classe Block na raiz do nosso projeto.
Mas quais seriam os atributos desta classe? Todo bloco precisa de:
- index: o número do bloco;
- previousHash: o hash do bloco anterior;
- data: os dados do bloco (podem ser transações, Smart Contracts, etc);
- timestamp: o carimbo de data e hora que esse bloco foi gerado;
- hash: a assinatura digital deste bloco, gerada a partir de todos os dados anteriores;
Traduzir estas informações para uma classe JS é muito simples, como segue, sendo que intencionalmente deixei a parte do hash incompleta:
1 2 3 4 5 6 7 8 9 10 11 |
module.exports = class Block { constructor(index = 0, previousHash = null, data = 'Genesis Block') { this.index = index; this.previousHash = previousHash; this.data = data; this.timestamp = new Date(); this.hash = null; } } |
Repare nos valores default que representam o estado do “bloco gênese”, que é sempre o primeiro bloco de toda blockchain. Ele possui o índice 0, não possui hash anterior e seus dados são apenas a indicação que ele é o dito-cujo. Existe outro dado default aí no meio que é o timestamp, que sempre será a data atual de criação do bloco.
Agora, temos que implementar a geração do hash deste bloco, sua assinatura digital. Para isso, precisaremos instalar um pacote adicional em nosso projeto, o crypto-js, uma biblioteca cheia de implementações de algoritmos úteis de criptografia.
1 2 3 |
npm i crypto-js |
Agora vamos referenciar esta lib em nosso módulo Block.js e dentro dele vamos chamar uma nova função de geração do hash a partir de todos os dados internos do bloco.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
const sha256 = require('crypto-js/sha256'); module.exports = class Block { constructor(index = 0, previousHash = null, data = 'Genesis Block') { this.index = index; this.previousHash = previousHash; this.data = data; this.timestamp = new Date(); this.hash = this.generateHash(); } generateHash() { return sha256(this.index + this.previousHash + JSON.stringify(this.data) + this.timestamp).toString(); } } |
Ou seja, ao criar o bloco (constructor), automaticamente já calculamos o hash dele, para que seja possível adicioná-lo à corrente. O algoritmo de hashing usado aqui foi o SHA-256, recomendado inclusive pelo Google e considerado um dos mais rápidos e seguros para os padrões atuais. Ainda assim, poderia ser substituído por algoritmos diferentes, conforme o interesse do arquiteto da blockchain.
Repare que o atributo data pode ser qualquer coisa, como já mencionado anteriormente e estou adotando aqui o o uso de um objeto JS para ele, o que fica explícito na função de gerar o hash em que transformo ele em string através do JSON.stringify.
Experimente criar um index.js e instancie alguns Blocks, como abaixo, apenas para jogar em um console.log e ver o que foi gerado. Vai te ajudar a entender melhor a anatomia de um bloco.
1 2 3 4 5 6 |
const Block = require("./Block"); const bloco1 = new Block(); console.log(bloco1); |
Experimente inclusive criar blocos passando ou não os parâmetros do constructor e verá que mesmo que a diferença no data seja de apenas uma letra, sua assinatura digital será quase completamente diferente sempre.
Como os blocos são ligados na Blockchain?
Agora que aprendemos como criar um bloco, que tal criarmos uma cadeia deles?
Isso é possível de ser feito tanto usando classes quanto usando um módulo simples em JS, já que não é comum um projeto de blockchain subir vários em paralelo. Ainda assim acredito que solução orientada a objetos (com classes) fica mais elegante devido a alguns comportamentos default que são necessários.
Sendo assim, o que deveria ter de atributos em uma classe Blockchain?
- blocks: um array de blocos que pode crescer indefinidamente e que comece com o bloco gênese;
- nextIndex: o próximo índice do array onde podemos adicionar um novo bloco;
Claro, isso é para começarmos a falar de blockchain e a implementação abaixo é propositalmente simples para nossos primeiros testes, coloque-a em um arquivo Blockchain.js.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
const Block = require('./block') module.exports = class Blockchain { constructor() { this.blocks = [new Block()]; this.nextIndex = 1; } getLastHash() { return this.blocks[this.blocks.length - 1].hash; } addBlock(data) { const hash = this.getLastHash(); const block = new Block(this.nextIndex++, hash, data); this.blocks.push(block); } } |
Nesta implementação ingênua o array de blocos é inicializado com o bloco gênese logo na criação da blockchain e o índice do próximo bloco a ser adicionado é definido em 1 (já que o primeiro recebe a posição zero). Também já deixamos posicionada uma função para adicionar um novo bloco na corrente, apenas recebendo os seus dados, já que as demais informação são automáticas (timestamp por exemplo) ou gerenciadas pela blockchain (index por exemplo).
Você pode testar esta classe facilmente no seu index.js, criando uma blockchain do zero e adicionando blocos à ela.
1 2 3 4 5 6 7 |
const Blockchain = require("./Blockchain"); const blockchain = new Blockchain(); blockchain.addBlock([{ from: 'a', to: 'b', amount: 10 }]); console.log(blockchain); |
Repare que optei por usar como data um array de transações. Em cada transação podemos dizer quem (from) está enviando dinheiro (amount) para quem (to). Opcionalmente, você pode criar uma classe Transaction para registrar de maneira mais elegante as transações e os valores de from e to em uma situação de criptomoedas seriam os endereços das carteiras (que são hashes únicos para cada usuário).
Em uma blockchain real, o addBlock deveria registrar também os dados no disco, para não depender apenas de guardar tudo em memória, bem como na sua inicialização (constructor) ele deveria buscar estes dados já salvos para não recomeçar do zero sempre. Em uma situação distribuída e descentralizada, ainda há outros complicadores, que espero falar no futuro também.
Sim, no futuro, pois a nossa saga com blockchain acabou de começar e a parte 2 você já encontra neste link!
Olá, tudo bem?
O que você achou deste conteúdo? Conte nos comentários.