Web3 рдХреЗ рдЙрдкрдпреЛрдЧ рд╕реЗ JPMorgan Quorum blockchain рдкрд░ рд╕рд╛рд░реНрд╡рдЬрдирд┐рдХ рдФрд░ рдирд┐рдЬреА рд▓реЗрдирджреЗрди рдХрд░рдирд╛



рдХреЛрд░рдо рдЬреЗрдкреА рдореЙрд░реНрдЧрди рджреНрд╡рд╛рд░рд╛ рд╡рд┐рдХрд╕рд┐рдд рдПрдХ Ethereum рдЖрдзрд╛рд░рд┐рдд рдмреНрд▓реЙрдХрдЪреЗрди рд╣реИ рдФрд░ рд╣рд╛рд▓ рд╣реА рдореЗрдВ Microsoft Azure рджреНрд╡рд╛рд░рд╛ рдкреНрд░рджрд╛рди рдХрд┐рдпрд╛ рдЧрдпрд╛ рдкрд╣рд▓рд╛ рд╡рд┐рддрд░рд┐рдд рд░рдЬрд┐рд╕реНрдЯреНрд░реА рдордВрдЪ рдмрди рдЧрдпрд╛ рд╣реИред


рдХреЛрд░рдо рдирд┐рдЬреА рдФрд░ рд╕рд╛рд░реНрд╡рдЬрдирд┐рдХ рд▓реЗрдирджреЗрди рдХрд╛ рд╕рдорд░реНрдерди рдХрд░рддрд╛ рд╣реИ рдФрд░ рдЗрд╕рдореЗрдВ рдХрдИ рд╡реНрдпрд╛рд╡рд╕рд╛рдпрд┐рдХ рдЙрдкрдпреЛрдЧ рдХреЗ рдорд╛рдорд▓реЗ рд╣реИрдВред


рдЗрд╕ рд▓реЗрдЦ рдореЗрдВ, рд╣рдо рдЗрди рдкрд░рд┐рджреГрд╢реНрдпреЛрдВ рдореЗрдВ рд╕реЗ рдПрдХ рдХрд╛ рд╡рд┐рд╢реНрд▓реЗрд╖рдг рдХрд░реЗрдВрдЧреЗ - рдПрдХ рдЧреЛрджрд╛рдо рдХреЗ рддрд╛рдкрдорд╛рди рдХреЗ рдмрд╛рд░реЗ рдореЗрдВ рдкреНрд░рд╛рд╕рдВрдЧрд┐рдХ рдЬрд╛рдирдХрд╛рд░реА рдкреНрд░рджрд╛рди рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдПрдХ рд╕реБрдкрд░рдорд╛рд░реНрдХреЗрдЯ рдФрд░ рдПрдХ рдЧреЛрджрд╛рдо рдХреЗ рдорд╛рд▓рд┐рдХ рдХреЗ рдмреАрдЪ рд╡рд┐рддрд░рд┐рдд рд░рдЬрд┐рд╕реНрдЯреНрд░реА рдиреЗрдЯрд╡рд░реНрдХ рдХреА рддреИрдирд╛рддреАред


рдЗрд╕ рдЧрд╛рдЗрдб рдореЗрдВ рдкреНрд░рдпреБрдХреНрдд рдХреЛрдб GitHub рдХреЗ рднрдВрдбрд╛рд░ рдореЗрдВ рдирд┐рд╣рд┐рдд рд╣реИ ред


рд▓реЗрдЦ рдореЗрдВ рд╢рд╛рдорд┐рд▓ рд╣реИрдВ:


  • рдПрдХ рд╕реНрдорд╛рд░реНрдЯ рдЕрдиреБрдмрдВрдз рдмрдирд╛рдирд╛;
  • рдЪреЙрдВрд╕реНрдЯреИрдХ рдХреЗ рд╕рд╛рде рдХреЛрд░рдо рдиреЗрдЯрд╡рд░реНрдХ рдХреА рддреИрдирд╛рддреА
  • рдХреЛрд░рдо рд╕рд╛рд░реНрд╡рдЬрдирд┐рдХ рд▓реЗрдирджреЗрди
  • рдХреЛрд░рдо рдирд┐рдЬреА рд▓реЗрдирджреЗрдиред

