最近使用fabric 的Go SDK搭建了个Go服务器,完整项目还包括链代码的调用以及相关连接配置文件,这里只给出区块链浏览器相关的构建代码。由于百度博客找的资料太少或者又是不全,分享下希望对大家有帮助。
效果图(Vue前端)部分数据简单地模拟了下
主要功能包括可以查询最新的区块以及通过交易ID查询交易详细信息
https://blog.csdn.net/AlexTan_/article/details/110826476
区块体结构:
本人使用了iris搭建了Go Rest API这里只给出具体的区块及交易载荷的解析(参考博客熟悉区块体结构)
相关文件结构:
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条)