Como construir um blockchain de criptomoeda simples no Node.js

Publicados: 2022-03-10
Resumo rápido ↬ Este tutorial demonstra como criar uma criptomoeda simples, chamada smashingCoin , usando os conceitos de classes JavaScript e Node.js. Experimente - é mais simples do que você pensa!

O aumento sem precedentes das criptomoedas e sua tecnologia blockchain de sustentação tomaram o mundo de assalto – desde o início humilde de ser um conceito acadêmico há mais de uma década até o aumento da adoção atual em vários setores.

A tecnologia blockchain está recebendo muita atenção por causa de sua capacidade de aumentar a segurança em ambientes sem confiança, impor a descentralização e tornar os processos eficientes.

Tradicionalmente, o Python tem sido a linguagem de programação de fato para o desenvolvimento de blockchain. No entanto, com a proliferação dessa tecnologia incrível, as opções de desenvolvimento também aumentaram — e o Node.js não ficou para trás.

Neste tutorial, falarei sobre como construir um blockchain de criptomoeda simples em Node.js. Não será muito sofisticado, mas apenas o suficiente para ajudá-lo a entender como funciona um blockchain.

Vou chamar essa simples criptomoeda de smashingCoin .

Se você é um desenvolvedor JavaScript que deseja dar um salto no campo florescente das criptomoedas, este artigo irá equipá-lo com as habilidades necessárias para começar. Ou, se você está curioso sobre como as coisas funcionam no mundo das criptomoedas, este tutorial pode ajudar a responder algumas de suas perguntas.

Leitura recomendada : Entendendo a integridade dos sub-recursos por Drew McLellan

Pré-requisitos

Para seguir este tutorial com sucesso, você precisará ter o seguinte:

  • Node.js instalado em sua máquina. Você pode fazer o download aqui;
  • Um editor de código, como Visual Studio Code, Sublime Text ou qualquer outro.

Vamos começar…

Mais depois do salto! Continue lendo abaixo ↓

O que é uma Blockchain?

Blockchain é a tecnologia que alimenta as moedas digitais, como Bitcoin e Ethereum. É uma tecnologia inovadora de contabilidade pública distribuída que mantém uma lista crescente de registros, chamados de blocos, que são conectados de forma segura usando criptografia.

O termo blockchain ganhou esse nome devido à forma como mantém os dados das transações, ou seja, em blocos que são conectados entre si para criar uma cadeia . O tamanho do blockchain cresce com o aumento do número de transações realizadas.

Quaisquer dados de transação válidos são registrados na rede blockchain, que é regida por regras peer-to-peer que os participantes estipulam. Por exemplo, esses dados podem conter o “valor” do bloco, como em moedas digitais, um registro de transações (como quando as partes trocam bens e serviços) ou privilégios de titularidade, como quando a cadeia registra informações de propriedade.

Além dos dados da transação, cada bloco pode conter seu próprio hash criptográfico (um identificador exclusivo ou pegada digital), seu próprio valor de nonce (um número aleatório arbitrário usado uma vez em cálculos criptográficos), o hash do bloco anterior e um carimbo de data e hora de dados recentes. transações autenticadas.

Como cada novo bloco deve apontar para o bloco anterior, se um bloco for incorporado à cadeia sem conter o hash correto do último bloco, isso poderá tornar todo o blockchain inválido. Essa propriedade de imutabilidade é fundamental para a segurança das blockchains.

Além disso, vários tipos de protocolos de consenso são frequentemente aplicados para manter a autenticidade do blockchain. O consenso garante que todos os participantes concordem com as transações validadas pela rede.

Por exemplo, um protocolo de consenso comumente usado é a prova de trabalho, que visa identificar um número que encontra uma solução para um problema matemático complicado após a conclusão de uma certa quantidade de trabalho de computação.

A ideia principal do trabalho de prova é que qualquer participante da rede blockchain deve achar esse número difícil de identificar, mas facilmente verificável. Consequentemente, desencoraja o spam e a adulteração da estrutura do blockchain.

No caso da maioria das criptomoedas, adicionar um novo bloco ao blockchain requer a resolução de uma equação matemática complexa, que aumenta a dificuldade ao longo do tempo à medida que o blockchain cresce. Consequentemente, qualquer pessoa que comprove ter feito um trabalho resolvendo esse problema é compensada com uma moeda digital, em um processo chamado de “mineração”.

Como criar um bloco

