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/[email protected]/tls/client.key
cert:
path: ${FABRIC_SDK_GO_PROJECT_PATH}/${CRYPTOCONFIG_FIXTURES_PATH}/peerOrganizations/tls.example.com/users/[email protected]/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/[email protected]/tls/client.key
cert:
path: ${FABRIC_SDK_GO_PROJECT_PATH}/${CRYPTOCONFIG_FIXTURES_PATH}/peerOrganizations/tls.example.com/users/[email protected]/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/[email protected]/tls/client.key
cert:
path: ${FABRIC_SDK_GO_PROJECT_PATH}/${CRYPTOCONFIG_FIXTURES_PATH}/peerOrganizations/tls.example.com/users/[email protected]/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/[email protected]/tls/client.key
cert:
path: ${FABRIC_SDK_GO_PROJECT_PATH}/${CRYPTOCONFIG_FIXTURES_PATH}/peerOrganizations/tls.example.com/users/[email protected]/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/[email protected]/tls/client.key
cert:
path: /root/go/src/fabric-sdk-go/fixtures/crypto-config/peerOrganizations/org1.example.com/users/[email protected]/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"
)
  • 调用创建通道函数及加入通道
func CreateAndJoinChannel(info *SdkEnvInfo) error {
fmt.Println(">> 开始创建通道......")
if len(info.Orgs) == 0 {
return fmt.Errorf("通道组织不能为空,请提供组织信息")
}
// 获得所有组织的签名信息
signIds := []msp.SigningIdentity{}
for _, org := range info.Orgs {
// Get signing identity that is used to sign create channel request
orgSignId, err := org.orgMspClient.GetSigningIdentity(org.OrgAdminUser)
if err != nil {
return fmt.Errorf("GetSigningIdentity error: %v", err)
}
signIds = append(signIds, orgSignId)
}
// 创建通道,createChannel方法在下面定义
if err := createChannel(signIds, info); err != nil {
return fmt.Errorf("Create channel error: %v", err)
}
fmt.Println(">> 创建通道成功")
fmt.Println(">> 加入通道......")
for _, org := range info.Orgs {
// 加入通道
if err := org.OrgResMgmt.JoinChannel(info.ChannelID, resmgmt.WithRetry(retry.DefaultResMgmtOpts), resmgmt.WithOrdererEndpoint("orderer.example.com")); err != nil {
return fmt.Errorf("%s peers failed to JoinChannel: %v", org.OrgName, err)
}
}
fmt.Println(">> 加入通道成功")
return nil
}
  • 创建通道
func createChannel(signIDs []msp.SigningIdentity, info *SdkEnvInfo) error {
// Channel management client 负责管理通道,如创建更新通道
chMgmtClient, err := resmgmt.New(*info.OrdererClientContext)
if err != nil {
return fmt.Errorf("Channel management client create error: %v", err)
}
// 根据channel.tx创建通道
req := resmgmt.SaveChannelRequest{ChannelID: info.ChannelID,
ChannelConfigPath: info.ChannelConfig,
SigningIdentities: signIDs}
if _, err := chMgmtClient.SaveChannel(req, resmgmt.WithRetry(retry.DefaultResMgmtOpts), resmgmt.WithOrdererEndpoint("orderer.example.com")); err != nil {
return fmt.Errorf("error should be nil for SaveChannel of orgchannel: %v", err)
}
fmt.Println(">>>> 使用每个org的管理员身份更新锚节点配置...")
//根据锚节点文件更新锚节点,与上面创建通道流程相同
for i, org := range info.Orgs {
req = resmgmt.SaveChannelRequest{ChannelID: info.ChannelID,
ChannelConfigPath: org.OrgAnchorFile,
SigningIdentities: []msp.SigningIdentity{signIDs[i]}}
if _, err = org.OrgResMgmt.SaveChannel(req, resmgmt.WithRetry(retry.DefaultResMgmtOpts), resmgmt.WithOrdererEndpoint("orderer.example.com")); err != nil {
return fmt.Errorf("SaveChannel for anchor org %s error: %v", org.OrgName, err)
}
}
fmt.Println(">>>> 使用每个org的管理员身份更新锚节点配置完成")
return nil
}

五、链码生命周期

链码运行在一个隔离于背书peer节点进程的安全的Docker容器中。链码通过应用提交的交易来初始化以及管理账本状态。从hyperledger fabric v2.0版本开始启用了新的链码生命周期,Fabric 链码生命周期是一个过程,它允许多个组织在使用一个链码之前就如何操作达成一致。Fabric链码生命周期需要组织同意定义一个链码的参数,比如说名称、版本以及链码背书策略。通道成员通过以下四步达成共识。不是通道上的每一个组织都需要完成每一步。
  • 打包链码:这一步可以被一个或者每一个组织完成。
  • 安装链码在你的 peer 节点上:每一个用链码的组织需要完成这一步。
  • 为你的组织批准链码定义:使用链码的每一个组织需要完成这一步。链码能够在通道上运行之前,链码定义需要被足够多的组织批准来满足通道的生命周期背书(LifecycleEndorsement)策略(默认为大多数组织)。
  • 提交链码定义到链上:一旦通道上所需数量的组织已经同意,提交交易需要被提交。提交者首先从已同意组织中的足够的peer节点中收集背书,然后通过提交交易来提交链码声明。
1. 添加DiscoverLocalPeers方法
DiscoverLocalPeers方法可以自动查找的所有节点
sdkInit路径下新建一个名为intergration.go的文件。编辑如下:
package sdkInit
import (
"fmt"
"github.com/hyperledger/fabric-sdk-go/pkg/common/errors/retry"
"github.com/hyperledger/fabric-sdk-go/pkg/common/errors/status"
contextAPI "github.com/hyperledger/fabric-sdk-go/pkg/common/providers/context"
fabAPI "github.com/hyperledger/fabric-sdk-go/pkg/common/providers/fab"
contextImpl "github.com/hyperledger/fabric-sdk-go/pkg/context"
)
// 查找本地节点
func DiscoverLocalPeers(ctxProvider contextAPI.ClientProvider, expectedPeers int) ([]fabAPI.Peer, error) {
ctx, err := contextImpl.NewLocal(ctxProvider)
if err != nil {
return nil, fmt.Errorf("error creating local context: %v", err)
}
discoveredPeers, err := retry.NewInvoker(retry.New(retry.TestRetryOpts)).Invoke(
func() (interface{}, error) {
peers, serviceErr := ctx.LocalDiscoveryService().GetPeers()
if serviceErr != nil {
return nil, fmt.Errorf("getting peers for MSP [%s] error: %v", ctx.Identifier().MSPID, serviceErr)
}
if len(peers) < expectedPeers {
return nil, status.New(status.TestStatus, status.GenericTransient.ToInt32(), fmt.Sprintf("Expecting %d pee