Hyberledger-Fabric 1.00 RPC學習(1)


參考:http://hyperledger-fabric.readthedocs.io/en/latest/write_first_app.html

本文的目的就是基於Hyperledger Fabric network學習第一個application,blockchain上的application最基本的作用就是查詢以及更新賬本。看完本文后,將會對application(使用Node.js的fabric SDK)如何與fabric Ledger進行交互的有一個初步了解。

一.開始一個Test Network

首頁需要確保Hyberledger Fabric所需要的環境已經安裝完成。(安裝可以參考http://www.cnblogs.com/studyzy/p/6973334.html) 

克隆一個fabric-samples倉庫,然后進入fabcar子目錄

git clone https://github.com/hyperledger/fabric-samples.git
cd fabric-samples/fabcar

fabcar目錄下包括用於運行樣例app的腳本以及應用程序,輸入ls,能看到如下文件或文件夾

chaincode    invoke.js       network         package.json    query.js        startFabric.sh

我們使用startFabric.sh啟動網絡,接下來的命令會下載與安裝Fabric docker鏡像

./startFabric.sh

上述命令主要

1.啟動了一個peer節點、一個ordering節點、一個CA以及CLI容器

2.創建了一個channel,同時把peer加入到channel中

3.在peer的文件系統上安裝並實例化了智能合約(chaincode),啟動了一個chaincode容器

4.調用了initLedger函數在channel Ledger上生成了10個car

上述操作由一個組織(organization)或者節點(peer)admin實現。startFaric.sh腳本使用CLI執行上述命令,具體參考Hyperledger Fabric Node SDK repo 

使用docker ps -a命令查看剛啟動的容器。

下圖簡要的說明了,application如何與fabric network進行交互的。

 

 

 

application如何與network進行交互:application使用API去調用智能合約(chaincode),這些chaincode被托管在network中,同時chaincode的名稱與版本是得到認證的。例如,chaincode容器 - dev-peer0.org1.example.com-fabcar-1.0 - ,其中名稱是fabcar,版本是1.0,peer是dev-peer0.org1.example.com

二.查詢Ledger

查詢就是從Ledger上讀取數據,可以通過單鍵值或者多鍵值查詢。假如Ledger使用類似json的富數據存儲方式,那么其支持復雜查詢(例如模糊查詢)。

 

在fabcar目錄下,我們可以使用query.js代碼可以用於查詢在Ledger上的car詳情。

接下來運行JavaScript程序query.js,將會返回在Ledger上的car列表

node query.js

返回值為

Query result count =  1
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"}}]

展示了10輛車,本例中,car1到car9是key值,record是value值。

我們來看看query.js里面有哪些內容,通過vim打開query.js

vim query.js

發現初始化的參數options包括了chaincode ID,channel名稱以及network端點

var options = {
      wallet_path : path.join(__dirname, './network/creds'),
      user_id: 'PeerAdmin',
      channel_id: 'mychannel',
      chaincode_id: 'fabcar',
      network_url: 'grpc://localhost:7051',
}

以下是我們構建的查詢塊

const request = {
   chaincodeId: options.chaincode_id,
   txId: transaction_id,
   fcn: 'queryAllCars',
   args: ['']
}

chaincode_id用於確定具體的chaincode,接下來調用在chaincode中定義的queryAllCars函數。

在我們執行node query.js時,調用了queryAllCars函數用於查詢Ledger。除了queryAllCars函數之外,還有initLedger, queryCar, queryAllCars, createCar 以及 changeCarOwner函數可以調用。

接下來,我們打開fabcar.go,看看queryAllCars函數是如何實現查詢所有car的。

func (s *SmartContract) queryAllCars(APIstub shim.ChaincodeStubInterface) sc.Response {
     startKey := "CAR0"
     endKey := "CAR999"
     resultsIterator, err := APIstub.GetStateByRange(startKey, endKey)
}

該函數使用的fabric shim接口GetStateByRange,用於返回startKey與endKey之間的Ledger數據。這些定義分別被定義為CAR0以及CAR999,因此理論上我們可以創建1000輛車,一個queryAllCars函數即可查詢所有車輛信息。

下圖表示一個app是如何調用不同的chaincode的函數。

 

其中createCar用於更新Ledger,同時最終增加了一個新的block到鏈上。

回到查詢功能上,讓我們回到query.js程序,同時我們將代碼中的queryAllCars改成queryCar,同時對key值進行修改,這里key值暫時使用CAR4,query.js將會包括如下代碼:

const request = {
      chaincodeId: options.chaincode_id,
      txId: transaction_id,
      fcn: 'queryCar',
      args: ['CAR4']
}

輸入node query.js后將會查出如下結果:

{"colour":"black","make":"Tesla","model":"S","owner":"Adriana"}

本次查詢只查詢一輛車,調用了queryCar函數,通過key值去查詢。

三.更新Ledger

上面我們調用chaincode的查詢函數對車輛信息進行了查詢,接下來,我們需要嘗試對Ledger進行修改。

首先application先生成一個transaction proposal。就想query的request的一樣,這里也需要生成一個request。程序接下來調用channel.SendTransactionProposal API 把transaction proposal發送到endoring peer。

接着,network(也就是endorsing peer)會返回一個proposal response,application通過這個response對transaction request進行build與sign。然后把這個處理過的request通過channel.sendTransaction API發送至ordering serivce。ordering service將會把transaction打包至到block,接着把block發送到channel中的所有peer做驗證。 

最后,application使用eh.setPeerAddr API  連接到peer的事件監聽端口,同時調用eh.registerTxEvent方法並使用具體的transactionID注冊事件。該API使得application能夠追蹤到transaction的具體情況(提交成功還是失敗)。其實就是一個通知機制。 

通過執行invoke.js我們創建了一個新的asset(一輛車)。打開invoke.js,我們能夠找到類似query.js中的request。

vim invoke.js

能夠看到request內容

// createCar - requires 5 args, ex: args: ['CAR11', 'Honda', 'Accord', 'Black', 'Tom'],
// changeCarOwner - requires 2 args , ex: args: ['CAR10', 'Barry'],
// send proposal to endorser
var request = {
    targets: targets,
    chaincodeId: options.chaincode_id,
    fcn: '',
    args: [''],
    chainId: options.channel_id,
    txId: tx_id
}

接下來,我們將調用createCar 或 changeCarOwner生成一個新的車。參數如下所示

var request = {
    targets: targets,
    chaincodeId: options.chaincode_id,
    fcn: 'createCar',
    args: ['CAR11’, ‘Audi’, ‘A4’, ‘Black’, ‘Xiaohu Li’],
    chainId: options.channel_id,
    txId: tx_id
}

輸入node invoke.js能夠看到

 

peer發出了該事件通知,我們的application通過eh.registerTxEvent API收到了該通知。接下來,我們回到query.js,修改查詢key值為CAR11,然后執行代碼。

node query.js

接下來我們能夠看到如下信息:

 

說明我們剛創建的車輛信息已經寫入Ledger中了。

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM