G2EX

Fabric 1.0 填坑指南

0x00 介绍

目前 Fabric 1.0 部署还是比较繁琐,环境搭建过程需要安装的和配置的东西较多,而且容易出错。

Fabric 从 1.0 beta 版到 1.0 正式版,官方文档也更新了不少。网络上很多中文资料是翻译的较早的官方文档,所以学习 Fabric 一定要参考最新的官方文档。官方文档中提供了一个名为 fabcar 智能合约的演示,指导我们从构建第一个网络到构建第一个应用。不过这一路从配置环境到合约演示,尤其在 Chinternet 的网络环境下,大大小小的坑有不少。正是因为这些原因,应该有一个对 Fabric 1.0 部署到合约演示的指导性文档,这也是本文的写作目的。初学者请以官方文档为主要学习材料,本文仅作为官方文档之外的参考指导。

本文使用 Fabric 1.0.4,基于 Ubuntu 16.04 x64,总结 Fabric 部署过程和 fabcar 链码演示过程中需要注意的地方,解释某些步骤使得知其然又能知其所以然,同时给出自己的最佳实践。


0x01 部署的先决条件

1) Docker [必需]

文档中 Prerequisites 一节,说的是运行 Fabric 的先决条件。因为 Fabric 基于 docker 部署,所以 docker 和 docker-compose 是必须的。同时对它们的版本有要求:

docker - 17.03.0-ce +
docker-compose - 1.8 +

安装 Docker CE

今年 3 月之后,Docker 17+ 分化成了 CE 社区版和 EE 企业版。和大多数一样,社区版免费使用。在 Ubuntu x64 里安装社区版推荐使用官方仓库安装,参考 https://docs.docker.com/engine/installation/linux/docker-ce/ubuntu/#set-up-the-repository

总结一下,命令分别如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
# 安装依赖
$ sudo apt-get update
$ sudo apt-get install \
apt-transport-https \
ca-certificates \
curl \
software-properties-common

# 添加 Docker 官方 GPG key
$ curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo apt-key add -

# 本地添加 Docker 更新源地址
$ sudo add-apt-repository \
"deb [arch=amd64] https://download.docker.com/linux/ubuntu \
$(lsb_release -cs) \
stable"

# 安装 Docker CE
$ sudo apt-get update
$ sudo apt-get install docker-ce

# 通过查看版本测试是否安装成功
$ docker --version

给 Docker 加速

如果在国内使用 Docker,推荐使用阿里云的 Docker 加速。登陆阿里云容器镜像服务 https://cr.console.aliyun.com/#/accelerator 在加速器页分配了自己的加速器地址。使用以下命令把加速地址写入 Docker 配置文件并重启服务:

1
2
3
4
5
6
7
8
sudo mkdir -p /etc/docker
sudo tee /etc/docker/daemon.json <<-'EOF'
{
"registry-mirrors": ["https://你的加速地址.mirror.aliyuncs.com"]
}
EOF
sudo systemctl daemon-reload
sudo systemctl restart docker

Docker 权限问题

安装完成后,如果用普通用户执行 docker 命令,会出现权限问题,需要用 sudo 命令运行。但是出于安全考虑,更好的做法是将需要使用 docker 的用户加入 docker 用户组。命令如下:

1
2
3
4
5
建立 docker 组:
$ sudo groupadd docker

将当前用户加入 docker 组:
$ sudo usermod -aG docker $USER

安装 docker-compose

因为 Fabric 容器使用 docker-compose 编排,所以 docker-compose 是必须的。安装方法参考 https://docs.docker.com/compose/install/#prerequisites

总结一下,命令如下:

1
2
3
4
5
6
7
8
# 当前 docker-compose 最新版是 1.17.0
$ sudo curl -L https://github.com/docker/compose/releases/download/1.17.0/docker-compose-`uname -s`-`uname -m` -o /usr/local/bin/docker-compose

