Hyperledger Fabric 2.0 debug 环境准备

0. 环境


Fabric v2.0.1
go version go1.13.7 darwin/amd64
GoLand 2019.3

1. 转换为 go module


也可不使用 go module 管理依赖,设置 GO111MODULE=off

到目前为止 Fabric 还没有启用 go module 管理依赖,首先将工程转换为 go module 工程。

go mod init 会根据 Gopkg.tomlGopkg.lock 生成依赖并添加到 go.mod 中,期间会访问 google.com 的一些包,go mod init 过程中不会使用 GOPROXY,因此设置HTTP_PROXY ,否则 timeout 的依赖解析不会添加 go.mod 中,后续可能下载不匹配的依赖版本。

cd github.com/hyperledger/fabric
git checkout v2.0.1
HTTP_PROXY=http://127.0.0.1:8010 HTTPS_PROXY=http://127.0.0.1:8010 go mod init

个人理解 GoLand 即使启用了 Vendoring mode 还是会以 go module 为主管理 vendor 目录,可能误更新 vendor 目录。可以通过 git status 检查vendor 是否改动。

编译


make orderer 遇到如下错误:

Building build/bin/orderer
GOBIN=/Users/dian/workspaces/go_workspace/src/github.com/hyperledger/fabric/build/bin go install "" -tags "" -ldflags "-X github.com/hyperledger/fabric/common/metadata.Version=2.0.1 -X github.com/hyperledger/fabric/common/metadata.CommitSHA=1cfa5da98 -X github.com/hyperledger/fabric/common/metadata.BaseDockerLabel=org.hyperledger.fabric -X github.com/hyperledger/fabric/common/metadata.DockerNamespace=hyperledger -X github.com/hyperledger/fabric/common/metadata.BaseDockerNamespace=hyperledger" github.com/hyperledger/fabric/cmd/orderer
go: downloading golang.org/x/crypto v0.0.0-20190621222207-cc06ce4a13d4
go: extracting golang.org/x/crypto v0.0.0-20190621222207-cc06ce4a13d4
go: gopkg.in/fsnotify/[email protected] used for two different module paths (gopkg.in/fsnotify.v1 and gopkg.in/fsnotify/fsnotify.v1)
make: *** [build/bin/orderer] Error 1

解决办法,构建时加上 -mod=vendor 选项,增加GO_BUILD_FLAGS变量修改 Makefile 209行如下:

...
GO_BUILD_FLAGS ?= -mod=vendor
$(BUILD_DIR)/bin/%: GO_LDFLAGS = $(METADATA_VAR:%=-X $(PKGNAME)/common/metadata.%)
$(BUILD_DIR)/bin/%:
	@echo "Building $@"
	@mkdir -p $(@D)
	GOBIN=$(abspath $(@D)) go install "$(GO_BUILD_FLAGS)" -tags "$(GO_TAGS)" -ldflags "$(GO_LDFLAGS)" $(pkgmap.$(@F))
	@touch $@
...

2. Fabric 网络


使用 sampleconfig 搭建 Fabric 开发调试网络

Bash 脚本

MacLinux 环境可通过脚本 快速准备环境。Windows Cygwin 未经测试

脚本使用方式:

  1. 新建一个目录,如 /tmp/fabric
  2. 将下面的 fab.sh 内容拷贝到新建目录下 fab.sh 文件中
  3. 设置执行权限 chmod u+x fab.sh
  4. 快速创建 ./fab.sh new </path/to/fabric source code>
  5. fab.sh 生成 utils.sh 辅助脚本可用于简化操作 source utils.sh ,之后使用其提供的函数
  6. 清理 ./fab.sh clean

fab.sh

#!/bin/bash

echo
echo '    ______      __         _     '
echo '   / ____/___ _/ /_  _____(_)____'
echo '  / /_  / __ `/ __ \/ ___/ / ___/'
echo ' / __/ / /_/ / /_/ / /  / / /__  '
echo '/_/    \__,_/_.___/_/  /_/\___/  '
echo

# Print the usage message
function usage() {
  echo "Usage: "
  echo "  $0 new /path/to/fabric-source"
  echo "  $0 clean"
}

function sedi () {
    case $(uname -s) in
        *[Dd]arwin* | *BSD* ) sed -i '' "$@";;
        *) sed -i "$@";;
    esac
}

