Executando transações públicas e privadas no blockchain JPMorgan Quorum usando Web3



O Quorum é um blockchain baseado em Ethereum desenvolvido pelo JPMorgan e mais recentemente se tornou a primeira plataforma de registro distribuída que o Microsoft Azure oferece.


O Quorum suporta transações públicas e privadas e possui muitos casos de uso comercial.


Neste artigo, analisaremos um desses cenários - a implantação de uma rede de registro distribuída entre um supermercado e um proprietário de armazém para fornecer informações relevantes sobre a temperatura de um armazém.


O código usado neste guia está no repositório do GitHub .


O artigo aborda:


  • criando um contrato inteligente;
  • Implantando a rede Quorum com o Chainstack
  • Transações públicas de quorum
  • Transações privadas de quorum.

Para ilustrar isso, usamos o cenário de monitoramento de temperatura nas salas de armazenamento dos participantes da rede Quorum como parte da Internet das Coisas (IoT).


Contexto


Um grupo de empresas de armazém está unido em um consórcio para o armazenamento conjunto de informações e automação de processos no blockchain. Para isso, as empresas decidiram usar o Quorum. Neste artigo, abordaremos dois cenários: transações públicas e transações privadas.


As transações são criadas por diferentes participantes para interagir com o consórcio ao qual pertencem. Cada transação implementa um contrato ou chama uma função em um contrato para carregar dados na rede. Essas ações são replicadas para todos os nós na rede.


As transações públicas estão disponíveis para visualização por todos os membros do consórcio. As transações privadas adicionam uma camada de confidencialidade e estão disponíveis apenas para os participantes que têm direitos sobre ela.


Nos dois cenários, usamos o mesmo contrato para maior clareza.


Contrato inteligente


Abaixo está um contrato inteligente simples criado para o nosso cenário. Possui uma temperature pública variável, que pode ser alterada usando o método set e recuperada pelo método get .


 pragma solidity ^0.4.25; contract TemperatureMonitor { int8 public temperature; function set(int8 temp) public { temperature = temp; } function get() view public returns (int8) { return temperature; } } 

Para que o contrato funcione com o web3.js , ele deve ser convertido para o formato ABI e o bytecode. O uso da função formatContract abaixo compila o contrato usando solc-js .


 function formatContract() { const path = './contracts/temperatureMonitor.sol'; const source = fs.readFileSync(path,'UTF8'); return solc.compile(source, 1).contracts[':TemperatureMonitor']; } 

O contrato finalizado é o seguinte:


 // interface [ { constant: true, inputs: [], name: 'get', outputs: [Array], payable: false, stateMutability: 'view', type: 'function' }, { constant: true, inputs: [], name: 'temperature', outputs: [Array], payable: false, stateMutability: 'view', type: 'function' }, { constant: false, inputs: [Array], name: 'set', outputs: [], payable: false, stateMutability: 'nonpayable', type: 'function' } ] 

 // bytecode 

Agora que o contrato está pronto, implantaremos a rede e o contrato.


Implementação do nó


imagem


A implantação de um nó pode consumir bastante tempo e esse processo pode ser substituído usando o serviço Chainstack .


A seguir, é apresentado um processo de implantação de rede Quorum com um consenso de Raft e três nós.


Para começar, vamos iniciar um projeto e chamá-lo de Projeto Quorum:


imagem


Crie uma rede de quorum com consenso de jangada no Google Cloud Platform:


imagem


Para o nó padrão já criado, adicione mais dois nós:


imagem


Três nós em execução:


imagem


A página de detalhes do nó mostra o terminal RPC, chave pública, etc.


imagem


A rede está implantada. Agora vamos implantar contratos inteligentes e executar transações usando web3.js.


Transações públicas


Contexto


A temperatura do armazém é de grande importância para reduzir custos, especialmente para produtos destinados ao armazenamento em temperaturas abaixo de zero.


Ao oferecer às empresas a capacidade de compartilhar valores em tempo real da temperatura externa de sua localização geográfica e registrá-los em um registro imutável, os membros da rede reduzem custos e tempo.


imagem


