Fabric v2.0.1
go version go1.13.7 darwin/amd64
GoLand 2019.3
也可不使用 go module 管理依赖,设置 GO111MODULE=off
到目前为止 Fabric 还没有启用 go module
管理依赖,首先将工程转换为 go module
工程。
go mod init
会根据 Gopkg.toml
、Gopkg.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 $@
...
使用 sampleconfig
搭建 Fabric
开发调试网络
Mac
或 Linux
环境可通过脚本 快速准备环境。Windows Cygwin
未经测试
脚本使用方式:
fab.sh
内容拷贝到新建目录下 fab.sh
文件中chmod u+x fab.sh
./fab.sh new
fab.sh
生成 utils.sh
辅助脚本可用于简化操作 source utils.sh
,之后使用其提供的函数./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