基於區塊鏈技術的超級賬本(Hyperledger) - 從理論到實戰


什么是區塊鏈?簡單來說區塊鏈就是一個分布式的記賬本,或者分布式的數據庫。

區塊鏈的數據結構是一個鏈表,交易數據被存儲到鏈表的區塊中,區塊鏈的第一個區塊叫創世區塊,除了創世塊以外,每個區塊還包含前一個區塊的哈希指針,這個哈希指針的值是根據前一個區塊的實際數據計算出來的。哈希指針指向前一個區塊,后面的區塊可以查找前面所有區塊的信息。

賬本的數據結構就是這樣的一個鏈表,那么分布式的含義是什么呢?

區塊鏈的眾多參與者組成了一個松散自治的 P2P 網絡,我們把區塊鏈網絡的參與者叫做節點,每個節點都擁有一個賬本拷貝,所有賬本的信息都是一致的,在區塊鏈里沒有中心節點。每當有新的交易進來,所有節點的賬本都會更新,並且最終保持一致。更新的方式不是去修改某個區塊的值,而是保存交易記錄。比如在比特幣系統中,它沒有用戶資產記錄這樣的概念,不像普通數據庫那樣用一條數據存儲資產,比特幣用戶資產的值是通過把所有的交易記錄串聯聚合后得到的,賬戶里資產的來源可以一直向上追溯,直到創世塊為止。區塊鏈里的交易數據根據具體場景,可以是任何需要記錄的信息。

智能合約

為了支持信息的持續更新,以及對賬本進行管理(寫入交易,進行查詢等),區塊鏈網絡引入了智能合約來實現對賬本的訪問和控制。智能合約不僅僅可用於在區塊鏈網絡中打包信息,它們也可以被用於自動的執行由參與者定義的特定交易操作。

比如智能合約可以規定物流中的運輸費用,根據物流的快慢收取不同的費用,根據貨物的到達時間進行自動轉賬等。上傳到區塊鏈網絡中的的智能合約會被打包到某一個區塊中,因此智能合約一旦寫入區塊鏈,也是不可更改的。

共識機制

區塊鏈網絡中交易信息同步的過程,確保交易只有獲得適當參與者批准后才更新,所有的參與者都會將同樣的信息按照同樣的順序更新,這樣的過程叫做共識。共識機制是區塊鏈的核心之一。

區塊鏈的第一個應用比特幣,采用的是Proof of Work(工作量證明)的共識機制。簡單介紹一下比特幣的共識機制,算法的具體細節大家可以去查白皮書。節點收到一個交易后,會根據判斷標准對該交易進行有效性校驗,無效的交易會被廢棄。通過有效性驗證之后的交易將會被廣播給其他節點。其他節點會做同樣的獨立校驗,當有效的交易達到整個網絡所有節點時,即全網達成了“該交易有效”的共識。每個節點都會收到很多有效但是還未被打包到區塊中的交易,這些交易被組裝成 Merkle Tree,Merkle Tree 的第一個交易比較特殊,叫做 coinbase,由節點自己創建,將挖礦獎勵支付到礦工自己的地址。挖礦獎勵包括新創建的比特幣和打包進該區塊所有交易的手續費總額。然后節點計算一個符合難度的哈希值,挖礦就是通過修改參數不斷計算區塊哈希值,直至達到難度要求,也就間接證明了該節點付出了對應的工作量,這就是工作量證明。筆者的另一篇文章300行ABAP代碼實現一個最簡單的區塊鏈原型里用了一個 ABAP 方法CL_ABAP_MESSAGE_DIGEST=>CALCULATE_HASH_FOR_CHAR 來計算區塊的哈希值。

當節點計算出一個符合難度的區塊哈希時,即說明該礦工挖礦成功了,該節點將該區塊組裝到本地的區塊鏈,同時也將此區塊廣播給其他節點。其他節點接收到該區塊后會驗證該區塊是否有效,有可能有兩個節點同時挖出了新的區塊 B1 和 B2,它們的上一個區塊都是同一個區塊 P。有的節點可能會先收到 B1,有的會先收到 B2,這時區塊鏈出現了暫時性的兩個分叉。要打破這種局面,要看下一個區塊是基於 B1 生成還是基於 B2 生成。如果基於 B1,B1 這條鏈就變成了最長鏈,其他包含 B2 的節點會重新選擇最長鏈,而 B2 作為孤塊被丟棄掉。