function fabric::generateutils() {
    cat > utils.sh <<EOF
#!/bin/bash

export FABRIC_CFG_PATH=\$(pwd)

: \${SYS_CHANNEL_NAME:="sys-channel"}
: \${SYS_CHANNEL_PROFILE:="SampleDevModeSolo"}
: \${CHANNEL_NAME:="wagaga"}
: \${CHANNEL_PROFILE:="SampleSingleMSPChannel"}
: \${CC_NAME:="mycc"}
: \${CC_LABEL:="golang-external"}
: \${CC_VERSION:="1"}
: \${CC_SEQUENCE:="1"}

function configtxgen::genesis() {
    bin/configtxgen -profile \${SYS_CHANNEL_PROFILE} -channelID \$SYS_CHANNEL_NAME -outputBlock ./channel-artifacts/genesis.block
}

function configtxgen::channel() {
    bin/configtxgen -profile \$CHANNEL_PROFILE -channelID \$CHANNEL_NAME -outputCreateChannelTx ./channel-artifacts/channel.tx
}

function orderer::start() {
    bin/orderer &>/dev/null &
    echo "\$!"
}

function peer::start() {
    GOCACHE=\$(go env GOCACHE) GOPATH=\$(go env GOPATH) bin/peer node start &>/dev/null &
    echo "\$!"
}

function peer::create::channel() {
    bin/peer channel create -o 127.0.0.1:7050 -c \$CHANNEL_NAME -f ./channel-artifacts/channel.tx
}

function peer::join::channel() {
    bin/peer channel join -b \${CHANNEL_NAME}.block
}

function lifecycle::chaincode::package() {
    bin/peer lifecycle chaincode package --label \$CC_LABEL -p ./module/ -l golang ./chaincode.tgz
}

function lifecycle::chaincode::install() {
    bin/peer lifecycle chaincode install --peerAddresses 127.0.0.1:7051 ./chaincode.tgz
}

function lifecycle::chaincode::installed() {
    ret=\$(bin/peer lifecycle chaincode queryinstalled)
    echo "\$ret"
}

function lifecycle::chaincode::approve() {
    bin/peer lifecycle chaincode approveformyorg --channelID \$CHANNEL_NAME --name \$CC_NAME --version \$CC_VERSION --init-required --package-id \$(lifecycle::chaincode::packageId) --sequence \$CC_SEQUENCE --waitForEvent
}

function lifecycle::chaincode::commit() {
    bin/peer lifecycle chaincode commit --channelID \$CHANNEL_NAME --name \$CC_NAME --version \$CC_VERSION --init-required --sequence \$CC_SEQUENCE
}

function lifecycle::chaincode::packageId() {
    ret="\$(lifecycle::chaincode::installed)"
    PACKAGE_ID=\$(echo "\$ret" | sed -n "/Label: \$CC_LABEL/{s/^Package ID: //; s/, Label:.*\$//; p;}")
    echo "\$PACKAGE_ID"
}
EOF
    source utils.sh
}

function checkRequire() {
    for r in $@; do
        command -v $r >/dev/null 2>&1 || { echo >&2 "Require $r but it's not installed.  Aborting."; exit 1; }
    done
}

