本文链码实例为Fabric 官方实例examples/chaincode/go/chaincode_example02,实现简单的转账功能
进入到cli容器里面
$ docker exec -it fabric-cli bash |
1. 链码安装
以在org1, peer0 为例
1.1 设置环境变量
export CORE_PEER_LOCALMSPID=Org2MSP export CORE_PEER_ADDRESS=peer1.org2.example.com:7051 export CORE_PEER_MSPCONFIGPATH=/etc/hyperledger/fabric/crypto-config/peerOrganizations/org2.example.com/users/[email protected]/msp export CORE_PEER_TLS_ROOTCERT_FILE=/etc/hyperledger/fabric/crypto-config/peerOrganizations/org2.example.com/peers/peer1.org2.example.com/tls/ca.crt |
1.2 安装链码
# peer chaincode install -n test02 -v 1.0 -p examples/chaincode/go/chaincode_example02 |
修改相关环境变量和参数,重复步骤1.1 和1.2,在{org1, peer1},{org2, peer0},{org2, peer1}上安装链码
2.链码实例化
以下过程在任意一个节点执行一次就行。
peer chaincode instantiate \ -o orderer.example.com:7050 \ -C "businesschannel" \ -n test02 \ -v 1.0 \ -c '{"Args":["init","a","100","b","200"]}' \ -P "OR ('Org1MSP.member','Org2MSP.member')" \ --tls true \ --cafile /etc/hyperledger/fabric/crypto-config/ordererOrganizations/example.com/orderers/orderer.example.com/msp/tlscacerts/tlsca.example.com-cert.pem |
3.测试链码
3.1 查询初始值
# peer chaincode query -C "businesschannel" -n "exp02" -c '{"Args":["query","a"]}' |
# peer chaincode query -C "businesschannel" -n "exp02" -c '{"Args":["query","b"]}' |
3.2 转账:从"a" 的账户转账10到"b" 的账户
peer chaincode invoke \ -o orderer.example.com:7050 \ -C "businesschannel" \ -n "test02" \ -c '{"Args":["invoke","a","b","10"]}' \ --tls true \ --cafile /etc/hyperledger/fabric/crypto-config/ordererOrganizations/example.com/orderers/orderer.example.com/msp/tlscacerts/tlsca.example.com-cert.pem |
3.3 查询转账结果
# peer chaincode query -C "businesschannel" -n "test02" -c '{"Args":["query","a"]}' |
查询另一个节点{org2,peer1} 的账本
export CORE_PEER_LOCALMSPID=Org2MSP export CORE_PEER_ADDRESS=peer1.org2.example.com:7051 export CORE_PEER_MSPCONFIGPATH=/etc/hyperledger/fabric/crypto-config/peerOrganizations/org2.example.com/users/[email protected]/msp export CORE_PEER_TLS_ROOTCERT_FILE=/etc/hyperledger/fabric/crypto-config/peerOrganizations/org2.example.com/peers/peer1.org2.example.com/tls/ca.cr |
结果一致。
4.代码解析
4.1 引入必要的包
import ( "fmt" "strconv" "github.com/hyperledger/fabric/core/chaincode/shim" |
"github.com/hyperledger/fabric/core/chaincode/shim":shim包提供了链码与账本交互的中间层。
4.2 初始化
func (t *SimpleChaincode) Init(stub shim.ChaincodeStubInterface) pb.Response { ...... //提取参数 _, args := stub.GetFunctionAndParameters() ...... // 初始化链码 A = args[0] ...... B = args[2] Bval, err = strconv.Atoi(args[3]) ...... // 把状态写入账本 err = stub.PutState(A, []byte(strconv.Itoa(Aval))) |
4.3 Inovke方法
获取function值
function, args := stub.GetFunctionAndParameters() |
根据function值不同,执行不同的分支处理逻辑。
if function == "invoke" { // Make payment of X units from A to B return t.invoke(stub, args) } else if function == "delete" { // Deletes an entity from its state return t.delete(stub, args) } else if function == "query" { // the old "Query" is now implemtned in invoke return t.query(stub, args) } |
query分支
func (t *SimpleChaincode) query(stub shim.ChaincodeStubInterface, args []string) pb.Response { ...... A = args[0] // 从账本获得状态值 Avalbytes, err := stub.GetState(A) ...... } |
invoke分支
func (t *SimpleChaincode) invoke(stub shim.ChaincodeStubInterface, args []string) pb.Response { ...... //从账本获取"a"的值 Avalbytes, err := stub.GetState(A) ...... //从账本获取"b"的值 Bvalbytes, err := stub.GetState(B) ...... //执行转账 Aval = Aval - X ...... //结果计入账本 err = stub.PutState(A, []byte(strconv.Itoa(Aval))) ...... err = stub.PutState(B, []byte(strconv.Itoa(Bval))) ......} |
delete分支
func (t *SimpleChaincode) delete(stub shim.ChaincodeStubInterface, args []string) pb.Response { ...... //删除一个实体 err := stub.DelState(A) |
}
原文地址:http://blog.51cto.com/yinweiai/2084324