到目前為止,我們可以將區塊鏈看做是一個共享的,去中心化的多備份系統,通過智能合約更新交易數據,同時借助共識的協作流程使網絡中所有的節點保持一致。

這里的交易可以指代任何數據,例如:數字貨幣,合同,記錄或者其它任何信息。

區塊鏈的類型

  • 公有鏈:網絡中的節點可以任意接入,網絡中數據讀寫權限不受限制,所有節點都參與共識過程。比特幣,以太坊等數字貨幣都屬於公有鏈。

  • 私有鏈:網絡中的節點被一個組織控制,由其獨享該區塊鏈的寫入權限,私有鏈和其他的分布式存儲沒有太大區別。

  • 聯盟鏈:多個公司或組織通過授權接入,由某些節點參與共識過程。Hyperledger Fabric屬於聯盟鏈。

什么是 Hyperledger Fabric?

Hyperledger Fabric 是 Linux 基金會發起的 Hyperledger 項目之一。Hyperledger Fabric 專為在企業環境中使用而設計的開源的基於區塊鏈的分布式賬本。Hyperledger Fabric 可用於全球供應鏈管理、金融交易、資產記賬、人力資源、保險、健康和數字音樂等領域。

Hyperledger Fabric 中的賬本子系統(ledger)包括兩個組件:世界觀(world state)和事務日志(transaction log)。世界觀記錄了賬本在特定時間點的現狀,是一個鍵值數據庫。交易日志記錄產生世界狀態當前值的所有交易,是世界觀的更新歷史。賬本的世界觀的底層數據庫可以更換,可以選擇使用 levelDB 或 couchDB。

Hyperledger Fabric 是第一個支持以通用語言編寫智能合約的區塊鏈平台,可以使用java,nodejs 和 go 語言來編寫智能合約。Hyperledger Fabric 中的智能合約也叫鏈碼(chain code)。

和其他公有區塊鏈平台最大的不同,Hyperledger Fabric 是私有的並且需要授權才能接入,它擁有一個 MSP(Membership Service Provider) 模塊專門提供成員管理服務。

CA(Certificate Authority) 負責權限管理,成員身份相關證書管理 (Enrollment CertificateAuthority) 和維護交易相關證書管理 (Transaction Certificate Authority) 等等。

Hyperledger Fabric 提供了建立 channel 的功能,這允許參與者為交易新建一個單獨的賬本。當網絡中的一些參與者是競爭對手時,這個功能變得尤為重要。因為這些參與者並不希望所有的交易信息——比如提供給部分客戶的特定價格信息——都對網絡中所有參與者公開。只有在同一個 channel 中的參與者,才會擁有該 channel 中的賬本,而其他不在此 channel 中的參與者則看不到這個賬本。

Hyperledger Fabric 使用獨立的排序節點(order)來提供共識服務,負責排序交易,提供全局確認的交易順序。

應用程序通過 SDK 訪問 Hyperledger Fabric。

最新版 Hyperledger Fabric 的設計中,根據功能將節點角色解耦開,讓不同節點處理不同類型的工作負載。從業務邏輯上又將節點分為背書節點(Endorser)和提交節點(Committer)。

  • Endorser peer:負責對來自客戶端的交易進行合法性和權限檢查(模擬交易),通 過檢查則簽名並返回結果給客戶端。

  • Committer peer:負責維護賬本,將達成一致順序的批量交易結果進行狀態檢查,生成區塊,執行合法的交易,並寫入賬本,同一個物理節點可以同時擔任 endorser 和committer 兩個角色。

Hyperledger Fabric 交易流程:共識

共識流程主要分 Proposal,Packaging 和 Validation 三個階段。

Proposal

