hyperledger Fabric 2.3版本使用Go SDK搭建区块浏览器

前言

最近使用fabric 的Go SDK搭建了个Go服务器,完整项目还包括链代码的调用以及相关连接配置文件,这里只给出区块链浏览器相关的构建代码。由于百度博客找的资料太少或者又是不全,分享下希望对大家有帮助。

效果图(Vue前端)

部分数据简单地模拟了下
主要功能包括可以查询最新的区块以及通过交易ID查询交易详细信息
在这里插入图片描述
在这里插入图片描述

参考博客

https://blog.csdn.net/AlexTan_/article/details/110826476
区块体结构:

fabric连接服务

本人使用了iris搭建了Go Rest API这里只给出具体的区块及交易载荷的解析(参考博客熟悉区块体结构)
相关文件结构:

关键代码

entity.go

package services

//自定义区块结构体
//注意:DataHash并不是当前区块哈希,
//当前区块哈希的计算方式为区块头的三个字段(即number、previous_hash、data_hash)
//首先使用ASN.1中的DER编码规则进行编码,而后进行SHA256哈希值计算得出。
type Block struct {
	Number               uint64   `json:"number"` //区块号
	PreviousHash         []byte   `json:"previousHash"` //前区块Hash
	DataHash             []byte    `json:"dataHash"` //交易体Hash
	BlockHash			 []byte    `json:"blockHash"` //区块Hash
	TxNum			     int	  `json:"txNum"`  //区块内交易个数
	TransactionList		 []*Transaction   `json:"transactionList"` //交易列表
	CreateTime			 string   `json:"createTime"` //区块生成时间
}
type Transaction struct {
	TransactionActionList		 []*TransactionAction   `json:"transactionActionList"` //交易列表
}

type TransactionAction struct {
	TxId 			string 		`json:"txId"` //交易ID
	BlockNum 		uint64 		`json:"blockNum"` //区块号
	Type			string 		`json:"type"` //交易类型
	Timestamp		string 		`json:"timestamp"` //交易创建时间
	ChannelId		string 		`json:"channelId"` //通道ID
	Endorsements 	[]string 	`json:"endorsements"` //背书组织ID列表
	ChaincodeId		string 		`json:"chaincodeId"` //链代码名称
	ReadSetList			[]string 		`json:"readSetList"` //读集
	WriteSetList		[]string 		`json:"writeSetList"` //写集
}

chainBrowserService.go

package services

import (
	"encoding/json"
	"fmt"
	"github.com/hyperledger/fabric-sdk-go/pkg/client/ledger"
	"github.com/hyperledger/fabric-sdk-go/pkg/common/providers/fab"
	"github.com/hyperledger/fabric-sdk-go/pkg/core/config"
	"github.com/hyperledger/fabric-sdk-go/pkg/fabsdk"
	"github.com/hyperledger/fabric-sdk-go/pkg/util/pathvar"
	"log"
)

//区块链浏览器服务

var mainSDK *fabsdk.FabricSDK
var ledgerClient *ledger.Client

const (
	org1Name      = "Org1"
	org2Name      = "Org2"
	org1Peer0 	  = "peer0.org1.example.com"
	org1AdminUser = "Admin"
	org2AdminUser = "Admin"
	org1User      = "User1"
	org2User      = "User1"
	channelID     = "mychannel"
	windowConfigPath = "D:/GoProject/src/github.com/rightstar/fabric-client-config/config/config.yaml"
	linuxConfigPath = "/root/go/src/github.com/rightstar/fabric-client-config/config/linuxConfig.yaml"
)
var chainBrowserConfigPath = windowConfigPath

//初始化区块浏览器SDK
func InitChainBrowserService(){
	log.Println("============ 初始化区块浏览器服务 ============")
	//获取fabsdk
	var err error
	ConfigBackend := config.FromFile(pathvar.Subst(chainBrowserConfigPath))
	mainSDK, err = fabsdk.New(ConfigBackend)
	if err != nil {
		panic(fmt.Sprintf("Failed to create new SDK: %s", err))
	}
	//获取context
	org1AdminChannelContext := mainSDK.ChannelContext(channelID, fabsdk.WithUser(org1AdminUser), fabsdk.WithOrg(org1Name))
	//Ledger client
	ledgerClient, err = ledger.New(org1AdminChannelContext)
	if err != nil {
		fmt.Printf("Failed to create new resource management client: %s", err)
	}
}