рдЗрд╕реЗ рд╕реНрдкрд╖реНрдЯ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП, рд╣рдо рдЗрдВрдЯрд░рдиреЗрдЯ рдСрдл рдерд┐рдВрдЧреНрд╕ (IoT) рдХреЗ рднрд╛рдЧ рдХреЗ рд░реВрдк рдореЗрдВ рдХреЛрд░рдо рдиреЗрдЯрд╡рд░реНрдХ рдкреНрд░рддрд┐рднрд╛рдЧрд┐рдпреЛрдВ рдХреЗ рднрдВрдбрд╛рд░рдг рдХрдХреНрд╖реЛрдВ рдореЗрдВ рддрд╛рдкрдорд╛рди рдХреА рдирд┐рдЧрд░рд╛рдиреА рдХреЗ рдкрд░рд┐рджреГрд╢реНрдп рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рддреЗ рд╣реИрдВред


рдкреНрд░рд╕рдВрдЧ


рдмреНрд▓реЙрдХрдЪреЗрди рдкрд░ рд╕реВрдЪрдирд╛рдУрдВ рдХреЗ рд╕рдВрдпреБрдХреНрдд рднрдВрдбрд╛рд░рдг рдФрд░ рдкреНрд░рдХреНрд░рд┐рдпрд╛рдУрдВ рдХреЗ рд╕реНрд╡рдЪрд╛рд▓рди рдХреЗ рд▓рд┐рдП рдПрдХ рд╕рдВрдЧреЛрд╖реНрдареА рдореЗрдВ рдЧреЛрджрд╛рдо рдХрдВрдкрдирд┐рдпреЛрдВ рдХрд╛ рдПрдХ рд╕рдореВрд╣ рдПрдХрдЬреБрдЯ рд╣реЛрддрд╛ рд╣реИред рдЗрд╕рдХреЗ рд▓рд┐рдП рдХрдВрдкрдирд┐рдпреЛрдВ рдиреЗ рдХреЛрд░рдо рдХрд╛ рдЗрд╕реНрддреЗрдорд╛рд▓ рдХрд░рдиреЗ рдХрд╛ рдлреИрд╕рд▓рд╛ рдХрд┐рдпрд╛ред рдЗрд╕ рд▓реЗрдЦ рдореЗрдВ, рд╣рдо рджреЛ рдкрд░рд┐рджреГрд╢реНрдпреЛрдВ рдХреЛ рдХрд╡рд░ рдХрд░реЗрдВрдЧреЗ: рд╕рд╛рд░реНрд╡рдЬрдирд┐рдХ рд▓реЗрдирджреЗрди рдФрд░ рдирд┐рдЬреА рд▓реЗрдирджреЗрдиред


рд▓реЗрди-рджреЗрди рдЕрд▓рдЧ-рдЕрд▓рдЧ рдкреНрд░рддрд┐рднрд╛рдЧрд┐рдпреЛрдВ рджреНрд╡рд╛рд░рд╛ рдмрдирд╛рдП рдЧрдП рдХрдВрд╕реЛрд░реНрдЯрд┐рдпрдо рдХреЗ рд╕рд╛рде рдмрд╛рддрдЪреАрдд рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИ рдЬрд┐рд╕рд╕реЗ рд╡реЗ рд╕рдВрдмрдВрдзрд┐рдд рд╣реИрдВред рдкреНрд░рддреНрдпреЗрдХ рд▓реЗрдирджреЗрди рдпрд╛ рддреЛ рдПрдХ рдЕрдиреБрдмрдВрдз рдХреЛ рддреИрдирд╛рдд рдХрд░рддрд╛ рд╣реИ рдпрд╛ рдиреЗрдЯрд╡рд░реНрдХ рдХреЛ рдбреЗрдЯрд╛ рдЕрдкрд▓реЛрдб рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдПрдХ рдЕрдиреБрдмрдВрдз рдореЗрдВ рдПрдХ рдлрд╝рдВрдХреНрд╢рди рдХреЛ рдХреЙрд▓ рдХрд░рддрд╛ рд╣реИред рдЗрди рдХрд╛рд░реНрдпреЛрдВ рдХреЛ рдиреЗрдЯрд╡рд░реНрдХ рдХреЗ рд╕рднреА рдиреЛрдбреНрд╕ рдореЗрдВ рджреЛрд╣рд░рд╛рдпрд╛ рдЬрд╛рддрд╛ рд╣реИред


