淺析Hyperledger Fabric應用開發原理
準備工作
開發環境:Mac + Parallels + Ubuntu 16.04.4 LTS(虛擬機器作業系統)
1、安裝cURL
$ sudo apt install curl
$ curl -V
2、安裝 Docker CE
Hyperledger Fabric系統需要將多個模組分離部署在不同節點上,為了方便演示,通過docker模擬各個節點,因此,需要安裝docker以及相關元件。
Docker CE安裝方法:https://docs.docker.com/install/linux/docker-ce/ubuntu/#upgrade-docker-ce
3、增加一個docker非root使用者
$ sudo groupadd docker
$ sudo usermod -aG docker $USER
$ docker run hello-world
4、安裝Docker Compose元件
$ sudo apt update
$ sudo apt install docker-compose
$ docker --version && docker-compose --version
5、安裝 Node.js
$ curl -sL https://deb.nodesource.com/setup_10.x | sudo -E bash - sudo apt-get install -y nodejs
6、安裝Go Language
$ sudo curl -O https://storage.googleapis.com/golang/go1.9.2.linux-amd64.tar.gz
$ sudo tar -xvf go1.9.2.linux-amd64.tar.gz
$ sudo mv go /usr/local
$ echo 'export PATH=$PATH:/usr/local/go/bin' >> ~/.profile
$ source ~/.profile
$ go version
安裝Hyperledger Fabric Docker映象
$ curl -sSL
https://raw.githubusercontent.com/hyperledger/fabric/master/scripts/bootstrap.sh | bash -s 1.1.0
注意:如果上述命令執行失敗或者卡住,可以先按照下面方式將bootstrap.sh指令碼下載到本地後執行。
$ curl –O https://raw.githubusercontent.com/hyperledger/fabric/master/scripts/bootstrap.sh
$ sudo bash bootstrap.sh –s 1.1.0
$ docker images
下載Hyperledger Fabric示例工程
$ export PATH=$PWD/bin:$PATH
$ git clone https://github.com/hyperledger/fabric-samples.git
(或者:git clone https://gerrit.hyperledger.org/r/fabric-samples)
$ cd fabric-samples/first-network
啟動Hyperledger Fabric測試網路
Hyperledger Fabric安裝完成後,通過docker映象構建一個簡單的測試網路,包含兩個organizations,每個organization包含兩個peers節點,然後共用一個ordering service節點(SOLO模式)。
1、建立網路節點
./byfn.sh generate
Generating certs and genesis block for with channel 'mychannel' and CLI timeout of '10' Continue? [Y/n] y proceeding ... /Users/xxx/dev/fabric-samples/bin/cryptogen ########################################################## ##### Generate certificates using cryptogen tool ######### ########################################################## org1.example.com 2017-06-12 21:01:37.334 EDT [bccsp] GetDefault -> WARN 001 Before using BCCSP, please call InitFactories(). Falling back to bootBCCSP. ... /Users/xxx/dev/fabric-samples/bin/configtxgen ########################################################## ######### Generating Orderer Genesis block ############## ########################################################## 2017-06-12 21:01:37.558 EDT [common/configtx/tool] main -> INFO 001 Loading configuration 2017-06-12 21:01:37.562 EDT [msp] getMspConfig -> INFO 002 intermediate certs folder not found at [/Users/xxx/dev/byfn/crypto-config/ordererOrganizations/example.com/msp/intermediatecerts]. Skipping.: [stat /Users/xxx/dev/byfn/crypto-config/ordererOrganizations/example.com/msp/intermediatecerts: no such file or directory] ... 2017-06-12 21:01:37.588 EDT [common/configtx/tool] doOutputBlock -> INFO 00b Generating genesis block 2017-06-12 21:01:37.590 EDT [common/configtx/tool] doOutputBlock -> INFO 00c Writing genesis block ################################################################# ### Generating channel configuration transaction 'channel.tx' ### ################################################################# 2017-06-12 21:01:37.634 EDT [common/configtx/tool] main -> INFO 001 Loading configuration 2017-06-12 21:01:37.644 EDT [common/configtx/tool] doOutputChannelCreateTx -> INFO 002 Generating new channel configtx 2017-06-12 21:01:37.645 EDT [common/configtx/tool] doOutputChannelCreateTx -> INFO 003 Writing new channel tx ################################################################# ####### Generating anchor peer update for Org1MSP ########## ################################################################# 2017-06-12 21:01:37.674 EDT [common/configtx/tool] main -> INFO 001 Loading configuration 2017-06-12 21:01:37.678 EDT [common/configtx/tool] doOutputAnchorPeersUpdate -> INFO 002 Generating anchor peer update 2017-06-12 21:01:37.679 EDT [common/configtx/tool] doOutputAnchorPeersUpdate -> INFO 003 Writing anchor peer update ################################################################# ####### Generating anchor peer update for Org2MSP ########## ################################################################# 2017-06-12 21:01:37.700 EDT [common/configtx/tool] main -> INFO 001 Loading configuration 2017-06-12 21:01:37.704 EDT [common/configtx/tool] doOutputAnchorPeersUpdate -> INFO 002 Generating anchor peer update 2017-06-12 21:01:37.704 EDT [common/configtx/tool] doOutputAnchorPeersUpdate -> INFO 003 Writing anchor peer update
2、執行測試網路
./byfn.sh up
啟動容器測試網路,然後執行一些基本的測試用例,包括建立channel、加入channel、部署智慧合約、呼叫智慧合約等步驟,具體程式碼實現細節可以參考:
https://github.com/hyperledger/fabric-samples/blob/release-1.2/first-network/scripts/script.sh
啟動成功後的日誌如下:
用例執行結束後的日誌,說明所有用例執行成功:
最後,關閉測試網路並清理環境:
$ ./byfn.sh down
開發一個簡單的應用程式
在fabric-samples中有一個fabcar應用程式,模擬了一個簡單的車輛管理系統,包括建立車輛、交易車輛等操作。應用程式通過智慧合約介面和賬本互動,然後將資訊結果呈現在使用者介面(例如,linux terminal)。
1、fabcar目錄結構:
fabcar應用程式由5個檔案組成,每個檔案完成一個獨立的功能模組,後面會詳細解釋。
# cd fabric-samples/fabcar && ls
enrollAdmin.js
invoke.js
package.json
query.js registerUser.js
startFabric.sh
2、安裝應用客戶端
首先,安裝nodejs開發依賴庫,這個過程可能會出現一些依賴庫安裝失敗,有可能是由於系統中缺少一些基礎庫,可以通過單獨安裝後解決。
$ npm install
3、啟動區塊鏈網路,這個指令碼會先初始化各個網路實體(endorsing peers、ordering service、committing peers等等)並建立關聯channel,然後,部署智慧合約並呼叫初始化方法插入一些車輛資訊。startFabric.sh完成了區塊鏈系統的初始化工作。
$ ./startFabric.sh
4、註冊admin使用者
首先向CA伺服器傳送一個註冊請求,然後獲取認證證書(包括一組公鑰私鑰),後面可以用證書建立一些普通使用者。執行js指令碼後,專案根目錄會生成hfc-key-store
目錄(類似以太坊的keystore檔案),裡面包含證書資訊。
$ node enrollAdmin.js
5、註冊普通使用者user1
通過admin的eCert證書,繼續向CA伺服器傳送註冊請求,建立一個新的普通使用者user1。
$ node registerUser.js
6、查詢賬本資訊
車輛資訊是以key-value形式儲存在賬本中的,key是CAR0、CAR1…車輛編號,value是具體的車輛屬性。通過js指令碼查詢到10條車輛資訊。
# node query.js Successfully loaded user1 from persistence Query has completed, checking results Response is [{"Key":"CAR0", "Record":{"colour":"blue","make":"Toyota","model":"Prius","owner":"Tomoko"}}, {"Key":"CAR1", "Record":{"colour":"red","make":"Ford","model":"Mustang","owner":"Brad"}}, {"Key":"CAR2", "Record":{"colour":"green","make":"Hyundai","model":"Tucson","owner":"Jin Soo"}}, {"Key":"CAR3", "Record":{"colour":"yellow","make":"Volkswagen","model":"Passat","owner":"Max"}}, {"Key":"CAR4", "Record":{"colour":"black","make":"Tesla","model":"S","owner":"Adriana"}}, {"Key":"CAR5", "Record":{"colour":"purple","make":"Peugeot","model":"205","owner":"Michel"}}, {"Key":"CAR6", "Record":{"colour":"white","make":"Chery","model":"S22L","owner":"Aarav"}}, {"Key":"CAR7", "Record":{"colour":"violet","make":"Fiat","model":"Punto","owner":"Pari"}}, {"Key":"CAR8", "Record":{"colour":"indigo","make":"Tata","model":"Nano","owner":"Valeria"}}, {"Key":"CAR9", "Record":{"colour":"brown","make":"Holden","model":"Barina","owner":"Shotaro"}}]
查詢過程只是通過APIs獲取賬本中的資料,並不改變區塊鏈狀態,也不會產生新的區塊。所以,整個過程不需要 endorsing peers、ordering service和committing peers參與。
query.js指令碼通過呼叫fabcar智慧合約的queryAllCars方法,完成查詢動作。
// queryCar chaincode function - requires 1 argument, ex: args: ['CAR4'],
// queryAllCars chaincode function - requires no arguments , ex: args: [''],
const request = {
//targets : --- letting this default to the peers assigned to the channel chaincodeId: 'fabcar',
fcn: 'queryAllCars',
args: ['']
};
// send the query proposal to the peer
return channel.queryByChaincode(request);
fabcar.go智慧合約中的queryAllCars函式查詢從startKey到endKey範圍的value,並打印出來。
func (s *SmartContract) queryAllCars(APIstub shim.ChaincodeStubInterface) sc.Response {
resultsIterator, err := APIstub.GetStateByRange(startKey, endKey)
…
}
fabcar.go智慧合約中包含所有車輛資訊管理介面,例如建立車輛(createCar)、更新車輛顏色(updateCarColor)等等:
7、更新賬本資訊
更新賬本的過程會改變區塊鏈狀態,需要ordering節點將交易資訊打包成區塊,然後發給committing peers節點寫入區塊鏈。
通過invoke.js指令碼呼叫智慧合約的createCar函式建立一輛車,在執行指令碼之前需要按照註釋內容修改一下具體呼叫的函式,具體如下:
// createCar chaincode function - requires 5 args, ex: args: ['CAR12', 'Honda', 'Accord', 'Black', 'Tom'],
// changeCarOwner chaincode function - requires 2 args , ex: args: ['CAR10', 'Barry'], // must send the proposal to endorsing peers var request = {
//targets: let default to the peer assigned to the client
chaincodeId: 'fabcar',
fcn: 'createCar',
args: ['CAR12', 'Honda', 'Accord', 'Black', 'Tom'],
chainId: 'mychannel',
txId: tx_id
};
執行指令碼後,即可建立一條車輛資訊,然後通過query.js指令碼可以查詢到。
$ node invoke.js
總結
通過這個簡單的車輛資訊管理程式,我們可以很直觀的感受到上層應用是如何通過智慧合約與區塊鏈資料庫互動的。首先,最上層的業務邏輯呼叫智慧合約函式介面,然後,智慧合約通過協議層的SDK介面與區塊鏈服務層互動,進行查詢、更新操作,最後,上層應用將處理結果呈現到使用者介面。其實,本質上,底層的區塊鏈系統就是一個黑盒分散式資料庫,同時提供防篡改、資料加密、許可權控制等功能。
通過Hyperledger Fabric框架,開發者可以無需關注底層區塊鏈的技術細節,只關注上層業務邏輯開發即可,極大的簡化了應用開發難度,同時,通過各個模組的分離部署,實現了模組的外掛式管理,更加靈活可靠。