Blockchain: qual PoC devemos construir?

Seus olhos estão com medo e suas mãos estão coçando!

Em artigos anteriores, tratamos das tecnologias nas quais os blockchains são construídos (O que devemos construir um blockchain?) e casos que podem ser implementados com a ajuda deles (Por que devemos construir um caso?). É hora de trabalhar com as mãos! Para implementar pilotos e PoC (Proof of Concept), prefiro usar as nuvens, porque... eles podem ser acessados ​​de qualquer lugar do mundo e, muitas vezes, não há necessidade de perder tempo com a tediosa instalação do ambiente, pois Existem configurações predefinidas. Então, vamos fazer algo simples, por exemplo, uma rede para transferência de moedas entre participantes e vamos chamá-la modestamente de Bitcoin. Para isso utilizaremos a nuvem IBM e o blockchain universal Hyperledger Fabric. Primeiro, vamos descobrir por que o Hyperledger Fabric é chamado de blockchain universal?

Blockchain: qual PoC devemos construir?

Hyperledger Fabric - um blockchain universal

De modo geral, um sistema de informação universal é:

  • Um conjunto de servidores e um núcleo de software que executa a lógica de negócios;
  • Interfaces para interação com o sistema;
  • Ferramentas para cadastro, autenticação e autorização de dispositivos/pessoas;
  • Banco de dados que armazena dados operacionais e de arquivo:

Blockchain: qual PoC devemos construir?

A versão oficial do que é Hyperledger Fabric pode ser lida em On-linee, resumindo, Hyperledger Fabric é uma plataforma de código aberto que permite construir blockchains privados e executar contratos inteligentes arbitrários escritos nas linguagens de programação JS e Go. Vamos examinar detalhadamente a arquitetura do Hyperledger Fabric e ter certeza de que este é um sistema universal que possui apenas especificidades para armazenamento e gravação de dados. A especificidade é que os dados, como em todos os blockchains, são armazenados em blocos que são colocados no blockchain somente se os participantes chegarem a um consenso e após o registro os dados não puderem ser corrigidos ou excluídos silenciosamente.

Arquitetura de malha Hyperledger

O diagrama mostra a arquitetura do Hyperledger Fabric:

Blockchain: qual PoC devemos construir?

Organizações — as organizações contêm pares, ou seja, blockchain existe devido ao apoio de organizações. Diferentes organizações podem fazer parte do mesmo canal.

Canal — uma estrutura lógica que une pares em grupos, ou seja, o blockchain é especificado. O Hyperledger Fabric pode processar simultaneamente vários blockchains com diferentes lógicas de negócios.

Provedor de serviços de associação (MSP) é uma CA (Autoridade Certificadora) para emitir identidade e atribuir funções. Para criar um nó, você precisa interagir com o MSP.

Nós pares — verificar transações, armazenar blockchain, executar contratos inteligentes e interagir com aplicações. Os peers possuem uma identidade (certificado digital), que é emitida pelo MSP. Ao contrário da rede Bitcoin ou Etherium, onde todos os nós têm direitos iguais, no Hyperledger Fabric os nós desempenham funções diferentes:

  • Pare talvez endossando pares (EP) e executar contratos inteligentes.
  • Comprometendo par (CP) - salva apenas dados no blockchain e atualiza o “estado mundial”.
  • Ponto âncora (AP) - se várias organizações participam do blockchain, então pares âncoras são usados ​​para comunicação entre elas. Cada organização deve ter um ou mais pares âncora. Usando AP, qualquer peer em uma organização pode obter informações sobre todos os peers em outras organizações. Usado para sincronizar informações entre APs protocolo de fofoca.
  • Par líder — se uma organização tiver vários pares, apenas o líder do par receberá blocos do serviço de pedido e os entregará ao restante dos pares. O líder pode ser especificado estaticamente ou selecionado dinamicamente pelos pares da organização. O protocolo de fofoca também é usado para sincronizar informações sobre líderes.

Ativos — entidades que têm valor e estão armazenadas na blockchain. Mais especificamente, trata-se de dados de valor-chave no formato JSON. São esses dados que ficam registrados no Blockchain. Eles têm um histórico, que é armazenado no blockchain, e um estado atual, que é armazenado no banco de dados “Estado mundial”. As estruturas de dados são preenchidas arbitrariamente dependendo das tarefas de negócios. Não há campos obrigatórios, a única recomendação é que os ativos tenham dono e sejam valiosos.

