fabric-sdk-go

项目地址:https://github.com/sxguan/fabric-go-sdk

一、fabric-sdk-go概述

软件开发工具包(外语首字母缩写:SDK、外语全称:Software Development Kit)一般都是一些软件工程师为特定的软件包、软件框架、硬件平台、操作系统等建立应用软件时的开发工具的集合。软件开发工具包括广义上指辅助开发某一类软件的相关文档、范例和工具的集合。软件开发工具包是一些被软件工程师用于为特定的软件包、软件框架、硬件平台、操作系统等创建应用软件的开发工具的集合,一般而言SDK即开发 Windows 平台下的应用程序所使用的 SDK。它可以简单的为某个程序设计语言提供应用程序接口 API 的一些文件,但也可能包括能与某种嵌入式系统通讯的复杂的硬件。一般的工具包括用于调试和其他用途的实用工具。SDK 还经常包括示例代码、支持性的技术注解或者其他的为基本参考资料澄清疑点的支持文档。为了鼓励开发者使用其系统或者语言,许多 SDK 是免费提供的。

Fabric的Peer节点和Orderer节点都提供了基于GRPC协议(Google开发的远程过程调用RPC)的接口,通过这些接口可以和Peer节点与Orderer节点进行命令/数据交互,为了简化开发,官方提供了多语言版本的SDK。目前主流支持的已经有Go版本了,列出主流的三个:

  • Fabric Nodejs SDK

  • Fabric Java SDK

  • Fabric Go SDK

Golang是Fabric原生的开发语言,Fabric,Fabric-ca,Chaincode都是采用Golang开发的,所以我们围绕Golang版本的Fabric SDK来介绍。

fabric-go-sdk官方网址为https://github.com/hyperledger/fabric-sdk-go,其目录结构如下:

其中pkg目录是fabric-go-sdk的主要实现,internel目录和third_party目录包含了fabric-go-sdk依赖的一些代码。

pkg目录包含了以下这些软件包:

基本工作流程:

  • 使用配置实例化fabsdk实例。 注意:fabsdk维护高速缓存,因此您应最小化fabsdk本身的实例。

  • 使用fabsdk实例基于用户和组织创建上下文。 注意:通道上下文还需要通道ID。

  • 使用其New函数创建一个客户端实例,并传递上下文。 注意:您需要为每个上下文创建一个新的客户端实例。

  • 使用每个客户提供的功能来创建解决方案。

  • 调用fabsdk.Close()释放资源和缓存。

二、准备网络环境

在这个项目中我们构建一个有一个排序节点以及两个组织每个组织有一个节点的超级账本网络。

1. 准备证书文件

$GOPATH/src目录下创建一个名为fabric-sdk-go的文件夹做为项目根目录,在此目录下创建名为fixtures的文件夹存放我们网络相关配置文件,在文件夹中创建一个名为crypto-config.yaml的文件并编辑如下:

OrdererOrgs:
  - Name: Orderer
    Domain: example.com
    EnableNodeOUs: true
    Specs:
      - Hostname: orderer

PeerOrgs:
  - Name: Org1
    Domain: org1.example.com
    EnableNodeOUs: true
    Template:
      Count: 1
    Users:
      Count: 1
      
  - Name: Org2
    Domain: org2.example.com
    EnableNodeOUs: true
    Template:
      Count: 1
    Users:
      Count: 1

使用以下命令生成证书文件:

cryptogen generate --config=crypto-config.yaml

2. 准备通道文件

fixtures路径下创建一个名为configtx.yaml的文件并编辑如下:

---

Organizations:

    - &OrdererOrg
 
        Name: OrdererOrg
        ID: OrdererMSP
        MSPDir: crypto-config/ordererOrganizations/example.com/msp
        Policies:
            Readers:
                Type: Signature
                Rule: "OR('OrdererMSP.member')"
            Writers:
                Type: Signature
                Rule: "OR('OrdererMSP.member')"
            Admins:
                Type: Signature
                Rule: "OR('OrdererMSP.admin')"
        OrdererEndpoints:
            - orderer.example.com:7050

    - &Org1

        Name: Org1MSP    
        ID: Org1MSP
        MSPDir: crypto-config/peerOrganizations/org1.example.com/msp
        Policies:
            Readers:
                Type: Signature
                Rule: "OR('Org1MSP.member')"
            Writers:
                Type: Signature
                Rule: "OR('Org1MSP.member')"
            Admins:
                Type: Signature
                Rule: "OR('Org1MSP.admin')"
            Endorsement:
                Type: Signature
                Rule: "OR('Org1MSP.member')"

        AnchorPeers:
            - Host: peer0.org1.example.com
              Port: 7051

    - &Org2
        Name: Org2MSP
        ID: Org2MSP
        MSPDir: crypto-config/peerOrganizations/org2.example.com/msp
        Policies:
            Readers:
                Type: Signature
                Rule: "OR('Org2MSP.member')"
            Writers:
                Type: Signature
                Rule: "OR('Org2MSP.member')"
            Admins:
                Type: Signature
                Rule: "OR('Org2MSP.admin')"
            Endorsement:
                Type: Signature
                Rule: "OR('Org2MSP.member')"
        AnchorPeers:
            - Host: peer0.org2.example.com
              Port: 9051

Capabilities: 
    Channel: &ChannelCapabilities    
        V2_0: true 
    Orderer: &OrdererCapabilities
      
        V2_0: true   
    Application: &ApplicationCapabilities      
        V2_0: true

Application: &ApplicationDefaults

    Organizations:
        - *Org1
        - *Org2
    Policies:
        Readers:
            Type: ImplicitMeta
            Rule: "ANY Readers"
        Writers:
            Type: ImplicitMeta
            Rule: "ANY Writers"
        Admins:
            Type: ImplicitMeta
            Rule: "MAJORITY Admins"
        LifecycleEndorsement:
            Type: Signature
            Rule: "OR('Org1MSP.member','Org2MSP.member')"
        Endorsement:
            Type: Signature
            Rule: "OR('Org1MSP.member','Org2MSP.member')"
    Capabilities:
        <<: *ApplicationCapabilities

Orderer: &OrdererDefaults

    OrdererType: solo
    Addresses:
        - orderer.example.com:7050
    BatchTimeout: 2s
    BatchSize:
        MaxMessageCount: 10
        AbsoluteMaxBytes: 99 MB
        PreferredMaxBytes: 512 KB
    Organizations:
    Policies:
        Readers:
            Type: ImplicitMeta
            Rule: "ANY Readers"
        Writers:
            Type: ImplicitMeta
            Rule: "ANY Writers"
        Admins:
            Type: ImplicitMeta
            Rule: "MAJORITY Admins"
        BlockValidation:
            Type: ImplicitMeta
            Rule: "ANY Writers"


Channel: &ChannelDefaults
    Policies:
        Readers:
            Type: ImplicitMeta
            Rule: "ANY Readers"
        Writers:
            Type: ImplicitMeta
            Rule: "ANY Writers"
        Admins:
            Type: ImplicitMeta
            Rule: "MAJORITY Admins"
    Capabilities:
        <<: *ChannelCapabilities

Profiles:
    TwoOrgsOrdererGenesis:
        <<: *ChannelDefaults
        Orderer:
            <<: *OrdererDefaults
            Organizations:
                - *OrdererOrg
            Capabilities:
                <<: *OrdererCapabilities
        Consortiums:
            SampleConsortium:
                Organizations:
                    - *Org1
                    - *Org2

    TwoOrgsChannel:
        Consortium: SampleConsortium
        <<: *ChannelDefaults
        Application:
            <<: *ApplicationDefaults
            Organizations:
                - *Org1
                - *Org2
            Capabilities:
                <<: *ApplicationCapabilities

