Criando uma rede blockchain com Hyperledger Fabric e Node.js

Tutorial passo-a-passo de como criar uma rede blockchain utilizando o Hyperledger Fabric 1.4.0 com Smart Contract em Node.js.

Rodrigo Morbach
Sep 4, 2018 · 12 min read

Blockchain é um tipo de DLT (Distributed Ledger Technologies), que nada mais é do que um livro-razão (ledger) imutável, mantido por nós (peers) em uma rede distribuída.

Hyperleger Fabric é uma das diversas DLTs existentes e também uma das engines de Smart Contracts, privadas e permissionadas, com maior nível de maturidade atualmente. Isso se deve muito ao fato de o Hyperledger ser mantido pela Linux Foundation, tendo o Fabric como um dos principais projetos, o que contribui para um maior engajamento da comunidade de desenvolvedores.

O objetivo deste tutorial é fornecer insumos em português (embora grande parte dos links referenciem páginas em inglês) para desenvolvedores de sistemas que, assim como eu, estão iniciando os seus estudos em blockchain. Serão exibidas instruções para a criação de uma rede simples e a implantação de um Smart Contract desenvolvido em Node.js.

Antes de começar

Este tutorial assume que o leitor está familiarizado com os principais conceitos do Hyperledger Fabric, e foca exclusivamente na exemplificação de utilização da versão 1.4.0 do framework.

O primeiro passo para seguir este tutorial é fazer download ou clone do projeto no repositório do Github. Ele contém os artefatos necessários para a criação e configuração da rede.

Além disso, assume-se que os seguintes softwares e versões estejam instalados na máquina onde os comandos serão executados:

  • Docker 18.06.0 ou superior
  • Docker-compose 1.22 ou superior (já incluso no Docker para macOS)
  • Node.js família 8.11.x (parece haver problemas com as versões 9 e 10)
  • NPM (Node Package Manager) 5.6.0 ou superior (já incluso no Node.js)
  • cURL, qualquer versão 7.x deve ser suficiente.

Opcional, mas altamente recomendado, é a instalação de alguma ferramenta de debug remoto para Node.js. Nesse tutorial será utilizado o próprio Google Chrome, que já possui uma ferramenta de inspeção remota nas opções para desenvolvedores.

Observação: os comandos executados nas demais seções podem, e talvez até devam, ser automatizados utilizando shell scripts, por exemplo. No entanto, o intuito deste tutorial é fornecer um passo-a-passo das etapas necessárias para a criação de uma rede blockchain, com objetivo de facilitar o entendimento do desenvolvedor durante a processo de desenvolvimento.

Cenário de exemplo

Este tutorial não foca no posicionamento de mercado das organizações que compõem a rede blockchain. Ao invés disso, criaremos organizações genéricas com o intuito único de exercitar os papéis desempenhados pelos participantes em uma rede no Fabric.

O cenário de exemplo é composto por:

  • 2 organizações compostas por 2 peers cada.
  • 1 nó ordenador, responsável por executar o “consenso” através do mecanismo SOLO (somente para desenvolvimento)
  • 1 canal para comunicação entre todos os participantes da rede.

Vamos denominar as organizações de Provider e Consumer. Essas organizações farão parte do mesmo consórcio, denominado sampledomain, e se comunicarão através do mesmo canal, denominado samplechannel. Os peers das organizações serão denominados peer0 e peer1, por simplicidade. Desta forma teremos os seguintes participantes:

  • orderer.sampledomain.com
  • peer0.provider.sampledomain.com
  • peer1.provider.sampledomain.com
  • peer0.consumer.sampledomain.com
  • peer1.consumer.sampledomain.com

Preparando o ambiente de desenvolvimento

Após fazer clone do repositório, utilize o terminal para acessar o diretório hyperledger-fabric-sample. As primeiras etapas de configuração da rede exigem o uso de ferramentas de terceiros para a criação de alguns artefatos. Felizmente, o Hyperledger Fabric disponibiliza os binários dessas ferramentas que, para este tutorial, são baixados através do script downloadBinaries.sh .

$ ./downloadBinaries.sh

Ao finalizar, o script terá criado uma pasta bin contendo os binários baixados de acordo com a plataforma onde o script foi executado.

Gerando material criptográfico dos participantes

A primeira ferramenta a ser utilizada é o cryptogen. Seu objetivo é gerar os certificados digitais x.509 e as chaves de assinatura para todos os participantes da rede. Em teoria o cryptogen pode ser facilmente substituído por outra ferramenta de mercado, como o OpenSSL, para a geração dos certificados.