Ledger — consiste no Blockchain e no banco de dados de estado do Word, que armazena o estado atual dos ativos. O estado mundial usa LevelDB ou CouchDB.

Contrato inteligente — usando contratos inteligentes, a lógica de negócios do sistema é implementada. No Hyperledger Fabric, os contratos inteligentes são chamados de chaincode. Usando chaincode, os ativos e as transações sobre eles são especificados. Em termos técnicos, contratos inteligentes são módulos de software implementados nas linguagens de programação JS ou Go.

Política de endosso — para cada chaincode, você pode definir uma política sobre quantas confirmações de uma transação devem ser esperadas e de quem. Se a política não for definida, o padrão será: “a transação deve ser confirmada por qualquer membro de qualquer organização do canal”. Exemplos de políticas:

  • A transação deve ser aprovada por qualquer administrador da organização;
  • Deve ser confirmado por qualquer membro ou cliente da organização;
  • Deve ser confirmado por qualquer organização semelhante.

Serviço de pedidos — empacota as transações em blocos e as envia aos pares no canal. Garante a entrega de mensagens a todos os pares da rede. Usado para sistemas industriais Corretor de mensagens Kafka, para desenvolvimento e teste solo.

Fluxo de chamadas

Blockchain: qual PoC devemos construir?

  • A aplicação se comunica com o Hyperledger Fabric usando Go, Node.js ou Java SDK;
  • O cliente cria uma transação tx e a envia aos pares endossantes;
  • O Peer verifica a assinatura do cliente, conclui a transação e envia a assinatura de endosso de volta ao cliente. O Chaincode é executado apenas no peer endossante e o resultado de sua execução é enviado a todos os peers. Este algoritmo de trabalho é denominado consenso PBFT (Practical Byzantine Fault Tolerant). Difere de BFT clássico o fato de a mensagem ser enviada e a confirmação não ser esperada de todos os participantes, mas apenas de um determinado conjunto;
  • Após o cliente ter recebido o número de respostas correspondente à política de endosso, envia a transação para o serviço de Encomendas;
  • O serviço Ordering gera um bloco e o envia a todos os pares confirmados. O serviço de pedidos garante o registro sequencial dos blocos, o que elimina a chamada bifurcação do razão (consulte a seção "Garfos");
  • Os pares recebem um bloco, verificam a política de endosso novamente, gravam o bloco no blockchain e alteram o estado no banco de dados “Estado mundial”.

Aqueles. Isso resulta em uma divisão de funções entre os nós. Isso garante que o blockchain seja escalonável e seguro:

  • Contratos inteligentes (chaincode) realizam o endosso de pares. Isso garante a confidencialidade dos contratos inteligentes, porque não é armazenado por todos os participantes, mas apenas pelos pares endossados.
  • O pedido deve funcionar rapidamente. Isto é garantido pelo fato de que o Ordering apenas forma um bloco e o envia para um conjunto fixo de pares líderes.
  • Os pares comprometidos armazenam apenas o blockchain - pode haver muitos deles e eles não exigem muita energia e operação instantânea.

Mais detalhes sobre as soluções arquitetônicas do Hyperledger Fabric e por que ele funciona dessa maneira e não de outra podem ser encontrados aqui: Origens da Arquitetura ou aqui: Hyperledger Fabric: um sistema operacional distribuído para blockchains permitidos.

Portanto, o Hyperledger Fabric é um sistema verdadeiramente universal com o qual você pode:

  • Implementar lógica de negócios arbitrária usando o mecanismo de contrato inteligente;
  • Registrar e receber dados do banco de dados blockchain em formato JSON;
  • Conceda e verifique o acesso à API usando a Autoridade de Certificação.

Agora que entendemos um pouco sobre as especificidades do Hyperledger Fabric, vamos finalmente fazer algo útil!

Implantando blockchain

Formulação do problema

A tarefa é implementar a rede Citcoin com as seguintes funções: criar uma conta, obter saldo, recarregar sua conta, transferir moedas de uma conta para outra. Vamos desenhar um modelo de objeto, que implementaremos posteriormente em um contrato inteligente. Assim, teremos contas que são identificadas por nomes e contêm saldo e lista de contas. As contas e uma lista de contas são, em termos de ativos do Hyperledger Fabric. Assim, eles têm uma história e um estado atual. Vou tentar desenhar isso claramente:

Blockchain: qual PoC devemos construir?

Os números principais são o estado atual, que é armazenado no banco de dados “Estado mundial”. Abaixo deles estão figuras que mostram o histórico armazenado no blockchain. O estado atual dos ativos é alterado pelas transações. O Ativo muda apenas como um todo, portanto, como resultado da transação, um novo objeto é criado e o valor atual do ativo entra no histórico.

Nuvem IBM

Criamos uma conta em Nuvem IBM. Para usar a plataforma blockchain, ela deve ser atualizada para Pay-As-You-Go. Este processo pode não ser rápido, porque... A IBM solicita informações adicionais e as verifica manualmente. De forma positiva, posso dizer que a IBM possui bons materiais de treinamento que permitem implantar o Hyperledger Fabric em sua nuvem. Gostei da seguinte série de artigos e exemplos:

A seguir estão capturas de tela da plataforma IBM Blockchain. Esta não é uma instrução sobre como criar uma blockchain, mas simplesmente uma demonstração do escopo da tarefa. Então, para nossos propósitos, criamos uma Organização:

Blockchain: qual PoC devemos construir?

Criamos nós nele: Orderer CA, Org1 CA, Orderer Peer:

Blockchain: qual PoC devemos construir?

Criamos usuários:

Blockchain: qual PoC devemos construir?

Crie um canal e chame-o de citcoin:

Blockchain: qual PoC devemos construir?

Essencialmente, o Canal é um blockchain, então começa com o bloco zero (bloco Genesis):

Blockchain: qual PoC devemos construir?

Escrevendo um contrato inteligente

/*
 * Citcoin smart-contract v1.5 for Hyperledger Fabric
 * (c) Alexey Sushkov, 2019
 */
 
'use strict';
 
const { Contract } = require('fabric-contract-api');
const maxAccounts = 5;
 
class CitcoinEvents extends Contract {
 
    async instantiate(ctx) {
        console.info('instantiate');
        let emptyList = [];
        await ctx.stub.putState('accounts', Buffer.from(JSON.stringify(emptyList)));
    }
    // Get all accounts
    async GetAccounts(ctx) {
        // Get account list:
        let accounts = '{}'
        let accountsData = await ctx.stub.getState('accounts');
        if (accountsData) {
            accounts = JSON.parse(accountsData.toString());
        } else {
            throw new Error('accounts not found');
        }
        return accountsData.toString()
    }
     // add a account object to the blockchain state identifited by their name
    async AddAccount(ctx, name, balance) {
        // this is account data:
        let account = {
            name: name,
            balance: Number(balance),       
            type: 'account',
        };
        // create account:
        await ctx.stub.putState(name, Buffer.from(JSON.stringify(account)));
 
        // Add account to list:
        let accountsData = await ctx.stub.getState('accounts');
        if (accountsData) {
            let accounts = JSON.parse(accountsData.toString());
            if (accounts.length < maxAccounts)
            {
                accounts.push(name);
                await ctx.stub.putState('accounts', Buffer.from(JSON.stringify(accounts)));
            } else {
                throw new Error('Max accounts number reached');
            }
        } else {
            throw new Error('accounts not found');
        }
        // return  object
        return JSON.stringify(account);
    }
    // Sends money from Account to Account
    async SendFrom(ctx, fromAccount, toAccount, value) {
        // get Account from
        let fromData = await ctx.stub.getState(fromAccount);
        let from;
        if (fromData) {
            from = JSON.parse(fromData.toString());
            if (from.type !== 'account') {
                throw new Error('wrong from type');
            }   
        } else {
            throw new Error('Accout from not found');
        }
        // get Account to
        let toData = await ctx.stub.getState(toAccount);
        let to;
        if (toData) {
            to = JSON.parse(toData.toString());
            if (to.type !== 'account') {
                throw new Error('wrong to type');
            }  
        } else {
            throw new Error('Accout to not found');
        }
 
        // update the balances
        if ((from.balance - Number(value)) >= 0 ) {
            from.balance -= Number(value);
            to.balance += Number(value);
        } else {
            throw new Error('From Account: not enought balance');          
        }
 
        await ctx.stub.putState(from.name, Buffer.from(JSON.stringify(from)));
        await ctx.stub.putState(to.name, Buffer.from(JSON.stringify(to)));
                 
        // define and set Event
        let Event = {
            type: "SendFrom",
            from: from.name,
            to: to.name,
            balanceFrom: from.balance,
            balanceTo: to.balance,
            value: value
        };
        await ctx.stub.setEvent('SendFrom', Buffer.from(JSON.stringify(Event)));
 
        // return to object
        return JSON.stringify(from);
    }
 
