ã¯ã©ãŒã©ã ã¯ãã©ã€ããŒãããã³ãããªãã¯ã®ãã©ã³ã¶ã¯ã·ã§ã³ããµããŒãããŠãããå€ãã®åçšãŠãŒã¹ã±ãŒã¹ããããŸãã
ãã®èšäºã§ã¯ããã®ãããªã·ããªãªã® XNUMX ã€ã§ãããã¹ãŒããŒããŒã±ãããšå庫ææè ã®éã«åæ£åå°åž³ãããã¯ãŒã¯ãå°å ¥ããŠãå庫ã®æž©åºŠã«é¢ããææ°æ å ±ãæäŸããã·ããªãªãæ€èšããŸãã
ãã®ãã¥ãŒããªã¢ã«ã§äœ¿çšãããã³ãŒãã¯æ¬¡ã®ãšããã§ãã
ãã®èšäºã®å 容ã¯æ¬¡ã®ãšããã§ãã
- ã¹ããŒãã³ã³ãã©ã¯ãã®äœæã
- ã䜿çšããã¯ã©ãŒã©ã ãããã¯ãŒã¯ã®å±é
ãã§ãŒã³ã¹ã¿ã㯠; - ã¯ã©ãŒã©ã ãããªãã¯ãã©ã³ã¶ã¯ã·ã§ã³ã
- ã¯ã©ãŒã©ã ãã©ã€ããŒããã©ã³ã¶ã¯ã·ã§ã³ã
説æã®ããã«ãã¢ãã®ã€ã³ã¿ãŒããã (IoT) å ã®ã¯ã©ãŒã©ã ãããã¯ãŒã¯ã®ã¡ã³ããŒã®å庫ã®æž©åºŠãç£èŠããã·ããªãªã䜿çšããŸãã
ã³ã³ããã¹ã
å庫äŒç€Ÿã®ã°ã«ãŒããã³ã³ãœãŒã·ã¢ã ãçµæãããããã¯ãã§ãŒã³äžã§æ å ±ãå ±åä¿ç®¡ããããã»ã¹ãèªååããããšããŠããŸãã ãã®ããã«ãäŒæ¥ã¯ Quorum ã䜿çšããããšã«ããŸããã ãã®èšäºã§ã¯ããããªã㯠ãã©ã³ã¶ã¯ã·ã§ã³ãšãã©ã€ããŒã ãã©ã³ã¶ã¯ã·ã§ã³ãšãã XNUMX ã€ã®ã·ããªãªã«ã€ããŠèª¬æããŸãã
ãã©ã³ã¶ã¯ã·ã§ã³ã¯ãæå±ããã³ã³ãœãŒã·ã¢ã ãšå¯Ÿè©±ããããã«ããŸããŸãªåå è ã«ãã£ãŠäœæãããŸãã åãã©ã³ã¶ã¯ã·ã§ã³ã¯ãã³ã³ãã©ã¯ãããããã€ããããã³ã³ãã©ã¯ãå ã®é¢æ°ãåŒã³åºããŠããŒã¿ããããã¯ãŒã¯ã«ã¢ããããŒãããŸãã ãããã®ã¢ã¯ã·ã§ã³ã¯ãããã¯ãŒã¯äžã®ãã¹ãŠã®ããŒãã«è€è£œãããŸãã
ãããªã㯠ãã©ã³ã¶ã¯ã·ã§ã³ã¯ãã³ã³ãœãŒã·ã¢ã ã®ãã¹ãŠã®åå è ãé²èŠ§ã§ããŸãã ãã©ã€ããŒããã©ã³ã¶ã¯ã·ã§ã³ã¯æ©å¯æ§ã®å±€ãè¿œå ããããããæš©å©ãæã€åå è ã®ã¿ãå©çšã§ããŸãã
ã©ã¡ãã®ã·ããªãªã§ããããããããããããã«åãã³ã³ãã©ã¯ãã䜿çšããŸãã
ã¹ããŒãå¥çŽ
以äžã¯ããã®ã·ããªãªçšã«äœæãããåçŽãªã¹ããŒã ã³ã³ãã©ã¯ãã§ãã ãããªãã¯å€æ°ããããŸã 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;
}
}
å¥çŽãæ©èœããããã«ã¯ 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
0x608060405234801561001057600080fd5b50610104806100206000396000f30060806040526004361060525763ffffffff7c01000000000000000000000000000000000000000000000000000000006000350416636d4ce63c81146057578063adccea12146082578063faee13b9146094575b600080fd5b348015606257600080fd5b50606960ae565b60408051600092830b90920b8252519081900360200190f35b348015608d57600080fd5b50606960b7565b348015609f57600080fd5b5060ac60043560000b60c0565b005b60008054900b90565b60008054900b81565b6000805491810b60ff1660ff199092169190911790555600a165627a7a72305820af0086d55a9a4e6d52cb6b3967afd764ca89df91b2f42d7bf3b30098d222e5c50029
å¥çŽã®æºåãã§ããã®ã§ããããã¯ãŒã¯ãå±éããŠå¥çŽãå±éããŸãã
ããŒãã®å±é
ããŒãã®ãããã€ã¯éåžžã«åŽåããããå Žåãããããã®ããã»ã¹ã¯ãµãŒãã¹ã䜿çšããããšã§çœ®ãæããããšãã§ããŸãã
以äžã¯ãRaft ã³ã³ã»ã³ãµã¹ãš XNUMX ã€ã®ããŒãã䜿çšããŠã¯ã©ãŒã©ã ãããã¯ãŒã¯ããããã€ããããã»ã¹ã§ãã
ãŸãããããžã§ã¯ããäœæããŠãQuorum ãããžã§ã¯ããšããååãä»ããŸãããã
Google Cloud Platform äžã§ Raft ã³ã³ã»ã³ãµã¹ã䜿çšããŠã¯ã©ãŒã©ã ãããã¯ãŒã¯ãäœæããŠã¿ãŸãããã
ããã©ã«ãã§ãã§ã«äœæãããŠããããŒãã«ããã« XNUMX ã€ã®ããŒããè¿œå ããŸãããã
XNUMX ã€ã®å®è¡ããŒã:
ããŒãã®è©³çŽ°ããŒãžã«ã¯ãRPC ãšã³ããã€ã³ããå ¬éããŒãªã©ã衚瀺ãããŸãã
ãããã¯ãŒã¯ãå±éãããŠããŸãã 次ã«ãã¹ããŒã ã³ã³ãã©ã¯ãããããã€ãã次ã䜿çšããŠãã©ã³ã¶ã¯ã·ã§ã³ãå®è¡ããŸãããã
å ¬çååŒ
ã³ã³ããã¹ã
å庫ã®æž©åºŠã¯ãç¹ã«æ°·ç¹äžã®æž©åºŠã§ä¿ç®¡ãã補åã®å Žåãã³ã¹ããåæžããäžã§éåžžã«éèŠã§ãã
äŒæ¥ãå°ççäœçœ®ã®å€æ°æž©ããªã¢ã«ã¿ã€ã ã§å ±æããäžå€ã®å°åž³ã«èšé²ã§ããããã«ããããšã§ããããã¯ãŒã¯åå è ã¯ã³ã¹ããšæéãåæžããŸãã
å³ã«ç€ºã XNUMX ã€ã®ã¿ã¹ã¯ãå®è¡ããŸãã
-
çµç±ã§å¥çŽããããã€ããŸã ããŒã1:
const contractAddress = await deployContract(raft1Node); console.log(`Contract address after deployment: ${contractAddress}`);
-
枩床ãèšå®ããã«ã¯ ããŒã2 3床ãã€ïŒ
const status = await setTemperature(raft2Node, contractAddress, 3); console.log(`Transaction status: ${status}`);
-
ããŒã3 ã¹ããŒãã³ã³ãã©ã¯ãããæ å ±ãåãåããŸãã ã³ã³ãã©ã¯ã㯠3 床ã®å€ãè¿ããŸãã
const temp = await getTemperature(raft3Node, contractAddress); console.log(âRetrieved contract Temperatureâ, temp);
次ã«ã次ã䜿çšããŠã¯ã©ãŒã©ã ãããã¯ãŒã¯äžã§ãããªã㯠ãã©ã³ã¶ã¯ã·ã§ã³ãå®è¡ããæ¹æ³ãèŠãŠãããŸãã
web3.js .
XNUMX ã€ã®ããŒãã«å¯Ÿã㊠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;
});
}
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);
}
ããã§å®è¡ã§ããŸã
// Execute public script
node public.js
Contract address after deployment: 0xf46141Ac7D6D6E986eFb2321756b5d1e8a25008F
Transaction status: true
Retrieved contract Temperature 3
次ã«ã以äžã«ç€ºãããã«ã[Chainstack] ããã«ã® Quorum ãšã¯ã¹ãããŒã©ãŒã§ãšã³ããªã衚瀺ã§ããŸãã
XNUMX ã€ã®ããŒããã¹ãŠã察話ãããã©ã³ã¶ã¯ã·ã§ã³ãæŽæ°ãããŸããã
- æåã®ãã©ã³ã¶ã¯ã·ã§ã³ã§ã³ã³ãã©ã¯ãããããã€ãããŸããã
- 3 çªç®ã®ãã©ã³ã¶ã¯ã·ã§ã³ã§ã¯ãå¥çŽæž©åºŠã XNUMX 床ã«èšå®ããŸããã
- 枩床ã¯ããŒã«ã« ããŒããéããŠåä¿¡ãããããããã©ã³ã¶ã¯ã·ã§ã³ã¯äœæãããŸããã
ãã©ã€ããŒããã©ã³ã¶ã¯ã·ã§ã³
ã³ã³ããã¹ã
çµç¹ã®å ±éã®èŠä»¶ã¯ããŒã¿ä¿è·ã§ãã äŸãšããŠã次ã®ãããªã·ããªãªãèããŠã¿ãŸãããã ã¹ãŒããŒããŒã±ãã éä»é¡ãä¿ç®¡ããå庫ã¹ããŒã¹ãå¥ã®æ¥è ããåããŠããŸãã ãã³ããŒ:
- ãã³ã㌠IoTã»ã³ãµãŒã䜿çšãã30ç§ããšã«æž©åºŠå€ãèªã¿åããéä¿¡ããŸã ã¹ãŒããŒããŒã±ãããž;
- ãããã®å€ã¯ã®ã¿å©çšå¯èœã§ããå¿ èŠããããŸã ãã³ããŒãž О ã¹ãŒããŒããŒã±ãããžãã³ã³ãœãŒã·ã¢ã ã«ãã£ãŠãããã¯ãŒã¯åãããŠããŸãã
äžã®å³ã«ç€ºãããŠãã XNUMX ã€ã®ã¿ã¹ã¯ãå®äºããŸãã
- åã®ã·ããªãªãšåã XNUMX ã€ã®ããŒãã䜿çšããŠããã©ã€ããŒã ãã©ã³ã¶ã¯ã·ã§ã³ã瀺ããŸãã
- ã¹ãŒããŒããŒã±ãã ãã©ã€ããŒããªã¹ããŒãã³ã³ãã©ã¯ããå±éããŸã ã¹ãŒããŒããŒã±ãã О ãã³ããŒ.
- XNUMXçªç®ã®é¢ ã¹ããŒãã³ã³ãã©ã¯ãã«ã¢ã¯ã»ã¹ããæš©å©ã¯ãããŸããã
ã¡ãœãããåŒã³åºããŸã get
О set
ã«ä»£ãã£ãŠ ã¹ãŒããŒããŒã±ãã О ãã³ã㌠ãã©ã€ããŒã ã¯ã©ãŒã©ã ãã©ã³ã¶ã¯ã·ã§ã³ããã¢ã³ã¹ãã¬ãŒã·ã§ã³ããŸãã
-
åå è åãã«åå¥å¥çŽãå±éããŸã ã¹ãŒããŒããŒã±ãã О ãã³ã㌠åå è ãéã㊠ã¹ãŒããŒããŒã±ãã:
const contractAddress = await deployContract( raft1Node, process.env.PK2, ); console.log(`Contract address after deployment: ${contractAddress}`);
-
ãã枩床ãèšå®ããŸããã 第äžè (å€éšããŒã) ãå®è¡ãã枩床å€ãååŸããŸãã
// 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}`);
-
ãã枩床ãèšå®ããŸããã ãã³ã㌠ïŒå éšããŒãïŒæž©åºŠå€ãååŸããŸãã
ãã®ã·ããªãªã®æž©åºŠã¯ãã¹ããŒã ã³ã³ãã©ã¯ãããå€ 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}`);
-
ãã枩床ãååŸããŸã 第äžè (å€éšããŒã):
æé 3 ã§ã¯æž©åºŠã 12 ã«èšå®ããŸãããã XNUMXçªç®ã®é¢ ã¹ããŒãã³ã³ãã©ã¯ãã«ã¢ã¯ã»ã¹ã§ããŸããã ãããã£ãŠãæ»ãå€ã¯ null ã§ãªããã°ãªããŸããã
// This returns null const temp3 = await getTemperature(raft3Node, contractAddress); console.log(`[Node3] temp retrieved from external nodes after update ${temp}`);
次ã«ãã¯ã©ãŒã©ã ãããã¯ãŒã¯äžã§ãã©ã€ããŒã ãã©ã³ã¶ã¯ã·ã§ã³ãå®è¡ããæ¹æ³ã詳ããèŠãŠãããŸãã
web3.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;
});
}
ããã§èµ°ããŸã
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
ãã 第äžè ; - å®è¡
SetTemperature
åå è ããã® ãã³ããŒ.
ã芧ã®ãšãããäž¡æ¹ã®ãã©ã³ã¶ã¯ã·ã§ã³ãå®äºããŸããããåå è ããã®ãã©ã³ã¶ã¯ã·ã§ã³ã®ã¿ãå®äºããŸããã ãã³ã㌠å¥çŽäžã®æž©åºŠãæŽæ°ããŸããã ãããã£ãŠããã©ã€ããŒã ãã©ã³ã¶ã¯ã·ã§ã³ã¯äžå€æ§ãæäŸããŸãããåæã«ããŒã¿ã第äžè ã«å ¬éããŸããã
ãŸãšã
ç§ãã¡ã¯ãã¹ãŒããŒããŒã±ãããšå庫ææè ã® XNUMX è éã«ãããã¯ãŒã¯ãå±éããŠãå庫å ã®ææ°ã®æž©åºŠæ å ±ãæäŸãã Quorum ã®åçšãŠãŒã¹ ã±ãŒã¹ãæ€èšããŸããã
ãããªãã¯ããã³ãã©ã€ããŒãã®äž¡æ¹ã®ãã©ã³ã¶ã¯ã·ã§ã³ãéããŠææ°ã®æž©åºŠæ å ±ãç¶æããæ¹æ³ã瀺ããŸããã
å¿çšã·ããªãªã¯æ°å€ããããŸãããã芧ã®ãšããããŸã£ããé£ããããšã§ã¯ãããŸããã
å®éšããŠãã¹ã¯ãªãããæ¡åŒµããŠã¿ãŠãã ããã ããã«ããããã¯ãã§ãŒã³æè¡æ¥çã¯ã
åºæïŒ habr.com