Concluiremos as três tarefas ilustradas no diagrama:


  1. Terminaremos o contrato através do Nó 1 :


     const contractAddress = await deployContract(raft1Node); console.log(`Contract address after deployment: ${contractAddress}`); 

  2. Defina a temperatura através do nó 2 a 3 graus:


     const status = await setTemperature(raft2Node, contractAddress, 3); console.log(`Transaction status: ${status}`); 

  3. O nó 3 receberá informações do contrato inteligente. O contrato retornará um valor de 3 graus:


     const temp = await getTemperature(raft3Node, contractAddress); console.log('Retrieved contract Temperature', temp); 

    A seguir, veremos como executar uma transação pública na rede Quorum usando web3.js.



Iniciamos uma instância via RPC para três nós:


 const raft1Node = new Web3( new Web3.providers.HttpProvider(process.env.RPC1), null, { transactionConfirmationBlocks: 1, }, ); const raft2Node = new Web3( new Web3.providers.HttpProvider(process.env.RPC2), null, { transactionConfirmationBlocks: 1, }, ); const raft3Node = new Web3( new Web3.providers.HttpProvider(process.env.RPC3), null, { transactionConfirmationBlocks: 1, }, ); 

Destrua o contrato inteligente:


 // returns the default account from the Web3 instance initiated previously function getAddress(web3) { return web3.eth.getAccounts().then(accounts => accounts[0]); } // Deploys the contract using contract's interface and node's default address async function deployContract(web3) { const address = await getAddress(web3); // initiate contract with contract's interface const contract = new web3.eth.Contract( temperatureMonitor.interface ); return contract.deploy({ // deploy contract with contract's bytecode data: temperatureMonitor.bytecode, }) .send({ from: address, gas: '0x2CD29C0', }) .on('error', console.error) .then((newContractInstance) => { // returns deployed contract address return newContractInstance.options.address; }); } 

O web3.js fornece dois métodos para interagir com um contrato: call e send .


Atualize a temperatura do contrato executando o set usando o método de send web3.


 // get contract deployed previously async function getContract(web3, contractAddress) { const address = await getAddress(web3); return web3.eth.Contract( temperatureMonitor.interface, contractAddress, { defaultAccount: address, } ); } // calls contract set method to update contract's temperature async function setTemperature(web3, contractAddress, temp) { const myContract = await getContract(web3, contractAddress); return myContract.methods.set(temp).send({}).then((receipt) => { return receipt.status; }); } 

Em seguida, usamos o método de call web3 para obter a temperatura do contrato. Observe que o método de call é executado no nó local e a transação não será criada no blockchain.


 // calls contract get method to retrieve contract's temperature async function getTemperature(web3, contractAddress) { const myContract = await getContract(web3, contractAddress); return myContract.methods.get().call().then(result => result); } 

Agora você pode executar public.js para obter o seguinte resultado:


 // Execute public script node public.js Contract address after deployment: 0xf46141Ac7D6D6E986eFb2321756b5d1e8a25008F Transaction status: true Retrieved contract Temperature 3 

Em seguida, podemos ver as entradas no Quorum explorer no painel Chainstack, como mostrado abaixo.


Todos os três nós interagiram e as transações foram atualizadas:


  1. A primeira transação garantiu um contrato.
  2. A segunda transação definiu a temperatura do contrato para 3 graus.
  3. A temperatura é obtida através do nó local, portanto, a transação não foi criada.

imagem


Transações privadas


Contexto


Um requisito comum das organizações é a proteção de dados. Como exemplo, considere um cenário em que um supermercado aluga um armazém para armazenar frutos do mar de um fornecedor separado:


  • O fornecedor, com a ajuda dos sensores da IoT, lê os valores de temperatura a cada 30 segundos e os transmite ao supermercado ;
  • esses valores devem estar disponíveis apenas para o fornecedor e o supermercado , um consórcio em rede.

imagem


Concluiremos as quatro tarefas ilustradas no diagrama acima.


  • Usamos os mesmos três nós do cenário anterior para demonstrar transações privadas:
  • O supermercado está implantando um contrato inteligente que é privado para o supermercado e o fornecedor .
  • Um terceiro não tem acesso ao contrato inteligente.

