Fabirc2.2安裝、使用文檔
官方文檔: https://hyperledger-fabric.readthedocs.io/en/release-2.2/write_first_app.html
參考文檔: https://blog.csdn.net/shengsikandan/article/details/107656060
1、Fabric2.2環境安裝
1.1、環境准備
1.1.1、Go語言
(1)安裝必須的依賴
sudo yum install libtool libltdl-dev
(2)下載Go語言安裝包,我的版本是:go1.14.6.linux-amd64.tar.gz
將壓縮包上傳到/usr/local下,解壓。
cd /usr/local
tar zxvf go1.14.6.linux-amd64.tar.gz
(3)配置Go環境變量
- 編輯/etc/profile文件
vi /etc/profile
- 在文件末尾追加
export PATH=$PATH:/usr/local/go/bin
export GOROOT=/usr/local/go
export GOPATH=$HOME/go
export PATH=$PATH:$GOPATH/bin
- 重新加載該文件
source /etc/profile
- 通過查看go版本檢查是否安裝成功
go version

1.1.2、docker以及docker-compose安裝
- 首先安裝所需工具包yum-utils,它提供了yum-config-manager,並且device mapper 存儲驅動程序需要 device-mapper-persistent-data 和 lvm2
sudo yum install -y yum-utils device-mapper-persistent-data lvm2
- 設置yum源添加docker倉庫
官方源地址(比較慢)
sudo yum-config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.repo
阿里雲(推薦)
sudo yum-config-manager --add-repo http://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo
清華大學源
sudo yum-config-manager --add-repo https://mirrors.tuna.tsinghua.edu.cn/docker-ce/linux/centos/docker-ce.repo
- 安裝docker(默認最新)
sudo yum install docker-ce
- 安裝docker compose
sudo curl -L "https://github.com/docker/compose/releases/download/1.27.3/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose
如果網速慢,下載失敗, 可以用下載工具進行下載,傳到linux的/usr/bin目錄即可,
下載地址: https://github.com/docker/compose/releases

下載完成后需要賦予docker-compose可執行的權限,
chmod +x /usr/bin/docker-compose
- 驗證docker是否安裝成功
docker version
- 驗證docker compose 是否安裝成功
docker-compose -v
- 啟動docker
systemctl start docker
1.2 Fabric環境搭建
- 創建文件夾
cd #cd 返回Home文件夾
mkdir -p go/src/github.com/hyperledger/
#進入剛剛創建的文件夾內
cd go/src/github.com/hyperledger/
- 從github上拉取fabric的源碼:
git clone "https://github.com/hyperledger/fabric.git"
如果沒有git環境,先安裝git,如下
yum install git
下載fabric源碼比較慢,可以在github上下載然后上傳到服務器新建的文件夾下。
- 進入到克隆下的fabric目錄下的scripts文件夾
cd fabric/scripts/
- fabric官方提供了一個bootstrap.sh的腳本, 該腳本擁有三個功能 :
-
下載fabric-samples文件;
-
下載二進制文件;
-
拉取docker鏡像。
並且這個腳本支持三個參數, 可以靈活地控制它的執行 . 分別是
-b:加上此參數,則不下載二進制文件
-d:加上此參數則不拉取docker鏡像
-s:加上此參數則不下載fabric-samples
- 如果直接執行 bootstrap.sh腳本會特別慢,修改bootstrap.sh。
vi bootstrap.sh
- 修改cloneSamplesRepo() 函數
在cloneSamplesRepo() 函數中會發現fabric-samples是在GitHub中克隆的,注釋原克隆代碼,修改為以下三個地址中任一克隆代碼(可以試試哪一個訪問地址最快,選擇最快的訪問地址)
# 源代碼為
# git clone -b master https://github.com/hyperledger/fabric-samples.git && cd fabric-samples && git checkout v${VERSION}
# 修改為
git clone -b master https://hub.fastgit.org/hyperledger/fabric-samples.git && cd fabric-samples && git checkout v${VERSION}
# or
git clone -b master https://github.com.cnpmjs.org/hyperledger/fabric-samples.git && cd fabric-samples && git checkout v${VERSION}
# or
git clone -b master https://github.91chifun.workers.dev//https://github.com/hyperledger/fabric-samples.git && cd fabric-samples && git checkout v${VERSION}
修改完后函數為:

- 修改pullBinaries() 函數
在pullBinaries() 函數中會發現二進制文件fabric v* 和 fabric ca v*也是在GitHub中下載的,注釋原下載代碼,修改為以下代碼
# 源代碼為
download "${BINARY_FILE}" "https://github.com/hyperledger/fabric/releases/download/v${VERSION}/${BINARY_FILE}"
download "${CA_BINARY_FILE}" "https://github.com/hyperledger/fabric-ca/releases/download/v${CA_VERSION}/${CA_BINARY_FILE}"
# 修改為
download "${BINARY_FILE}" "https://github.91chifun.workers.dev//https://github.com/hyperledger/fabric/releases/download/v${VERSION}/${BINARY_FILE}"
download "${CA_BINARY_FILE}" "https://github.91chifun.workers.dev//https://github.com/hyperledger/fabric-ca/releases/download/v${CA_VERSION}/${CA_BINARY_FILE}"
修改完后函數為:

保存腳本。
- 執行修改后bootstrap.sh腳本
./bootstrap.sh
如果修改后下載二進制文件還是很慢,加上-b忽略二進制文件,稍后通過手動下載二進制文件)
./bootstrap.sh -b
執行完成后會生成一個 fabric-samples文件夾。
- 切換到該目錄下
cd fabric-samples
在目錄下會有一個bin目錄,就是存放二進制文件。
- 接下來下載二進制文件(如果已經有二進制文件,則忽略此步)
下載地址: https://github.com/hyperledger/fabric/releases/

下載完成后,上傳到當前fabric-samples所在目錄,然后解壓,解壓完成后在bin目錄下就會出現:

-
然后切換到test-network:
cd ../test-network/啟動測試網絡:
sudo ./network.sh up -
第一次啟動時會創建證書

- 出現如下界面,則環境搭建成功。

