Quorum 支援私人和公共交易,並且有許多商業用例。
在本文中,我們將研究一個這樣的場景 - 在超市和倉庫所有者之間部署分散式帳本網絡,以提供有關倉庫溫度的最新資訊。
本教程中使用的程式碼位於
文章涵蓋:
- 創建智能合約;
- 使用 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;
}
}
為了使合約能夠與 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 共識和三個節點的 Quorum 網路的流程。
首先,我們建立一個專案並將其命名為 Quorum Project:
讓我們在 Google Cloud Platform 上建立一個具有 Raft 共識的 Quorum 網路:
讓我們在預設創建的節點上再新增兩個節點:
三個運行節點:
節點詳細資料頁面顯示RPC端點、公鑰等。
網路已部署。 現在讓我們部署智能合約並使用以下命令執行交易
公開交易
上下文
倉庫溫度對於降低成本非常重要,特別是對於打算在零度以下儲存的產品。
透過允許公司即時共享其地理位置的外部溫度並將其記錄在不可變的分類帳中,網路參與者可以降低成本和時間。
我們將執行三項任務,如圖所示:
-
我們將透過以下方式部署合約 節點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);
接下來,我們將了解如何使用 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;
});
}
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 explorer中查看條目,如下所示。
所有三個節點進行互動並更新交易:
- 第一個交易部署了合約。
- 第二筆交易將合約溫度設定為3度。
- 溫度是透過本地節點接收的,因此不會建立交易。
私人交易
上下文
組織的一個共同要求是資料保護。 舉個例子,考慮這樣一個場景: 超市場 租用一個單獨的倉庫來儲存海鮮 小販:
- 小販 使用物聯網感測器,每30秒讀取一次溫度值並傳輸 去超市;
- 這些值應該只可用 致供應商 и 去超市,由一個聯盟聯網。
我們將完成上圖所示的四個任務。
- 我們使用與上一個場景相同的三個節點來示範私有交易:
- 超級市場 部署一個私有的智能合約 超市場 и 小販.
- 第三面 無權存取智能合約。
我們將調用這些方法 get
и set
代表 超市場 и 小販 演示私人 Quorum 交易。
-
我們將為參與者部署一個私人合約 超級市場 и 小販 透過一個參與者 超級市場:
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,但是 第三面 無權存取智能合約。 因此回傳值必須為空。
// This returns null const temp3 = await getTemperature(raft3Node, contractAddress); console.log(`[Node3] temp retrieved from external nodes after update ${temp}`);
接下來,我們將仔細研究在 Quorum 網路上執行私人交易
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
來自參與者 小販.
可以看到,兩筆交易都完成了,但只有參與者的交易 小販 更新了合約中的溫度。 因此,私人交易提供了不變性,但同時不會向第三方洩露資料。
結論
我們研究了 Quorum 的一個商業用例,透過在超市和倉庫所有者兩方之間部署網路來提供倉庫中的最新溫度資訊。
我們展示瞭如何透過公共和私人交易來維護最新的溫度資訊。
應用場景可以有很多,正如你所看到的,一點也不困難。
實驗,嘗試擴展你的腳本。 此外,區塊鏈技術產業
來源: www.habr.com