Conceitos, Programação, Programação Funcional

Como fazer uma simples Blockchain com JavaScript

Tempo de leitura: 6 min

Blockchain foi uma das grandes Buzzwords de 2017, foi um tema muito discutido durante o ano. Para algumas pessoas blockchain era a resposta pra todos os problemas…

O que não é bem assim, nós que somos da área de TI sabemos que não existe bala de prata na questão de resolução de problemas, cada problema pode ser resolvido de diversas formas, “corretas” ou não.

“Blockchain é uma solução esperando por problemas para resolver”.(Gerald Nash)

Para quem não sabe, uma Blockchain é basicamente um banco de dados descentralizado, imutável e distribuído que valida cada transação em todos os nós da rede. Isso nos dá a capacidade de usar uma arquitetura p2p(peer to peer). Devido a essa arquitetura os usuários podem fazer transações sem depender de uma “server” central.

Tá mas por que a blockchain recebeu tanto destaque em 2017?

Por quê 2017 foi um ano da ascensão das criptomoedas, o bitcoin teve a sua maior alta e também ganhou um destaque fora do nicho de TI, também tivemos várias aplicações criadas com baseados em blockchain como a Ethereum.

E a blockchain é uma tecnologia que foi criada para o bitcoin ser possível, mas isso não a limita sua aplicação em apenas criptomoedas, no projeto Ethereum, por exemplo, ela te da a possibilidade de criar contratos inteligentes e você pode usar esse conceito para diversas aplicações desde se você necessita de:

  • Autenticidade;
  • Consistência dos Dados;
  • Descentralização;

Ok, eu quero aprender blockchain, como eu faço?

Vamos construir uma!

“A Melhor forma de aprender algo novo é construindo com suas próprias mãos” .(Roman Stremedlovskyi)

Neste artigo, nós vamos implementar uma blockchain pequena e uma conexão peer to peer usando websockets. Não vai ser a melhor blockchain do mundo nem a mais complexa, mas vai ser uma boa base para começar entender como funciona a Blockchain em si e alguns conceitos como: P2P, Imutabilidade, Proof of work.

Eu vou quebrar esse artigo em duas partes, na parte 1 teremos a implementação dos seguintes itens:

  • O Bloco;
  • Chain;

Na parte 2 teremos a implementação do sistema de comunicação P2P com Web Sockets.

1. O Bloco

O Bloco é a parte mais básica de uma blockchain (obvio!), mas o que é um bloco? Basicamente(e no nosso caso) é um objeto literal do JavaScript, no qual, vai armazenar nossas informações que vão ser:

  • Index;
  • PrevHash;
  • Timestamp;
  • Data;
  • Hash;

Onde a propriedade index como está explicito é a referência do nosso Bloco, prevHash é o hash do nosso ultimo bloco e é uma propriedade que usaremos para fazer a validação de blocos, timestamp é a hora que nosso bloco foi adicionado à Chain, a propriedade data é onde iremos colocar nossos dados, que na verdade, podem armazenar qualquer coisa seja uma quantidade de moedas virtuais até mesmo uma certidão de nascimento.

vamos à implementação do bloco:

const crypto = require('crypto-js');
const chain = require('./chain');

module.exports.generateHash = function({index, prevHash, timestamp, data}) {
  return crypto.SHA256(data + index + prevHash + timestamp).toString();;
}

module.exports.create = (data) => {
  const lastBlock = chain.last();
  
  const newblock = {
    index : lastBlock.index + 1,
    prevHash : lastBlock.hash,
    timestamp : new Date().getTime(),
    data : data,
  }
  newblock.hash = this.generateHash(newblock);
  return newblock;
}

module.exports.validateBlock = (newBlock, lastBlock = chain.last()) => {
  let blockIsValid = false;

  if (newBlock.index == lastBlock.index+1) {
    blockIsValid = true;
  } else if (newBlock.prevHash == lastBlock.hash) {
    blockIsValid = true;
  } else if (newBlock.hash == this.generateHash(newBlock)) {
    blockIsValid = true
  }

  return blockIsValid;
}

A o arquivo block.js temos a estrutura básica do nosso bloco, eu implementei a moda antiga, mas você pode implementar com class se quiser.

Neste arquivo temos só três funções, que estão bem auto-explicativas, uma vai gerar os hashs dos blocos, uma para criação de novos blocos, e uma para verificar se o bloco é valido, bem simples de ler e de escrever.

2. A Chain

chain é um pouco mais complexa, para que isto funcione direito, precisamos implementar um singleton.

Vamos ver o código:

const block = require('./block');

const Chain = (function() {
  let instance;

  const firstBlock = {
    index : 0,
    prevHash : 0,
    timestamp : 0,
    data : 'Blockchain is Borning',
    hash : block.generateHash({index : 0, prevHash : 0, timestamp : 0,  data : 'Blockchain is Borning'}),
  };

  const chain = [firstBlock];

  function validateChain(chain) {
    let validChain = true;
    if(JSON.stringify(chain[0]) !== JSON.stringify(origin)) {
      validChain = false;
      return validChain;
    }
    
    const temp = [chain[0]];

    for(let i=1; i < chain.length; i++) {
      if (block.validateBlock(chain[i], temp[i-1])) {
        temp.push(chain[i]);
      } else {
        validChain = false;
        return validChain;
      }
    }

    return validChain;

  }

  function get() {
    return chain;
  };

  function last() {
    return chain.slice().pop();
  }

  function update(newBlock) {
    block.validateBlock(newBlock) ? chain.push(newBlock) : console.log('invalid block recived');
  }

  function replace(newChain) {
    if (validateChain(newChain) && newChain.length > chain.length) {
      chain.splice(0, chain.length);
      chain.push(...newChain);
    } else {
      console.log('invalid chain recived');
    }
  }

  function create() {
    return {get, last, update, replace}
  }

  return {
    init() {
      if (!instance) {
        instance = create();
      }

      return instance;

    }
  };

})();

