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被修改或替換時,要避免和以前所產生的交易資料產生衝突。