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

浅试Hyperledger Fabric go 小项目之应用应用代码,第1张

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

文章目录 前言一、fabcar示例fabcar.go注册和登记应用程序用户连接通道和cc测试与cc交互功能,也就是访问cc的函数 runfabcar.sh 二、我的示例1.连接2.与CC交互 三 运行总结


前言

上一篇记录了如何利用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交互的代码,供新手参考理解,自己摸索多有不足,请各位大佬包含指正。

欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/zaji/925373.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-05-16
下一篇 2022-05-16

发表评论

登录后才能评论

评论列表(0条)

保存