function fabric::new() {
    FAB_SRC=$1

    if [ -z "$FAB_SRC" ]; then
        usage
        exit 1
    fi

    if [ ! -d "$FAB_SRC" ]; then
        echo "ERROR! Fabric source $FAB_SRC not a directory."
        exit 1
    fi

    checkRequire sed make go jq

    echo
    echo "#########################################"
    echo "##### Building required program #########"
    echo "#########################################"
    echo

    CUR=$(pwd)

    cd $FAB_SRC
    GOMODULE=off
    if [ -f "$FAB_SRC/go.mod" ]; then
        GOMODULE=on
    fi
    GO111MODULE=$GOMODULE make configtxgen orderer peer

    cd $CUR

    cp -R $FAB_SRC/sampleconfig/* .
    cp -R $FAB_SRC/integration/externalbuilders .
    cp -R $FAB_SRC/integration/chaincode/module .

    ln -s $FAB_SRC/build/bin bin

    # modify orderer config
    echo
    echo "######################################################################"
    echo "##### Modify orderer config                                  #########"
    echo "##### General.BootstrapFile: channel-artifacts/genesis.block #########"
    echo "##### FileLedger.Location: production/orderer                #########"
    echo "######################################################################"
    echo
    sedi 's|    BootstrapFile:.*|    BootstrapFile: channel-artifacts/genesis.block|' orderer.yaml
    sedi 's|    Location:.*|    Location: production/orderer|' orderer.yaml

    # modify peer config
    echo
    echo "#######################################################"
    echo "##### Modify peer config                      #########"
    echo "##### peer.fileSystemPath: production/peer    #########"
    echo "##### vm.endpoint:                            #########"
    echo "##### chaincode:                              #########"
    echo "#####     externalBuilders:                   #########"
    echo "#####     - path $CUR/externalbuilders/golang #########"
    echo "#####       name: external-golang             #########"
    echo "#####       environmentWhitelist:             #########"
    echo "#####       - GOPROXY                         #########"
    echo "#####       - GOCACHE                         #########"
    echo "#####       - GOPATH                          #########"
    echo "#######################################################"
    echo
    sedi 's|    fileSystemPath:.*|    fileSystemPath: production/peer|' core.yaml
    sedi 's/    endpoint:.*/    endpoint: /' core.yaml

    sedi 's/    externalBuilders:.*/    externalBuilders: /' core.yaml

    cat > eb.tmp <<EOF
    - path: $(pwd)/externalbuilders/golang
      name: external-golang
      environmentWhitelist:
      - GOPROXY
      - GOCACHE
      - GOPATH

EOF
    sedi '/    externalBuilders:/r eb.tmp' core.yaml

    rm -f eb.tmp

    fabric::generateutils

    configtxgen::genesis

    # start orderer
    opid=$(orderer::start)

    # start peer
    ppid=$(peer::start)

    echo "started orderer $opid, started peer $ppid"
    sleep 2

    configtxgen::channel
    peer::create::channel
    peer::join::channel

    lifecycle::chaincode::package
    lifecycle::chaincode::install
    # lifecycle::chaincode::installed
    sleep 5
    PACKAGE_ID=$(lifecycle::chaincode::packageId)
    echo "---------------------------------------------"
    echo "$PACKAGE_ID"
    echo "---------------------------------------------"

    sleep 5
    kill $opid $ppid
}

function fabric::clean() {
    script_name=`basename $1`
    if [ "$(uname)" == "Darwin" ]; then
        find . -type d -depth 1 | xargs rm -rf {}
        find . -type l -exec rm -f {} \;
        find . -type f ! -name "$script_name" -exec rm -f {} \;
    else
        ls -I "$script_name" | xargs rm -rf {}
    fi
}

cmd=$1

if [ "$cmd" == "new" ]; then
    shift
    fabric::new $@
elif [ "$cmd" == "clean" ]; then
    fabric::clean $0
else
    usage
    exit 1
fi

手动搭建

cd $TMP,以下以当前工作目录为 $TMP

链接编译输出到 $TMP 目录

ln -s /path/to/fabric_source/build/bin bin

设置 FABRIC_CFG_PATH开启新终端主要设置配置路径变量

export FABRIC_CFG_PATH=$(pwd)

生成网络配置创世块,并启动 orderer

bin/configtxgen -profile SampleDevModeSolo -channelID sys-channel -outputBlock ./channel-artifacts/genesis.block

修改 orderer.yaml 文件

General:
    BootstrapFile: channel-artifacts/genesis.block

FileLedger:
    # Location: The directory to store the blocks in.
    # NOTE: If this is unset, a new temporary location will be chosen every time
    # the orderer is restarted, using the prefix specified by Prefix.
    Location: production/orderer
