fabric链码操作和编写链码约束


官方链码example02操作

进入容器

docker exec -it cli /bin/bash 

创建通道

peer channel create -o orderer.example.com:7050 -c zlktchannel -f ./channel-artifacts/channel.tx --tls true --cafile /opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/ordererOrganizations/example.com/msp/tlscacerts/tlsca.example.com-cert.pem 

当前节点加入通道

peer channel join -b zlktchannel.block

其他节点在cli配置环境

export CORE_PEER_ID=org2peer0
export CORE_PEER_ADDRESS=peer0.org2.example.com:7051
export CORE_PEER_LOCALMSPID=Org2MSP
export CORE_PEER_TLS_CERT_FILE=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org2.example.com/peers/peer0.org2.example.com/tls/server.crt
export CORE_PEER_TLS_KEY_FILE=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org2.example.com/peers/peer0.org2.example.com/tls/server.key
export CORE_PEER_TLS_ROOTCERT_FILE=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org2.example.com/peers/peer0.org2.example.com/tls/ca.crt
export CORE_PEER_MSPCONFIGPATH=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org2.example.com/users/Admin@org2.example.com/msp

其他节点加入通道

peer channel join -b zlktchannel.block

安装链码

peer chaincode install -n example02 -p github.com/hyperledger/fabric/examples/chaincode/go -v 1.0.0

链码实例化

peer chaincode instantiate 
-o orderer.example.com:7050
-C zlktchannel
-c '{"Args":["init","a","2","b","3"]}'
-n example02
-P "AND ('OrdererOrg.member','Org1.member','Org2.member')"
-v 1.0.0
--tls true
--cafile /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 -C zlktchannel -c '{"Args":["init","a","2","b","3"]}' -n example02 -P "AND ('OrdererOrg.member','Org1.member','Org2.member')" -v 1.0.0 --tls true --cafile /opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/ordererOrganizations/example.com/orderers/orderer.example.com/msp/tlscacerts/tlsca.example.com-cert.pem

验证是否有新增容器

exit
docker ps -a

链码操作

//查询账户状态
peer chaincode query -C zlktchannel -n example02 -c '{"Args":["query","a"]}'
//账户转账
-c '{"Args":["invoke","a","b","1"]}'
//删除指定账户:
-c '{"Args":["delete","a"]}'

编写链码相关约束

  • 1.package必须是main

  • 2.必须要有main函数,main函数中执行了shim.Start

  • shim.Start(new(SimpleChaincode))   // SimpleChaincode是个结构体
  • 3.必须要有个结构体,除了main函数,其他的函数必须都挂到这个结构体下,使用指针,包括Init函数

  • 4.必须要有Init函数,不是小写的init

  • 5.必须要用Invoke函数

peer包

type Response struct {
       // A status code that should follow the HTTP status codes.
       Status int32 `protobuf:"varint,1,opt,name=status" json:"status,omitempty"`
       // A message associated with the response code.
       Message string `protobuf:"bytes,2,opt,name=message" json:"message,omitempty"`
       // A payload that can be used to include metadata with this response.
       Payload []byte `protobuf:"bytes,3,opt,name=payload,proto3" json:"payload,omitempty"`
  }
?
?
   shim.Success(nil)
?
   func Success(payload []byte) pb.Response {
       return pb.Response{
           Status:  OK,
           Payload: payload,
      }
  }

shim包

1.Chaincode interface

Init(stub ChaincodeStubInterface) pb.Response 
Invoke(stub ChaincodeStubInterface) pb.Response

2.ChaincodeStubInterface interface

GetArgs() [][]byte         // 获取所有的参数,包括函数和参数两个                  
GetStringArgs() []string   // 获取所有的参数,包括函数和参数两个,转成string类型      
GetFunctionAndParameters() (string, []string)  // 获取所有的参数,把函数和参数分成两部分
GetArgsSlice() ([]byte, error)  // 获取所有的参数,包括函数和参数两个,封装成切片类型  
GetTxID() string                // 获取交易的id
GetChannelID() string           // 获取通道id
InvokeChaincode(chaincodeName string, args [][]byte, channel string) pb.Response  // 根据链码名和channel名调用链码
GetState(key string) ([]byte, error)   // 根据指定用户查看状态
PutState(key string, value []byte) error        // 写入用户状态到账本
DelState(key string) error                    // 删除指定用户
GetStateByRange(startKey, endKey string) (StateQueryIteratorInterface, error) // 通过range方式获取多个用户状态
GetStateByPartialCompositeKey(objectType string, keys []string) (StateQueryIteratorInterface, error)  // 获取组合键的集合
CreateCompositeKey(objectType string, attributes []string) (string, error)  // 创建组合键
SplitCompositeKey(compositeKey string) (string, []string, error)  // 切割组合键
GetQueryResult(query string) (StateQueryIteratorInterface, error)  // CouchDB查询结果,couchdb 文档 https://github.com/cloudant/mango
GetHistoryForKey(key string) (HistoryQueryIteratorInterface, error)  // 获取key的历史值
GetPrivateData(collection, key string) ([]byte, error)  // 获取私有数据
PutPrivateData(collection string, key string, value []byte) error
DelPrivateData(collection, key string) error
GetPrivateDataByRange(collection, startKey, endKey string) (StateQueryIteratorInterface, error)
GetPrivateDataByPartialCompositeKey(collection, objectType string, keys []string) (StateQueryIteratorInterface, error)  // 根据组合键获取私有数据
GetPrivateDataQueryResult(collection, query string) (StateQueryIteratorInterface, error)
GetCreator() ([]byte, error)   // 获取当前用户
GetTransient() (map[string][]byte, error)  // 返回可以被链码使用但没有保存在账本中的临时映射表,例如用于加密和解密的密码学信息
GetBinding() ([]byte, error)  // 交易的nonce、creator和epoch拼接结果的SHA256哈希
GetDecorations() map[string][]byte  // 获取map结构的附加数据
GetSignedProposal() (*pb.SignedProposal, error)  // 返回完全解码的签名交易对象
GetTxTimestamp() (*timestamp.Timestamp, error)  // 返回交易创建时的时间戳
SetEvent(name string, payload []byte) error  // 当ChainCode提交完毕,会通过Event的方式通知Client。而通知的内

3.CommonIteratorInterface interface

HasNext() bool
Close() error

4.StateQueryIteratorInterface interface

CommonIteratorInterface
Next() (*queryresult.KV, error)

5.HistoryQueryIteratorInterface interface

CommonIteratorInterface 继承
Next() (*queryresult.KeyModification, error)

6.MockQueryIteratorInterface interface

StateQueryIteratorInterface 继承

接口文档:https://godoc.org/github.com/hyperledger/fabric/core/chaincode/shim