官方文档及网上的文章通常都是介绍如何使用Docker搭建第一个Fabric网络,并且搭建的第一个网络就有四个Peer节点,这样过于复杂,并且下载一大堆Docker镜像,也比较费时间。所以,我这节将首先介绍如何根据fabric源码编译出可执行程序,而后介绍如何直接用这些可执行程序搭建单个Peer节点的网络。node
本节相关操做是在64位 Ubuntu 16.04下进行的,开始本节以前,请确保你已经按照了golang 1.9.2,而且已经配置了GO相关的环境变量,例如,我机器的go环境以下: git
在$GOPATH下创建目录结构src/github.com/hyperledger,切换到此目录后下载fabric 1.1.0-preview版源码:github
mkdir -p $GOPATH/src/github.com/hyperledger cd $GOPATH/src/github.com/hyperledger wget https://github.com/hyperledger/fabric/archive/v1.1.0-preview.tar.gz
而后,解压文件并将解压后获得的目录重命名为fabric:golang
tar -zxvf v1.1.0-preview.tar.gz mv fabric-1.1.0-preview fabric
开始编译以前,到fabric源码目录下执行make test-cmd
命令获取-ldflags选项的取值:
接下来,编译每一个可执行程序时都要带上-ldflags选项。shell
为了方即可执行程序的管理及后续编写相关shell脚本,先在当前用户的home目录下创建以下目录结构数组
fabric-1.1.0-preview-demo(后续全部的例子都放在此目录下) ----bin(编译的可执行程序放在此目录下) ----networks(fabric网络相关配置在此目录下) ----chaincodes(链码相关源码放在此目录下)
相关脚本以下:bash
mkdir -p ~/fabric-1.1.0-preview-demo/bin mkdir -p ~/fabric-1.1.0-preview-demo/networks mkdir -p ~/fabric-1.1.0-preview-demo/chaincodes
cd ~/fabric-1.1.0-preview-demo/bin
切换到刚创建的bin目录下,就能够开始编译了。网络
Orderer用于处理交易的排队及共识。编译命令以下:测试
go build -gcflags "-N -l" -ldflags "-X github.com/hyperledger/fabric/common/metadata.Version=1.1.0-preview -X github.com/hyperledger/fabric/common/metadata.BaseVersion=0.4.2 -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 -X github.com/hyperledger/fabric/common/metadata.Experimental=false" github.com/hyperledger/fabric/orderer
编译时加入-gcflags可让编译器忽略一些优化,方便后面在调试可执行程序时观察变量及对应代码行号。优化
go build -gcflags "-N -l" -ldflags "-X github.com/hyperledger/fabric/common/metadata.Version=1.1.0-preview -X github.com/hyperledger/fabric/common/metadata.BaseVersion=0.4.2 -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 -X github.com/hyperledger/fabric/common/metadata.Experimental=false" github.com/hyperledger/fabric/peer
cryptogen用于生成交易签名及SSL通讯用到证书及私钥对,能够使用fabric-ca或者其余ca颁发的证书,但测试环境使用crytogen更简单。编译命令以下:
go build -gcflags "-N -l" -ldflags "-X github.com/hyperledger/fabric/common/metadata.Version=1.1.0-preview -X github.com/hyperledger/fabric/common/metadata.BaseVersion=0.4.2 -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 -X github.com/hyperledger/fabric/common/metadata.Experimental=false" github.com/hyperledger/fabric/common/tools/cryptogen
configtxgen用于生成Orderer的创世纪块及通道配置交易等内容。编译命令以下:
go build -gcflags "-N -l" -ldflags "-X github.com/hyperledger/fabric/common/metadata.Version=1.1.0-preview -X github.com/hyperledger/fabric/common/metadata.BaseVersion=0.4.2 -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 -X github.com/hyperledger/fabric/common/metadata.Experimental=false" github.com/hyperledger/fabric/common/tools/configtxgen
上述编译都结束后,bin目录下就有了四个可执行程序:
能够使用chmod
命令给这些程序加上可执行权限,而后能够使用version
子命令查看相应程序的版本:
本节将演示如何搭建一个Peer节点和一个Orderer节点的网络。开始以前,先在~/fabric-1.1.0-preview-demo/networks下创建以下结构的目录:
single-dev-env --config(存放配置文件) ----channel-artifacts(存放后面要生成的通道配置交易等文件)
shell命令:
mkdir -p ~/fabric-1.1.0-preview-demo/networks/single-dev-env/config/channel-artifacts
Fabric中搭建一个网络须要以下步骤:
1. 使用cryptogen生成网络须要的证书。
2. 使用configtxgen生成Orderer的创世纪块
3. 使用configtxgen建立通道配置交易
4. 使用peer cli建立及加入通道
注意:若是没有特殊说明,接下来的命令均是在~/fabric-1.1.0-preview-demo目录下执行的。
使用cryptogen生成网络须要的证书,需指定配置文件,参考官方fabric-samples的first-network的crypto-config.yaml文件,编写只有一个orderer和一个peer的配置文件crypto-config.yaml(放在single-dev-env/config目录下):
OrdererOrgs: - Name: Orderer Domain: example.com Specs: - Hostname: orderer PeerOrgs: - Name: Org Domain: example.com Template: Count: 1 Hostname: peer Users: Count: 1
export PATH=$(pwd)/bin:$PATH cryptogen generate --config=networks/single-dev-env/config/crypto-config.yaml --output=networks/single-dev-env/config/crypto-config
fabric编译成的二进制文件均可以使用<命令> <命令> –help查看帮助。
命令执行成功后,networks/single-dev-env/config/crypto-config目录下生成了以下结构的证书目录:
orderer.example.com目录存放的是Orderer节点须要的证书,等会启动Orderer节点时须要指定msp目录:
peer.example.com目录存放的是Peer节点须要的证书,等会启动Peer节点时须要指定msp目录:
Admin@example.com
目录下的证书是Peer节点管理员证书,建立、加入通道、发送交易等操做都是用此目录下的证书进行签名,所以,咱们使用peer cli时须要指定msp目录:
参考官方fabric-samples的first-network的configtx.yaml文件编写一个configtx.yaml文件(放在single-dev-env/config目录下):
Profiles: SingleSoloOrdererGenesis: Orderer: <<: *OrdererDefaults Organizations: - *OrdererOrg Consortiums: SampleConsortium: Organizations: - *Org SingleSoloChannel: Consortium: SampleConsortium Application: <<: *ApplicationDefaults Organizations: - *Org Organizations: - &OrdererOrg Name: OrdererOrg ID: OrdererMSP MSPDir: crypto-config/ordererOrganizations/example.com/msp - &Org Name: OrgMSP ID: OrgMSP MSPDir: crypto-config/peerOrganizations/example.com/msp AnchorPeers: - Host: peer.example.com Port: 7051 Orderer: &OrdererDefaults OrdererType: solo Addresses: - orderer.example.com:7050 BatchTimeout: 2s BatchSize: MaxMessageCount: 10 AbsoluteMaxBytes: 99 MB PreferredMaxBytes: 512 KB Organizations: Application: &ApplicationDefaults Organizations:
sudo gedit /etc/hosts
修改/etc/hosts,追加上以下内容并保存:
127.0.0.1 example.com 127.0.0.1 orderer.example.com 127.0.0.1 peer.example.com
Fabric使用X.509证书做为节点及用户的身份,而证书通常优于域名管理,所以,这里作了域名映射。
设置FABRIC_CFG_PATH
环境变量告诉configtxgen去哪一个目录寻找configtx.yaml文件,使用“生成证书”一节用到终端执行以下命令:
export FABRIC_CFG_PATH=$(pwd)/networks/single-dev-env/config/
使用上一小节用到终端执行以下命令:
configtxgen -outputBlock networks/single-dev-env/config/genesis.block -profile SingleSoloOrdererGenesis
本步骤及下一步中的-profile选项的取值均是与configtx.yaml文件内容对应。
命令执行成功后,networks/single-dev-env/config目录下就多了一个genesis.block文件:
使用上一小节用到终端执行以下命令::
export CHANNEL_NAME=mychannel configtxgen -outputCreateChannelTx networks/single-dev-env/config/channel-artifacts/channel.tx -profile SingleSoloChannel -channelID $CHANNEL_NAME
命令执行成功后,networks/single-dev-env/config/channel-artifacts目录下多了一个channel.tx文件。
本小节是使用环境变量配置Orderer和Peer节点,其实也能够使用yaml文件配置,后面再介绍。
新打开一个终端,切换到~/fabric-1.1.0-preview-demo目录并设环境变量配置Orderer节点:
export rootDir=$(pwd) export PATH=$rootDir/bin:$PATH export ORDERER_GENERAL_LOGLEVEL=DEBUG export ORDERER_GENERAL_TLS_ENABLED=false export ORDERER_GENERAL_PROFILE_ENABLED=false export ORDERER_GENERAL_LISTENADDRESS=0.0.0.0 export ORDERER_GENERAL_LISTENPORT=7050 export ORDERER_GENERAL_GENESISMETHOD=file export ORDERER_GENERAL_GENESISFILE=$rootDir/networks/single-dev-env/config/genesis.block export ORDERER_GENERAL_LOCALMSPDIR=$rootDir/networks/single-dev-env/config/crypto-config/ordererOrganizations/example.com/orderers/orderer.example.com/msp export ORDERER_GENERAL_LOCALMSPID=OrdererMSP export ORDERER_FILELEDGER_LOCATION=$rootDir/networks/single-dev-env/data/orderer
启动Orderer节点:
orderer
为了方便,能够把环境变量的设置及orderer启动的命令写在shell脚本中。
Orderer启动成功后,控制台输出以下:
再打开一个终端,切换到~/fabric-1.1.0-preview-demo目录并设环境变量配置Peer节点:
export rootDir=$(pwd) export PATH=$rootDir/bin:$PATH export CORE_PEER_ID=example_org export CORE_CHAINCODE_MODE=dev export CORE_PEER_CHAINCODELISTENADDRESS=0.0.0.0:7052 export CORE_PEER_NETWORKID=dev export CORE_LOGGING_LEVEL=INFO export CORE_PEER_TLS_ENABLED=false export CORE_PEER_PROFILE_ENABLED=false export CORE_PEER_ADDRESS=0.0.0.0:7051 export CORE_PEER_LISTENADDRESS=0.0.0.0:7051 export CORE_PEER_GOSSIP_ENDPOINT=0.0.0.0:7051 export CORE_PEER_EVENTS_ADDRESS=0.0.0.0:7053 export CORE_PEER_LOCALMSPID=OrgMSP export CORE_LEDGER_STATE_STATEDATABASE=goleveldb export CORE_PEER_MSPCONFIGPATH=$rootDir/networks/single-dev-env/config/crypto-config/peerOrganizations/example.com/peers/peer.example.com/msp export CORE_PEER_FILESYSTEMPATH=$rootDir/networks/single-dev-env/data/peer
启动:
peer node start -o 127.0.0.1:7050 --peer-chaincodedev=true
Peer启动成功后,控制台输出以下:
新打开一个终端,切换到~/fabric-1.1.0-preview-demo目录并设环境变量:
export rootDir=$(pwd) export PATH=$rootDir/bin:$PATH export CHANNEL_NAME=mychannel export CORE_CHAINCODE_MODE=dev export CORE_PEER_ID=peer-cli export CORE_PEER_ADDRESS=peer.example.com:7051 export CORE_PEER_LOCALMSPID=OrgMSP export CORE_PEER_MSPCONFIGPATH=$rootDir/networks/single-dev-env/config/crypto-config/peerOrganizations/example.com/users/Admin@example.com/msp
这些环境变量之后操做时常常用到,能够保存在一个文本文件中,新开终端就使用
source <文件名>
使其生效。
peer channel create -o orderer.example.com:7050 -c $CHANNEL_NAME -f $rootDir/networks/single-dev-env/config/channel-artifacts/channel.tx
执行成功后,当前目录生成了一个mychannel.block文件:
在上一小节使用到终端执行以下命令:
peer channel join -b $CHANNEL_NAME.block
执行成功后,终端输入日志:
启动Peer节点的终端打印日志:
从日志中能够看到,节点加入通道后会建立一个通道对应的帐本并在通道上部署系统链码。
$GOPATH/src/github.com/hyperledger/fabric/examples/chaincode目录下有官方提供的各类语言的链码示例,本节将演示如何部署及调用一个简单的go语言示例——fabric/examples/chaincode/go/chaincode_example02。
链码部署及调用过程以下:
1. 启动链码对应的程序;
2. 部署链码,分install和instantiate两个阶段。其中,install将链码源码打包成链码部署文件(CDS)并上传到Peer节点,instantiate将根据CDS生成链码对应的Docker容器,启动容器并执行链码的实例化操做,通常是调用链码的init方法。这里描述的instantiate是使用“network”模式运行链码,而咱们这次测试使用的是“dev”模式,由启动Peer节点时设置的CORE_CHAINCODE_MODE环境变量的值决定的。
3. 调用链码,分invoke和query两种操做。invoke是写操做,可修改帐本,能产生块,而query是读操做,不写帐本,也不生成块。
打开一个终端,执行以下命令:
export CORE_CHAINCODE_ID_NAME=mycc:1.0 export CORE_PEER_ADDRESS=peer.example.com:7052 go run $GOPATH/src/github.com/hyperledger/fabric/examples/chaincode/go/chaincode_example02/chaincode_example02.go
启动成功后,控制台输出以下:
这里使用go run
命令直接运行的,固然,也能够先使用go build -gcflags "-N -l" github.com/hyperledger/fabric/examples/chaincode/go/chaincode_example02
将链码编译成可执行程序再运行。
新打开一个终端,切换到~/fabric-1.1.0-preview-demo目录,首先参照“建立通道”一节设置环境变量。
第1步:install链码:
peer chaincode install -n mycc -v 1.0 -p github.com/hyperledger/fabric/examples/chaincode/go/chaincode_example02
选项说明:
终端输出:
peer节点帐本目录的chaincodes目录下生成了一个文件,其名称是由链码名称和版本号组成的。
第2步:instantiate链码
peer chaincode instantiate -o orderer.example.com:7050 -C $CHANNEL_NAME -n mycc -v 1.0 -c "{\"Args\":[\"init\",\"a\", \"100\", \"b\",\"200\"]}" -P "OR('OrgMSP.member')"
选项说明:
当前终端输出内容以下:
初始化了两个状态A和B,其初始值分别为100和200(启动链码的终端输出的内容):
此外,peer和orderer的终端也有相应的日志输出。
本节的操做都是使用上一小节部署链码用的终端。
首先,使用invoke操做把A的余额转10到B:
peer chaincode invoke -o orderer.example.com:7050 -C $CHANNEL_NAME -n mycc -c "{\"Args\":[\"invoke\",\"a\",\"b\",\"10\"]}"
接下来,再使用query操做查询A的余额,发现确实少了10:
peer chaincode query -C $CHANNEL_NAME -n mycc -c "{\"Args\":[\"query\",\"a\"]}"