美文网首页
fabric1.4如何开发实现system chaincode(

fabric1.4如何开发实现system chaincode(

作者: CodingCode | 来源:发表于2020-08-15 02:57 被阅读0次

    这里介绍如果使用plugin的方式实现system chaincode。

    在fabric1.4版本里缺省情况下不支持plugin方式的system chaincode;所以即使部署了插件的so文件,peer也不会去加载。

    所以:

    1. 打开peer的pluginsenabled开关,重写编译peer
    $ GO_TAGS="pluginsenabled" make peer
    

    或者在fabric/Makefile里面直接修改

    --- a/src/github.com/hyperledger/fabric/Makefile
    +++ b/src/github.com/hyperledger/fabric/Makefile
    @@ -78,7 +78,7 @@ METADATA_VAR += BaseDockerNamespace=$(BASE_DOCKER_NS)
     
     GO_LDFLAGS = $(patsubst %,-X $(PKGNAME)/common/metadata.%,$(METADATA_VAR))
     
    -GO_TAGS ?=
    +GO_TAGS ?= pluginsenabled
    

    然后重新编译peer,部署peer到container里面

    1. 生成system chaincode代码
    /*
    Copyright IBM Corp. All Rights Reserved.
    
    SPDX-License-Identifier: Apache-2.0
    */
    
    package main
    
    import (
        "fmt"
    
        "github.com/hyperledger/fabric/common/flogging"
        "github.com/hyperledger/fabric/core/chaincode/shim"
    pb  "github.com/hyperledger/fabric/protos/peer"
    )
    
    // New returns an instance of MYSCC.
    // Typically this is called once per peer.
    //func New() *MySccImp {
    func New() shim.Chaincode {
        return &MySccImp{
        }
    }
    
    // MySccImp implements the ledger query functions, including:
    // - Add add a record
    // - Query query a record
    type MySccImp struct {
    }
    
    var myscclogger = flogging.MustGetLogger("myscc")
    
    // These are function names from Invoke first parameter
    const (
        PUT string = "Put"
        GET string = "Get"
    )
    
    // Init is called once per chain when the chain is created.
    // This allows the chaincode to initialize any variables on the ledger prior
    // to any transaction execution on the chain.
    func (e *MySccImp) Init(stub shim.ChaincodeStubInterface) pb.Response {
        myscclogger.Info("Init MYSCC")
    
        return shim.Success(nil)
    }
    
    // Invoke is called with args[0] contains the query function name, args[1]
    // contains the chain ID, which is temporary for now until it is part of stub.
    // Each function requires additional parameters as described below:
    // # Add: Return a BlockchainInfo object marshalled in bytes
    // # Query: Return the block specified by block number in args[2]
    func (e *MySccImp) Invoke(stub shim.ChaincodeStubInterface) pb.Response {
        args := stub.GetArgs()
    
        if len(args) < 2 {
            return shim.Error(fmt.Sprintf("Incorrect number of arguments, %d", len(args)))
        }
        fname := string(args[0])
        key   := string(args[1])
        myscclogger.Debugf("Invoke function: %s on chain: %s", fname, key)
    
        switch fname {
        case PUT:
            if len(args) < 3 {
                return shim.Error(fmt.Sprintf("missing 3rd argument for %s", fname))
            }
            value := args[2]
            return Put(stub, key, value)
        case GET:
            return Get(stub, key)
        default:
            return shim.Error(fmt.Sprintf("Requested function %s not found.", fname))
        }
    }
    
    func Put(stub shim.ChaincodeStubInterface, key string, value []byte) pb.Response {
        stub.PutState(key, value)
        return shim.Success(nil)
    }
    
    func Get(stub shim.ChaincodeStubInterface, key string) pb.Response {
        value, err := stub.GetState(key)
        if err != nil {
            return shim.Error(fmt.Sprintf("unable get key %s, error: %v", key, err))
        }
        return shim.Success(value)
    }
    
    func main() {}
    

    和前面介绍的直接链接在peer文件内的system chaincode比较有几点注意。

    1. package名字必须是main啦
    2. 必须包含一个空main()函数啦,否则编译不过。
    • 即使定义成非空函数,这个main也不会被执行。
    1. New函数必须定义成func New() shim.Chaincode,否则会报错peer: panic: Function New does not match expected definition func() shim.Chaincode
    • 不能带参数,(对照内置的用法,这里不能传ACL参数对象,可能对ACL的使用有限制???)
    • 返回类型必须是shim.Chaincode,不能是扩展了的struct,例如func New() *MySccImp,虽然MySccImp实现了shim.Chaincode的接口,也不行;
    1. 编译system chaincode
    $ go build -buildmode=plugin -o myscc.so myscc.go
    

    注意:

    1. plugin的编译必须和peer的编译使用相同的编译环境,包括go语言,依赖库版本等,否则运行的时候出乱七八糟的问题:fabric plugin was built with a different version of package <name>
    2. 编译出来的.so文件缺省没有可执行权限,这也不需要,peer加载的时候不管这个。
    1. 部署system chaincode

    把myscc.so拷贝的peer container里面,同时修改core.yaml两个地方:

        # system chaincodes whitelist. To add system chaincode "myscc" to the
        # whitelist, add "myscc: enable" to the list below, and register in
        # chaincode/importsysccs.go
        system:
            cscc: enable
            lscc: enable
            escc: enable
            vscc: enable
            qscc: enable
    +       myscc: enable
    
        # System chaincode plugins: in addition to being imported and compiled
        # into fabric through core/chaincode/importsysccs.go, system chaincodes
        # can also be loaded as shared objects compiled as Go plugins.
        # See examples/plugins/scc for an example.
        # Like regular system chaincodes, plugins must also be white listed in the
        # chaincode.system section above.
        systemPlugins:
          # example configuration:
    +     - enabled: true
    +       name: myscc
    +       path: /path/to/myscc.so
    +       invokableExternal: true
     +      invokableCC2CC: true
    

    重启peer就可以使用了。

    相关文章

      网友评论

          本文标题:fabric1.4如何开发实现system chaincode(

          本文链接:https://www.haomeiwen.com/subject/ffyodktx.html