應用提交一個交易 proposal,然后將其提交給所有的背書節點,后者接到后,將其作為輸入執行鏈碼生成相應的交易 proposal 響應。此時並不會更新 Ledger,而是對交易proposal 響應簽名,並將其返回給應用。應用收到簽名后的響應,共識流程的第一階段就完成了。

Packaging

這個階段是 order 節點對交易進行排序打包。Order 節點從各個應用接收交易 proposal響應,然后對這些交易進行排序,排序之后打包成區塊。

Validation

共識流程的最后一個階段,由 order 節點將區塊分發給所有和它連接的節點,這些節點將確認區塊中的交易都經過背書節點簽名,然后將確認后的區塊更新到 ledger 中。

整個流程稱為共識,所有節點都已對交易內容和順序達成一致,這一過程由 order 節點控制。 共識是一個多步驟的過程,只有在整個流程完成時才會更新賬本 ,可能每個節點的更新時間稍有不同。

構建一個 Hyperledger Fabric 平台絕非易事,既需要硬件基礎設施的投入,也需要全方位的開發和運營管理(DevOps)。除了平台本身,一套完整的解決方案,還包括設備接入,訪問控制,服務監控等管理功能。

SAP Cloud Platform(下文簡稱 SCP )提供了開箱即用的 Hyperledger Fabric Service,為開發者提供了強大的服務支持:

  • 直觀友好的可視化監控與操作界面,幫助開發者按需申請區塊鏈網絡,創建管理節點、渠道,而無需考慮底層硬件資源。

  • 簡單易用的智能合約開發與測試環境,方便開發者對應用代碼進行管理。

  • 安全,隱私性方面的保障,並對相關資源進行了性能優化。

下面是具體的實戰步驟,該步驟使用 go 語言開發一組微服務,這組微服務包含讀和寫兩個API,能夠將數據寫入架設於 SAP 雲平台上的超級賬本服務。

簡單地說,應用程序通過智能合約接口同超級賬本進行讀寫操作。我們將開發一個 Hello World 的智能合約,部署到 SAP 雲平台上。出於簡單起見,我們沒有開發應用,而是簡單地在 SAP 雲平台的 API 控制台上直接消費這個 Hello World 的智能合約,對雲平台上的超級賬本進行讀和寫。

打開超級賬本項目 Fabric 的 github 倉庫地址:

https://github.com/hyperledger/fabric

發現 Fabric 項目是 Google 的編程語言 GoLang 開發的,因此咱們這個練習也使用 Go 語言來進行智能合約的開發。

  1. 從 Google 網站上將 Go 語言 1.11 版的二進制包下載到本地,解壓到 /usr/local 目錄下:

sudo tar -C /usr/local -xzf /home/vagrant/Downloads/go1.11.linux-amd64.tar.gz

將該目錄配置到環境變量 PATH 中去:

  1. Fabric 項目已經將智能合約同超級賬本的通信封裝到一個名叫 shim 的接口中,我們只需要在我們編寫的智能合約代碼中直接調用該 shim 接口即可。

我們使用 import 將這個 shim 接口的依賴引入進來,在第14行定義一個結構體,包含 ID 和 Value 兩個字段。這個結構體即是待寫入超級賬本的數據結構,ABAP 顧問可以將其視為 ABAP 數據字典里定義的結構體。

第46行定義的方法 Invoke 是這個最簡單的智能合約的核心代碼,cc *MessageStore 這個語法和 C 語言很像,定義了一個類型為 MessageStore 的指針變量 cc。這個指針變量同 C++ 的 this 指針和 ABAP 的 me 引用作用類似,在方法被調用時,指向了方法的調用者。

Invoke 后面括號里的 stub shim.ChaincodeStubInterface 定義了該方法的輸入參數(形參)stub, 類型為 shim.ChaincodeStubInterface。

這個 Invoke 方法不會通過應用程序顯式調用,而是通過超級賬本程序回調:當方法被調用時,指針 cc 和輸入參數 stub 已經自動被 Fabric 框架賦上了對應值。在 Invoke 方法運行的上下文里,通過輸入參數 stub 判斷出當前回調的場景是讀還是寫,然后進入對應的分支。分支內部調用我們自己開發的 write 和 read 方法同超級賬本進行交互。

