序言
fabric1.0 开发chaincode的例子中一个chaincode都是由一个go文件组成,当做模块化开发时总不能多个人使用同一个go文件吧?
仔细研究了fabric1.0中的examples\chaincode\go\utxo 的例子,是可以是实现 一个chaincode由多个go文件组成的。
仿照utxo的例子,写一个实现了机构注册和机构查询的简单的功能,由2个go文件组成,第一个go文件是chaincode的main函数文件,第二个go文件实现了真正的功能,以此类推,再多的功能可以由第3个,第n个go文件实现,不同类型的go文件放到不同的子目录中,从而实现了chaincode的模块化开发。
1)建立主目录和子模块目录
在GOPATH目录下 建立一个测试目录 mytest.com,在mytest.com下建立orgbase子模块目录
2)建立chaincode主程序
在mytest.com目录下建立一个testmain.go的chaincode主程序文件,
文件中必须包含main函数,Init函数和Invoke函数,文件内容如下:
package main
import (
"fmt"
"mytest.com/orgbase"
"github.com/hyperledger/fabric/core/chaincode/shim"
pb "github.com/hyperledger/fabric/protos/peer"
)
/*
定义SimpleChaincode
*/
type SimpleChaincode struct {
}
/*
主程序初始化
*/
func (t *SimpleChaincode) Init(stub shim.ChaincodeStubInterface) pb.Response {
return shim.Success(nil)
}
/*
机构开户
*/
func (t *SimpleChaincode) orgReg(stub shim.ChaincodeStubInterface, args []string) pb.Response {
return orgbase.OrgReg(stub, args)
}
/*
机构查询
*/
func (t *SimpleChaincode) orgQry(stub shim.ChaincodeStubInterface, args []string) pb.Response {
return orgbase.OrgQry(stub, args)
}
/*
所有的程序入口都在这里定义
*/
func (t *SimpleChaincode) Invoke(stub shim.ChaincodeStubInterface) pb.Response {
function, args := stub.GetFunctionAndParameters()
if function == "orgReg" {
return t.orgReg(stub, args)
} else if function == "orgQry" {
return t.orgQry(stub, args)
}
jsonResp := "{\"errCode\":\"0\",\"errMsg\":错误的函数名称,请检查\"}"
return shim.Success([]byte(jsonResp))
}
/*
启动主程序
*/
func main() {
err := shim.Start(new(SimpleChaincode))
if err != nil {
fmt.Printf("Error starting Simple chaincode: %s", err)
}
}
3)建立模块子程序
在 orgbase子目录下建立orgmanage.go文件,文件内容如下:
package orgbase
import (
"encoding/json"
"fmt"
"time"
"github.com/hyperledger/fabric/core/chaincode/shim"
pb "github.com/hyperledger/fabric/protos/peer"
)
/*
机构开户
*/
func OrgReg(stub shim.ChaincodeStubInterface, arg []string) pb.Response {
_, args := stub.GetFunctionAndParameters()
var orgId string
var orgPk string
var Aval string
var err error
orgId = args[0]
orgPk = "org_" + orgId
Aval = args[1]
var dat map[string]interface{}
if err := json.Unmarshal([]byte(Aval), &dat); err != nil {
jsonResp := "{\"errCode\":\"001\",\"errMsg\":\"系统错误\"}"
return shim.Success([]byte(jsonResp + err.Error()))
}
if len(dat["orgId"].(string)) == 0 {
return shim.Success([]byte("{\"errCode\":\"001\",\"errMsg\":\"orgId is null\"}"))
}
if len(dat["oraName"].(string)) == 0 {
return shim.Success([]byte("{\"errCode\":\"001\",\"errMsg\":\"oraName is null\"}"))
}
Avalbytes, _ := stub.GetState(orgPk)
if Avalbytes != nil {
jsonResp := "{\"errCode\":\"001\",\"errMsg\":\"该机构ID已经存在\"}"
return shim.Success([]byte(jsonResp))
}
err = stub.PutState(orgPk, []byte(Aval))
if err != nil {
jsonResp := "{\"errCode\":\"001\",\"errMsg\":\"系统错误\"}"
return shim.Success([]byte(jsonResp + err.Error()))
}
jsonResp := "{\"errCode\":\"0\",\"errMsg\":\"机构注册成功\"}"
fmt.Printf("orgReg Response:%s\n", jsonResp)
return shim.Success([]byte(jsonResp))
}
/*
机构查询
*/
func OrgQry(stub shim.ChaincodeStubInterface, args []string) pb.Response {
var orgId string
var orgPk string
var err error
if len(args) != 1 {
return shim.Error("Incorrect number of arguments. Expecting name of the person to query")
}
orgId = args[0]
orgPk = "org_" + orgId
Avalbytes, err := stub.GetState(orgPk)
if err != nil {
jsonResp := "{\"errCode\":\"org001\",\"errMsg\":\"Failed to get state for " + orgId + "\"}"
return shim.Success([]byte(jsonResp))
}
if Avalbytes == nil {
jsonResp := "{\"errCode\":\"org002\",\"errMsg\":\"机构ID不存在 " + orgId + "\"}"
return shim.Success([]byte(jsonResp))
}
jsonResp := "{\"errCode\":\"0\",\"errMsg\":\"\",\"list\":" + string(Avalbytes) + "}"
fmt.Printf("orgQry Response:%s\n", jsonResp)
fmt.Println(time.Now().Format("2006-01-02 15:04:05:006") + "-----")
return shim.Success([]byte(jsonResp))
}
4)目录结构如下:
$GOPATH
-- mytest.com
-- testmain.go
-- orgbase
-- orgmagage.go
5) 部署智能合约
使用 peer chaincode install -n mycc -v 1.0 -p mytest.com >&log.txt
可以将mytest.com目录下的所有go文件发布成一个chaincode
6)实例化智能合约
使用 peer chaincode instantiate -o orderer.example.com:7050 -C mychannel -n mycc -v 1.0 -c '{"Args":["init"]}' -P "OR('Org1MSP.member','Org2MSP.member')" >&log.txt
实例化刚才部署的 mycc 智能合约,查看log.txt可以查询部署和实例化是否成功。