рд╕рд╛рд░реНрд╡рдЬрдирд┐рдХ рд▓реЗрдирджреЗрди рдХрдВрд╕реЛрд░реНрдЯрд┐рдпрдо рдХреЗ рд╕рднреА рд╕рджрд╕реНрдпреЛрдВ рджреНрд╡рд╛рд░рд╛ рджреЗрдЦрдиреЗ рдХреЗ рд▓рд┐рдП рдЙрдкрд▓рдмреНрдз рд╣реИрдВред рдирд┐рдЬреА рд▓реЗрдирджреЗрди рдЧреЛрдкрдиреАрдпрддрд╛ рдХреА рдПрдХ рдкрд░рдд рдЬреЛрдбрд╝рддреЗ рд╣реИрдВ рдФрд░ рдХреЗрд╡рд▓ рдЙрди рдкреНрд░рддрд┐рднрд╛рдЧрд┐рдпреЛрдВ рдХреЗ рд▓рд┐рдП рдЙрдкрд▓рдмреНрдз рд╣реИрдВ рдЬрд┐рдирдХреЗ рдкрд╛рд╕ рдЗрд╕рдХреЗ рдЕрдзрд┐рдХрд╛рд░ рд╣реИрдВред


рджреЛрдиреЛрдВ рдкрд░рд┐рджреГрд╢реНрдпреЛрдВ рдХреЗ рд▓рд┐рдП, рд╣рдо рд╕реНрдкрд╖реНрдЯрддрд╛ рдХреЗ рд▓рд┐рдП рдПрдХ рд╣реА рдЕрдиреБрдмрдВрдз рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рддреЗ рд╣реИрдВред


рд╕реНрдорд╛рд░реНрдЯ рдЕрдиреБрдмрдВрдз


рдиреАрдЪреЗ рд╣рдорд╛рд░реЗ рдкрд░рд┐рджреГрд╢реНрдп рдХреЗ рд▓рд┐рдП рдмрдирд╛рдпрд╛ рдЧрдпрд╛ рдПрдХ рд╕рд░рд▓ рд╕реНрдорд╛рд░реНрдЯ рдЕрдиреБрдмрдВрдз рд╣реИред рдЗрд╕рдореЗрдВ рдПрдХ рд╕рд╛рд░реНрд╡рдЬрдирд┐рдХ рдЪрд░ 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 рдХреЗ рд╕рд╛рде рдХрд╛рдо рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП, рдЗрд╕реЗ рдПрдмреАрдЖрдИ рдкреНрд░рд╛рд░реВрдк рдФрд░ рдмрд╛рдИрдЯреЗрдХреЛрдб рдореЗрдВ рдкрд░рд┐рд╡рд░реНрддрд┐рдд рдХрд┐рдпрд╛ рдЬрд╛рдирд╛ рдЪрд╛рд╣рд┐рдПред рдиреАрдЪреЗ formatContract рдлрд╝рдВрдХреНрд╢рди рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдХреЗ рд╕реЙрд▓-рдЬреЗрдПрд╕ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдХреЗ рдЕрдиреБрдмрдВрдз рдХреЛ рд╕рдВрдХрд▓рд┐рдд рдХрд░рддрд╛ рд╣реИред


 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 

рдЕрдм рдЬрдм рдЕрдиреБрдмрдВрдз рддреИрдпрд╛рд░ рд╣реИ, рддреЛ рд╣рдо рдиреЗрдЯрд╡рд░реНрдХ рдХреЛ рддреИрдирд╛рдд рдХрд░реЗрдВрдЧреЗ рдФрд░ рдЕрдиреБрдмрдВрдз рдХреЛ рддреИрдирд╛рдд рдХрд░реЗрдВрдЧреЗред


рдиреЛрдб рддреИрдирд╛рддреА


рдЫрд╡рд┐


рдПрдХ рдиреЛрдб рдХреА рддреИрдирд╛рддреА рдХрд╛рдлреА рд╕рдордп рд▓реЗрдиреЗ рд╡рд╛рд▓реА рд╣реЛ рд╕рдХрддреА рд╣реИ рдФрд░ рдЗрд╕ рдкреНрд░рдХреНрд░рд┐рдпрд╛ рдХреЛ рдЪреИрдВрд╕реНрдЯреИрдХ рд╕реЗрд╡рд╛ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдХреЗ рдмрджрд▓рд╛ рдЬрд╛ рд╕рдХрддрд╛ рд╣реИред


рдирд┐рдореНрдирд▓рд┐рдЦрд┐рдд рдПрдХ рд░рд╛рдЙрд░ рд╕рд░реНрд╡рд╕рдореНрдорддрд┐ рдФрд░ рддреАрди рдиреЛрдбреНрд╕ рдХреЗ рд╕рд╛рде рдПрдХ рдХреЛрд░рдо рдиреЗрдЯрд╡рд░реНрдХ рдкрд░рд┐рдирд┐рдпреЛрдЬрди рдкреНрд░рдХреНрд░рд┐рдпрд╛ рд╣реИред


