Виконання публічних та приватних транзакцій у блокчейні JPMorgan Quorum з використанням Web3

Виконання публічних та приватних транзакцій у блокчейні JPMorgan Quorum з використанням Web3

Кворум — блокчейн на базі Ethereum, розроблений JPMorgan і нещодавно став першою платформою розподіленого реєстру, яку пропонує Microsoft Azure.

Quorum підтримує приватні та публічні транзакції та має багато комерційних сценаріїв використання.

У цій статті ми розберемо один із таких сценаріїв — розгортання мережі розподіленого реєстру між супермаркетом та власником складу для забезпечення актуальної інформації про температуру складського приміщення.

Код, який використовується в цьому посібнику, лежить у репозиторії на GitHub.

Стаття покриває:

  • створення смарт-контракту;
  • розгортання мережі Quorum за допомогою Стек ланцюгів;
  • публічні транзакції Quorum;
  • приватні транзакції Quorum.

Для ілюстрації використовується сценарій моніторингу температури у складських приміщеннях учасників мережі Quorum у рамках Internet of Things (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.

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

Готовий контракт виглядає так:

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

Тепер, коли контракт готовий, ми розгорнемо мережу та задеплоємо контракт.

Розгортання нід

Виконання публічних та приватних транзакцій у блокчейні JPMorgan Quorum з використанням Web3

Розгортання ноди може бути досить трудомістким, і цей процес можна замінити використанням сервісу Стек ланцюгів.

Нижче наведено процес розгортання мережі Quorum з консенсусом Raft та трьома нодами.

Для початку заведемо проект і назвемо його Quorum Project:

Виконання публічних та приватних транзакцій у блокчейні JPMorgan Quorum з використанням Web3

Створимо мережу Quorum з консенсусом Raft на Google Cloud Platform:

Виконання публічних та приватних транзакцій у блокчейні JPMorgan Quorum з використанням Web3

До вже створеної за замовчуванням ноди додамо ще дві ноди:

Виконання публічних та приватних транзакцій у блокчейні JPMorgan Quorum з використанням Web3

Три запущені ноди:

Виконання публічних та приватних транзакцій у блокчейні JPMorgan Quorum з використанням Web3

Сторінка деталей ноди показує RPC endpoint, публічний ключ тощо.

Виконання публічних та приватних транзакцій у блокчейні JPMorgan Quorum з використанням Web3

Мережа розгорнута. Тепер займемося деплоєм смарт-контрактів та виконанням транзакцій за допомогою web3.js.

Публічні транзакції

Контекст

Температура складського приміщення має значення для зниження витрат, особливо для продуктів, призначених для зберігання при мінусовій температурі.

Даючи компаніям можливість ділитися значеннями зовнішньої температури їхнього географічного положення в режимі реального часу та записувати в незмінний реєстр, учасники мережі скорочують витрати та час.

Виконання публічних та приватних транзакцій у блокчейні JPMorgan Quorum з використанням Web3

Ми виконаємо три завдання, проілюстровані на діаграмі:

  1. Задеплоїмо контракт через Вузол 1:

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

  2. Встановимо температуру через Вузол 2 на 3 градуси:

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

  3. Вузол 3 отримає інформацію із смарт-контракту. Контракт поверне значення 3 градуси:

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

    Далі розглянемо як виконати публічну транзакцію у мережі 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 на панелі Chainstack, як показано нижче.

Усі три ноди провзаємодіяли та транзакції оновилися:

  1. Перша транзакція задеплоїла контракт.
  2. Друга транзакція встановила температуру контракту 3 градуси.
  3. Отримання температури відбувається через локальну ноду, тому транзакцію не створено.

Виконання публічних та приватних транзакцій у блокчейні JPMorgan Quorum з використанням Web3

Приватні транзакції

Контекст

Частою вимогою організацій є захист даних. Як приклад розглянемо сценарій, у якому Супермаркет орендує складське приміщення для зберігання морепродуктів у окремого Вендора:

  • Вендор за допомогою IoT-датчиків зчитує температурні значення кожні 30 секунд і передає їх Супермаркету;
  • дані значення мають бути доступні тільки Вендору и Супермаркету, об'єднаним у мережу консорціум.

Виконання публічних та приватних транзакцій у блокчейні JPMorgan Quorum з використанням Web3

Ми виконаємо чотири завдання, проілюстровані вище на діаграмі.

  • Використовуємо самі три ноди з попереднього сценарію для демонстрації приватних транзакцій:
  • супермаркет деплоїт смарт-контракт, який є приватним для Супермаркету и Вендора.
  • Третя сторона не має права на доступ до смарт-контракту.

Ми викличемо методи get и set від особи Супермаркету и Вендора для демонстрації приватної транзакції Quorum

  1. Задеплоїмо приватний контракт для учасників супермаркет и Вендор через учасника супермаркет:

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

  2. Встановимо температуру від Третього боку (зовнішня нода) та отримаємо значення температури:

    // 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. Встановимо температуру від Вендора (внутрішня нода) та отримаємо значення температури:

    Температура в цьому сценарії має повернути зі смарт-контракту значення 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}`);

  4. Отримаємо температуру від Третього боку (зовнішня нода):

    На кроці 3 температура була встановлена ​​зі значенням 12, але Третя сторона немає доступу до смарт-контракту. Тому повернення значення має бути null.

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

    Далі детальніше розглянемо виконання приватних транзакцій у мережі Quorum з web3.js. Оскільки більшість коду збігаються з публічними транзакціями, виділимо ті частини, які відрізняються приватних транзакцій.

Зверніть увагу, що контракт, завантажений у мережу, є незмінним, тому доступ з дозволом (permissioned) має бути виданий відповідним нодам шляхом включення публічного контракту на момент деплою контракту, а чи не після.

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 від учасника Вендор.

Виконання публічних та приватних транзакцій у блокчейні JPMorgan Quorum з використанням Web3

Як бачите, обидві транзакції виконані, але лише транзакція від учасника Вендор оновила температуру у контракті. Таким чином, приватні транзакції забезпечують незмінність, але при цьому не видають дані третій стороні.

Висновок

Ми розглянули комерційний сценарій використання Quorum для забезпечення актуальної інформації про температуру у складському приміщенні шляхом розгортання мережі між двома сторонами – супермаркетом та власником складу.

Ми показали, як актуальна інформація про температуру може підтримуватися як через публічні, так і через приватні транзакції.

Сценаріїв застосування може бути дуже багато і, як бачите, це зовсім не складно.

Експериментуйте, спробуйте розгорнути свій сценарій. Тим більше, що індустрія блокчейн-технологій. до 2024 року може зрости майже вдесятеро.

Джерело: habr.com

Додати коментар або відгук