//查询账本信息
func QueryLedgerInfo() (*fab.BlockchainInfoResponse,error){
	ledgerInfo, err := ledgerClient.QueryInfo()
	if err != nil {
		fmt.Printf("QueryInfo return error: %s", err)
		return nil, err
	}
	return ledgerInfo,nil
}
//查询最新5个区块信息
func QueryLatestBlocksInfo() ([]*Block,error){
	ledgerInfo, err := ledgerClient.QueryInfo()
	if err != nil {
		fmt.Printf("QueryLatestBlocksInfo return error: %s\n", err)
		return nil, err
	}
	latestBlockList :=[]*Block{}
	lastetBlockNum :=ledgerInfo.BCI.Height-1

	for i:=lastetBlockNum;i>0&&i>(lastetBlockNum-5);i--{
		block,err :=QueryBlockByBlockNumber(int64(i))
		if err != nil {
			fmt.Printf("QueryLatestBlocksInfo return error: %s", err)
			return latestBlockList, err
		}
		latestBlockList = append(latestBlockList,block)
	}
	return latestBlockList,nil
}
func QueryLatestBlocksInfoJsonStr()(string,error){
	blockList,err:=QueryLatestBlocksInfo()
	jsonStr,err :=json.Marshal(blockList)
	return string(jsonStr),err
}

//查询指定区块信息
func QueryBlockByBlockNumber(num int64) (*Block,error){
	rawBlock,err :=ledgerClient.QueryBlock(uint64(num))
	if err != nil {
		fmt.Printf("QueryBlock return error: %s", err)
		return nil, err
	}

	//解析区块体
	txList :=[]*Transaction{}
	for i :=range rawBlock.Data.Data{
		rawEnvelope,err :=GetEnvelopeFromBlock(rawBlock.Data.Data[i])
		if err != nil {
			fmt.Printf("QueryBlock return error: %s", err)
			return nil, err
		}
		transaction, err :=GetTransactionFromEnvelopeDeep(rawEnvelope)
		if err != nil {
			fmt.Printf("QueryBlock return error: %s", err)
			return nil, err
		}
		for i :=range transaction.TransactionActionList {
			transaction.TransactionActionList[i].BlockNum=rawBlock.Header.Number
		}
		txList= append(txList,transaction)
	}



	block :=Block{
		Number:       rawBlock.Header.Number,
		PreviousHash: rawBlock.Header.PreviousHash,
		DataHash:     rawBlock.Header.DataHash,
		BlockHash:    rawBlock.Header.DataHash, //需要计算
		TxNum:        len(rawBlock.Data.Data),
		TransactionList:     txList,
		CreateTime:   txList[0].TransactionActionList[0].Timestamp,
	}

	return &block,nil
}


//查询交易信息
func QueryTransactionByTxId(txId string) (*Transaction,error){
	rawTx,err :=ledgerClient.QueryTransaction(fab.TransactionID(txId))
	if err != nil {
		fmt.Printf("QueryBlock return error: %s", err)
		return nil, err
	}

	transaction, err :=GetTransactionFromEnvelopeDeep(rawTx.TransactionEnvelope)
	if err != nil {
		fmt.Printf("QueryBlock return error: %s", err)
		return nil, err
	}
	block,err :=ledgerClient.QueryBlockByTxID(fab.TransactionID(txId))
	if err != nil {
		fmt.Printf("QueryBlock return error: %s", err)
		return nil, err
	}
	for i :=range transaction.TransactionActionList {
		transaction.TransactionActionList[i].BlockNum=block.Header.Number
	}
	return transaction,nil
}
func QueryTransactionByTxIdJsonStr(txId string) (string,error){
	transaction,err:=QueryTransactionByTxId(txId)
	if err!=nil{
		return "",err
	}
	jsonStr,err :=json.Marshal(transaction)
	return string(jsonStr),err
}

jsonUtil.go


package services