рдЖрд░рдВрдн рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП, рдПрдХ рдкрд░рд┐рдпреЛрдЬрдирд╛ рд╢реБрд░реВ рдХрд░рддреЗ рд╣реИрдВ рдФрд░ рдЗрд╕реЗ рдХреЛрд░рдо рдкрд░рд┐рдпреЛрдЬрдирд╛ рдХрд╣рддреЗ рд╣реИрдВ:


рдЫрд╡рд┐


Google рдХреНрд▓рд╛рдЙрдб рдкреНрд▓реЗрдЯрдлрд╝реЙрд░реНрдо рдкрд░ рд░рдЬрд╝рд╛рдо рд╕рд░реНрд╡рд╕рдореНрдорддрд┐ рдХреЗ рд╕рд╛рде рдПрдХ рдХреЛрд░рдо рдиреЗрдЯрд╡рд░реНрдХ рдмрдирд╛рдПрдБ:


рдЫрд╡рд┐


рдкрд╣рд▓реЗ рд╕реЗ рдирд┐рд░реНрдорд┐рдд рдбрд┐рдлрд╝реЙрд▓реНрдЯ рдиреЛрдб рдореЗрдВ, рджреЛ рдФрд░ рдиреЛрдб рдЬреЛрдбрд╝реЗрдВ:


рдЫрд╡рд┐


рддреАрди рдЪрд▓рдиреЗ рд╡рд╛рд▓реЗ рдиреЛрдб:


рдЫрд╡рд┐


рдиреЛрдб рд╡рд┐рд╡рд░рдг рдкреГрд╖реНрда RPC рд╕рдорд╛рдкрди рдмрд┐рдВрджреБ, рд╕рд╛рд░реНрд╡рдЬрдирд┐рдХ рдХреБрдВрдЬреА рдЖрджрд┐ рджрд┐рдЦрд╛рддрд╛ рд╣реИред


рдЫрд╡рд┐


рдиреЗрдЯрд╡рд░реНрдХ рддреИрдирд╛рдд рд╣реИред рдЕрдм рд╣рдо web3.js. рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдХреЗ рд╕реНрдорд╛рд░реНрдЯ рдХреЙрдиреНрдЯреНрд░реИрдХреНрдЯ рдХреЛ рддреИрдирд╛рдд рдХрд░рдиреЗ рдФрд░ рд▓реЗрдирджреЗрди рдХреЛ рдирд┐рд╖реНрдкрд╛рджрд┐рдд рдХрд░рдиреЗ рдЬрд╛ рд░рд╣реЗ рд╣реИрдВред


рд╕рд╛рд░реНрд╡рдЬрдирд┐рдХ рд▓реЗрдирджреЗрди


рдкреНрд░рд╕рдВрдЧ


рд▓рд╛рдЧрдд рдХреЛ рдХрдо рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдЧреЛрджрд╛рдо рдХреЗ рддрд╛рдкрдорд╛рди рдХрд╛ рдмрд╣реБрдд рдорд╣рддреНрд╡ рд╣реИ, рдЦрд╛рд╕рдХрд░ рдЙрдк-рд╢реВрдиреНрдп рддрд╛рдкрдорд╛рди рдкрд░ рднрдВрдбрд╛рд░рдг рдХреЗ рд▓рд┐рдП рдЗрдЪреНрдЫрд┐рдд рдЙрддреНрдкрд╛рджреЛрдВ рдХреЗ рд▓рд┐рдПред


рдХрдВрдкрдирд┐рдпреЛрдВ рдХреЛ рдЙрдирдХреЗ рднреМрдЧреЛрд▓рд┐рдХ рд╕реНрдерд╛рди рдХреЗ рдмрд╛рд╣рд░реА рддрд╛рдкрдорд╛рди рдХреЗ рд╡рд╛рд╕реНрддрд╡рд┐рдХ рд╕рдордп рдХреЗ рдореВрд▓реНрдпреЛрдВ рдХреЛ рд╕рд╛рдЭрд╛ рдХрд░рдиреЗ рдФрд░ рдПрдХ рдЕрдкрд░рд┐рд╡рд░реНрддрдиреАрдп рд░рдЬрд┐рд╕реНрдЯреНрд░реА рдореЗрдВ рд░рд┐рдХреЙрд░реНрдб рдХрд░рдиреЗ рдХреА рдХреНрд╖рдорддрд╛ рджреЗрдХрд░, рдиреЗрдЯрд╡рд░реНрдХ рд╕рджрд╕реНрдп рд▓рд╛рдЧрдд рдФрд░ рд╕рдордп рдХреЛ рдХрдо рдХрд░рддреЗ рд╣реИрдВред