Agora, depois de apresentar a tecnologia blockchain e como ela funciona, vamos ver como podemos aplicar os conceitos na criação de um bloco. Como mencionado anteriormente, os blocos são o que se interligam para formar uma blockchain.

Para criar a moeda smashingCoin , usarei classes JavaScript, que foram introduzidas no ES6.

Preparar?

Vamos sujar as mãos...

Aqui está o código para a classe CryptoBlock :

 const SHA256 = require('crypto-js/sha256'); class CryptoBlock{ constructor(index, timestamp, data, precedingHash=" "){ this.index = index; this.timestamp = timestamp; this.data = data; this.precedingHash = precedingHash; this.hash = this.computeHash(); } computeHash(){ return SHA256(this.index + this.precedingHash + this.timestamp + JSON.stringify(this.data)).toString(); } }

Como você pode ver no código acima, criei a classe CryptoBlock e adicionei o método constructor() a ela — assim como em qualquer outra classe JavaScript. Então, para inicializar suas propriedades, atribuí os seguintes parâmetros ao método constructor :

index É um número único que rastreia a posição de cada bloco em toda a blockchain.
timestamp Ele mantém um registro do tempo de ocorrência de cada transação concluída.
data Ele fornece dados sobre as transações concluídas, como detalhes do remetente, detalhes do destinatário e quantidade transacionada.
precedingHash Ele aponta para o hash do bloco anterior no blockchain, algo importante para manter a integridade do blockchain.

Além disso, usei o método computeHash para calcular o hash do bloco com base em suas propriedades, conforme dados acima.

Como você pode ver, importei a biblioteca JavaScript crypto-js e usei seu módulo crypto-js/sha256 para calcular o hash de cada bloco. Como o módulo retorna um objeto numérico, usei o toString() para convertê-lo em uma string.

Para adicionar a biblioteca crypto-js ao seu projeto, acesse o terminal e execute o seguinte comando para instalá-lo usando npm :

 npm install --save crypto-js

Após executar o comando acima, o diretório de módulos do nó, que contém a biblioteca e outros arquivos essenciais, será adicionado à pasta do seu projeto.

Como criar uma blockchain

Como explicado anteriormente, a tecnologia blockchain é baseada no conceito de que todos os blocos estão encadeados uns aos outros. Então, vamos criar uma classe CryptoBlockchain que será responsável por lidar com as operações de toda a cadeia. É aqui que a borracha vai encontrar a estrada.

A classe CryptoBlockchain manterá as operações do blockchain usando métodos auxiliares que realizam diferentes tarefas, como criar novos blocos e adicioná-los à cadeia.

Aqui está o código para a classe CryptoBlockchain :

 class CryptoBlockchain{ constructor(){ this.blockchain = [this.startGenesisBlock()]; } startGenesisBlock(){ return new CryptoBlock(0, "01/01/2020", "Initial Block in the Chain", "0"); } obtainLatestBlock(){ return this.blockchain[this.blockchain.length - 1]; } addNewBlock(newBlock){ newBlock.precedingHash = this.obtainLatestBlock().hash; newBlock.hash = newBlock.computeHash(); this.blockchain.push(newBlock); } }

Deixe-me falar sobre os papéis de cada um dos métodos auxiliares que constituem a classe CryptoBlockchain .

1. Método Construtor

Este método instancia o blockchain. Dentro do construtor, criei a propriedade blockchain , que se refere a um array de blocos. Observe que passei para ele o método startGenesisBlock() , que cria o bloco inicial na cadeia.

2. Criando o Bloco Genesis

Em uma blockchain, o bloco de gênese refere-se ao primeiro bloco criado na rede. Sempre que um bloco é integrado ao restante da cadeia, ele deve referenciar o bloco anterior.

Por outro lado, no caso desse bloco inicial, ele não possui nenhum bloco anterior para apontar. Portanto, um bloco de gênese geralmente é codificado no blockchain. Desta forma, blocos subsequentes podem ser criados nele. Geralmente tem um índice de 0.

Usei o método startGenesisBlock() para criar o bloco genesis. Observe que eu o criei usando a classe CryptoBlock criada precedingHash e passei os parâmetros index , timestamp , data e previousHash .

3. Obtendo o bloco mais recente

Obter o bloco mais recente no blockchain ajuda a garantir que o hash do bloco atual aponte para o hash do bloco anterior - mantendo assim a integridade da cadeia.

