Wykonywanie publicznych i prywatnych transakcji w blockchainie JPMorgan Quorum z wykorzystaniem Web3

Wykonywanie publicznych i prywatnych transakcji w blockchainie JPMorgan Quorum z wykorzystaniem Web3

Quorum — blockchain oparty na Ethereum, opracowany przez JPMorgan, który niedawno stał się pierwszą platformą rozproszonych rejestrów dostępną na Microsoft Azure.

Quorum obsługuje transakcje prywatne i publiczne oraz ma wiele komercyjnych scenariuszy zastosowania.

W tym artykule omówimy jeden z takich scenariuszy — wdrażanie sieci rozproszonego rejestru między supermarketem a właścicielem magazynu w celu zapewnienia aktualnych informacji o temperaturze w pomieszczeniu magazynowym.

Kod używany w tym przewodniku znajduje się w repozytorium na GitHubie.

Artykuł obejmuje:

  • tworzenie smart kontraktów;
  • wdrażanie sieci Quorum przy użyciu Chainstack;
  • publiczne transakcje Quorum;
  • prywatne transakcje Quorum.

Do ilustracji wykorzystano scenariusz monitorowania temperatury w pomieszczeniach magazynowych uczestników sieci Quorum w ramach Internet of Things (IoT).

Kontekst

Grupa firm magazynowych łączy się w konsorcjum, aby wspólnie przechowywać informacje i automatyzować procesy na blockchainie. W tym celu firmy postanowiły wykorzystać Quorum. W tym artykule omówimy dwa scenariusze: transakcje publiczne i transakcje prywatne.

Transakcje są tworzone przez różnych uczestników w celu interakcji z konsorcjum, do którego należą. Każda transakcja albo wdraża kontrakt, albo wywołuje funkcję w kontrakcie, aby załadować dane do sieci. Te operacje są replikowane na wszystkich węzłach w sieci.

Transakcje publiczne są dostępne do przeglądania przez wszystkich uczestników konsorcjum. Im jednak transakcje prywatne dodają warstwę poufności i są dostępne tylko dla tych uczestników, którzy mają do tego prawa.

Dla obu scenariuszy dla przejrzystości używamy tego samego kontraktu.

Smart kontrakt

Poniżej przedstawiono prosty smart kontrakt stworzony dla naszego scenariusza. Zawiera on publiczną zmienną temperature, którą można zmieniać metodą set i uzyskiwać metodą 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;
  }
}

Aby kontrakt działał z web3.js, należy go przetłumaczyć na format ABI i kod bajtowy. Użycie funkcji formatContract, przedstawionej poniżej, kompiluje kontrakt przy użyciu solc-js.

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

Gotowy kontrakt wygląda następująco:

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

Teraz, gdy kontrakt jest gotowy, wdrożymy sieć i rozproszymy kontrakt.

Wdrażanie węzłów

Wykonywanie publicznych i prywatnych transakcji w blockchainie JPMorgan Quorum z wykorzystaniem Web3

Wdrażanie węzła może być dość pracochłonne i ten proces można zastąpić używaniem usługi Chainstack.

Poniżej przedstawiony jest proces wdrażania sieci Quorum z konsensusem Raft i trzema węzłami.

Na początku załóżmy projekt i nazwijmy go Quorum Project:

Wykonywanie publicznych i prywatnych transakcji w blockchainie JPMorgan Quorum z wykorzystaniem Web3

Utworzymy sieć Quorum z konsensusem Raft na Google Cloud Platform:

Wykonywanie publicznych i prywatnych transakcji w blockchainie JPMorgan Quorum z wykorzystaniem Web3

Do już utworzonego domyślnie węzła dodamy jeszcze dwa węzły:

Wykonywanie publicznych i prywatnych transakcji w blockchainie JPMorgan Quorum z wykorzystaniem Web3

Trzy uruchomione węzły:

Wykonywanie publicznych i prywatnych transakcji w blockchainie JPMorgan Quorum z wykorzystaniem Web3