    // get the state from key
    async GetState(ctx, key) {
        let data = await ctx.stub.getState(key);
        let jsonData = JSON.parse(data.toString());
        return JSON.stringify(jsonData);
    }
    // GetBalance   
    async GetBalance(ctx, accountName) {
        let data = await ctx.stub.getState(accountName);
        let jsonData = JSON.parse(data.toString());
        return JSON.stringify(jsonData);
    }
     
    // Refill own balance
    async RefillBalance(ctx, toAccount, value) {
        // get Account to
        let toData = await ctx.stub.getState(toAccount);
        let to;
        if (toData) {
            to = JSON.parse(toData.toString());
            if (to.type !== 'account') {
                throw new Error('wrong to type');
            }  
        } else {
            throw new Error('Accout to not found');
        }
 
        // update the balance
        to.balance += Number(value);
        await ctx.stub.putState(to.name, Buffer.from(JSON.stringify(to)));
                 
        // define and set Event
        let Event = {
            type: "RefillBalance",
            to: to.name,
            balanceTo: to.balance,
            value: value
        };
        await ctx.stub.setEvent('RefillBalance', Buffer.from(JSON.stringify(Event)));
 
        // return to object
        return JSON.stringify(from);
    }
}
module.exports = CitcoinEvents;

Intuitivamente, tudo deve ficar claro aqui:

  • Existem diversas funções (AddAccount, GetAccounts, SendFrom, GetBalance, RefillBalance) que o programa de demonstração chamará usando a API do Hyperledger Fabric.
  • As funções SendFrom e RefillBalance geram eventos que o programa de demonstração receberá.
  • A função instanciar é chamada uma vez quando um contrato inteligente é instanciado. Na verdade, ele não é chamado apenas uma vez, mas sempre que a versão do contrato inteligente muda. Portanto, inicializar uma lista com um array vazio é uma má ideia, porque Agora, quando mudarmos a versão do contrato inteligente, perderemos a lista atual. Mas está tudo bem, estou apenas aprendendo).
  • As contas e uma lista de contas são estruturas de dados JSON. JS é usado para manipulação de dados.
  • Você pode obter o valor atual de um ativo usando a chamada de função getState e atualizá-lo usando putState.
  • Ao criar uma Conta, é chamada a função AddAccount, na qual é feita uma comparação para o número máximo de contas na blockchain (maxAccounts = 5). E aqui tem um batente (você notou?), que leva a um aumento infinito no número de contas. Tais erros devem ser evitados)

A seguir, carregamos o contrato inteligente no Canal e o instanciamos:

Blockchain: qual PoC devemos construir?

Vejamos a transação para instalação do Smart Contract:

Blockchain: qual PoC devemos construir?

Vejamos os detalhes sobre nosso canal:

Blockchain: qual PoC devemos construir?

Como resultado, obtemos o seguinte diagrama de uma rede blockchain na nuvem IBM. O diagrama também mostra um programa de demonstração em execução na nuvem Amazon em um servidor virtual (mais sobre isso na próxima seção):

Blockchain: qual PoC devemos construir?

Criando uma GUI para chamadas de API do Hyperledger Fabric

O Hyperledger Fabric possui uma API que pode ser usada para:

  • Criar canal;
  • Conexões ponto a canal;
  • Instalação e instanciação de contratos inteligentes no canal;
  • Chamando transações;
  • Solicite informações sobre o blockchain.

Desenvolvimento de aplicações

Em nosso programa de demonstração usaremos a API apenas para chamar transações e solicitar informações, pois Já concluímos as etapas restantes usando a plataforma blockchain da IBM. Escrevemos uma GUI usando uma pilha de tecnologia padrão: Express.js + Vue.js + Node.js. Você pode escrever um artigo separado sobre como começar a criar aplicativos da web modernos. Aqui deixarei o link da série de palestras que mais gostei: Aplicativo Web Full Stack usando Vue.js e Express.js. O resultado é um aplicativo cliente-servidor com uma interface gráfica familiar no estilo Material Design do Google. A API REST entre cliente e servidor consiste em várias chamadas:

  • HyperledgerDemo/v1/init – inicializa o blockchain;
  • HyperledgerDemo/v1/accounts/list — obtenha uma lista de todas as contas;
  • HyperledgerDemo/v1/account?name=Bob&balance=100 — crie uma conta Bob;
  • HyperledgerDemo/v1/info?account=Bob — obtenha informações sobre a conta de Bob;
  • HyperledgerDemo/v1/transaction?from=Bob&to=Alice&volume=2 — transfira duas moedas de Bob para Alice;
  • HyperledgerDemo/v1/disconnect - fecha a conexão com o blockchain.

