Effectuer des transactions publiques et privées sur la blockchain JPMorgan Quorum à l'aide de Web3



Quorum est une blockchain basée sur Ethereum développée par JPMorgan et est récemment devenue la premiÚre plate-forme de registre distribuée offerte par Microsoft Azure.


Quorum prend en charge les transactions privées et publiques et dispose de nombreux cas d'utilisation commerciale.


Dans cet article, nous analyserons l'un de ces scénarios - le déploiement d'un réseau de registre distribué entre un supermarché et un propriétaire d'entrepÎt pour fournir des informations pertinentes sur la température d'un entrepÎt.


Le code utilisé dans ce guide se trouve dans le référentiel sur GitHub .


L'article couvre:


  • crĂ©er un contrat intelligent;
  • DĂ©ploiement du rĂ©seau Quorum avec Chainstack
  • Transactions publiques de quorum
  • Transactions privĂ©es de quorum.

Pour illustrer cela, nous utilisons le scénario de surveillance de la température dans les salles de stockage des participants au réseau Quorum dans le cadre de l'Internet des objets (IoT).


Contexte


Un groupe de sociétés d'entrepÎt est uni dans un consortium pour le stockage conjoint d'informations et l'automatisation des processus sur la blockchain. Pour cela, les entreprises ont décidé d'utiliser Quorum. Dans cet article, nous couvrirons deux scénarios: les transactions publiques et les transactions privées.


Les transactions sont créées par diffĂ©rents participants pour interagir avec le consortium auquel ils appartiennent. Chaque transaction dĂ©ploie un contrat ou appelle une fonction dans un contrat pour tĂ©lĂ©charger des donnĂ©es sur le rĂ©seau. Ces actions sont rĂ©pliquĂ©es sur tous les nƓuds du rĂ©seau.


Les transactions publiques peuvent ĂȘtre consultĂ©es par tous les membres du consortium. Les transactions privĂ©es ajoutent une couche de confidentialitĂ© et ne sont disponibles que pour les participants qui y ont droit.


Pour les deux scĂ©narios, nous utilisons le mĂȘme contrat pour plus de clartĂ©.


Contrat intelligent


Vous trouverez ci-dessous un simple contrat intelligent créé pour notre scĂ©nario. Il a une temperature variable publique, qui peut ĂȘtre modifiĂ©e Ă  l'aide de la mĂ©thode set et rĂ©cupĂ©rĂ©e par la mĂ©thode 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; } } 

Pour que le contrat fonctionne avec web3.js , il doit ĂȘtre converti au format ABI et au bytecode. L'utilisation de la fonction formatContract ci-dessous compile le contrat Ă  l'aide de solc-js .


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

Le contrat terminé est le suivant:


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

Maintenant que le contrat est prĂȘt, nous allons dĂ©ployer le rĂ©seau et dĂ©ployer le contrat.


Déploiement de noeud


image


Le dĂ©ploiement d'un nƓud peut prendre beaucoup de temps et ce processus peut ĂȘtre remplacĂ© Ă  l'aide du service Chainstack .


Voici un processus de dĂ©ploiement de rĂ©seau Quorum avec un consensus Raft et trois nƓuds.


Pour commencer, commençons un projet et appelons-le le projet Quorum:


image


Créez un réseau Quorum avec le consensus Raft sur la plateforme Google Cloud:


image


Au nƓud par dĂ©faut dĂ©jĂ  créé, ajoutez deux nƓuds supplĂ©mentaires:


image


Trois nƓuds en cours d'exĂ©cution:


image


La page des dĂ©tails du nƓud affiche le point de terminaison RPC, la clĂ© publique, etc.


image


Le réseau est déployé. Nous allons maintenant déployer des contrats intelligents et exécuter des transactions à l'aide de web3.js.


Transactions publiques


Contexte


La température de l'entrepÎt est d'une grande importance pour réduire les coûts, en particulier pour les produits destinés au stockage à des températures inférieures à zéro.


En donnant aux entreprises la possibilité de partager les valeurs en temps réel de la température extérieure de leur emplacement géographique et de les enregistrer dans un registre immuable, les membres du réseau réduisent les coûts et le temps.


image


Nous réaliserons les trois tùches illustrées dans le schéma:


  1. Nous rĂ©silierons le contrat via le nƓud 1 :


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

  2. RĂ©glez la tempĂ©rature via le nƓud 2 Ă  3 degrĂ©s:


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

  3. Le nƓud 3 recevra les informations du contrat intelligent. Le contrat renverra une valeur de 3 degrĂ©s:


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

    Ensuite, nous verrons comment exécuter une transaction publique sur le réseau Quorum à l'aide de web3.js.



Nous initions une instance via RPC pour trois nƓuds:


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

Détruisez le contrat intelligent:


 // 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 propose deux méthodes pour interagir avec un contrat: call et send .


Mettez à jour la température du contrat en exécutant set à l'aide de la méthode d' 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; }); } 

Ensuite, nous utilisons la mĂ©thode d' call web3 pour obtenir la tempĂ©rature du contrat. Veuillez noter que la mĂ©thode d' call est exĂ©cutĂ©e sur le nƓud local et la transaction ne sera pas créée sur la 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); } 

