Você pesquisou sobre Bockchain, viu e leu algumas explicações teóricas mas não conseguiu imaginar como fica a implementação dos blocos? Como é a mineração do hash do bloco?
A seguir uma implementação bem conceitual, simples e reduzida do encadeamento em blocos, complementando o entendimento teórico.
Usarei C#, mas como o código é super simples, facilmente pode ser traduzido para a linguagem de sua preferência.
Antes de iniciar, o repositório com o código fonte completo está disponível em:
Começando do final
Resumidamente, cada bloco do blockchain irá conter:
- Os dados de interesse a serem assinados
- Uma assinatura de data e hora
- O hash do bloco anterior
- Número sequencial de ajuste do hash
Então ao adicionar um bloco à corrente é necessário descobrir um novo hash válido para esse bloco, adicionar os dados de interesse e ligar com o hash anterior.
Podemos representar este o programa final então da seguinte forma:
1 | static void Main(string[] args) |
Iniciando a corrente
O blockchain será iniciado através do objeto ‘chain‘, que será a instância da classe “BlockChain“
1 | BlockChain chain = new BlockChain(difficulty, genesis); |
Esta classe recebe a dificuldade, que está neste exemplo definido em 2 bytes e o genesis, que é interface da estrutura do bloco
1 | //A variável genesis é do tipo 'IBlock' |
No construtor da classe BlockChain, um novo hash é minerado para ser atribuído ao bloco que está sendo criado.
Por enquanto não precisamos nos atentar a como esta mineração é realizada.
1 | public BlockChain(byte[] difficulty, IBlock genesis) |
Neste nosso exemplo, a classe ‘BlockChain‘ será instanciado somente uma única vez. Os próximos blocos e minerações serão realizados através do método ‘Add‘, que será mostrado com mais detalhes a seguir.
Adicionado novos blocos à corrente
Depois de criado o bloco inicial, onde está definido a dificuldade de mineração e assinatura dos hash’s, base adicionar os novos blocos na corrente criada. Esta ação é realizada a através do método ‘Add‘, que conterá as implementações necessárias.
1 | public void Add(IBlock item) |
Mineração dos hash’s
A mineração de novos hash’s é realizada pelo método ‘MineHash‘, que nada mais é do que um hash das informações concatenadas do bloco. Neste exemplo, estamos gerando o hash através do método GenerateHash da seguinte maneira:
1 | public static byte[] GenerateHash(this IBlock block) |
Porém a diferença é que estamos procurando por assinatura de hash com prefixo específico. A dificuldade que definimos inicialmente está determinando o prefixo dos primeiros bytes que o hash deve possuir, e então aí entra a parte da ‘mineração‘.
O hash é gerado e a sequência inicial é verificada. Enquanto não possuir o prefixo buscado, utilizamos a propriedade ‘Nonce‘ para incrementar um valor, mudando assim a assinatura do bloco por completo.
Faremos o incremento na propriedade para mudar o hash até que este possua o prefixo desejado, por força bruta de tentativa e erro.
Por isso que o aumento da dificuldade resulta em um tempo maior de mineração.
1 | public static byte[] MineHash(this IBlock block, byte[] difficulty) |
Verificando a validade de um bloco
Agora ficou simples, cada bloco vai possuir o hash de assinatura do seu próprio bloco e também carregará a assinatura do hash do bloco anterior, fazendo com que toda a cadeia fique fechada para alterações.
Para validar isoladamente um bloco, basta geramos novamente o hash de suas informações e comparar com o hash que ele carrega. O mesmo vale para o hash do bloco anterior
1 | public static bool IsValid(this IBlock block) |
Podemos também validar toda a cadeia da seguinte forma:
1 | public static bool IsValid(this IEnumerable<IBlock> items) |
Conclusão
Pessoas diferentes aprendem de formas diferentes. Quando eu mesmo fiz a implementação deste exemplo, consegui enxergar com mais clareza como um blockchain deve funcionar além da teoria.
Existem muitos problemas que podem ser resolvidos com uma implementação própria de algoritmos deste tipo, como validação de transações financeiras, assinaturas de documentos digitais, entre outros onde este modelo inicial pode ser um ponto de partida.
Referências
O código foi implementado utilizando como referência uma lista de vídeos que se inicia por este aqui: