Web3๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ JPMorgan Quorum ๋ธ”๋ก์ฒด์ธ์—์„œ ๊ณต๊ฐœ ๋ฐ ๋น„๊ณต๊ฐœ ํŠธ๋žœ์žญ์…˜์„ ์ˆ˜ํ–‰ํ•ฉ๋‹ˆ๋‹ค.

Web3๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ JPMorgan Quorum ๋ธ”๋ก์ฒด์ธ์—์„œ ๊ณต๊ฐœ ๋ฐ ๋น„๊ณต๊ฐœ ํŠธ๋žœ์žญ์…˜์„ ์ˆ˜ํ–‰ํ•ฉ๋‹ˆ๋‹ค.

์ •์กฑ์ˆ˜ JPMorgan์ด ๊ฐœ๋ฐœํ•œ Ethereum ๊ธฐ๋ฐ˜ ๋ธ”๋ก์ฒด์ธ์ด๋ฉฐ ๊ฐ€์žฅ ์ตœ๊ทผ์—๋Š” Microsoft Azure๊ฐ€ ์ œ๊ณตํ•˜๋Š” ์ตœ์ดˆ์˜ ๋ถ„์‚ฐ ์›์žฅ ํ”Œ๋žซํผ์ด ๋˜์—ˆ์Šต๋‹ˆ๋‹ค.

์ฟผ๋Ÿผ์€ ๊ฐœ์ธ ๋ฐ ๊ณต์šฉ ํŠธ๋žœ์žญ์…˜์„ ์ง€์›ํ•˜๋ฉฐ ๋งŽ์€ ์ƒ์—…์  ์‚ฌ์šฉ ์‚ฌ๋ก€๋ฅผ ๋ณด์œ ํ•˜๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค.

์ด ๊ธฐ์‚ฌ์—์„œ๋Š” ์ฐฝ๊ณ  ์˜จ๋„์— ๋Œ€ํ•œ ์ตœ์‹  ์ •๋ณด๋ฅผ ์ œ๊ณตํ•˜๊ธฐ ์œ„ํ•ด ์Šˆํผ๋งˆ์ผ“๊ณผ ์ฐฝ๊ณ  ์†Œ์œ ์ž ์‚ฌ์ด์— ๋ถ„์‚ฐ ์›์žฅ ๋„คํŠธ์›Œํฌ๋ฅผ ๋ฐฐํฌํ•˜๋Š” ์‹œ๋‚˜๋ฆฌ์˜ค ์ค‘ ํ•˜๋‚˜๋ฅผ ์‚ดํŽด๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค.

์ด ํŠœํ† ๋ฆฌ์–ผ์—์„œ ์‚ฌ์šฉ๋œ ์ฝ”๋“œ๋Š” ๋‹ค์Œ๊ณผ ๊ฐ™์Šต๋‹ˆ๋‹ค. GitHub์˜ ๋ฆฌํฌ์ง€ํ† ๋ฆฌ.

์ด ๊ธฐ์‚ฌ์—์„œ๋Š” ๋‹ค์Œ ๋‚ด์šฉ์„ ๋‹ค๋ฃน๋‹ˆ๋‹ค.

  • ์Šค๋งˆํŠธ ๊ณ„์•ฝ ์ƒ์„ฑ;
  • ๋‹ค์Œ์„ ์‚ฌ์šฉํ•˜์—ฌ Quorum ๋„คํŠธ์›Œํฌ ๋ฐฐํฌ ์ฒด์ธ ์Šคํƒ;
  • ์ฟผ๋Ÿผ ๊ณต๊ฐœ ํŠธ๋žœ์žญ์…˜
  • ์ฟผ๋Ÿผ ๋น„๊ณต๊ฐœ ํŠธ๋žœ์žญ์…˜.

์„ค๋ช…์„ ์œ„ํ•ด IoT(์‚ฌ๋ฌผ ์ธํ„ฐ๋„ท) ๋‚ด Quorum ๋„คํŠธ์›Œํฌ ๊ตฌ์„ฑ์›์˜ ์ฐฝ๊ณ  ์˜จ๋„๋ฅผ ๋ชจ๋‹ˆํ„ฐ๋งํ•˜๋Š” ์‹œ๋‚˜๋ฆฌ์˜ค๋ฅผ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค.

๋ฌธ๋งฅ

์ฐฝ๊ณ  ํšŒ์‚ฌ ๊ทธ๋ฃน์ด ์ปจ์†Œ์‹œ์—„์œผ๋กœ ์—ฐํ•ฉํ•˜์—ฌ ๋ธ”๋ก์ฒด์ธ์— ์ •๋ณด๋ฅผ ๊ณต๋™์œผ๋กœ ์ €์žฅํ•˜๊ณ  ํ”„๋กœ์„ธ์Šค๋ฅผ ์ž๋™ํ™”ํ•˜๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค. ์ด๋ฅผ ์œ„ํ•ด ๊ธฐ์—…์—์„œ๋Š” 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;
  }
}

๊ณ„์•ฝ์ด ์ž‘๋™ํ•˜๋ ค๋ฉด ์›น3.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

์ด์ œ ๊ณ„์•ฝ์ด ์ค€๋น„๋˜์—ˆ์œผ๋ฏ€๋กœ ๋„คํŠธ์›Œํฌ๋ฅผ ๋ฐฐํฌํ•˜๊ณ  ๊ณ„์•ฝ์„ ๋ฐฐํฌํ•˜๊ฒ ์Šต๋‹ˆ๋‹ค.

๋…ธ๋“œ ๋ฐฐํฌ

Web3๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ JPMorgan Quorum ๋ธ”๋ก์ฒด์ธ์—์„œ ๊ณต๊ฐœ ๋ฐ ๋น„๊ณต๊ฐœ ํŠธ๋žœ์žญ์…˜์„ ์ˆ˜ํ–‰ํ•ฉ๋‹ˆ๋‹ค.

๋…ธ๋“œ ๋ฐฐํฌ๋Š” ์ƒ๋‹นํžˆ ๋…ธ๋™ ์ง‘์•ฝ์ ์ผ ์ˆ˜ ์žˆ์œผ๋ฉฐ ์ด ํ”„๋กœ์„ธ์Šค๋Š” ์„œ๋น„์Šค๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ๋Œ€์ฒด๋  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์ฒด์ธ ์Šคํƒ.

๋‹ค์Œ์€ Raft ํ•ฉ์˜์™€ XNUMX๊ฐœ์˜ ๋…ธ๋“œ๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ Quorum ๋„คํŠธ์›Œํฌ๋ฅผ ๋ฐฐํฌํ•˜๋Š” ํ”„๋กœ์„ธ์Šค์ž…๋‹ˆ๋‹ค.

๋จผ์ € ํ”„๋กœ์ ํŠธ๋ฅผ ๋งŒ๋“ค๊ณ  Quorum Project๋ผ๊ณ  ๋ถ€๋ฅด๊ฒ ์Šต๋‹ˆ๋‹ค.

Web3๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ JPMorgan Quorum ๋ธ”๋ก์ฒด์ธ์—์„œ ๊ณต๊ฐœ ๋ฐ ๋น„๊ณต๊ฐœ ํŠธ๋žœ์žญ์…˜์„ ์ˆ˜ํ–‰ํ•ฉ๋‹ˆ๋‹ค.

Google Cloud Platform์—์„œ Raft ํ•ฉ์˜๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ Quorum ๋„คํŠธ์›Œํฌ๋ฅผ ๋งŒ๋“ค์–ด ๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค.

Web3๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ JPMorgan Quorum ๋ธ”๋ก์ฒด์ธ์—์„œ ๊ณต๊ฐœ ๋ฐ ๋น„๊ณต๊ฐœ ํŠธ๋žœ์žญ์…˜์„ ์ˆ˜ํ–‰ํ•ฉ๋‹ˆ๋‹ค.

๊ธฐ๋ณธ์ ์œผ๋กœ ์ด๋ฏธ ์ƒ์„ฑ๋œ ๋…ธ๋“œ์— ๋‘ ๊ฐœ์˜ ๋…ธ๋“œ๋ฅผ ๋” ์ถ”๊ฐ€ํ•ด ๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค.

Web3๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ JPMorgan Quorum ๋ธ”๋ก์ฒด์ธ์—์„œ ๊ณต๊ฐœ ๋ฐ ๋น„๊ณต๊ฐœ ํŠธ๋žœ์žญ์…˜์„ ์ˆ˜ํ–‰ํ•ฉ๋‹ˆ๋‹ค.

์‹คํ–‰ ์ค‘์ธ ๋…ธ๋“œ XNUMX๊ฐœ:

Web3๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ JPMorgan Quorum ๋ธ”๋ก์ฒด์ธ์—์„œ ๊ณต๊ฐœ ๋ฐ ๋น„๊ณต๊ฐœ ํŠธ๋žœ์žญ์…˜์„ ์ˆ˜ํ–‰ํ•ฉ๋‹ˆ๋‹ค.

๋…ธ๋“œ ์„ธ๋ถ€์ •๋ณด ํŽ˜์ด์ง€์—๋Š” RPC ์—”๋“œํฌ์ธํŠธ, ๊ณต๊ฐœ ํ‚ค ๋“ฑ์ด ํ‘œ์‹œ๋ฉ๋‹ˆ๋‹ค.

Web3๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ JPMorgan Quorum ๋ธ”๋ก์ฒด์ธ์—์„œ ๊ณต๊ฐœ ๋ฐ ๋น„๊ณต๊ฐœ ํŠธ๋žœ์žญ์…˜์„ ์ˆ˜ํ–‰ํ•ฉ๋‹ˆ๋‹ค.

๋„คํŠธ์›Œํฌ๊ฐ€ ๋ฐฐํฌ๋˜์—ˆ์Šต๋‹ˆ๋‹ค. ์ด์ œ ์Šค๋งˆํŠธ ๊ณ„์•ฝ์„ ๋ฐฐํฌํ•˜๊ณ  ๋‹ค์Œ์„ ์‚ฌ์šฉํ•˜์—ฌ ํŠธ๋žœ์žญ์…˜์„ ์ˆ˜ํ–‰ํ•ด ๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค. ์›น3.js.

๊ณต๊ฐœ ๊ฑฐ๋ž˜

๋ฌธ๋งฅ

์ฐฝ๊ณ  ์˜จ๋„๋Š” ํŠนํžˆ ์˜ํ•˜์˜ ์˜จ๋„์—์„œ ๋ณด๊ด€ํ•  ์ œํ’ˆ์˜ ๊ฒฝ์šฐ ๋น„์šฉ ์ ˆ๊ฐ์— ๋งค์šฐ ์ค‘์š”ํ•ฉ๋‹ˆ๋‹ค.

๊ธฐ์—…์ด ์ง€๋ฆฌ์  ์œ„์น˜์˜ ์™ธ๋ถ€ ์˜จ๋„๋ฅผ ์‹ค์‹œ๊ฐ„์œผ๋กœ ๊ณต์œ ํ•˜๊ณ  ์ด๋ฅผ ๋ถˆ๋ณ€์˜ ์›์žฅ์— ๊ธฐ๋กํ•  ์ˆ˜ ์žˆ๋„๋ก ํ•จ์œผ๋กœ์จ ๋„คํŠธ์›Œํฌ ์ฐธ์—ฌ์ž๋Š” ๋น„์šฉ๊ณผ ์‹œ๊ฐ„์„ ์ ˆ๊ฐํ•ฉ๋‹ˆ๋‹ค.

Web3๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ JPMorgan Quorum ๋ธ”๋ก์ฒด์ธ์—์„œ ๊ณต๊ฐœ ๋ฐ ๋น„๊ณต๊ฐœ ํŠธ๋žœ์žญ์…˜์„ ์ˆ˜ํ–‰ํ•ฉ๋‹ˆ๋‹ค.

๋‹ค์ด์–ด๊ทธ๋žจ์— ํ‘œ์‹œ๋œ ๋Œ€๋กœ ์„ธ ๊ฐ€์ง€ ์ž‘์—…์„ ์ˆ˜ํ–‰ํ•ฉ๋‹ˆ๋‹ค.

  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 ๋„คํŠธ์›Œํฌ์—์„œ ๊ณต๊ฐœ ํŠธ๋žœ์žญ์…˜์„ ์‹คํ–‰ํ•˜๋Š” ๋ฐฉ๋ฒ•์„ ์‚ดํŽด๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค. ์›น3.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;
  });
}

์›น3.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);
}

์ด์ œ ์‹คํ–‰ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค ๊ณต๊ฐœ.js ๋‹ค์Œ ๊ฒฐ๊ณผ๋ฅผ ์–ป์œผ๋ ค๋ฉด :

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

