
â en blockchain baserad pĂ„ Ethereum, utvecklad av JPMorgan och nyligen blivit den första plattformen för distribuerad ledger som erbjuds av Microsoft Azure.
Quorum stödjer bÄde privata och offentliga transaktioner och har mÄnga kommersiella anvÀndningsscenarier.
I denna artikel kommer vi att granska ett sĂ„dant scenario â att implementera ett distribuerat ledger-nĂ€tverk mellan en stormarknad och en lagerĂ€gare för att sĂ€kerstĂ€lla aktuell information om temperaturen i lagret.
Koden som anvÀnds i denna guide finns i .
Artikeln omfattar:
- skapande av ett smart kontrakt;
- implementering av ett Quorum-nÀtverk med hjÀlp av ;
- offentliga transaktioner i Quorum;
- privata transaktioner i Quorum.
För att illustrera anvÀnds ett scenario för temperaturövervakning i lagerutrymmen hos deltagarna i Quorum-nÀtverket inom ramen för Internet of Things (IoT).
Kontext
Gruppen av lagerföretag gÄr samman i ett konsortium för att gemensamt lagra information och automatisera processer pÄ blockchain. För detta har företagen beslutat att anvÀnda Quorum. I denna artikel kommer vi att tÀcka tvÄ scenarier: offentliga transaktioner och privata transaktioner.
Transaktioner skapas av olika deltagare för att interagera med det konsortium de tillhör. Varje transaktion antingen deployar ett kontrakt eller anropar en funktion i kontraktet för att ladda upp data till nÀtverket. Dessa ÄtgÀrder repliceras pÄ alla noder i nÀtverket.
Offentliga transaktioner Àr tillgÀngliga för visning av alla medlemmar i konsortiet. Privata transaktioner lÀgger till ett lager av sekretess och Àr endast tillgÀngliga för dem deltagare som har rÀttighet till det.
För bÄda scenarierna anvÀnder vi samma kontrakt för tydlighetens skull.
Smart kontrakt
Nedan finns ett enkelt smart kontrakt, skapad för vÄrt scenario. Det innehÄller en offentlig variabel temperature, som kan Àndras med metoden set och hÀmtas med metoden hÀmta.
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;
}
}För att kontraktet ska kunna fungera med , mÄste det översÀttas till ABI- och bytekodformat. AnvÀndningen av funktionen formatContract, som beskrivs nedan, kompilerar kontraktet med hjÀlp av .
function formatContract() {
const path = '.\/contracts\/temperatureMonitor.sol';
const source = fs.readFileSync(path,'UTF8');
return solc.compile(source, 1).contracts[':TemperatureMonitor'];
}Det fÀrdiga kontraktet ser ut pÄ följande sÀtt:
// 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
0x608060405234801561001057600080fd5b50610104806100206000396000f30060806040526004361060525763ffffffff7c01000000000000000000000000000000000000000000000000000000006000350416636d4ce63c81146057578063adccea12146082578063faee13b9146094575b600080fd5b348015606257600080fd5b50606960ae565b60408051600092830b90920b8252519081900360200190f35b348015608d57600080fd5b50606960b7565b348015609f57600080fd5b5060ac60043560000b60c0565b005b60008054900b90565b60008054900b81565b6000805491810b60ff1660ff199092169190911790555600a165627a7a72305820af0086d55a9a4e6d52cb6b3967afd764ca89df91b2f42d7bf3b30098d222e5c50029Nu nÀr kontraktet Àr klart kommer vi att distribuera nÀtverket och implementera kontraktet.
Utplacering av noder

Att distribuera en nod kan vara ganska arbetskrÀvande och denna process kan ersÀttas genom att anvÀnda en tjÀnst. .
Nedan visas processen för att distribuera ett Quorum-nÀtverk med Raft-konsensus och tre noder.
Först skapar vi ett projekt och döper det till Quorum Project:

Vi skapar ett Quorum-nÀtverk med Raft-konsensus pÄ Google Cloud Platform:

Till den redan skapade noden lÀgger vi till ytterligare tvÄ noder:

Tre körande noder:

Nodens detaljsida visar RPC-endpoint, publik nyckel osv.

NÀtverket Àr distribuerat. Nu gÄr vi vidare med att implementera smarta kontrakt och utföra transaktioner med hjÀlp av .
Offentliga transaktioner
Kontext
Lagringstemperaturen Àr mycket viktig för att minska kostnader, sÀrskilt för produkter som Àr avsedda att lagras vid minusgrader.
Genom att ge företag möjlighet att dela vÀrden av den externa temperaturen vid deras geografiska lÀge i realtid och registrera dem i ett oförÀnderligt register, minskar nÀtverksdeltagarna kostnader och tid.