生成创始块文件,使用以下命令在当前目录下的channel-artifacts目录下得到一个文件genesis.block

configtxgen -profile TwoOrgsOrdererGenesis -outputBlock ./channel-artifacts/genesis.block -channelID fabric-channel

生成通道文件,使用以下命令在当前目录下的channel-artifacts目录下得到一个文件channel.tx

configtxgen -profile TwoOrgsChannel -outputCreateChannelTx ./channel-artifacts/channel.tx -channelID mychannel

生成组织一锚节点更新文件,使用以下命令在当前目录下的channel-artifacts目录下得到一个文件Org1MSPanchors.tx

configtxgen -profile TwoOrgsChannel -outputAnchorPeersUpdate ./channel-artifacts/Org1MSPanchors.tx -channelID mychannel -asOrg Org1MSP

生成组织二锚节点更新文件,使用以下命令在当前目录下的channel-artifacts目录下得到一个文件Org2MSPanchors.tx

configtxgen -profile TwoOrgsChannel -outputAnchorPeersUpdate ./channel-artifacts/Org2MSPanchors.tx -channelID mychannel -asOrg Org2MSP

使用ls命令查看刚刚生成的文件。

ls channel-artifacts
channel.tx  Org1MSPanchors.tx  Org1MSPanchors.tx  genesis.block

3. 准备docker-compose文件

fixtures路径下创建一个名为docker-compose.yaml的文件并编辑如下:

version: '2'

volumes:
  orderer.example.com:
  peer0.org1.example.com:
  peer0.org2.example.com:
  
networks:
  test:

services:

  orderer.example.com:
    container_name: orderer.example.com
    image: hyperledger/fabric-orderer:2.2
    environment:
      - FABRIC_LOGGING_SPEC=DEBUG
      - ORDERER_GENERAL_LISTENADDRESS=0.0.0.0
      - ORDERER_GENERAL_LISTENPORT=7050
      - ORDERER_GENERAL_GENESISMETHOD=file
      - ORDERER_GENERAL_GENESISFILE=/var/hyperledger/orderer/orderer.genesis.block
      - ORDERER_GENERAL_LOCALMSPID=OrdererMSP
      - ORDERER_GENERAL_LOCALMSPDIR=/var/hyperledger/orderer/msp
      # enabled TLS
      - ORDERER_GENERAL_TLS_ENABLED=true
      - ORDERER_GENERAL_TLS_PRIVATEKEY=/var/hyperledger/orderer/tls/server.key
      - ORDERER_GENERAL_TLS_CERTIFICATE=/var/hyperledger/orderer/tls/server.crt
      - ORDERER_GENERAL_TLS_ROOTCAS=[/var/hyperledger/orderer/tls/ca.crt]
#      - ORDERER_KAFKA_TOPIC_REPLICATIONFACTOR=1
#      - ORDERER_KAFKA_VERBOSE=true
#      - ORDERER_GENERAL_CLUSTER_CLIENTCERTIFICATE=/var/hyperledger/orderer/tls/server.crt
#      - ORDERER_GENERAL_CLUSTER_CLIENTPRIVATEKEY=/var/hyperledger/orderer/tls/server.key
#      - ORDERER_GENERAL_CLUSTER_ROOTCAS=[/var/hyperledger/orderer/tls/ca.crt]
    working_dir: /opt/gopath/src/github.com/hyperledger/fabric
    command: orderer
    volumes:
        - ./channel-artifacts/genesis.block:/var/hyperledger/orderer/orderer.genesis.block
        - ./crypto-config/ordererOrganizations/example.com/orderers/orderer.example.com/msp:/var/hyperledger/orderer/msp
        - ./crypto-config/ordererOrganizations/example.com/orderers/orderer.example.com/tls/:/var/hyperledger/orderer/tls
        - orderer.example.com:/var/hyperledger/production/orderer
    ports:
      - 7050:7050
    networks:
      - test

  peer0.org1.example.com:
    container_name: peer0.org1.example.com
    image: hyperledger/fabric-peer:2.2
    environment:
      #Generic peer variables
      - CORE_VM_ENDPOINT=unix:///host/var/run/docker.sock
      # the following setting starts chaincode containers on the same
      # bridge network as the peers
      # https://docs.docker.com/compose/networking/
      - CORE_VM_DOCKER_HOSTCONFIG_NETWORKMODE=fixtures_test
      - FABRIC_LOGGING_SPEC=DEBUG
      #- FABRIC_LOGGING_SPEC=DEBUG
      - CORE_PEER_TLS_ENABLED=true
      - CORE_PEER_PROFILE_ENABLED=true
      - CORE_PEER_TLS_CERT_FILE=/etc/hyperledger/fabric/tls/server.crt
      - CORE_PEER_TLS_KEY_FILE=/etc/hyperledger/fabric/tls/server.key
      - CORE_PEER_TLS_ROOTCERT_FILE=/etc/hyperledger/fabric/tls/ca.crt
      # Peer specific variabes
      - CORE_PEER_ID=peer0.org1.example.com
      - CORE_PEER_ADDRESS=peer0.org1.example.com:7051
      - CORE_PEER_LISTENADDRESS=0.0.0.0:7051
      - CORE_PEER_CHAINCODEADDRESS=peer0.org1.example.com:7052
      - CORE_PEER_CHAINCODELISTENADDRESS=0.0.0.0:7052
      - CORE_PEER_GOSSIP_BOOTSTRAP=peer0.org1.example.com:7051
      - CORE_PEER_GOSSIP_EXTERNALENDPOINT=peer0.org1.example.com:7051
      - CORE_PEER_LOCALMSPID=Org1MSP
 
    volumes:
        - /var/run/:/host/var/run/
        - ./crypto-config/peerOrganizations/org1.example.com/peers/peer0.org1.example.com/msp:/etc/hyperledger/fabric/msp
        - ./crypto-config/peerOrganizations/org1.example.com/peers/peer0.org1.example.com/tls:/etc/hyperledger/fabric/tls
        - peer0.org1.example.com:/var/hyperledger/production
    working_dir: /opt/gopath/src/github.com/hyperledger/fabric/peer
    command: peer node start
    ports:
      - 7051:7051
    depends_on:
      - orderer.example.com
      #- couchdb.org1.example.com
    networks:
      - test

  peer0.org2.example.com:
    container_name: peer0.org2.example.com
    image: hyperledger/fabric-peer:2.2
    environment:
      #Generic peer variables
      - CORE_VM_ENDPOINT=unix:///host/var/run/docker.sock
      # the following setting starts chaincode containers on the same
      # bridge network as the peers
      # https://docs.docker.com/compose/networking/
      - CORE_VM_DOCKER_HOSTCONFIG_NETWORKMODE=fixtures_test
      - FABRIC_LOGGING_SPEC=DEBUG
      #- FABRIC_LOGGING_SPEC=DEBUG
      - CORE_PEER_TLS_ENABLED=true
      - CORE_PEER_PROFILE_ENABLED=true
      - CORE_PEER_TLS_CERT_FILE=/etc/hyperledger/fabric/tls/server.crt
      - CORE_PEER_TLS_KEY_FILE=/etc/hyperledger/fabric/tls/server.key
      - CORE_PEER_TLS_ROOTCERT_FILE=/etc/hyperledger/fabric/tls/ca.crt
      # Peer specific variabes
      - CORE_PEER_ID=peer0.org2.example.com
      - CORE_PEER_ADDRESS=peer0.org2.example.com:9051
      - CORE_PEER_LISTENADDRESS=0.0.0.0:9051
      - CORE_PEER_CHAINCODEADDRESS=peer0.org2.example.com:9052
      - CORE_PEER_CHAINCODELISTENADDRESS=0.0.0.0:9052
      - CORE_PEER_GOSSIP_EXTERNALENDPOINT=peer0.org2.example.com:9051
      - CORE_PEER_GOSSIP_BOOTSTRAP=peer0.org2.example.com:9051
      - CORE_PEER_LOCALMSPID=Org2MSP
    volumes:
      - /var/run/:/host/var/run/
      - ./crypto-config/peerOrganizations/org2.example.com/peers/peer0.org2.example.com/msp:/etc/hyperledger/fabric/msp
      - ./crypto-config/peerOrganizations/org2.example.com/peers/peer0.org2.example.com/tls:/etc/hyperledger/fabric/tls
      - peer0.org2.example.com:/var/hyperledger/production
    working_dir: /opt/gopath/src/github.com/hyperledger/fabric/peer
    command: peer node start
    ports:
      - 9051:9051
    networks:
      - test


  ca.org1.example.com:
    image: hyperledger/fabric-ca:1.4.9
    container_name: ca.org1.example.com
    environment:
      - FABRIC_CA_HOME=/etc/hyperledger/fabric-ca-server
      - FABRIC_CA_SERVER_CA_NAME=ca.org1.example.com
      - FABRIC_CA_SERVER_CA_CERTFILE=/etc/hyperledger/fabric-ca-server-config/ca.org1.example.com-cert.pem
      - FABRIC_CA_SERVER_CA_KEYFILE=/etc/hyperledger/fabric-ca-server-config/priv_sk
      - FABRIC_CA_SERVER_TLS_ENABLED=true
      - FABRIC_CA_SERVER_TLS_CERTFILE=/etc/hyperledger/fabric-ca-server-config/ca.org1.example.com-cert.pem
      - FABRIC_CA_SERVER_TLS_KEYFILE=/etc/hyperledger/fabric-ca-server-config/priv_sk
    ports:
      - 7054:7054
    command: sh -c 'fabric-ca-server start -b admin:adminpw -d'
    volumes:
      - ./crypto-config/peerOrganizations/org1.example.com/ca/:/etc/hyperledger/fabric-ca-server-config
    networks:
      - test

