Fabric 票据项目(三)使用Fabric SDK go

Fabric项目结构

Fabric 票据项目(三)2

用户通过浏览器访问项目的Goweb服务,service通过SDK调用链码查询或更新数据,链码将结果返回给service,Goweb服务将结果展示给用户

一、配置应用参数

应用程序需要很多参数,特别是Fabric组件的通信地址。 现在把所有内容放入新的配置文件中(Fabric SDK Go配置和自定义参数)。

$ cd $GOPATH/src/zhq/bill
$ vim config.yaml

将下面内容拷贝到config.yaml中,文件中的路径替换为自己的项目路径


name: "bill-network"

# Describe what the target network is/does.
description: "The network which will host my first blockchain"

# Schema version of the content. Used by the SDK to apply the corresponding parsing rules.
version: 2

# The client section used by GO SDK.
client:
  # Which organization does this application instance belong to? The value must be the name of an org
  organization: Org1
  logging:
    level: info

  # Global configuration for peer, event service and orderer timeouts
  peer:
    timeout:
      connection: 3s
      queryResponse: 45s
      executeTxResponse: 30s
  eventService:
    timeout:
      connection: 3s
      registrationResponse: 3s
  orderer:
    timeout:
      connection: 3s
      response: 5s

  # Root of the MSP directories with keys and certs. The Membership Service Providers is component that aims to offer an abstraction of a membership operation architecture.
  #组织结构路径
  cryptoconfig:
    path: "${GOPATH}/src/zhq/bill/fixtures/crypto-config"

  # Some SDKs support pluggable KV stores, the properties under "credentialStore" are implementation specific
  credentialStore:
    path: "/tmp/bill-kvs"

     # [Optional]. Specific to the CryptoSuite implementation used by GO SDK. Software-based implementations requiring a key store. PKCS#11 based implementations does not.
    cryptoStore:
      path: "/tmp/bill-msp"

  # BCCSP config for the client. Used by GO SDK. It's the Blockchain Cryptographic Service Provider.
  # It offers the implementation of cryptographic standards and algorithms.
  #设置加密方式为软件密,sha256
  BCCSP:
    security:
     enabled: true
     default:
      provider: "SW"
     hashAlgorithm: "SHA2"
     softVerify: true
     ephemeral: false
     level: 256

  tlsCerts:
    systemCertPool: false

# [Optional]. But most apps would have this section so that channel objects can be constructed based on the content below.
# If one of your application is creating channels, you might not use this
channels:
  mychannel:
    orderers:
      - orderer.example.com

    # Network entity which maintains a ledger and runs chaincode containers in order to perform operations to the ledger. Peers are owned and maintained by members.
    peers:
      peer0.org1.example.com:
        # [Optional]. will this peer be sent transaction proposals for endorsement? The peer must
        # have the chaincode installed. The app can also use this property to decide which peers
        # to send the chaincode install request. Default: true
        endorsingPeer: true

        # [Optional]. will this peer be sent query proposals? The peer must have the chaincode
        # installed. The app can also use this property to decide which peers to send the
        # chaincode install request. Default: true
        chaincodeQuery: true

        # [Optional]. will this peer be sent query proposals that do not require chaincodes, like
        # queryBlock(), queryTransaction(), etc. Default: true
        ledgerQuery: true

        # [Optional]. will this peer be the target of the SDK's listener registration? All peers can
        # produce events but the app typically only needs to connect to one to listen to events.
        # Default: true
        eventSource: true

      peer1.org1.example.com:

# List of participating organizations in this network
organizations:
  Org1:
    mspid: Org1MSP
    cryptoPath: "peerOrganizations/org1.example.com/users/{userName}@org1.example.com/msp"
    peers:
      - peer0.org1.example.com
      - peer1.org1.example.com
    certificateAuthorities:
      - ca.org1.example.com

