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自己的链码。

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

### 回答1: 下面是一个简单的 Hyperledger Fabric 2.0 Go语言链码示例: ``` package main import ( "fmt" "github.com/hyperledger/fabric-chaincode-go/shim" pb "github.com/hyperledger/fabric-protos-go/peer" ) // SimpleChaincode example simple Chaincode implementation type SimpleChaincode struct { } func (t *SimpleChaincode) Init(stub shim.ChaincodeStubInterface) pb.Response { fmt.Println("ex02 Init") _, args := stub.GetFunctionAndParameters() var A, B string // Entities var Aval, Bval int // Asset holdings var err error if len(args) != 4 { return shim.Error("Incorrect number of arguments. Expecting 4") } // Initialize the chaincode A = args[0] Aval, err = strconv.Atoi(args[1]) if err != nil { return shim.Error("Expecting integer value for asset holding") } B = args[2] Bval, err = strconv.Atoi(args[3]) if err != nil { return shim.Error("Expecting integer value for asset holding") } fmt.Printf("Aval = %d, Bval = %d\n", Aval, Bval) // Write the state to the ledger err = stub.PutState(A, []byte(strconv.Itoa(Aval))) if err != nil { return shim.Error(err.Error()) } err = stub.PutState(B, []byte(strconv.Itoa(Bval))) if err != nil { return shim.Error(err.Error()) } return shim.Success(nil) } func (t *SimpleChaincode) Invoke(stub shim.ChaincodeStubInterface) pb.Response { fmt.Println("ex02 Invoke") function, args := stub.GetFunctionAndParameters() 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) } return shim.Error("Invalid invoke function name. Expecting \"invoke\" \"delete\" \"query\"") } // Transaction makes payment of X units from A to B func (t *SimpleChaincode) invoke(stub shim.ChaincodeStubInterface, args []string) pb.Response { var A, B string // Entities var Aval, Bval int // Asset holdings var X int // Transaction value var err error ### 回答2: Hyperledger Fabric 是一个开源的区块链平台,可以用于构建企业级的去中心化应用程序。而 Hyperledger Fabric 2.0 是其最新版本,引入了许多新特性和改进。 编写一个 Hyperledger Fabric 2.0 的 Go 语言链码需要按照一定的流程进行: 1. 准备开发环境:首先,需要安装 Go 语言的开发环境和 Hyperledger Fabric 的相关工具,如 Hyperledger Fabric SDK 和 Hyperledger Fabric CA。 2. 编写链码逻辑:使用 Go 语言编写链码的逻辑,链码是在 Hyperledger Fabric 上运行的智能合约。可以根据项目需求和业务逻辑定义相关的数据结构和函数。 3. 定义链码接口:需要定义链码接口,包括 Init 和 Invoke 两个核心函数。Init 函数用于链码的初始化操作,而 Invoke 函数用于链码的业务逻辑执行。 4. 部署链码:将编写好的链码部署到 Hyperledger Fabric 网络中。可以使用 Hyperledger Fabric SDK 提供的工具和 API 来进行链码的部署操作。 5. 测试链码:编写相应的测试用例,对链码逻辑进行测试。可以使用模拟的 Fabric 网络进行测试,或者与实际的 Fabric 网络交互进行测试。 6. 部署链码应用程序:将编写好的链码应用程序部署到 Hyperledger Fabric 网络上。可以使用 Hyperledger Fabric SDK 提供的工具和 API 来进行链码应用程序的部署操作。 Go 语言是一种高性能的编程语言,适合于开发区块链平台和链码。编写 Hyperledger Fabric 2.0 的 Go 语言链码需要熟悉 Go 语言的基本语法和特性,以及了解 Hyperledger Fabric 的相关知识。通过合理的设计和编码,可以实现各种复杂的业务逻辑和功能。 ### 回答3: 编写一个Hyperledger Fabric 2.0的Go语言链码可以分为以下几个步骤: 1. 准备开发环境:首先,需要在开发机器上安装Go语言和Hyperledger Fabric的相关依赖。可以通过配置Golang环境变量,并使用Golang包管理器安装Fabric的Go SDK。 2. 创建链码项目:使用Go语言的IDE或文本编辑器创建一个新的文件夹,作为链码项目的根目录。 3. 定义链码结构:创建一个新的Go文件,并定义链码结构。链码结构应该实现fabric的Chaincode接口,并实现Init和Invoke两个方法。 4. 实现Init方法:Init方法在链码被实例化时调用,并进行初始化设置。可以在该方法中初始化链码的状态数据和其他必要的准备工作。 5. 实现Invoke方法:Invoke方法在链码接收到调用请求时被调用。在该方法中处理具体的业务逻辑,并根据请求中的操作类型执行相应的操作。 6. 将链码打包:使用Fabric提供的命令行工具将链码打包成压缩文件,以便于后续部署和安装。 7. 部署和安装链码:使用Fabric提供的链码生命周期管理工具,将链码部署到指定的Fabric网络中,并安装到指定的通道上。 8. 实例化链码:在指定的通道上实例化链码,使其可以被其他参与方调用。 9. 调用链码:使用Fabric提供的客户端SDK或命令行工具,向链码发送调用请求,验证链码的功能和逻辑是否正确。 10. 测试链码:编写一些测试用例,用于对链码的功能和性能进行验证。 以上是一个简要的步骤,编写Hyperledger Fabric 2.0的Go语言链码还需要进一步了解链码开发的相关知识和Fabric的API,以有效地实现业务逻辑,并与Fabric网络进行交互。
评论 11
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值