Strona szczegółów węzła pokazuje punkt końcowy RPC, klucz publiczny itd.

Wykonywanie publicznych i prywatnych transakcji w blockchainie JPMorgan Quorum z wykorzystaniem Web3

Sieć została wdrożona. Teraz zajmiemy się rozproszonymi kontraktami inteligentnymi i wykonywaniem transakcji za pomocą web3.js.

Publiczne transakcje

Kontekst

Temperatura w pomieszczeniu magazynowym ma duże znaczenie dla obniżenia kosztów, szczególnie dla produktów przeznaczonych do przechowywania w ujemnych temperaturach.

Dając firmom możliwość dzielenia się wartościami zewnętrznej temperatury ich lokalizacji geograficznej w czasie rzeczywistym i zapisywania ich w niezmiennym rejestrze, uczestnicy sieci zmniejszają wydatki i czas.

Wykonywanie publicznych i prywatnych transakcji w blockchainie JPMorgan Quorum z wykorzystaniem Web3

Wykonamy trzy zadania, przedstawione na diagramie:

  1. Rozproszymy kontrakt przez Węzeł 1:

    const contractAddress = await deployContract(raft1Node);
    console.log(`Adres kontraktu po wdrożeniu: ${contractAddress}`);

  2. Ustalimy temperaturę przez Węzeł 2 o 3 stopnie:

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

  3. Węzeł 3 pobierze informacje z kontraktu inteligentnego. Kontrakt zwróci wartość 3 stopni:

    const temp = await getTemperature(raft3Node, contractAddress);
    console.log(‘Pobrana temperatura kontraktu’, temp);

    Następnie omówimy, jak wykonać publiczną transakcję w sieci Quorum z użyciem web3.js.

Inicjujemy instancję przez RPC dla trzech węzłów:

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

Rozproszmy kontrakt inteligentny:

// 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 zapewnia dwie metody do interakcji z kontraktem: call i send.

Zaktualizujemy temperaturę kontraktu wykonując set używając metody 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;
  });
}

Następnie użyjemy metody web3 call aby uzyskać temperaturę kontraktu. Zauważ, że metoda call jest wykonywana na lokalnym węźle i na blockchainie transakcja nie zostanie utworzona.

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

Teraz można uruchomić public.js aby uzyskać następujący wynik:

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

Następnie możemy zobaczyć zapisy w eksploratorze Quorum w panelu Chainstack, jak pokazano poniżej.

Wszystkie trzy węzły współdziałały, a transakcje zostały zaktualizowane:

  1. Pierwsza transakcja wdrożyła kontrakt.
  2. Druga transakcja ustawiła temperaturę kontraktu na 3 stopnie.
  3. Odczyt temperatury odbywa się przez lokalny węzeł, dlatego transakcja nie została utworzona.

Wykonywanie publicznych i prywatnych transakcji w blockchainie JPMorgan Quorum z wykorzystaniem Web3

Transakcje prywatne

Kontekst

Częstym wymogiem organizacji jest ochrona danych. Na przykład rozważmy scenariusz, w którym supermarket wynajmuje przestrzeń magazynową do przechowywania owoców morza od oddzielnego dostawcy:

  • Dostawca poprzez czujniki IoT odczytuje wartości temperatury co 30 sekund i przesyła je supermarketowi;
  • te wartości powinny być dostępne tylko dla dostawcy i supermarketu, połączonego w sieć konsorcjum.

Wykonywanie publicznych i prywatnych transakcji w blockchainie JPMorgan Quorum z wykorzystaniem Web3

Wykonamy cztery zadania, ilustrowane na powyższym diagramie.

  • Użyjemy tych samych trzech węzłów z poprzedniego scenariusza do demonstracji transakcji prywatnych:
  • supermarket wdroży inteligentny kontrakt, który jest prywatny dla supermarketu i dostawcy.
  • Trzecia strona nie ma dostępu do inteligentnego kontraktu.