Vous pouvez maintenant exécuter public.js pour obtenir le résultat suivant:


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

Ensuite, nous pouvons voir les entrées dans l'explorateur de quorum dans le panneau Chainstack, comme indiqué ci-dessous.


Les trois nƓuds ont interagi et les transactions ont Ă©tĂ© mises Ă  jour:


  1. La premiĂšre transaction a obtenu un contrat.
  2. La deuxiÚme transaction a fixé la température du contrat à 3 degrés.
  3. La tempĂ©rature est obtenue via le nƓud local, la transaction n'a donc pas Ă©tĂ© créée.

image


Transactions privées


Contexte


Une exigence courante des organisations est la protection des donnĂ©es. À titre d'exemple, considĂ©rons un scĂ©nario dans lequel un supermarchĂ© loue un entrepĂŽt pour stocker des fruits de mer auprĂšs d'un fournisseur distinct:


  • Le vendeur, Ă  l'aide de capteurs IoT, lit les valeurs de tempĂ©rature toutes les 30 secondes et les transmet au supermarchĂ© ;
  • ces valeurs ne devraient ĂȘtre disponibles que pour le vendeur et le supermarchĂ© , un consortium en rĂ©seau.

image


Nous terminerons les quatre tùches illustrées dans le diagramme ci-dessus.


  • Nous utilisons les trois mĂȘmes nƓuds du scĂ©nario prĂ©cĂ©dent pour illustrer les transactions privĂ©es:
  • Le supermarchĂ© dĂ©ploie un contrat intelligent qui est privĂ© au supermarchĂ© et au vendeur .
  • Un tiers n'a pas accĂšs au contrat intelligent.

Nous appellerons les méthodes get et set au nom du supermarché et du vendeur pour démontrer la transaction privée du quorum.


  1. Nous résilierons le contrat privé pour les participants au supermarché et au vendeur par le biais du participant au supermarché :


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

  2. RĂ©glez la tempĂ©rature Ă  partir du tiers (nƓud externe) et obtenez la valeur de tempĂ©rature:


     // 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. RĂ©glez la tempĂ©rature auprĂšs du fournisseur (nƓud interne) et obtenez la valeur de tempĂ©rature:


    La température dans ce scénario devrait revenir du contrat intelligent à 12. Veuillez noter que le fournisseur ici a autorisé l'accÚs au contrat intelligent.


     // 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. Obtenez la tempĂ©rature du tiers (nƓud externe):


    À l'Ă©tape 3, la tempĂ©rature a Ă©tĂ© rĂ©glĂ©e sur 12, mais le tiers n'a pas accĂšs au contrat intelligent. Par consĂ©quent, la valeur de retour doit ĂȘtre nulle.


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

    Ensuite, nous considĂ©rerons plus en dĂ©tail l'exĂ©cution de transactions privĂ©es sur le rĂ©seau Quorum avec web3.js. Étant donnĂ© que la plupart du code coĂŻncide avec des transactions publiques, nous sĂ©lectionnons uniquement les parties qui sont diffĂ©rentes pour les transactions privĂ©es.



Veuillez noter que le contrat tĂ©lĂ©chargĂ© sur le rĂ©seau est inchangeable, donc l'accĂšs avec autorisation doit ĂȘtre accordĂ© aux nƓuds correspondants en incluant le contrat public au moment du dĂ©ploiement du contrat, et non aprĂšs.


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

Les transactions privĂ©es sont effectuĂ©es de la mĂȘme maniĂšre - en incluant la clĂ© publique des participants au moment de l'exĂ©cution.


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

Maintenant, nous pouvons exécuter private.js avec les résultats suivants:


 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 

L'explorateur de quorum de Chainstack affichera les éléments suivants:


  • DĂ©ploiement d'un contrat d'un participant dans un supermarchĂ© ;
  • ExĂ©cution de SetTemperature partir d'un tiers ;
  • Effectuez une SetTemperature partir d'un participant fournisseur .

image


Comme vous pouvez le voir, les deux transactions sont terminĂ©es, mais seule la transaction du vendeur participant a mis Ă  jour la tempĂ©rature dans le contrat. Ainsi, les transactions privĂ©es offrent une immuabilitĂ©, mais en mĂȘme temps, elles ne fournissent pas de donnĂ©es Ă  un tiers.


Conclusion


Nous avons examiné le scénario commercial d'utilisation de Quorum pour fournir des informations à jour sur la température dans un entrepÎt en déployant un réseau entre deux parties - un supermarché et le propriétaire de l'entrepÎt.


Nous avons montrĂ© comment les informations sur la tempĂ©rature actuelle peuvent ĂȘtre conservĂ©es par le biais de transactions publiques et privĂ©es.


Il peut y avoir beaucoup de scénarios d'application et, comme vous le voyez, ce n'est pas du tout difficile.


Expérimentez, essayez de déployer votre script. De plus, l'industrie de la technologie blockchain peut croßtre prÚs de dix fois d'ici 2024 .

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


All Articles