cryptogen consome um arquivo de configuração denominado crypto-config.yaml, que contém a definição de topologia da rede e permite gerar um conjunto de certificados e chaves para as organizações e seus participantes.

Acesse a pasta network e execute o seguinte comando:

$ ../bin/cryptogen generate --config=./crypto-config.yaml

Após a execução do script será criada uma pasta crypto-config dentro de network, contendo todo o material criptográfico, tanto para o nó ordenador quando para as organizações, necessário para rodar a rede blockchain.

Criando o bloco gênesis e as configurações do canal

Outra ferramenta baixada anteriormente e que será utilizada é a configtxgen. Para este tutorial, configtxgen terá a função de gerar:

  • o bloco gênesis do ordenador, que é o bloco inicial da ledger e que inicia o serviço de ordenação;
  • o arquivo de transação de configuração que será utilizado no momento de criação do canal;
  • arquivos de transação dos peers âncora de cada organização participante da rede, no nosso caso, duas.

configtxgen consome o arquivo configtx.yaml que contém as definições da rede sampledomain. Ele contém as configurações do nó ordenador (OrdererOrg), das organizações participantes (Provider e Consumer), e também dos peers âncora de cada organização. Um peer âncora é a porta entrada (ou saída) para comunicação de uma organização com as demais participantes da rede, através do protocolo Gossip. Uma organização pode ter vários peers do tipo âncora, sendo necessário minimamente a definição de um.

Outra importante definição neste arquivo é o caminho para as configurações de MSP (Membership Service Providers) de cada organização, que será referenciado posteriormente para a identificação e autorização de transações na ledger. A principal função do MSP é abstrair os mecanismos e processos de emissão e validação de certificados, além de autenticação de usuários.

Uma seção importante no arquivo configtx.yaml é a Profiles, que possui configurações do bloco gênesis do ordenador (OrgsOrdererGenesis ), e de canal (OrgsChannel ). Esses perfis serão utilizados como argumentos para gerar os artefatos utilizando o configtxgen.

Execute os comandos abaixo para gerar os arquivos mencionados anteriormente:

$ ../bin/configtxgen -profile OrgsOrdererGenesis -outputBlock ./channel-artifacts/genesis.block$ ../bin/configtxgen -profile OrgsChannel -outputCreateChannelTx ./channel-artifacts/channel.tx -channelID samplechannel$ ../bin/configtxgen -profile OrgsChannel -outputAnchorPeersUpdate ./channel-artifacts/ProviderMSPanchors.tx -channelID samplechannel -asOrg ProviderMSP$ ../bin/configtxgen -profile OrgsChannel -outputAnchorPeersUpdate ./channel-artifacts/ConsumerMSPanchors.tx -channelID samplechannel -asOrg ConsumerMSP

Como pode ser observado, todos os artefatos são gerados na pasta channel-artifacts , dentro de network .

Iniciando os containers Docker

Neste ponto todos os arquivos necessários para configurar a rede já foram criados. O próximo passo é iniciar os containers Docker.

As configurações dos containers, ou serviços Docker, estão especificadas no arquivo docker-compose.yaml . Esse arquivo contém as definições de imagens Docker utilizadas, o mapeamento de volumes e portas, além de definir variáveis de ambiente existentes em cada um dos containers. Reserve um momento para inspecionar este arquivo e entender melhor como os componentes da rede estão organizados.

Um ponto a ser notado é que a definição de alguns containers, especificamente os peers das organizações, herdam propriedades de outro arquivo de configuração, o peer-base.yaml . Esse arquivo contém configurações comuns para todos os peers participantes da rede. Inspecione o arquivo peer-base.yaml e note a propriedade command . Sua definição deve ser a seguinte:

command: peer node start —-peer-chaincodedev=true

Esse comando habilita o modo desenvolvedor de chaincodes. Normalmente, chaincodes são iniciados e gerenciados pelo próprio peer. No entanto, quando o peer é iniciado utilizando o comando acima, "o chaincode é construído e iniciado pelo próprio usuário". De modo geral, esse comando permite que chaincodes desenvolvidos em Node.js sejam alterados e testados sem a necessidade de reinstalá-los nos peers a cada nova alteração, tornando-se extremamente útil durante a fase de desenvolvimento. No caso do Go, por ser compilado, chaincodes desenvolvidos nessa linguagem precisam ser reinstalados e instanciados nos peers.

