区块链教程Fabric1.0源代码分析Chaincode(链码)体系总结
生活随笔
收集整理的這篇文章主要介紹了
区块链教程Fabric1.0源代码分析Chaincode(链码)体系总结
小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.
Fabric 1.0源代碼筆記 之 Chaincode(鏈碼)
1、Chaincode概述
Chaincode,即鏈碼或智能合約,代碼分布在protos/peer目錄、core/chaincode和core/common/ccprovider目錄,目錄結構如下:
- protos/peer目錄:
????* chaincode.pb.go,ChaincodeDeploymentSpec、ChaincodeInvocationSpec結構體定義。 - core/chaincode目錄:
???? platforms目錄,鏈碼的編寫語言平臺實現(xiàn),如golang或java。
???????? platforms.go,Platform接口定義,及部分工具函數(shù)。
???????? java目錄,java語言平臺實現(xiàn)。
???????? golang目錄,golang語言平臺實現(xiàn)。 - core/common/ccprovider目錄:ccprovider相關實現(xiàn)。
2、protos相關結構體定義
2.1、ChaincodeDeploymentSpec結構體定義(用于Chaincode部署)
2.1.1 ChaincodeDeploymentSpec結構體定義
type ChaincodeDeploymentSpec struct {ChaincodeSpec *ChaincodeSpec //ChaincodeSpec消息EffectiveDate *google_protobuf1.TimestampCodePackage []byte //鏈碼文件打包ExecEnv ChaincodeDeploymentSpec_ExecutionEnvironment //鏈碼執(zhí)行環(huán)境,DOCKER或SYSTEM }type ChaincodeDeploymentSpec_ExecutionEnvironment int32const (ChaincodeDeploymentSpec_DOCKER ChaincodeDeploymentSpec_ExecutionEnvironment = 0ChaincodeDeploymentSpec_SYSTEM ChaincodeDeploymentSpec_ExecutionEnvironment = 1 ) //代碼在protos/peer/chaincode.pb.go2.1.2、ChaincodeSpec結構體定義
type ChaincodeSpec struct {Type ChaincodeSpec_Type //鏈碼的編寫語言,GOLANG、JAVAChaincodeId *ChaincodeID //ChaincodeId,鏈碼路徑、鏈碼名稱、鏈碼版本Input *ChaincodeInput //鏈碼的具體執(zhí)行參數(shù)信息Timeout int32 }type ChaincodeSpec_Type int32const (ChaincodeSpec_UNDEFINED ChaincodeSpec_Type = 0ChaincodeSpec_GOLANG ChaincodeSpec_Type = 1ChaincodeSpec_NODE ChaincodeSpec_Type = 2ChaincodeSpec_CAR ChaincodeSpec_Type = 3ChaincodeSpec_JAVA ChaincodeSpec_Type = 4 )type ChaincodeID struct {Path stringName stringVersion string }type ChaincodeInput struct { //鏈碼的具體執(zhí)行參數(shù)信息Args [][]byte } //代碼在protos/peer/chaincode.pb.go2.2、ChaincodeInvocationSpec結構體定義
type ChaincodeInvocationSpec struct {ChaincodeSpec *ChaincodeSpec //參考本文2.2IdGenerationAlg string } //代碼在protos/peer/chaincode.pb.go3、ccprovider目錄相關實現(xiàn)
3.1、ChaincodeData結構體
type ChaincodeData struct {Name stringVersion stringEscc stringVscc stringPolicy []byte //chaincode 實例的背書策略Data []byteId []byteInstantiationPolicy []byte //實例化策略 }//獲取ChaincodeData,優(yōu)先從緩存中讀取 func GetChaincodeData(ccname string, ccversion string) (*ChaincodeData, error) //代碼在core/common/ccprovider/ccprovider.gofunc GetChaincodeData(ccname string, ccversion string) (*ChaincodeData, error)代碼如下:
var ccInfoFSProvider = &CCInfoFSImpl{} var ccInfoCache = NewCCInfoCache(ccInfoFSProvider)func GetChaincodeData(ccname string, ccversion string) (*ChaincodeData, error) {//./peer/node/start.go:?ccprovider.EnableCCInfoCache()//如果啟用ccInfoCache,優(yōu)先從緩存中讀取ChaincodeDataif ccInfoCacheEnabled { return ccInfoCache.GetChaincodeData(ccname, ccversion)}ccpack, err := ccInfoFSProvider.GetChaincode(ccname, ccversion)return ccpack.GetChaincodeData(), nil } //代碼在core/common/ccprovider/ccprovider.go3.2、ccInfoCacheImpl結構體
type ccInfoCacheImpl struct {sync.RWMutexcache map[string]*ChaincodeData //ChaincodeDatacacheSupport CCCacheSupport }//構造ccInfoCacheImpl func NewCCInfoCache(cs CCCacheSupport) *ccInfoCacheImpl //獲取ChaincodeData,優(yōu)先從c.cache中獲取,如果c.cache中沒有,則從c.cacheSupport(即CCInfoFSImpl)中獲取并寫入c.cache func (c *ccInfoCacheImpl) GetChaincodeData(ccname string, ccversion string) (*ChaincodeData, error) //代碼在core/common/ccprovider/ccinfocache.gofunc (c ccInfoCacheImpl) GetChaincodeData(ccname string, ccversion string) (ChaincodeData, error) 代碼如下:
func (c *ccInfoCacheImpl) GetChaincodeData(ccname string, ccversion string) (*ChaincodeData, error) {key := ccname + "/" + ccversionc.RLock()ccdata, in := c.cache[key] //優(yōu)先從c.cache中獲取c.RUnlock()if !in { //如果c.cache中沒有var err error//從c.cacheSupport中獲取ccpack, err := c.cacheSupport.GetChaincode(ccname, ccversion)c.Lock()//并寫入c.cacheccdata = ccpack.GetChaincodeData()c.cache[key] = ccdatac.Unlock()}return ccdata, nil } //代碼在core/common/ccprovider/ccinfocache.go3.3、CCCacheSupport接口定義及實現(xiàn)
3.3.1、CCCacheSupport接口定義
type CCCacheSupport interface {//獲取Chaincode包GetChaincode(ccname string, ccversion string) (CCPackage, error) } //代碼在core/common/ccprovider/ccprovider.go3.3.2、CCCacheSupport接口實現(xiàn)(即CCInfoFSImpl結構體)
type CCInfoFSImpl struct{}//從文件系統(tǒng)中讀取并構造CDSPackage或SignedCDSPackage func (*CCInfoFSImpl) GetChaincode(ccname string, ccversion string) (CCPackage, error) {cccdspack := &CDSPackage{}_, _, err := cccdspack.InitFromFS(ccname, ccversion)if err != nil {//try signed CDSccscdspack := &SignedCDSPackage{}_, _, err = ccscdspack.InitFromFS(ccname, ccversion)if err != nil {return nil, err}return ccscdspack, nil}return cccdspack, nil }//將ChaincodeDeploymentSpec序列化后寫入文件系統(tǒng) func (*CCInfoFSImpl) PutChaincode(depSpec *pb.ChaincodeDeploymentSpec) (CCPackage, error) {buf, err := proto.Marshal(depSpec)cccdspack := &CDSPackage{}_, err := cccdspack.InitFromBuffer(buf)err = cccdspack.PutChaincodeToFS() } //代碼在core/common/ccprovider/ccprovider.go3.4、CCPackage接口定義及實現(xiàn)
3.4.1、CCPackage接口定義
type CCPackage interface {//從字節(jié)初始化包InitFromBuffer(buf []byte) (*ChaincodeData, error)//從文件系統(tǒng)初始化包InitFromFS(ccname string, ccversion string) ([]byte, *pb.ChaincodeDeploymentSpec, error)//將chaincode包寫入文件系統(tǒng)PutChaincodeToFS() error//從包中獲取ChaincodeDeploymentSpecGetDepSpec() *pb.ChaincodeDeploymentSpec//從包中獲取序列化的ChaincodeDeploymentSpecGetDepSpecBytes() []byte//校驗ChaincodeDataValidateCC(ccdata *ChaincodeData) error//包轉換為proto.MessageGetPackageObject() proto.Message//獲取ChaincodeDataGetChaincodeData() *ChaincodeData//基于包計算獲取chaincode IdGetId() []byte } //代碼在core/common/ccprovider/ccprovider.go3.4.2、CCPackage接口實現(xiàn)(CDSPackage)
type CDSData struct {CodeHash []byte //ChaincodeDeploymentSpec.CodePackage哈希MetaDataHash []byte //ChaincodeSpec.ChaincodeId.Name和ChaincodeSpec.ChaincodeId.Version哈希 }type CDSPackage struct {buf []byte //ChaincodeDeploymentSpec哈希depSpec *pb.ChaincodeDeploymentSpec //ChaincodeDeploymentSpecdata *CDSDatadatab []byteid []byte //id為CDSData.CodeHash和CDSData.MetaDataHash求哈希 }//獲取ccpack.id func (ccpack *CDSPackage) GetId() []byte //獲取ccpack.depSpec func (ccpack *CDSPackage) GetDepSpec() *pb.ChaincodeDeploymentSpec //獲取ccpack.buf,即ChaincodeDeploymentSpec哈希 func (ccpack *CDSPackage) GetDepSpecBytes() []byte //獲取ccpack.depSpec func (ccpack *CDSPackage) GetPackageObject() proto.Message //構造ChaincodeData func (ccpack *CDSPackage) GetChaincodeData() *ChaincodeData //獲取ChaincodeDeploymentSpec哈希、CDSData、id func (ccpack *CDSPackage) getCDSData(cds *pb.ChaincodeDeploymentSpec) ([]byte, []byte, *CDSData, error) //校驗CDSPackage和ChaincodeData func (ccpack *CDSPackage) ValidateCC(ccdata *ChaincodeData) error //[]byte反序列化為ChaincodeDeploymentSpec,構造CDSPackage,進而構造ChaincodeData func (ccpack *CDSPackage) InitFromBuffer(buf []byte) (*ChaincodeData, error) //從文件系統(tǒng)中獲取ChaincodeData,即buf, err := GetChaincodePackage(ccname, ccversion)和_, err = ccpack.InitFromBuffer(buf) func (ccpack *CDSPackage) InitFromFS(ccname string, ccversion string) ([]byte, *pb.ChaincodeDeploymentSpec, error) //ccpack.buf寫入文件,文件名為/var/hyperledger/production/chaincodes/Name.Version func (ccpack *CDSPackage) PutChaincodeToFS() error //代碼在core/common/ccprovider/cdspackage.go3.5、CCContext結構體
type CCContext struct { //ChaincodeD上下文ChainID stringName stringVersion stringTxID stringSyscc boolSignedProposal *pb.SignedProposalProposal *pb.ProposalcanonicalName string }//構造CCContext func NewCCContext(cid, name, version, txid string, syscc bool, signedProp *pb.SignedProposal, prop *pb.Proposal) *CCContext //name + ":" + version func (cccid *CCContext) GetCanonicalName() string //代碼在core/common/ccprovider/ccprovider.go4、chaincode目錄相關實現(xiàn)
4.1、ChaincodeProviderFactory接口定義及實現(xiàn)
4.1.1、ChaincodeProviderFactory接口定義
type ChaincodeProviderFactory interface {//構造ChaincodeProvider實例NewChaincodeProvider() ChaincodeProvider }func RegisterChaincodeProviderFactory(ccfact ChaincodeProviderFactory) {ccFactory = ccfact } func GetChaincodeProvider() ChaincodeProvider {return ccFactory.NewChaincodeProvider() } //代碼在core/common/ccprovider/ccprovider.go4.1.2、ChaincodeProviderFactory接口實現(xiàn)
type ccProviderFactory struct { }func (c *ccProviderFactory) NewChaincodeProvider() ccprovider.ChaincodeProvider {return &ccProviderImpl{} }func init() {ccprovider.RegisterChaincodeProviderFactory(&ccProviderFactory{}) } //代碼在core/chaincode/ccproviderimpl.go4.2、ChaincodeProvider接口定義及實現(xiàn)
4.2.1、ChaincodeProvider接口定義
type ChaincodeProvider interface {GetContext(ledger ledger.PeerLedger) (context.Context, error)GetCCContext(cid, name, version, txid string, syscc bool, signedProp *pb.SignedProposal, prop *pb.Proposal) interface{}GetCCValidationInfoFromLSCC(ctxt context.Context, txid string, signedProp *pb.SignedProposal, prop *pb.Proposal, chainID string, chaincodeID string) (string, []byte, error)ExecuteChaincode(ctxt context.Context, cccid interface{}, args [][]byte) (*pb.Response, *pb.ChaincodeEvent, error)Execute(ctxt context.Context, cccid interface{}, spec interface{}) (*pb.Response, *pb.ChaincodeEvent, error)ExecuteWithErrorFilter(ctxt context.Context, cccid interface{}, spec interface{}) ([]byte, *pb.ChaincodeEvent, error)Stop(ctxt context.Context, cccid interface{}, spec *pb.ChaincodeDeploymentSpec) errorReleaseContext() } //代碼在core/common/ccprovider/ccprovider.go4.2.2、ChaincodeProvider接口實現(xiàn)
type ccProviderImpl struct {txsim ledger.TxSimulator //交易模擬器 }type ccProviderContextImpl struct {ctx *ccprovider.CCContext }//獲取context.Context,添加TXSimulatorKey綁定c.txsim func (c *ccProviderImpl) GetContext(ledger ledger.PeerLedger) (context.Context, error) //構造CCContext,并構造ccProviderContextImpl func (c *ccProviderImpl) GetCCContext(cid, name, version, txid string, syscc bool, signedProp *pb.SignedProposal, prop *pb.Proposal) interface{} //調用GetChaincodeDataFromLSCC(ctxt, txid, signedProp, prop, chainID, chaincodeID)獲取ChaincodeData中Vscc和Policy func (c *ccProviderImpl) GetCCValidationInfoFromLSCC(ctxt context.Context, txid string, signedProp *pb.SignedProposal, prop *pb.Proposal, chainID string, chaincodeID string) (string, []byte, error) //調用ExecuteChaincode(ctxt, cccid.(*ccProviderContextImpl).ctx, args)執(zhí)行上下文中指定的鏈碼 func (c *ccProviderImpl) ExecuteChaincode(ctxt context.Context, cccid interface{}, args [][]byte) (*pb.Response, *pb.ChaincodeEvent, error) //調用Execute(ctxt, cccid.(*ccProviderContextImpl).ctx, spec) func (c *ccProviderImpl) Execute(ctxt context.Context, cccid interface{}, spec interface{}) (*pb.Response, *pb.ChaincodeEvent, error) //調用ExecuteWithErrorFilter(ctxt, cccid.(*ccProviderContextImpl).ctx, spec) func (c *ccProviderImpl) ExecuteWithErrorFilter(ctxt context.Context, cccid interface{}, spec interface{}) ([]byte, *pb.ChaincodeEvent, error) //調用theChaincodeSupport.Stop(ctxt, cccid.(*ccProviderContextImpl).ctx, spec) func (c *ccProviderImpl) Stop(ctxt context.Context, cccid interface{}, spec *pb.ChaincodeDeploymentSpec) error //調用c.txsim.Done() func (c *ccProviderImpl) ReleaseContext() { //代碼在core/chaincode/ccproviderimpl.go4.3、ChaincodeSupport結構體
ChaincodeSupport更詳細內容,參考:Fabric 1.0源代碼筆記 之 Chaincode(鏈碼) #ChaincodeSupport(鏈碼支持服務端)
4.4、ExecuteChaincode函數(shù)(執(zhí)行鏈碼)
執(zhí)行鏈碼上下文中指定的鏈碼。
func ExecuteChaincode(ctxt context.Context, cccid *ccprovider.CCContext, args [][]byte) (*pb.Response, *pb.ChaincodeEvent, error) {var spec *pb.ChaincodeInvocationSpecvar err errorvar res *pb.Responsevar ccevent *pb.ChaincodeEventspec, err = createCIS(cccid.Name, args) //構造ChaincodeInvocationSpecres, ccevent, err = Execute(ctxt, cccid, spec)return res, ccevent, err } //代碼在core/chaincode/chaincodeexec.gores, ccevent, err = Execute(ctxt, cccid, spec)代碼如下:
func Execute(ctxt context.Context, cccid *ccprovider.CCContext, spec interface{}) (*pb.Response, *pb.ChaincodeEvent, error) {var err errorvar cds *pb.ChaincodeDeploymentSpecvar ci *pb.ChaincodeInvocationSpeccctyp := pb.ChaincodeMessage_INIT //初始化if cds, _ = spec.(*pb.ChaincodeDeploymentSpec); cds == nil { //優(yōu)先判斷ChaincodeDeploymentSpecif ci, _ = spec.(*pb.ChaincodeInvocationSpec); ci == nil { //其次判斷ChaincodeInvocationSpecpanic("Execute should be called with deployment or invocation spec")}cctyp = pb.ChaincodeMessage_TRANSACTION //交易}_, cMsg, err := theChaincodeSupport.Launch(ctxt, cccid, spec)var ccMsg *pb.ChaincodeMessageccMsg, err = createCCMessage(cctyp, cccid.TxID, cMsg)resp, err := theChaincodeSupport.Execute(ctxt, cccid, ccMsg, theChaincodeSupport.executetimeout)if resp.ChaincodeEvent != nil {resp.ChaincodeEvent.ChaincodeId = cccid.Nameresp.ChaincodeEvent.TxId = cccid.TxID}if resp.Type == pb.ChaincodeMessage_COMPLETED {res := &pb.Response{}unmarshalErr := proto.Unmarshal(resp.Payload, res)return res, resp.ChaincodeEvent, nil} } //代碼在core/chaincode5、platforms(鏈碼的編寫語言平臺)
platforms更詳細內容,參考:Fabric 1.0源代碼筆記 之 Chaincode(鏈碼) #platforms(鏈碼語言平臺)歡迎繼續(xù)關注兄弟連區(qū)塊鏈教程分享!
轉載于:https://blog.51cto.com/14041296/2310244
總結
以上是生活随笔為你收集整理的区块链教程Fabric1.0源代码分析Chaincode(链码)体系总结的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: proxmox超融合集群用户授权
- 下一篇: iptables规则备份恢复,firew