区块链教程Fabric1.0源代码分析Chaincode(链码)体系总结-兄弟连

简介:

Fabric 1.0源代码笔记 之 Chaincode(链码)

1、Chaincode概述

Chaincode,即链码或智能合约,代码分布在protos/peer目录、core/chaincode和core/common/ccprovider目录,目录结构如下:

  • protos/peer目录:
        * chaincode.pb.go,ChaincodeDeploymentSpec、ChaincodeInvocationSpec结构体定义。
  • core/chaincode目录:
        * platforms目录,链码的编写语言平台实现,如golang或java。

        * platforms.go,Platform接口定义,及部分工具函数。
        * java目录,java语言平台实现。
        * golang目录,golang语言平台实现。

  • core/common/ccprovider目录:ccprovider相关实现。

2、protos相关结构体定义

2.1、ChaincodeDeploymentSpec结构体定义(用于Chaincode部署)

2.1.1 ChaincodeDeploymentSpec结构体定义

type ChaincodeDeploymentSpec struct {
    ChaincodeSpec *ChaincodeSpec //ChaincodeSpec消息
    EffectiveDate *google_protobuf1.Timestamp
    CodePackage   []byte //链码文件打包
    ExecEnv       ChaincodeDeploymentSpec_ExecutionEnvironment //链码执行环境,DOCKER或SYSTEM
}

type ChaincodeDeploymentSpec_ExecutionEnvironment int32

const (
    ChaincodeDeploymentSpec_DOCKER ChaincodeDeploymentSpec_ExecutionEnvironment = 0
    ChaincodeDeploymentSpec_SYSTEM ChaincodeDeploymentSpec_ExecutionEnvironment = 1
)
//代码在protos/peer/chaincode.pb.go

2.1.2、ChaincodeSpec结构体定义

type ChaincodeSpec struct {
    Type        ChaincodeSpec_Type //链码的编写语言,GOLANG、JAVA
    ChaincodeId *ChaincodeID //ChaincodeId,链码路径、链码名称、链码版本
    Input       *ChaincodeInput //链码的具体执行参数信息
    Timeout     int32
}

type ChaincodeSpec_Type int32

const (
    ChaincodeSpec_UNDEFINED ChaincodeSpec_Type = 0
    ChaincodeSpec_GOLANG    ChaincodeSpec_Type = 1
    ChaincodeSpec_NODE      ChaincodeSpec_Type = 2
    ChaincodeSpec_CAR       ChaincodeSpec_Type = 3
    ChaincodeSpec_JAVA      ChaincodeSpec_Type = 4
)

type ChaincodeID struct {
    Path string
    Name string
    Version string
}

type ChaincodeInput struct { //链码的具体执行参数信息
    Args [][]byte
}
//代码在protos/peer/chaincode.pb.go

2.2、ChaincodeInvocationSpec结构体定义

type ChaincodeInvocationSpec struct {
    ChaincodeSpec *ChaincodeSpec //参考本文2.2
    IdGenerationAlg string
}
//代码在protos/peer/chaincode.pb.go

3、ccprovider目录相关实现

3.1、ChaincodeData结构体

type ChaincodeData struct {
    Name string
    Version string
    Escc string
    Vscc string
    Policy []byte //chaincode 实例的背书策略
    Data []byte
    Id []byte
    InstantiationPolicy []byte //实例化策略
}

//获取ChaincodeData,优先从缓存中读取
func GetChaincodeData(ccname string, ccversion string) (*ChaincodeData, error)
//代码在core/common/ccprovider/ccprovider.go

func 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,优先从缓存中读取ChaincodeData
    if ccInfoCacheEnabled { 
        return ccInfoCache.GetChaincodeData(ccname, ccversion)
    }
    ccpack, err := ccInfoFSProvider.GetChaincode(ccname, ccversion)
    return ccpack.GetChaincodeData(), nil
}
//代码在core/common/ccprovider/ccprovider.go

3.2、ccInfoCacheImpl结构体

type ccInfoCacheImpl struct {
    sync.RWMutex
    cache        map[string]*ChaincodeData //ChaincodeData
    cacheSupport CCCacheSupport
}

//构造ccInfoCacheImpl
func NewCCInfoCache(cs CCCacheSupport) *ccInfoCacheImpl
//获取ChaincodeData,优先从c.cache中获取,如果c.cache中没有,则从c.cacheSupport(即CCInfoFSImpl)中获取并写入c.cache
func (c *ccInfoCacheImpl) GetChaincodeData(ccname string, ccversion string) (*ChaincodeData, error) 
//代码在core/common/ccprovider/ccinfocache.go

func (c ccInfoCacheImpl) GetChaincodeData(ccname string, ccversion string) (ChaincodeData, error) 代码如下:

