Efectuați tranzacții publice și private pe blockchain-ul JPMorgan Quorum folosind Web3

Efectuați tranzacții publice și private pe blockchain-ul JPMorgan Quorum folosind Web3

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

Quorum поддерживает приватные и публичные транзакции и имеет много коммерческих сценариев использования.

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

Код, используемый в данном руководстве, лежит в depozite pe GitHub.

Статья покрывает:

  • создание смарт-контракта;
  • развертывание сети Quorum при помощи Chainstack;
  • публичные транзакции Quorum;
  • приватные транзакции Quorum.

Для иллюстрации используется сценарий мониторинга температуры в складских помещениях участников сети Quorum в рамках Internet of Things (IoT).

context

Группа складских компаний объединяется в консорциум для совместного хранения информации и автоматизации процессов на блокчейне. Для этого компании решили использовать Quorum. В данной статье мы покроем два сценария: публичные транзакции и приватные транзакции.

Транзакции создаются разными участниками для взаимодействия с консорциумом, которому они принадлежат. Каждая транзакция либо деплоит контракт, либо вызывает функцию в контракте для загрузки данных в сеть. Данные действия реплицируются на все ноды в сети.

Публичные транзакции доступны для просмотра всеми участниками консорциума. Приватные же транзакции добавляют слой конфиденциальности и доступны только тем участникам, у которых есть на это права.

Для обоих сценариев мы для наглядности используем один и тот же контракт.

Contract inteligent

Ниже приведен простой смарт-контракт, созданный для нашего сценария. В нем есть публичная переменная 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

Теперь, когда контракт готов, мы развернем сеть и задеплоим контракт.

Развертывание нод

Efectuați tranzacții publice și private pe blockchain-ul JPMorgan Quorum folosind Web3

Развертывание ноды может быть довольно трудоемким и этот процесс можно заменить использованием сервиса Chainstack.

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

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

Efectuați tranzacții publice și private pe blockchain-ul JPMorgan Quorum folosind Web3

Создадим сеть Quorum с консенсусом Raft на Google Cloud Platform:

Efectuați tranzacții publice și private pe blockchain-ul JPMorgan Quorum folosind Web3

К уже созданной по умолчанию ноде добавим еще две ноды:

Efectuați tranzacții publice și private pe blockchain-ul JPMorgan Quorum folosind Web3

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

Efectuați tranzacții publice și private pe blockchain-ul JPMorgan Quorum folosind Web3

Страница деталей ноды показывает RPC endpoint, публичный ключ и т. д.

Efectuați tranzacții publice și private pe blockchain-ul JPMorgan Quorum folosind Web3

Сеть развернута. Теперь займемся деплоем смарт-контрактов и выполнением транзакций при помощи web3.js.

Публичные транзакции

context

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

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

Efectuați tranzacții publice și private pe blockchain-ul JPMorgan Quorum folosind Web3

Мы выполним три задачи, проиллюстрированные на диаграмме:

  1. Задеплоим контракт через Nodul 1:

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

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

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

  3. Nodul 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);
}

Teper mojno zapustit 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. Получение температуры происходит через локальную ноду, поэтому транзакция не создана.

Efectuați tranzacții publice și private pe blockchain-ul JPMorgan Quorum folosind Web3

Приватные транзакции

context

Частым требованием организаций является защита данных. В качестве примера рассмотрим сценарий, в котором Cупермаркет арендует складское помещение для хранения морепродуктов у отдельного Вендора:

  • Furnizor при помощи IoT-датчиков считывает температурные значения каждые 30 секунд и передает их Cупермаркету;
  • данные значения должны быть доступны только Вендору и Супермаркету, объединенным в сеть консорциум.

Efectuați tranzacții publice și private pe blockchain-ul JPMorgan Quorum folosind Web3

Мы выполним четыре задачи, проиллюстрированные на диаграмме выше.

  • Используем те же три ноды из предыдущего сценария для демонстрации приватных транзакций:
  • Supermarket деплоит смарт-контракт, который является приватным для Супермаркета и Вендора.
  • A treia latură не имеет права доступа к смарт-контракту.

Мы вызовем методы get и set în numele Супермаркета и Вендора для демонстрации приватной транзакции Quorum.

  1. Задеплоим приватный контракт для участников Supermarket и Furnizor через участника Supermarket:

    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. Обратите внимание, что Furnizor здесь имеет разрешенный доступ к смарт-контракту.

    // 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, но A treia latură не имеет доступа к смарт-контракту. Поэтому возврат значения должен быть 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 покажет следующее:

  • деплой контракта от участника Supermarket;
  • execuție SetTemperature din Третьей стороны;
  • execuție SetTemperature от участника Furnizor.

Efectuați tranzacții publice și private pe blockchain-ul JPMorgan Quorum folosind Web3

Как видите, обе транзакции выполнены, но только транзакция от участника Furnizor обновила температуру в контракте. Таким образом, приватные транзакции обеспечивают неизменяемость, но при этом и не выдают данные третьей стороне.

Concluzie

Мы рассмотрели коммерческий сценарий использования Quorum для обеспечения актуальной информации о температуре в складском помещении путем развертывания сети между двумя сторонами — супермаркетом и владельцем склада.

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

Сценариев применения может быть очень много и, как видите, это совсем не сложно.

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

Sursa: www.habr.com

Adauga un comentariu