Eu usei o método obtainLatestBlock() para recuperá-lo.

4. Adicionando novos blocos

Eu usei o método addNewBlock() para adicionar um novo bloco à cadeia. Para fazer isso, defino o hash anterior do novo bloco para ser igual ao hash do último bloco na cadeia - garantindo assim que a cadeia seja à prova de adulteração.

Como as propriedades do novo bloco são alteradas a cada novo cálculo, é importante calcular seu hash criptográfico novamente. Depois de atualizar seu hash, o novo bloco é enviado para o array blockchain.

Na realidade, adicionar um novo bloco a uma blockchain não é tão fácil por causa das várias verificações que foram feitas. No entanto, para essa criptomoeda simples, basta demonstrar como um blockchain realmente funciona.

Testando o Blockchain

Agora, vamos testar nosso blockchain simples e ver se funciona.

Aqui está o código:

 let smashingCoin = new CryptoBlockchain(); smashingCoin.addNewBlock(new CryptoBlock(1, "01/06/2020", {sender: "Iris Ljesnjanin", recipient: "Cosima Mielke", quantity: 50})); smashingCoin.addNewBlock(new CryptoBlock(2, "01/07/2020", {sender: "Vitaly Friedman", recipient: "Ricardo Gimenes", quantity: 100}) ); console.log(JSON.stringify(smashingCoin, null, 4));

Como você pode ver no código acima, criei uma nova instância da classe CryptoBlockchain e a nomeei como smashingCoin . Então, adicionei dois blocos ao blockchain usando alguns valores arbitrários. No parâmetro data , usei um objeto e adicionei detalhes do remetente, detalhes do destinatário e quantidade transacionada.

Se eu executar o código no terminal, aqui está a saída que recebo:

Como um blockchain se parece sob o capô
Testando para ver se nosso blockchain funciona. (Visualização grande)

É assim que o smashingCoin se parece! É um objeto que contém a propriedade blockchain , que é um array contendo todos os blocos da cadeia. Como você pode ver na imagem acima, cada bloco referencia o hash do bloco anterior. Por exemplo, o segundo bloco faz referência ao hash do primeiro bloco. Depois de testar e ver que nosso blockchain funciona, vamos adicionar mais algumas funcionalidades para aprimorar os recursos do smashingCoin .

Como verificar a integridade do Blockchain

Como mencionado anteriormente, uma característica chave de uma blockchain é que uma vez que um bloco tenha sido adicionado à cadeia, ele não pode ser alterado sem invalidar a integridade do resto da cadeia.

Portanto, para verificar a integridade do blockchain, adicionarei um método checkChainValidity() à classe CryptoBlockchain .

Os hashes são críticos para garantir a validade e a segurança de um blockchain porque qualquer alteração no conteúdo de um bloco resultará na produção de um hash totalmente novo e na invalidação do blockchain.

Como tal, o método checkChainValidity() fará uso de instruções if para verificar se o hash de cada bloco foi adulterado. A partir do primeiro bloco criado, ele percorrerá todo o blockchain e verificará sua validade. Observe que, como o bloco de gênese foi codificado, ele não será verificado.

Além disso, o método verificará se os hashes de cada dois blocos consecutivos estão apontando um para o outro. Se a integridade do blockchain não foi comprometida, ele retorna true; caso contrário, em caso de alguma anomalia, retorna false.

Aqui está o código:

 checkChainValidity(){ for(let i = 1; i < this.blockchain.length; i++){ const currentBlock = this.blockchain[i]; const precedingBlock= this.blockchain[i-1]; if(currentBlock.hash !== currentBlock.computeHash()){ return false; } if(currentBlock.precedingHash !== precedingBlock.hash) return false; } return true; }

Como adicionar prova de trabalho

Como mencionado anteriormente, a prova de trabalho é o conceito aplicado para aumentar a dificuldade envolvida na mineração ou adição de novos blocos ao blockchain.

No caso do smashingCoin , vou empregar um algoritmo simples que impede as pessoas de gerar novos blocos facilmente ou enviar spam para o blockchain.

Então, na classe CryptoBlock , adicionarei outro método chamado proofOfWork(). Essencialmente, esse algoritmo simples identifica um número, passado como uma propriedade de difficulty , de modo que o hash de cada bloco contenha zeros à esquerda que correspondem a esse nível de difficulty .