рдЫрд╡рд┐


рд╣рдо рдЪрд┐рддреНрд░ рдореЗрдВ рджрд┐рдП рдЧрдП рддреАрди рдХрд╛рд░реНрдпреЛрдВ рдХреЛ рдкреВрд░рд╛ рдХрд░реЗрдВрдЧреЗ:


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

    рдЕрдЧрд▓рд╛, рд╣рдо рд╡реЗрдм 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; }); } 

web3.js рдПрдХ рдЕрдиреБрдмрдВрдз рдХреЗ рд╕рд╛рде рдмрд╛рддрдЪреАрдд рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рджреЛ рддрд░реАрдХреЗ рдкреНрд░рджрд╛рди рдХрд░рддрд╛ рд╣реИ: call рдФрд░ send ред


рд╡реЗрдм 3 send рд╡рд┐рдзрд┐ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдХреЗ set рдХреЛ рдирд┐рд╖реНрдкрд╛рджрд┐рдд рдХрд░рдХреЗ рдЕрдиреБрдмрдВрдз рдХреЗ рддрд╛рдкрдорд╛рди рдХреЛ рдЕрдкрдбреЗрдЯ рдХрд░реЗрдВред


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

рдЕрдЧрд▓рд╛, рд╣рдо рдЕрдиреБрдмрдВрдз рдХрд╛ рддрд╛рдкрдорд╛рди рдкреНрд░рд╛рдкреНрдд рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рд╡реЗрдм 3 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 

рдЗрд╕рдХреЗ рдмрд╛рдж, рд╣рдо рдиреАрдЪреЗ рджрд┐рдЦрд╛рдП рдЧрдП рдЕрдиреБрд╕рд╛рд░, рдЪреИрдирд╕реНрдЯреИрдХ рдкреИрдирд▓ рдореЗрдВ рдХреЛрд░рдо рдЦреЛрдЬрдХрд░реНрддрд╛ рдореЗрдВ рдкреНрд░рд╡рд┐рд╖реНрдЯрд┐рдпрд╛рдБ рджреЗрдЦ рд╕рдХрддреЗ рд╣реИрдВред


рд╕рднреА рддреАрди рдиреЛрдбреНрд╕ рдиреЗ рдмрд╛рддрдЪреАрдд рдХреА рдФрд░ рд▓реЗрдирджреЗрди рдЕрдкрдбреЗрдЯ рдХрд┐рдпрд╛ рдЧрдпрд╛:


  1. рдкрд╣рд▓реЗ рд▓реЗрдирджреЗрди рдиреЗ рдПрдХ рдЕрдиреБрдмрдВрдз рд╣рд╛рд╕рд┐рд▓ рдХрд┐рдпрд╛ рд╣реИред
  2. рджреВрд╕рд░реЗ рд▓реЗрдирджреЗрди рдиреЗ рдЕрдиреБрдмрдВрдз рдХрд╛ рддрд╛рдкрдорд╛рди 3 рдбрд┐рдЧреНрд░реА рдкрд░ рд╕реЗрдЯ рдХрд┐рдпрд╛ред
  3. рддрд╛рдкрдорд╛рди рд╕реНрдерд╛рдиреАрдп рдиреЛрдб рдХреЗ рдорд╛рдзреНрдпрдо рд╕реЗ рдкреНрд░рд╛рдкреНрдд рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИ, рдЗрд╕рд▓рд┐рдП рд▓реЗрдирджреЗрди рдирд╣реАрдВ рдмрдирд╛рдпрд╛ рдЧрдпрд╛ рд╣реИред

рдЫрд╡рд┐


рдирд┐рдЬреА рд▓реЗрди-рджреЗрди


рдкреНрд░рд╕рдВрдЧ


