0%

区块链入门(一)(hyperledger-fabric-v2.0环境搭建)

懒🐕的爷不到DDL是⑧可能开始工作的,近日DDL将近,不得不开始光速入门。
而或环境崩坏,有此记录,亦便于日后重建。
链来!

环境准备:

centos8.0系统的阿里云ecs服务器一台
xshell6.0或其他ssh工具

参考链接

官方文档:https://hyperledger-fabric.readthedocs.io/en/release-2.0/prereqs.html
本文可以看作对于官方文档的个人理解搭建(可作为补充参考),有能力者建议直接按照官网内容自行搭建。

环境依赖

  • git
  • curl
  • wget
  • Docker和Docker-Compose(Docker 17.06.2-ce或更高版本。)
  • Go语言(1.13.10)

环境依赖搭建:

  • git
    1
    yum install git
  • curl
    1
    sudo dnf install curl
  • wget
    1
    2
    3
    yum -y install wget
    yum -y install setup
    yum -y install perl
  • docker
    1
    2
    3
    4
    5
    6
    curl https://download.docker.com/linux/centos/docker-ce.repo -o /etc/yum.repos.d/docker-ce.repo
    yum install https://download.docker.com/linux/fedora/30/x86_64/stable/Packages/containerd.io-1.2.6-3.3.fc30.x86_64.rpm
    yum install docker-ce
    systemctl start docker
    docker info
    docker --version
  • docker-compose
    1
    2
    3
    curl -L https://github.com/docker/compose/releases/download/1.25.1/docker-compose-`uname -s`-`uname -m` -o /usr/local/bin/docker-compose
    chmod +x /usr/local/bin/docker-compose
    docker-compose --version
    是⑧是发现docker-compose下载速度很慢?
    下面是豪子哥推荐的光速安装docker-compose法
    1
    2
    3
    4
    5
    6
    7
    8
    9
    yum -y install epel-release
    yum -y install python2-pip
    yum -y install python3-pip
    pip3 install --upgrade pip
    yum install python3-devel -y
    yum install -y gcc
    yum install -y libffi-devel python3-devel openssl-devel
    pip install docker-compose
    docker-compose version
  • go语言
    1
    2
    wget -c https://studygolang.com/dl/golang/go1.13.10.linux-amd64.tar.gz
    tar -C /opt/ -zxvf go1.13.10.linux-amd64.tar.gz
    添加go进入环境变量,注意这里建立的gopath文件夹,之后下载相关文件我们要在gopath里下载
    1
    2
    3
    4
    5
    6
    mkdir ~/gopath
    vim ~/.bash_profile
    #写入以下内容
    export GOROOT=/opt/go
    export PATH=$PATH:$GOROOT/bin
    export GOPATH=~/gopath
    加载环境变量并验证
    1
    2
    . ~/.bash_profile
    go version

拉取必要文件

  • 拉取the Fabric Samples and binaries:(多种方法任选一种,推荐使用我已经下载好的文件)
    这一步的速度很慢(这里推荐大家使用我下载好的压缩包文件,上传到服务器上解压部署)
    1
    2
    3
    4
    cd /opt
    mkdir hyperledger
    cd hyperledger
    curl -sSL https://bit.ly/2ysbOFE | bash -s
    这里我下载完,发现出现了未知错误,查询官方发现
    如果遇到错误,可以使用先下载
    https://raw.githubusercontent.com/hyperledger/fabric/master/scripts/bootstrap.sh
    然后在相应保存目录运行(这个方法也很慢)
    1
    2
    chmod 777 ./bootstrap.sh
    ./bootstrap.sh
    建议大家直接去github手动下载,地址如下:(这里我已经分享在qq群里了)
    1
    2
    3
    4
    5
    6
    hyperledger-fabric:
    https://github.com/hyperledger/fabric/releases/download/v2.0.0/hyperledger-fabric-linux-amd64-2.0.0.tar.gz
    hyperledger-fabric-ca:
    https://github.com/hyperledger/fabric-ca/releases/download/v1.4.6/hyperledger-fabric-ca-linux-amd64-1.4.6.tar.gz
    hyperledger-fabric-samples:
    git clone https://github.com/hyperledger/fabric-samples.git
    注意,这里下载下来的文件要放在之前配置go环境的GOPATH文件夹下并解压(比如这里就是~/gopath文件夹中,所以我们可以在/gopath文件夹下面新建一个hyperledger文件夹,然后放到hyperledger文件夹里)
    这里将samples放到hyperledger文件夹中,然后把其他两个文件中对应的bins和config文件夹加入到samples里中,这里由于使用xtfp直接传输就不作演示了
    1
    2
    3
    cd ~/gopath
    mkdir hyperledger
    cd hyperledger
    接下来要设置权限并把bins中内容添加到path环境变量(此时在fabric-samples目录下)
    1
    2
    chmod 777 *
    export PATH=/root/gopath/hyperledger/fabric-samples/bin:$PATH