bin/orderer
2020-03-13 15:21:58.884 CST [localconfig] completeInitialization -> INFO 001 Kafka.Version unset, setting to 0.10.2.0
2020-03-13 15:21:58.884 CST [orderer.common.server] prettyPrintStruct -> INFO 002 Orderer config values:
	General.ListenAddress = "127.0.0.1"
	General.ListenPort = 7050
	General.TLS.Enabled = false
	General.TLS.PrivateKey = "/Users/dian/tmp/fabric/tls/server.key"
	General.TLS.Certificate = "/Users/dian/tmp/fabric/tls/server.crt"
	General.TLS.RootCAs = [/Users/dian/tmp/fabric/tls/ca.crt]
	General.TLS.ClientAuthRequired = false
	General.TLS.ClientRootCAs = []
	General.Cluster.ListenAddress = ""
	General.Cluster.ListenPort = 0
	General.Cluster.ServerCertificate = ""
	General.Cluster.ServerPrivateKey = ""
	General.Cluster.ClientCertificate = ""
	General.Cluster.ClientPrivateKey = ""
	General.Cluster.RootCAs = []
	General.Cluster.DialTimeout = 5s
	General.Cluster.RPCTimeout = 7s
	General.Cluster.ReplicationBufferSize = 20971520
	General.Cluster.ReplicationPullTimeout = 5s
	General.Cluster.ReplicationRetryTimeout = 5s
	General.Cluster.ReplicationBackgroundRefreshInterval = 5m0s
	General.Cluster.ReplicationMaxRetries = 12
	General.Cluster.SendBufferSize = 10
	General.Cluster.CertExpirationWarningThreshold = 168h0m0s
	General.Cluster.TLSHandshakeTimeShift = 0s
	General.Keepalive.ServerMinInterval = 1m0s
	General.Keepalive.ServerInterval = 2h0m0s
	General.Keepalive.ServerTimeout = 20s
	General.ConnectionTimeout = 0s
	General.GenesisMethod = ""
	General.GenesisFile = ""
	General.BootstrapMethod = "file"
	General.BootstrapFile = "/Users/dian/tmp/fabric/channel-artifacts/genesis.block"
	General.Profile.Enabled = false
	General.Profile.Address = "0.0.0.0:6060"
	General.LocalMSPDir = "/Users/dian/tmp/fabric/msp"
	General.LocalMSPID = "SampleOrg"
	General.BCCSP.ProviderName = "SW"
	General.BCCSP.SwOpts.SecLevel = 256
	General.BCCSP.SwOpts.HashFamily = "SHA2"
	General.BCCSP.SwOpts.Ephemeral = true
	General.BCCSP.SwOpts.FileKeystore.KeyStorePath = ""
	General.BCCSP.SwOpts.DummyKeystore =
	General.BCCSP.SwOpts.InmemKeystore =
	General.Authentication.TimeWindow = 15m0s
	General.Authentication.NoExpirationChecks = false
	FileLedger.Location = "/Users/dian/tmp/fabric/production/orderer"
	FileLedger.Prefix = "hyperledger-fabric-ordererledger"
	Kafka.Retry.ShortInterval = 5s
	Kafka.Retry.ShortTotal = 10m0s
	Kafka.Retry.LongInterval = 5m0s
	Kafka.Retry.LongTotal = 12h0m0s
	Kafka.Retry.NetworkTimeouts.DialTimeout = 10s
	Kafka.Retry.NetworkTimeouts.ReadTimeout = 10s
	Kafka.Retry.NetworkTimeouts.WriteTimeout = 10s
	Kafka.Retry.Metadata.RetryMax = 3
	Kafka.Retry.Metadata.RetryBackoff = 250ms
	Kafka.Retry.Producer.RetryMax = 3
	Kafka.Retry.Producer.RetryBackoff = 100ms
	Kafka.Retry.Consumer.RetryBackoff = 2s
	Kafka.Verbose = false
	Kafka.Version = 0.10.2.0
	Kafka.TLS.Enabled = false
	Kafka.TLS.PrivateKey = ""
	Kafka.TLS.Certificate = ""
	Kafka.TLS.RootCAs = []
	Kafka.TLS.ClientAuthRequired = false
	Kafka.TLS.ClientRootCAs = []
	Kafka.SASLPlain.Enabled = false
	Kafka.SASLPlain.User = ""
	Kafka.SASLPlain.Password = ""
	Kafka.Topic.ReplicationFactor = 3
	Debug.BroadcastTraceDir = ""
	Debug.DeliverTraceDir = ""
	Consensus = map[SnapDir:/var/hyperledger/production/orderer/etcdraft/snapshot WALDir:/var/hyperledger/production/orderer/etcdraft/wal]
	Operations.ListenAddress = "127.0.0.1:8443"
	Operations.TLS.Enabled = false
	Operations.TLS.PrivateKey = ""
	Operations.TLS.Certificate = ""
	Operations.TLS.RootCAs = []
	Operations.TLS.ClientAuthRequired = false
	Operations.TLS.ClientRootCAs = []
	Metrics.Provider = "disabled"
	Metrics.Statsd.Network = "udp"
	Metrics.Statsd.Address = "127.0.0.1:8125"
	Metrics.Statsd.WriteInterval = 30s
	Metrics.Statsd.Prefix = ""