三、配置文件config.yaml

客户端使用sdk与fabric网络交互,需要告诉sdk两类信息:

  • 我是谁:即当前客户端的信息,包含所属组织、密钥和证书文件的路径等, 这是每个客户端专用的信息。

  • 对方是谁:即fabric网络结构的信息,channel、org、orderer和peer等 的怎么组合起当前fabric网络的,这些结构信息应当与configytx.yaml中是一致的。这是通用配置,每个客户端都可以拿来使用。另外,这部分信息并不需要是完整fabric网络信息,如果当前客户端只和部分节点交互,那配置文件中只需要包含所使用到的网络信息。

下面是详细的配置文件用法:

1. 声明

#
# Copyright SecureKey Technologies Inc. All Rights Reserved.
#
# SPDX-License-Identifier: Apache-2.0
#
#
# The network connection profile provides client applications the information about the target
# blockchain network that are necessary for the applications to interact with it. These are all
# knowledge that must be acquired from out-of-band sources. This file provides such a source.
# 网络连接配置文件为客户端应用程序提供目标区块链网络的信息,这是应用程序与之交互所必须的。
# 这些都是必须从带外源获得的信息。该文件提供了这样的源代码。

#
# Schema version of the content. Used by the SDK to apply the corresponding parsing rules.
# 内容的模式版本。SDK用于应用相应的解析规则。
version: 1.0.0

2. 客户端部分

#
# The client section used by GO SDK.
# 用于GO SDK的客户端部分。
client:

  # Which organization does this application instance belong to? The value must be the name of an org
  # defined under "organizations"
  # 这个应用程序实例属于哪个组织?这个值必须是定义在"organizations"下的一个组织的名称。
  
  organization: org1

  logging:
    level: info

  # Global configuration for peer, event service and orderer timeouts
  # if this this section is omitted, then default values will be used (same values as below)
  # 对等节点,事件服务和排序节点超时的全局配置。
  # 如果这个部分省略,将会使用默认值(默认值如下所示)。
#  peer:
#    timeout:
#      connection: 10s
#      response: 180s
#      discovery:
#        # Expiry period for discovery service greylist filter
#        # The channel client will greylist peers that are found to be offline
#        # to prevent re-selecting them in subsequent retries.
#        # This interval will define how long a peer is greylisted
		 # 发现服务灰名单过滤器的过期时间
		 # 通道客户端需要将掉线的对等节点列为灰名单以阻止重复选择并重试。
		 # 这个间隔时间将定义多长时间将对等节点列为灰名单。
		 
#        greylistExpiry: 10s

    # the below timeouts are commented out to use the default values that are found in
    # "pkg/fab/endpointconfig.go"
    # the client is free to override the default values by uncommenting and resetting
    # the values as they see fit in their config file
    # 下面的超时时间被注释掉以使用默认值,默认值可以在"pkg/fab/endpointconfig.go"中找到
    # 客户端可以根据配置文件的需要取消注释并重新设置这些值,从而覆盖默认值
#    timeout:
#      connection: 15s
#      registrationResponse: 15s
#  orderer:
#    timeout:
#      connection: 15s
#      response: 15s
#  global:
#    timeout:
#      query: 180s
#      execute: 180s
#      resmgmt: 180s
#    cache:
#      connectionIdle: 30s
#      eventServiceIdle: 2m
#      channelConfig: 30m
#      channelMembership: 30s
#      discovery: 10s
#      selection: 10m

  # Root of the MSP directories with keys and certs.
  # 根MSP的keys和certs路径
  cryptoconfig:
    path: ${FABRIC_SDK_GO_PROJECT_PATH}/${CRYPTOCONFIG_FIXTURES_PATH}

  # Some SDKs support pluggable KV stores, the properties under "credentialStore"
  # are implementation specific
  # 一些SDK支持可插拔的KV存储,"credentialStore"下的属性是具体实现
  credentialStore:
    # [Optional]. Used by user store. Not needed if all credentials are embedded in configuration
    # and enrollments are performed elsewhere.
    # [可选的] 用于用户存储。如果所有凭证都嵌入到配置中,并且在其他地方执行登记,则不需要。
    path: "/tmp/state-store"

    # [Optional]. Specific to the CryptoSuite implementation used by GO SDK. Software-based implementations
    # requiring a key store. PKCS#11 based implementations does not.
    # [可选的] 特定于GO SDK使用的CryptoSuite实现。基于软件的实现需要密钥存储区。基于PKCS#11的实现则不用。
    cryptoStore:
      # Specific to the underlying KeyValueStore that backs the crypto key store.
      # 特定于支持加密密钥存储的基础KeyValueStore。
      
      path: /tmp/msp

  # [Optional] BCCSP config for the client. Used by GO SDK.
  # [可选的] 客户端的BCCSP配置。用于GO SDK。
  BCCSP:
    security:
     enabled: true
     default:
      provider: "SW"
     hashAlgorithm: "SHA2"
     softVerify: true
     level: 256

  tlsCerts:
    # [Optional]. Use system certificate pool when connecting to peers, orderers (for negotiating TLS) Default: false
    # [可选的] 当连接到对等节点、排序节点(用于协商TLS)时使用系统证书池。默认值:false
    
    systemCertPool: true

    # [Optional]. Client key and cert for TLS handshake with peers and orderers
    # [可选的] 与对等节点和排序节点进行TLS握手的客户端密钥和证书
    client:
      key:
        path: ${FABRIC_SDK_GO_PROJECT_PATH}/${CRYPTOCONFIG_FIXTURES_PATH}/peerOrganizations/tls.example.com/users/User1@tls.example.com/tls/client.key
      cert:
        path: ${FABRIC_SDK_GO_PROJECT_PATH}/${CRYPTOCONFIG_FIXTURES_PATH}/peerOrganizations/tls.example.com/users/User1@tls.example.com/tls/client.crt