注意,由于后面搭建出现错误,此处作了改动
对于docker镜像,手动拉取会产生错误,所以这里我们新建一个脚本用于拉取,内容如下,命名为dockerpull.sh,设置权限后运行即可

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
#!/bin/bash
#
# Copyright IBM Corp. All Rights Reserved.
#
# SPDX-License-Identifier: Apache-2.0
#

# if version not passed in, default to latest released version
VERSION=2.0.0
# if ca version not passed in, default to latest released version
CA_VERSION=1.4.6
# current version of thirdparty images (couchdb, kafka and zookeeper) released
THIRDPARTY_IMAGE_VERSION=0.4.18
ARCH=$(echo "$(uname -s|tr '[:upper:]' '[:lower:]'|sed 's/mingw64_nt.*/windows/')-$(uname -m | sed 's/x86_64/amd64/g')")
MARCH=$(uname -m)

printHelp() {
echo "Usage: bootstrap.sh [version [ca_version [thirdparty_version]]] [options]"
echo
echo "options:"
echo "-h : this help"
echo "-d : bypass docker image download"
echo "-s : bypass fabric-samples repo clone"
echo "-b : bypass download of platform-specific binaries"
echo
echo "e.g. bootstrap.sh 2.0.0 1.4.6 0.4.18 -s"
echo "would download docker images and binaries for Fabric v2.0.0 and Fabric CA v1.4.6"
}

# dockerPull() pulls docker images from fabric and chaincode repositories
# note, if a docker image doesn't exist for a requested release, it will simply
# be skipped, since this script doesn't terminate upon errors.

dockerPull() {
#three_digit_image_tag is passed in, e.g. "1.4.6"
three_digit_image_tag=$1
shift
#two_digit_image_tag is derived, e.g. "1.4", especially useful as a local tag for two digit references to most recent baseos, ccenv, javaenv, nodeenv patch releases
two_digit_image_tag=$(echo $three_digit_image_tag | cut -d'.' -f1,2)
while [[ $# -gt 0 ]]
do
image_name="$1"
echo "====> hyperledger/fabric-$image_name:$three_digit_image_tag"
docker pull "hyperledger/fabric-$image_name:$three_digit_image_tag"
docker tag "hyperledger/fabric-$image_name:$three_digit_image_tag" "hyperledger/fabric-$image_name"
docker tag "hyperledger/fabric-$image_name:$three_digit_image_tag" "hyperledger/fabric-$image_name:$two_digit_image_tag"
shift
done
}

cloneSamplesRepo() {
# clone (if needed) hyperledger/fabric-samples and checkout corresponding
# version to the binaries and docker images to be downloaded
if [ -d first-network ]; then
# if we are in the fabric-samples repo, checkout corresponding version
echo "===> Checking out v${VERSION} of hyperledger/fabric-samples"
git checkout v${VERSION}
elif [ -d fabric-samples ]; then
# if fabric-samples repo already cloned and in current directory,
# cd fabric-samples and checkout corresponding version
echo "===> Checking out v${VERSION} of hyperledger/fabric-samples"
cd fabric-samples && git checkout v${VERSION}
else
echo "===> Cloning hyperledger/fabric-samples repo and checkout v${VERSION}"
git clone -b master https://github.com/hyperledger/fabric-samples.git && cd fabric-samples && git checkout v${VERSION}
fi
}

# This will download the .tar.gz
download() {
local BINARY_FILE=$1
local URL=$2
echo "===> Downloading: " "${URL}"
curl -L --retry 5 --retry-delay 3 "${URL}" | tar xz || rc=$?
if [ -n "$rc" ]; then
echo "==> There was an error downloading the binary file."
return 22
else
echo "==> Done."
fi
}


pullDockerImages() {
command -v docker >& /dev/null
NODOCKER=$?
if [ "${NODOCKER}" == 0 ]; then
FABRIC_IMAGES=(peer orderer ccenv tools)
case "$VERSION" in
1.*)
FABRIC_IMAGES+=(javaenv)
shift
;;
2.*)
FABRIC_IMAGES+=(nodeenv baseos javaenv)
shift
;;
esac
echo "FABRIC_IMAGES:" "${FABRIC_IMAGES[@]}"
echo "===> Pulling fabric Images"
dockerPull "${FABRIC_TAG}" "${FABRIC_IMAGES[@]}"
echo "===> Pulling fabric ca Image"
CA_IMAGE=(ca)
dockerPull "${CA_TAG}" "${CA_IMAGE[@]}"
echo "===> Pulling thirdparty docker images"
THIRDPARTY_IMAGES=(zookeeper kafka couchdb)
dockerPull "${THIRDPARTY_TAG}" "${THIRDPARTY_IMAGES[@]}"
echo
echo "===> List out hyperledger docker images"
docker images | grep hyperledger
else
echo "========================================================="
echo "Docker not installed, bypassing download of Fabric images"
echo "========================================================="
fi
}

