Hyperledger Fabric测试不同组织链码调用

Hyperledger Fabric测试不同组织链码调用

在熟悉fabric的各种操作之后,开始针对多组织智能合约的应用,发现不同组织的链码应该不同,这时候相互调用涉及到一个链码如何部署的问题。


本测试环境,fabric1.1版本,两个组织A和B,其中A安装官方链码go/src/github.com/hyperledger/fabric/examples/chaincode/go/chaincode_example02
B安装我自己写的链码,链码里调用官方链码的交易以及查询功能,链码如下:

//为了操作更简便,我把调用的参数写的跟A组织传入一样,后面操作只要修改链码名称就可以了,invoke和query均相同。
package main

import (
  "fmt"
  "github.com/hyperledger/fabric/core/chaincode/shim"
  pb "github.com/hyperledger/fabric/protos/peer"
)

// SimpleChaincode example simple Chaincode implementation
type SimpleChaincode struct {
}

func (t *SimpleChaincode) Init(stub shim.ChaincodeStubInterface) pb.Response {
  fmt.Println("ChaincodeInvoke Init")
  return shim.Success(nil)
}

func (t *SimpleChaincode) Invoke(stub shim.ChaincodeStubInterface) pb.Response {
  fmt.Println("ChaincodeInvoke Invoke")
  function, args := stub.GetFunctionAndParameters()
  if function == "invoke" {
     //调用A链码的invoke
     return t.invoke(stub, args)
  } else if function == "query" {
   //调用A链码的query
     return t.query(stub, args)
  }

  return shim.Error("Invalid invoke function name. Expecting \"invoke\" \"delete\" \"query\"")
}
func (t *SimpleChaincode) invoke(stub shim.ChaincodeStubInterface, args []string) pb.Response {
  var A, B string    // Entities
  if len(args) != 3 {
     return shim.Error("Incorrect number of arguments. Expecting 3")
  }
  A = args[0]
  B = args[1]
  parm1:=[]string{"invoke",A,B,args[2]}
  queryArgs:=make([][]byte,len(parm1))
  for i,arg:=range parm1{
     queryArgs[i]=[]byte(arg)
  }
  response:=stub.InvokeChaincode("mychannel",queryArgs,"mychannel")
  if response.Status !=shim.OK{
     return shim.Error("failed to invoke other chaincode")
  }
  result:=string(response.Payload)
  return shim.Success([]byte("success to invoke:"+result)) //和官方输出有点区别,我这里输出多了个“success to invoke",便于区分

}

func (t *SimpleChaincode) query(stub shim.ChaincodeStubInterface, args []string) pb.Response {
  if len(args) != 1 {
     return shim.Error("Incorrect number of arguments. Expecting 1")
  }
  account:=args[0]
  parm1:=[]string{"query",account}
  queryArgs:=make([][]byte,len(parm1))
  for i,arg:=range parm1{
     queryArgs[i]=[]byte(arg)
  }
  response:=stub.InvokeChaincode("mychannel",queryArgs,"mychannel")
  if response.Status !=shim.OK{
     return shim.Error("failed to invoke other chaincode")
  }
  result:=string(response.Payload)
  return shim.Success([]byte("success to invoke:"+result))
}

func main() {
  err := shim.Start(new(SimpleChaincode))
  if err != nil {
     fmt.Printf("Error starting Simple chaincode: %s", err)
  }
}

想到这个问题的,环境肯定都没啥问题,这里直接说结果。
A组织安装example链码,实例化

peer chaincode install -n mychannel -p github.com/hyperledger/fabric/aberic/chaincode/go/chaincode_example02 -v 1.0
peer chaincode instantiate -o orderer.example.com:7050 -C mychannel -n mychannel -c '{"Args":["init","A","100","B","100"]}' -P "OR ('Org1MSP.member','Org2MSP.member')" -v 1.0
peer chaincode query -C mychannel -n mychannel -c '{"Args":["query","A"]}'
peer chaincode invoke -C mychannel -n mychannel -c '{"Args":["invoke","A","B","5"]}'
//官方链码很简单,实例化的时候,A,B两个账户存100快,然后invoke是AB之间转账,这里是A给B转账5块钱。
转完之后A 95,B 105.
peer channel list   //列出当前通道
peer chaincode list --installed //列出当前组织安装的链码
peer chaincode list --instantiated -C mychannel //列出通道已经实例化的链码

切换到另外个组织B,我这里嫌麻烦用的是单机,执行的是cli客户端操作,修改一下cli容器的环境变量就可以。

peer channel join -b mychannel.block //加入创建的通道
peer chaincode install -n test -p github.com/hyperledger/fabric/aberic/chaincode/go/test -v 1.0
peer chaincode instantiate -o orderer.example.com:7050 -C mychannel -n test -c '{"Args":[]}' -P "OR ('Org1MSP.member','Org2MSP.member')" -v 1.0
peer chaincode query -C mychannel -n test -c '{"Args":["query","A"]}'//操作失败,显示找不到链码
peer chaincode invoke -C mychannel -n test -c '{"Args":["invoke","A","B","10"]}'

peer chaincode list --installed //列出B组织安装的链码,可以看到只有B组织test链码
peer chaincode list --instantiated -C mychannel //这里可以看到mychannel通道里实例化链码包括A组织的和B组织的

原因:虽然都在同一个通道,但是AB组织都只有各自的链码,即使B组织链码调用了A链码,但是B组织没有安装链码,无法执行A链码的逻辑。

修改
在B组织安装A的链码,B的链码就可以调用了,同时由于B安装A的链码,所以在B组织执行A链码也是ok的,
感觉这里相当于把A的链码当成一个函数传入了。安装A链码,就相当于引入了这个库,要不然找不到。
//B安装A的链码不需要实例化,同一个通道的某个链码只需要实例化一次。
peer chaincode list --installed //列出B组织安装的链码,可以看到AB链码均存在了。
peer chaincode query -C mychannel -n test -c '{"Args":["query","A"]}'//成功,和A组织执行查询结果相同
peer chaincode invoke -C mychannel -n test -c '{"Args":["invoke","A","B","10"]}'//成功,和A组织执行交易结果相同
------
ps:多加一句,回到A组织,查询安装的链码只有官方链码,所以A还是智能查询A自己的链码。

图都都没贴,但是核心链码和步骤都写了,记住结论,如果一个组织要调用其他链码,那么当前组织一定要安装调用的链码

猜你喜欢

转载自blog.csdn.net/hungrylion/article/details/109288785
今日推荐