Vi kommer att utföra tre uppgifter som illustreras i diagrammet:
Vi implementerar kontraktet via Nod 1:
const contractAddress = await deployContract(raft1Node); console.log(`Contract address after deployment: ${contractAddress}`);Vi stÀller in temperaturen via Nod 2 till 3 grader:
const status = await setTemperature(raft2Node, contractAddress, 3); console.log(`Transaction status: ${status}`);Nod 3 kommer att hÀmta information frÄn det smarta kontraktet. Kontraktet kommer att returnera vÀrdet 3 grader:
const temp = await getTemperature(raft3Node, contractAddress); console.log(âRetrieved contract Temperatureâ, temp);DĂ€refter tittar vi pĂ„ hur man utför en offentlig transaktion i Quorum-nĂ€tverket med hjĂ€lp av .
Vi initierar en instans via RPC för tre noder:
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,
},
);Vi implementerar det smarta kontraktet:
// 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;
});
} tillhandahÄller tvÄ metoder för att interagera med kontraktet: call och send.
Vi uppdaterar kontraktets temperatur genom att utföra set anvÀnda metoden 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;
});
}DÀrefter anvÀnder vi metoden web3 call för att hÀmta kontraktets temperatur. Observera att metoden call utförs pÄ den lokala noden och att ingen transaktion kommer att skapas pÄ blockkedjan.
// 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);
}Nu kan vi köra för att fÄ följande resultat:
// Execute public script
node public.js
Contract address after deployment: 0xf46141Ac7D6D6E986eFb2321756b5d1e8a25008F
Transaction status: true
Retrieved contract Temperature 3Vi kan nu titta pÄ poster i Quorum-explorern i Chainstack-panelen, som visas nedan.
Alla tre noder interagerade och transaktionerna uppdaterades:
- Den första transaktionen deployade kontraktet.
- Den andra transaktionen satte kontraktets temperatur till 3 grader.
- Temperaturen erhÄlls genom den lokala noden, dÀrför skapas ingen transaktion.

Privata transaktioner
Kontext
Ett vanligt krav frÄn organisationer Àr dataskydd. Som ett exempel kan vi övervÀga ett scenario dÀr supermarkedet hyr ett lager för lagring av skaldjur frÄn en separat leverantör:
- leverantör genom IoT-sensorer avlÀser temperaturvÀrden var 30:e sekund och överför dem till supermarkedet;
- och dessa vÀrden ska endast vara tillgÀngliga för leverantören och supermarkedet, som Àr förenade i ett konsortium.

Vi kommer att utföra fyra uppgifter, illustrerade i diagrammet ovan.
- Vi anvÀnder samma tre noder som i det föregÄende scenariot för att demonstrera privata transaktioner:
- supermarkedet deployar ett smart kontrakt som Àr privat för supermarkedet. och leverantör.
- Tredje part har inte rÀtt att fÄ tillgÄng till det smarta kontraktet.
Vi kommer att anropa metoder hÀmta och set Ä deras vÀgnar supermarkedet. och leverantör för att demonstrera en privat transaktion i Quorum.
Vi kommer att deploya ett privat kontrakt för deltagarna supermarkedet och leverantör genom deltagaren supermarkedet:
const contractAddress = await deployContract( raft1Node, process.env.PK2, ); console.log(`Kontraktsadress efter deployment: ${contractAddress}`);Vi sÀtter temperaturen av den tredje parten (extern nod) och fÄr temperaturvÀrdet:
// 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}`);Vi sÀtter temperaturen av leverantör (intern nod) och fÄr temperaturvÀrdet:
Temperaturen i detta scenario ska returnera vÀrdet 12 frÄn det smarta kontraktet. Observera att leverantör det hÀr har tillÄten tillgÄng till det smarta kontraktet.
// 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}`);Vi fÄr temperaturen frÄn den tredje parten (extern nod):
I steg 3 var temperaturen satt med vÀrdet 12, men Tredje part har inte tillgÄng till det smarta kontraktet. DÀrför bör vÀrdet som returneras vara null.
// This returns null const temp3 = await getTemperature(raft3Node, contractAddress); console.log(`[Node3] temp retrieved from external nodes after update ${temp}`);Vi ska nu titta mer ingÄende pÄ genomförandet av privata transaktioner i Quorum-nÀtverket med . Eftersom mycket av koden överensstÀmmer med offentliga transaktioner, kommer vi endast att markera de delar som skiljer sig för privata transaktioner.
Observera att kontraktet som laddades upp pÄ nÀtet Àr oförÀnderligt, sÄ Ätkomst med tillstÄnd (permissioned) mÄste ges till de aktuella noderna genom att inkludera det offentliga kontraktet vid distributionen av kontraktet och inte efterÄt.
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;
});
}PÄ samma sÀtt utförs privata transaktioner - genom att inkludera deltagarnas offentliga nyckel vid utförandet.
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;
});
}Nu kan vi starta med följande resultat:
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 nullQuorum-explorern i Chainstack kommer att visa följande:
- distributivt kontrakt frÄn deltagaren supermarkedet;
- Genomförande
SetTemperaturefrÄn den tredje parten; - Genomförande
SetTemperaturefrÄn deltagaren leverantör.

Som ni ser, bÄda transaktionerna genomfördes, men endast transaktionen frÄn deltagaren leverantör uppdaterade temperaturen i kontraktet. SÄledes sÀkerstÀller privata transaktioner oförÀnderlighet, men de avslöjar inte data för tredje part.
Slutsats
Vi har granskat ett kommersiellt anvÀndningsscenario för Quorum för att sÀkerstÀlla aktuell information om temperaturen i ett lager genom att distribuera ett nÀtverk mellan tvÄ parter - stormarknaden och lagerÀgaren.
Vi har visat hur aktuell information om temperaturen kan upprÀtthÄllas bÄde genom offentliga och privata transaktioner.
AnvÀndningsscenarierna kan vara mÄnga och, som ni ser, Àr det inte sÄ svÄrt.
Experimentera, försök att distribuera ditt scenario. Dessutom kan blockchain-teknologibranschen .
KĂ€lla: habr.com