#
# [Optional]. But most apps would have this section so that channel objects can be constructed
# based on the content below. If an app is creating channels, then it likely will not need this
# section.
# [可选的] 但是大多数应用程序都会有此部分,以便可以根据以下内容构造通道对象。
# 如果某个应用正在创建频道,则可能不需要此部分。

3. 通道部分

#
# [Optional]. But most apps would have this section so that channel objects can be constructed
# based on the content below. If an app is creating channels, then it likely will not need this
# section.
# [可选的] 但是大多数应用程序都会有此部分,以便可以根据以下内容构造通道对象。
# 如果某个应用正在创建频道,则可能不需要此部分。
channels:

  # Default channel is used if channel configuration is missing or if defined channel configuration is missing info
  # If channel doesn't define peers then peers from default channel will be used
  # If channel doesn't define orderes then orderes from default channel will be used
  # If channel doesn't define policies then policies from default channel will be used.
  # Also, if channel defines policies and some policy info is missing than that missing info will be filled from default channel.
  # 如果缺少通道配置或定义的通道配置缺少信息,则使用默认通道配置
  # 如果通道未定义对等节点,则将使用默认通道中的对等节点
  # 如果通道未定义排序节点,则将使用默认通道的排序节点
  # 如果通道未定义策略,则将使用默认通道中的策略。
  # 此外,如果通道定义了策略,并且缺少某些策略信息,那么该缺失信息将从默认通道中填充。
  _default:

    # [Optional]. list of peers from participating orgs
    # [可选的] 参与组织的对等节点列表。
    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
        # 这个对等节点是否会被发送交易建议以供背书?对等端必须安装了chaincode。
        # 应用程序也可以使用这个属性来决定哪个对等节点发送chaincode安装请求。默认值: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
        # 这个对等节点会被发送查询建议吗?对等端必须安装了chaincode。
        # 应用程序也可以使用这个属性来决定哪个对等节点发送chaincode安装请求。默认值:true
        chaincodeQuery: true

        # [Optional]. will this peer be sent query proposals that do not require chaincodes, like
        # queryBlock(), queryTransaction(), etc. Default: true
        # 这个对等节点是否会被发送不需要链码的查询建议,如queryBlock(), queryTransaction()等。默认值: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
        # 这个对等节点会成为SDK侦听器注册的目标吗?所有对等节点都可以产生事件,但应用程序通常只需要连接到一个对等节点就可以监听事件。
		# 默认:真
        eventSource: true

    # [Optional]. The application can use these options to perform channel operations like retrieving channel
    # config etc.
    # 应用程序可以使用这些选项来执行通道操作,如检索通道配置等。
    policies:
      #[Optional] options for retrieving discovery info
      # 检索发现信息的选项
      discovery:
        #[Optional] discovery info will be retrieved for these number of random targets
        maxTargets: 2
        #[Optional] retry options for retriving discovery info
        # 发现信息将为这些数目的随机目标检索
        retryOpts:
          #[Optional] number of retry attempts
          # 重试次数
          attempts: 4
          #[Optional] the back off interval for the first retry attempt
          # 第一次重试尝试的后退间隔
          initialBackoff: 500ms
          #[Optional] the maximum back off interval for any retry attempt
          # 任何重试尝试的最大回退间隔
          maxBackoff: 5s
          #[Optional] he factor by which the initial back off period is exponentially incremented
          # 它使初始的回退周期以指数形式增加
          backoffFactor: 2.0
      #[Optional] options for selection service
      # 选择服务选项
      selection:
        #[Optional] endorser selection sorting strategy. Possible values: [BlockHeightPriority,Balanced]
        # 背书者选择排序策略
        SortingStrategy: BlockHeightPriority
        #[Optional] load-balancer type. Possible values: [RoundRobin,Random]
        # 负载平衡器类型
        Balancer: RoundRobin
        #[Optional] the number of blocks from the highest block number of a group of peers that a peer
        #can lag behind and still be considered to be up-to-date. These peers will be sorted using the
        #given Balancer. If a peer's block height falls behind this threshold then it will be demoted
        #to a lower priority list of peers which will be sorted according to block height.
        #Note: This property only applies to BlockHeightPriority sorter.
        # 在一组对等节点中,一个对等节点可以落后但仍然被认为是最新的最大块数。
        # 这些对等节点将使用给定的平衡器进行排序。
        # 如果一个对等节点的块高度低于这个阈值,那么它将被降级到一个较低优先级的对等节点列表中,该列表将根据块高度进行排序。
		# 注意:此属性仅适用于BlockHeightPriority排序器。
        BlockHeightLagThreshold: 5
      #[Optional] options for retrieving channel configuration blocks
      # 检索通道配置块的选项
      queryChannelConfig:
        #[Optional] min number of success responses (from targets/peers)
        # 最小成功响应数(来自目标/对等节点)
        minResponses: 1
        #[Optional] channel config will be retrieved for these number of random targets
        # 通道配置将为这些数量的随机目标检索
        maxTargets: 1
        #[Optional] retry options for query config block
        # 查询配置块的重试选项
        retryOpts:
          #[Optional] number of retry attempts
          # 重试次数
          attempts: 5
          #[Optional] the back off interval for the first retry attempt
          initialBackoff: 500ms
          #[Optional] the maximum back off interval for any retry attempt
          maxBackoff: 5s
          #[Optional] he factor by which the initial back off period is exponentially incremented
          backoffFactor: 2.0

      #[Optional] options for the event service
      # 事件服务的选项
      eventService:
        # [Optional] resolverStrategy specifies the peer resolver strategy to use when connecting to a peer
        # resolverStrategy指定连接到对等节点时使用的对等解析器策略
        # Possible values: [PreferOrg (default), MinBlockHeight, Balanced]
        #
        # PreferOrg:
        #   Determines which peers are suitable based on block height lag threshold, although will prefer the peers in the
        #   current org (as long as their block height is above a configured threshold). If none of the peers from the current org
        #   are suitable then a peer from another org is chosen.
        # 根据块高度滞后阈值确定哪些对等节点是合适的,尽管会更喜欢当前org中的对等节点(只要它们的块高度高于配置的阈值)。
        # 如果当前组织的对等节点中没有一个是合适的,则选择另一个组织的对等节点。
        # MinBlockHeight:
        #   Chooses the best peer according to a block height lag threshold. The maximum block height of all peers is
        #   determined and the peers whose block heights are under the maximum height but above a provided "lag" threshold are load
        #   balanced. The other peers are not considered.
        # 根据块高度延迟阈值选择最佳的对等节点。所有对等节点的最大块高度被确定,并且其块高度低于最大高度但高于提供的“滞后”阈值的对等节点被负载平衡。
        # 其他同行不考虑。
        # Balanced:
        #   Chooses peers using the configured balancer.
        # 使用配置的均衡器选择对等节点。
        resolverStrategy: PreferOrg

        # [Optional] balancer is the balancer to use when choosing a peer to connect to
        # 平衡器是在选择要连接的对等点时使用的平衡器
        # Possible values: [Random (default), RoundRobin]
        balancer: RoundRobin

        # [Optional] blockHeightLagThreshold sets the block height lag threshold. This value is used for choosing a peer
        # to connect to. If a peer is lagging behind the most up-to-date peer by more than the given number of
        # blocks then it will be excluded from selection.
        # Note that this parameter is applicable only when minBlockHeightResolverMode is set to ResolveByThreshold.
        # blockHeightLagThreshold块高度滞后阈值。此值用于选择要连接的对等点。如果一个对等节点落后于最新的对等点超过给定的块数,那么它将被排除在选择之外。
		# 需要注意的是,当minBlockHeightResolverMode设置为ResolveByThreshold时,此参数才会生效
        # Default: 5
        blockHeightLagThreshold: 2

        # [Optional] reconnectBlockHeightLagThreshold - the event client will disconnect from the peer if the peer's
        # block height falls behind the specified number of blocks and will reconnect to a better performing peer.
        # Note that this parameter is only applicable if peerMonitor is set to Enabled (default).
        # reconnectBlockHeightLagThreshold—如果对等节点的块高度低于指定的块数量,事件客户端将断开与对等节点的连接,并重新连接到性能更好的对等节点。
		# 注意:只有当“peerMonitor”设置为“Enabled”(默认)时,此参数才有效。
        # Default: 10
        # NOTES:
        #   - Setting this value too low may cause the event client to disconnect/reconnect too frequently, thereby
        #     affecting performance.
        reconnectBlockHeightLagThreshold: 5

        # [Optional] peerMonitorPeriod is the period in which the connected peer is monitored to see if
        # the event client should disconnect from it and reconnect to another peer.
        # peerMonitorPeriod是监控已连接的对等节点的周期,以查看事件客户端是否应该断开连接并重新连接到另一个对等节点。
        # Default: 0 (disabled) for Balanced resolverStrategy; 5s for PreferOrg and MinBlockHeight strategy
        peerMonitorPeriod: 3s

  # Mychannel overrides initialBackoff for discovery
  # Mychannel覆盖发现的initialBackoff
  mychannel:
    policies:
      discovery:
        retryOpts:
          #[Required for override] number of retry attempts
          attempts: 4
          initialBackoff: 1s

  # multi-org test channel
  orgchannel:

#    orderers:
#      - orderer.example.com

    peers:
      peer0.org1.example.com:
        endorsingPeer: true
        chaincodeQuery: true
        ledgerQuery: true
        eventSource: true

      peer1.org1.example.com:
        endorsingPeer: true
        chaincodeQuery: true
        ledgerQuery: true
        eventSource: true

      peer0.org2.example.com:
        endorsingPeer: true
        chaincodeQuery: true
        ledgerQuery: true
        eventSource: true

4. 组织部分

#
# list of participating organizations in this network
# 参与该网络的组织名单
#
organizations:
  org1:
    mspid: Org1MSP

    # This org's MSP store (absolute path or relative to client.cryptoconfig)
    # MSP存储路径
    cryptoPath:  peerOrganizations/org1.example.com/users/{username}@org1.example.com/msp

    peers:
      - peer0.org1.example.com
      - peer1.org1.example.com

    # [Optional]. Certificate Authorities issue certificates for identification purposes in a Fabric based
    # network. Typically certificates provisioning is done in a separate process outside of the
    # runtime network. Fabric-CA is a special certificate authority that provides a REST APIs for
    # dynamic certificate management (enroll, revoke, re-enroll). The following section is only for
    # Fabric-CA servers.
    # 在基于Fabric的网络中,证书颁发机构为识别目的颁发证书。通常,证书提供是在运行时网络之外的单独进程中完成的。
    # Fabric-CA是一个特殊的证书颁发机构,它为动态证书管理(注册、撤销、重新注册)提供了一个REST api。以下内容仅适用于Fabric-CA服务器。
    certificateAuthorities:
      - ca.org1.example.com
      - tlsca.org1.example.com

  # the profile will contain public information about organizations other than the one it belongs to.
  # These are necessary information to make transaction lifecycles work, including MSP IDs and
  # peers with a public URL to send transaction proposals. The file will not contain private
  # information reserved for members of the organization, such as admin key and certificate,
  # fabric-ca registrar enroll ID and secret, etc.
  # 这个概要文件将包含关于它所属组织以外的其他组织的公共信息。
  # 这些是使事务生命周期正常工作所必需的信息,包括MSP id和使用公共URL发送事务建议的对等节点。
  # 该文件将不包含为组织成员保留的私人信息,如管理员密钥和证书、fabric-ca注册商注册ID和秘密等。
  org2:
    mspid: Org2MSP

    # This org's MSP store (absolute path or relative to client.cryptoconfig)
    cryptoPath:  peerOrganizations/org2.example.com/users/{username}@org2.example.com/msp

    peers:
      - peer0.org2.example.com
      - peer1.org2.example.com

    certificateAuthorities:
      - ca.org2.example.com

  # Orderer Org name
  ordererorg:
      # Membership Service Provider ID for this organization
      mspID: OrdererMSP

      # Needed to load users crypto keys and certs for this org (absolute path or relative to global crypto path, DEV mode)
      cryptoPath: ordererOrganizations/example.com/users/{username}@example.com/msp

5. 排序节点部分

#
# List of orderers to send transaction and channel create/update requests to. For the time
# being only one orderer is needed. If more than one is defined, which one get used by the
# SDK is implementation specific. Consult each SDK's documentation for its handling of orderers.
#
# 要发送事务和通道创建/更新请求的订购者列表。目前只需要一份订单。如果定义了多个,那么SDK将使用哪个是特定于实现的。
# 请查阅每个SDK的文档,了解它对排序的处理。
orderers:
  _default:
    # common orderer config items between all the orderers in  config
    # these are standard properties defined by the gRPC library
    # they will be passed in as-is to gRPC client constructor
    # 这些是gRPC库定义的标准属性,它们将被原样传递给gRPC客户端构造器
    grpcOptions:
      # These parameters should be set in coordination with the keepalive policy on the server,
      # as incompatible settings can result in closing of connection.
      # When duration of the 'keep-alive-time' is set to 0 or less the keep alive client parameters are disabled
      # 这些参数的设置应该与服务器上的keepalive策略相协调,因为不兼容的设置可能导致连接关闭。
      # 当“keep-alive-time”的持续时间设置为0或更小时,保持活跃的客户端参数将被禁用
      keep-alive-time: 0s
      keep-alive-timeout: 20s
      keep-alive-permit: false
      fail-fast: false
      # allow-insecure will be taken into consideration if address has no protocol defined, if true then grpc or else grpcs
      # 如果address没有定义协议,Allow-insecure将被考虑,如果address为true则GRPC或GRPCS
      allow-insecure: false

  orderer.example.com:
    # [Optional] Default: Infer from hostname
    url: orderer.example.com:7050

    # these are standard properties defined by the gRPC library
    # they will be passed in as-is to gRPC client constructor
    # 这些是gRPC库定义的标准属性,它们将原样传递给gRPC客户端构造函数
    grpcOptions:
      #ssl-target-name-override: orderer.example.com
      # These parameters should be set in coordination with the keepalive policy on the server,
      # as incompatible settings can result in closing of connection.
      # When duration of the 'keep-alive-time' is set to 0 or less the keep alive client parameters are disabled
      # 这些参数的设置应该与服务器上的keepalive策略相协调,因为不兼容的设置可能导致连接关闭。
      # 当“keep-alive-time”的持续时间设置为0或更小时,保持活跃的客户端参数将被禁用
      #keep-alive-time: 0s
      #keep-alive-timeout: 20s
      #keep-alive-permit: false
      #fail-fast: false
      # allow-insecure will be taken into consideration if address has no protocol defined, if true then grpc or else grpcs
      # 如果address没有定义协议,Allow-insecure将被考虑,如果address为true则GRPC或GRPCS
      #allow-insecure: false

    tlsCACerts:
      # Certificate location absolute path
      path: ${FABRIC_SDK_GO_PROJECT_PATH}/${CRYPTOCONFIG_FIXTURES_PATH}/ordererOrganizations/example.com/tlsca/tlsca.example.com-cert.pem

