
— uma blockchain baseada em Ethereum, desenvolvida pelo JPMorgan e recentemente tornada a primeira plataforma de registro distribuído oferecida pela Microsoft Azure.
Quorum suporta transações privadas e públicas, e possui muitos cenários comerciais de uso.
Neste artigo, vamos examinar um desses cenários — a implementação de uma rede de registro distribuído entre um supermercado e o proprietário de um armazém para garantir informações atualizadas sobre a temperatura do armazém.
O código utilizado neste guia encontra-se em .
O artigo cobre:
- criação de um contrato inteligente;
- implementação da rede Quorum utilizando ;
- transações públicas do Quorum;
- transações privadas do Quorum.
Para ilustrar, utilizamos um cenário de monitoramento de temperatura em armazéns dos participantes da rede Quorum no contexto da Internet das Coisas (IoT).
Contexto
Um grupo de empresas de armazém se une em um consórcio para compartilhar informações e automatizar processos na blockchain. Para isso, as empresas decidiram usar o Quorum. Neste artigo, cobriramos 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 ou implementa um contrato ou chama uma função no contrato para carregar dados na rede. Essas ações são replicadas em todos os nós da rede.
Transações públicas estão disponíveis para visualização por todos os participantes do consórcio. As transações privadas adicionam uma camada de confidencialidade e estão disponíveis apenas para aqueles participantes que têm os direitos apropriados.
Para ambos os cenários, utilizamos o mesmo contrato para clareza.
Contrato inteligente
Abaixo está um contrato inteligente simples, criado para o nosso cenário. Ele possui uma variável pública temperature, que pode ser alterada pelo 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 , ele precisa ser convertido para o formato ABI e bytecode. O uso da função formatContract, apresentada abaixo, compila o contrato usando .
function formatContract() {
const path = '.\/contracts\/temperatureMonitor.sol';
const source = fs.readFileSync(path,'UTF8');
return solc.compile(source, 1).contracts[':TemperatureMonitor'];
}O contrato final é 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
0x608060405234801561001057600080fd5b50610104806100206000396000f30060806040526004361060525763ffffffff7c01000000000000000000000000000000000000000000000000000000006000350416636d4ce63c81146057578063adccea12146082578063faee13b9146094575b600080fd5b348015606257600080fd5b50606960ae565b60408051600092830b90920b8252519081900360200190f35b348015608d57600080fd5b50606960b7565b348015609f57600080fd5b5060ac60043560000b60c0565b005b60008054900b90565b60008054900b81565b6000805491810b60ff1660ff199092169190911790555600a165627a7a72305820af0086d55a9a4e6d52cb6b3967afd764ca89df91b2f42d7bf3b30098d222e5c50029Agora que o contrato está pronto, vamos implantar a rede e fazer o deploy do contrato.
Implantação de nós

Implantar um nó pode ser bastante trabalhoso e esse processo pode ser substituído pelo uso de um serviço. .
Abaixo está o processo de implantação da rede Quorum com consenso Raft e três nós.
Para começar, vamos criar um projeto e nomeá-lo de Quorum Project:

Vamos criar uma rede Quorum com consenso Raft na Google Cloud Platform:

À já criada por padrão, vamos adicionar mais dois nós:

Três nós em funcionamento:

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

A rede foi implantada. Agora vamos trabalhar no deploy de contratos inteligentes e na execução de transações com .
Transações públicas
Contexto
A temperatura do armazém tem grande importância na redução de custos, especialmente para produtos que precisam ser armazenados em temperaturas negativas.
Ao permitir que as empresas compartilhem os valores de temperatura externa de sua localização geográfica em tempo real e registrem em um livro-razão imutável, os participantes da rede reduzem despesas e tempo.

Vamos realizar três tarefas, ilustradas no diagrama:
Faremos o deploy do contrato através de Node 1:
const contractAddress = await deployContract(raft1Node); console.log(`Endereço do contrato após o deploy: ${contractAddress}`);Vamos definir a temperatura através de Node 2 para 3 graus:
const status = await setTemperature(raft2Node, contractAddress, 3); console.log(`Status da transação: ${status}`);Node 3 receberá informações do contrato inteligente. O contrato retornará o valor de 3 graus:
const temp = await getTemperature(raft3Node, contractAddress); console.log('Temperatura do contrato recuperada', temp);A seguir, veremos como executar uma transação pública na rede Quorum utilizando .
Iniciaremos uma instância através do 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,
},
);Faremos o deploy do 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;
});
} fornece dois métodos para interagir com o contrato: call e send.
Atualizaremos a temperatura do contrato executando set usando o método web3 send.
// 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;
});
}A seguir, usaremos o método web3 call para obter a temperatura do contrato. Observe que o método call é executado em um nó local e a transação não será criada na 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 podemos executar para obter o próximo resultado:
// Execute public script
node public.js
Contract address after deployment: 0xf46141Ac7D6D6E986eFb2321756b5d1e8a25008F
Transaction status: true
Retrieved contract Temperature 3Em seguida, podemos visualizar os registros no explorador Quorum no painel Chainstack, conforme mostrado abaixo.
Os três nós interagiram e as transações foram atualizadas:
- A primeira transação implantou o contrato.
- A segunda transação definiu a temperatura do contrato em 3 graus.
- A leitura da temperatura ocorre através de um nó local, portanto, a transação não foi criada.

