📜 ⬆️ ⬇️

Perform public and private transactions on the JPMorgan Quorum blockchain using Web3



Quorum is a Ethereum-based blockchain developed by JPMorgan and most recently the first distributed registry platform offered by Microsoft Azure.


Quorum supports private and public transactions and has many commercial use cases.


In this article we will examine one of these scenarios - the deployment of a distributed registry network between a supermarket and a warehouse owner to provide up-to-date information about the temperature of the warehouse.


The code used in this tutorial is in the GitHub repository .


The article covers:



For illustration, a temperature monitoring scenario is used in the warehouse premises of Quorum network members within the Internet of Things (IoT).


Context


A group of warehousing companies joins together in a consortium to share information and automate processes on the blockchain. For this, the companies decided to use Quorum. In this article we will cover two scenarios: public transactions and private transactions.


Transactions are created by different participants to interact with the consortium to which they belong. Each transaction either deploit the contract, or calls a function in the contract to download data to the network. These actions are replicated to all nodes in the network.


Public transactions are available for viewing by all members of the consortium. Private transactions add a layer of confidentiality and are available only to those participants who have rights to do so.


For both scenarios, we use the same contract for clarity.


Smart contract


Below is a simple smart contract created for our scenario. It has a public variable temperature , which can be changed by the set method and obtained by the get method.


 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; } } 

In order for the contract to work with web3.js , it needs to be converted to ABI format and bytecode. Using the formatContract function below compiles a contract using solc-js .


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

The finished contract is as follows:


 // 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 

Now that the contract is ready, we will deploy the network and complete the contract.


Deploying Nodes


image


Deploying a node can be quite time consuming and this process can be replaced using the Chainstack service.


Below is the process of deploying a Quorum network with a consensus of Raft and three nodes.


To get started, we will start a project and name it Quorum Project:


image


Create a Quorum network with the Raft consensus on the Google Cloud Platform:


image


Add two more nodes to the node already created by default:


image


Three running nodes:


image


The detail page of the node shows the RPC endpoint, the public key, and so on.


image


The network is deployed. Now let's deal with the deployment of smart contracts and the execution of transactions using web3.js.


Public transactions


Context


The temperature of the storage room is of great importance for reducing costs, especially for products intended for storage at sub-zero temperatures.


By giving companies the ability to share the external temperature values ​​of their geographic location in real time and write to an immutable registry, network members reduce costs and time.


image


We will complete the three tasks illustrated in the diagram:


  1. Seal the contract through Node 1 :


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

  2. Set the temperature through Node 2 to 3 degrees:


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

  3. Node 3 will receive information from the smart contract. The contract will return the value of 3 degrees:


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

    Next, consider how to execute a public transaction on the Quorum network using web3.js.



We initiate instans through RPC for three nodes:


 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, }, ); 

Seen a smart contract:


 // 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; }); } 

web3.js provides two methods for interacting with a contract: call and send .


Update the contract temperature by running set using the web3 send method.


 // 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; }); } 

Next, we use the web3 call method to get the contract temperature. Please note that the call method is executed on the local node and the transaction will not be created on the 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); } 

You can now run public.js to get the following result:


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

Next, we can look at the Quorum Explorer entries in the Chainstack panel, as shown below.


All three nodes interacted and transactions were updated:


  1. The first transaction closed the contract.
  2. The second transaction set the contract temperature to 3 degrees.
  3. Getting the temperature occurs through the local node, so the transaction is not created.

image


Private transactions


Context


A frequent requirement of organizations is data protection. As an example, consider the scenario in which the Supermarket rents a warehouse for the storage of seafood from a separate vendor :



image


We will complete the four tasks illustrated in the diagram above.



We will call the get and set methods on behalf of the Supermarket and Vendor to demonstrate the Quorum private transaction.


  1. We will secure a private contract for the Supermarket and Vendor participants through the Supermarket participant:


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

  2. Set the temperature from the Third Party (external node) and get the temperature value:


     // 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. Set the temperature from the vendor (internal node) and get the temperature value:


    The temperature in this scenario should return the value of 12 from the smart contract. Please note that the vendor here has allowed access to the smart contract.


     // 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. Get the temperature from the Third Party (external node):


    In step 3, the temperature was set to 12, but the Third Party does not have access to the smart contract. Therefore, the return value must be null.


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

    Next, we will take a closer look at performing private transactions on the Quorum network with web3.js. Since most of the code coincides with public transactions, select only those parts that are different for private transactions.



Please note that the contract loaded onto the network is immutable, so permission with permission must be issued to the appropriate nodes by including a public contract at the time of the contract’s deployment, and not after.


 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; }); } 

Similarly, private transactions are performed — by including the public key of the participants at the time of execution.


 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; }); } 

Now we can run private.js with the following results:


 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 

The Quorum Explorer in Chainstack will show the following:



image


As you can see, both transactions are completed, but only the transaction from the Vendor participant has updated the temperature in the contract. Thus, private transactions provide immutability, but at the same time they do not give out data to third parties.


Conclusion


We looked at the commercial use of Quorum to provide up-to-date information about the temperature in the storage room by deploying a network between two parties - the supermarket and the warehouse owner.


We have shown how up-to-date temperature information can be maintained through both public and private transactions.


There can be a lot of application scenarios and, as you can see, it is not at all difficult.


Experiment, try to deploy your script. Moreover, the blockchain technology industry may grow almost tenfold by 2024 .


')

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


All Articles