DOCKER=true
SAMPLES=true
BINARIES=true

# Parse commandline args pull out
# version and/or ca-version strings first
if [ -n "$1" ] && [ "${1:0:1}" != "-" ]; then
VERSION=$1;shift
if [ -n "$1" ] && [ "${1:0:1}" != "-" ]; then
CA_VERSION=$1;shift
if [ -n "$1" ] && [ "${1:0:1}" != "-" ]; then
THIRDPARTY_IMAGE_VERSION=$1;shift
fi
fi
fi

# prior to 1.2.0 architecture was determined by uname -m
if [[ $VERSION =~ ^1\.[0-1]\.* ]]; then
export FABRIC_TAG=${MARCH}-${VERSION}
export CA_TAG=${MARCH}-${CA_VERSION}
export THIRDPARTY_TAG=${MARCH}-${THIRDPARTY_IMAGE_VERSION}
else
# starting with 1.2.0, multi-arch images will be default
: "${CA_TAG:="$CA_VERSION"}"
: "${FABRIC_TAG:="$VERSION"}"
: "${THIRDPARTY_TAG:="$THIRDPARTY_IMAGE_VERSION"}"
fi

BINARY_FILE=hyperledger-fabric-${ARCH}-${VERSION}.tar.gz
CA_BINARY_FILE=hyperledger-fabric-ca-${ARCH}-${CA_VERSION}.tar.gz

# then parse opts
while getopts "h?dsb" opt; do
case "$opt" in
h|\?)
printHelp
exit 0
;;
d) DOCKER=false
;;
s) SAMPLES=false
;;
b) BINARIES=false
;;
esac
done

if [ "$SAMPLES" == "true" ]; then
echo
echo "Clone hyperledger/fabric-samples repo"
echo
cloneSamplesRepo
fi

if [ "$DOCKER" == "true" ]; then
echo
echo "Pull Hyperledger Fabric docker images"
echo
pullDockerImages
fi