# List of orderers to send transaction and channel create/update requests to.
# The orderers consent on the order of transactions in a block to be committed to the ledger. For the time being only one orderer is needed.
orderers:
  orderer.example.com:
    url: grpcs://localhost:7050
    grpcOptions:
      ssl-target-name-override: orderer.example.com
      grpc-max-send-message-length: 15
    tlsCACerts:
      path: "${GOPATH}/src/zhq/bill/fixtures/crypto-config/ordererOrganizations/example.com/tlsca/tlsca.example.com-cert.pem"

# List of peers to send various requests to, including endorsement, query and event listener registration.
peers:
  peer0.org1.example.com:
    # this URL is used to send endorsement and query requests
    url: grpcs://localhost:7051
    # this URL is used to connect the EventHub and registering event listeners
    eventUrl: grpcs://localhost:7053
    # These parameters should be set in coordination with the keepalive policy on the server
    grpcOptions:
      ssl-target-name-override: peer0.org1.example.com
      grpc.http2.keepalive_time: 15

    tlsCACerts:
      path: "${GOPATH}/src/zhq/bill/fixtures/crypto-config/peerOrganizations/org1.example.com/tlsca/tlsca.org1.example.com-cert.pem"

  peer1.org1.example.com:
    url: grpcs://localhost:8051
    eventUrl: grpcs://localhost:8053
    grpcOptions:
      ssl-target-name-override: peer1.org1.example.com
      grpc.http2.keepalive_time: 15
    tlsCACerts:
      # Certificate location absolute path
      path: "${GOPATH}/src/zhq/bill/fixtures/crypto-config/peerOrganizations/org1.example.com/tlsca/tlsca.org1.example.com-cert.pem"

# Fabric-CA is a special kind of Certificate Authority provided by Hyperledger Fabric which allows certificate management to be done via REST APIs.
certificateAuthorities:
  ca.org1.example.com:
    url: https://localhost:7054
    # the properties specified under this object are passed to the 'http' client verbatim when making the request to the Fabric-CA server
    httpOptions:
      verify: false
    registrar:
      enrollId: admin
      enrollSecret: adminpw
    caName: ca.org1.example.com

二、初始化SDK

在这个阶段,我们只初始化一个客户端,它将与 peer,CA 和 orderer进行通信。 还创建了一个新通道, 并将Peer节点加入到此通道中

goLand新建项目bill,新建Blockchain目录,新建startInit.go文件

startInit.go文件中创建FabricSetup结构体,保存sdk配置

type FabricSetup struct {
	//应用配置文件路径
	ConfigFile string
	//通道ID
	ChannelID string
	//sdk是否已初始化过,若已初始化,不再做初始化操作
	Initialized bool
	//通道配置文件路径
	ChannelConfig string
	//组织管理员账户名
	OrgAdmin string
	//组织名
	OrgName string
	//ResourceMgmtClient 使用'github.com/hyperledger/fabric-sdk-go/api/apitxn/resmgmtclient'包下的结构体,不要搞错
	Admin resmgmtclient.ResourceMgmtClient 
	sdk *fabsdk.FabricSDK
}

初始化sdk

接下来要做的是创建通道,回忆手动启动一个网络时,创建通道前需要一些配置文件,这些文件现在已经准备好了,接下来是:

进入CLI容器->创建通道->加入通道

以前都是通过命令行实现,现在通过代码实现:

func (setup *FabricSetup) Initialize() error {
	fmt.Println("开始初始化。。。")
	if setup.Initialized {
		return errors.New("sdk已经初始化")
	}
	//使用指定的配置文件创建SDK
	sdk, err := fabsdk.New(config.FromFile(setup.ConfigFile))
	if err != nil {
		return fmt.Errorf("创建SDK失败:%s", err.Error())
	}
	setup.sdk = sdk
	//根据指定的具有特权的用户(admin)创建用于管理通道的客户端API
	chMgmtClient, err := setup.sdk.NewClient(fabsdk.WithUser(setup.OrgAdmin), fabsdk.WithOrg(setup.OrgName)).ChannelMgmt()

	//chMgmtClient, err := setup.sdk.NewClient(fabsdk.WithUser(setup.OrgAdmin), fabsdk.WithOrg(setup.OrgName)).ChannelMgmt()
	if err != nil {
		return fmt.Errorf("SDK添加管理用户失败:%s", err.Error())
	}

	//获取客户端的会话用户
	session, err := setup.sdk.NewClient(fabsdk.WithUser(setup.OrgAdmin), fabsdk.WithOrg(setup.OrgName)).Session()
	if err != nil {
		return fmt.Errorf("获取会话用户失败:%s,%s:%s\n", setup.OrgName, setup.OrgAdmin, err.Error())
	}
	orgAdminUser := session

	//指定用于创建或更新通道的参数
	req := chmgmtclient.SaveChannelRequest{
		ChannelID:setup.ChannelID,
		ChannelConfig:setup.ChannelConfig,
		SigningIdentity:orgAdminUser,
	}
	//使用指定参数创建或更新通道
	err = chMgmtClient.SaveChannel(req)
	if err != nil {
		return fmt.Errorf("创建通道失败:%s\n",err.Error())
	}
	//创建或更新通过会有延迟,主线程等5秒
	time.Sleep(time.Second * 5)
	//创建一个用于管理系统资源的饿客户端API
	setup.Admin,err = setup.sdk.NewClient(fabsdk.WithUser(setup.OrgAdmin)).ResourceMgmt()
	if err != nil {
		return fmt.Errorf("创建资源管理客户端失败:%s\n",err.Error())
	}

	//将peer加入通道
	if err = setup.Admin.JoinChannel(setup.ChannelID); err != nil {
		return fmt.Errorf("peer加入通道失败:%s\n",err.Error())
	}
	fmt.Println("初始化成功")
	setup.Initialized = true
	return nil

}


测试

在工程目录下新建main.go文件

package main

import (
	"os"
	"fmt"
	"zhq/bill/Blockchain"
)

func main()  {
	setup := Blockchain.FabricSetup{
		//组织内管理员用户
		OrgAdmin:      "Admin",
		//组织ID
		OrgName:       "Org1",
		//通道ID
		ChannelID:     "mychannel",
		//应用配置文件路径
		ConfigFile:    "config.yaml",
		//通道配置文件路径
		ChannelConfig: os.Getenv("GOPATH") + "/src/zhq/bill/fixtures/artifacts/channel.tx",
	}
	err := setup.Initialize()
	if err != nil {
		fmt.Println(err)
	}
}

指定了环境的GOPATH,用来编译链码

