在 corda ledger 系列教程 4 節點服務(上) 一節中我們梳理了 ServicesForResolution 的成員變量的職責,這一節我們繼續來看服務樞紐 ServiceHub:

corda ledger 系列教程 6 節點服務(下)

一、首先來看 VaultService :

corda ledger 系列教程 6 節點服務(下)

職責很明確,就是爲持久化 state 所服務的,回顧一下教程 corda ledger 系列教程 2 核心概念(上)–與比特幣類比,state 其實類比於比特幣系統中的“幣”,同樣遵循着 UTXO 模型,但是考慮到 corda ledger 是爲了金融業或者銀行業的商業化落地,所以 state 的數據結構可以遠比比特幣複雜,事實上它可以是任意類型的 pojo,這意味着只要你的建模能力能跟得上,它幾乎可以支撐任何業務場景 :)同時 state 也是賬本的一半(另外一半是交易,即下文所要描述的 TransactionStorage ),所以對它的處理顯得尤爲重要。乾脆來看一下這個接口的實現:

corda ledger 系列教程 6 節點服務(下)

看到這裏大家可能會非常驚訝,corda ledger 賬本存儲的技術選型非常友好,關係型數據庫加 orm 框架 hibernate , 這和比特幣的自定義文件系統以及以太坊的 leveldb 很大不同。這裏不比較優劣,但是大家可以自己思考一下幾種持久化方式:文件、關係型數據庫、非關係型數據庫,對比的去體會一下會有更大收穫。

二、TransactionStorage:

corda ledger 系列教程 6 節點服務(下)

在 corda ledger 系列教程 2 核心概念(上)–與比特幣類比 我們也講過,交易參與了整個 state 的演化,即保證了 UTXO 模型在這套分佈式賬本的落實。順藤摸瓜抓一下 TransactionStorage 的實現:

corda ledger 系列教程 6 節點服務(下)

ok,這裏我們看到了非常典型的聲明 entity 的寫法,微服務或者 java 後端的同學都很熟悉。關於詳細的記賬過程我們後面會有教程分析,現在大家有個印象,corda ledger 的底層持久化依賴關係型數據庫(mysql 或 h2 等),並且使用了 orm 框架 hibernate 即可。

三、KeyManagementService

密鑰管理其實是 PKI 體系在 corda ledger 系統的一個集中體現,這裏給大家簡要的回憶一下有關密碼學的知識背景:

  1. 單鑰加密(private key cryptography)加密和解密過程都用同一套密碼

  2. 雙鑰加密(public key cryptography) 在雙鑰加密的情況下,密鑰有兩把,一把是公開的公鑰,還有一把是不公開的私鑰。

  3. 雙鑰加密的原理如下: a) 公鑰和私鑰是一一對應的關係,有一把公鑰就必然有一把與之對應的、獨一無二的私鑰,反之亦成立。 b) 所有的(公鑰 , 私鑰)對都是不同的。 c) 用公鑰可以解開私鑰加密的信息,反之亦成立。 d) 同時生成公鑰和私鑰應該相對比較容易,但是從公鑰推算出私鑰,應該是很困難或者是不可能的。

  4. 在雙鑰體系中,公鑰用來加密信息,私鑰用來數字簽名。 因爲任何人都可以生成自己的(公鑰,私鑰)對,所以爲了防止有人散佈僞造的公鑰騙取信任,就需要一個可靠的第三方機構來生成經過認證的(公鑰,私鑰)對。

corda ledger 系列教程 6 節點服務(下)

聯想到我們之前所說的 doorman , 一個節點想要加入 corda ledger 網絡必須通過它的允許並獲得其頒發的證書,這裏的證書就包含了這個節點的公鑰。這裏附上 corda 網絡許可結構圖:

corda ledger 系列教程 6 節點服務(下)

回到代碼層面上,密鑰對的數據結構如下:

corda ledger 系列教程 6 節點服務(下)

再來抓一下 KeyManagementService 的實現:

corda ledger 系列教程 6 節點服務(下)

邏輯基本明朗,KeyManagementService 主要做了兩件事:

  1. 對本節點的公私鑰進行持久化,以支持節點重啓

  2. 封裝了一些簽名算法

至於 KeyManagementService 如何在啓動的時候加載公私鑰,何時簽名以及簽名的細節,flow 內置的自動化簽名機制,我們還是放到後面的教程描述。

四、ContractUpgradeService

和常規的後端應用不同的是,dapp 由於其自身的特殊性(主要是分佈在不同的節點上),所以一旦 dapp 的版本升級 (如底層 state 模型需要演進),那麼確保每個節點能統一的,平穩升級則變得異常重要。ContractUpgradeService 即誕生於此,但由於涉及到 flow 的工作流,這裏也先放一放。

五、NetworkMapCache 和 NodeInfo

NetworkMapCache 其實是 network map server 的相關信息在本地節點的一個緩存,因此提供了增、刪、改等能力。節點會階段性向 map server 獲取網絡中其他節點的信息,實時的更改本地緩存,這不難理解,eureka 也有類似的動作。

corda ledger 系列教程 6 節點服務(下)

解釋一下,這裏的 sealed 是 kotlin 中獨特的關鍵字,表示 MapChange 是一個密封類。官方文檔解釋:密封類用來表示受限的類繼承結構,當一個值爲有限集中的類型、而不能有任何其他類型時。在某種意義上,他們是枚舉類的擴展:枚舉類型的值集合也是受限的,但每個枚舉常量只存在一個實例,而密封類的一個子類可以有可包含狀態的多個實例。翻譯成白話文就是,MapChange 的子類都提前定義好了,不允許再有其他的子類;但是比枚舉稍微好點,每個子類還是可以有多個實例的。

關鍵的存儲變量在 NetworkMapCache 繼承的接口這裏:

corda ledger 系列教程 6 節點服務(下)

順便看一下 NodeInfo 的數據結構:

corda ledger 系列教程 6 節點服務(下)

可見節點信息包含了節點的網絡地址、Party 和證書、以及平臺版本等。最後,ServiceHub 還使用一個特殊的 Clock 對象用來表示節點的當前時間。

至此關於 ServiceHub 的統籌講解就結束了,有困惑沒有關係,後面我們會針對每個服務和其所在的場景都會有詳細的描述,大家閱讀愉快!

最後,corda ledger 交流羣的人數快滿 500 啦,想加入的抓緊聯繫我;另外爲了滿足同學們的需求,我們也聚集了一批對超級賬本 fabric 感興趣的小夥伴,同樣可以聯繫我加入哦!