# 添加可执行权限
$ sudo chmod +x /usr/local/bin/docker-compose

# 通过查看版本测试是否安装成功
$ docker-compose --version

2) Golang [非必需]

虽然 Prerequisites 中提到了 Golang,但 Golang 并不是必须的。
如果是把现成的链码部署到 Fabirc 上,比如 fabric-samples 中的 fabcar demo 示例,向 Fabric 网络安装和实例化 fabcar 链码的过程是在 docker 容器 cli 中执行的,容器 cli 中已经配置好了 Golang 环境。
如果你想在本地编写自己的链码,验证是否能通过编译,则需要本地配置 Golang 环境,版本要求 1.7 +。

配置 Golang 环境参考 https://golang.org/doc/install

总结一下:

1
2
3
4
5
6
7
8
9
10
11
# 下载安装包后,root 权限解压至 /usr/local 下:
$ sudo tar -C /usr/local -xzf go$VERSION.$OS-$ARCH.tar.gz

# 编辑 /etc/profile 或 $HOME/.profile,在文件最后添加环境变量:
export PATH=$PATH:/usr/local/go/bin

# 编辑 $HOME/.profile 或者 $HOME/.bashrc,添加 go 工作目录环境变量 GOPATH:
export GOPATH=$HOME/workspace/gopath

# 通过查看版本测试是否安装成功
$ go version

3) Node.JS [非必需]

Node.JS 也不是必需的。
Fabric 1.0 提供了 SDK,它封装了与 Fabric 区块链交互的 API,目前功能最全官方最推荐的是 Node.js 版本的 SDK。所以,如果要简单演示 fabcar demo 示例,或者要开发上层应用,需要 Node.js 环境。

目前对 Node.js 的版本要求如下:
Node.js - version 6.9.x +(但不支持 7.x)
npm - @3.10.10

需要注意的坑

Node.js 官网最新的 LTS 版本已经从 6.x 升级到了 8.x。(2017.11.9)Ubuntu 仓库默认的 Nodejs 版本太古老,因此强烈推荐使用官网的 package manager 方法安装 Node.js。参考 https://nodejs.org/en/download/package-manager/

总结如下:

1
2
3
$ curl -sL https://deb.nodesource.com/setup_6.x | sudo -E bash -
$ sudo apt-get install -y nodejs
$ npm version

npm加速

国内使用 npm 非常不稳定,推荐使用淘宝 NPM 镜像加速。
推荐使用淘宝定制的 cnpm (gzip 压缩支持) 命令行工具代替默认的 npm:

1
$ sudo npm install -g cnpm --registry=https://registry.npm.taobao.org

以后用到 npm install 命令的地方,直接用 cnpm install 代替即可。

至此,基本上所需要配置的环境已经安装好了,可以进入下一步,根据你的需要下载所需的 docker 镜像,运行示例。


0x02 下载 Docker 镜像

官方文档里提供了 Fabric Samples https://hyperledger-fabric.readthedocs.io/en/release/samples.html
该示例的源码在 Github 上 https://github.com/hyperledger/fabric-samples

fabric-samples 项目里包括了我们接下来要演示的 fabcar 链码。这里要用到一个脚本去下载所需 Docker 镜像和所需工具。为了把所需工具下载到 fabric-samples 项目里,需要先把该项目 clone 到本地,再在项目目录里下载并执行脚本。

把项目 Clone 项目到本地:

1
$ git clone https://github.com/hyperledger/fabric-samples.git

接下来在项目目录里执行下面命令,会获取 bootstrap-1.0.4.sh 脚本并运行:

1
2
$ cd fabric-samples
$ curl -sSL https://raw.githubusercontent.com/hyperledger/fabric/release/scripts/bootstrap-1.0.4.sh | bash

bootstrap-1.0.4.sh 会下载 1.0.4 版本的 Docker 镜像 peer orderer couchdb ccenv javaenv kafka zookeeper tools 并标记成 latest。 同时会下载 hyperledger-fabric-linux-amd64-1.0.4.tar.gz 压缩包(工具包),并解压缩到当前的 bin 目录下。
脚本运行结束后,可以看到项目目录中多出一个 bin 目录,里有 5 个可执行文件和 2 个脚本:configtxgen configtxlator cryptogen orderer peer get-byfn.sh get-docker-images.sh。这些文件在后续搭建网络、生成配置文件和操作链码的时候会用到。

Docker 镜像下载完成后应该是这样的:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
$ docker images | grep hyperledger*
hyperledger/fabric-ca latest 8e691b3509bf 8 days ago 238MB
hyperledger/fabric-ca x86_64-1.0.4 8e691b3509bf 8 days ago 238MB
hyperledger/fabric-tools latest 6051774928a6 8 days ago 1.33GB
hyperledger/fabric-tools x86_64-1.0.4 6051774928a6 8 days ago 1.33GB
hyperledger/fabric-couchdb latest cf24b91dfeb1 8 days ago 1.5GB
hyperledger/fabric-couchdb x86_64-1.0.4 cf24b91dfeb1 8 days ago 1.5GB
hyperledger/fabric-kafka latest 7a9d6f3c4a7c 8 days ago 1.29GB
hyperledger/fabric-kafka x86_64-1.0.4 7a9d6f3c4a7c 8 days ago 1.29GB
hyperledger/fabric-zookeeper latest 53c4a0d95fd4 8 days ago 1.3GB
hyperledger/fabric-zookeeper x86_64-1.0.4 53c4a0d95fd4 8 days ago 1.3GB
hyperledger/fabric-orderer latest b17741e7b036 8 days ago 151MB
hyperledger/fabric-orderer x86_64-1.0.4 b17741e7b036 8 days ago 151MB
hyperledger/fabric-peer latest 1ce935adc397 8 days ago 154MB
hyperledger/fabric-peer x86_64-1.0.4 1ce935adc397 8 days ago 154MB
hyperledger/fabric-javaenv latest a517b70135c7 8 days ago 1.41GB
hyperledger/fabric-javaenv x86_64-1.0.4 a517b70135c7 8 days ago 1.41GB
hyperledger/fabric-ccenv latest 856061b1fed7 8 days ago 1.28GB
hyperledger/fabric-ccenv x86_64-1.0.4 856061b1fed7 8 days ago 1.28GB

0x03 演示 fabcar Demo

参考官方文档的《构建你的第一个应用》去操作。

1
2
3
4
5
6
# 进入 fabcar 目录
$ cd fabric-samples/fabcar
# 安装依赖,因为用的是 Node.js SDK
$ cnpm install
# 启动 Fabric 网络:1 Peer + 1 orderer + ca + couchdb + cli
$ ./startFabric.sh

如果前面你的配置没问题,运行 fabcar 目录下的 startFabric.sh 脚本后,就可以启动一个简单的 Fabric 网络了,网络由 1 Peer + 1 orderer + ca + couchdb + cli 组成。

之后,就可以按照官方文档中的步骤,用 node enrollAdmin.js node registerUser.js node invoke.js node query.js 与 fabcar 链码交互了。

疑惑1
Fabric 网络是怎么建立起来的?

具体参见 startFabric.sh 脚本,可以看到它启动了 fabric-samples/basic-network 目录下的 start.sh,该脚本里执行了:

1
docker-compose -f docker-compose.yml up -d ca.example.com orderer.example.com peer0.org1.example.com couchdb

Fabric 网络就在这个 docker-compose.yml 中定义好了:

1
2
3
4
5
CA 容器 - ca.example.com
orderer 容器 - orderer.example.com
peer 容器 - peer0.org1.example.com
couchdb 容器 - couchdb
cli 容器 - cli

疑惑2
fabcar 链码放在了哪里?以后我们自己的合约又怎么部署 Fabric 网络上?