在开始编译之前,最后一件事是使用一个vendor目录来包含我们所有的依赖关系。 在我们的GOPATH中,我们有Fabric SDK Go和其他项目。 当尝试编译应用程序时,Golang会在GOPATH中搜索依赖项,但首先会检查项目中是否存在vendor文件夹。 如果依赖性得到满足,那么Golang就不会去看GOPATH或GOROOT。 这在使用几个不同版本的依赖关系时非常有用(可能会发生一些冲突,比如在例子中有多个BCCSP定义,通过使用像dep这样的工具来处理这些依赖关系在vendor目录中。

当您安装SDK依赖关系时,DEP会自动安装。 如果不是这种情况,您可以阅读以下说明安装它: dep安装

创建一个名为Gopkg.toml的文件并将其复制到里面:

$ vim Gopkg.toml
[[constraint]]
  name = "github.com/hyperledger/fabric"
  revision = "014d6befcf67f3787bb3d67ff34e1a98dc6aec5f"

[[constraint]]
  name = "github.com/hyperledger/fabric-sdk-go"
  revision = "614551a752802488988921a730b172dada7def1d"

这是dep一个限制,以便在 vendor 中指定希望SDK转到特定版本。

保存该文件,然后执行此命令将vendor目录与项目的依赖关系同步(这可能需要一段时间):

$ dep ensure

提醒:dep ensure由于时间久,执行一次后即可,在后面的Makefile中可注释@dep ensure命令。

编译应用程序

$ go build

一段时间后,一个名为 bill的新二进制文件将出现在项目的根目录下。 尝试像这样启动二进制文件:

$ ./bill

./bill命令执行失败

此时,它将无法工作,因为没有可以与SDK进行通信的网络。 须先启动网络,然后再次启动应用程序:

$ cd fixtures
$ docker-compose up -d
$ cd ..
$ ./bill

初始化SDK

注意 :需要看到“初始化成功”。 如果没有看到则说明出现问题。 有> 启动完了,别忘了 docker-compose down 关闭po

现在只用本地网络初始化SDK。 在下一步中,将与链码进行交互。

清理和Makefile

Fabric SDK生成一些文件,如证书,二进制文件和临时文件。 关闭网络不会完全清理环境,当需要重新启动时,这些文件将被重复使用以避免构建过程。 对于开发,可以快速测试,但对于真正的测试,需要清理所有内容并从头开始。

如何清理环境

  • 关闭你的网络: cd $GOPATH/src/zhq/bill/fixtures && docker-compose down

  • 删除证书存储(在配置文件中,client.credentialStore中定义): rm -rf /tmp/bill-*

  • 删除一些不是由docker-compose命令生成的docker容器和docker镜像:

    docker rm -f -v `docker ps -a --no-trunc | grep "bill" | cut -d ' ' -f 1` 2>/dev/null
    和 
    docker rmi `docker images --no-trunc | grep "bill" | cut -d ' ' -f 1` 2>/dev/null
      
    

如何更有效率?

可以在一个步骤中自动完成所有这些任务。 构建和启动过程也可以自动化。 为此,将创建一个Makefile。 首先,确保 make 工具:

make --version

如果没有安装make (Ubuntu):

sudo apt install make 

然后使用以下内容在项目的根目录下创建一个名为Makefile的文件:

$ cd $GOPATH/src/zhq/bill
$ vim Makefile
.PHONY: all dev clean build env-up env-down run

all: clean build env-up run

dev: build run

##### BUILD
build:
	@echo "Build ..."
	@dep ensure
	@go build
	@echo "Build done"

##### ENV
env-up:
	@echo "Start environment ..."
	@cd fixtures && docker-compose up --force-recreate -d
	@echo "Sleep 15 seconds in order to let the environment setup correctly"
	@sleep 15
	@echo "Environment up"

env-down:
	@echo "Stop environment ..."
	@cd fixtures && docker-compose down
	@echo "Environment down"

##### RUN
run:
	@echo "Start app ..."
	@./bill

##### CLEAN
clean: env-down
	@echo "Clean up ..."
	@rm -rf /tmp/bill-* bill
	@docker rm -f -v `docker ps -a --no-trunc | grep "bill" | cut -d ' ' -f 1` 2>/dev/null || true
	@docker rmi `docker images --no-trunc | grep "bill" | cut -d ' ' -f 1` 2>/dev/null || true
	@echo "Clean up done"

现在完成任务:

  1. 整个环境将被清理干净,
  2. go程序将被编译,
  3. 之后将部署网络
  4. 最后该应用程序将启动并运行。

要使用它,请进入项目的根目录并使用make命令:

  • 任务allmakemake all
  • 任务clean :清理一切并释放网络( make clean
  • 任务build :只需构建应用程序( make build
  • 任务env-up :只需建立网络( make env-up

源码下载 https://github.com/sweetMegan/bill

感谢韩晓东(老韩)指导

打赏一个呗

取消

感谢您的支持,我会继续努力的!

扫码支持
扫码支持
扫码打赏,你说多少就多少

打开支付宝扫一扫,即可进行扫码打赏哦