Ainda na linha de facilitar a etapa de desenvolvimento, a comunicação entre os nós da rede foi desabilitada através da variável de ambiente CORE_PEER_TLS_ENABLED=false e ORDERER_GENERAL_TLS_ENABLED=false . Isso nos permitirá inspecionar remotamente os chaincodes utilizando portas utilizadas para comunicação não-TLS.

Quando estiver confortável com as configurações dos containers Docker, execute o seguinte comando para criar os participantes da rede:

$ docker-compose up -d

A execução do comando deve levar alguns minutos para completar, principalmente se você o estiver executando pela primeira vez, pois o Docker irá baixar todas as imagens necessárias para a criação dos containers.

Configurando peers participantes da rede

A partir deste ponto todos os comandos devem ser executados a partir dos containers Docker. É como se estivéssemos acessando os computadores remotamente e executando comandos nos seus terminais. Felizmente isso não é necessário pois o Hyperledger fornece uma imagem Docker que nos permite acessar cada nó participante da rede através de um único container, o cli .

Para acessar o terminal do container cli execute o comando abaixo:

$ docker exec -it cli bash

Uma vez dentro do container é possível utilizar ferramentas do Fabric para configurar os nós participantes e estabelecer uma rede blockchain.

Criando o canal samplechannel

A primeira etapa para o estabelecimento da rede é a criação de um canal com base nos artefatos gerados anteriormente através da ferramenta configtxgen. Neste ponto utilizaremos outra importante ferramenta do Fabric, o peer channel. Utilize o comando abaixo para criar um canal e escrever o bloco gênesis em arquivo (samplechannel.block )

$ peer channel create -o orderer.sampledomain.com:7050 -c samplechannel -f ./channel-artifacts/channel.tx

Para todos os comandos do canal é necessário informar o endereço do nó ordenador, orderer.sampledomain.com:7050 , e o nome do canal, no nosso caso samplechannel . Especificamente para a criação do canal é preciso referenciar o arquivo channel.tx gerado anteriormente.

Criado o canal, agora é preciso adicionar os participantes. Cada peer participante da rede deve se juntar "manualmente" ao canal recém criado.

Adicionar participantes ao canal samplechannel

Primeiramente vamos adicionar o peer0 da organização Provider, que é o peer padrão do cli:

$ peer channel join -b samplechannel.block

Após isso, vamos adicionar o peer1 de Provider ao canal:

$ export CORE_PEER_ADDRESS=peer1.provider.sampledomain.com:7051
$ peer channel join -b samplechannel.block

É importante mencionar aqui que, utilizando o container cli , o chaveamento de um peer para outro é feito exclusivamente através da alteração nos valores de variáveis de ambiente, por exemplo, de CORE_PEER_ADDRESS . Se estiver em dúvida sobre em qual peer você está executando as operações, ecoe o valor das seguintes variáveis:

$ echo $CORE_PEER_ADDRESS
$ echo $CORE_PEER_MSPCONFIGPATH
$ echo $CORE_PEER_LOCALMSPID

Neste ponto todos os peers da organização Provider já estão fazendo parte do canal samplechannel . Para se certificar, execute o comando abaixo:

$ peer channel list

A mensagem Channels peers has joined com o valor samplechannel deve ser exibida no seu console. Isso significa que os comandos executados até o momento estavam corretos.

O próximo passo é mudar para a organização Consumer e adicionar os seus peers ao canal samplechannel. Execute os comandos abaixo para adicionar o peer0:

$ export CORE_PEER_MSPCONFIGPATH=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto-config/peerOrganizations/consumer.sampledomain.com/users/Admin\@consumer.sampledomain.com/msp/$ export CORE_PEER_ADDRESS=peer0.consumer.sampledomain.com:7051
$ export CORE_PEER_LOCALMSPID=ConsumerMSP
$ peer channel join -b samplechannel.block

E agora, o peer1:

$ export CORE_PEER_ADDRESS=peer1.consumer.sampledomain.com:7051
$ peer channel join -b samplechannel.block

Atualizando informações de peer âncora no canal

O último passo para a configuração da rede é atualizar as informações de peer âncora no canal com os arquivos gerados pela ferramenta configtxgen.

Diferente da etapa de adicionar participantes ao canal, esta etapa precisa ser executada somente nos peers âncora de cada organização, e não em todos os nós da rede.

Primeiramente, vamos alterar as configurações do cli para atuar no peer0 de organização Provider.

$ export CORE_PEER_MSPCONFIGPATH=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto-config/peerOrganizations/provider.sampledomain.com/users/Admin\@provider.sampledomain.com/msp/$ export CORE_PEER_ADDRESS=peer0.provider.sampledomain.com:7051
$ export CORE_PEER_LOCALMSPID=ProviderMSP