import (
	"encoding/json"
	"fmt"
	"github.com/golang/protobuf/proto"
	"github.com/hyperledger/fabric-protos-go/common"
	"github.com/hyperledger/fabric-protos-go/ledger/rwset"
	"github.com/hyperledger/fabric-protos-go/ledger/rwset/kvrwset"
	"github.com/hyperledger/fabric-protos-go/msp"
	"github.com/hyperledger/fabric-protos-go/peer"
	"time"
)

//json Marshal/Unmarshal解析工具
//自定义解析类型


//获取区块体数据item
func GetEnvelopeFromBlock(data []byte) (*common.Envelope, error){
	var err error
	env := &common.Envelope{}
	if err = proto.Unmarshal(data, env); err != nil {
		fmt.Printf("block unmarshal err: %s", err)
	}

	return env, nil
}

//解析Transaction深度递归
func GetTransactionFromEnvelopeDeep(rawEnvelope *common.Envelope)(*Transaction,error) {
	//解析payload
	rawPayload := &common.Payload{}
	err := proto.Unmarshal(rawEnvelope.Payload, rawPayload)
	if err != nil {
		fmt.Printf("block unmarshal err: %s", err)
	}
	//解析channelHeader
	channelHeader := &common.ChannelHeader{}
	err = proto.Unmarshal(rawPayload.Header.ChannelHeader, channelHeader)
	if err != nil {
		fmt.Printf("block unmarshal err: %s\n", err)
	}
	//解析Transaction
	transactionObj := &peer.Transaction{}
	err = proto.Unmarshal(rawPayload.Data, transactionObj)
	if err != nil {
		fmt.Printf("block unmarshal err: %s\n", err)
	}
	transactionActionList := []*TransactionAction{}
	//解析transactionAction
	for i := range transactionObj.Actions {
		transactionAction, err := GetTransactionActionFromTransactionDeep(transactionObj.Actions[i])
		if err != nil {
			fmt.Printf("block unmarshal err: %s\n", err)
		}
		transactionAction.TxId = channelHeader.TxId
		transactionAction.Type = string(channelHeader.Type)
		transactionAction.Timestamp = time.Unix(channelHeader.Timestamp.Seconds, 0).Format("2006-01-02 15:04:05")
		transactionAction.ChannelId = channelHeader.ChannelId
		transactionActionList = append(transactionActionList, transactionAction)
	}
	transaction :=Transaction{transactionActionList}

	return &transaction,nil
}

