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