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

2020-08-15  本文已影响0人  CodingCode

这里介绍如果使用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()函数啦,否则编译不过。
  1. New函数必须定义成func New() shim.Chaincode,否则会报错peer: panic: Function New does not match expected definition func() 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就可以使用了。

上一篇下一篇

猜你喜欢

热点阅读