本文主要内容是使用docker镜像编译Fabric源码,并使用编译生成的程序构建一个只有1个Orderer、1个Peer的简单网络,以此作为后续学习的基础。
本文代码使用fabric v1.0.4、docker镜像是yeasy/hyperledger-fabric:1.0.4,我们可以从 Docker Hub上看到该镜像的信息,基于golang镜像构建,给我们安装好了编译Fabric的环境依赖、gotools等,可以给我们省不少事情。
第一步是下载我们将要进行编译的Fabric源码。在这里说来真是觉得Fabric文档写的很详细。基本上根据文档来都能有所收获。废话少说我们通过以下命令下载源码,并将代码版本切到1.0.4
~$:git clone https://github.com/hyperledger/fabric.git
~$:cd fabric
~/fabric$:git tag
~/fabric$:git checkout v1.0.4
这一步没什么说的,需要强调的一点是一定要使用国内的镜像站(如阿里镜像),不然的话镜像下载超慢,你可能在这一步就直接放弃了。
docker pull yeasy/hyperledger-fabric:1.0.4
事实上在yeasy/hyperledger-fabric镜像当中已经给我们装好了Fabric了(在/go路径下),但我们不直接使用它提供的,而是使用我们在上边下载好的源文件编译重新生成并安装。具体步骤如下:
首先我们需要一个docker-compose配置文件,具体文件内容如下:
version: '2'
services: compile: container_name: compile image: yeasy/hyperledger-fabric:1.0.4 command: /bin/bash -c 'sleep 6000000' working_dir: /go/src/github.com/hyperledger/fabric volumes: - ~/bin:/go/bin - ~/fabric:/go/src/github.com/hyperledger/fabric
我们将该文件命名为docker-compose-compile.yaml
并将其放在~/
目录下。
启动docker镜像
~$:docker-compose -f ~/docker-compose-compile.yaml up -d
进入docker镜像并编译(以编译orderer模块为例)
~$:docker exec -it compile bash
#进入docker镜像交互界面后
root@dbb634aa44a5:/go/src/github.com/hyperledger/fabric# cd orderer
root@dbb634aa44a5:/go/src/github.com/hyperledger/fabric# go build
root@dbb634aa44a5:/go/src/github.com/hyperledger/fabric# go install
以上步骤成功的话你应该可以在镜像的/go/bin
目录下看到新生成的orderer可执行程序,并且在本机~/bin
目录下也可以看到编译生成的orderer
文件,此外我们还需要生成peer
模块,进入该peer目录go build
,go install
即可
以上方法主要是利用了docker数据卷的功能,我们在本地修改代码后,镜像当中可以立即看到被修改内容,只需要在镜像中重新编译就可以使修改后的代码生效。
接下来我们搭建一个仅有一个Orderer和一个Peer的网络。
首先们们需要编译生成两个工具:cryptogen
生成加密证书,configtxgen
生成交易配置(详情请查看官方文档)。
这两个工具在镜像中的目录分别为/go/src/github.com/hyperledger/fabric/common/tools/cryptogen
,/go/src/github.com/hyperledger/fabric/common/configtx/tool/configtxgen
,分别进入其中执行go build
,go install
即可在镜像的/go/bin
目录(对应本机的~/bin
目录)下生成相应的可执行文件。
接下来我们需要准备两个配置文件。
先新建一个目录用于保存我们所有的配置文件
~$:mkdir mynet
~$:cd mynet
在mynet
目录下新建crypto-config.yaml
这是一个生成机构加密证书的配置文件,具体内容如下
OrdererOrgs:
- Name: Orderer Domain: orderer.com
Specs:
- Hostname: orderer0 PeerOrgs:
- Name: Org1 Domain: peer.com
Template:
Count: 1
Users:
Count: 1
我们可以看到其内容根据字面意思理解就是一个Orderer机构,一个Peer机构,Peer机构里有一个节点(Template.Count:1) 一个用户(Users.Count:1)
我们可以使用~/bin/cryptogen
工具来生成证书如下:
~/mynet$:~/bin/cryptogen generate --config=./crypto-config.yaml
peer.com
在当前目录下可以看到生成了一个crypto-config
文件夹,里面包含两个文件夹分别是ordererOrganizations, peerOrganizations
接下来我们需要使用configtxgen
生成交易的配置。需要一个配置文件configtx.yaml
内容如下
Profiles:
OneOrgsOrdererGenesis:
Orderer:
<<: *OrdererDefaults
Organizations:
- *OrdererOrg Consortiums:
SampleConsortium:
Organizations:
- *Org1 OneOrgsChannel:
Consortium: SampleConsortium
Application:
<<: *ApplicationDefaults
Organizations:
- *Org1
Organizations:
- &OrdererOrg Name: OrdererOrg
ID: OrdererMSP
MSPDir: crypto-config/ordererOrganizations/orderer.com/msp
- &Org1 Name: Org1MSP
ID: Org1MSP
MSPDir: crypto-config/peerOrganizations/peer.com/msp
AnchorPeers:
- Host: peer0.peer.com Port: 7051
Orderer: &OrdererDefaults
OrdererType: solo
Addresses:
- orderer0.orderer.com:7050 BatchTimeout: 2s
BatchSize:
MaxMessageCount: 10
AbsoluteMaxBytes: 99 MB
PreferredMaxBytes: 512 KB
Kafka:
Brokers:
- 127.0.0.1:9092 Organizations:
Application: &ApplicationDefaults
Organizations:
建议查看一下官方文档。
执行如下命令
~/mynet$:export FABRIC_CFG_PATH=$PWD
~/mynet$:mkdir channel-artifacts
~/mynet$:~/bin/configtxgen -profile OneOrgsOrdererGenesis -outputBlock ./channel-artifacts/genesis.block #产生创世块
~/mynet$:export CHANNEL_NAME=mychannel
~/mynet$:~/bin/configtxgen -profile OneOrgsChannel -outputCreateChannelTx ./channel-artifacts/channel.tx -channelID $CHANNEL_NAME #产生channel配置
~/mynet$:~/bin/configtxgen -profile OneOrgsChannel -outputAnchorPeersUpdate ./channel-artifacts/Org1MSPanchors.tx -channelID $CHANNEL_NAME -asOrg Org1MSP #机构1 AnchorPeer配置
成功执行以上命令后会在~/mynet/channel-artifacts
目录下生成以下三个文件
channel.tx
genesis.block
Org1MSPanchors.tx
为了更深入的学习我们分别启动Orderer节点和Peer节点,首先是Orderer ,我们需要准备一个docker-compose的配置文件
内容如下
version: '2'
networks: my_net: services: orderer0.orderer.com: container_name: orderer0.orderer.com image: yeasy/hyperledger-fabric:1.0.4 environment: - ORDERER_GENERAL_LOGLEVEL=debug - ORDERER_GENERAL_LISTENADDRESS=0.0.0.0 - ORDERER_GENERAL_GENESISMETHOD=file - ORDERER_GENERAL_GENESISFILE=/root/Workspace/mynet/channel-artifacts/genesis.block - ORDERER_GENERAL_LOCALMSPID=OrdererMSP - ORDERER_GENERAL_LOCALMSPDIR=/root/Workspace/mynet/crypto-config/ordererOrganizations/orderer.com/orderers/orderer0.orderer.com/msp - GRPC_TRACE=all=true - GRPC_VERBOSITY=debug # enabled TLS - ORDERER_GENERAL_TLS_ENABLED=true - ORDERER_GENERAL_TLS_PRIVATEKEY=/root/Workspace/mynet/crypto-config/ordererOrganizations/orderer.com/orderers/orderer0.orderer.com/tls/server.key - ORDERER_GENERAL_TLS_CERTIFICATE=/root/Workspace/mynet/crypto-config/ordererOrganizations/orderer.com/orderers/orderer0.orderer.com/tls/server.crt - ORDERER_GENERAL_TLS_ROOTCAS=[/root/Workspace/mynet/crypto-config/ordererOrganizations/orderer.com/orderers/orderer0.orderer.com/tls/ca.crt] command: /bin/bash -c 'sleep 6000000' working_dir: /root/Workspace/mynet volumes: - ./:/root/Workspace/mynet - ~/bin:/go/bin - ~/fabric:/go/src/github.com/hyperledger/fabric ports: - 7050:7050 networks: - my_net
文件我们保存为docker-compose-orderer.yaml
使用docker-compose启动
~/mynet$:docker-compose -f docker-compose-orderer.yaml up -d
~/mynet$:docker exec -it orderer0.orderer.com bash
root@4c05353b5007:/root/Workspace/mynet#orderer
一切正常的情况下我们可以看到类似于如下输出
... ...
2018-03-18 01:27:30.335 UTC [policies] GetPolicy -> DEBU 0be Returning policy Readers for evaluation
2018-03-18 01:27:30.335 UTC [policies] CommitProposals -> DEBU 0bf As expected, current configuration has policy '/Channel/Readers'
2018-03-18 01:27:30.335 UTC [policies] GetPolicy -> DEBU 0c0 Returning policy Writers for evaluation
2018-03-18 01:27:30.335 UTC [policies] CommitProposals -> DEBU 0c1 As expected, current configuration has policy '/Channel/Writers'
2018-03-18 01:27:30.335 UTC [policies] GetPolicy -> DEBU 0c2 Returning policy Orderer/BlockValidation for evaluation
2018-03-18 01:27:30.335 UTC [policies] CommitProposals -> DEBU 0c3 As expected, current configuration has policy '/Channel/Orderer/BlockValidation'
2018-03-18 01:27:30.335 UTC [fsblkstorage] retrieveBlockByNumber -> DEBU 0c4 retrieveBlockByNumber() - blockNum = [0]
2018-03-18 01:27:30.336 UTC [fsblkstorage] newBlockfileStream -> DEBU 0c5 newBlockfileStream(): filePath=[/var/hyperledger/production/orderer/chains/testchainid/blockfile_000000], startOffset=[0]
2018-03-18 01:27:30.337 UTC [fsblkstorage] nextBlockBytesAndPlacementInfo -> DEBU 0c6 Remaining bytes=[6357], Going to peek [8] bytes
2018-03-18 01:27:30.337 UTC [fsblkstorage] nextBlockBytesAndPlacementInfo -> DEBU 0c7 Returning blockbytes - length=[6355], placementInfo={fileNum=[0], startOffset=[0], bytesOffset=[2]}
2018-03-18 01:27:30.337 UTC [orderer/multichain] newChainSupport -> DEBU 0c8 [channel: testchainid] Retrieved metadata for tip of chain (blockNumber=0, lastConfig=0, lastConfigSeq=0):
2018-03-18 01:27:30.337 UTC [orderer/multichain] NewManagerImpl -> INFO 0c9 Starting with system channel testchainid and orderer type solo
2018-03-18 01:27:30.337 UTC [orderer/main] main -> INFO 0ca Beginning to serve requests
至此我们自己编译生成的orderer
节点就算启动成功了。
准备docker-compose-peer.yaml
文件,内容如下
version: '2'
networks: my_net: services: peer0.peer.com: container_name: peer0.peer.com image: yeasy/hyperledger-fabric:1.0.4 environment: - CORE_VM_ENDPOINT=unix:///host/var/run/docker.sock # the following setting starts chaincode containers on the same # bridge network as the peers # https://docs.docker.com/compose/networking/ #- CORE_VM_DOCKER_HOSTCONFIG_NETWORKMODE=${COMPOSE_PROJECT_NAME}_byfn #- CORE_LOGGING_LEVEL=ERROR - CORE_LOGGING_LEVEL=DEBUG - CORE_PEER_GOSSIP_USELEADERELECTION=true - CORE_PEER_GOSSIP_ORGLEADER=false - CORE_PEER_PROFILE_ENABLED=true - CORE_PEER_TLS_ENABLED=true - CORE_PEER_TLS_CERT_FILE=/root/Workspace/mynet/crypto-config/peerOrganizations/peer.com/peers/peer0.peer.com/tls/server.crt - CORE_PEER_TLS_KEY_FILE=/root/Workspace/mynet/crypto-config/peerOrganizations/peer.com/peers/peer0.peer.com/tls/server.key - CORE_PEER_TLS_ROOTCERT_FILE=/root/Workspace/mynet/crypto-config/peerOrganizations/peer.com/peers/peer0.peer.com/tls/ca.crt - CORE_PEER_ID=peer0.peer.com - CORE_PEER_ADDRESS=peer0.peer.com:7051 - CORE_PEER_GOSSIP_EXTERNALENDPOINT=peer0.peer.com:7051 - CORE_PEER_LOCALMSPID=Org1MSP - CORE_PEER_MSPCONFIGPATH=/root/Workspace/mynet/crypto-config/peerOrganizations/peer.com/users/Admin@peer.com/msp command: /bin/bash -c 'sleep 6000000' working_dir: /root/Workspace/mynet volumes: - ./:/root/Workspace/mynet - ~/bin:/go/bin - ~/fabric:/go/src/github.com/hyperledger/fabric ports: - 7051:7051 - 7053:7053 networks: - my_net
启动Peer节点
~/mynet:docker-compose -f docker-compose-peer.yaml up -d
~/mynet:docker exec -it peer0.peer.com bash
root@6f8bea5ddecd:/root/Workspace/mynet# peer node start
成功后应该会出现如下输
... ...
2018-03-18 01:49:04.704 UTC [nodeCmd] serve -> INFO 192 Starting peer with ID=[name:"peer0.org1.example.com" ], network ID=[dev], address=[peer0.org1.example.com:7051]
2018-03-18 01:49:04.704 UTC [nodeCmd] serve -> INFO 193 Started peer with ID=[name:"peer0.org1.example.com" ], network ID=[dev], address=[peer0.org1.example.com:7051]
2018-03-18 01:49:04.704 UTC [flogging] setModuleLevel -> DEBU 194 Module 'msp/identity' logger enabled for log level 'WARNING'
2018-03-18 01:49:04.705 UTC [flogging] setModuleLevel -> DEBU 195 Module 'msp' logger enabled for log level 'WARNING'
2018-03-18 01:49:04.705 UTC [flogging] setModuleLevel -> DEBU 196 Module 'configvalues/msp' logger enabled for log level 'WARNING'
2018-03-18 01:49:04.705 UTC [flogging] setModuleLevel -> DEBU 197 Module 'peer/gossip/sa' logger enabled for log level 'WARNING'
2018-03-18 01:49:04.705 UTC [flogging] setModuleLevel -> DEBU 198 Module 'gossip/election' logger enabled for log level 'WARNING'
2018-03-18 01:49:04.705 UTC [flogging] setModuleLevel -> DEBU 199 Module 'gossip/gossip' logger enabled for log level 'WARNING'
2018-03-18 01:49:04.705 UTC [flogging] setModuleLevel -> DEBU 19a Module 'gossip/service' logger enabled for log level 'WARNING'
2018-03-18 01:49:04.705 UTC [flogging] setModuleLevel -> DEBU 19b Module 'gossip/pull' logger enabled for log level 'WARNING'
2018-03-18 01:49:04.705 UTC [flogging] setModuleLevel -> DEBU 19c Module 'gossip/state' logger enabled for log level 'WARNING'
2018-03-18 01:49:04.705 UTC [flogging] setModuleLevel -> DEBU 19d Module 'peer/gossip/mcs' logger enabled for log level 'WARNING'
2018-03-18 01:49:04.705 UTC [flogging] setModuleLevel -> DEBU 19e Module 'gossip/comm' logger enabled for log level 'WARNING'
2018-03-18 01:49:04.705 UTC [flogging] setModuleLevel -> DEBU 19f Module 'gossip/discovery' logger enabled for log level 'WARNING'
2018-03-18 01:49:04.705 UTC [flogging] setModuleLevel -> DEBU 1a0 Module 'ledgermgmt' logger enabled for log level 'INFO'
2018-03-18 01:49:04.705 UTC [flogging] setModuleLevel -> DEBU 1a1 Module 'kvledger' logger enabled for log level 'INFO'
2018-03-18 01:49:04.705 UTC [flogging] setModuleLevel -> DEBU 1a2 Module 'kvledger.util' logger enabled for log level 'INFO'
2018-03-18 01:49:04.705 UTC [flogging] setModuleLevel -> DEBU 1a3 Module 'cauthdsl' logger enabled for log level 'WARNING'
2018-03-18 01:49:04.705 UTC [flogging] setModuleLevel -> DEBU 1a4 Module 'policies' logger enabled for log level 'WARNING'
2018-03-18 01:49:04.705 UTC [flogging] setModuleLevel -> DEBU 1a5 Module 'grpc' logger enabled for log level 'ERROR'
2018-03-18 01:49:04.706 UTC [nodeCmd] func5 -> INFO 1a6 Starting profiling server with listenAddress = 0.0.0.0:6060
这一步可是废了我好大的力气,如果在创建Channel的时候不成功就好好检查上边的配置吧,我修改了好几遍才最终成功。
root@6f8bea5ddecd:/root/Workspace/mynet# export CHANNEL_NAME=mychannel
root@6f8bea5ddecd:/root/Workspace/mynet# peer channel create -o orderer0.orderer.com:7050 -c $CHANNEL_NAME -f ./channel-artifacts/channel.tx --tls --cafile /root/Workspace/mynet/crypto-config/ordererOrganizations/orderer.com/orderers/orderer0.orderer.com/msp/tlscacerts/tlsca.orderer.com-cert.pem
root@6f8bea5ddecd:/root/Workspace/mynet# peer channel join -b mychannel.block
peer channel update -o orderer0.orderer.com:7050 -c $CHANNEL_NAME -f ./channel-artifacts/Org1MSPanchors.tx --tls --cafile /root/Workspace/mynet/crypto-config/ordererOrganizations/orderer.com/orderers/orderer0.orderer.com/msp/tlscacerts/tlsca.orderer.com-cert.pem
输出为
2018-04-03 16:01:10.535 UTC [msp] GetLocalMSP -> DEBU 00a Returning existing local MSP
2018-04-03 16:01:10.535 UTC [msp] GetDefaultSigningIdentity -> DEBU 00b Obtaining default signing identity
2018-04-03 16:01:10.535 UTC [msp] GetLocalMSP -> DEBU 00c Returning existing local MSP
2018-04-03 16:01:10.535 UTC [msp] GetDefaultSigningIdentity -> DEBU 00d Obtaining default signing identity
2018-04-03 16:01:10.535 UTC [msp/identity] Sign -> DEBU 00e Sign: plaintext: 0AA2060A1508021A0608C6CA8ED60522...7DE2990B6D1B864A669BA59D3D159989
2018-04-03 16:01:10.535 UTC [msp/identity] Sign -> DEBU 00f Sign: digest: 126C57735E1A67D918AB54A61FD1009A5390A3351012B444764FB308A1DB38B6
2018-04-03 16:01:10.558 UTC [main] main -> INFO 010 Exiting.....
在fabric/example/chaincode下有很多样例合约,我们为了演示,选取其中较简单的map进行部署测试
peer chaincode install -p github.com/hyperledger/fabric/examples/chaincode/go/map -n mycc -v 0
得到如下输出
2018-03-18 13:03:15.015 UTC [msp] GetLocalMSP -> DEBU 001 Returning existing local MSP
2018-03-18 13:03:15.015 UTC [msp] GetDefaultSigningIdentity -> DEBU 002 Obtaining default signing identity
2018-03-18 13:03:15.015 UTC [chaincodeCmd] checkChaincodeCmdParams -> INFO 003 Using default escc
2018-03-18 13:03:15.015 UTC [chaincodeCmd] checkChaincodeCmdParams -> INFO 004 Using default vscc
2018-03-18 13:03:15.073 UTC [golang-platform] getCodeFromFS -> DEBU 005 getCodeFromFS github.com/hyperledger/fabric/examples/chaincode/go/map
2018-03-18 13:03:15.352 UTC [golang-platform] func1 -> DEBU 006 Discarding GOROOT package encoding/json
2018-03-18 13:03:15.352 UTC [golang-platform] func1 -> DEBU 007 Discarding GOROOT package fmt
2018-03-18 13:03:15.352 UTC [golang-platform] func1 -> DEBU 008 Discarding provided package github.com/hyperledger/fabric/core/chaincode/shim
2018-03-18 13:03:15.353 UTC [golang-platform] func1 -> DEBU 009 Discarding provided package github.com/hyperledger/fabric/protos/peer
2018-03-18 13:03:15.353 UTC [golang-platform] func1 -> DEBU 00a Discarding GOROOT package strconv
2018-03-18 13:03:15.353 UTC [golang-platform] func1 -> DEBU 00b Discarding GOROOT package time
2018-03-18 13:03:15.353 UTC [golang-platform] GetDeploymentPayload -> DEBU 00c done
2018-03-18 13:03:15.398 UTC [msp/identity] Sign -> DEBU 00d Sign: plaintext: 0AE9060A5C08031A0C0893C7B9D50510...1F70FC270000FFFFD9315A97001E0000
2018-03-18 13:03:15.398 UTC [msp/identity] Sign -> DEBU 00e Sign: digest: 65B8E2ECB1B647DA9B1E93048E874ECCCA2E6BBCC3A52B0EB77EB6B7D76049D2
2018-03-18 13:03:15.403 UTC [chaincodeCmd] install -> DEBU 00f Installed remotely response:<status:200 payload:"OK" >
2018-03-18 13:03:15.403 UTC [main] main -> INFO 010 Exiting.....
实例化Chaincode
peer chaincode instantiate -o orderer0.orderer.com:7050 --tls true --cafile /root/Workspace/mynet/crypto-config/ordererOrganizations/orderer.com/orderers/orderer0.orderer.com/msp/tlscacerts/tlsca.orderer.com-cert.pem -C $CHANNEL_NAME -n mycc -v 0 -c '{"Args":["a","10"]}'
Error: Error endorsing chaincode: rpc error: code = Unknown desc = Error starting container: Failed to generate platform-specific docker build: Failed to pull /fabric-ccenv:x86_64-development build: API error (400): {"message":"invalid reference format"}
security_opt: - seccomp=unconfined
这样就可以正常使用gdb调试了。