這種通過同一個回調函數內部的 switch case 來處理多個場景的做法,ABAP 和 Java 開發者應該都不陌生。比如下圖是通過 InvocationHandler 實現 Java 動態代理的例子,其中 invoke 方法的邏輯結構和本文智能合約代碼的結構非常相似。

關於 ABAP 和 Java 里各種靜態代理和動態代理的寫法,請參考我的博客:

Various Proxy Design Pattern implementation variants in Java, ABAP and JavaScript

  1. 將開發好的智能合約源文件構建成可執行文件。這一步確保在部署智能合約到 SAP 雲平台之前,先在本地開發環境將所有潛在錯誤全部檢測出並修復。

  1. 登錄 SAP 雲平台,在 Service Marketplace 里點擊 Hyperledger Fabric 的超鏈接:

創建一個新的 Service 實例:

創建過程中需要填寫 channel 的 ID 和密匙。

區塊鏈分為公有鏈,私有鏈和聯盟鏈,而超級賬本屬於聯盟鏈。在聯盟鏈里,有一個專門的稱為 MSP(Membership Service Provider)的模塊,提供成員管理服務,只有授權用戶才能接入區塊鏈網絡。這里我事先在 SAP 雲平台上創建了一個渠道並進行認證,因此此處直接輸入一個合法的渠道 ID 和密匙。關於 SAP 雲平台上超級賬本渠道的創建和成員授權接入的步驟,請參考這篇 SAP 幫助文檔

Service 實例創建完畢后,點擊 Create Service Key 按鈕創建 key,目的是生成用於OAuth 認證的 clientId 和 clientSecret,方便接下來的 API 調用。

點擊 Service 實例的 Referencing Apps 面板,點擊按鈕 Open Dashboard:

點擊 Deploy Chaincode,選擇本地構建好的 zip 包,進行上傳並部署。這個按鈕同 SAP 雲平台 CloudFoundry 環境部署本地應用的邏輯相同。

部署成功后,點擊 Test Chaincode 超鏈接進入 API 控制台。

該控制台集成了 Swagger 框架,在調用 post 請求進行超級賬本的寫操作和 get 請求進行讀操作之前,先要點擊 Authorize 按鈕進行身份認證:

輸入第四步創建 Service Key 后生成的 clientID 和 clientSecret 進行認證:

認證成功后,可以在 Swagger 的控制台里調用 post 和 get 請求了。

首先發送 post 請求,請求負載就是一個簡單的 json 對象,id 為 i042416,value 為Hello World:

post 請求在 SAP 雲平台上的超級賬本執行成功,返回 200 響應碼:

緊接着執行 get 請求,輸入剛才寫入的數據 id: i042416:

get 請求能夠將之前通過 post 請求寫入賬本的數據成功讀出來:

登錄 SAP 雲平台超級賬本控制台,能看到之前通過 post 寫入的數據已經加入到區塊鏈尾部的區塊了。點擊區塊可以查看數據明細:

在超級賬本控制台的 API Calls 和 Logs 面板里也能看到每次超級賬本讀寫的詳細信息。


總結

SAP 雲平台的超級賬本服務,成功地幫助了希望使用這項區塊鏈技術的企業避免了硬件基礎設施的投入,同時屏蔽了大部分超級賬本平台管理的底層細節。通過 SAP 雲平台提供的控制台,即可實現對超級賬本進行設備接入,訪問控制,服務監控等管理功能。同時,通過 Go 語言編寫的智能合約一旦部署到 SAP 雲平台,生成的 Restful API 能夠被其他編程語言方便地消費。調用這些 API 寫入超級賬本區塊鏈中的數據將無法再被篡改。使用 SAP 雲平台的超級賬本服務,應用開發人員可以無需將過多精力花費在超級賬本體系架構本身,從而能夠專注於應用邏輯的編寫上去。


免責聲明!

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



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