рд╕рдВрдЧрдардиреЛрдВ рдХреА рдПрдХ рд╕рд╛рдорд╛рдиреНрдп рдЖрд╡рд╢реНрдпрдХрддрд╛ рдбреЗрдЯрд╛ рд╕реБрд░рдХреНрд╖рд╛ рд╣реИред рдПрдХ рдЙрджрд╛рд╣рд░рдг рдХреЗ рд░реВрдк рдореЗрдВ, рдПрдХ рдкрд░рд┐рджреГрд╢реНрдп рдкрд░ рд╡рд┐рдЪрд╛рд░ рдХрд░реЗрдВ рдЬрд┐рд╕рдореЗрдВ рдПрдХ рд╕реБрдкрд░рдорд╛рд░реНрдХреЗрдЯ рдПрдХ рдЕрд▓рдЧ рд╡рд┐рдХреНрд░реЗрддрд╛ рд╕реЗ рд╕рдореБрджреНрд░реА рднреЛрдЬрди рднрдВрдбрд╛рд░рдг рдХреЗ рд▓рд┐рдП рдПрдХ рдЧреЛрджрд╛рдо рдХрд┐рд░рд╛рдП рдкрд░ рд▓реЗрддрд╛ рд╣реИ:


  • IoT рд╕реЗрдВрд╕рд░ рдХреА рдорджрдж рд╕реЗ рд╡рд┐рдХреНрд░реЗрддрд╛ рд╣рд░ 30 рд╕реЗрдХрдВрдб рдореЗрдВ рддрд╛рдкрдорд╛рди рдорд╛рди рдкрдврд╝рддрд╛ рд╣реИ рдФрд░ рдЙрдиреНрд╣реЗрдВ рд╕реБрдкрд░рдорд╛рд░реНрдХреЗрдЯ рдореЗрдВ рднреЗрдЬрддрд╛ рд╣реИ ;
  • рдпреЗ рдорд╛рди рдХреЗрд╡рд▓ рд╡реЗрдВрдбрд░ рдФрд░ рд╕реБрдкрд░рдорд╛рд░реНрдХреЗрдЯ рдХреЗ рд▓рд┐рдП рдЙрдкрд▓рдмреНрдз рд╣реЛрдиреЗ рдЪрд╛рд╣рд┐рдП, рдЬреЛ рдПрдХ рдХрдВрд╕реЛрд░реНрдЯрд┐рдпрдо рдиреЗрдЯрд╡рд░реНрдХ рд╣реИред

рдЫрд╡рд┐


рд╣рдо рдКрдкрд░ рдЪрд┐рддреНрд░ рдореЗрдВ рд╡рд░реНрдгрд┐рдд рдЪрд╛рд░ рдХрд╛рд░реНрдпреЛрдВ рдХреЛ рдкреВрд░рд╛ рдХрд░реЗрдВрдЧреЗред


  • рд╣рдо рдирд┐рдЬреА рд▓реЗрдирджреЗрди рдкреНрд░рджрд░реНрд╢рд┐рдд рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдкрд┐рдЫрд▓реЗ рдкрд░рд┐рджреГрд╢реНрдп рд╕реЗ рд╕рдорд╛рди рддреАрди рдиреЛрдбреНрд╕ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рддреЗ рд╣реИрдВ:
  • рд╕реБрдкрд░рдорд╛рд░реНрдХреЗрдЯ рдПрдХ рд╕реНрдорд╛рд░реНрдЯ рдЕрдиреБрдмрдВрдз рддреИрдирд╛рдд рдХрд░ рд░рд╣рд╛ рд╣реИ рдЬреЛ рд╕реБрдкрд░рдорд╛рд░реНрдХреЗрдЯ рдФрд░ рд╡рд┐рдХреНрд░реЗрддрд╛ рдХреЗ рд▓рд┐рдП рдирд┐рдЬреА рд╣реИред
  • рдПрдХ рддреАрд╕рд░реЗ рдкрдХреНрд╖ рдХреЗ рдкрд╛рд╕ рд╕реНрдорд╛рд░реНрдЯ рдЕрдиреБрдмрдВрдз рддрдХ рдкрд╣реБрдВрдЪ рдирд╣реАрдВ рд╣реИред

