在网上看了很多hyperledger fabric安装的文章,也踩了很多坑,在此简单介绍关于mac系统下运行fabric-samples中first-network的流程,本身也是一个菜鸟,不正确不恰当的地方欢迎指正交流。
一、环境安装
(关于环境配置墙裂推荐这篇博客,特别是关于docker加速的,楼主按照教程改用了zhong'ke'da 的源,镜像下载速度快了不少,另外目前docker版本升级后链接博客的方法不适用,docker镜像可以用下述方法:
打开docker for mac的Perference,打开Docker Engine,右侧代码行中输入:
"registry-mirrors": [
"https://docker.mirrors.ustc.edu.cn/"
]
备注:以上是中科的源
结果如下:
运行
docker info
出现如下字样则说明配合成功
二、源码下载
#进入gopath的路径下文件夹
#没有的src以后的则使用mkdir创建,GOPATH需要提前调整好
cd $GOPATH/src/github.com/hyperledger
#下载fabric源码
git clone https://github.com/hyperledger/fabric.git
#进入下载的fabric然后切换到v1.0.6分支(也可以是其他,但是楼主暂时没尝试)
cd fabric
git tag #查看版本
git checkout v1.0.6 #切换版本
#进入hyperledger下载fabric-samples
git clone https://github.com/hyperledger/fabric-samples.git
#切换到相同分支
cd fabric-samples
git tag
git checkout v1.0.6
下载运行fabric所需的二进制文件:
# 将hyperledger/fabric/scripts/bootstrap.sh拷贝到hyperledger/fabric-samples中
cp -r ../fabric/scripts/boostrap.sh ../fabric-samples
# 修改bootstrap.sh权限
chmod +x bootstrap.sh
#运行bootstrap.sh
./bootstrap.sh
该命令会下载所需要的docker image,结果如下:
运行之前需要在fabric-samples下下载bin目录,里面存放生成身份信息的配置文件。git下来的fabric-samples是不含这个目录的,很多教程也没有说,楼主在这踩了好多坑; 另外网上给了一个kx上网下载的链接,然鹅一直是404 Not Found。终于在万能的CSDN上找到了资源,花了8个币下载了。虽然是1.0.5版本,但是试了也是可以用的,楼主自己上传了一个资源,不知道算不算侵权(侵权就删了),如果各位朋友有币的话可以花一个币下载,当然也可以私聊我给你发。
下载完成以后拷贝到fabric-samples目录下(同样是cp命令)。
三、自动运行
cd first-network
查看当前目录下byfn.sh的帮助文档:
first-network % ./byfn.sh -h
Usage:
byfn.sh -m up|down|restart|generate [-c ] [-t ] [-d ] [-f ] [-s ] [-i ]
byfn.sh -h|--help (print this message)
-m - one of 'up', 'down', 'restart' or 'generate'
- 'up' - bring up the network with docker-compose up
- 'down' - clear the network with docker-compose down
- 'restart' - restart the network
- 'generate' - generate required certificates and genesis block
-c - channel name to use (defaults to "mychannel")
-t - CLI timeout duration in microseconds (defaults to 10000)
-d - delay duration in seconds (defaults to 3)
-f - specify which docker-compose file use (defaults to docker-compose-cli.yaml)
-s - the database backend to use: goleveldb (default) or couchdb
-i - pass the image tag to launch the network using the tag: 1.0.1, 1.0.2, 1.0.3, 1.0.4 (defaults to latest)
Typically, one would first generate the required certificates and
genesis block, then bring up the network. e.g.:
byfn.sh -m generate -c mychannel
byfn.sh -m up -c mychannel -s couchdb
byfn.sh -m up -c mychannel -s couchdb -i 1.0.6
byfn.sh -m down -c mychannel
Taking all defaults:
byfn.sh -m generate
byfn.sh -m up
byfn.sh -m down
第一步,生成我们各种网络实体的所有证书和密钥。执行以下命令,当看到yes/no时输入y即可,如下:
./byfn.sh -m generate
Generating certs and genesis block for with channel 'mychannel' and CLI timeout of '10'
Continue (y/n)? y
proceeding ...
/Users/chenpeng/go/src/github.com/hyperledger/fabric-samples/first-network/../bin/cryptogen
##########################################################
##### Generate certificates using cryptogen tool #########
##########################################################
org1.example.com
org2.example.com
/Users/chenpeng/go/src/github.com/hyperledger/fabric-samples/first-network/../bin/configtxgen
##########################################################
######### Generating Orderer Genesis block ##############
##########################################################
2020-03-24 22:05:21.790 CST [common/configtx/tool] main -> INFO 001 Loading configuration
2020-03-24 22:05:21.813 CST [common/configtx/tool] doOutputBlock -> INFO 002 Generating genesis block
2020-03-24 22:05:21.815 CST [common/configtx/tool] doOutputBlock -> INFO 003 Writing genesis block
#################################################################
### Generating channel configuration transaction 'channel.tx' ###
#################################################################
2020-03-24 22:05:21.835 CST [common/configtx/tool] main -> INFO 001 Loading configuration
2020-03-24 22:05:21.838 CST [common/configtx/tool] doOutputChannelCreateTx -> INFO 002 Generating new channel configtx
2020-03-24 22:05:21.839 CST [common/configtx/tool] doOutputChannelCreateTx -> INFO 003 Writing new channel tx
#################################################################
####### Generating anchor peer update for Org1MSP ##########
#################################################################
2020-03-24 22:05:21.859 CST [common/configtx/tool] main -> INFO 001 Loading configuration
2020-03-24 22:05:21.862 CST [common/configtx/tool] doOutputAnchorPeersUpdate -> INFO 002 Generating anchor peer update
2020-03-24 22:05:21.863 CST [common/configtx/tool] doOutputAnchorPeersUpdate -> INFO 003 Writing anchor peer update
#################################################################
####### Generating anchor peer update for Org2MSP ##########
#################################################################
2020-03-24 22:05:21.887 CST [common/configtx/tool] main -> INFO 001 Loading configuration
2020-03-24 22:05:21.891 CST [common/configtx/tool] doOutputAnchorPeersUpdate -> INFO 002 Generating anchor peer update
2020-03-24 22:05:21.891 CST [common/configtx/tool] doOutputAnchorPeersUpdate -> INFO 003 Writing anchor peer update
这个指令生成了Org1MSPanchors.tx, Org2MSPanchors.tx,channel.tx, genesis.block.存储在first-networks/channel-artifacts下。如果不提供channel名称,则脚本将使用默认名称mychannel
。CLI超时参数(用-t标志指定)是一个可选值;如果你选择不设置它,那么CLI容器将会在脚本执行完之后退出。
接下来,启动整个网络,同样回答y:
./byfn.sh -m up
Starting with channel 'mychannel' and CLI timeout of '10'
Continue (y/n)? y
proceeding ...
Creating network "net_byfn" with the default driver
Creating volume "net_peer0.org2.example.com" with default driver
Creating volume "net_peer1.org2.example.com" with default driver
Creating volume "net_peer1.org1.example.com" with default driver
Creating volume "net_peer0.org1.example.com" with default driver
Creating volume "net_orderer.example.com" with default driver
Creating peer1.org1.example.com ... done
Creating peer0.org1.example.com ... done
Creating peer1.org2.example.com ... done
Creating peer0.org2.example.com ... done
Creating orderer.example.com ... done
Creating cli ... done
____ _____ _ ____ _____
/ ___| |_ _| / \ | _ \ |_ _|
\___ \ | | / _ \ | |_) | | |
___) | | | / ___ \ | _ < | |
|____/ |_| /_/ \_\ |_| \_\ |_|
Build your first network (BYFN) end-to-end test
Channel name : mychannel
Creating channel...
将继续运行,输出日志文件,启动所有容器,驱动一个端到端的应用场景。成功后输出如下内容:
Query Result: 90
2020-03-24 14:11:48.584 UTC [main] main -> INFO 007 Exiting.....
===================== Query on PEER3 on channel 'mychannel' is successful =====================
========= All GOOD, BYFN execution completed ===========
_____ _ _ ____
| ____| | \ | | | _ \
| _| | \| | | | | |
| |___ | |\ | | |_| |
|_____| |_| \_| |____/
使用一下命令关闭网络,改命令将关闭你的容器,移除加密材料和4个配置信息,并且从Docker仓库删除chaincode镜像。
./byfn.sh -m down
Stopping with channel 'mychannel' and CLI timeout of '10'
Continue (y/n)? y
proceeding ...
WARNING: The CHANNEL_NAME variable is not set. Defaulting to a blank string.
WARNING: The DELAY variable is not set. Defaulting to a blank string.
WARNING: The TIMEOUT variable is not set. Defaulting to a blank string.
Stopping peer1.org2.example.com ... done
Stopping orderer.example.com ... done
Stopping peer0.org1.example.com ... done
Stopping peer1.org1.example.com ... done
Stopping peer0.org2.example.com ... done
Removing cli ... done
Removing peer1.org2.example.com ... done
Removing orderer.example.com ... done
Removing peer0.org1.example.com ... done
Removing peer1.org1.example.com ... done
Removing peer0.org2.example.com ... done
Removing network net_byfn
Removing volume net_peer0.org2.example.com
Removing volume net_peer1.org2.example.com
Removing volume net_peer1.org1.example.com
Removing volume net_peer0.org1.example.com
Removing volume net_orderer.example.com
四、手动部署
1.手动生成配置文件。运行前面拷贝的bin目录下的cryptogen工具
../bin/cryptogen generate --config=./crypto-config.yaml
org1.example.com
org2.example.com
接下来调用configtxgen工具创建order genesis block:
#设置一个环境变量来告诉configtxgen哪里去寻找configtx.yam
export FABRIC_CFG_PATH=$PWD
#调用configtxgen工具去创建orderer genesis block
../bin/configtxgen -profile TwoOrgsOrdererGenesis -outputBlock ./channel-artifacts/genesis.block
#运行结果
2020-03-24 22:20:31.852 CST [common/configtx/tool] main -> INFO 001 Loading configuration
2020-03-24 22:20:31.880 CST [common/configtx/tool] doOutputBlock -> INFO 002 Generating genesis block
2020-03-24 22:20:31.881 CST [common/configtx/tool] doOutputBlock -> INFO 003 Writing genesis block
可以在channel-artifacts看到创建的genesis.block,我觉的这就是创世区块。
ls channel-artifacts
channelID genesis.block
接下来,创建channel transaction
配置
#设定channle的名称是mychannel
export CHANNEL_NAME=mychannel
#创建channel.tx
../bin/configtxgen -profile TwoOrgsChannel -outputCreateChannelTx ./channel-artifacts/channel.tx -channelID $CHANNEL_NAME
#运行结果
2020-03-24 22:24:33.798 CST [common/configtx/tool] main -> INFO 001 Loading configuration
2020-03-24 22:24:33.802 CST [common/configtx/tool] doOutputChannelCreateTx -> INFO 002 Generating new channel configtx
2020-03-24 22:24:33.802 CST [common/configtx/tool] doOutputChannelCreateTx -> INFO 003 Writing new channel tx
同样可以在channel-artifacts下看到创建的channel.tx。
接下来,将在正在构建的通道上定义Org1
的anchor peer
../bin/configtxgen -profile TwoOrgsChannel -outputAnchorPeersUpdate ./channel-artifacts/Org1MSPanchors.tx -channelID $CHANNEL_NAME -asOrg Org1MSP
同理,定义Org2
的anchor peer
../bin/configtxgen -profile TwoOrgsChannel -outputAnchorPeersUpdate ./channel-artifacts/Org2MSPanchors.tx -channelID $CHANNEL_NAME -asOrg Org2MSP
此时,所有配置文件均以生成,存放在channel-artifacts目录下,如下:
ls channel-artifacts
Org1MSPanchors.tx Org2MSPanchors.tx channel.tx channelID genesis.block
2. 启动网络
编辑docker-compose-cli.yaml,注释command命令,如果没有注释,该脚本将在网络启动时执行所有命令。
vim docker-compose-cli.yaml
结果如下:
注:vim下i输入,输入完成以后按esc退出插入,:wq保存并退出。
运行docker-compose-cli,适当地为TIMEOUT
传递较高的值(以秒为单位);默认情况下CLI容器将在60秒之后退出。
CHANNEL_NAME=$CHANNEL_NAME TIMEOUT=600 docker-compose -f docker-compose-cli.yaml up -d
Creating network "net_byfn" with the default driver
Creating volume "net_peer0.org2.example.com" with default driver
Creating volume "net_peer1.org2.example.com" with default driver
Creating volume "net_peer1.org1.example.com" with default driver
Creating volume "net_peer0.org1.example.com" with default driver
Creating volume "net_orderer.example.com" with default driver
Creating peer0.org2.example.com ... done
Creating orderer.example.com ... done
Creating peer1.org1.example.com ... done
Creating peer0.org1.example.com ... done
Creating peer1.org2.example.com ... done
Creating cli ... done
创建和加入通道
docker exec -it cli bash
#成功运行的结果
root@20e415adceb3:/opt/gopath/src/github.com/hyperledger/fabric/peer#
peer channel join -b mychannel.block
#结果
2020-03-24 14:40:40.527 UTC [msp] GetLocalMSP -> DEBU 001 Returning existing local MSP
2020-03-24 14:40:40.527 UTC [msp] GetDefaultSigningIdentity -> DEBU 002 Obtaining default signing identity
2020-03-24 14:40:40.535 UTC [channelCmd] InitCmdFactory -> INFO 003 Endorser and orderer connections initialized
Error: genesis block file not found open mychannel.block: no such file or directory
Usage:
peer channel join [flags]
Flags:
-b, --blockpath string Path to file containing genesis block
Global Flags:
--cafile string Path to file containing PEM-encoded trusted certificate(s) for the ordering endpoint
--logging-level string Default logging level and overrides, see core.yaml for full syntax
-o, --orderer string Ordering service endpoint
--test.coverprofile string Done (default "coverage.cov")
--tls Use TLS when communicating with the orderer endpoint
-v, --version Display current version of fabric peer server
peer channel list
#结果
2020-03-24 14:43:03.428 UTC [msp] GetLocalMSP -> DEBU 001 Returning existing local MSP
2020-03-24 14:43:03.428 UTC [msp] GetDefaultSigningIdentity -> DEBU 002 Obtaining default signing identity
2020-03-24 14:43:03.437 UTC [channelCmd] InitCmdFactory -> INFO 003 Endorser and orderer connections initialized
2020-03-24 14:43:03.438 UTC [msp/identity] Sign -> DEBU 004 Sign: plaintext: 0A86070A5C08031A0C08F7B8E8F30510...631A0D0A0B4765744368616E6E656C73
2020-03-24 14:43:03.438 UTC [msp/identity] Sign -> DEBU 005 Sign: digest: AB1FCA54283B3564049D3E2BC9F0B0A6F9CD1DEBFBB533F8C5DBEB85407393D1
2020-03-24 14:43:03.448 UTC [channelCmd] list -> INFO 006 Channels peers has joined to:
2020-03-24 14:43:03.448 UTC [main] main -> INFO 007 Exiting.....
3.安装并实例化链码
-n
指定链码安装的名字,-v
指定version,-l
指定使用语言,-p
指定安装链码的所在路径)peer chaincode install -n mycc -v 1.0 -p github.com/hyperledger/fabric/examples/chaincode/go/chaincode_example02
peer chaincode instantiate -o orderer.example.com:7050 --tls $CORE_PEER_TLS_ENABLED --cafile /opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/ordererOrganizations/example.com/orderers/orderer.example.com/msp/tlscacerts/tlsca.example.com-cert.pem -C $CHANNEL_NAME -n mycc -v 1.0 -c '{"Args":["init","a", "100", "b","200"]}' -P "OR ('Org1MSP.member','Org2MSP.member')"
peer chaincode query -C $CHANNEL_NAME -n mycc -c '{"Args":["query","a"]}'
peer chaincode invoke -o orderer.example.com:7050 --tls $CORE_PEER_TLS_ENABLED --cafile /opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/ordererOrganizations/example.com/orderers/orderer.example.com/msp/tlscacerts/tlsca.example.com-cert.pem -C $CHANNEL_NAME -n mycc -c '{"Args":["invoke","a","b","10"]}'
peer chaincode query -C $CHANNEL_NAME -n mycc -c '{"Args":["query","a"]}'
exit
退出docker
容器并关闭网络exit
./byfn.sh -m down
写在最后:楼主也系一菜鸟,对于fabric也是刚刚接触,但在前期安装的过程中踩了很多坑,因此写下这篇博客供后来者学习少踩坑,本文也非作者原创,很多都是综合网上资料以后得出的结果。其中主体是以下两个博客:博客1,博客2。感谢大牛的帮助,本文也只是简单的跑一跑,更多更详细的原理可以阅读博客,不到位的地方欢迎大家指正,也欢迎大家一起讨论学习。