Descrição da API com exemplos incluídos em Site do carteiro - um programa conhecido para testar API HTTP.

Aplicativo de demonstração na nuvem Amazon

Carreguei o aplicativo na Amazon porque... A IBM ainda não conseguiu atualizar minha conta e permitir a criação de servidores virtuais. Como adicionar uma cereja ao domínio: www.citcoin.info. Vou deixar o servidor ligado por um tempo e depois desligar, porque... centavos de aluguel estão pingando e as moedas citcoin ainda não estão listadas na bolsa de valores). Estou incluindo capturas de tela da demonstração no artigo para que a lógica do trabalho fique clara. O aplicativo de demonstração pode:

  • Inicialize o blockchain;
  • Criar uma conta (mas agora você não pode criar uma nova conta, pois o número máximo de contas especificado no contrato inteligente foi atingido no blockchain);
  • Receba uma lista de contas;
  • Transferir moedas citcoin entre Alice, Bob e Alex;
  • Receber eventos (mas agora não há como mostrar eventos, então para simplificar a interface diz que eventos não são suportados);
  • Registrar ações.

Primeiro inicializamos o blockchain:

Blockchain: qual PoC devemos construir?

A seguir criamos nossa conta, não perca tempo com o saldo:

Blockchain: qual PoC devemos construir?

Obtemos uma lista de todas as contas disponíveis:

Blockchain: qual PoC devemos construir?

Selecionamos o remetente e o destinatário e obtemos seus saldos. Se o remetente e o destinatário forem iguais, sua conta será reabastecida:

Blockchain: qual PoC devemos construir?

No log monitoramos a execução das transações:

Blockchain: qual PoC devemos construir?

Na verdade, isso é tudo com o programa de demonstração. Abaixo você pode ver nossa transação no blockchain:

Blockchain: qual PoC devemos construir?

E a lista geral de transações:

Blockchain: qual PoC devemos construir?

Com isso, concluímos com sucesso a implementação do PoC para criação da rede Citcoin. O que mais precisa ser feito para que a Citcoin se torne uma rede completa de transferência de moedas? Muito pouco:

  • Na fase de criação da conta, implemente a geração de uma chave privada/pública. A chave privada deve ser armazenada com o usuário da conta, a chave pública deve ser armazenada no blockchain.
  • Faça uma transferência de moedas na qual uma chave pública, em vez de um nome, seja usada para identificar o usuário.
  • Criptografe as transações que vão do usuário ao servidor com sua chave privada.

Conclusão

Implementamos a rede Citcoin com as seguintes funções: adicionar uma conta, obter saldo, recarregar sua conta, transferir moedas de uma conta para outra. Então, quanto nos custou construir um PoC?

  • Você precisa estudar blockchain em geral e Hyperledger Fabric em particular;
  • Aprenda a usar nuvens IBM ou Amazon;
  • Aprenda a linguagem de programação JS e alguns frameworks web;
  • Se alguns dados precisarem ser armazenados não no blockchain, mas em um banco de dados separado, aprenda a integrar, por exemplo, com PostgreSQL;
  • E por último mas não menos importante: você não pode viver no mundo moderno sem conhecimento de Linux!)

Claro, não é ciência de foguetes, mas você terá que trabalhar duro!

Исходники no GitHub

Fontes colocadas GitHub. Breve descrição do repositório:
Catálogo "servidor» — Servidor Node.js
Catálogo "cliente» — Cliente Node.js
Catálogo "blockchain"(valores de parâmetros e chaves, é claro, não funcionam e são dados apenas como exemplo):

  • contrato – código-fonte do contrato inteligente
  • wallet — chaves de usuário para usar a API Hyperledger Fabric.
  • *.cds – versões compiladas de contratos inteligentes
  • Arquivos *.json – exemplos de arquivos de configuração para usar a API Hyperledger Fabric

É só o começo!

Fonte: habr.com

Adicionar um comentário