ProHoster > Блог > администрация > Извършвайте публични и частни транзакции в блокчейна на JPMorgan Quorum с помощта на Web3
Извършвайте публични и частни транзакции в блокчейна на JPMorgan Quorum с помощта на Web3
кворум е базирана на Ethereum блокчейн, разработена от JPMorgan и наскоро стана първата платформа за разпределени счетоводни книги, предлагана от Microsoft Azure.
Quorum поддържа частни и публични транзакции и има много случаи на търговска употреба.
В тази статия ще разгледаме един такъв сценарий - разгръщането на мрежа от разпределени счетоводни книги между супермаркет и собственик на склад, за да предостави актуална информация за температурата на склада.
За да илюстрираме, ние използваме сценарий за наблюдение на температурата в складове на членове на мрежата Quorum в рамките на Интернет на нещата (IoT).
контекст
Група складови компании се обединяват в консорциум, за да съхраняват съвместно информация и да автоматизират процесите в блокчейна. За целта компаниите решиха да използват Quorum. В тази статия ще разгледаме два сценария: публични транзакции и частни транзакции.
Транзакциите се създават от различни участници, за да взаимодействат с консорциума, към който принадлежат. Всяка транзакция или внедрява договор, или извиква функция в договора за качване на данни в мрежата. Тези действия се копират към всички възли в мрежата.
Публичните транзакции са достъпни за преглед от всички участници в консорциума. Частните транзакции добавят ниво на поверителност и са достъпни само за онези участници, които имат права за това.
И за двата сценария използваме един и същ договор за по-голяма яснота.
Интелигентен договор
По-долу е прост интелигентен договор, създаден за нашия сценарий. Има публична променлива temperature, които могат да се променят с помощта на set и получавате по метод 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;
}
}
За да може договорът да работи с web3.js, той трябва да бъде преведен в ABI формат и байт код. Използване на функцията formatContractпо-долу компилира договора с помощта на solc-js.
Сега, когато договорът е готов, ние ще разгърнем мрежата и ще разгърнем договора.
Разгръщане на възел
Разполагането на възел може да бъде доста трудоемко и този процес може да бъде заменен с използване на услуга Верига.
По-долу е процесът за разгръщане на мрежата Quorum с консенсус на Raft и три възела.
Първо, нека създадем проект и да го наречем Quorum Project:
Нека създадем кворумна мрежа с консенсус на Raft в Google Cloud Platform:
Нека добавим още два възела към вече създадения по подразбиране възел:
Три работещи възела:
Страницата с подробности за възела показва RPC крайната точка, публичния ключ и т.н.
Мрежата е разгърната. Сега нека внедрим интелигентни договори и да извършваме транзакции, използвайки web3.js.
Публични сделки
контекст
Температурата в склада е от голямо значение за намаляване на разходите, особено за продукти, предназначени за съхранение при минусови температури.
Като позволяват на компаниите да споделят външната температура на тяхното географско местоположение в реално време и да я записват в неизменна книга, участниците в мрежата намаляват разходите и времето.
Ще изпълним три задачи, илюстрирани на диаграмата:
Ние ще внедрим договора чрез Възел 1:
const contractAddress = await deployContract(raft1Node);
console.log(`Contract address after deployment: ${contractAddress}`);
Задайте температурата чрез Възел 2 с 3 градуса:
const status = await setTemperature(raft2Node, contractAddress, 3);
console.log(`Transaction status: ${status}`);
Възел 3 ще получи информация от интелигентния договор. Договорът ще върне стойността 3 степени:
След това ще разгледаме как да изпълним публична транзакция в мрежата на Quorum, използвайки web3.js.
Инициираме екземпляр чрез RPC за три възела:
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,
},
);
Нека внедрим интелигентния договор:
// 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 предоставя два метода за взаимодействие с договора: call и send.
Нека актуализираме температурата на договора, като изпълним set използвайки метода 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;
});
}
След това използваме метода web3 call за получаване на договорната температура. Моля, имайте предвид, че методът call се изпълнява на локален възел и транзакцията няма да бъде създадена в блокчейна.
// 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);
}
Сега можете да бягате public.js за да получите следния резултат:
// Execute public script
node public.js
Contract address after deployment: 0xf46141Ac7D6D6E986eFb2321756b5d1e8a25008F
Transaction status: true
Retrieved contract Temperature 3
След това можем да видим записите в Quorum Explorer в панела Chainstack, както е показано по-долу.
И трите възела си взаимодействаха и транзакциите бяха актуализирани:
Първата транзакция разгърна договора.
Втората транзакция зададе температурата на договора на 3 градуса.
Температурата се получава чрез локален възел, така че не се създава транзакция.
Частни сделки
контекст
Общо изискване на организациите е защитата на данните. Като пример, разгледайте сценарий, при който Супермаркет отдава под наем складово помещение за съхранение на морски дарове от отдел Доставчик:
Доставчик използвайки IoT сензори, чете температурни стойности на всеки 30 секунди и ги предава До супермаркета;
тези стойности трябва да са налични само Към продавача и До супермаркета, свързани в мрежа от консорциум.
Ще изпълним четирите задачи, илюстрирани на диаграмата по-горе.
Използваме същите три възела от предишния сценарий, за да демонстрираме частни транзакции:
супермаркет внедрява интелигентен договор, който е частен за Супермаркет и Доставчик.
Третата страна няма право на достъп до интелигентния договор.
Ще извикаме методите get и set от името на Супермаркет и Доставчик за демонстриране на транзакция с частен кворум.
Ние ще разположим частен договор за участниците супермаркет и Доставчик чрез участник супермаркет:
Нека зададем температурата от Трета страна (външен възел) и вземете стойността на температурата:
// 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}`);
Нека зададем температурата от Доставчик (вътрешен възел) и вземете стойността на температурата:
Температурата в този сценарий трябва да върне стойността 12 от интелигентния договор. Моля, имайте предвид, че Доставчик тук има разрешен достъп до интелигентния договор.
// 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}`);
Получаваме температурата от Трета страна (външен възел):
В стъпка 3 температурата беше зададена на 12, но Третата страна няма достъп до интелигентния договор. Следователно върнатата стойност трябва да е нула.
// This returns null
const temp3 = await getTemperature(raft3Node, contractAddress);
console.log(`[Node3] temp retrieved from external nodes after update ${temp}`);
След това ще разгледаме по-отблизо извършването на частни транзакции в мрежата на Quorum с web3.js. Тъй като по-голямата част от кода е един и същ за публични транзакции, ще подчертаем само онези части, които са различни за частни транзакции.
Обърнете внимание, че договорът, качен в мрежата, е неизменен, така че разрешеният достъп трябва да бъде предоставен на съответните възли чрез активиране на публичния договор в момента на внедряване на договора, а не след това.
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;
});
}
Частните транзакции се извършват по подобен начин – чрез включване на публичния ключ на участниците в момента на изпълнение.
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;
});
}
Сега можем да бягаме private.js със следните резултати:
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
Изследователят на Quorum в Chainstack ще покаже следното:
разгръщане на договора от участника супермаркет;
изпълнение SetTemperature от Трета страна;
изпълнение SetTemperature от участник Доставчик.
Както можете да видите, и двете транзакции са завършени, но само транзакцията от участника Доставчик актуализира температурата в договора. Така частните транзакции осигуряват неизменност, но в същото време не разкриват данни на трета страна.
Заключение
Разгледахме случай на комерсиална употреба на Quorum за предоставяне на актуална информация за температурата в склад чрез разгръщане на мрежа между две страни – супермаркет и собственик на склад.
Показахме как може да се поддържа актуална информация за температурата чрез публични и частни транзакции.
Може да има много сценарии за приложение и, както виждате, не е никак трудно.