开发测试代码
cd $GOPATH/src/github.com/hyperledger/fabric/examples/chaincode/go
mkdir fsmtest && cd fsmtest && vim fsmtest.go
package main
import (
"fmt"
"github.com/hyperledger/fabric/core/chaincode/shim"
pb "github.com/hyperledger/fabric/protos/peer"
"github.com/looplab/fsm"
)
type SimpleChaincode struct {
}
func InitFSM(initStatus string) *fsm.FSM {
f := fsm.NewFSM(
initStatus,
fsm.Events{
{Name: "Submit", Src: []string{"Draft"}, Dst: "Submited"},
{Name: "Approve", Src: []string{"Submited"}, Dst: "L1Approved"},
{Name: "Reject", Src: []string{"Submited"}, Dst: "Reject"},
{Name: "Approve", Src: []string{"L1Approved"}, Dst: "Complete"},
{Name: "Reject", Src: []string{"L1Approved"}, Dst: "Reject"},
},
fsm.Callbacks{},
)
return f
}
func (t *SimpleChaincode) Init(stub shim.ChaincodeStubInterface) pb.Response {
return shim.Success(nil)
}
func (t *SimpleChaincode) Invoke(stub shim.ChaincodeStubInterface) pb.Response {
function, args := stub.GetFunctionAndParameters()
fmt.Println("invoke is running " + function)
if function == "Draft" {
return t.Draft(stub, args)
} else if function == "Submit" {
return FsmEvent(stub, args, "Submit")
} else if function == "Approve" {
return FsmEvent(stub, args, "Approve")
} else if function == "Reject" {
return FsmEvent(stub, args, "Reject")
}
return shim.Error("Receive unknown function invocation")
}
func (t *SimpleChaincode) Draft(stub shim.ChaincodeStubInterface, args []string) pb.Response {
formNumber := args[0]
status := "Draft"
stub.PutState(formNumber, []byte(status))
return shim.Success([]byte(status))
}
func FsmEvent(stub shim.ChaincodeStubInterface, args []string, event string) pb.Response {
formNumber := args[0]
bstatus, err := stub.GetState(formNumber)
if err != nil {
return shim.Error("Query form status fail, form number:" + formNumber)
}
status := string(bstatus)
fmt.Println("Form[" + formNumber + "] status:" + status)
f := InitFSM(status)
err = f.Event(event)
if err != nil {
return shim.Error("Current status is " + status + " does not support event:" + event)
}
status = f.Current()
fmt.Println("New status:" + status)
stub.PutState(formNumber, []byte(status))
return shim.Success([]byte(status))
}
func main() {
err := shim.Start(new(SimpleChaincode))
if err != nil {
fmt.Printf("Error starting SimpleChaincode: %s", err)
}
}
下载依赖包
go get github.com/looplab/fsm
修改docker-compose-cli.yaml
volumes:
- /root/golang/src/github.com/looplab/fsm:/opt/gopath/src/github.com/looplab/fsm
启动测试网络
cd $GOPATH/src/github.com/hyperledger/fabric/examples/e2e_cli
./network_setup.sh up
进入fabric client
docker exec -it cli bash
安装链码
peer chaincode install -n fsmtest -v 1.0 -p github.com/hyperledger/fabric/examples/chaincode/go/fsmtest
实例化链码
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 chaincode instantiate -o orderer.example.com:7050 --tls true --cafile $ORDERER_CA -C mychannel -n fsmtest -v 1.0 -c '{"Args":[]}'
测试运行链码
peer chaincode invoke -o orderer.example.com:7050 --tls true --cafile $ORDERER_CA -C mychannel -n fsmtest -c '{"Args":["Draft","EXP1"]}'
[chaincodeCmd] chaincodeInvokeOrQuery -> INFO 00a Chaincode invoke successful. result: status:200 payload:"Draft"
peer chaincode invoke -o orderer.example.com:7050 --tls true --cafile $ORDERER_CA -C mychannel -n fsmtest -c '{"Args":["Submit","EXP1"]}'
[chaincodeCmd] chaincodeInvokeOrQuery -> INFO 00a Chaincode invoke successful. result: status:200 payload:"Submited"
peer chaincode invoke -o orderer.example.com:7050 --tls true --cafile $ORDERER_CA -C mychannel -n fsmtest -c '{"Args":["Approve","EXP1"]}'
[chaincodeCmd] chaincodeInvokeOrQuery -> INFO 00a Chaincode invoke successful. result: status:200 payload:"L1Approved"
peer chaincode invoke -o orderer.example.com:7050 --tls true --cafile $ORDERER_CA -C mychannel -n fsmtest -c '{"Args":["Approve","EXP1"]}'
[chaincodeCmd] chaincodeInvokeOrQuery -> INFO 00a Chaincode invoke successful. result: status:200 payload:"Complete"
peer chaincode invoke -o orderer.example.com:7050 --tls true --cafile $ORDERER_CA -C mychannel -n fsmtest -c '{"Args":["Approve","EXP1"]}'
Error: Error endorsing invoke: rpc error: code = Unknown desc = chaincode error (status: 500, message: Current status is Complete does not support event:Approve) -
参考文档
在Fabric ChainCode中使用状态机
http://www.cnblogs.com/studyzy/p/7492637.html