6. 对等节点部分

#
# List of peers to send various requests to, including endorsement, query
# and event listener registration.
# 发送各种请求的对等点节点列表,包括背书、查询和事件侦听器注册。
#
peers:
  _default:
    #common grpc options between all the peers
    # 所有对等节点的通用GRPC选项
    grpcOptions:
      # These parameters should be set in coordination with the keepalive policy on the server,
      # as incompatible settings can result in closing of connection.
      # When duration of the 'keep-alive-time' is set to 0 or less the keep alive client parameters are disabled
      # 这些参数的设置应该与服务器上的keepalive策略相协调,因为不兼容的设置可能导致连接关闭。
      # 当“keep-alive-time”的持续时间设置为0或更小时,保持活跃的客户端参数将被禁用
      keep-alive-time: 0s
      keep-alive-timeout: 20s
      keep-alive-permit: false
      fail-fast: false
      # allow-insecure will be taken into consideration if address has no protocol defined, if true then grpc or else grpcs
      # 如果address没有定义协议,Allow-insecure将被考虑,如果address为true则GRPC或GRPCS
      allow-insecure: false

  peer0.org1.example.com:
    # this URL is used to send endorsement and query requests
    # 此URL用于发送背书和查询请求
    # [Optional] Default: Infer from hostname
    url: peer0.org1.example.com:7051

    #grpcOptions:
    #  ssl-target-name-override: peer0.org1.example.com

    tlsCACerts:
      # 证书本地绝对路径
      path: ${FABRIC_SDK_GO_PROJECT_PATH}/${CRYPTOCONFIG_FIXTURES_PATH}/peerOrganizations/org1.example.com/tlsca/tlsca.org1.example.com-cert.pem

  peer1.org1.example.com:
    # 此URL用于发送背书和查询请求
    url: peer1.org1.example.com:7151

    #grpcOptions:
    #  ssl-target-name-override: peer1.org1.example.com

    tlsCACerts:
      # Certificate location absolute path
      path: ${FABRIC_SDK_GO_PROJECT_PATH}/${CRYPTOCONFIG_FIXTURES_PATH}/peerOrganizations/org1.example.com/tlsca/tlsca.org1.example.com-cert.pem

  peer0.org2.example.com:
    url: peer0.org2.example.com:8051
    #grpcOptions:
    #  ssl-target-name-override: peer0.org2.example.com

    tlsCACerts:
      path: ${FABRIC_SDK_GO_PROJECT_PATH}/${CRYPTOCONFIG_FIXTURES_PATH}/peerOrganizations/org2.example.com/tlsca/tlsca.org2.example.com-cert.pem

  peer1.org2.example.com:
    url: peer1.org2.example.com:9051
    #grpcOptions:
    #  ssl-target-name-override: peer1.org2.example.com

    tlsCACerts:
      path: ${FABRIC_SDK_GO_PROJECT_PATH}/${CRYPTOCONFIG_FIXTURES_PATH}/peerOrganizations/org2.example.com/tlsca/tlsca.org2.example.com-cert.pem

7. CA部分

#
# Fabric-CA is a special kind of Certificate Authority provided by Hyperledger Fabric which allows
# certificate management to be done via REST APIs. Application may choose to use a standard
# Certificate Authority instead of Fabric-CA, in which case this section would not be specified.
# Fabric- ca是Hyperledger Fabric提供的一种特殊的证书颁发机构,它允许通过REST api进行证书管理。
# 应用程序可以选择使用标准的证书颁发机构而不是Fabric-CA,在这种情况下,将不指定此部分。
#
certificateAuthorities:
  ca.org1.example.com:
    # [Optional] Default: Infer from hostname
    url: https://ca.org1.example.com:7054
    # [Optional] The optional server name for target override
    #grpcOptions:
    #  ssl-target-name-override: ca.org1.example.com
    tlsCACerts:
      # Comma-Separated list of paths
      path: ${FABRIC_SDK_GO_PROJECT_PATH}/${CRYPTOCONFIG_FIXTURES_PATH}/peerOrganizations/org1.example.com/tlsca/tlsca.org1.example.com-cert.pem
      # Client key and cert for SSL handshake with Fabric CA
      client:
        key:
          path: ${FABRIC_SDK_GO_PROJECT_PATH}/${CRYPTOCONFIG_FIXTURES_PATH}/peerOrganizations/tls.example.com/users/User1@tls.example.com/tls/client.key
        cert:
          path: ${FABRIC_SDK_GO_PROJECT_PATH}/${CRYPTOCONFIG_FIXTURES_PATH}/peerOrganizations/tls.example.com/users/User1@tls.example.com/tls/client.crt

    # Fabric-CA supports dynamic user enrollment via REST APIs. A "root" user, a.k.a registrar, is
    # needed to enroll and invoke new users.
    # Fabric-CA支持通过REST api动态注册用户。注册和调用新用户需要一个“根”用户,即注册商
    registrar:
      enrollId: admin
      enrollSecret: adminpw
    # [Optional] The optional name of the CA.
    caName: ca.org1.example.com
  tlsca.org1.example.com:
    # [Optional] Default: Infer from hostname
    url: https://ca.org1.example.com:7154
    tlsCACerts:
      # Comma-Separated list of paths
      path: ${FABRIC_SDK_GO_PROJECT_PATH}/${CRYPTOCONFIG_FIXTURES_PATH}/peerOrganizations/org1.example.com/tlsca/tlsca.org1.example.com-cert.pem
      # Client key and cert for SSL handshake with Fabric CA
      client:
        key:
          path: ${FABRIC_SDK_GO_PROJECT_PATH}/${CRYPTOCONFIG_FIXTURES_PATH}/peerOrganizations/tls.example.com/users/User1@tls.example.com/tls/client.key
        cert:
          path: ${FABRIC_SDK_GO_PROJECT_PATH}/${CRYPTOCONFIG_FIXTURES_PATH}/peerOrganizations/tls.example.com/users/User1@tls.example.com/tls/client.crt

    # Fabric-CA supports dynamic user enrollment via REST APIs. A "root" user, a.k.a registrar, is
    # needed to enroll and invoke new users.
    registrar:
      enrollId: admin2
      enrollSecret: adminpw2
    # [Optional] The optional name of the CA.
    caName: tlsca.org1.example.com
  ca.org2.example.com:
    url: https://ca.org2.example.com:8054
    # [Optional] The optional server name for target override
    #grpcOptions:
    #  ssl-target-name-override: ca.org2.example.com
    tlsCACerts:
      # Comma-Separated list of paths
      path: ${FABRIC_SDK_GO_PROJECT_PATH}/${CRYPTOCONFIG_FIXTURES_PATH}/peerOrganizations/org2.example.com/tlsca/tlsca.org2.example.com-cert.pem
      # Client key and cert for SSL handshake with Fabric CA
      client:
        key:
          path: ${FABRIC_SDK_GO_PROJECT_PATH}/${CRYPTOCONFIG_FIXTURES_PATH}/peerOrganizations/tls.example.com/users/User1@tls.example.com/tls/client.key
        cert:
          path: ${FABRIC_SDK_GO_PROJECT_PATH}/${CRYPTOCONFIG_FIXTURES_PATH}/peerOrganizations/tls.example.com/users/User1@tls.example.com/tls/client.crt

     # Fabric-CA supports dynamic user enrollment via REST APIs. A "root" user, a.k.a registrar, is
     # needed to enroll and invoke new users.
     # Fabric-CA支持通过REST api动态注册用户。注册和调用新用户需要一个“根”用户,即注册商。
    registrar:
      enrollId: admin
      enrollSecret: adminpw
    # [Optional] The optional name of the CA.
    caName: ca.org2.example.com

