Hyperledger Fabric chaincode development practice log

1. Overview of chain code structure

Here, the development of the chain code uses the Go language. For this reason, you need to learn the Go language briefly. This is a lightweight language. The interesting thing is that it has its own channels and can be concurrent, which is very suitable for large-scale distributed systems. Development.
To start the chain code, the Start function in the shim package must be called. The parameter of this function is a Chaincode interface type. There are two methods in the Chaincode interface type, Init and Invoke. These are two extremely important methods in chain code development:

  • Init: Called when the chain code is instantiated or upgraded to complete data initialization;
  • Invoke: Called when updating or querying the status of the ledger data in a proposal transaction.

In actual development, you need to define a structure and rewrite the Init and Invoke methods to complete related functions. Let's take a concrete look at the necessary structure of a chain code:

package main //所写的包的名称

import (
        "fmt"
        "github.com/hyperledger/fabric/core/chaincode/shim"
        "github.com/hyperledger/fabric/protos/peer"
)//引入必要的包

type HelloChaincode struct{
    
    }//定义一个结构体

func main() {
    
    
        err := shim.Start(new(HelloChaincode))
        if err != nil {
    
    
                fmt.Printf("链码启动失败: %v", err)
        }
}//主函数,调用shim.Start方发启动链码

func (t *HelloChaincode) Init(stub shim.ChaincodeStubInterface) peer.Response{
    
    
       
}

func (t *HelloChaincode) Invoke(stub shim.ChaincodeStubInterface) peer.Response{
    
            fun, args := stub.GetFunctionAndParameters()
       
}

2. Familiar with chaincode related API

Mainly the API provided by the shim package, divided into 5 categories:

  1. Parameter analysis API: used to obtain parameters
  2. Ledger data status operation API: query and update account data, etc.
  3. Transaction information acquisition API: get submitted transaction information
  4. Event processing API: related to event processing
  5. API for private data manipulation: specifically for private data manipulation

The number of APIs is still relatively large, most of which are for obtaining relevant information. If you have time, you can take a closer look. The main ones used in the initial stage:

  • GetFunctionAndParameters()(function string, params []string) returns the name of the called function and the list of parameters
  • GetStringArgs()[]string returns the parameter list directly
  • GetState(key string)([]byte,error) Query the data state according to the specified key value
  • PutState(key string,value []byte)error According to the specified key, save the corresponding value to the ledger

3. Chaincode implements Hello World

3.1 Chaincode development

First write a hello world to practice hands.

  1. Go to the chaincode directory and create a folder named hello, then create and edit the chaincode file:
sudo mkdir hello && cd hello
sudo vim hello.go
  1. Import the chain code dependency package:
package main

import (
			"fmt"
			"github.com/hyperledger/fabric/core/chaincode/shim"
			"github.com/hyperledger/fabric/protos/peer"
		)
  1. Write the main function:
func main() {
    
    
			err := shim.Start(new(HelloChaincode))
			if err != nil {
    
    
				fmt.Printf("链码启动失败: %v", err)
			}
}
  1. Custom structure:
type HelloChaincode struct{
    
    }
  1. Rewrite the Init method. Its function is to initialize the data state. A simple logical step is as follows:
  • Obtain parameters and determine whether the parameters are legal;
  • Call PutState function to write the state into the ledger;
  • Whether there is a write error;
  • Finally, call the Success function to return a success status.
func (t *HelloChaincode) Init(stub shim.ChaincodeStubInterface) peer.Response{
    
    
		    fmt.Println("开始实例化链码")
			_, args := stub.GetFunctionAndParameters()
			if len(args) != 2 {
    
    
				return shim.Error("指定了错误的参数个数")
			}
			fmt.Println("保存数据")
			err := stub.PutState(args[0],[]byte(args[1]))
			if err !=nil{
    
    
				return shim.Error("保存数据时发生错误")
			}
			fmt.Println("实例化成功")
			return shim.Success(nil)
}

You can pay attention to the GetFunctionAndParameters() function, where the parameter form is: "Args":["init","Hello","Wzh"], the function gets the called function "init" and the passed parameter "Hello" ","Wzh", so written in the form of _,args, can also be replaced with GetStringArgs() function to directly get the following parameters.

  1. Rewrite the Invoke method, its simple logic is:
  • Obtain parameters and determine whether the parameters are legal;
  • Use the key value to get the status;
  • Complete the function of the called function;
  • Return data status or success status.
func (t *HelloChaincode) Invoke(stub shim.ChaincodeStubInterface) peer.Response{
    
    	fun, args := stub.GetFunctionAndParameters()
			if fun == "query"{
    
    
				return query(stub,args)
			}
			return shim.Error("非法操作,指定功能不能实现")
}

func query(stub shim.ChaincodeStubInterface,args  []string) peer.Response{
    
    
			if len(args) !=1{
    
    
				return shim.Error("指定的参数错误,必须且只能指定相应的Key")
			}
			result,err :=stub.GetState(args[0])
			if err !=nil {
    
    
				return shim.Error("根据指定的" +args[0] +"查询数据时发生错误")
			}
			if result ==nil {
    
    
				return shim.Error("根据指定的" +args[0] +"没有查询到相应的数据")
			}
			return shim.Success(result)
}

This piece of code is very simple and clear, so I won't repeat it.

3.2 Chaincode test

It's the link of chain code testing again. The specific process is in the previous log. Only the code is attached below:

cd chaincode-docker-devmode
sudo docker-compose -f docker-compose-simple.yaml up -d

Open the terminal 2 window:

sudo docker exec -it chaincode bash
cd hello
go build
CORE_PEER_ADDRESS=peer:7052 CORE_CHAINCODE_ID_NAME=hellocc:0 ./hello

Open the terminal 3 window:

sudo docker exec -it cli bash、
peer chaincode install -p chaincodedev/chaincode/hello -n hellocc -v 0
peer chaincode instantiate -n hellocc -v 0 -c '{"Args":["init","Hello","Wzh"]}' -C myc
peer chaincode query -n hellocc  -c '{"Args":["query","Hello"]}' -C myc

The final query should be able to get Wzh (that is, the content of the Hello key assignment)

Guess you like

Origin blog.csdn.net/weixin_43107949/article/details/109350623