Transações privadas
Contexto
Uma exigência comum das organizações é a proteção de dados. Como exemplo, consideremos um cenário em que um supermercado aluga um espaço de armazenamento para manter frutos do mar com um fornecedor:
- Fornecedor usando sensores IoT lê os valores de temperatura a cada 30 segundos e os transmite para o supermercado.;
- Esses valores devem estar disponíveis apenas para o fornecedor e do supermercado,unidos em uma rede de consórcio.

Executaremos quatro tarefas ilustradas no diagrama acima.
- Usaremos os mesmos três nós do cenário anterior para demonstrar transações privadas:
- O supermercado implanta um contrato inteligente que é privado para o supermercado. e fornecedor.
- Uma terceira parte não tem acesso ao contrato inteligente.
Chamaremos os métodos get e set em nome de o supermercado. e fornecedor para demonstrar a transação privada no Quorum.
Implantaremos um contrato privado para os participantes O supermercado e Fornecedor através do participante O supermercado:
const contractAddress = await deployContract( raft1Node, process.env.PK2, ); console.log(`Endereço do contrato após a implantação: ${contractAddress}`);Definiremos a temperatura de uma terceira parte (nó externo) e obteremos 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}`);Definiremos a temperatura de fornecedor (nó interno) e obteremos o valor da temperatura:
A temperatura neste cenário deve retornar do contrato inteligente o valor 12. Note que Fornecedor aqui tem acesso permitido 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}`);Obtendo a temperatura de uma terceira parte (nó externo):
No passo 3, a temperatura foi definida com o valor 12, mas Uma terceira parte não tem acesso ao contrato inteligente. Portanto, o valor retornado deve ser null.
// This returns null const temp3 = await getTemperature(raft3Node, contractAddress); console.log(`[Node3] temp retrieved from external nodes after update ${temp}`);A seguir, veremos mais detalhadamente a execução de transações privadas na rede Quorum com . Como a maior parte do código é semelhante às transações públicas, destacaremos apenas as partes que diferem para transações privadas.
Por favor, note que o contrato carregado na rede é imutável, portanto, o acesso permissionado deve ser concedido aos nós apropriados ao incluir o contrato público no momento do deployment 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’,
// Conceder permissão ao contrato incluindo as chaves públicas dos nós
privateFor: [publicKey],
})
.then((contract) => {
return contract.options.address;
});
}Da mesma forma, as transações privadas são realizadas - 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,
// Conceder permissão incluindo as chaves públicas dos nós
privateFor: [publicKey],
}).then((receipt) => {
return receipt.status;
});
}Agora podemos iniciar com os seguintes resultados:
node private.js
Endereço do contrato após o deployment: 0x85dBF88B4dfa47e73608b33454E4e3BA2812B21D
[Node3] temperatura recuperada após atualização do contrato de nós externos: null
[Node2] temperatura recuperada após atualização do contrato de nós internos: 12
[Node3] temperatura recuperada de nós externos após atualização nullO explorador Quorum na Chainstack mostrará o seguinte:
- deployment do contrato pelo participante O supermercado;
- Execução
SetTemperaturede uma terceira parte; - Execução
SetTemperaturepelo participante Fornecedor.

Como você pode ver, ambas as transações foram executadas, mas apenas a transação do participante Fornecedor atualizou a temperatura no contrato. Assim, as transações privadas garantem a imutabilidade, mas também não revelam dados a terceiros.
Conclusão
Nós analisamos um cenário comercial do uso do Quorum para garantir informações atualizadas sobre a temperatura em um armazém, através do deployment de uma rede entre duas partes - um supermercado e o proprietário do armazém.
Mostramos como as informações atualizadas sobre a temperatura podem ser mantidas por meio de transações públicas e privadas.
Os cenários de aplicação podem ser muitos e, como você pode ver, não é tão difícil.
Experimente, tente implantar seu cenário. Além disso, a indústria de tecnologias blockchain .
Fonte: habr.com
