7.2.2 Interchain Services based on Hyperledger Fabric

Application Contract Development Guide in BSN production environment

The development of Fabric application contract is based on its own business scenario. The main implementation includes two parts: if the source chain initiates a cross-chain transaction, its application contract needs to get outbound to access the target chain; if the target chain receives a cross-chain transaction, its application contract needs to get inbound. Fabric's chain IDand cross-chain management contract’s name are automatically assigned and generated through the BSN operations and maintenance system when users open interchain services, and can be viewed in the BSN portal.

Below is an example of a source chain initiating a cross-chain transaction call:

/**
 * @Author AndyCao
 * @Date 2020-11-4 18:27
 * @Description: This method is used for calling other target chains across the chain. (This method can be self-defined)
 * @Param
 * @Return
 **/
func (t*HelloPoly) say(stub shim.ChaincodeStubInterface, args []string) 
peer.Response {
   setLogger("The say method is called......")
   defer setLogger("End called say method......")
   // Checking configuration
   if len(args) != 4 {
      return shim.Error("Parameter error!!!")
   }
   // Save data
   if err:=stub.PutState(args[1],[]byte(args[2]));err!=nil{
      return shim.Error(fmt.Sprintf("Failed to save data: %v", err))
   }
   //Build cross-chain management contract calling parameters
// args[0] is the target chain ID
// args[1] is the target chain application contract name (or contract address)
// args[2] is the calling method name of the  target chain
// args[3] is the calling parameter

ccArgs := []string{"crossChain",
   args[0],
   hex.EncodeToString([]byte(args[1])),
   args[2],
   hex.EncodeToString([]byte(args[3]))}   // Calling cross-chain management contract 
   var resp = stub.InvokeChaincode(string("ccm"), invokeArgs, "")
   if resp.Status != shim.OK {
      return shim.Error(fmt.Sprintf("Failed to call the cross-chain management contract %s: %s", "ccm", resp.Message))
   }
   // Set event notification 
   if err := stub.SetEvent("from_ccm", resp.Payload); err != nil {
      return shim.Error(fmt.Sprintf("Event setting failed: %v", err))
   }
   setLogger("Successfully call the cross-chain management contract for cross-chain: (target chain ID: %d, target chain contract address: %x, cross-chain message: %s)", args[1], args[1], args[2])
   return shim.Success(nil)
}
func packArgs(args []string) [][]byte {
   r := [][]byte{}
   for _, s := range args {
      temp := []byte(s)
      r = append(r, temp)
   }
   return r
}

Below is an example of a target chain call when receiving a cross-chain transaction:

**
 * @Author AndyCao
 * @Date 2020-11-4 18:28
 * @Description: This method is used for calling other target chains across the chain. (This method can be self-defined)
 * @Param
 * @Return
 **/
func (t *HelloPoly) hear(stub shim.ChaincodeStubInterface, args []string) 
peer.Response {
   setLogger("The hear method is called......")
   defer setLogger("End called hear method......")
   // Checking parameters
   if len(args) != 1 {
      return shim.Error("Parameter error!!!")
   }

   // Save the cross-chain information committed by the source chain 
   if err:=stub.PutState("FABRIC_CROSS_CHAIN",[]byte(args[0]));err!=nil {
      return shim.Error(fmt.Sprintf("Failed to save data: %v", err))
   }
   return shim.Success([]byte("SUCCESS"))
}

Application Contract Development Guide in BSN Testnet

Fabric's chain ID in the BSN China Testnet is 8 and in the BSN International Testnet is 9. This chain ID is registered in Poly Enterprise, not the channel ID corresponding to Fabric itself. The name of Fabric cross-chain contract is ccm.

Below is an example of a source chain initiating a cross-chain transaction call:

/**
 * @Author AndyCao
 * @Date 2020-11-4 18:27
 * @Description: This method is used for calling other target chains across the chain. (This method can be self-defined)
 * @Param
 * @Return
 **/