func (c *ccInfoCacheImpl) GetChaincodeData(ccname string, ccversion string) (*ChaincodeData, error) {
    key := ccname + "/" + ccversion
    c.RLock()
    ccdata, in := c.cache[key] //优先从c.cache中获取
    c.RUnlock()

    if !in { //如果c.cache中没有
        var err error
        //从c.cacheSupport中获取
        ccpack, err := c.cacheSupport.GetChaincode(ccname, ccversion)
        c.Lock()
        //并写入c.cache
        ccdata = ccpack.GetChaincodeData()
        c.cache[key] = ccdata
        c.Unlock()
    }
    return ccdata, nil
}
//代码在core/common/ccprovider/ccinfocache.go

3.3、CCCacheSupport接口定义及实现

3.3.1、CCCacheSupport接口定义

type CCCacheSupport interface {
    //获取Chaincode包
    GetChaincode(ccname string, ccversion string) (CCPackage, error)
}
//代码在core/common/ccprovider/ccprovider.go

3.3.2、CCCacheSupport接口实现(即CCInfoFSImpl结构体)

type CCInfoFSImpl struct{}

//从文件系统中读取并构造CDSPackage或SignedCDSPackage
func (*CCInfoFSImpl) GetChaincode(ccname string, ccversion string) (CCPackage, error) {
    cccdspack := &CDSPackage{}
    _, _, err := cccdspack.InitFromFS(ccname, ccversion)
    if err != nil {
        //try signed CDS
        ccscdspack := &SignedCDSPackage{}
        _, _, err = ccscdspack.InitFromFS(ccname, ccversion)
        if err != nil {
            return nil, err
        }
        return ccscdspack, nil
    }
    return cccdspack, nil
}

//将ChaincodeDeploymentSpec序列化后写入文件系统
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.go

3.4、CCPackage接口定义及实现

3.4.1、CCPackage接口定义

type CCPackage interface {
    //从字节初始化包
    InitFromBuffer(buf []byte) (*ChaincodeData, error)
    //从文件系统初始化包
    InitFromFS(ccname string, ccversion string) ([]byte, *pb.ChaincodeDeploymentSpec, error)
    //将chaincode包写入文件系统
    PutChaincodeToFS() error
    //从包中获取ChaincodeDeploymentSpec
    GetDepSpec() *pb.ChaincodeDeploymentSpec
    //从包中获取序列化的ChaincodeDeploymentSpec
    GetDepSpecBytes() []byte
    //校验ChaincodeData
    ValidateCC(ccdata *ChaincodeData) error
    //包转换为proto.Message
    GetPackageObject() proto.Message
    //获取ChaincodeData
    GetChaincodeData() *ChaincodeData
    //基于包计算获取chaincode Id
    GetId() []byte
}
//代码在core/common/ccprovider/ccprovider.go

3.4.2、CCPackage接口实现(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 //ChaincodeDeploymentSpec
    data    *CDSData
    datab   []byte
    id      []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)
//从文件系统中获取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.go

3.5、CCContext结构体

type CCContext struct { //ChaincodeD上下文
    ChainID string
    Name string
    Version string
    TxID string
    Syscc bool
    SignedProposal *pb.SignedProposal
    Proposal *pb.Proposal
    canonicalName 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.go

4、chaincode目录相关实现

4.1、ChaincodeProviderFactory接口定义及实现

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.go

4.1.2、ChaincodeProviderFactory接口实现

type ccProviderFactory struct {
}

func (c *ccProviderFactory) NewChaincodeProvider() ccprovider.ChaincodeProvider {
    return &ccProviderImpl{}
}

func init() {
    ccprovider.RegisterChaincodeProviderFactory(&ccProviderFactory{})
}
//代码在core/chaincode/ccproviderimpl.go

4.2、ChaincodeProvider接口定义及实现

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) error
    ReleaseContext()
}
//代码在core/common/ccprovider/ccprovider.go

4.2.2、ChaincodeProvider接口实现

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)执行上下文中指定的链码
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.go

4.3、ChaincodeSupport结构体

ChaincodeSupport更详细内容,参考:Fabric 1.0源代码笔记 之 Chaincode(链码) #ChaincodeSupport(链码支持服务端)

4.4、ExecuteChaincode函数(执行链码)

执行链码上下文中指定的链码。

func ExecuteChaincode(ctxt context.Context, cccid *ccprovider.CCContext, args [][]byte) (*pb.Response, *pb.ChaincodeEvent, error) {
    var spec *pb.ChaincodeInvocationSpec
    var err error
    var res *pb.Response
    var ccevent *pb.ChaincodeEvent

    spec, err = createCIS(cccid.Name, args) //构造ChaincodeInvocationSpec
    res, ccevent, err = Execute(ctxt, cccid, spec)
    return res, ccevent, err
}
//代码在core/chaincode/chaincodeexec.go

res, ccevent, err = Execute(ctxt, cccid, spec)代码如下:

func Execute(ctxt context.Context, cccid *ccprovider.CCContext, spec interface{}) (*pb.Response, *pb.ChaincodeEvent, error) {
    var err error
    var cds *pb.ChaincodeDeploymentSpec
    var ci *pb.ChaincodeInvocationSpec

    cctyp := pb.ChaincodeMessage_INIT //初始化
    if cds, _ = spec.(*pb.ChaincodeDeploymentSpec); cds == nil { //优先判断ChaincodeDeploymentSpec
        if ci, _ = spec.(*pb.ChaincodeInvocationSpec); ci == nil { //其次判断ChaincodeInvocationSpec
            panic("Execute should be called with deployment or invocation spec")
        }
        cctyp = pb.ChaincodeMessage_TRANSACTION //交易
    }

    _, cMsg, err := theChaincodeSupport.Launch(ctxt, cccid, spec)
    var ccMsg *pb.ChaincodeMessage
    ccMsg, err = createCCMessage(cctyp, cccid.TxID, cMsg)
    resp, err := theChaincodeSupport.Execute(ctxt, cccid, ccMsg, theChaincodeSupport.executetimeout)
    if resp.ChaincodeEvent != nil {
        resp.ChaincodeEvent.ChaincodeId = cccid.Name
        resp.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/chaincode

5、platforms(链码的编写语言平台)

参考上一篇文章

相关文章
|
6月前
|
存储 供应链 监控
区块链技术在供应链管理中的应用与前景分析
随着信息化时代的到来,供应链管理面临着越来越多的挑战和机遇。本文主要探讨了区块链技术在供应链管理中的应用,以及未来的发展前景。通过对区块链技术的特点和优势进行分析,结合实际案例和趋势展望,展示了区块链技术在提升供应链透明度、效率和安全性方面的潜力,以及未来发展的可能方向。
|
6月前
|
安全 区块链
区块链积分商城系统开发详细指南//需求功能/指南教程/源码流程
Developing a blockchain points mall system involves multiple aspects such as blockchain technology, smart contracts, front-end development, and business logic design. The following is the general process for developing a blockchain points mall system
|
6月前
|
存储 算法 API
面向企业的区块链教程(一)(2)
面向企业的区块链教程(一)
107 6
|
3月前
|
安全 区块链
Massa Layer 1区块链 POS 安全性分析
Massa Labs 回应 Certik 的挑战,通过严格的数学分析证明了其权益证明系统的安全性,抵抗了潜在攻击者试图操纵随机抽签的企图。
59 0
Massa Layer 1区块链 POS 安全性分析
|
6月前
|
存储 供应链 安全
基于区块链技术的智能合约安全性分析
【5月更文挑战第31天】本文深入探讨了区块链技术中智能合约的安全性问题,通过分析现有智能合约的安全漏洞和攻击手段,提出了一系列增强智能合约安全性的策略。文章首先介绍了区块链和智能合约的基本概念,随后详细讨论了智能合约面临的安全挑战,包括代码漏洞、重入攻击等问题,并对比分析了不同平台下智能合约的安全性差异。最后,文章提出了一系列提高智能合约安全性的建议,旨在为区块链应用的健康发展提供参考。
|
5月前
|
存储 安全 区块链
元宇宙与区块链技术的关系可以从多个角度进行阐述。以下是对这两者之间关系的详细分析
**元宇宙:虚拟世界融合现实元素,强调交互与沉浸;区块链:去中心化、安全的分布式账本。两者结合,区块链确保元宇宙中虚拟资产安全、支付高效、身份验证私密、治理透明,支撑其经济体系与用户信任,驱动未来发展。**
|
6月前
|
存储 算法 安全
区块链系统开发技术规则分析
区块链核心技术包括:1) 哈希算法,利用单向函数将任意数据转化为固定长度代码,确保安全验证;2) 非对称加密,使用公钥和私钥一对进行加密解密,保证信息安全;3) 共识机制,如PoW、PoS、DPoS等,实现快速交易验证和确认;4) 智能合约,自动执行的可信代码,一旦编写即不可更改,用于自动化交易;5) 分布式存储,将数据分散存储在网络各处,涵盖结构化、非结构化和半结构化数据。
|
5月前
|
区块链
近期区块链市场趋势分析
**区块链市场趋势摘要:** - 跨链技术成熟,提升互操作性,助力区块链网络融合。 - DeFi持续繁荣,智能合约与AMM创新活跃,市场竞争驱动市场壮大。 - NFT市场多样化,拓展至游戏、音乐等领域,实用性增强。 - 区块链寻求绿色转型,通过PoS共识与绿色能源减少能耗。 - 技术模块化、可组合性提升,降低成本,增强系统灵活性。 这些趋势展现区块链潜力,带来机遇与挑战,促进行业创新。
|
6月前
|
供应链 区块链 数据安全/隐私保护
探索区块链技术在金融领域的应用与前景分析
本文将深入探讨区块链技术在金融领域的具体应用场景,分析其优势与挑战,并展望未来发展趋势。通过案例分析和技术解析,揭示区块链技术在金融行业中的革新意义及前景。
939 15
|
开发框架 .NET 区块链
Hyperledger fabric部署链码(五)初始化与链码升级
fabric部署chaincode-go(智能合约)系列之五
201 0