原计划等node-SDK的代码搞完一起写个总结,结果实验环境要在今天被清空了
先把链码的基础编写(增删改查)总结出来
链码一,对{name ; num} 形式数据进行増,删,查操作
安装新链码
peer chaincode install -n mycc -v 2.0 -p github.com/hyperledger/fabric/examples/chaincode/go
实例化新链码
peer chaincode upgrade -o orderer.example.com:7050 --tls --cafile $ORDERER_CA -C $CHANNEL_NAME -n mycc -v 2.0 -c '{"Args":["init"]}'
导入包;声明结构体;初始化;
package main
import (
"fmt"
"strconv"
"github.com/hyperledger/fabric/core/chaincode/shim"
pb "github.com/hyperledger/fabric/protos/peer"
)
// SimpleChaincode example simple Chaincode implementation
type SimpChaincode struct {
}
func (t *SimpChaincode) Init(stub shim.ChaincodeStubInterface) pb.Response {
fmt.Println("ex02y Init")
return shim.Success(nil)
}
声明invoke函数,内部定义要编写的函数
func (t *SimpChaincode) Invoke(stub shim.ChaincodeStubInterface) pb.Response {
fmt.Println("ex02y Invoke")
function, args := stub.GetFunctionAndParameters()
if function == "add" {
return t.add(stub, args)
} else if function == "delete" {
return t.delete(stub, args)
} else if function == "query" {
return t.query(stub, args)
}
return shim.Error("Invalid invoke function name. Expecting \"invoke\" \"delete\" \"query\"")
}
add 添加数据
func (t *SimpChaincode) add(stub shim.ChaincodeStubInterface, args []string) pb.Response {
var name string
var num int
var err error
if len(args) != 2 {
return shim.Error("Incorrect number of arguments. Expecting 2")
}
name = args[0]
NumExit, err := stub.GetState(name)
if err != nil {
return shim.Error("Failed to get state")
}
if NumExit != nil {
return shim.Error("Name already exit")
}
num, err = strconv.Atoi(args[1])
if err != nil {
return shim.Error("Invalid transaction amount, expecting a integer value")
}
fmt.Printf("name = %s, num = %d\n", name, num)
err = stub.PutState(name, []byte(strconv.Itoa(num)))
if err != nil {
return shim.Error(err.Error())
}
return shim.Success(nil)
}
cli指令
peer chaincode invoke -o orderer.example.com:7050 --tls --cafile $ORDERER_CA -C $CHANNEL_NAME -n mycc -c '{"Args":["add","aaa","001"]}'
query 查询数据
func (t *SimpChaincode) query(stub shim.ChaincodeStubInterface, args []string) pb.Response {
var name string // Entities
var err error
if len(args) != 1 {
return shim.Error("Incorrect number of arguments. Expecting name of the person to query")
}
name = args[0]
// Get the state from the ledger
QueryNum, err := stub.GetState(name)
if err != nil {
jsonResp := "{\"Error\":\"Failed to get state for " + name + "\"}"
return shim.Error(jsonResp)
}
if QueryNum == nil {
jsonResp := "{\"Error\":\"Nil amount for " + name + "\"}"
return shim.Error(jsonResp)
}
jsonResp := "{\"Name\":\"" + name + "\",\"Amount\":\"" + string(QueryNum) + "\"}"
fmt.Printf("Query Response:%s\n", jsonResp)
return shim.Success(QueryNum)
}
cli指令
peer chaincode query -C $CHANNEL_NAME -n mycc -c '{"Args":["query","aaa"]}'
查询到aaa对应的值 1
delete 删除数据
func (t *SimpChaincode) delete(stub shim.ChaincodeStubInterface, args []string) pb.Response {
if len(args) != 1 {
return shim.Error("Incorrect number of arguments. Expecting 1")
}
name := args[0]
// Delete the key from the state in ledger
err := stub.DelState(name)
if err != nil {
return shim.Error("Failed to delete state")
}
return shim.Success(nil)
}
cli指令
peer chaincode invoke -o orderer.example.com:7050 --tls --cafile $ORDERER_CA -C $CHANNEL_NAME -n mycc -c '{"Args":["delete","aaa"]}'
成功删除aaa数据,后续再次查询结果为空
链码二,对{num ; {name ; value ; type}} 形式数据进行,増,删,改,查询单个或全部数据
声明结构体和复杂的数据结构体;初始化
type StructChaincode struct {
}
type User struct {
Name string `json:"name"`
Value int `json:"value"`
Type string `json:"type"`
}
func (t *StructChaincode) Init(stub shim.ChaincodeStubInterface) pb.Response {
fmt.Println("mvcc 3.0 Init")
return shim.Success(nil)
}
声明invoke函数
func (t *StructChaincode) Invoke(stub shim.ChaincodeStubInterface) pb.Response {
fmt.Println("mvcc 3.0 Invoke")
function, args := stub.GetFunctionAndParameters()
if function == "add" {
return t.add(stub, args)
} else if function == "delete" {
return t.delete(stub, args)
} else if function == "query" {
return t.query(stub, args)
} else if function == "update" {
return t.uptade(stub, args)
} else if function == "queryall" {
return t.queryall(stub,args)
}
return shim.Error("Invalid invoke function name. Expecting \"invoke\" \"delete\" \"query\"")
}
add 增加数据
func (t *StructChaincode) add(stub shim.ChaincodeStubInterface, args []string) pb.Response {
if len(args) != 4 {
return shim.Error("Incorrect number of arguments. Expecting 5")
}
a, err := strconv.Atoi(args[2])
if err != nil {
return shim.Error("Invalid transaction amount, expecting a integer value")
}
var per = User{Name:args[1], Value:a, Type:args[3]}
PerAsByte, _ := json.Marshal(per)
err = stub.PutState(args[0], PerAsByte)
if err != nil {
return shim.Error(err.Error())
}
return shim.Success(nil)
}
cli指令
peer chaincode invoke -o orderer.example.com:7050 --tls --cafile $ORDERER_CA -C $CHANNEL_NAME -n mycc -c '{"Args":["add","Peo1","aaa","100","student"]}'
query 查询数据
func (t *StructChaincode) query(stub shim.ChaincodeStubInterface, args []string) pb.Response {
if len(args) != 1 {
return shim.Error("Incorrect number of arguments. Expecting name of the person to query")
}
QueryMessage, err := stub.GetState(args[0])
if err != nil {
jsonResp := "{\"Error\":\"Failed to get state for " + args[0] + "\"}"
return shim.Error(jsonResp)
}
//jsonResp := "{\"Name\":\"" + args[0] + "\",\"Amount\":\"" + string(QueryMessage) + "\"}"
//fmt.Printf("Query Response:%s\n", jsonResp)
return shim.Success(QueryMessage)
}
cli指令
peer chaincode query -C $CHANNEL_NAME -n mycc -c '{"Args":["query","Peo1"]}'
update 修改name数据
func (t *StructChaincode) uptade(stub shim.ChaincodeStubInterface, args []string) pb.Response {
if len(args) != 2 {
return shim.Error("Incorrect number of arguments. Expecting 2")
}
PeoAsBytes, _:= stub.GetState(args[0])
peo := User{}
er :=json.Unmarshal(PeoAsBytes, &peo)
if er != nil {
return shim.Error("Failed to unmarshal")
}
peo.Name = args[1]
PeoAsBytes, _= json.Marshal(peo)
err := stub.PutState(args[0],PeoAsBytes)
if err != nil {
return shim.Error("Failed to update state")
}
return shim.Success(nil)
}
cli指令
peer chaincode invoke -o orderer.example.com:7050 --tls --cafile $ORDERER_CA -C $CHANNEL_NAME -n mycc -c '{"Args":["uptade","Peo1","abb"]}'
再次查询,name修改成功(aaa -> abb)
delete删除数据
func (t *StructChaincode) delete(stub shim.ChaincodeStubInterface, args []string) pb.Response {
if len(args) != 1 {
return shim.Error("Incorrect number of arguments. Expecting 1")
}
err := stub.DelState(args[0])
if err != nil {
return shim.Error("Failed to delete state")
}
return shim.Success(nil)
}
cli指令
peer chaincode invoke -o orderer.example.com:7050 --tls --cafile $ORDERER_CA -C $CHANNEL_NAME -n mycc -c '{"Args":["delete","Peo3"]}'
再次查询,Peo3已经删除
queryall 查询所有数据
使用的是GetStateByRange函数,尾指针无所谓,只会返回存在的数据
GetStateByRange返回的是指针,getListResult函数用来对数据格式进行处理
func getListResult(resultsIterator shim.StateQueryIteratorInterface) ([]byte,error){
defer resultsIterator.Close()
// buffer is a JSON array containing QueryRecords
var buffer bytes.Buffer
buffer.WriteString("[")
bArrayMemberAlreadyWritten := false
for resultsIterator.HasNext() {
queryResponse, err := resultsIterator.Next()
if err != nil {
return nil, err
}
if bArrayMemberAlreadyWritten == true {
buffer.WriteString(",")
}
buffer.WriteString("{\"Key\":")
buffer.WriteString("\"")
buffer.WriteString(queryResponse.Key)
buffer.WriteString("\"")
buffer.WriteString(", \"Record\":")
// Record is a JSON object, so we write as-is
buffer.WriteString(string(queryResponse.Value))
buffer.WriteString("}")
bArrayMemberAlreadyWritten = true
}
buffer.WriteString("]")
fmt.Printf("queryResult:\n%s\n", buffer.String())
return buffer.Bytes(), nil
}
func (t *StructChaincode) queryall (stub shim.ChaincodeStubInterface, args []string) pb.Response{
resultsIterator,err:= stub.GetStateByRange(args[0],args[1])
if err!=nil{
return shim.Error("Query by Range failed")
}
result,err:=getListResult(resultsIterator)
if err!=nil{
return shim.Error("getListResult failed")
}
return shim.Success(result)
}
cli指令
peer chaincode invoke -o orderer.example.com:7050 --tls --cafile $ORDERER_CA -C $CHANNEL_NAME -n mycc -c '{"Args":["queryall","Peo1","Peo4"]}'
返回Peo1及Peo2的全部信息