๋‹ค์Œ์œผ๋กœ ์•„๋ž˜์™€ ๊ฐ™์ด Chainstack ํŒจ๋„์˜ Quorum ํƒ์ƒ‰๊ธฐ์—์„œ ํ•ญ๋ชฉ์„ ๋ณผ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

์„ธ ๋…ธ๋“œ๊ฐ€ ๋ชจ๋‘ ์ƒํ˜ธ ์ž‘์šฉํ•˜๊ณ  ํŠธ๋žœ์žญ์…˜์ด ์—…๋ฐ์ดํŠธ๋˜์—ˆ์Šต๋‹ˆ๋‹ค.

  1. ์ฒซ ๋ฒˆ์งธ ๊ฑฐ๋ž˜๋Š” ๊ณ„์•ฝ์„ ๋ฐฐํฌํ–ˆ์Šต๋‹ˆ๋‹ค.
  2. ๋‘ ๋ฒˆ์งธ ํŠธ๋žœ์žญ์…˜์—์„œ๋Š” ๊ณ„์•ฝ ์˜จ๋„๋ฅผ 3๋„๋กœ ์„ค์ •ํ–ˆ์Šต๋‹ˆ๋‹ค.
  3. ์˜จ๋„๋Š” ๋กœ์ปฌ ๋…ธ๋“œ๋ฅผ ํ†ตํ•ด ์ˆ˜์‹ ๋˜๋ฏ€๋กœ ํŠธ๋žœ์žญ์…˜์ด ์ƒ์„ฑ๋˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค.

Web3๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ JPMorgan Quorum ๋ธ”๋ก์ฒด์ธ์—์„œ ๊ณต๊ฐœ ๋ฐ ๋น„๊ณต๊ฐœ ํŠธ๋žœ์žญ์…˜์„ ์ˆ˜ํ–‰ํ•ฉ๋‹ˆ๋‹ค.

๊ฐœ์ธ ๊ฑฐ๋ž˜

๋ฌธ๋งฅ

์กฐ์ง์˜ ์ผ๋ฐ˜์ ์ธ ์š”๊ตฌ ์‚ฌํ•ญ์€ ๋ฐ์ดํ„ฐ ๋ณดํ˜ธ์ž…๋‹ˆ๋‹ค. ์˜ˆ๋ฅผ ๋“ค์–ด, ๋‹ค์Œ๊ณผ ๊ฐ™์€ ์‹œ๋‚˜๋ฆฌ์˜ค๋ฅผ ์ƒ๊ฐํ•ด ๋ณด์‹ญ์‹œ์˜ค. ์Šˆํผ๋งˆ์ผ“ ํ•ด์‚ฐ๋ฌผ์„ ๋ณด๊ด€ํ•˜๊ธฐ ์œ„ํ•œ ์ฐฝ๊ณ  ๊ณต๊ฐ„์„ ๋ณ„๋„๋กœ ์ž„๋Œ€ํ•ฉ๋‹ˆ๋‹ค. ๊ณต๊ธ‰์—…์ฒด:

  • ๊ณต๊ธ‰์—…์ฒด IoT ์„ผ์„œ๋ฅผ ์ด์šฉํ•ด 30์ดˆ๋งˆ๋‹ค ์˜จ๋„๊ฐ’์„ ์ฝ์–ด ์ „์†กํ•œ๋‹ค. ์Šˆํผ๋งˆ์ผ“์œผ๋กœ;
  • ์ด ๊ฐ’์€ ๋งŒ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์–ด์•ผํ•ฉ๋‹ˆ๋‹ค ํŒ๋งค์ž์—๊ฒŒ ะธ ์Šˆํผ๋งˆ์ผ“์œผ๋กœ, ์ปจ์†Œ์‹œ์—„์œผ๋กœ ๋„คํŠธ์›Œํฌํ™”๋จ.

Web3๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ JPMorgan Quorum ๋ธ”๋ก์ฒด์ธ์—์„œ ๊ณต๊ฐœ ๋ฐ ๋น„๊ณต๊ฐœ ํŠธ๋žœ์žญ์…˜์„ ์ˆ˜ํ–‰ํ•ฉ๋‹ˆ๋‹ค.