8. EntityMatchers部分

# EntityMatchers enable substitution of network hostnames with static configurations
 # so that properties can be mapped. Regex can be used for this purpose
# UrlSubstitutionExp can be empty which means the same network hostname will be used
# UrlSubstitutionExp can be given same as mapped peer url, so that mapped peer url can be used
# UrlSubstitutionExp can have golang regex matchers like ${1}.local.example.${2}:${3} for pattern
 # like peer0.org1.example.com:1234 which converts peer0.org1.example.com to peer0.org1.local.example.com:1234
# sslTargetOverrideUrlSubstitutionExp follow in the same lines as
 # SubstitutionExp for the fields gprcOptions.ssl-target-name-override respectively
# In any case mappedHost's config will be used, so mapped host cannot be empty, if entityMatchers are used
# EntityMatchers支持使用静态配置替换网络主机名,以便可以映射属性。
# 正则表达式可以用于此目的
# UrlSubstitutionExp可以为空,这意味着将使用相同的网络主机名
# UrlSubstitutionExp可以与映射的对等节点url相同,这样就可以使用映射的对等url
#entityMatchers:
entityMatchers:
  peer:
    - pattern: (\w+).org1.example.com:(\d+)
      urlSubstitutionExp: ${1}.org1.example.com:${2}
      sslTargetOverrideUrlSubstitutionExp: ${1}.org1.example.com
      mappedHost: peer0.org1.example.com

    - pattern: (\w+).org2.example.com:(\d+)
      urlSubstitutionExp: ${1}.org2.example.com:${2}
      sslTargetOverrideUrlSubstitutionExp: ${1}.org2.example.com
      mappedHost: peer0.org2.example.com

    - pattern: (\w+).org1.example.(\w+)
      urlSubstitutionExp: peer0.org1.example.com:7051
      sslTargetOverrideUrlSubstitutionExp: peer0.org1.example.com
      mappedHost: peer0.org1.example.com

    - pattern: (\w+).org2.example.(\w+)
      urlSubstitutionExp: peer0.org2.example.com:8051
      sslTargetOverrideUrlSubstitutionExp: peer0.org2.example.com
      mappedHost: peer0.org2.example.com

    - pattern: (\w+).example1.(\w+):(\d+)
      urlSubstitutionExp: ${1}.org1.example.${2}:${3}
      sslTargetOverrideUrlSubstitutionExp: ${1}.org1.example.${2}
      mappedHost: peer0.org1.example.com

    - pattern: (\w+).org1.example.(\w+):(\d+)
      urlSubstitutionExp: peer0.org1.example.com:7051
      sslTargetOverrideUrlSubstitutionExp: peer0.org1.example.com
      mappedHost: peer0.org1.example.com

  orderer:
    - pattern: (\w+).example.(\w+)
      urlSubstitutionExp: orderer.example.com:7050
      sslTargetOverrideUrlSubstitutionExp: orderer.example.com
      mappedHost: orderer.example.com

    - pattern: (\w+).example2.(\w+)
      urlSubstitutionExp: localhost:7050
      sslTargetOverrideUrlSubstitutionExp: localhost
      mappedHost: orderer.example.com

    - pattern: (\w+).example3.(\w+)
      urlSubstitutionExp:
      sslTargetOverrideUrlSubstitutionExp:
      mappedHost: orderer.example.com

    - pattern: (\w+).example4.(\w+):(\d+)
      urlSubstitutionExp: ${1}.example.${2}:${3}
      sslTargetOverrideUrlSubstitutionExp: ${1}.example.${2}
      mappedHost: orderer.example.com

  certificateAuthority:
    - pattern: (\w+).org1.example.(\w+)
      urlSubstitutionExp:
      sslTargetOverrideUrlSubstitutionExp: ca.example.com
      mappedHost: ca.org1.example.com

    - pattern: (\w+).org2.example.(\w+)
      urlSubstitutionExp:
      sslTargetOverrideUrlSubstitutionExp: ca.example.com
      mappedHost: ca.org2.example.com

9. operations部分

#################################################################################    Operations部分#    从Fabric core.yaml复制而来###############################################################################operations:  # host and port for the operations server  listenAddress: 127.0.0.1:8080  # TLS configuration for the operations endpoint  tls:    # TLS enabled    enabled: false    # TODO replace cert.file, key.file and clientRootCAs.files to tlsCACerts as used elsewhere in this config file    # path to PEM encoded server certificate for the operations server    cert:      file:    # path to PEM encoded server key for the operations server    key:      file:    # require client certificate authentication to access all resources    clientAuthRequired: false    # paths to PEM encoded ca certificates to trust for client authentication    clientRootCAs:      files: []

10. Metrics部分

#################################################################################    Metrics 部分#    copied from Fabric's core.yaml###############################################################################metrics:  # metrics provide选项可以是statsd, prometheus,或disabled  provider: prometheus  # statsd configuration  # statsd配置  statsd:    # network类型: tcp或udp    network: udp    # statsd server address    address: 127.0.0.1:8125    # the interval at which locally cached counters and gauges are pushed    # to statsd; timings are pushed immediately    # 本地缓存的计数器和计量表被推入statsd的时间间隔;时间被立即推后    writeInterval: 10s    # prefix is prepended to all emitted statsd metrics    prefix:

11. 改写一个配置文件

现在我们来改写一个适用于我们网络的配置文件。在fabric-sdk-go路径下新建一个名为config.yaml的配置文件并编辑。我们将官方的config_e2e_multiorg_bootstrap.yaml文件进行改写,相关文件可在官方githubhttps://github.com/hyperledger/fabric-sdk-go/blob/main/test/fixtures/config/config_e2e_multiorg_bootstrap.yaml上找到。我们只将所有的证书路径改成我们项目的对应路径,以及将端口号改为在基础网络中对应的端口号。改好的配置文件如下:

version: 1.0.0

client:
  organization: org1
  logging:
    level: info
  cryptoconfig:
    path: /root/go/src/fabric-sdk-go/fixtures/crypto-config
  credentialStore:
    path: "/tmp/state-store"
    cryptoStore:
      path: /tmp/msp
  BCCSP:
    security:
     enabled: true
     default:
      provider: "SW"
     hashAlgorithm: "SHA2"
     softVerify: true
     level: 256
  tlsCerts:
    systemCertPool: true
    client:
      key:
        path: /root/go/src/fabric-sdk-go/fixtures/crypto-config/peerOrganizations/org1.example.com/users/User1@org1.example.com/tls/client.key
      cert:
        path: /root/go/src/fabric-sdk-go/fixtures/crypto-config/peerOrganizations/org1.example.com/users/User1@org1.example.com/tls/client.crt

channels:
  orgchannel:
    peers:
      peer0.org1.example.com:
        endorsingPeer: true
        chaincodeQuery: true
        ledgerQuery: true
        eventSource: true

      peer0.org2.example.com:
        endorsingPeer: true
        chaincodeQuery: true
        ledgerQuery: true
        eventSource: true

    policies:
      queryChannelConfig:
        minResponses: 1
        maxTargets: 1
        retryOpts:
          attempts: 5
          initialBackoff: 500ms
          maxBackoff: 5s
          backoffFactor: 2.0