func (t*HelloPoly) say(stub shim.ChaincodeStubInterface, args []string) 
peer.Response {
   setLogger("The say method is called......")
   defer setLogger("End called say method......")
   // Checking configuration
   if len(args) != 4 {
      return shim.Error("Parameter error!!!")
   }
   // Save data
   if err:=stub.PutState(args[1],[]byte(args[2]));err!=nil{
      return shim.Error(fmt.Sprintf("Failed to save data: %v", err))
   }
   //Build cross-chain management contract calling parameters
   invokeArgs := make([][]byte, 6)
   // Set the calling method of the cross-chain management contract 
   invokeArgs[0] = []byte("crossChain")
   // Set the chain corresponding to the target chain in Poly network 
   invokeArgs[1] = []byte(args[0])
    // Set the target chain’s smart contract address, note:
    // 1. If the target chain is fabric, then this is the name of the application contract, for example:mycc; if the target chain is fisco/eth/neo, then this is the name of the application contract, for example: 11..., don't add "0x" prefix.
    // 2. The parameters passed to the cross-chain management contract must be EncodeToString converts bytes to hex strings and then transform to byte arrays. 
if args[0]=="8"||args[0]=="9"{ 
    invokeArgs[2] = []byte(hex.EncodeToString([]byte(args[1]))) 
 }else{ 
invokeArgs[2] = []byte(args[1])
    }
   // Target chain’s application contract method
   invokeArgs[3] = []byte("hear")
   // Cross-chain information that target chain’s application contract needs to pass(Note: The parameters passed to the cross-chain management contract must be EncodeToString converts bytes to hex strings and then transform to byte arrays.) 
   invokeArgs[4] = []byte(args[2])
   // Name of the application contract
   invokeArgs[5] = []byte(args[3])
   // Calling cross-chain management contract 
   var resp = stub.InvokeChaincode(string("ccm"), invokeArgs, "")
   if resp.Status != shim.OK {
      return shim.Error(fmt.Sprintf("Failed to call the cross-chain management contract %s: %s", "ccm", resp.Message))
   }
   // Set event notification 
   if err := stub.SetEvent("from_ccm", resp.Payload); err != nil {
      return shim.Error(fmt.Sprintf("Event setting failed: %v", err))
   }
   setLogger("Successfully call the cross-chain management contract for cross-chain: (target chain ID: %d, target chain contract address: %x, cross-chain message: %s)", args[1], args[1], args[2])
   return shim.Success(nil)
}

Below is an example of a target chain call when receiving a cross-chain transaction:

**
 * @Author AndyCao
 * @Date 2020-11-4 18:28
 * @Description: This method is used for calling other target chains across the chain. (This method can be self-defined)
 * @Param
 * @Return
 **/
func (t *HelloPoly) hear(stub shim.ChaincodeStubInterface, args []string) peer.Response {
   setLogger("The hear method is called......")
   defer setLogger("End called hear method......")
   // Checking parameters
   if len(args) != 1 {
      return shim.Error("Parameter error!!!")
   }

   // Save the cross-chain information committed by the source chain 
   if err:=stub.PutState("FABRIC_CROSS_CHAIN",[]byte(args[0]));err!=nil {
      return shim.Error(fmt.Sprintf("Failed to save data: %v", err))
   }
   return shim.Success([]byte("SUCCESS"))

Demo Contract Example

BSN production environment:

https://github.com/BSNDA/ICH/tree/main/sample/polychain/fabric-contract/online/hellopoly

BSN Testnet:

https://github.com/BSNDA/ICH/tree/main/sample/polychain/fabric-contract/testnet/hellopoly

© 2019-2020 Red Date (Hong Kong) Technology Limited. all right reserved,powered by GitbookFile Modify: 2021-01-29 19:00:36

results matching ""

    No results matching ""

    results matching ""

      No results matching ""