2020-03-13 15:21:58.940 CST [fsblkstorage] NewProvider -> INFO 003 Creating new file ledger directory at /Users/dian/tmp/fabric/production/orderer/chains
2020-03-13 15:21:58.945 CST [orderer.common.server] extractSysChanLastConfig -> INFO 004 Bootstrapping because no existing channels
2020-03-13 15:21:58.951 CST [fsblkstorage] newBlockfileMgr -> INFO 005 Getting block information from block storage
2020-03-13 15:21:58.988 CST [orderer.consensus.solo] HandleChain -> WARN 006 Use of the Solo orderer is deprecated and remains only for use in test environments but may be removed in the future.
2020-03-13 15:21:58.989 CST [orderer.commmon.multichannel] Initialize -> INFO 007 Starting system channel 'sys-channel' with genesis block hash e361dd19160d745745cb4bb2eb41f5b409bcb00b502b536b12dc2f7fdceac9ba and orderer type solo
2020-03-13 15:21:58.989 CST [orderer.common.server] Main -> INFO 008 Starting orderer:
 Version: 2.0.1
 Commit SHA: 1cfa5da98
 Go version: go1.13.7
 OS/Arch: darwin/amd64
2020-03-13 15:21:58.989 CST [orderer.common.server] Main -> INFO 009 Beginning to serve requests

创建 channel

bin/configtxgen -profile SampleSingleMSPChannel -outputCreateChannelTx ./channel-artifacts/channel.tx -channelID wagaga
bin/peer channel create -o 127.0.0.1:7050 -c wagaga -f ./channel-artifacts/channel.tx

启动 peer

bin/peer node start
2020-03-13 15:59:41.714 CST [nodeCmd] serve -> INFO 001 Starting peer:
 Version: 2.1.0
 Commit SHA: 3c198339d
 Go version: go1.13.7
 OS/Arch: darwin/amd64
 Chaincode:
  Base Docker Label: org.hyperledger.fabric
  Docker Namespace: hyperledger
