使用Node.js開發Hyperledger Fabric Chaincode

買賣虛擬貨幣
Hyperledger Fabric術語中的Chaincode是什麼?在Hyperledger Fabric中,Chaincode是在網路peer上執行的一段程式碼,用於實現應用程式如何與分類帳互動的業務邏輯。提出交易時,它會觸發Chaincode,該Chaincode決定應將哪種狀態更改應用於分類帳。因此為了在Hyperledger Fabric上開發去中心化的應用程式,必須編寫稱為Chaincode的應用程式邏輯。
Chaincode可以使用Go,Nodejs,Java編寫。其他兩種語言相比,Node.js是一種更容易理解和使用的語言。由於Node.js文件中可用的資訊非常少,但編寫和部署Node.js Chaincode並不困難。因此我決定編寫一些Node.js Chaincode的概念,並逐步編寫和部署簡單的Chaincode。Hyperledger Fabric資料庫在深入研究Chaincode之前,首先讓我們看一下Hyperledger Fabric Network中資料的儲存位置。Hyperledger Fabric使用鍵值資料庫儲存其狀態。預設情況下,Fabric使用LevelDB。該資料庫儲存可以使用其鍵查詢的特定物件的二進位制資料。與傳統的資料庫不同,區塊鏈資料庫位於網路的每個peer上。因此它被稱為分散網路。
除了LevelDB,還有另一個用於Hyperledger Fabric的資料庫稱為CouchDB。CouchDB是可選的替代外部可插拔狀態資料庫。與LevelDB鍵值儲存一樣,CouchDB可以儲存以鏈碼建模的任何二進位制資料。但作為JSON文件儲存,當將Chaincode值(例如資產)建模為JSON資料時,CouchDB還可以對Chaincode資料進行豐富的查詢。 Chaincode元件1.fabric-contract-api:用於實現智慧合約的高階合約API(作為npm模組提供)2.fabric-shim:用於實現智慧合約的低階合約API(作為npm模組提供)
我們可以將fabric-shim視為fabric-contract-api的遞減版本。對新版本的fabric使用高階API是一個好習慣。但是fabric-contract-api可以完成shim可以做的所有事情。當然不止如此。3.stub:它是fabric-contract-api中的介面,用於訪問和修改分類帳(資料庫狀態)。因此它是主要資料Chaincode介面,用於在分類賬上讀寫資料,我們如何讀寫資料?讓我們看一下Stub介面中的一些常用方法Stub介面中的常用方法1.getState(k):眾所周知,Hyperledger Fabric資料庫以鍵值對的形式儲存資料。
此方法從分類帳讀取資料。它以輸入“ k”作為鍵,並返回與鍵“ k”關聯的二進位制值。2.putState(k,v):此方法將資料寫入分類帳。它以“ k”為鍵,“ v”為值。明確地說,假設我們想將Alice的年齡儲存到分類帳中,我們可以將Alice作為鍵,並將AGE作為值。3.deleteState(k):此方法從分類賬中刪除關聯金鑰“ k”的值。4.getStateByRange(k1,k9):
此方法在分類帳中的一組鍵上返回範圍迭代器。它將迭代startKey(k1)和endKey(k9)並返回這兩個鍵之間的所有鍵值。這類似於javascript中的for迴圈。假設如果我們已經按鍵k1,k2,k3…k99的順序儲存了一些使用者資料,則可以使用此方法簡單地獲取所有這些值的狀態。5.getTxID():此方法返回被呼叫事務的事務ID。交易ID對於鏈上的每個交易都是唯一的。因此交易ID在跟蹤交易中起著至關重要的作用。6.getTxTimestamp():此方法返回建立事務時的時間戳。這是從交易ChannelHeader獲取的,因此它將指示客戶的時間戳,並且在所有背書人中都具有相同的值。編寫您的第一個Chaincode
您已經瞭解了在node.js中編寫鏈碼的一些先決條件。因此就目前而言,您可能會非常興奮地編寫您的第一個chaincode。由於我們要用Nodejs編寫Chaincode,因此我們首先需要建立傳統的npm東西,例如package.json和index.js。如果您不知道此package.json。列出您的專案所依賴的軟體包使用語義版本控制規則指定專案可以使用的軟體包的版本使您的構建具有可複製性,因此更易於與其他開發人員共享.簡而言之,我們的Chaincode取決於fabric-contract-api和fabric-shim模組。我們在package.json中提到了這些軟體包和版本。
我們還將新增fabric-chaincode-node start作為我們的啟動指令碼,這是在peer節點上安裝chaincode所需的。這是我們的package.json:{    "name": "Test-Chaincode",    "version": "1.0.0",    "description": "my first exciting node.js chaincode on Hyperledger-fabric",
    "main": "index.js",    "engines": {        "node": ">=8",        "npm": ">=5"    },    "scripts": {
        "lint": "eslint .",        "pretest": "npm run lint",        "test": "nyc mocha --recursive",        "start": "fabric-chaincode-node start"    },    "engineStrict": true,
    "author": "Hyperledger",    "license": "Apache-2.0",    "dependencies": {        "fabric-contract-api": "~1.4.0",        "fabric-shim": "~1.4.0"    },
    "devDependencies": {        "chai": "^4.1.2",        "eslint": "^4.19.1",        "mocha": "^5.2.0",        "nyc": "^12.0.2",        "sinon": "^6.0.0",
        "sinon-chai": "^3.2.0"    },    "nyc": {        "exclude": [            "coverage/**",            "test/**"
        ],        "reporter": [            "text-summary",            "html"        ],        "all": true,
        "check-coverage": true,        "statements": 100,        "branches": 100,        "functions": 100,        "lines": 100    }
}如果您可以仔細觀察程式碼,則有一行“ main”:“ index.js”。這意味著什麼—在啟動時(安裝chaincode期間),npm模組用於檢查index.js並在peer節點上安裝提到的合約。”因此我們的index.js包含作為模組匯出的合約。這是我們的index.js檔案:'use strict';const testContract = require(’./logic’);module.exports.contracts = [ testContract ];
智慧合約:我們的業務邏輯是什麼?新增,檢索和刪除學生標記。1.新增標記涉及將資料寫入分類帳。因此我們將從chaincode的stub介面使用putState(k,v)方法。2.檢索標記涉及從分類帳讀取資料。因此我們需要使用getState(k)方法。3.刪除標記涉及刪除資料。因此我們需要使用deleteState(k)方法。
chaincode首先從fabric-contract-api模組引入作用域金鑰類Contract。此類將用於編寫邏輯,所有chaincode函式都應使用This庫類。const { Contract}=require(’fabric-contract-api’); class testContract extends Contract {//Functions go here}新增標記:
我們將建立一個JavaScript物件來儲存每個學科中學生的成績,並將該物件儲存為一個值,並將StudentId儲存為一個鍵。透過伺服器將資料傳送到資料庫時,資料必須是字串。因此我們需要使用JSON.stringify()方法將此標記物件轉換為字串,並應用緩衝區以二進位制資料的形式傳送到資料庫。async addMarks(ctx,studentId,subject1,subject2,subject3) {     let marks={     subj1:subject1,      subj2:subject2,     subj3:subject3 
     }; await  ctx.stub.putState(studentId,Buffer.from(JSON.stringify(marks))); console.log(’Student Marks added To the ledger Succesfully..’); }刪除標記async deleteMarks(ctx,studentId) {
 await ctx.stub.deleteState(studentId); console.log(’Student Marks deleted from the ledger Succesfully..’);    }查詢學生成績:由於我們在先前的addMarks()函式中將值以緩衝區的形式放置。一旦查詢,它將返回buffer。因此我們需要將緩衝區轉換為字串並將其解析為原始javascript物件。async queryMarks(ctx,studentId){
     let marksAsBytes = await ctx.stub.getState(studentId);      if (!marksAsBytes || marksAsBytes.toString().length <= 0) {        throw new Error(’Student with this Id does not exist: ');          }     let marks=JSON.parse(marksAsBytes.toString());     return JSON.stringify(marks); 
   }最終版智慧合約程式碼您可以在此處找到完整的智慧合約。https://gist.github.com/Salmandabbakuti/fb25d0429359c6d77ab64d097c5b588c'use strict';const { Contract} = require('fabric-contract-api');class testContract extends Contract {
async queryMarks(ctx,studentId) {    let marksAsBytes = await ctx.stub.getState(studentId);     if (!marksAsBytes || marksAsBytes.toString().length <= 0) {      throw new Error('Student with this Id does not exist: ');       }      let marks=JSON.parse(marksAsBytes.toString());
      return JSON.stringify(marks);  }async addMarks(ctx,studentId,subject1,subject2,subject3) {   let marks={       subj1:subject1,       subj2:subject2,
       subj3:subject3       };    await ctx.stub.putState(studentId,Buffer.from(JSON.stringify(marks)));     console.log('Student Marks added To the ledger Succesfully..');  }async deleteMarks(ctx,studentId) {
    await ctx.stub.deleteState(studentId);     console.log('Student Marks deleted from the ledger Succesfully..');    }}module.exports=testContract;為了安裝和測試此智慧合約,我將使用包含單個peer的基本網路。在這個網路上,我們將安裝名為mycc的Node.js的chaincode到peer0.org1.example.com上,並在通道mychannel上例項化它。然後我們可以呼叫這些chaincode函式。確保在您的設定中安裝了docker。為了簡單起見,我已經將chaincode檔案(logic.js,index.js,package.json)安裝在chaincode/newcc目錄中。
首先,我們需要啟動網路並建立通道。git clone https://github.com/Salmandabbakuti/hlf-chaincodeTest.gitcd hlf-chaincodeTest/basic-network./start.sh等待片刻。建立網路將需要一段時間。如果遇到任何許可權錯誤,只需在root使用者許可權下執行就行。一旦我們的具有單個peer的網路建立並執行,我們就可以安裝chaincode。為了安裝和呼叫chaincode,我們可以使用Peer的CLI容器。輸入CLI容器
docker exec -it cli bash安裝和例項化Chaincodepeer chaincode install -n mycc -v 1.0 -p "/opt/gopath/src/github.com/newcc" -l "node"peer chaincode instantiate -o orderer.example.com:7050 -C mychannel -n mycc -l "node" -v 1.0 -c '{"Args":[]}'增加學生標誌peer chaincode invoke -o orderer.example.com:7050 -C mychannel -n 
mycc -c '{"function":"addMarks","Args":["Alice","68","84","89"]}'查詢學生“Alice”的標誌peer chaincode query -o orderer.example.com:7050 -C mychannel -n mycc -c '{"function":"queryMarks","Args":["Alice"]}'從Ledger刪除“Alice”標誌peer chaincode invoke -o orderer.example.com:7050 -C mychannel -n 
mycc -c '{"function":"deleteMarks","Args":["Alice"]}'上面的指令碼將從賬本中刪除金鑰“ Alice”和相關資料。如果再次查詢Alice的標記,則會收到一條錯誤訊息,提示“ studentId不存在”。我還製作了一個自動化指令碼,用於在客戶端目錄中安裝和測試此chaincode。請按照以下步驟進行快速演示首先,退出CLI容器並在客戶端目錄中執行指令碼exit # exits from CLI docker container if you're incd ..
cd client  #change your directory to clientchmod a+x start.sh./start.sh  #Automated script for testing您也可以使用client / start.sh檔案中定義的指令碼手動呼叫chaincode函式。結論我們在這裡演示了什麼是Chaincode,chaincode的stub介面中的方法,chaincode的部署結構以及編寫chaincode和在網路上進行部署的難易程度。希望本文能以某種方式幫助您開始編寫chaincode並在網路上進行部署。

免責聲明:

  1. 本文版權歸原作者所有,僅代表作者本人觀點,不代表鏈報觀點或立場。
  2. 如發現文章、圖片等侵權行爲,侵權責任將由作者本人承擔。
  3. 鏈報僅提供相關項目信息,不構成任何投資建議

推荐阅读

;