初步搭建测试

  • 这里我们将搭建samples下的test-network
    首先进入相应目录:

    1
    cd fabric-samples/test-network

    设置权限并查看命令的使用方法

    1
    2
    chmod 777 ./network.sh
    ./network.sh -h

    删除之前运行的容器

    1
    ./network.sh down

    运行命令启动网络

    1
    ./network.sh up

    注意这里有可能遇到了一个错误:Fabric Docker image version of 1.4.6 does not match the versions supported by the test network.
    解决方案是使用上面的脚本拉取镜像,放弃手动拉取docker镜像
    如果出现以下的字样,则说明你已经成功搭建了2.0的环境

    1
    2
    3
    4
    CONTAINER ID        IMAGE                               COMMAND             CREATED             STATUS                  PORTS                              NAMES
    b8912b452ca9 hyperledger/fabric-orderer:latest "orderer" 2 seconds ago Up Less than a second 0.0.0.0:7050->7050/tcp orderer.example.com
    9e9ae4e89fa9 hyperledger/fabric-peer:latest "peer node start" 2 seconds ago Up Less than a second 7051/tcp, 0.0.0.0:9051->9051/tcp peer0.org2.example.com
    c6beb480a0d4 hyperledger/fabric-peer:latest "peer node start" 2 seconds ago Up Less than a second 0.0.0.0:7051->7051/tcp peer0.org1.example.com

    查看创建的节点

    1
    docker ps -a

    建立频道,下面的命令将创建默认名称频道mychannel

    1
    ./network.sh createChannel

    看到successfully则说明创建成功
    如果想创建自定义频道,可以使用如下命令

    1
    ./network.sh createChannel -c <name>

    在channel上启动链码,命令如下

    1
    ./network.sh deployCC

    这里可能有人就遇到问题了,下载慢且下载不下来,怎么办呢?在命令行执行如下命令:(使用七牛云go moudles镜像)

    1
    2
    go env -w GO111MODULE=on
    go env -w GOPROXY=https://goproxy.cn,direct

    成功则输出如下:

    1
    2
    [{"Key":"CAR0","Record":{"make":"Toyota","model":"Prius","colour":"blue","owner":"Tomoko"}},{:"Brad"}},{"Key":"CAR2","Record":{"make":"Hyundai","model":"Tucson","colour":"green","owner":our":"yellow","owner":"Max"}},{"Key":"CAR4","Record":{"make":"Tesla","model":"S","colour":"bl5","colour":"purple","owner":"Michel"}},{"Key":"CAR6","Record":{"make":"Chery","model":"S22L"del":"Punto","colour":"violet","owner":"Pari"}},{"Key":"CAR8","Record":{"make":"Tata","model""Holden","model":"Barina","colour":"brown","owner":"Shotaro"}}]
    ===================== Query successful on peer0.org1 on channel 'mychannel' ================

    下一步则是设置PWD环境变量和设置FABRIC_CFG_PATH

    1
    2
    export PATH=${PWD}/root/gopath/hyperledger/fabric-samples/bin:${PWD}:$PATH
    export FABRIC_CFG_PATH=$PWD/../config/

    进一步设置环境变量,使得可以通过peer ..的形式执行命令

    1
    2
    3
    4
    5
    6
    7
    # Environment variables for Org1

    export CORE_PEER_TLS_ENABLED=true
    export CORE_PEER_LOCALMSPID="Org1MSP"
    export CORE_PEER_TLS_ROOTCERT_FILE=${PWD}/organizations/peerOrganizations/org1.example.com/peers/peer0.org1.example.com/tls/ca.crt
    export CORE_PEER_MSPCONFIGPATH=${PWD}/organizations/peerOrganizations/org1.example.com/users/Admin@org1.example.com/msp
    export CORE_PEER_ADDRESS=localhost:7051

    如果上一步设置成功了,则输入下列命令获取汽车列表

    1
    peer chaincode query -C mychannel -n fabcar -c '{"Args":["queryAllCars"]}'

    成功则会输出:

    1
    [{"Key":"CAR0","Record":{"make":"Toyota","model":"Prius","colour":"blue","owner":"Tomoko"}},{"Key":"CAR1","Record":{"make":"Ford","model":"Mustang","colour":"red","owner":"Brad"}},{"Key":"CAR2","Record":{"make":"Hyundai","model":"Tucson","colour":"green","owner":"Jin Soo"}},{"Key":"CAR3","Record":{"make":"Volkswagen","model":"Passat","colour":"yellow","owner":"Max"}},{"Key":"CAR4","Record":{"make":"Tesla","model":"S","colour":"black","owner":"Adriana"}},{"Key":"CAR5","Record":{"make":"Peugeot","model":"205","colour":"purple","owner":"Michel"}},{"Key":"CAR6","Record":{"make":"Chery","model":"S22L","colour":"white","owner":"Aarav"}},{"Key":"CAR7","Record":{"make":"Fiat","model":"Punto","colour":"violet","owner":"Pari"}},{"Key":"CAR8","Record":{"make":"Tata","model":"Nano","colour":"indigo","owner":"Valeria"}},{"Key":"CAR9","Record":{"make":"Holden","model":"Barina","colour":"brown","owner":"Shotaro"}}]

    当网络成员要转移或更改分类帐上的资产时,将调用链码。我们可以通过使用以下命令通过调用fabcar链码来更改分类帐中汽车的所有者:

    1
    peer chaincode invoke -o localhost:7050 --ordererTLSHostnameOverride orderer.example.com --tls true --cafile ${PWD}/organizations/ordererOrganizations/example.com/orderers/orderer.example.com/msp/tlscacerts/tlsca.example.com-cert.pem -C mychannel -n fabcar --peerAddresses localhost:7051 --tlsRootCertFiles ${PWD}/organizations/peerOrganizations/org1.example.com/peers/peer0.org1.example.com/tls/ca.crt --peerAddresses localhost:9051 --tlsRootCertFiles ${PWD}/organizations/peerOrganizations/org2.example.com/peers/peer0.org2.example.com/tls/ca.crt -c '{"function":"changeCarOwner","Args":["CAR9","Dave"]}'

    修改成功后,则结果如图所示:

    1
    2020-04-17 19:23:16.596 CST [chaincodeCmd] chaincodeInvokeOrQuery -> INFO 001 Chaincode invoke successful. result: status:200

    调用链代码后,我们可以使用org2查询来查看该调用如何更改了区块链分类账上的资产。由于我们已经查询过Org1对等体,因此我们可以进一步查询Org2对等体上运行的链码。设置以下环境变量来对Org2进行操作:

    1
    2
    3
    4
    5
    6
    7
    # Environment variables for Org2

    export CORE_PEER_TLS_ENABLED=true
    export CORE_PEER_LOCALMSPID="Org2MSP"
    export CORE_PEER_TLS_ROOTCERT_FILE=${PWD}/organizations/peerOrganizations/org2.example.com/peers/peer0.org2.example.com/tls/ca.crt
    export CORE_PEER_MSPCONFIGPATH=${PWD}/organizations/peerOrganizations/org2.example.com/users/Admin@org2.example.com/msp
    export CORE_PEER_ADDRESS=localhost:9051

    上面命令执行成功后,我们看一下在peer0.org2.example.com上运行的fabric链码

    1
    peer chaincode query -C mychannel -n fabcar -c '{"Args":["queryCar","CAR9"]}'

    如果命令执行成功,则会输出”CAR9”查询结果如下所示

    1
    {"make":"Holden","model":"Barina","colour":"brown","owner":"Dave"}

    上面我们对于test-network的测试基本成功,就可以中断网络

    1
    ./network.sh down

    接下来我们看一下如何与证书颁发机构建立网络
    输入以下命令:

    1
    ./network.sh up -ca

    成功我们则可以在刚开始执行时就看到

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    Starting nodes with CLI timeout of '5' tries and CLI delay of '3' seconds and using database 'leveldb' with crypto from 'Certificate Authorities'

    LOCAL_VERSION=2.0.0
    DOCKER_IMAGE_VERSION=2.0.0

    ##########################################################
    ##### Generate certificates using Fabric CA's ############
    ##########################################################
    Creating network "net_test" with the default driver
    Creating ca_orderer ... done
    Creating ca_org1 ... done
    Creating ca_org2 ... done
    ##########################################################
    ############ Create Org1 Identities ######################
    ##########################################################

    输入如下命令查看MSP文件夹的结构和配置文件

    1
    tree organizations/peerOrganizations/org1.example.com/users/Admin@org1.example.com/

    若成功则输出

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    organizations/peerOrganizations/org1.example.com/users/Admin@org1.example.com/
    └── msp
    ├── cacerts
    │   └── localhost-7054-ca-org1.pem
    ├── config.yaml
    ├── IssuerPublicKey
    ├── IssuerRevocationPublicKey
    ├── keystore
    │   └── 08af5d7a52deab54d88999f40624a0464b227af8e0af52e187f2a346f205dd46_sk
    ├── signcerts
    │   └── cert.pem
    └── user

    5 directories, 6 files

    我们可以在signcerts文件夹中找到admin用户的证书,并在文件夹中找到私钥keystore。更多关于此内容的介绍,请参考官方文档相关章节

    我们对于test-network的使用基本结束,接下来中断该网络

    1
    ./network.sh down

上面环境的搭建和测试已经基本完成,下一步就是搭建真实环境,将在我的下一篇blog中讲述

好饿啊,早知道不学安全了