рд╣рдо рдирд┐рдЬреА рдХреНрд╡реЛрд░рдо рд▓реЗрдирджреЗрди рдХреЛ рдкреНрд░рджрд░реНрд╢рд┐рдд рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рд╕реБрдкрд░рдорд╛рд░реНрдХреЗрдЯ рдФрд░ рд╡реЗрдВрдбрд░ рдХреА рдУрд░ рд╕реЗ get рдФрд░ set рддрд░реАрдХреЛрдВ рдХреЛ рдХреЙрд▓ рдХрд░реЗрдВрдЧреЗред


  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 рдкрд░ рд╕реЗрдЯ рдХрд┐рдпрд╛ рдЧрдпрд╛ рдерд╛, рд▓реЗрдХрд┐рди рддреАрд╕рд░реЗ рдкрдХреНрд╖ рдХреЗ рдкрд╛рд╕ рд╕реНрдорд╛рд░реНрдЯ рдЕрдиреБрдмрдВрдз рддрдХ рдкрд╣реБрдВрдЪ рдирд╣реАрдВ рд╣реИред рдЗрд╕рд▓рд┐рдП, рд╡рд╛рдкрд╕реА рдорд╛рди рд╢реВрдиреНрдп рд╣реЛрдирд╛ рдЪрд╛рд╣рд┐рдПред


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

    рдЕрдЧрд▓рд╛, рд╣рдо рдФрд░ рдЕрдзрд┐рдХ рд╡рд┐рд╕реНрддрд╛рд░ рд╕реЗ рд╡реЗрдм 3 рдХреЗ рд╕рд╛рде рдХреЛрд░рдо рдиреЗрдЯрд╡рд░реНрдХ рдкрд░ рдирд┐рдЬреА рд▓реЗрдирджреЗрди рдХреЗ рдирд┐рд╖реНрдкрд╛рджрди рдкрд░ рд╡рд┐рдЪрд╛рд░ рдХрд░реЗрдВрдЧреЗред рдЪреВрдВрдХрд┐ рдЕрдзрд┐рдХрд╛рдВрд╢ рдХреЛрдб рд╕рд╛рд░реНрд╡рдЬрдирд┐рдХ рд▓реЗрдирджреЗрди рдХреЗ рд╕рд╛рде рдореЗрд▓ рдЦрд╛рддреЗ рд╣реИрдВ, рд╣рдо рдХреЗрд╡рд▓ рдЙрди рд╣рд┐рд╕реНрд╕реЛрдВ рдХрд╛ рдЪрдпрди рдХрд░рддреЗ рд╣реИрдВ рдЬреЛ рдирд┐рдЬреА рд▓реЗрдирджреЗрди рдХреЗ рд▓рд┐рдП рдЕрд▓рдЧ рд╣реИрдВред



рдХреГрдкрдпрд╛ рдзреНрдпрд╛рди рджреЗрдВ рдХрд┐ рдиреЗрдЯрд╡рд░реНрдХ рдкрд░ рдЕрдкрд▓реЛрдб рдХрд┐рдпрд╛ рдЧрдпрд╛ рдЕрдиреБрдмрдВрдз рдЕрдкрд░рд┐рд╡рд░реНрддрдиреАрдп рд╣реИ, рдЗрд╕рд▓рд┐рдП рдЕрдиреБрдмрдВрдз рдХреА рддреИрдирд╛рддреА рдХреЗ рд╕рдордп рд╕рд╛рд░реНрд╡рдЬрдирд┐рдХ рдЕрдиреБрдмрдВрдз рдХреЛ рд╢рд╛рдорд┐рд▓ рдХрд░рдХреЗ рдЕрдиреБрдорддрд┐ рдХреЗ рд╕рд╛рде рдПрдХреНрд╕реЗрд╕ рдХреЛ рд╕рдВрдмрдВрдзрд┐рдд рдиреЛрдбреНрд╕ рдХреЛ рджрд┐рдпрд╛ рдЬрд╛рдирд╛ рдЪрд╛рд╣рд┐рдП, рдФрд░ рдЗрд╕рдХреЗ рдмрд╛рдж рдирд╣реАрдВред


 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 

рдЪреИрдирд╕реНрдЯреИрдХ рдореЗрдВ рдХреЛрд░рдо рдЦреЛрдЬрдХрд░реНрддрд╛ рдирд┐рдореНрдирд▓рд┐рдЦрд┐рдд рджрд┐рдЦрд╛рдПрдЧрд╛:


  • рдПрдХ рд╕реБрдкрд░рдорд╛рд░реНрдХреЗрдЯ рдореЗрдВ рдПрдХ рдкреНрд░рддрд┐рднрд╛рдЧреА рд╕реЗ рдПрдХ рдЕрдиреБрдмрдВрдз рдХреА рддреИрдирд╛рддреА;
  • рдерд░реНрдб рдкрд╛рд░реНрдЯреА рд╕реЗ SetTemperature ;
  • рд╡рд┐рдХреНрд░реЗрддрд╛ рдкреНрд░рддрд┐рднрд╛рдЧреА рд╕реЗ SetTemperature рдХрд░реЗрдВред

рдЫрд╡рд┐


