参考:http://hyperledger-fabric.readthedocs.io/en/latest/chaincode4ade.html
每一个chaincode都需要实现chaincode interface
的Init
和Invoke
接口
每一个chaincode都应该有一个main函数
代码结构如下所示:
package main
import (
"fmt"
"strconv"
"github.com/hyperledger/fabric/core/chaincode/shim"
peer "github.com/hyperledger/fabric/protos/peer"
)
type MyFirstCC struct {
}
func (t *MyFirstCC) Init(stub shim.ChaincodeStubInterface) peer.Response {
}
func (t *MyFirstCC) Invoke(stub shim.ChaincodeStubInterface) peer.Response {
}
func main() {
}
main
函数,负责在instantiate
时启动chaincode
func main() {
err := shim.Start(new(MyFirstCC))
if err != nil {
fmt.Printf("error start MyFirstCC")
}
}
Init
函数,在chaincodeinstantiation
或upgrade
时调用,初始化或者重置数据
func (t *MyFirstCC) Init(stub shim.ChaincodeStubInterface) peer.Response {
fmt.Println("ex10 Init")
_, args := stub.GetFunctionAndParameters()
//set 2 parmas for this chaincode init
//when instantiation chaincode,should give 2 params
if len(args) != 2 {
return shim.Error("Incorrect len of arguments")
}
var Aval int
var A string
var err error
A = args[0]
Aval, err = strconv.Atoi(args[1])
if err != nil {
return shim.Error("Expecting integer value for asset holding")
}
fmt.Printf("Aval = %d\n", Aval)
//put the data to ledger
err = stub.PutState(A, []byte(strconv.Itoa(Aval)))
if err != nil {
return shim.Error("failed to Create asset")
}
return shim.Success(nil)
}
Invoke
函数,在交易时调用。我们可以自定义一些函数,当调用时传递函数名字和参数即可,例如,在本例中我们自定义set
和get
函数。set
更新账本数据,get
读取账本数据
func (t *MyFirstCC) Invoke(stub shim.ChaincodeStubInterface) peer.Response {
fmt.Println("ex10 Invoke")
fn, args := stub.GetFunctionAndParameters()
var result string
var err error
if fn == "set" {
result, err = set(stub, args)
} else if fn == "get" {
result, err = get(stub, args)
} else {
return shim.Error("func not found")
}
if err != nil {
return shim.Error(err.Error())
}
return shim.Success([]byte(result))
}
func set(stub shim.ChaincodeStubInterface, args []string) (string, error) {
fmt.Println("ex10 set")
if len(args) != 2 {
return "", fmt.Errorf("Incorrect arguments")
}
var Aval int
var A string
var err error
A = args[0]
Aval, err = strconv.Atoi(args[1])
if err != nil {
return "", fmt.Errorf("Expecting integer value for asset holding")
}
fmt.Printf("Aval = %d\n", Aval)
//update data in ledger
err = stub.PutState(A, []byte(strconv.Itoa(Aval)))
if err != nil {
return "", fmt.Errorf("failed to PutState:%s", args[0])
}
return args[1], nil
}
func get(stub shim.ChaincodeStubInterface, args []string) (string, error) {
fmt.Println("ex10 get")
if len(args) != 1 {
return "", fmt.Errorf("Incorrect arguments")
}
var A string
A = args[0]
//read data from ledger
value, err := stub.GetState(A)
if err != nil {
return "", fmt.Errorf("failed to get asset: %s with error:%s", args[0], err)
}
if value == nil {
return "", fmt.Errorf("asset not found")
}
return string(value), nil
}
github.com/hyperledger/fabric/examples/chaincode/go
下边新建一个文件夹,命名为example10
,将go文件放置在本文件夹下,这样可以将我们自己写的chaincode映射到clidocker中docker-compose -f docker-compose-cli.yaml up -d
docker exec -it cli bash //创建channel需要先进入cli
ORDERER_CA=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/ordererOrganizations/example.com/orderers/orderer.example.com/msp/tlscacerts/tlsca.example.com-cert.pem
peer channel create -o orderer.example.com:7050 -c mychannel -f ./channel-artifacts/channel.tx --tls true --cafile $ORDERER_CA
peer channel join -b mychannel.block
peer chaincode install -n mycc -v 0 -p github.com/hyperledger/fabric/examples/chaincode/go/chaincode_example10 //文件夹的名字是我们放置go文件的位置
peer chaincode instantiate -o orderer.example.com:7050 --tls true --cafile $ORDERER_CA -C mychannel -n mycc -v 0 -c '{"Args":["init","a","20"]}' //这里给两个参数"a"和"100"
get
方法peer chaincode query -C mychannel -n mycc -c '{"Args":["get","a"]}' //查询余额不往账本写数据,不需要背书,用query即可
set
方法peer chaincode invoke -o orderer.example.com:7050 --tls true --cafile $ORDERER_CA -C mychannel -n mycc -c '{"Args":["set","a","200"]}' //需要往更新账本,用invoke
再次调用chaincode的get
方法
peer chaincode query -C mychannel -n mycc -c '{"Args":["get","a"]}' //我们发现余额已更新为200
有的时候更改了chaincode代码重启docker发现chaincode没有更新,原因可能是上次创建的chaincode docker image还在,可以通过如下方法解决
docker ps -a
docker rm 23bae5e36c07
docker rmi 05ebb1ebdf07 //参数要改为你的chaincode 对应的image id
至此,问题解决,每次都会更新的