Garantir que o hash de cada bloco comece com o número de zeros definido no nível de difficulty requer muito poder de computação. Quanto maior o nível de dificuldade, mais tempo leva para minerar novos blocos.

Além disso, adicionarei um valor de nonce aleatório a cada bloco com hash, de modo que, quando o rehashing ocorrer, as restrições de nível de dificuldade ainda possam ser atendidas.

Aqui está o código:

 proofOfWork(difficulty){ while(this.hash.substring(0, difficulty) !==Array(difficulty + 1).join("0")){ this.nonce++; this.hash = this.computeHash(); } }

E aqui está o método computeHash() atualizado com a variável nonce incluída:

 computeHash(){ return SHA256(this.index + this.precedingHash + this.timestamp + JSON.stringify(this.data)+this.nonce).toString(); }

Além disso, para implementar o mecanismo de prova de trabalho na geração de novos blocos, vou incluí-lo no método addNewBlock() :

 addNewBlock(newBlock){ newBlock.precedingHash = this.obtainLatestBlock().hash; //newBlock.hash = newBlock.computeHash(); newBlock.proofOfWork(this.difficulty); this.blockchain.push(newBlock); }

Empacotando

Aqui está todo o código para construir a criptomoeda smashingCoin usando Node.js:

 const SHA256 = require("crypto-js/sha256"); class CryptoBlock { constructor(index, timestamp, data, precedingHash = " ") { this.index = index; this.timestamp = timestamp; this.data = data; this.precedingHash = precedingHash; this.hash = this.computeHash(); this.nonce = 0; } computeHash() { return SHA256( this.index + this.precedingHash + this.timestamp + JSON.stringify(this.data) + this.nonce ).toString(); } proofOfWork(difficulty) { while ( this.hash.substring(0, difficulty) !== Array(difficulty + 1).join("0") ) { this.nonce++; this.hash = this.computeHash(); } } } class CryptoBlockchain { constructor() { this.blockchain = [this.startGenesisBlock()]; this.difficulty = 4; } startGenesisBlock() { return new CryptoBlock(0, "01/01/2020", "Initial Block in the Chain", "0"); } obtainLatestBlock() { return this.blockchain[this.blockchain.length - 1]; } addNewBlock(newBlock) { newBlock.precedingHash = this.obtainLatestBlock().hash; //newBlock.hash = newBlock.computeHash(); newBlock.proofOfWork(this.difficulty); this.blockchain.push(newBlock); } checkChainValidity() { for (let i = 1; i < this.blockchain.length; i++) { const currentBlock = this.blockchain[i]; const precedingBlock = this.blockchain[i - 1]; if (currentBlock.hash !== currentBlock.computeHash()) { return false; } if (currentBlock.precedingHash !== precedingBlock.hash) return false; } return true; } } let smashingCoin = new CryptoBlockchain(); console.log("smashingCoin mining in progress...."); smashingCoin.addNewBlock( new CryptoBlock(1, "01/06/2020", { sender: "Iris Ljesnjanin", recipient: "Cosima Mielke", quantity: 50 }) ); smashingCoin.addNewBlock( new CryptoBlock(2, "01/07/2020", { sender: "Vitaly Friedman", recipient: "Ricardo Gimenes", quantity: 100 }) ); console.log(JSON.stringify(smashingCoin, null, 4));

Se eu executar o código no terminal, aqui está a saída que recebo:

Resultado da criação de uma criptomoeda simples em Node.js
Finalmente, nossa criptomoeda smashingCoin ! (Visualização grande)

Como você pode ver na imagem acima, os hashes agora começam com quatro zeros, que correspondem ao nível de dificuldade definido no mecanismo de prova de trabalho.

Conclusão

É isso! É assim que você pode construir um blockchain de criptomoeda simples usando Node.js.

Claro, a criptomoeda smashingCoin está longe de ser completa. Na verdade, se você lançá-lo sem fazer mais melhorias, é improvável que atenda às demandas atuais do mercado por uma moeda digital segura, confiável e intuitiva - tornando você o único a usá-lo!

No entanto, espero que este tutorial tenha equipado você com algumas habilidades básicas para mergulhar no emocionante mundo das criptomoedas.

Se você tiver quaisquer comentários ou perguntas, por favor, poste-os abaixo.

Recursos adicionais

  • “Blockchain 101,” CoinDesk
  • “Bitcoin: um sistema de dinheiro eletrônico ponto a ponto”, Satoshi Nakamoto, Bitcoin.org