Wywołamy metody get i set w imieniu supermarketu i dostawcy aby zademonstrować prywatną transakcję Quorum.

  1. Wdrożymy prywatny kontrakt dla uczestników supermarket i Dostawca przez uczestnika supermarket:

    const contractAddress = await deployContract(
    raft1Node,
    process.env.PK2,
    );
    console.log(`Adres kontraktu po wdrożeniu: ${contractAddress}`);

  2. Ustalimy temperaturę od Trzeciej strony (zewnętrzny węzeł) i otrzymamy wartość temperatury:

    // 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. Ustalimy temperaturę od dostawcy (wewnętrzny węzeł) i otrzymamy wartość temperatury:

    Temperatura w tym scenariuszu powinna zwrócić wartość 12 z inteligentnego kontraktu. Zauważ, że Dostawca ma tu dozwolony dostęp do inteligentnego kontraktu.

    // 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. Otrzymamy temperaturę od Trzeciej strony (zewnętrzny węzeł):

    Na kroku 3 temperatura została ustawiona na wartość 12, ale Trzecia strona nie ma dostępu do inteligentnego kontraktu. Dlatego zwrócona wartość powinna być null.

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

    Następnie dokładniej przyjrzymy się realizacji transakcji prywatnych w sieci Quorum z web3.js. Ponieważ większość kodu pokrywa się z publicznymi transakcjami, uwydatnimy tylko te części, które różnią się dla transakcji prywatnych.

Zauważ, że kontrakt załadowany do sieci jest niezmienny, więc dostęp z pozwoleniem (permissioned) musi zostać przyznany odpowiednim węzłom przez uwzględnienie publicznego kontraktu w momencie wdrożenia kontraktu, a nie później.

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

W podobny sposób realizowane są transakcje prywatne — poprzez uwzględnienie publicznego klucza uczestników w momencie wykonania.

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

Teraz możemy uruchomić private.js z następującymi wynikami:

node private.js
Adres kontraktu po wdrożeniu: 0x85dBF88B4dfa47e73608b33454E4e3BA2812B21D
[Node3] temperatura pobrana po aktualizacji kontraktu z zewnętrznych węzłów: null
[Node2] temperatura pobrana po aktualizacji kontraktu z wewnętrznych węzłów: 12
[Node3] temperatura pobrana z zewnętrznych węzłów po aktualizacji: null

Eksplorator Quorum w Chainstack pokaże następująco:

  • wdrożenie kontraktu przez uczestnika supermarket;
  • Wykonywanie SetTemperature od Trzeciej strony;
  • Wykonywanie SetTemperature przez uczestnika Dostawca.

Wykonywanie publicznych i prywatnych transakcji w blockchainie JPMorgan Quorum z wykorzystaniem Web3

Jak widać, obie transakcje zostały wykonane, ale tylko transakcja od uczestnika Dostawca aktualizowała temperaturę w kontrakcie. W ten sposób transakcje prywatne zapewniają niezmienność, ale nie ujawniają danych osobie trzeciej.

Podsumowanie

Omówiliśmy komercyjny scenariusz użycia Quorum do zapewnienia aktualnych informacji o temperaturze w składowisku poprzez wdrożenie sieci między dwiema stronami — supermarketem a właścicielem składu.

Pokazaliśmy, jak aktualne informacje o temperaturze mogą być utrzymywane zarówno za pomocą transakcji publicznych, jak i prywatnych.

Scenariuszy zastosowania może być bardzo dużo i, jak widać, wcale nie jest to skomplikowane.

Eksperymentuj, spróbuj wdrożyć swój scenariusz. Tym bardziej, że branża technologii blockchain do 2024 roku może urosnąć prawie dziesięciokrotnie..

Źródło: habr.com

Kup solidny hosting stron z ochroną przed DDoS, serwery VPS VDS 🔥 Kup solidny hosting stron z ochroną przed DDoS, serwery VPS VDS | ProHoster