module.exports = Chain.init();

Simplificando, nossa chain propriamente dita é um array com nossos blocos, aqui implementamos algumas funções para manipulação da nossa blockchain e uma função para validar nossa chain.

Agora, vamos dar uma olhada em cada parte do código em nosso arquivo Chain.js :

const block = require('./block');

const Chain = (function() {
  let instance;

  const firstBlock = {
    index : 0,
    prevHash : 0,
    timestamp : 0,
    data : 'Blockchain is Borning',
    hash : block.generateHash({index : 0, prevHash : 0, timestamp : 0,  data : 'Blockchain is Borning'}),
  };

  const chain = [firstBlock];

Nessa primeira parte do código nós importamos o nosso arquivo bloco, declaramos nossa const Chain como uma função auto-executável do javascript, na linha 4 declaramos nossa variável instance, essa variavel vai fazer nosso controle do objeto e é com ela que vamos garantir que só teremos uma instancia de Chain (Lembra que eu falei que precisamos de uma singleton?).

Depois disso nós declaramos um objeto que será o genesis block da nossa blockchain. (linha 6)

E finalmente na linha 14 declaramos um array que é a blockchain propriamente dita, e já adicionamos nosso genesis block à ela.


  function validateChain(chain) {
    let validChain = true;
    if(JSON.stringify(chain[0]) !== JSON.stringify(fistBlock)) {
      validChain = false;
      return validChain;
    }
    
    const temp = [chain[0]];

    for(let i=1; i < chain.length; i++) {
      if (block.validateBlock(chain[i], temp[i-1])) {
        temp.push(chain[i]);
      } else {
        validChain = false;
        return validChain;
      }
    }

    return validChain;

  }

Nessa segunda parte do arquivo Chain.js temos a maior função do nosso objeto, essa função é bastante importante para consistência de dados da nossa blockchain.

Nessa função nós primeiro verificamos que o genesis block da chain que recebemos é igual ao objeto que declaramos na primeira parte do arquivo. Se ele for diferente a gente retorna a chain inválida.

Se o genesis block for válido a gente passar para o nosso loop que verifica cada bloco da chain que a gente recebeu e compara com a chain que temos na memoria se os blocos passarem no teste a gente retorna a variável validChain como true , se algum bloco falhar na verificação a gente retorna false.

  function get() {
    return chain;
  };

  function last() {
    return chain.slice().pop();
  }

  function update(newBlock) {
    block.validateBlock(newBlock) ? chain.push(newBlock) : console.log('invalid block recived');
  }

Essas são as funções mais simples do nosso arquivo, basicamente são dois getters e um setter .
Na função get() nós retornamos nosso array com a chain que está na memoria, a função last() é auto explicativa e a função update verifica se o bloco que ele recebeu da rede é valido, se for ele atualiza a chain da memoria, se não ele cospe aquele console.log() com uma mensagem de error (eu sei, eu sei, tem maneiras melhores de tratar ou jogar errors, mas para o nosso exemplo esse basta :D).

function replace(newChain) {
    if (validateChain(newChain) && newChain.length > chain.length) {
      chain.splice(0, chain.length);
      chain.push(...newChain);
    } else {
      console.log('invalid chain recived');
    }
  }

  function create() {
    return {get, last, update, replace}
  }

Estamos chegando no final do nosso arquivo Chain.js essas são as duas ultima funções do nosso objeto, na função replace() é usado para substituir nossa chain por outra que a gente receber da rede, nessa função nós usamos a função validateChain() que definimos no começo do arquivo (segunda parte) para verificar se o array que recebemos é valido e se ele é maior que a o array que temos em memória.

Nossa ultima função create() é a função que retorna um objeto com as funções.


 return {
    init() {
      if (!instance) {
        instance = create();
      }

      return instance;

    }
  };

})();

module.exports = Chain.init();

Essa é a ultima parte do nosso arquivo(e da nossa função), que retorna a função init() que é responsável por verificar se existe uma instancia do nosso objeto Chain, se existir nós exportamos a nossa instancia, se não existir, nós criamos a instancia e depois exportamos ela.

Vou parar esse artigo por aqui com nossa base da blockchain implementada, no próximo vou mostrar como vai ser implementado a nossa conexão P2P usando o modulo webSocket do node.

Abaixo vou deixar algumas referencias, e se você manja mais que eu e vê que falei alguma coisa errada, comenta que eu ajusto, vamos criar uma comunidade com um ótimo conteúdo, se você gostou deixa um clap.

Obrigado por ter lido e até a proxima!

Referencias:

Leia outros artigos…

Deixe um comentário

O seu endereço de e-mail não será publicado.