func GetTransactionActionFromTransactionDeep(transactionAction *peer.TransactionAction)(*TransactionAction,error){

	//解析ChaincodeActionPayload 1
	ChaincodeActionPayload := &peer.ChaincodeActionPayload{}
	err := proto.Unmarshal(transactionAction.Payload, ChaincodeActionPayload)
	if err != nil {
		fmt.Printf("block unmarshal err: %s\n", err)
	}

	//解析ProposalResponsePayload 1.2
	ProposalResponsePayload := &peer.ProposalResponsePayload{}
	ChaincodeAction := &peer.ChaincodeAction{}
	chaincodeId :=""
	NsReadWriteSetList := []*rwset.NsReadWriteSet{}
	ReadWriteSetList := []*kvrwset.KVRWSet{}
	readSetList := []string{}
	writeSetList := []string{}
	if ChaincodeActionPayload.GetAction()!=nil{
		err = proto.Unmarshal(ChaincodeActionPayload.Action.ProposalResponsePayload, ProposalResponsePayload)
		if err != nil {
			fmt.Printf("block unmarshal err: %s", err)
		}
		//解析ChaincodeAction 1.2.1
		err = proto.Unmarshal(ProposalResponsePayload.Extension, ChaincodeAction)
		if err != nil {
			fmt.Printf("block unmarshal err: %s", err)
		}

		chaincodeId =ChaincodeAction.ChaincodeId.Name
		//解析TxReadWriteSet	1.2.1.1
		TxReadWriteSet := &rwset.TxReadWriteSet{}
		err = proto.Unmarshal(ChaincodeAction.Results, TxReadWriteSet)
		if err != nil {
			fmt.Printf("block unmarshal err: %s", err)
		}
		//解析TxReadWriteSet	1.2.1.1.1
		for i := range TxReadWriteSet.NsRwset {
			ReadWriteSet := &kvrwset.KVRWSet{}
			//解析ReadWriteSet	1.2.1.1.1.1
			err = proto.Unmarshal(TxReadWriteSet.NsRwset[i].Rwset, ReadWriteSet)
			if err != nil {
				fmt.Printf("block unmarshal err: %s", err)
			}

			//解析读集
			for i:=range ReadWriteSet.Reads{
				readSetJsonStr,err :=json.Marshal(ReadWriteSet.Reads[i])
				if err != nil {
					fmt.Printf("block unmarshal err: %s", err)
				}
				readSetList = append(readSetList,string(readSetJsonStr))
			}


			//解析写集
			for i:=range ReadWriteSet.Writes{
				writeSetItem := map[string]interface{}{
					"Key":ReadWriteSet.Writes[i].GetKey(),
					"Value":string(ReadWriteSet.Writes[i].GetValue()),
					"IsDelete":ReadWriteSet.Writes[i].GetIsDelete(),
				}

				writeSetJsonStr,err :=json.Marshal(writeSetItem)
				if err != nil {
					fmt.Printf("block unmarshal err: %s", err)
				}
				writeSetList = append(writeSetList,string(writeSetJsonStr))

			}

			ReadWriteSetList = append(ReadWriteSetList,ReadWriteSet)
			NsReadWriteSetList = append(NsReadWriteSetList,TxReadWriteSet.NsRwset[i])
		}

	}else{
		chaincodeId = "没有交易数据"
	}



	//log.Println("数据:"+fmt.Sprintf("%s\n",ChaincodeActionPayload.Action.GetEndorsements()[0] ))
	//解析Endorsements 1.3
	endorsements := []string{}
	if ChaincodeActionPayload.Action.GetEndorsements()!=nil{
		for i := range ChaincodeActionPayload.Action.GetEndorsements() {
			endorser := &msp.SerializedIdentity{}
			err = proto.Unmarshal(ChaincodeActionPayload.Action.Endorsements[i].Endorser, endorser)
			if err != nil {
				fmt.Printf("block unmarshal err: %s", err)
			}

			endorsements = append(endorsements,string(endorser.Mspid))
		}
	}

	transactionActionObj :=TransactionAction{
		Endorsements: endorsements,
		ChaincodeId:  chaincodeId,
		ReadSetList:      readSetList,
		WriteSetList:     writeSetList,
	}

	return &transactionActionObj,nil
}

其他

//根据操作系统判断服务器配置
func InitOSConfig(){
	log.Println("============ 正在使用"+runtime.GOOS+"系统 ============")
	switch runtime.GOOS {
		case "windows":
			ccpPath =windowCcpPath
			credPath =windowCredPath
			chainBrowserConfigPath = windowConfigPath
			break
		case "linux":
			ccpPath =linuxCcpPath
			credPath =linuxCredPath
			chainBrowserConfigPath = linuxConfigPath
			break
		default:
			ccpPath =linuxCcpPath
			credPath =linuxCredPath
			chainBrowserConfigPath = linuxConfigPath
		break
	}
}
  • config.yaml
name: "example-network"
#
# Schema version of the content. Used by the SDK to apply the corresponding parsing rules.
#
version: 1.0.0

#
# The client section used by GO SDK.
#
client:

  # Which organization does this application instance belong to? The value must be the name of an org
  # defined under "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
#  eventService:
#    # Event service type (optional). If not specified then the type is automatically
#    # determined from channel capabilities.
#    type: (deliver|eventhub)
    # 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
#    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.
  #GOPATH D:/GoProject
  cryptoconfig:
    path: ${GOPATH}/src/github.com/rightstar/fabric-client-config

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

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

   # BCCSP config for the client. Used by 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
    systemCertPool: false

    # [Optional]. Client key and cert for TLS handshake with peers and orderers
      #连接证书路径
    client:
      key:
        path:
      cert:
        path:

#
# [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:
  # name of the channel
  mychannel:
    # Required. list of orderers designated by the application to use for transactions on this
    # channel. This list can be a result of access control ("org1" can only access "ordererA"), or
    # operational decisions to share loads from applications among the orderers.  The values must
    # be "names" of orgs defined under "organizations/peers"
    # deprecated: not recommended, to override any orderer configuration items, entity matchers should be used.
    # orderers:
    #  - orderer.example.com

    # Required. 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
        endorsingPeer: true

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

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

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

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


    policies:
      #[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 retrieving discovery info
      discovery:
        #[Optional] discovery info will be retrieved for these number of random targets
        maxTargets: 2
        #[Optional] retry options for retrieving 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 the event service
      eventService:
        # [Optional] resolverStrategy specifies the peer resolver strategy to use when connecting to a peer
        # 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.
        # 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: Random
        # [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.
        # If set to 0 then only the most up-to-date peers are considered.
        # If set to -1 then all peers (regardless of block height) are considered for selection.
        # Default: 5
        blockHeightLagThreshold: 5
        # [Optional] reconnectBlockHeightLagThreshold - if >0 then 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.
        # If set to 0 then this feature is disabled.
        # Default: 10
        # NOTES:
        #   - peerMonitorPeriod must be >0 to enable this feature
        #   - Setting this value too low may cause the event client to disconnect/reconnect too frequently, thereby
        #     affecting performance.
        reconnectBlockHeightLagThreshold: 10
        # [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.
        # Default: 0 (disabled)
        peerMonitorPeriod: 5s

#
# list of participating organizations in this network
#
organizations:
  Org1:
    mspid: Org1MSP

    # This org's MSP store (absolute path or relative to client.cryptoconfig)
    cryptoPath:  peerOrganizations/org1.example.com/users/{username}@org1.example.com/msp
    users:
      Admin:
        cert:
          path: ${GOPATH}/src/github.com/rightstar/fabric-client-config/peerOrganizations/org1.example.com/users/Admin@org1.example.com/msp/signcerts/cert.pem
      User1:
        cert:
          path: ${GOPATH}/src/github.com/rightstar/fabric-client-config/peerOrganizations/org1.example.com/users/User1@org1.example.com/msp/signcerts/cert.pem


    peers:
      - peer0.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.
    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.
  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

    certificateAuthorities:
      - ca.org2.example.com


#
# 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.
#
orderers:
  orderer.example.com:
    url: localhost:7050

    # these are standard properties defined by the gRPC library
    # they will be passed in as-is to gRPC client constructor
    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
      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
      allow-insecure: false

    tlsCACerts:
      # Certificate location absolute path
      path: ${GOPATH}/src/github.com/rightstar/fabric-client-config/ordererOrganizations/example.com/msp/tlscacerts/tlsca.example.com-cert.pem

#
# List of peers to send various requests to, including endorsement, query
# and event listener registration.
#
peers:
  peer0.org1.example.com:
    # this URL is used to send endorsement and query requests
    url: grpcs://localhost:7051
    # eventUrl is only needed when using eventhub (default is delivery service)
    eventUrl: grpcs://localhost:7053

    grpcOptions:
      ssl-target-name-override: peer0.org1.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
      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
      allow-insecure: false

    tlsCACerts:
      # Certificate location absolute path
      path: ${GOPATH}/src/github.com/rightstar/fabric-client-config/peerOrganizations/org1.example.com/msp/tlscacerts/ca.crt


#
# 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.
#
certificateAuthorities:
  ca.org1.example.com:
    url: https://localhost:7054
    tlsCACerts:
      # Certificate location absolute path
      path: ${GOPATH}/src/github.com/rightstar/fabric-client-config/peerOrganizations/org1.example.com/ca/ca.org1.example.com-cert.pem

    # 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: admin
      enrollSecret: adminpw
    # [Optional] The optional name of the CA.
    caName: ca.org1.example.com

entityMatchers:
  peer:
    - pattern: (\w*)peer0.org1.example.com(\w*)
      urlSubstitutionExp: grpcs://localhost:7051
      eventUrlSubstitutionExp: grpcs://localhost:7053
      sslTargetOverrideUrlSubstitutionExp: peer0.org1.example.com
      mappedHost: peer0.org1.example.com

  orderer:
    - pattern: (\w*)orderer.example.com(\w*)
      urlSubstitutionExp: grpcs://localhost:7050
      sslTargetOverrideUrlSubstitutionExp: orderer.example.com
      mappedHost: orderer.example.com

  certificateAuthorities:
    - pattern: (\w*)ca.org1.example.com(\w*)
      urlSubstitutionExp: http://localhost:7054
      mappedHost: ca.org1.example.com

后续

完整项目代码请关注作者更新

  • 0
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 5
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值