Chamaremos os métodos get e set em nome do Supermercado e do Fornecedor para demonstrar a transação privada do Quorum.


  1. Terminaremos o contrato privado para os participantes do Supermercado e Fornecedor através do participante do Supermercado :


     const contractAddress = await deployContract( raft1Node, process.env.PK2, ); console.log(`Contract address after deployment: ${contractAddress}`); 

  2. Defina a temperatura do terceiro (nó externo) e obtenha o valor da temperatura:


     // Attempts to set Contract temperature to 10, this will not mutate contract's temperature await setTemperature( raft3Node, contractAddress, process.env.PK1, 10, ); // This returns null const temp = await getTemperature(raft3Node, contractAddress); console.log(`[Node3] temp retrieved after updating contract from external nodes: ${temp}`); 

  3. Defina a temperatura no fornecedor (nó interno) e obtenha o valor da temperatura:


    A temperatura nesse cenário deve retornar do contrato inteligente para 12. Observe que o fornecedor aqui permitiu o acesso ao contrato inteligente.


     // Updated Contract temperature to 12 degrees await setTemperature( raft2Node, contractAddress, process.env.PK1, 12, ); // This returns 12 const temp2 = await getTemperature(raft2Node, contractAddress); console.log(`[Node2] temp retrieved after updating contract from internal nodes: ${temp2}`); 

  4. Obtenha a temperatura do terceiro (nó externo):


    Na etapa 3, a temperatura foi definida como 12, mas o Terceiro não tem acesso ao contrato inteligente. Portanto, o valor de retorno deve ser nulo.


     // This returns null const temp3 = await getTemperature(raft3Node, contractAddress); console.log(`[Node3] temp retrieved from external nodes after update ${temp}`); 

    A seguir, consideraremos com mais detalhes a execução de transações privadas na rede Quorum com web3.js. Como a maior parte do código coincide com transações públicas, selecionamos apenas as partes que são diferentes para transações privadas.



Observe que o contrato carregado na rede é imutável; portanto, o acesso com permissão deve ser concedido aos nós correspondentes, incluindo o contrato público no momento da implantação do contrato, e não depois.


 async function deployContract(web3, publicKey) { const address = await getAddress(web3); const contract = new web3.eth.Contract( temperatureMonitor.interface, ); return contract.deploy({ data: temperatureMonitor.bytecode, }) .send({ from: address, gas: '0x2CD29C0', // Grant Permission to Contract by including nodes public keys privateFor: [publicKey], }) .then((contract) => { return contract.options.address; }); } 

As transações privadas são realizadas da mesma maneira - incluindo a chave pública dos participantes no momento da execução.


 async function setTemperature(web3, contractAddress, publicKey, temp) { const address = await getAddress(web3); const myContract = await getContract(web3, contractAddress); return myContract.methods.set(temp).send({ from: address, // Grant Permission by including nodes public keys privateFor: [publicKey], }).then((receipt) => { return receipt.status; }); } 

Agora podemos executar private.js com os seguintes resultados:


 node private.js Contract address after deployment: 0x85dBF88B4dfa47e73608b33454E4e3BA2812B21D [Node3] temp retrieved after updating contract from external nodes: null [Node2] temp retrieved after updating contract from internal nodes: 12 [Node3] temp retrieved from external nodes after update null 

O explorador do Quorum no Chainstack mostrará o seguinte:


  • Implantação de um contrato de um participante de um supermercado ;
  • Executando SetTemperature de um terceiro ;
  • Execute uma SetTemperature de um participante do fornecedor .

imagem


Como você pode ver, ambas as transações foram concluídas, mas apenas a transação do fornecedor participante atualizou a temperatura no contrato. Assim, as transações privadas fornecem imutabilidade, mas ao mesmo tempo não fornecem dados a terceiros.


Conclusão


Examinamos o cenário comercial do uso do Quorum para fornecer informações atualizadas sobre temperatura em um armazém, implantando uma rede entre duas partes - um supermercado e o proprietário do armazém.


Mostramos como as informações atuais sobre temperatura podem ser mantidas por meio de transações públicas e privadas.


Pode haver muitos cenários de aplicativos e, como você vê, não é nada difícil.


Experimente, tente implantar seu script. Além disso, o setor de tecnologia blockchain pode crescer quase dez vezes até 2024 .

Source: https://habr.com/ru/post/pt456368/


All Articles