рдЬреИрд╕рд╛ рдХрд┐ рдЖрдк рджреЗрдЦ рд╕рдХрддреЗ рд╣реИрдВ, рджреЛрдиреЛрдВ рд▓реЗрди-рджреЗрди рдкреВрд░реЗ рд╣реЛ рдЧрдП рд╣реИрдВ, рд▓реЗрдХрд┐рди рднрд╛рдЧреАрджрд╛рд░ рд╡рд┐рдХреНрд░реЗрддрд╛ рд╕реЗ рдХреЗрд╡рд▓ рд▓реЗрдирджреЗрди рдиреЗ рдЕрдиреБрдмрдВрдз рдореЗрдВ рддрд╛рдкрдорд╛рди рдХреЛ рдЕрдкрдбреЗрдЯ рдХрд┐рдпрд╛ред рдЗрд╕ рдкреНрд░рдХрд╛рд░, рдирд┐рдЬреА рд▓реЗрдирджреЗрди рдЕрдкрд░рд┐рд╡рд░реНрддрдиреАрдпрддрд╛ рдкреНрд░рджрд╛рди рдХрд░рддреЗ рд╣реИрдВ, рд▓реЗрдХрд┐рди рд╕рд╛рде рд╣реА рд╡реЗ рдХрд┐рд╕реА рддреАрд╕рд░реЗ рдкрдХреНрд╖ рдХреЛ рдбреЗрдЯрд╛ рдкреНрд░рджрд╛рди рдирд╣реАрдВ рдХрд░рддреЗ рд╣реИрдВред


рдирд┐рд╖реНрдХрд░реНрд╖


рд╣рдордиреЗ рджреЛ рдкрдХреНрд╖реЛрдВ рдХреЗ рдмреАрдЪ рдПрдХ рдиреЗрдЯрд╡рд░реНрдХ рддреИрдирд╛рдд рдХрд░рдХреЗ рдЧреЛрджрд╛рдо рдореЗрдВ рдЕрдк-рдЯреВ-рдбреЗрдЯ рддрд╛рдкрдорд╛рди рдХреА рдЬрд╛рдирдХрд╛рд░реА рдкреНрд░рджрд╛рди рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдХреЛрд░рдо рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рд╡рд╛рдгрд┐рдЬреНрдпрд┐рдХ рдкрд░рд┐рджреГрд╢реНрдп рдХреА рдЬрд╛рдВрдЪ рдХреА - рдПрдХ рд╕реБрдкрд░рдорд╛рд░реНрдХреЗрдЯ рдФрд░ рдЧреЛрджрд╛рдо рдХреЗ рдорд╛рд▓рд┐рдХред


рд╣рдордиреЗ рджрд┐рдЦрд╛рдпрд╛ рд╣реИ рдХрд┐ рд╕рд╛рд░реНрд╡рдЬрдирд┐рдХ рдФрд░ рдирд┐рдЬреА рд▓реЗрдирджреЗрди рджреЛрдиреЛрдВ рдХреЗ рдорд╛рдзреНрдпрдо рд╕реЗ рд╡рд░реНрддрдорд╛рди рддрд╛рдкрдорд╛рди рдХреА рдЬрд╛рдирдХрд╛рд░реА рдХреЛ рдХреИрд╕реЗ рдмрдирд╛рдП рд░рдЦрд╛ рдЬрд╛ рд╕рдХрддрд╛ рд╣реИред


рдмрд╣реБрдд рд╕рд╛рд░реЗ рдПрдкреНрд▓рд┐рдХреЗрд╢рди рдкрд░рд┐рджреГрд╢реНрдп рд╣реЛ рд╕рдХрддреЗ рд╣реИрдВ рдФрд░, рдЬреИрд╕рд╛ рдХрд┐ рдЖрдк рджреЗрдЦ рд╕рдХрддреЗ рд╣реИрдВ, рдпрд╣ рдмрд┐рд▓реНрдХреБрд▓ рдореБрд╢реНрдХрд┐рд▓ рдирд╣реАрдВ рд╣реИред


рдкреНрд░рдпреЛрдЧ рдХрд░реЗрдВ, рдЕрдкрдиреА рд╕реНрдХреНрд░рд┐рдкреНрдЯ рдкрд░рд┐рдирд┐рдпреЛрдЬрд┐рдд рдХрд░рдиреЗ рдХрд╛ рдкреНрд░рдпрд╛рд╕ рдХрд░реЗрдВред рдЗрд╕рдХреЗ рдЕрд▓рд╛рд╡рд╛, рдмреНрд▓реЙрдХрдЪреИрди рдкреНрд░реМрджреНрдпреЛрдЧрд┐рдХреА рдЙрджреНрдпреЛрдЧ 2024 рддрдХ рд▓рдЧрднрдЧ рджрд╕ рдЧреБрдирд╛ рдмрдврд╝ рд╕рдХрддрд╛ рд╣реИ ред

Source: https://habr.com/ru/post/hi456368/


All Articles