接下来的这篇文章,主要是讲通过源码编译的方式来搭建 Fabric 网络。关于 go 语言等环境的设置,是基于《HyperLedger 实战-快速搭建一个 Fabric1.0 环境 》来设置的。
主要分为三个步骤,编译组件,根据组件来搭建一个单个节点。最后,调用官方的链码,将链码部署安装在我们搭建的网络之中,并调用链码进行简单的查询和转账等等。
全文将按照如下结构展开:
全文结构
一、编译组件
第一部分主要工作是编译后面需要的组件,主要使用 make 命令来生成相关组件。这里先简单介绍 make 与 MakeFile 文件,然后在详细介绍如何来一步步编译相关组件。
1、make 工具
对于 Linux 跟 Unix 系统而言,make 是一个极其重要的编译命令。
make 工具最基本的功能是调用 Makefile 文件,通过 Makefile 文件来描述程编译的整个过程,不必每次敲 gcc 或 g++等命令来完成编译工作。当然,Makefile 文件需要按照一定的语法进行编写,说明如何编译各个源文件并链接生成可执行文件,以及各个文件之间的依赖关系。
在本文中,对于工具cryptogen 和 configtxgen的生成,Fabric 源码提供了专门编译 cryptogen 的入口。而 peer 和 Orderer 的生成,则是通过编译 Fabric 源码来生成的。
【疑问】
在编译组件的过程中,生成cryptogen 和 configtxgen的方式与生成 peer 和 Orderer 的生成的方式明显是不同的。
前者,我猜测是使用 MakeFile 文件来编译生成的.(知道的学友,烦请在文章评论告知)
后者,毫无疑问,是采用编译源码的方式生成的 peer 和 Orderer。
2、编译生成 cryptogen
我们既然获得了 Fabric 的源代码,那么就可以轻易的使用 make 命令编译需要的程序。Fabric 官方提供了专门编译 cryptogen 的入口,我们只需要运行以下命令即可:
cd ~/go/src/github.com/hyperledger/fabric
make cryptogen
3、编译生成 configtxgen
configtxgen 的作用是生成配置区块和配置交易。与前面 1.1 说到的类似,我们可以通过 make 命令生成 configtxgen 程序:
cd ~/go/src/github.com/hyperledger/fabric
make configtxgen
以上生成的工具在根目录 fabric 的 build/bin 中。
4、编译生成 Orderer
fabric 中源码的组成部分如下图所示:
fabric 源码结构
这里使用 make 工具,这上图所示的 Orderer 源码和 peer 源码进行编译。
cd ~/go/src/github.com/hyperledger/fabric
make orderer
完成后,Orderer 组件在 build/bin 文件夹中。
5、编译生成 peer
使用下面的命令进行编译
cd ~/go/src/github.com/hyperledger/fabric
make peer
完成后,Orderer 组件在 build/bin 文件夹中。最终该文件下中有以下几个工具:
6、可能遇到的 Bug
一路走过来并非一帆风顺的!这里将编译组件过程中遇到的 Bug 及其解决办法贴出来。
cp: cannot stat ‘build/docker/gotools/bin/protoc-gen-go’: No such file or directory
解决办法:
go get github.com/golang/protobuf/protoc-gen-go
cd $GOPATH/src/github.com/golang/protobuf/
make all
cd $GOPATH/src/github.com/hyperledger/fabric
cp $GOPATH/bin/protoc-gen-go build/docker/gotools/bin/
在运行“go get github.com/golang/protobuf/protoc-gen-go” 命令时,可能会出现卡住的状况,这可能是网络不流畅的原因。我之前使用宽带,后来将网络换成自己手机的热点,就很快下载下来了。
二、搭建单个 Peer 节点网络
Fabric 中搭建一个网络需要如下步骤:
- 环境准备
- 使用 cryptogen 生成网络需要的证书。
- 使用 configtxgen 生成 Orderer 的创世纪块
- 使用 configtxgen 创建通道配置交易
- 使用 peer cli 创建及加入通道
本节将演示如何搭建一个 Peer 节点和一个 Orderer 节点的网络。
1、环境准备
在开始之前,我们需要在一个独立的文件夹中来搭建我们的网络。
- 建立存放配置文件和证书的文件夹
先在~/fabric-demo/networks 下建立如下结构的目录:
single-dev-env
--config(存放配置文件)
----channel-artifacts(存放后面要生成的通道配置交易等文件)
shell 命令:
mkdir -p ~/fabric-demo/networks/single-dev-env/config/channel-artifacts
- 准备 fabric 组件和证书生成工具等
在~/fabric-demo 文件下建立一个 bin 文件,并将 fabric/build/bin 目录下的所有文件拷贝至该目录下:
shell 命令:
cd ~/go/src/github.com/hyperledger/fabric/build
cp -r bin ~/fabric-demo/bin
此时,~/fabric-demo/bin 目录中的文件如下:
将~/fabric-demo/bin 加入环境变量
nano ~/.profile
其中该文件中环境变量如下:
export PATH=$PATH:/usr/local/go/bin
export GOROOT=/usr/local/go
export GOPATH=$HOME/go
export PATH=$PATH:$HOME/go/bin
export PATH=$PATH:$HOME/fabric-demo/bin
最后更新一下环境变量的值:
source ~/.profile
2、生成证书
使用 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
在~/fabric-demo 目录下运行下面的 shell 命令:
cryptogen generate --config=networks/single-dev-env/config/crypto-config.yaml --output=networks/single-dev-env/config/crypto-config
命令执行成功后,networks/single-dev-env/config/crypto-config 目录下生成了如下结构的证书目录:
── ordererOrganizations
│ └── example.com
│ ├── ca
│ ├── msp
│ ├── orderers
│ ├── tlsca
│ └── users
│ └── Admin@example.com
└── peerOrganizations
└── example.com
├── ca
├── msp
├── peers
│ └── peer.example.com
├── tlsca
└── users
├── Admin@example.com
└── User1@example.com
http://orderer.example.com 目录存放的是 Orderer 节点需要的证书,等会启动 Orderer 节点时需要指定 msp 目录;
http://peer.example.com 目录存放的是 Peer 节点需要的证书,等会启动 Peer 节点时需要指定 msp 目录;
Admin@example.com
目录下的证书是 Peer 节点管理员证书,创建、加入通道、发送交易等操作都是用此目录下的证书进行签名,因此,我们使用 peer cli 时需要指定 msp 目录。
3、使用 configtxgen 生成 Orderer 的创世纪块
参考官方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 文件,在终端在~fabric-demo 根目录下,执行如下命令:
export FABRIC_CFG_PATH=$(pwd)/networks/single-dev-env/config/
在~fabric-demo 根目录下,执行如下命令:
configtxgen -outputBlock networks/single-dev-env/config/genesis.block -profile SingleSoloOrdererGenesis
命令执行成功后,networks/single-dev-env/config 目录下就多了一个 genesis.block 文件:
4、使用 configtxgen 创建通道配置交易
使用终端中,进入 fabric-demo 根目录,执行如下命令:
export CHANNEL_NAME=sxlchannel
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 文件。
5、启动 Orderer 和 Peer 节点
本小节是使用环境变量配置 Orderer 和 Peer 节点,其实也可以使用 yaml 文件配置,随着后面学习的深入,再慢慢介绍。
- 启动 orderer 节点
新打开一个终端,切换到~/fabric-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 启动成功后,控制台输出如下:
- 启动 peer 节点
再打开一个终端,切换到~/fabric-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 启动成功后,控制台输出如下:
6、创建通道
新打开一个终端,切换到~/fabric–demo 目录并设环境变量:
export rootDir=$(pwd)
export PATH=$rootDir/bin:$PATH
export CHANNEL_NAME=sxlchannel
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
执行成功后,当前目录生成了一个 sxlchannel.block 文件:
7、加入通道
在终端~/fabric-demo 目录下执行如下命令:
peer channel join -b $CHANNEL_NAME.block
执行成功后,终端输入日志:
从上面的输出克重,peer 节点成功加入通道中!
三、部署及调用官方链码示例
本节将演示如何部署及调用一个简单的 go 语言示例——fabric/examples/chaincode/go/chaincode_example02。
链码部署及调用过程如下:
- 启动链码对应的程序;
- 部署链码。分 install 和 instantiate 两个阶段。其中,install 将链码源码打包成链码部署文件(CDS)并上传到 Peer 节点,instantiate 将根据 CDS 生成链码对应的 Docker 容器,启动容器并执行链码的实例化操作,一般是调用链码的 init 方法。这里描述的 instantiate 是使用“network”模式运行链码,而我们此次测试使用的是“dev”模式,由启动 Peer 节点时设置的 CORE_CHAINCODE_MODE 环境变量的值决定的。
- 调用链码。分 invoke 和 query 两种操作。invoke 是写操作,可修改账本,能产生块,而 query 是读操作,不写账本,也不生成块。
1、启动链码
打开一个终端,执行如下命令:
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
命令直接运行的,当然,也可以将链码编译成可执行程序再运行。
2、部署链码
新打开一个终端,切换到~/fabric-demo 目录,
首先设置环境变量:
export rootDir=$(pwd)
export PATH=$rootDir/bin:$PATH
export CHANNEL_NAME=sxlchannel
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
- 第 1 步:install 链码:
peer chaincode install -n mycc -v 1.0 -p github.com/hyperledger/fabric/examples/chaincode/go/chaincode_example02
选项说明:
- -n:指定链码名称
- -v:链码版本
- -p:链码源码所在目录
终端输出:
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')"
选项说明:
- -o:orderer 节点的地址
- -C(大写):通道名称
- -n:链码名称
- -v:链码版本
- -c(小写):链码实例化时调用的方法及参数,JSON 字符串,Args 数组的第 0 个元素是调用的方法,实例化时一般都是 init 方法,其他元素是方法的参数。
- -P(大写):背书策略,即交易由哪些 Peer 节点签名后才是合法的。以后再详细说明。
当前终端输出内容如下:
3、调用链码
本节的操作都是使用上一小节部署链码用的终端。
首先,使用 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\"]}"
结果如下:
四、总结
前面说过,搭建 fabric 网络的时候,有两种方式。一种是基于 Docker 容器的方式,另一种是直接编译源码。今天总算是把手动编译源码这个计划完成了。后面这段时间,将着重研究区块链应用的开发。
参考文章:
- HyperLedger Fabric:自顶向下的方法–第 1 篇 编译 fabric 源码及手工搭建单个 Peer 节点网络
- Fabric 源码编译及示例
- ubuntu16.04 下源代码方式安装 fabric1.0
转自知乎 苏小乐 :https://www.zhihu.com/people/shan-de-ding-zhu/activities