Depois, vamos atualizar o canal utilizando peer channel update :

$ peer channel update -o orderer.sampledomain.com:7050 -c samplechannel -f ./channel-artifacts/${CORE_PEER_LOCALMSPID}anchors.tx

De volta ao peer0 de Consumer, vamos alterar as suas configurações de peer âncora:

$ export CORE_PEER_MSPCONFIGPATH=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto-config/peerOrganizations/consumer.sampledomain.com/users/Admin\@consumer.sampledomain.com/msp/$ export CORE_PEER_ADDRESS=peer0.consumer.sampledomain.com:7051
$ export CORE_PEER_LOCALMSPID=ConsumerMSP
$ peer channel update -o orderer.sampledomain.com:7050 -c samplechannel -f ./channel-artifacts/${CORE_PEER_LOCALMSPID}anchors.tx

Neste momento todos os comandos relativos à criação e configuração da rede blockchain foram concluídos. O próximo passo é instalar e instanciar o Smart Contract na rede.

Chaincode

Chaincode é o termo utilizado pelo Hyperledger Fabric para denominar o que é conhecido também por Smart Contract na terminologia do blockchain. Trata-se de um programa que roda nos peers participantes de uma rede e é responsável por realizar a manipulação de dados na ledger, principalmente escrita e leitura, podendo também executar funções relativas ao modelo de negócio. Na versão utilizada neste tutorial, 1.4.0, é possível escrever chaincodes em linguagem Go e Javascript, através de APIs do Node.js. Este tutorial exemplifica o uso da segunda opção.

Dentro da pasta chaincode existe uma subpasta denominada deal , que por sua vez possui um arquivo Javascript com o mesmo nome (deal.js). Esse arquivo é o nosso chaincode. Ele implementa a interface ChaincodeInterface , que define os métodos Init e Invoke , obrigatórios para todo chaincode do Fabric. Além destes, existem outros dois métodos definidos: registerProduct , responsável por cadastrar um produto, definido através de uma estrutura de dados simples, na ledger; e getProduct , responsável por realizar a consulta de um produto registrado na ledger através do seu identificador.

Instalando o chaincode na rede

Antes de poder interagir com o chaincode e realizar operações na ledger, é preciso instalá-lo nos peers participantes da rede. O comando de instalação deve ser executado em todos os peers de cada organização onde o chaincode deve ser hospedado.

Instalando no peer0 de Provider:

$ export CORE_PEER_MSPCONFIGPATH=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto-config/peerOrganizations/provider.sampledomain.com/users/Admin\@provider.sampledomain.com/msp/$ export CORE_PEER_ADDRESS=peer0.provider.sampledomain.com:7051
$ export CORE_PEER_LOCALMSPID=ProviderMSP

Para instalação do chaincode é preciso informar o seu nome, a versão e o caminho para o arquivo deal.js :

$ peer chaincode install -n deal -v 1.0 -l node -p /opt/gopath/src/github.com/chaincode/deal

Vale destacar que o caminho referenciado pelo argumento -p é relativo à estrutura de diretórios do container cli.

Instalando no peer1 de Provider:

$ export CORE_PEER_ADDRESS=peer1.provider.sampledomain.com:7051
$ peer chaincode install -n deal -v 1.0 -l node -p /opt/gopath/src/github.com/chaincode/deal

Instalando no peer0 de Consumer:

$ export CORE_PEER_MSPCONFIGPATH=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto-config/peerOrganizations/consumer.sampledomain.com/users/Admin\@consumer.sampledomain.com/msp/$ export CORE_PEER_ADDRESS=peer0.consumer.sampledomain.com:7051
$ export CORE_PEER_LOCALMSPID=ConsumerMSP
$ peer chaincode install -n deal -v 1.0 -l node -p /opt/gopath/src/github.com/chaincode/deal

Por fim, instalando no peer1 de Consumer:

$ export CORE_PEER_ADDRESS=peer1.consumer.sampledomain.com:7051
$ peer chaincode install -n deal -v 1.0 -l node -p /opt/gopath/src/github.com/chaincode/deal

Instanciando o chaincode no canal samplechannel

O fato de instalar o chaincode nos peers da rede não é o suficiente para poder interagir com ele. Para disponibilizar o chaincode é preciso instanciá-lo. Instanciar um chaincode significa efetivamente implantá-lo para uso pelos seus participantes.