organizations:
  org1:
    mspid: Org1MSP 
    cryptoPath:  peerOrganizations/org1.example.com/users/{username}@org1.example.com/msp
    peers:
      - peer0.org1.example.com

  org2:
    mspid: Org2MSP
    cryptoPath:  peerOrganizations/org2.example.com/users/{username}@org2.example.com/msp
    peers:
      - peer0.org2.example.com

  ordererorg:   
      mspID: OrdererMSP
      cryptoPath: ordererOrganizations/example.com/users/{username}@example.com/msp

orderers:
  orderer.example.com:
    url: orderer.example.com:7050
    grpcOptions:
      ssl-target-name-override: orderer.example.com
      keep-alive-time: 0s
      keep-alive-timeout: 20s
      keep-alive-permit: false
      fail-fast: false
      allow-insecure: false
    tlsCACerts:
      path: /root/go/src/fabric-sdk-go/fixtures/crypto-config/ordererOrganizations/example.com/tlsca/tlsca.example.com-cert.pem

peers:
  peer0.org1.example.com:
    url: peer0.org1.example.com:7051
    grpcOptions:
      ssl-target-name-override: peer0.org1.example.com
      keep-alive-time: 0s
      keep-alive-timeout: 20s
      keep-alive-permit: false
      fail-fast: false
      allow-insecure: false
    tlsCACerts:
      path: /root/go/src/fabric-sdk-go/fixtures/crypto-config/peerOrganizations/org1.example.com/tlsca/tlsca.org1.example.com-cert.pem

  peer0.org2.example.com:
    url: peer0.org2.example.com:9051
    grpcOptions:
      ssl-target-name-override: peer0.org2.example.com
      keep-alive-time: 0s
      keep-alive-timeout: 20s
      keep-alive-permit: false
      fail-fast: false
      allow-insecure: false
    tlsCACerts:
      path: /root/go/src/fabric-sdk-go/fixtures/crypto-config/peerOrganizations/org2.example.com/tlsca/tlsca.org2.example.com-cert.pem

entityMatchers:
  peer:
    - pattern: (\w+).org1.example.com:(\d+)
      urlSubstitutionExp: ${1}.org1.example.com:${2}
      sslTargetOverrideUrlSubstitutionExp: ${1}.org1.example.com
      mappedHost: peer0.org1.example.com

    - pattern: (\w+).org2.example.com:(\d+)
      urlSubstitutionExp: ${1}.org2.example.com:${2}
      sslTargetOverrideUrlSubstitutionExp: ${1}.org2.example.com
      mappedHost: peer0.org2.example.com

四、初始化及加入通道

1. 定义所需结构体

在项目路径下新建名为sdkInit的文件夹,此文件夹用于存放实现sdk的代码。在sdkInit路径下新建sdkInfo.go并编辑如下:

导入所需包

package sdkInit
import (
	mspclient "github.com/hyperledger/fabric-sdk-go/pkg/client/msp"
	"github.com/hyperledger/fabric-sdk-go/pkg/client/resmgmt"
	contextAPI "github.com/hyperledger/fabric-sdk-go/pkg/common/providers/context"
	"github.com/hyperledger/fabric-sdk-go/pkg/common/providers/fab"
)
  • mspclient "github.com/hyperledger/fabric-sdk-go/pkg/client/msp"

    msp包允许在Fabric网络上创建和更新用户。msp客户端支持以下操作:注册、重注册、登记和获取身份签名。基本工作流为:

    • 准备客户端上下文

    • 创建msp客户端

    • 登记用户

    • 注册用户

  • "github.com/hyperledger/fabric-sdk-go/pkg/client/resmgmt"

    resmgmt包用于在Fabric网络中创建和更新资源。它允许管理员创建和/或更新通道,并允许对等节点加入通道。管理员还可以在对等节点上执行链码相关操作,如安装、实例化、升级链码等。基本工作流为:

    • 准备客户端上下文

    • 创建资源管理器客户端

    • 创建新通道

    • 节点加入通道

    • 查询对等节点的通道,安装/实例化的链代码等。

  • contextAPI "github.com/hyperledger/fabric-sdk-go/pkg/common/providers/context"

    提供所需上下文接口

type OrgInfo struct {
	OrgAdminUser          string //  管理员用户名,如"Admin"
	OrgName               string //  组织名,如"Org1"
	OrgMspId              string //  组织MSPid,如"Org1MSP"
	OrgUser               string //  用户名,如"User1"
	orgMspClient          *mspclient.Client // MSP客户端
	OrgAdminClientContext *contextAPI.ClientProvider // 客户端上下文信息
	OrgResMgmt            *resmgmt.Client // 资源管理客户端
	OrgPeerNum            int // 组织节点个数
	OrgAnchorFile         string //   锚节点配置文件路径 
}

type SdkEnvInfo struct {
	// 通道信息
	ChannelID     string // 通道名称,如"simplecc"
	ChannelConfig string // 通道配置文件路径

	// 组织信息
	Orgs []*OrgInfo
	// 排序服务节点信息
	OrdererAdminUser     string // orederer管理员用户名,如"Admin"
	OrdererOrgName       string // orderer组织名,如"OrdererOrg"
	OrdererEndpoint      string // orderer端点,如"orderer.example.com"
	OrdererClientContext *contextAPI.ClientProvider // orderer客户端上下文
	// 链码信息
	ChaincodeID      string // 链码名称
	ChaincodePath    string // 链码路径
	ChaincodeVersion string // 链码版本
}

2.初始化

sdkInit路径下新建sdkSetting.go并编辑如下:

导入所需包

package sdkInit
import (
	"fmt"
	mspclient "github.com/hyperledger/fabric-sdk-go/pkg/client/msp"
	"github.com/hyperledger/fabric-sdk-go/pkg/client/resmgmt"
	"github.com/hyperledger/fabric-sdk-go/pkg/core/config"
	"github.com/hyperledger/fabric-sdk-go/pkg/fabsdk"
)
  • "github.com/hyperledger/fabric-sdk-go/pkg/core/config":获取所需配置文件

  • "github.com/hyperledger/fabric-sdk-go/pkg/fabsdk"fabsdk包允许客户端使用Hyperledger Fabric网络。

func Setup(configFile string, info *SdkEnvInfo) (*fabsdk.FabricSDK, error) {
	var err error
    // 使用fabsdk包的new方法根据config.yaml文件提供的网络信息初始化sdk
	sdk, err := fabsdk.New(config.FromFile(configFile)) 
	if err != nil {
		return nil, err
	}
	// 为组织获得Client句柄和Context信息
	for _, org := range info.Orgs {
        // 初始化组织msp客户端
		org.orgMspClient, err = mspclient.New(sdk.Context(), mspclient.WithOrg(org.OrgName))
		if err != nil {
			return nil, err
		}
        // 创建所有所需上下文信息
		orgContext := sdk.Context(fabsdk.WithUser(org.OrgAdminUser), fabsdk.WithOrg(org.OrgName))
		org.OrgAdminClientContext = &orgContext

		// 新建客户端资源管理器实例
		resMgmtClient, err := resmgmt.New(orgContext)
		if err != nil {
			return nil, fmt.Errorf("根据指定的资源管理客户端Context创建通道管理客户端失败: %v", err)
		}
		org.OrgResMgmt = resMgmtClient
	}

	// 为Orderer获得Context信息
	ordererClientContext := sdk.Context(fabsdk.WithUser(info.OrdererAdminUser), fabsdk.WithOrg(info.OrdererOrgName))
	info.OrdererClientContext = &ordererClientContext
	return sdk, nil
}

3. 创建及加入通道

继续在sdkSetting.go文件中编辑如下:

  • 导入所需包

import (
    [......]
	"github.com/hyperledger/fabric-sdk-go/pkg/common/errors/retry"
	"github.com/hyperledger/fabric-sdk-go/pkg/common/providers/msp"
)