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

fabric1.4如何开发实现system chaincode

作者: CodingCode | 来源:发表于2020-08-14 09:58 被阅读0次

    这篇文章介绍如何在fabric1.4里面实现一个system chaincode的例子。
    (实现一个system chaincode的例子可以用插件(在fabric1.4版本中缺省情况下已经被禁用了),也可以直接build在peer里面)

    这里介绍直接build的peer里面的办法。

    1. 参考已有的system chaincode
    cp -r core/scc/qscc core/scc/myscc
    

    把qscc拷贝一份,作为例子直接在上面改了,然后简化实现:PUT和GET两个操作:

    $ cat core/scc/myscc/myscc.go
    /*
    Copyright IBM Corp. All Rights Reserved.
    
    SPDX-License-Identifier: Apache-2.0
    */
    
    package myscc
    
    import (
        "fmt"
    
        "github.com/hyperledger/fabric/common/flogging"
        "github.com/hyperledger/fabric/core/aclmgmt"
        "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(aclProvider aclmgmt.ACLProvider) *MySccImp {
        return &MySccImp{
            aclProvider: aclProvider,
        }
    }
    
    func (e *MySccImp) Name() string              { return "myscc" }
    func (e *MySccImp) Path() string              { return "github.com/hyperledger/fabric/core/scc/myscc" }
    func (e *MySccImp) InitArgs() [][]byte        { return nil }
    func (e *MySccImp) Chaincode() shim.Chaincode { return e }
    func (e *MySccImp) InvokableExternal() bool   { return true }
    func (e *MySccImp) InvokableCC2CC() bool      { return true }
    func (e *MySccImp) Enabled() bool             { return true }
    
    // MySccImp implements the ledger query functions, including:
    // - Add add a record
    // - Query query a record
    type MySccImp struct {
        aclProvider aclmgmt.ACLProvider
    }
    
    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)
    }
    
    1. 然后注册进去peer:
    $ diff --git a/src/github.com/hyperledger/fabric/peer/node/start.go b/src/github.com/hyperledger/fabric/peer/node/start.go
    index eae5f3c..ee3228d 100644
    --- a/src/github.com/hyperledger/fabric/peer/node/start.go
    +++ b/src/github.com/hyperledger/fabric/peer/node/start.go
    @@ -69,6 +69,7 @@ import (
            "github.com/hyperledger/fabric/core/scc/cscc"
            "github.com/hyperledger/fabric/core/scc/lscc"
            "github.com/hyperledger/fabric/core/scc/qscc"
    +       "github.com/hyperledger/fabric/core/scc/myscc"
            "github.com/hyperledger/fabric/discovery"
            "github.com/hyperledger/fabric/discovery/endorsement"
            discsupport "github.com/hyperledger/fabric/discovery/support"
    @@ -748,10 +749,11 @@ func registerChaincodeSupport(
     
            csccInst := cscc.New(ccp, sccp, aclProvider)
            qsccInst := qscc.New(aclProvider)
    +       mysccInst := myscc.New(aclProvider)
     
            //Now that chaincode is initialized, register all system chaincodes.
            sccs := scc.CreatePluginSysCCs(sccp)
    -       for _, cc := range append([]scc.SelfDescribingSysCC{lsccInst, csccInst, qsccInst, lifecycleSCC}, sccs...) {
    +       for _, cc := range append([]scc.SelfDescribingSysCC{lsccInst, csccInst, qsccInst, mysccInst, lifecycleSCC}, sccs...) {
                    sccp.RegisterSysCC(cc)
            }
    

    就是参考qscc的类似,一样实现就行了。
    注意这里看到New函数创建system chaincode实例的时候传入了一个aclProvider,但是在myscc里面并没有使用,丢掉了,后面可以再加强。

    1. 重新build peer executable

    2. 修改core.yaml文件

    把myscc添加到system chaincode的whitelist里面

        # 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
    
    1. 重启peer就可以了

    用命令行调用新的system chaincode:

    $ peer chaincode invoke -C "<channel>" -n "myscc" -c '{"Args":["Put", "a", "aaa"]}'
    $ peer chaincode invoke -C "<channel>" -n "myscc" -c '{"Args":["Get", "a"]}'
    

    当然要先把peer加入到<channel>里面。

    注意system chaincode并没有install, instantiate的操作,所以也不存在system chaincode属于哪一个channel的问题,在chaincode主函数Invoke的参数stub指向的就是从命令行中"-C"所传递的channel。

    相关文章

      网友评论

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

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