浅试Hyperledger Fabric go 小项目之应用应用代码

本文档介绍如何基于Hyperledger Fabric官方的gofabcar示例,编写Go语言应用代码与链码(智能合约)进行交互。首先解析了fabcar.go中的关键功能,包括用户注册、连接通道和调用链码函数。接着展示了如何在自己的项目中实现类似功能,包括连接和交互的代码示例。最后,给出了运行示例和总结。
摘要由CSDN通过智能技术生成

提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档


前言

上一篇记录了如何利用Hyperledger Fabric官方test-network运行自己的Chaincode流程,
链接这里
本文记录一个,参考官方 go fabcar示例编写自己的应用代码,并与cc交互。

一、fabcar示例

官方地址
go 语言 fabcar 项目目录结构
在这里插入图片描述
fabcar.go 主要的应用代码,runfabcar.sh 一个shell脚本,主要设置环境变量以及启动应用代码。

fabcar.go

主要包含三个功能:

注册和登记应用程序用户

//这个程序使用一个 证书签名请求 (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",
	)

连接通道和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")

测试与cc交互功能,也就是访问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

二、我的示例

应用程序 项目 目录结构
在这里插入图片描述

1.连接

封装了一中功能,函数直接调用,标注修改处,需要改成自己的
代码如下:

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",
		"User1@org1.example.com",
		"msp",
	)

	certPath := filepath.Join(credPath, "signcerts", "User1@org1.example.com-cert.pem")
	// 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)
}

main 中调用

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

2.与CC交互

交互函数 一 中示例,注意传参,参数1 CC中函数名,其他参数对应 CC 中函数的参数,只是string类型。
代码如下:

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...)
}

但是 数据结构,有数组类型

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

传参
在这里插入图片描述
cc 端接收
在这里插入图片描述
还可以,整个结构体对象整体json序列化,传递。cc端设置对应参数接收后 反序列化。两端参数要对应起来。

三 运行

将 runfabcar.sh 中 go run fabcar.go 换为自己的代码名称即可。

sh runfabcar.sh

运行后如下所示:
在这里插入图片描述

总结

第一次写go和使用Hyperledger Fabric交互的代码,供新手参考理解,自己摸索多有不足,请各位大佬包含指正。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值