- 關閉網絡,執行:
./network.sh down
如果啟動時出現,找不到docker-compose命令,但是docker-compose -v命令可以查看版本,則檢查該文件的位置,如果是在/usr/local/bin目錄下。
兩個辦法:
1、建立軟鏈接: sudo ln -s /usr/local/bin/docker-compose /usr/bin/docker-compose
2、復制一份到/usr/bin目錄下,並賦予可執行權限。
2、fabric使用描述
2.1、創建通道
(1)與 Fabric 網絡交互的每個節點和用戶都需要屬於一個組織才能參與網絡。測試網絡包括兩個對等組織,Org1 和 Org2。它還包括一個維護網絡訂購服務的單一訂購者組織。
(2)網絡中的每個peer節點都需要屬於一個組織。在測試網絡中,每個組織都操作一個peer節點,peer0.org1.example.com 並且peer0.org2.example.com.
(3)機器上運行了 peer 和 orderer 節點,我們可以使用腳本為 Org1 和 Org2 之間的交易創建一個 Fabric 通道。通道是特定網絡成員之間的私有通信層。通道只能由受邀加入通道的組織使用,並且對網絡的其他成員不可見。每個通道都有一個單獨的區塊鏈分類賬。被邀請的組織將其同行“加入”通道以存儲通道分類帳並驗證通道上的交易。
(4)可以使用該network.sh腳本在 Org1 和 Org2 之間創建一個通道,並將它們的對等節點加入該通道。運行以下命令以創建一個默認名稱為 的通道mychannel:
./network.sh createChannel
指定通道名稱創建:
./network.sh createChannel -c channel1
一步啟動網絡並創建通道,可以同時使用up和createChannel模式
./network.sh up createChannel
2.2、在通道上啟動鏈碼
(1)創建通道后,可以開始使用智能合約與通道分類帳進行交互。智能合約包含管理區塊鏈分類賬上資產的業務邏輯。由網絡成員運行的應用程序可以調用智能合約在分類賬上創建資產,以及更改和轉移這些資產。應用程序還會查詢智能合約以讀取分類帳上的數據。
(2)為確保交易有效,使用智能合約創建的交易通常需要由多個組織簽署才能提交到通道分類賬。多重簽名是 Fabric 信任模型不可或缺的一部分。要求對交易進行多次背書可以防止通道上的一個組織篡改其peer節點的分類帳或使用未經同意的業務邏輯。要簽署交易,每個組織都需要在其peer節點上調用並執行智能合約,然后對交易的輸出進行簽名。如果輸出一致並且已被足夠多的組織簽署,則可以將交易提交到分類帳中。指定通道上需要執行智能合約的設置組織的策略稱為背書策略,
(3)在 Fabric 中,智能合約以稱為鏈碼的包的形式部署在網絡上。Chaincode 安裝在組織的peer節點上,然后部署到通道,然后可用於對交易進行背書並與區塊鏈分類賬進行交互。在將鏈碼部署到通道之前,通道的成員需要就建立鏈碼治理的鏈碼定義達成一致。當所需的組織數量同意時,鏈碼定義可以提交到通道,鏈碼就可以使用了。
(4)使用network.sh創建通道后,可以使用以下命令在通道上啟動鏈碼:
./network.sh deployCC -ccn basic -ccp ../asset-transfer-basic/chaincode-go -ccl go
所述deployCC子命令將安裝資產轉移chaincode到 peer0.org1.example.com和peer0.org2.example.com,然后部署信道對chaincode使用信道標志指定的(或mychannel 如果未指定信道)。如果您是第一次部署鏈碼,腳本將安裝鏈碼依賴項。您可以使用語言標志 ,-l來安裝鏈代碼的 Go、typescript 或 javascript 版本。可以asset-transfer-basic在fabric-samples 目錄的文件夾中找到資產轉移(基本)鏈代碼。此文件夾包含作為示例提供並由教程用於突出 Fabric 功能的示例鏈代碼。
3、鏈碼部署以及執行示例
資產轉移智能合約和應用程序的 JavaScript 版本,fabric-samples文件夾下提供了多種語言示例,基本案例位於:
fabric-samples/asset-transfer-basic/

chaincode-*:表示各種語言對應的鏈碼
application-*:表示各種語言調用鏈碼的應用程序
3.1、資產轉移案例
此資產轉移(基本)示例演示了如何使用資產初始化分類帳、查詢這些資產、創建新資產、基於資產 ID 查詢單個資產、更新現有資產以及將資產轉移給新所有者。它涉及以下兩個組成部分:
- 示例應用程序:調用區塊鏈網絡,調用鏈碼(智能合約)中實現的交易。該應用程序位於以下
fabric-samples目錄中:asset-transfer-basic/application-javascript
- 智能合約本身,實現涉及與賬本交互的交易。智能合約(鏈碼)位於以下
fabric-samples目錄中:asset-transfer-basic/chaincode-(javascript, java, go, typescript)
3.2、設置區塊鏈網絡
(1)進入到目錄cd fabric-samples/test-network
- 如果已經有一個測試網絡在運行,請將其關閉以確保環境干凈
./network.sh down
- 使用
network.shshell 腳本啟動 Fabric 測試網絡
./network.sh up createChannel -c mychannel -ca
此命令將部署具有兩個peer、一個order排序服務和三個證書頒發機構(Orderer、Org1、Org2)的 Fabric 測試網絡。不使用 cryptogen 工具,而是使用證書頒發機構來啟動測試網絡,因此是-ca標志。此外,組織管理員用戶注冊在證書頒發機構啟動時被引導。在后面的步驟中,我們將展示示例應用程序如何完成管理員注冊。
執行完成后如圖所示:

可能的報錯:
(1)錯誤信息如下

- 沒有將fabric-samples/bin/目錄加到環境變量中。
- 編輯/etc/profile
export PATH=$PATH:/root/go/src/github.com/hyperledger/fabric/scripts/fabric-samples/bin
- 重新加載
source /etc/profile
(2)錯誤信息如下

-
缺少fabric-ca-client腳本文件
-
下載fabric-ca源碼:下載地址: https://github.com/hyperledger/fabric-ca/tags
-
下載1.5.0版本完成后並上傳,解壓后進入目錄
make fabric-ca-client
make fabric-ca-server
執行完成后,會生成一個bin目錄,bin目錄下會由兩個可執行文件,復制到環境變量配置的bin目錄下
/root/go/src/github.com/hyperledger/fabric/scripts/fabric-samples/bin。
- 通過
./network.sh使用鏈碼名稱和語言選項調用腳本來部署鏈碼
./network.sh deployCC -ccn basic -ccp ../asset-transfer-basic/chaincode-javascript/ -ccl javascript
3.3、應用程序調用鏈碼
使用javascript應用程序進行測試
(1) 打開一個新終端,然后導航到該application-javascript文件夾
cd asset-transfer-basic/application-javascript
(2) 此目錄包含使用 Fabric SDK for Node.js 開發的示例程序。運行以下命令以安裝應用程序依賴項。
npm install
此過程是安裝應用程序的 package.json. 其中最重要的是fabric-networkNode.js 模塊;它使應用程序能夠使用身份、錢包和網關連接到通道、提交交易和等待通知。使用fabric-ca-client模塊為用戶注冊各自的證書頒發機構,生成一個有效身份,然后fabric-network模塊使用該身份與區塊鏈網絡進行交互。
如果報錯顯示npm未找到命令,則需要安裝node環境
fabric2.2.3版本支持的node版本:"node":"^10.15.3 || ^12.13.1 || 14.13.1","npm":"6.4.1"
官網下載nodejs,https://nodejs.org/en/download/
- 獲取安裝包,或者下載上傳到centos
wget https://nodejs.org/dist/latest-v8.x/node-v14.13.1-linux-x64.tar.gz
- 解壓
tar -xvf node-v14.13.1-linux-x64
- 加入環境變量,編輯 /etc/profile,我的安裝目錄為:/usr/local/node/node-v14.13.1-linux-x64/bin
在/etc/profile文件末尾添加:
export PATH=$PATH:/usr/local/node/node-v14.13.1-linux-x64/bin
- 使文件生效
source /etc/profile
- 檢查是否安裝成功
node -v
安裝過程中出現:

解決:使用 yum install gcc-c++
之后,會看到以下目錄:

(3) 在第一步啟動 Fabric 測試網絡時,創建了一個管理員用戶(字面稱為admin)作為證書頒發機構 (CA)的注冊商。第一步是 admin通過讓應用程序調用enrollAdmin. 此過程使用證書簽名請求(CSR) — 首先在本地生成私鑰和公鑰,然后將公鑰發送到 CA,CA 返回編碼證書以供應用程序使用。然后這些憑據存儲在錢包中,使我們能夠充當 CA 的管理員。
執行命令:
node app.js
可以看到應用調用鏈碼,執行結果:

3.4、應用程序代碼
3.4.1、JavaScript
控制台中的輸出,都可以在代碼中找到對應的位置
/*
* Copyright IBM Corp. All Rights Reserved.
*
* SPDX-License-Identifier: Apache-2.0
*/
'use strict';
const { Gateway, Wallets } = require('fabric-network');
const FabricCAServices = require('fabric-ca-client');
const path = require('path');
const { buildCAClient, registerAndEnrollUser, enrollAdmin } = require('../../test-application/javascript/CAUtil.js');
const { buildCCPOrg1, buildWallet } = require('../../test-application/javascript/AppUtil.js');
const channelName = 'mychannel';
const chaincodeName = 'basic';
const mspOrg1 = 'Org1MSP';
const walletPath = path.join(__dirname, 'wallet');
const org1UserId = 'appUser';
function prettyJSONString(inputString) {
return JSON.stringify(JSON.parse(inputString), null, 2);
}
// pre-requisites:
// - fabric-sample two organization test-network setup with two peers, ordering service,
// and 2 certificate authorities
// ===> from directory /fabric-samples/test-network
// ./network.sh up createChannel -ca
// - Use any of the asset-transfer-basic chaincodes deployed on the channel "mychannel"
// with the chaincode name of "basic". The following deploy command will package,
// install, approve, and commit the javascript chaincode, all the actions it takes
// to deploy a chaincode to a channel.
// ===> from directory /fabric-samples/test-network
// ./network.sh deployCC -ccn basic -ccp ../asset-transfer-basic/chaincode-javascript/ -ccl javascript
// - Be sure that node.js is installed
// ===> from directory /fabric-samples/asset-transfer-basic/application-javascript
// node -v
// - npm installed code dependencies
// ===> from directory /fabric-samples/asset-transfer-basic/application-javascript
// npm install
// - to run this test application
// ===> from directory /fabric-samples/asset-transfer-basic/application-javascript
// node app.js
// NOTE: If you see kind an error like these:
/*
2020-08-07T20:23:17.590Z - error: [DiscoveryService]: send[mychannel] - Channel:mychannel received discovery error:access denied
******** FAILED to run the application: Error: DiscoveryService: mychannel error: access denied
OR
Failed to register user : Error: fabric-ca request register failed with errors [[ { code: 20, message: 'Authentication failure' } ]]
******** FAILED to run the application: Error: Identity not found in wallet: appUser
*/
// Delete the /fabric-samples/asset-transfer-basic/application-javascript/wallet directory
// and retry this application.
//
// The certificate authority must have been restarted and the saved certificates for the
// admin and application user are not valid. Deleting the wallet store will force these to be reset
// with the new certificate authority.
//
/**
* A test application to show basic queries operations with any of the asset-transfer-basic chaincodes
* -- How to submit a transaction
* -- How to query and check the results
*
* To see the SDK workings, try setting the logging to show on the console before running
* export HFC_LOGGING='{"debug":"console"}'
*/
async function main() {
try {
//使用網絡配置(也稱為連接配置文件)構建內存對象
const ccp = buildCCPOrg1();
// 根據網絡配置中的信息構建fabric ca服務客戶端的實例
const caClient = buildCAClient(FabricCAServices, ccp, 'ca.org1.example.com');
// 設置錢包以保存應用程序用戶的憑據
const wallet = await buildWallet(Wallets, walletPath);
// 在實際應用程序中,這將在管理流程中完成,並且僅一次。應用程序注冊admin用戶
await enrollAdmin(caClient, wallet, mspOrg1);
// 在實際應用程序中,這僅在需要添加新用戶並且將成為管理流程的一部分時完成
await registerAndEnrollUser(caClient, wallet, mspOrg1, org1UserId, 'org1.department1');
// Create a new gateway instance for interacting with the fabric network.
// In a real application this would be done as the backend server session is setup for
// a user that has been verified.
const gateway = new Gateway();
try {
// setup the gateway instance
// The user will now be able to create connections to the fabric network and be able to
// submit transactions and query. All transactions submitted by this gateway will be
// signed by this user using the credentials stored in the wallet.
await gateway.connect(ccp, {
wallet,
identity: org1UserId,
discovery: { enabled: true, asLocalhost: true } // using asLocalhost as this gateway is using a fabric network deployed locally
});
// Build a network instance based on the channel where the smart contract is deployed
//根據部署智能合約的通道構建網絡實例
const network = await gateway.getNetwork(channelName);
// Get the contract from the network.
//從網絡獲取合約
const contract = network.getContract(chaincodeName);
// Initialize a set of asset data on the channel using the chaincode 'InitLedger' function.
// This type of transaction would only be run once by an application the first time it was started after it
// deployed the first time. Any updates to the chaincode deployed later would likely not need to run
// an "init" type function.
console.log('\n--> Submit Transaction: InitLedger, function creates the initial set of assets on the ledger');
await contract.submitTransaction('InitLedger');
console.log('*** Result: committed');
// Let's try a query type operation (function).
// This will be sent to just one peer and the results will be shown.
console.log('\n--> Evaluate Transaction: GetAllAssets, function returns all the current assets on the ledger');
let result = await contract.evaluateTransaction('GetAllAssets');
console.log(`*** Result: ${prettyJSONString(result.toString())}`);
// Now let's try to submit a transaction.
// This will be sent to both peers and if both peers endorse the transaction, the endorsed proposal will be sent
// to the orderer to be committed by each of the peer's to the channel ledger.
console.log('\n--> Submit Transaction: CreateAsset, creates new asset with ID, color, owner, size, and appraisedValue arguments');
result = await contract.submitTransaction('CreateAsset', 'asset13', 'yellow', '5', 'Tom', '1300');
console.log('*** Result: committed');
if (`${result}` !== '') {
console.log(`*** Result: ${prettyJSONString(result.toString())}`);
}
console.log('\n--> Evaluate Transaction: ReadAsset, function returns an asset with a given assetID');
result = await contract.evaluateTransaction('ReadAsset', 'asset13');
console.log(`*** Result: ${prettyJSONString(result.toString())}`);
console.log('\n--> Evaluate Transaction: AssetExists, function returns "true" if an asset with given assetID exist');
result = await contract.evaluateTransaction('AssetExists', 'asset1');
console.log(`*** Result: ${prettyJSONString(result.toString())}`);
console.log('\n--> Submit Transaction: UpdateAsset asset1, change the appraisedValue to 350');
await contract.submitTransaction('UpdateAsset', 'asset1', 'blue', '5', 'Tomoko', '350');
console.log('*** Result: committed');
console.log('\n--> Evaluate Transaction: ReadAsset, function returns "asset1" attributes');
result = await contract.evaluateTransaction('ReadAsset', 'asset1');
console.log(`*** Result: ${prettyJSONString(result.toString())}`);
try {
// How about we try a transactions where the executing chaincode throws an error
// Notice how the submitTransaction will throw an error containing the error thrown by the chaincode
console.log('\n--> Submit Transaction: UpdateAsset asset70, asset70 does not exist and should return an error');
await contract.submitTransaction('UpdateAsset', 'asset70', 'blue', '5', 'Tomoko', '300');
console.log('******** FAILED to return an error');
} catch (error) {
console.log(`*** Successfully caught the error: \n ${error}`);
}
console.log('\n--> Submit Transaction: TransferAsset asset1, transfer to new owner of Tom');
await contract.submitTransaction('TransferAsset', 'asset1', 'Tom');
console.log('*** Result: committed');
console.log('\n--> Evaluate Transaction: ReadAsset, function returns "asset1" attributes');
result = await contract.evaluateTransaction('ReadAsset', 'asset1');
console.log(`*** Result: ${prettyJSONString(result.toString())}`);
} finally {
// Disconnect from the gateway when the application is closing
// This will close all connections to the network
gateway.disconnect();
}
} catch (error) {
console.error(`******** FAILED to run the application: ${error}`);
}
}
main();
(1)注冊管理員, 注冊管理員是發生在應用程序和證書頒發機構之間的交互,而不是應用程序和鏈碼之間的交互
//使用網絡配置(也稱為連接配置文件)構建內存對象
const ccp = buildCCPOrg1();
// 根據網絡配置中的信息構建fabric ca服務客戶端的實例
const caClient = buildCAClient(FabricCAServices, ccp, 'ca.org1.example.com');
// 設置錢包以保存應用程序用戶的憑據
const wallet = await buildWallet(Wallets, walletPath);
// 在實際應用程序中,這將在管理流程中完成,並且僅一次。應用程序注冊admin用戶
await enrollAdmin(caClient, wallet, mspOrg1);
這段代碼 在獲取公共連接配置文件路徑的引用、確保連接配置文件存在並指定創建錢包的位置后, enrollAdmin()將執行並從證書頒發機構生成管理員憑據 。
此命令將 CA 管理員的憑據存儲在wallet目錄中。可以在wallet/admin.id 文件中找到管理員的證書和私鑰。
enrollAdmin() 和其他 CA 相關函數包含在
fabric-samples/test-application/javascript/CAUtil.js通用實用程序中
(2)注冊用戶(應用程序用戶)
現在我們在錢包中擁有管理員的憑據,應用程序使用admin 用戶來注冊將用於與區塊鏈網絡交互的應用程序用戶
// 在實際應用程序中,這僅在需要添加新用戶並且將成為管理流程的一部分時完成
await registerAndEnrollUser(caClient, wallet, mspOrg1, org1UserId, 'org1.department1');
與管理員注冊類似,此功能使用 CSR 來注冊和注冊appUser並將其憑據與admin錢包中的憑據一起存儲。我們現在有兩個獨立用戶的身份——admin和appUser——應用程序中可以使用這些身份。
運行結果開頭中出現兩個Successfully:

(3)連接通道和智能合約
應用程序生成了管理員和應用程序用戶憑據並將它們放在錢包中。如果憑據存在並且具有與其關聯的正確權限,則示例應用程序用戶將能夠在獲取對通道名稱和合約名稱的引用后調用鏈代碼函數。
try {
// 新建一個網關實例
// 使用org1UserId用戶簽名校驗連接
await gateway.connect(ccp, {
wallet,
identity: org1UserId,
//告訴節點客戶端 sdk 使用服務發現(在對等方上運行),該服務發現獲取當前在線的其他對等方、相關背書策略等元數據以及與其他節點通信所需的任何靜態信息。asLocalhost設置為true告訴它為localhost連接,因為我們的客戶端是同一網絡等織物的節點上運行。如果與其他結構節點不在相同的網絡上運行客戶端的部署中,該asLocalhost選項將設置為false。
discovery: { enabled: true, asLocalhost: true }
});
//根據部署智能合約的通道構建網絡實例
const network = await gateway.getNetwork(channelName);
//根據合約名從網絡獲取部署的合約
const contract = network.getContract(chaincodeName);
(4)開始調用智能合約的方法
console.log('\n--> Submit Transaction: InitLedger, function creates the initial set of assets on the ledger');
await contract.submitTransaction('InitLedger');
console.log('*** Result: committed');
// Let's try a query type operation (function).
// This will be sent to just one peer and the results will be shown.
console.log('\n--> Evaluate Transaction: GetAllAssets, function returns all the current assets on the ledger');
let result = await contract.evaluateTransaction('GetAllAssets');
console.log(`*** Result: ${prettyJSONString(result.toString())}`);
submitTransaction() 函數用於調用鏈碼InitLedger函數以使用一些示例數據填充分類帳。在內部,submitTransaction() 函數將使用服務發現為鏈代碼找到一組所需的背書節點,在所需數量的節點上調用鏈代碼,從這些節點收集鏈代碼背書結果,最后將交易提交給order排序服務。
3.4.2、Java
參考官方文檔。
3.4.3、Go
參考官方文檔。