2020-03-13 15:59:41.714 CST [peer] getLocalAddress -> INFO 002 Auto-detected peer address: 192.168.43.62:7051
2020-03-13 15:59:41.714 CST [peer] getLocalAddress -> INFO 003 Host is 0.0.0.0 , falling back to auto-detected address: 192.168.43.62:7051
2020-03-13 15:59:41.770 CST [ledgermgmt] NewLedgerMgr -> INFO 004 Initializing LedgerMgr
2020-03-13 15:59:42.138 CST [ledgermgmt] NewLedgerMgr -> INFO 005 Initialized LedgerMgr
2020-03-13 15:59:42.146 CST [gossip.service] New -> INFO 006 Initialize gossip with endpoint 192.168.43.62:7051
2020-03-13 15:59:42.147 CST [gossip.gossip] New -> INFO 007 Creating gossip service with self membership of Endpoint: , InternalEndpoint: 192.168.43.62:7051, PKI-ID: 0d46737a45894d123895671221dbaddf8480fb0364f404be3aed491df442945f, Metadata:
2020-03-13 15:59:42.147 CST [gossip.gossip] New -> WARN 008 External endpoint is empty, peer will not be accessible outside of its organization
2020-03-13 15:59:42.147 CST [gossip.gossip] start -> INFO 009 Gossip instance 192.168.43.62:7051 started
2020-03-13 15:59:42.148 CST [lifecycle] InitializeLocalChaincodes -> INFO 00a Initialized lifecycle cache with 1 already installed chaincodes
2020-03-13 15:59:42.148 CST [nodeCmd] computeChaincodeEndpoint -> INFO 00b Entering computeChaincodeEndpoint with peerHostname: 192.168.43.62
2020-03-13 15:59:42.148 CST [nodeCmd] computeChaincodeEndpoint -> INFO 00c Exit with ccEndpoint: 192.168.43.62:7052
2020-03-13 15:59:42.148 CST [nodeCmd] createChaincodeServer -> WARN 00d peer.chaincodeListenAddress is not set, using 192.168.43.62:7052
2020-03-13 15:59:42.152 CST [sccapi] DeploySysCC -> INFO 00e deploying system chaincode 'lscc'
2020-03-13 15:59:42.152 CST [sccapi] DeploySysCC -> INFO 00f deploying system chaincode 'cscc'
2020-03-13 15:59:42.152 CST [sccapi] DeploySysCC -> INFO 010 deploying system chaincode 'qscc'
2020-03-13 15:59:42.152 CST [sccapi] DeploySysCC -> INFO 011 deploying system chaincode '_lifecycle'
2020-03-13 15:59:42.152 CST [nodeCmd] serve -> INFO 012 Deployed system chaincodes
2020-03-13 15:59:42.152 CST [discovery] NewService -> INFO 013 Created with config TLS: false, authCacheMaxSize: 1000, authCachePurgeRatio: 0.750000
2020-03-13 15:59:42.152 CST [nodeCmd] registerDiscoveryService -> INFO 014 Discovery service activated
2020-03-13 15:59:42.152 CST [nodeCmd] serve -> INFO 015 Starting peer with ID=[jdoe], network ID=[dev], address=[192.168.43.62:7051]
2020-03-13 15:59:42.152 CST [nodeCmd] serve -> INFO 016 Started peer with ID=[jdoe], network ID=[dev], address=[192.168.43.62:7051]
2020-03-13 15:59:42.153 CST [kvledger] LoadPreResetHeight -> INFO 017 Loading prereset height from path [/Users/dian/tmp/fabric/production/peer/ledgersData/chains]
2020-03-13 15:59:42.153 CST [fsblkstorage] preResetHtFiles -> INFO 018 No active channels passed
2020-03-13 16:00:51.875 CST [ledgermgmt] CreateLedger -> INFO 019 Creating ledger [wagaga] with genesis block
2020-03-13 16:00:51.893 CST [fsblkstorage] newBlockfileMgr -> INFO 01a Getting block information from block storage
2020-03-13 16:00:51.988 CST [kvledger] CommitLegacy -> INFO 01b [wagaga] Committed block [0] with 1 transaction(s) in 68ms (state_validation=0ms block_and_pvtdata_commit=38ms state_commit=13ms) commitHash=[]
2020-03-13 16:00:52.004 CST [ledgermgmt] CreateLedger -> INFO 01c Created ledger [wagaga] with genesis block
2020-03-13 16:00:52.007 CST [peer.orderers] Update -> WARN 01d Config defines both orderer org specific endpoints and global endpoints, global endpoints will be ignored channel=wagaga
2020-03-13 16:00:52.008 CST [gossip.gossip] JoinChan -> INFO 01e Joining gossip network of channel wagaga with 1 organizations
2020-03-13 16:00:52.008 CST [gossip.gossip] learnAnchorPeers -> INFO 01f No configured anchor peers of SampleOrg for channel wagaga to learn about
2020-03-13 16:00:52.010 CST [gossip.state] NewGossipStateProvider -> INFO 020 Updating metadata information for channel wagaga, current ledger sequence is at = 0, next expected block is = 1
2020-03-13 16:00:52.011 CST [endorser] callChaincode -> INFO 021 finished chaincode: cscc duration: 138ms channel= txID=34fc745d
2020-03-13 16:00:52.011 CST [comm.grpc.server] 1 -> INFO 022 unary call completed grpc.service=protos.Endorser grpc.method=ProcessProposal grpc.peer_address=127.0.0.1:54807 grpc.code=OK grpc.call_duration=139.087093ms
2020-03-13 16:00:58.017 CST [gossip.election] beLeader -> INFO 023 0d46737a45894d123895671221dbaddf8480fb0364f404be3aed491df442945f : Becoming a leader
2020-03-13 16:00:58.017 CST [gossip.service] func1 -> INFO 024 Elected as a leader, starting delivery service for channel wagaga
2020-03-13 16:00:58.017 CST [deliveryClient] StartDeliverForChannel -> INFO 025 This peer will retrieve blocks from ordering service and disseminate to other peers in the organization for channel wagaga

Join Channel

bin/peer join channel -b wagaga.block
2020-03-13 16:00:51.871 CST [channelCmd] InitCmdFactory -> INFO 001 Endorser and orderer connections initialized
2020-03-13 16:00:52.011 CST [channelCmd] executeJoin -> INFO 002 Successfully submitted proposal to join channel
发布了10 篇原创文章 · 获赞 1 · 访问量 633

猜你喜欢

转载自blog.csdn.net/DAOSHUXINDAN/article/details/104812206