Diferente da instalação, a instanciação de um chaincode deve ser feita no canal, através de qualquer peer de qualquer organização que faça parte do canal. O comando de instanciação também exige o nome e a versão do chaincode, além do endereço do nó ordenador e de um payload que pode ser usado para fazer uma configuração inicial da ledger, ou do chaincode, por exemplo. No nosso exemplo será fornecido um JSON vazio como payload.

$ peer chaincode instantiate -o orderer.sampledomain.com:7050 -C samplechannel -l node -n deal -v 1.0 -c '{"Args":[]}'

A execução deste comando pode demorar alguns segundos.

Quando instanciado na rede, o método Init do chaincode é invocado.

Executando operações na ledger através do chaincode

Após a instalação e instanciação do chaincode na rede, é possível executar operações na ledger. Para isso, utilizaremos o peer0 de Provider, para realizar o registro de um produto:

$ export CORE_PEER_MSPCONFIGPATH=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto-config/peerOrganizations/provider.sampledomain.com/users/Admin\@provider.sampledomain.com/msp/$ export CORE_PEER_ADDRESS=peer0.provider.sampledomain.com:7051
$ export CORE_PEER_LOCALMSPID=ProviderMSP

Registrando produto:

$ peer chaincode invoke -n deal -c '{"Args":["123", "Product one", "10"], "Function":"registerProduct"}' -C samplechannel

É possível também consultar o produto recém cadastrado:

$ peer chaincode query -n deal -c '{"Args":["123"], "Function":"getProduct"}' -C samplechannel

No seu console deve ser exibido um JSON com as informações do produto, por exemplo:

{"name":"Product one","price":"10"}

Vale destacar que todas essas chamadas de funções do chaincode podem ser realizadas utilizando SDKs fornecidos pela própria Hyperledger, como os SDKs Node.js e Java.

Inspecionando o chaincode em tempo de execução

Observação: as instruções descritas abaixo aplicam-se somente a chaincodes desenvolvidos em Node.js. Além disso, os comandos devem ser executados fora do container cli .

Conforme mencionado no início deste tutorial, é possível fazer debug remoto do chaincode utilizando o Google Chrome, por exemplo. Isso permite identificar e analisar mensagens recebidas pelo chaincode e também quais informações estão sendo recuperadas da ledger, facilitando e agilizando o processo de desenvolvimento.

Para inspecionar o chaincode deal.js navegue até a pasta deal e, caso ainda não tenha feito, instale as dependências executando npm install. Terminada a instalação, execute o seguinte comando para começar a inspecionar o chaincode:

$ CORE_CHAINCODE_ID_NAME="deal:1.0" node --inspect deal.js -— peer.address localhost:7052

Importante: o comando acima irá inspecionar o chaincode instalado no peer correspondente a porta local 7052, no nosso caso, esse é o peer0 de Provider. Para inspecionar outros peers é preciso alterar o número da porta para o valor correto.

Se tudo estiver correto, abra o Google Chrome e digite chrome://inspect/devices . Você deverá ver o arquivo deal.js , conforme mostra a imagem abaixo:

Debug remoto de deal.js

Clicando sobre deal.js o console do Chrome será aberto. Utilize command + P (no macOS) ou Control + P para selecionar o arquivo. Neste momento você deverá conseguir visualizar o código fonte do chaincode, conforme imagem abaixo:

Código fonte de deal.js

Com isso é possível adicionar Breakpoints em qualquer ponto do código e analisá-lo assim que operações invoke ou query sejam executadas.

Outras leituras

A referência mais atualizada do Fabric é o próprio read-the-docs.

Se você quer saber mais sobre a teoria do blockchain, aplicações e oportunidades de negócios e sua aplicação com Internet das Coisas (IoT), assista aos Webinars do CPqD e baixe os Whitepapers.

Há também um curso muito interessante preparado pela própria Linux Foundation no edX: Blockchain for Business — An introduction to Hyperledger Technologies.

Agradecimentos

Gostaria de aproveitar e agradecer ao Eduardo Ferreira Jucá de Castro e ao Fernando Marino pela revisão deste tutorial.

Thanks to Fernando Marino and Eduardo Ferreira Jucá de Castro

Rodrigo Morbach

Written by

Mobile developer and Researcher

Welcome to a place where words matter. On Medium, smart voices and original ideas take center stage - with no ads in sight. Watch
Follow all the topics you care about, and we’ll deliver the best stories for you to your homepage and inbox. Explore
Get unlimited access to the best stories on Medium — and support writers while you’re at it. Just $5/month. Upgrade