์œ„ ๋‹ค์ด์–ด๊ทธ๋žจ์— ํ‘œ์‹œ๋œ ๋„ค ๊ฐ€์ง€ ์ž‘์—…์„ ์™„๋ฃŒํ•˜๊ฒ ์Šต๋‹ˆ๋‹ค.

  • ์ด์ „ ์‹œ๋‚˜๋ฆฌ์˜ค์™€ ๋™์ผํ•œ ์„ธ ๊ฐœ์˜ ๋…ธ๋“œ๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ๊ฐœ์ธ ํŠธ๋žœ์žญ์…˜์„ ๋ณด์—ฌ์ค๋‹ˆ๋‹ค.
  • ์Šˆํผ๋งˆ์ผ“ ๋น„๊ณต๊ฐœ ์Šค๋งˆํŠธ ๊ณ„์•ฝ์„ ๋ฐฐํฌํ•ฉ๋‹ˆ๋‹ค. ์Šˆํผ๋งˆ์ผ“ ะธ ๊ณต๊ธ‰์—…์ฒด.
  • ์„ธ ๋ฒˆ์งธ ์ธก๋ฉด ์Šค๋งˆํŠธ ๊ณ„์•ฝ์— ์ ‘๊ทผํ•  ์ˆ˜ ์žˆ๋Š” ๊ถŒํ•œ์ด ์—†์Šต๋‹ˆ๋‹ค.

์šฐ๋ฆฌ๋Š” ๋ฉ”์†Œ๋“œ๋ฅผ ํ˜ธ์ถœํ•  ๊ฒƒ์ž…๋‹ˆ๋‹ค get ะธ set ๋Œ€์‹ ์— ์Šˆํผ๋งˆ์ผ“ ะธ ๊ณต๊ธ‰์—…์ฒด ๋น„๊ณต๊ฐœ ์ฟผ๋Ÿผ ํŠธ๋žœ์žญ์…˜์„ ๋ณด์—ฌ์ค๋‹ˆ๋‹ค.

  1. ์ฐธ๊ฐ€์ž๋ฅผ ์œ„ํ•œ ๋น„๊ณต๊ฐœ ๊ณ„์•ฝ์„ ๋ฐฐํฌํ•ฉ๋‹ˆ๋‹ค. ์Šˆํผ๋งˆ์ผ“ ะธ ๊ณต๊ธ‰์—…์ฒด ์ฐธ๊ฐ€์ž๋ฅผ ํ†ตํ•ด ์Šˆํผ๋งˆ์ผ“:

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

  2. ์˜จ๋„๋ถ€ํ„ฐ ์„ค์ •ํ•˜์ž ์ œXNUMX์ž (์™ธ๋ถ€ ๋…ธ๋“œ) ์˜จ๋„ ๊ฐ’์„ ์–ป์Šต๋‹ˆ๋‹ค.

    // 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. ์šฐ๋ฆฌ๋Š” ์˜จ๋„๋ฅผ ์–ป์Šต๋‹ˆ๋‹ค. ์ œXNUMX์ž (์™ธ๋ถ€ ๋…ธ๋“œ):

    3๋‹จ๊ณ„์—์„œ๋Š” ์˜จ๋„๋ฅผ 12๋„๋กœ ์„ค์ •ํ–ˆ์ง€๋งŒ ์„ธ ๋ฒˆ์งธ ์ธก๋ฉด ์Šค๋งˆํŠธ ๊ณ„์•ฝ์— ์ ‘๊ทผํ•  ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค. ๋”ฐ๋ผ์„œ ๋ฐ˜ํ™˜ ๊ฐ’์€ null์ด์–ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

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

    ๋‹ค์Œ์œผ๋กœ Quorum ๋„คํŠธ์›Œํฌ์—์„œ ๊ฐœ์ธ ํŠธ๋žœ์žญ์…˜์„ ์ˆ˜ํ–‰ํ•˜๋Š” ๋ฐฉ๋ฒ•์„ ์ž์„ธํžˆ ์‚ดํŽด๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค. ์›น3.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

Chainstack์˜ Quorum ํƒ์ƒ‰๊ธฐ์—๋Š” ๋‹ค์Œ์ด ํ‘œ์‹œ๋ฉ๋‹ˆ๋‹ค.

  • ์ฐธ๊ฐ€์ž์˜ ๊ณ„์•ฝ ๋ฐฐํฌ ์Šˆํผ๋งˆ์ผ“;
  • ์‹คํ–‰ SetTemperature ๋ถ€ํ„ฐ ์ œXNUMX์ž;
  • ์‹คํ–‰ SetTemperature ์ฐธ๊ฐ€์ž๋กœ๋ถ€ํ„ฐ ๊ณต๊ธ‰์—…์ฒด.

