文章目录 前言一、fabcar示例fabcar.go注册和登记应用程序用户连接通道和cc测试与cc交互功能,也就是访问cc的函数 runfabcar.sh 二、我的示例1.连接2.与CC交互 三 运行总结提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档
前言
上一篇记录了如何利用Hyperledger Fabric官方test-network运行自己的Chaincode流程,
链接这里
本文记录一个,参考官方 go fabcar示例编写自己的应用代码,并与cc交互。
官方地址
go 语言 fabcar 项目目录结构
fabcar.go 主要的应用代码,runfabcar.sh 一个shell脚本,主要设置环境变量以及启动应用代码。
主要包含三个功能:
注册和登记应用程序用户//这个程序使用一个 证书签名请求 (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
二、我的示例
应用程序 项目 目录结构
封装了一中功能,函数直接调用,标注修改处,需要改成自己的
代码如下:
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交互的代码,供新手参考理解,自己摸索多有不足,请各位大佬包含指正。
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)