作为开发者,我们要通过客户端 —— cli 容器——与 Fabric 网络交互。在部署链码时,会通过 cli 客户端把 cli 中的 fabcar 链码安装到 peer0 上。

在 fabric-samples 项目里,有一个 chaincode 目录,fabcar 就放在了这个目录下。在定义 Fabric 网络的 basic-network/docker-compose.yml 中,可以看到以下配置:

1
2
3
4
5
6
7
8
services:
...
cli:
...
volumes:
...
- ./../chaincode/:/opt/gopath/src/github.com/
...

cli 容器把项目中的 chaincode 目录映射到了容器的 /opt/gopath/src/github.com/ 路径下。我们可以进入 cli 容器验证一下:

1
2
3
$ docker exec -it cli bash
# ls /opt/gopath/src/github.com/
chaincode_example02 fabcar hyperledger marbles02 sacc

当 fabcar/startFabric.sh 脚本执行到:

1
docker exec -e "CORE_PEER_LOCALMSPID=Org1MSP" -e "CORE_PEER_MSPCONFIGPATH=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org1.example.com/users/Admin@org1.example.com/msp" cli peer chaincode install -n fabcar -v 1.0 -p github.com/fabcar

会把 cli 中 $GOPATH 路径下的 github.com/fabcar 链码安装到 Fabric 网络中。

所以,对于我们自己开发的链码,也可以把链码放到项目的 chaincode 目录下,同时链码目录映射到 cli 容器中。修改 startFabric.sh 中的参数,把我们自己的链码安装和实例化。


0x04 其他说明

说到用 Golang 开发链码,推荐 Visual Studio Code 编辑器。它自动推荐合适的扩展,对 Go 的支持很好。不过 VSC 在安装 Go 扩展的时候,因为墙的原因,往往会遇到下面的问题:

1
2
3
4
5
6
7
8
9
10
11
12
13
Installing github.com/nsf/gocode SUCCEEDED
Installing github.com/uudashr/gopkgs/cmd/gopkgs SUCCEEDED
Installing github.com/ramya-rao-a/go-outline FAILED
Installing github.com/acroca/go-symbols FAILED
Installing golang.org/x/tools/cmd/guru FAILED
Installing golang.org/x/tools/cmd/gorename FAILED
Installing github.com/fatih/gomodifytags SUCCEEDED
Installing github.com/josharian/impl FAILED
Installing github.com/rogpeppe/godef SUCCEEDED
Installing sourcegraph.com/sqs/goreturns FAILED
Installing github.com/golang/lint/golint FAILED
Installing github.com/cweill/gotests/... FAILED
Installing github.com/derekparker/delve/cmd/dlv SUCCEEDED

解决办法是,给 go 和 git 设置代理。之所以要给 git 也设置代理,是因为安装 go 扩展用到的 go get 命令会先用 git 去仓库获取。Go 目前只支持 http/https 代理,git 可以设置 http/https 和 SOCKS 代理。代理的设置,可以参考 https://g2ex.github.io/2017/10/22/windows-linux-git-proxy-cmd

简言之,在 Ubuntu 里使用以下命令为当前终端和 git 设置代理,然后手动执行 go get -u -v github.com/ramya-rao-a/go-outline 等命令给 VSC 安装扩展。

1
2
3
4
5
6
7
8
9
10
# 当前终端设置 http/https 代理以供 go get 命令使用
$ export http_proxy=http://127.0.0.1:8118
$ export https_proxy=http://127.0.0.1:8118

# Git 设置 http/https 代理
git config --global http.proxy http://127.0.0.1:8118
git config --global https.proxy http://127.0.0.1:8118
# 或 Git 设置 SOCKS 代理
git config --global http.proxy socks5://127.0.0.1:1080
git config --global https.proxy socks5://127.0.0.1:1080

以上是我在实际操作中遇到过的一些问题和解决方法。随着 Fabric 和官方文档的更新,本文也会过时,不过还是希望能对学习 Fabric 的朋友们有所帮助。