Try the application code of Hyperledger Fabric go small project

Tip: After the article is written, the table of contents can be automatically generated. How to generate it can refer to the help document on the right


foreword

The previous article recorded how to use Hyperledger Fabric official test-network to run your own Chaincode process,
link here
This article records one, refer to the official go fabcar example to write your own application code, and interact with cc.

1. fabcar example

Official address
go language fabcar project directory structure
insert image description here
fabcar.go is the main application code, runfabcar.sh is a shell script that mainly sets environment variables and starts the application code.

fabcar.go

It mainly contains three functions:

Registering and Enrolling Application Users

//这个程序使用一个 证书签名请求 (CSR)——现在本地生成公钥和私钥,然后把公钥发送到 CA ,CA 会发布会一个让应用程序使用的证书。这三个证书会保存在钱包中,以便于我们以管理员的身份使用 CA 。
os.Setenv("DISCOVERY_AS_LOCALHOST", "true")
	wallet, err := gateway.NewFileSystemWallet("wallet")
	if err != nil {
    
    
		fmt.Printf("Failed to create wallet: %s\n", err)
		os.Exit(1)
	}
// 创建一个新的应用程序用户,它将被用于与区块链交互。
// populateWallet 拿到用户的证书凭据
	if !wallet.Exists("appUser") {
    
    
		err = populateWallet(wallet)
		if err != nil {
    
    
			fmt.Printf("Failed to populate wallet contents: %s\n", err)
			os.Exit(1)
		}
	}
//代码中存在路径定义 要换成自己的路径
ccpPath := filepath.Join(
		"..",
		"..",
		"test-network",
		"organizations",
		"peerOrganizations",
		"org1.example.com",
		"connection-org1.yaml",
	)

connect channel and cc

gw, err := gateway.Connect(
//身份认证		gateway.WithConfig(config.FromFile(filepath.Clean(ccpPath))),
		gateway.WithIdentity(wallet, "appUser"),
	)
	if err != nil {
    
    
		fmt.Printf("Failed to connect to gateway: %s\n", err)
		os.Exit(1)
	}
	defer gw.Close()
// 连接通道
// 改成自己的名称
	network, err := gw.GetNetwork("mychannel")
	if err != nil {
    
    
		fmt.Printf("Failed to get network: %s\n", err)
		os.Exit(1)
	}
//连接智能合约
// 改成自己的名称
	contract := network.GetContract("fabcar")

Test the function of interacting with cc, that is, the function of accessing cc

//测试创建
result, err = contract.SubmitTransaction("createCar", "CAR10", "VW", "Polo", "Grey", "Mary")
//查询
result, err = contract.EvaluateTransaction("queryCar", "CAR10")
//修改
_, err = contract.SubmitTransaction("changeCarOwner", "CAR10", "Archie")	

runfabcar.sh

ENV_DAL=`echo $DISCOVERY_AS_LOCALHOST`

echo "ENV_DAL:"$DISCOVERY_AS_LOCALHOST

if [ "$ENV_DAL" != "true" ]
then
	export DISCOVERY_AS_LOCALHOST=true
fi

echo "DISCOVERY_AS_LOCALHOST="$DISCOVERY_AS_LOCALHOST

echo "run fabcar..."
# 修改此处改为自己的启动代码名称即可
go run fabcar.go

Two, my example

Application project directory structure
insert image description here

1. connect

Encapsulate a function, call the function directly, mark the modification, you need to change it into your own
code as follows:

func Getcontract1() *gateway.Contract {
    
    
	err := os.Setenv("DISCOVERY_AS_LOCALHOST", "flase")
	if err != nil {
    
    
		log.Fatalf("Error setting DISCOVERY_AS_LOCALHOST environemnt variable: %v", err)
	}
	wallet, err := gateway.NewFileSystemWallet("wallet")
	if err != nil {
    
    
		log.Fatalf("Failed to create wallet: %v", err)
	}
	if !wallet.Exists("appUser") {
    
    
		err = populateWallet1(wallet)
		if err != nil {
    
    
			log.Fatalf("Failed to populate wallet contents: %v", err)
		}
	}
//修改
	ccpPath := filepath.Join(
		"..",
		"github.com",
		"fabric-samples",
		"test-network",
		"organizations",
		"peerOrganizations",
		"org1.example.com",
		"connection-org1.yaml",
	)

	gw, err := gateway.Connect(
		// lyj:使用ccpath 的路径 以及 appuser 的身份认证 通过使用Gateway类连接网络
		gateway.WithConfig(config.FromFile(filepath.Clean(ccpPath))),
		gateway.WithIdentity(wallet, "appUser"),
	)
	if err != nil {
    
    
		log.Fatalf("Failed to connect to gateway: %v", err)
	}
	defer gw.Close()
//修改
	network, err1 := gw.GetNetwork("channeltest")
	if err != nil {
    
    
		log.Fatalf("Failed to get network: %v", err1)
	}
//修改
	contract := network.GetContract("savelist")

	return contract
}
func populateWallet1(wallet *gateway.Wallet) error {
    
    
//修改
	credPath := filepath.Join(
		"..",
		// "src",
		"github.com",
		"fabric-samples",
		"test-network",
		"organizations",
		"peerOrganizations",
		"org1.example.com",
		"users",
		"[email protected]",
		"msp",
	)

	certPath := filepath.Join(credPath, "signcerts", "[email protected]")
	// read the certificate pem
	cert, err := ioutil.ReadFile(filepath.Clean(certPath))
	if err != nil {
    
    
		return err
	}

	keyDir := filepath.Join(credPath, "keystore")
	// there's a single file in this dir containing the private key
	files, err := ioutil.ReadDir(keyDir)
	if err != nil {
    
    
		return err
	}
	if len(files) != 1 {
    
    
		return fmt.Errorf("keystore folder should have contain one file")
	}
	keyPath := filepath.Join(keyDir, files[0].Name())
	key, err := ioutil.ReadFile(filepath.Clean(keyPath))
	if err != nil {
    
    
		return err
	}

	identity := gateway.NewX509Identity("Org1MSP", string(cert), string(key))

	return wallet.Put("appUser", identity)
}

call in main

func main() {
    
    
	var contract *gateway.Contract
	contract = manufacture.Getcontract1()
	}

2. Interact with CC

Example of interactive function 1, pay attention to parameter passing, parameter 1 is the function name in CC, and other parameters correspond to the parameters of the function in CC, which are only string type.
code show as below:

func (c *Contract) SubmitTransaction(name string, args ...string) ([]byte, error) {
    
    
	txn, err := c.CreateTransaction(name)

	if err != nil {
    
    
		return nil, err
	}

	return txn.Submit(args...)
}

func (c *Contract) EvaluateTransaction(name string, args ...string) ([]byte, error) {
    
    
	txn, err := c.CreateTransaction(name)

	if err != nil {
    
    
		return nil, err
	}

	return txn.Evaluate(args...)
}

But the data structure, there is an array type

type SvcInfo struct {
    
    
	SvcID            string   `json:"SvcID"`
	ManufacturerName string   `json:"ManufacturerName"`
	SvcName          string   `json:"SvcName"`
	SaveSvc          []string `json:"SaveSvc"`
}

It is also possible to pass parameters to
insert image description here
the cc terminal to receive
insert image description here
, and the entire structure object is serialized in json as a whole and passed on. The cc terminal sets the corresponding parameters and deserializes them after receiving them. The parameters at both ends should correspond.

Three runs

Just replace go run fabcar.go in runfabcar.sh with your own code name.

sh runfabcar.sh

After running it looks like this:
insert image description here

Summarize

It is the first time to write go and interact codes using Hyperledger Fabric for reference and understanding by novices. There are many deficiencies in self-exploration, and please correct me.

Guess you like

Origin blog.csdn.net/qq_43341918/article/details/124059637