Web3๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ JPMorgan Quorum ๋ธ”๋ก์ฒด์ธ์—์„œ ๊ณต๊ฐœ ๋ฐ ๋น„๊ณต๊ฐœ ํŠธ๋žœ์žญ์…˜์„ ์ˆ˜ํ–‰ํ•ฉ๋‹ˆ๋‹ค.

๋ณด์‹œ๋‹ค์‹œํ”ผ ๋‘ ํŠธ๋žœ์žญ์…˜ ๋ชจ๋‘ ์™„๋ฃŒ๋˜์—ˆ์ง€๋งŒ ์ฐธ๊ฐ€์ž์˜ ํŠธ๋žœ์žญ์…˜๋งŒ ์™„๋ฃŒ๋˜์—ˆ์Šต๋‹ˆ๋‹ค. ๊ณต๊ธ‰์—…์ฒด ๊ณ„์•ฝ์„œ์˜ ์˜จ๋„๋ฅผ ์—…๋ฐ์ดํŠธํ–ˆ์Šต๋‹ˆ๋‹ค. ๋”ฐ๋ผ์„œ ๊ฐœ์ธ ๊ฑฐ๋ž˜๋Š” ๋ถˆ๋ณ€์„ฑ์„ ์ œ๊ณตํ•˜์ง€๋งŒ ๋™์‹œ์— ์ œXNUMX์ž์—๊ฒŒ ๋ฐ์ดํ„ฐ๋ฅผ ๊ณต๊ฐœํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค.

๊ฒฐ๋ก 

์šฐ๋ฆฌ๋Š” ์Šˆํผ๋งˆ์ผ“๊ณผ ์ฐฝ๊ณ  ์†Œ์œ ์ž๋ผ๋Š” ๋‘ ๋‹น์‚ฌ์ž ์‚ฌ์ด์— ๋„คํŠธ์›Œํฌ๋ฅผ ๋ฐฐํฌํ•˜์—ฌ ์ฐฝ๊ณ ์— ์ตœ์‹  ์˜จ๋„ ์ •๋ณด๋ฅผ ์ œ๊ณตํ•˜๋Š” Quorum์˜ ์ƒ์—…์  ์‚ฌ์šฉ ์‚ฌ๋ก€๋ฅผ ์‚ดํŽด๋ณด์•˜์Šต๋‹ˆ๋‹ค.

์šฐ๋ฆฌ๋Š” ๊ณต๊ฐœ ๋ฐ ๋น„๊ณต๊ฐœ ๊ฑฐ๋ž˜๋ฅผ ํ†ตํ•ด ์–ด๋–ป๊ฒŒ ์ตœ์‹  ์˜จ๋„ ์ •๋ณด๋ฅผ ์œ ์ง€ํ•  ์ˆ˜ ์žˆ๋Š”์ง€ ๋ณด์—ฌ์ฃผ์—ˆ์Šต๋‹ˆ๋‹ค.

๋งŽ์€ ์‘์šฉ ์‹œ๋‚˜๋ฆฌ์˜ค๊ฐ€ ์žˆ์„ ์ˆ˜ ์žˆ์œผ๋ฉฐ ๋ณด์‹œ๋‹ค์‹œํ”ผ ์ „ํ˜€ ์–ด๋ ต์ง€ ์•Š์Šต๋‹ˆ๋‹ค.

์‹คํ—˜ํ•˜๊ณ  ์Šคํฌ๋ฆฝํŠธ๋ฅผ ํ™•์žฅํ•ด ๋ณด์„ธ์š”. ๋˜ํ•œ, ๋ธ”๋ก์ฒด์ธ ๊ธฐ์ˆ  ์‚ฐ์—…์€ 2024๋…„๊นŒ์ง€ ๊ฑฐ์˜ XNUMX๋ฐฐ ์„ฑ์žฅํ•  ์ˆ˜ ์žˆ๋‹ค.

์ถœ์ฒ˜ : habr.com

์ฝ”๋ฉ˜ํŠธ๋ฅผ ์ถ”๊ฐ€