1. 程式人生 > >08.Fabric原始碼解析——peer的System Chaincode

08.Fabric原始碼解析——peer的System Chaincode

Fabric原始碼解析8——peer的System Chaincode

綜述

關於System Chaincode,下文中以系統鏈碼稱之。這是個人翻譯,依據是Chaincode本質是註冊儲存到鏈上的一段邏輯程式碼,因此個人習慣稱Chaincode為鏈碼,fabric文件中也變相的稱為智慧合約。但是,因為Chaincode是專用名詞,個人覺得不翻譯而直接使用是最好的。

start.go中的serve函式裡,在為peerServer註冊ChaincodeSupport服務的函式registerChaincodeSupport(peerServer.Server())中,實現了註冊System Chaincode:scc.RegisterSysCCs()。

系統鏈碼的核心程式碼在/fabric/core/common/sysccprovider和/fabric/core/scc下,**scc也就是System Chaincode的縮寫。**系統鏈碼分為五種:cscc,escc,lscc,qscc,vscc,均為各個系統鏈碼的縮寫。系統鏈碼均實現了/fabric/core/chaincode/shim/interfaces.go中定義的Chaincode介面,從此點就可以看出,系統鏈碼也屬於Chaincode,只不過作用稍微特殊一點:

cscc:configuration system chaincode
lscc:lifecycle system chaincode
escc:endorser system chaincode
vscc:validator system chaincode
qscc:querier system chaincode

sysccprovider目錄下的檔案有

sysccprovider.go - 定義系統鏈碼服務提供者介面
scc目錄下的檔案有

sysccapi.go - 系統鏈碼的各種api操作
importsysccs.go - 匯入五種預定義的系統鏈碼
sccproviderimpl.go - 定義了系統鏈碼服務提供者的具體實現和其操作

預定義和註冊

在/fabric/core/scc/importsysccs.go中:

//預定義的五個系統鏈碼存放到陣列中
var systemChaincodes = []*SystemChaincode{
    {
        Enabled:           true,
        Name:              "cscc",
        Path:              "github.com/hyperledger/fabric/core/scc/cscc",
        InitArgs:          [][]byte{[]byte("")},
        Chaincode:         &cscc.PeerConfiger{},
        InvokableExternal: true, // cscc is invoked to join a channel
    },{...},{...},{...},{...},
}

//註冊五個系統鏈碼
func RegisterSysCCs() {
    for _, sysCC := range systemChaincodes {
        RegisterSysCC(sysCC)
    }
}

RegisterSysCCs遍歷systemChaincodes中所有的系統鏈碼,並依次呼叫RegisterSysCC進行註冊。RegisterSysCC在/fabric/core/scc/sysccapi.go中定義:
//系統鏈碼開啟且處於白名單中

if !syscc.Enabled || !isWhitelisted(syscc) {...}

//最終將系統鏈碼註冊到系統中

err := inproccontroller.Register(syscc.Path, syscc.Chaincode)
inproccontroller.Register定義在/fabric/core/container/inproccontroller/inproccontroller.go:

//存放安裝的chaincode,以chaincode所在的path為key
typeRegistry = make(map[string]*inprocContainer)
//註冊到typeRegistry
func Register(path string, cc shim.Chaincode) error {
    tmp := typeRegistry[path]
    if tmp != nil {
        return SysCCRegisteredErr(path)
    }
    typeRegistry[path] = &inprocContainer{chaincode: cc}
    return nil
}

Register函式以系統鏈碼Path成員值為key,包含系統鏈碼的inprocContainer物件為value,將系統鏈碼放入typeRegistry對映中。至此,系統鏈碼註冊完畢。

釋義

以下文字翻譯自Fabric 文件中關於系統鏈碼(System Chaincode)的部分。

系統鏈碼與一般chaincode一樣,有相同的程式設計模型,比不過系統鏈碼是執行在peer程式中,即其是peer程式的一部分,而一般的chaincode是單獨執行在一個容器中的。因此,系統鏈碼是內建在peer程式中且不遵循一般chaincode那樣的生命週期。特別的,install,instantiate和upgrade操作也不應用於系統鏈碼。

系統鏈碼區別與一般的chaincode的目的是縮短grpc在peer結點與chaincode之間通訊的時間消耗(因為peer結點在一個容器,chaincode是單獨的一個容器),並權衡管理上的靈活性。比如,一個系統鏈碼可以僅通過升級peer程式的二進位制包來得到升級。系統鏈碼可以用預定義的元素註冊並編譯到peer程式中,而且不需要有類似於背書策略或背書功能等這樣的冗雜的功能。

系統鏈碼被用在fabric中,去操縱整個系統的配置表現,這樣的話可以隨時把系統改變到合適的狀態。

當前存在的系統鏈碼名單:

LSCC Lifecycle system chaincode,處理生命週期請求。我理解的生命週期請求應該指的是一個chaincode的安裝,例項化,升級,解除安裝等對其生命週期起關鍵作用的一系列操作請求。
CSCC Configuration system chaincode,處理在peer程式端的頻道配置。
QSCC Query system chaincode,提供賬本查詢介面,如獲取塊和交易資訊。
ESCC Endorsement system chaincode,通過對交易申請的應答資訊進行簽名,來提供背書功能。
VSCC Validation system chaincode,處理交易校驗,包括檢查背書策略和版本在併發時的控制。

在修改或替換系統鏈碼時必須注意,特別是LSCC,ESCC和VSCC,因為它們處於重要的交易環節中。以vscc為例,因為區域鏈中的交易資料都是永續性的,因此當vscc在提交一個block到賬本中之前先驗證該塊,這不值什麼,重要的是在同頻道中的所有peer必須計算出相同的證書(由驗證輸出的證書)以避免賬本產生衝突。因此特別需要注意的是vscc被修改或替換時,要避免和以前所產生的交易資料產生衝突。