运行fabric第一个示例e2e_cli
安装环境
我的系统是ubuntu 16.04,跑在Oracle VM VirtualBox 5.2.12虚拟机里边。
替换为国内的源
修改文件/etc/apt/source.list
使用阿里云的源,替换为
deb http://mirrors.aliyun.com/ubuntu/ xenial main restricted universe multiverse
deb http://mirrors.aliyun.com/ubuntu/ xenial-security main restricted universe multiverse
deb http://mirrors.aliyun.com/ubuntu/ xenial-updates main restricted universe multiverse
deb http://mirrors.aliyun.com/ubuntu/ xenial-backports main restricted universe multiverse
##測試版源
deb http://mirrors.aliyun.com/ubuntu/ xenial-proposed main restricted universe multiverse
# 源碼
deb-src http://mirrors.aliyun.com/ubuntu/ xenial main restricted universe multiverse
deb-src http://mirrors.aliyun.com/ubuntu/ xenial-security main restricted universe multiverse
deb-src http://mirrors.aliyun.com/ubuntu/ xenial-updates main restricted universe multiverse
deb-src http://mirrors.aliyun.com/ubuntu/ xenial-backports main restricted universe multiverse
##測試版源
deb [arch=amd64] https://download.docker.com/linux/ubuntu xenial stable
# deb-src [arch=amd64] https://download.docker.com/linux/ubuntu xenial stable
deb-src http://mirrors.aliyun.com/ubuntu/ xenial-proposed main restricted universe multiverse
Go安装
参考官方安装:https://golang.google.cn/doc/install
下载安装
下载地址:https://golang.google.cn/dl/
tar -C /usr/local -xzf go$VERSION.$OS-$ARCH.tar.gz
设置环境变量
这里直接修改的是/etc/profile
设置GOPATH
设置为/opt/gopath
因为e2e_cli示例里边很多地方写死了该路径。
export GOPATH=/opt/gopath
export PATH=$PATH:/usr/local/go/bin
设置系统PATH
export PATH=$PATH:/usr/local/go/bin
执行souce /etc/profile
验证安装
测试
go env
输出
GOARCH="amd64"
GOBIN=""
GOCACHE="/home/docker/.cache/go-build"
GOEXE=""
GOHOSTARCH="amd64"
GOHOSTOS="linux"
GOOS="linux"
GOPATH="/opt/gopath"
GORACE=""
GOROOT="/usr/local/go"
GOTMPDIR=""
GOTOOLDIR="/usr/local/go/pkg/tool/linux_amd64"
GCCGO="gccgo"
CC="gcc"
CXX="g++"
CGO_ENABLED="1"
CGO_CFLAGS="-g -O2"
CGO_CPPFLAGS=""
CGO_CXXFLAGS="-g -O2"
CGO_FFLAGS="-g -O2"
CGO_LDFLAGS="-g -O2"
PKG_CONFIG="pkg-config"
GOGCCFLAGS="-fPIC -m64 -pthread -fmessage-length=0 -fdebug-prefix-map=/tmp/go-build982916713=/tmp/go-build -gno-record-gcc-switches"
安装成功。
docker安装
参考官方文档Get Docker CE for Ubuntu
SET UP THE REPOSITORY
-
Update the
apt
package index:$ sudo apt-get update
-
Install packages to allow
apt
to use a repository over HTTPS:$ sudo apt-get install \ apt-transport-https \ ca-certificates \ curl \ software-properties-common
-
Add Docker’s official GPG key:
$ curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo apt-key add -
Verify that you now have the key with the fingerprint
9DC8 5822 9FC7 DD38 854A E2D8 8D81 803C 0EBF CD88
, by searching for the last 8 characters of the fingerprint.$ sudo apt-key fingerprint 0EBFCD88 pub 4096R/0EBFCD88 2017-02-22 Key fingerprint = 9DC8 5822 9FC7 DD38 854A E2D8 8D81 803C 0EBF CD88 uid Docker Release (CE deb) <docker@docker.com> sub 4096R/F273FCD8 2017-02-22
INSTALL DOCKER CE
-
Update the
apt
package index.$ sudo apt-get update
-
Install the latest version of Docker CE, or go to the next step to install a specific version:
$ sudo apt-get install docker-ce
Got multiple Docker repositories?
If you have multiple Docker repositories enabled, installing or updating without specifying a version in the
apt-get install
orapt-get update
command always installs the highest possible version, which may not be appropriate for your stability needs. -
To install a specific version of Docker CE, list the available versions in the repo, then select and install:
a. List the versions available in your repo:
$ apt-cache madison docker-ce docker-ce | 18.03.0~ce-0~ubuntu | https://download.docker.com/linux/ubuntu xenial/stable amd64 Packages
b. Install a specific version by its fully qualified package name, which is package name (
docker-ce
) “=” version string (2nd column), for example,docker-ce=18.03.0~ce-0~ubuntu
.$ sudo apt-get install docker-ce=<VERSION>
The Docker daemon starts automatically.
-
Verify that Docker CE is installed correctly by running the
hello-world
image.$ sudo docker run hello-world
This command downloads a test image and runs it in a container. When the container runs, it prints an informational message and exits.
docker compose安装
参考官方文档install-compose
Run this command to download the latest version of Docker Compose:
sudo curl -L https://github.com/docker/compose/releases/download/1.22.0/docker-compose-$(uname -s)-$(uname -m) -o /usr/local/bin/docker-compose
Apply executable permissions to the binary:
sudo chmod +x /usr/local/bin/docker-compose
Test the installation.
docker-compose --version
fabric下载
cd $GOPATH
最好将GOPATH设置为/opt/gopath。e2e_cli示例里边很多地方写死了该路径。
创建目录,一样的,也是写死了路径
mkdir -p src/github.com/hyperledger
下载fabric源代码
git clone https://github.com/hyperledger/fabric.git
切换到1.0分支
git checkout release-1.0
编译configtxgen
工具
cd $GOPATH/src/github.com/hyperledger/fabric
make configtxgen
编译后输出
Binary available as build/bin/configtxgen
示例程序e2e_cli
下载镜像
进入到e2e_cli目录
cd $GOPATH/src/github.com/hyperledger/fabric/examples/e2e_cli/
严格指定下载1.0.0版本
source download-dockerimages.sh -c x86_64-1.0.0 -f x86_64-1.0.0
运行
切换到e2e_cli目录下,执行network_setup.sh up
启动
cd $GOPATH/src/github.com/hyperledger/fabric/examples/e2e_cli/
sudo ./network_setup.sh up
接下来开始踩坑了。
错误1 - 未终止的"s"命令
脚本文件generateArtifacts.sh
函数 replacePrivateKey
中
sed $OPTS "s/CA1_PRIVATE_KEY/${PRIV_KEY}/g" docker-compose-e2e.yaml
sed $OPTS "s/CA2_PRIVATE_KEY/${PRIV_KEY}/g" docker-compose-e2e.yaml
必须使用单引号。(实际我在telminal中是能执行的,不知道为什么在shell中不行)
sed $OPTS 's/CA1_PRIVATE_KEY/${PRIV_KEY}/g' docker-compose-e2e.yaml
sed $OPTS 's/CA2_PRIVATE_KEY/${PRIV_KEY}/g' docker-compose-e2e.yaml
可能是我下载桌面版本ubuntu,安装是中文版。在服务器上是英文版没有遇到这个问题。
错误2 - fatal error: ltdl.h: No such file or directory
make cryptogen
find: ‘/src/github.com/hyperledger/fabric/core/chaincode/shim’: No such file or directory
build/bin/cryptogen
CGO_CFLAGS=" " GOBIN=/home/fabric/go/src/github.com/hyperledger/fabric/build/bin go install -tags "" -ldflags "-X github.com/hyperledger/fabric/common/tools/cryptogen/metadata.Version=1.0.7-snapshot-b23007c" github.com/hyperledger/fabric/common/tools/cryptogen
# github.com/hyperledger/fabric/vendor/github.com/miekg/pkcs11
vendor/github.com/miekg/pkcs11/pkcs11.go:29:18: fatal error: ltdl.h: No such file or directory
compilation terminated.
Makefile:230: recipe for target 'build/bin/cryptogen' failed
make: *** [build/bin/cryptogen] Error 2
通过安装libltdl
解决
sudo apt install libltdl-dev
错误3 - orderer节点启动失败
2018-08-15 09:41:58.640 UTC [grpc] Printf -> DEBU 003 grpc: addrConn.resetTransport failed to create client transport: connection error: desc = "transport: Error while dialing dial tcp: lookup orderer.example.com on 127.0.0.11:53: no such host"; Reconnecting to {orderer.example.com:7050 <nil>}
Error: Error connecting due to rpc error: code = Unavailable desc = grpc: the connection is unavailable
通过docker ps查看,orderer节点并未启动成功
查看network_setup.sh
中的函数networkUp
function networkUp () {
if [ -f "./crypto-config" ]; then
echo "crypto-config directory already exists."
else
#Generate all the artifacts that includes org certs, orderer genesis block,
# channel configuration transaction
source generateArtifacts.sh $CH_NAME
fi
if [ "${IF_COUCHDB}" == "couchdb" ]; then
CHANNEL_NAME=$CH_NAME TIMEOUT=$CLI_TIMEOUT docker-compose -f $COMPOSE_FILE -f $COMPOSE_FILE_COUCH up -d 2>&1
else
CHANNEL_NAME=$CH_NAME TIMEOUT=$CLI_TIMEOUT docker-compose -f $COMPOSE_FILE up -d 2>&1
fi
if [ $? -ne 0 ]; then
echo "ERROR !!!! Unable to pull the images "
exit 1
fi
docker logs -f cli
}
因为我们没有使用couchdb,最核心的就是这一行
CHANNEL_NAME=$CH_NAME TIMEOUT=$CLI_TIMEOUT docker-compose -f $COMPOSE_FILE up -d 2>&1
脚本文件network_setup.sh
开头已经定义OMPOSE_FILE=docker-compose-cli.yaml
实际命令最后为:
docker-compose -f docker-compose-cli.yaml up -d
既然是orderer节点启动不起来,那就将orderer节点的信息单独拷贝出来,到新建的文件docker-compose-cli-test.yaml
来测试,看启动失败的信息。
``docker-compose-cli-test.yaml`文件内容:
# Copyright IBM Corp. All Rights Reserved.
#
# SPDX-License-Identifier: Apache-2.0
#
version: '2'
services:
orderer.example.com:
extends:
file: base/docker-compose-base.yaml
service: orderer.example.com
container_name: orderer.example.com
通过docker-compose
执行
sudo docker-compose -f docker-compose-cli-test.yaml up
输出结果很多,重要信息在这
orderer.example.com | panic: Unable to bootstrap orderer. Error reading genesis block file: read /var/hyperledger/orderer/genesis.block: is a directory
说明可能文件挂载除了问题。
查看docker-compose-base.yaml
中的orderer.example.com
目录挂载信息
volumes:
- ../channel-artifacts/genesis.block:/var/hyperledger/orderer/orderer.genesis.block
- ../crypto-config/ordererOrganizations/example.com/orderers/orderer.example.com/msp:/var/hyperledger/orderer/msp
- ../crypto-config/ordererOrganizations/example.com/orderers/orderer.example.com/tls/:/var/hyperledger/orderer/tls
../channel-artifacts/genesis.block
是一个文件,而被当做目录挂载了。说明没有被读到。
尝试给这一行加上引号
- "../channel-artifacts/genesis.block:/var/hyperledger/orderer/genesis.block"
再进行重新启动,发现OK了,问题解决了。
后来再去创建了一个docker工程测试验证了下。发现
- volumes去挂载目录,host path是相对路径是没有问题的
- volumes去挂载文件,host path得是绝对路径或者得加上引号
错误4 - network e2ecli_default not found
错误信息
Error: Error endorsing chaincode: rpc error: code = Unknown desc = error starting container: API error (404): {"message":"network e2ecli_default not found"}
网上有不少人给出了解决方案,将peer-base.yaml文件中的
- CORE_VM_DOCKER_HOSTCONFIG_NETWORKMODE=e2ecli_default
改为
- CORE_VM_DOCKER_HOSTCONFIG_NETWORKMODE=e2e_cli_default
这样改是可以的。参考https://docs.docker.com/compose/networking/
真实原因是默认创建的网络名称为:$(目录名称)_default,而我们的这个示例项目目录名称为**e2e_cli
**。因此网络名称为e2e_cli_deault。
可以通过命令查看
docker network ls
输出结果
NETWORK ID NAME DRIVER SCOPE
aa27e123a2a5 e2e_cli_default bridge local
测试
进行cli容器实例内
docker exec -it cli bash
查询账户余额
peer chaincode query -C mychannel -n mycc -c '{"Args":["query","a"]}’
2018-08-15 10:02:51.818 UTC [msp] GetLocalMSP -> DEBU 001 Returning existing local MSP
2018-08-15 10:02:51.819 UTC [msp] GetDefaultSigningIdentity -> DEBU 002 Obtaining default signing identity
2018-08-15 10:02:51.819 UTC [chaincodeCmd] checkChaincodeCmdParams -> INFO 003 Using default escc
2018-08-15 10:02:51.819 UTC [chaincodeCmd] checkChaincodeCmdParams -> INFO 004 Using default vscc
2018-08-15 10:02:51.820 UTC [msp/identity] Sign -> DEBU 005 Sign: plaintext: 0A95070A6708031A0C08CBF4CFDB0510...6D7963631A0A0A0571756572790A0161
2018-08-15 10:02:51.823 UTC [msp/identity] Sign -> DEBU 006 Sign: digest: B0184158DA1C022502B398C719FED79E781EAB7B3F869DB1D4550EF95D500EBE
Query Result: 90
2018-08-15 10:02:51.850 UTC [main] main -> INFO 007 Exiting.....
转账20到b账户
peer chaincode invoke -o orderer.example.com:7050 --tls true --cafile /opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/ordererOrganizations/example.com/orderers/orderer.example.com/msp/tlscacerts/tlsca.example.com-cert.pem -C mychannel -n mycc -c '{"Args":["invoke","a","b","20"]}’
2018-08-15 10:03:05.369 UTC [msp] GetLocalMSP -> DEBU 001 Returning existing local MSP
2018-08-15 10:03:05.369 UTC [msp] GetDefaultSigningIdentity -> DEBU 002 Obtaining default signing identity
2018-08-15 10:03:05.375 UTC [chaincodeCmd] checkChaincodeCmdParams -> INFO 003 Using default escc
2018-08-15 10:03:05.375 UTC [chaincodeCmd] checkChaincodeCmdParams -> INFO 004 Using default vscc
2018-08-15 10:03:05.375 UTC [msp/identity] Sign -> DEBU 005 Sign: plaintext: 0A95070A6708031A0C08D9F4CFDB0510...696E766F6B650A01610A01620A023230
2018-08-15 10:03:05.375 UTC [msp/identity] Sign -> DEBU 006 Sign: digest: 0249597DB1E17B4BE333895FDAB47078D6A97B0C2F53D0FEB73337E585E3AF91
2018-08-15 10:03:05.419 UTC [msp/identity] Sign -> DEBU 007 Sign: plaintext: 0A95070A6708031A0C08D9F4CFDB0510...900474A86ED613AC027965F818A620FC
2018-08-15 10:03:05.419 UTC [msp/identity] Sign -> DEBU 008 Sign: digest: 229D5E280E0F0CDF052ADA80A61E2CE3B155F5576E3F69598F70D2458941A12B
2018-08-15 10:03:05.422 UTC [chaincodeCmd] chaincodeInvokeOrQuery -> DEBU 009 ESCC invoke result: version:1 response:<status:200 message:"OK" > payload:"\n \002\371r3\254a\371\364B\014K\000U%\031\253\323%\332\024MF\000,K\274\336\355q\252\300\270\022Y\nE\022\024\n\004lscc\022\014\n\n\n\004mycc\022\002\010\003\022-\n\004mycc\022%\n\007\n\001a\022\002\010\004\n\007\n\001b\022\002\010\004\032\007\n\001a\032\00270\032\010\n\001b\032\003230\032\003\010\310\001\"\013\022\004mycc\032\0031.0" endorsement:<endorser:"\n\007Org1MSP\022\200\006-----BEGIN -----\nMIICGTCCAcCgAwIBAgIRAP3w0ey8IOa63v5lgUiVMKwwCgYIKoZIzj0EAwIwczEL\nMAkGA1UEBhMCVVMxEzARBgNVBAgTCkNhbGlmb3JuaWExFjAUBgNVBAcTDVNhbiBG\ncmFuY2lzY28xGTAXBgNVBAoTEG9yZzEuZXhhbXBsZS5jb20xHDAaBgNVBAMTE2Nh\nLm9yZzEuZXhhbXBsZS5jb20wHhcNMTgwODE1MDk1MzAzWhcNMjgwODEyMDk1MzAz\nWjBbMQswCQYDVQQGEwJVUzETMBEGA1UECBMKQ2FsaWZvcm5pYTEWMBQGA1UEBxMN\nU2FuIEZyYW5jaXNjbzEfMB0GA1UEAxMWcGVlcjAub3JnMS5leGFtcGxlLmNvbTBZ\nMBMGByqGSM49AgEGCCqGSM49AwEHA0IABKZ5P5A2f/khG/PDnnLITek+Ge68+INF\ngNFEbQbkV2y+HzRsw1wHqNeYwzky42PIEq8dRyFj7S9k9aMHGM7o2c+jTTBLMA4G\nA1UdDwEB/wQEAwIHgDAMBgNVHRMBAf8EAjAAMCsGA1UdIwQkMCKAIAcbi91g7ZUn\nn/HoFepObbqvU6YhfxB0A7KrzErC48ZZMAoGCCqGSM49BAMCA0cAMEQCIGoHevzt\nHxSRVXd5aHLjPh+QucG+LlsRAtdAOME2/Ul3AiA6tS0YX5uQBbS1maAig2/rwlmq\nT3UkiSmmvOT0PSAKYQ==\n-----END -----\n" signature:"0D\002 O_9\367\255LK\307+\222(\246\370\335\213g\316\355Rs\371\225|\233qo`y\233\3630\374\002 W.-\207\270\305\363nb\303\273\017:t\007f\220\004t\250n\326\023\254\002ye\370\030\246 \374" >
2018-08-15 10:03:05.423 UTC [chaincodeCmd] chaincodeInvokeOrQuery -> INFO 00a Chaincode invoke successful. result: status:200
再次查询余额
peer chaincode query -C mychannel -n mycc -c '{"Args":["query","a"]}’
2018-08-15 10:03:19.427 UTC [msp] GetLocalMSP -> DEBU 001 Returning existing local MSP
2018-08-15 10:03:19.427 UTC [msp] GetDefaultSigningIdentity -> DEBU 002 Obtaining default signing identity
2018-08-15 10:03:19.427 UTC [chaincodeCmd] checkChaincodeCmdParams -> INFO 003 Using default escc
2018-08-15 10:03:19.427 UTC [chaincodeCmd] checkChaincodeCmdParams -> INFO 004 Using default vscc
2018-08-15 10:03:19.427 UTC [msp/identity] Sign -> DEBU 005 Sign: plaintext: 0A95070A6708031A0C08E7F4CFDB0510...6D7963631A0A0A0571756572790A0161
2018-08-15 10:03:19.427 UTC [msp/identity] Sign -> DEBU 006 Sign: digest: DB72AC91839F2ABAA05EC50CFB67FD681D9F11188468FC6300A78813C0CBCA80
Query Result: 70
2018-08-15 10:03:19.452 UTC [main] main -> INFO 007 Exiting.....
遇到的问题
-
版本问题,从代码到镜像,严格使用1.0的版本
-
不能翻墙的话,会非常痛苦,很多流程走不下去。代理的方式其实不是很方便,vpn的方式感觉会方便很多。
-
明明我在shell里边是可以执行的,但是sh脚本里边就是报错
-
docker挂载文件失败
-
基本都得采用sudo权限