fabric环境搭建

Hyperledger Fabric基础环境之Docker #

Docker 是一个开源的应用容器引擎,基于Go语言并遵从Apache2.0 协议开源。Docker 可以让开发者打包他们的应用以及依赖包到一个轻量级、可移植的容器中,然后发布到任何流行的 Linux 机器上,也可以实现虚拟化。容器是完全使用沙箱机制,相互之间不会有任何接口,更重要的是容器性能开销极低。Docker 从 17.03 版本之后分为 CE(Community Edition: 社区版) 和 EE(Enterprise Edition: 企业版),我们用社区版就可以了。

1.Docker安装与配置 #

使用 Docker 仓库进行安装在新主机上首次安装 Docker Engine-Community 之前,需要设置 Docker 仓库。之后,您可以从仓库安装和更新 Docker 。

使用apt-get命令更新包索引。

sudo apt-get update

使用apt-get命令安装依赖包,用于通过HTTPS来获取仓库。

sudo apt-get install \
    apt-transport-https \
    ca-certificates \
    curl \
    git \
    gnupg-agent \
    software-properties-common

使用curl命令添加 Docker 的官方 GPG 密钥。

curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo apt-key add -

9DC8 5822 9FC7 DD38 854A E2D8 8D81 803C 0EBF CD88 使用以下命令通过搜索指纹的后8个字符,验证您现在是否拥有带有指纹的密钥。

sudo apt-key fingerprint 0EBFCD88
pub   rsa4096 2017-02-22 [SCEA]
      9DC8 5822 9FC7 DD38 854A  E2D8 8D81 803C 0EBF CD88
uid           [ unknown] Docker Release (CE deb) <docker@docker.com>
sub   rsa4096 2017-02-22 [S]

使用以下命令设置稳定版仓库。

sudo add-apt-repository \
   "deb [arch=amd64] https://download.docker.com/linux/ubuntu \
   $(lsb_release -cs) \
   stable"

使用以下命令安装 Docker Engine-Community 和 containerd.io

sudo apt-get update
sudo apt-get install docker-ce docker-ce-cli containerd.io

使用以下命令启动Docker。

sudo systemctl start docker

可选:如果要在系统启动时启动Docker守护程序,请使用以下命令。

sudo systemctl enable docker

使用以下命令将用户添加到Docker组,使得任何用户都有权限使用Docker。

sudo usermod -a -G docker $USER

2.Docker compose安装与配置 #

Compose 是用于定义和运行多容器 Docker 应用程序的工具。通过 Compose,您可以使用 YML 文件来配置应用程序需要的所有服务。然后,使用一个命令,就可以从 YML 文件配置中创建并启动所有服务。

安装Docker Compose,使用以下命令以下载 Docker Compose 的当前最新版本

sudo curl -L "https://github.com/docker/compose/releases/download/1.26.2/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose

使用chmod命令将可执行权限应用于二进制文件。

sudo chmod +x /usr/local/bin/docker-compose

3.给docker设置自己的镜像加速 #

4.测试 #

Docker 允许你在容器内运行应用程序,使用 docker run 命令来在容器内运行一个应用程序输出Hello world。

docker run ubuntu:15.10 /bin/echo "Hello world"
Hello world

各个参数解析:

  • docker: Docker 的二进制执行文件。
  • run: 与前面的 Docker 组合来运行一个容器。
  • ubuntu:15.10: 指定要运行的镜像,Docker 首先从本地主机上查找镜像是否存在,如果不存在,Docker 就会从镜像仓库 Docker Hub 下载公共镜像。
  • /bin/echo "Hello world": 在启动的容器里执行的命令

以上命令完整的意思可以解释为:Docker 以 ubuntu15.10 镜像创建一个新容器,然后在容器里执行 bin/echo "Hello world",然后输出结果。

Hyperledger Fabric 基础环境之Golang #

1.Golang安装与配置 #

Golang是Google开发的一种静态强类型强类型、编译型、并发型,并具有垃圾回收功能的编程语言。Hyperledger Fabric开源平台就是用Golang开发的。

使用以下命令安装Golang,Fabric中链码的编写可以是Golang,JavaScript,Java,我们主要使用Golang来编写。

sudo add-apt-repository ppa:longsleep/golang-backports
sudo apt-get update
sudo apt-get install golang-go

创建GOPATH以及GOROOT路径。

cd ~
mkdir go 

配置Go环境变量,使用Vim打开环境变量配置文件。

安装vim

sudo apt install vim
创建/usr/local/go文件夹
cd /usr/local
sudo mkdir go
cd ~
sudo vim /etc/profile

在文件最后输入一下内容:

export GOROOT=/usr/local/go
export GOPATH=$HOME/go
export GOBIN=$GOPATH/bin
export PATH=$PATH:$GOROOT/bin:$GOBIN

Esc 键退回一般模式,然后输入 :wq 命令并回车保存退出文件。再使用以下命令使变量立即生效。

source /etc/profile

由于Golang的官方代理源速度慢有时候会出现包不能下载的情况,我们使用以下命令把代理源设置为国内的代理源。

go env -w GOPROXY=https://goproxy.cn,direct

使用以下命令查看Golang版本信息。

go version
go1.16.4 linux/amd64

使用以下命令查看Golang环境变量配置。

go env
GO111MODULE="on"
GOARCH="amd64"
GOBIN=""
GOCACHE="/root/.cache/go-build"
GOENV="/root/.config/go/env"
GOEXE=""
GOFLAGS=""
GOHOSTARCH="amd64"
GOHOSTOS="linux"
GONOPROXY=""
GONOSUMDB=""
GOOS="linux"
GOPATH="/root/go"
GOPRIVATE=""
GOPROXY="https://goproxy.cn,direct"
GOROOT="/usr/lib/go-1.13"
GOSUMDB="sum.golang.org"
GOTMPDIR=""
GOTOOLDIR="/usr/lib/go-1.13/pkg/tool/linux_amd64"
GCCGO="gccgo"
AR="ar"
CC="gcc"
CXX="g++"
CGO_ENABLED="1"
GOMOD="/dev/null"
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-build410299436=/tmp/go-build -gno-record-gcc-switches"

2.测试 #

使用以下命令在GOPATH路径下创建测试文件test.go

cd $GOPATH
vim test.go

输入测试文件内容如下:

package main

import "fmt"

func main() {
  fmt.Println("Hello, World!")
}

Esc 键退回一般模式,然后输入 :wq 命令并回车保存退出文件后使用以下命令运行测试文件。

sudo go run test.go        //必须以管理员身份运行  傻逼吧

输出以下结果。

Hello, World!

测试完毕,使用以下命令删除测试文件。

rm test.go

Hyperledger Fabric安装与测试 #

1.安装Fabric #

使用以下命令在根目录下创建目录并进入创建的目录。

cd ~
mkdir hyperledger
cd hyperledger

使用curl命令下载Fabric,不指定版本号默认下载最新版(因网络问题如不成功请重试)。

curl -sSL https://bit.ly/2ysbOFE | bash -s
curl -sSL https://bit.ly/2ysbOFE | bash -s -- 2.3.0 1.4.9

使用ls命令查看当前路径下目录,即下载结果。

ls
fabric-samples 

使用以下命令进入到bin目录查看Fabric的所有工具。

cd fabric-samples/bin
ls
configtxgen    cryptogen  fabric-ca-client  idemixgen  peer
configtxlator  discover   fabric-ca-server  orderer

使用以下命令将所有工具复到/usr/local/bin中,使得在任意目录下都可以使用Fabric的工具。

sudo cp * /usr/local/bin

注意

如果上面的由于网络原因下载不下来

采用如下步骤

cd ~
mkdir hyperledger
cd hyperledger

从git上拉取Hyperledger Fabric 实测用手机热点更快

git clone https://github.com/hyperledger/fabric.git

确定fabric版本-进入fabric的目录

cd fabric
git checkout v2.3.0      //选择版本分支

查看branch的版本

git branch

下载fabric-samples源码

cd scripts
#运行bootstrap.sh
./bootstrap.sh          //这里翻墙比较快  权限不够前面加sudo   有时网络问题会下载失败 多试几次

如果发现有两个镜像文件没有下载下来 bin文件夹里有文件就表示下载下来了

hyperledger-fabric-ca-darwin-amd64-1.4.9.tar.gz

hyperledger-fabric-darwin-amd64-2.3.0.tar.gz

下载上面两个文件

下载的 hyperledger-fabric-darwin-amd64-2.3.0.tar.gz压缩包内有 bin 和 config 两个文件夹,hyperledger-fabric-ca-darwin-amd64-1.4.9.tar.gz压缩包内有 bin 文件夹,将两个 bin 文件夹内的二进制文件汇总在一个 bin 文件夹内。 最后将 bin 和 config 文件夹复制到 fabric-samples文件夹内。

如果fabric-samples没有下载下来

  1. git clone https://github.com/hyperledger/fabric-samples.git
  2. $ cd ./fabric-samples
  3. $ git branch -a
  4. $ git checkout v2.3.0
  5. 将bin和config文件加放入fabric-samples

去github上下载 翻墙

使用以下命令进入到bin目录查看Fabric的所有工具。

cd fabric-samples/bin
ls
configtxgen    cryptogen  fabric-ca-client  idemixgen  peer
configtxlator  discover   fabric-ca-server  orderer

使用以下命令将所有工具复到/usr/local/bin中,使得在任意目录下都可以使用Fabric的工具。

sudo cp * /usr/local/bin

2.测试 #

下载成功后进入官方示例test-network目录。

cd ~/hyperledger/fabric/scripts/fabric-samples/test-network

官方的示例项目是一个有两个组织的网络结构,使用以下命令运行官方示例脚本启动网络。

sudo ./network.sh up

使用以下命令查看容器,可以看到有三个节点已经启动。

sudo docker ps -a
CONTAINER ID        IMAGE                               COMMAND             CREATED             STATUS                  PORTS                              NAMES
8d0c74b9d6af        hyperledger/fabric-orderer:latest   "orderer"           4 seconds ago       Up Less than a second   0.0.0.0:7050->7050/tcp             orderer.example.com
ea1cf82b5b99        hyperledger/fabric-peer:latest      "peer node start"   4 seconds ago       Up Less than a second   0.0.0.0:7051->7051/tcp             peer0.org1.example.com
cd8d9b23cb56        hyperledger/fabric-peer:latest      "peer node start"   4 seconds ago       Up 1 second             7051/tcp, 0.0.0.0:9051->9051/tcp   peer0.org2.example.com

使用network.sh脚本在Org1和Org2之间创建通道,并将其peer节点加入该通道。运行以下命令使用默认的名称mychannel创建频道。

sudo ./network.sh createChannel

下载go依赖包 如果出问题先把整个hyperledger文件夹解除权限限制

cd ~/hyperledger/fabric/scripts/fabric-samples/chaincode/sacc
go mod init 
go env -w GOPROXY=https://goproxy.cn,direct
go mod vendor

在Fabric中,智能合约以称为Chaincode(链码)的软件包部署在网络上。Chaincode安装在组织的peer节点上,然后部署到渠道,然后可以在该渠道中用于认可交易并与区块链分类账进行交互。在将链码部署到通道之前,通道的成员需要就建立链码治理的链码定义达成一致。当所需的组织数目达成一致时,可以将链码定义提交给渠道,并准备使用链码。使用network.sh创建频道后,可以使用以下命令在频道上启动链码,其中-ccl 指定语言版Chaincode。

sudo ./network.sh deployCC -ccn basic -ccp ../asset-transfer-basic/chaincode-go -ccl go

报错:Error: failed to normalize chaincode path: ‘go list’ failed with: go: github.com/golang/protobuf@v1.3.2: Get “https://proxy.golang.org/github.com/golang/protobuf/@v/v1.3.2.mod": dial tcp 216.58.200.49:443: i/o timeout: exit status 1 Chaincode packaging has failed Deploying chaincode failed

解决办法:

cd fabric-samples/asset-transfer-basic/chaincode-go

go env -w GOPROXY=https://goproxy.io,direct

go env -w GO111MODULE=on

go mod vendor

确保您正在从test-network目录进行操作。 如果你按照说明[安装示例,二进制文件和Docker映像, 您可以在fabric-samples代码库的bin文件夹中找到peer二进制文件。 使用以下命令将这些二进制文件添加到您的CLI路径:

export PATH=${PWD}/../bin:$PATH

使用以下命令设置FABRIC_CFG_PATH为指向存储库中的core.yaml文件。

export FABRIC_CFG_PATH=$PWD/../config/

现在使用以下命令设置环境变量,以 Org1的CLI操作,关于环境变量的具体含义与设置,我们将在后面小节详细介绍。

# 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

CORE_PEER_TLS_ROOTCERT_FILECORE_PEER_MSPCONFIGPATH环境变量指向Org1的organizations文件夹中的的加密材料。 如果您使用 ./network.sh deployCC -ccl go 安装和启动 asset-transfer (basic) 链码,您可以调用链码(Go)的 InitLedger 方法来赋予一些账本上的初始资产(如果使用 typescript 或者 javascript,例如 ./network.sh deployCC -l javascript,你会调用相关链码的 initLedger 功能)。

使用以下命令以使用资产初始化分类帐,invoke是调用链码的命令。

peer chaincode invoke -o localhost:7050 --ordererTLSHostnameOverride orderer.example.com --tls --cafile ${PWD}/organizations/ordererOrganizations/example.com/orderers/orderer.example.com/msp/tlscacerts/tlsca.example.com-cert.pem -C mychannel -n basic --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":"InitLedger","Args":[]}'

报错:Cannot run peer because error when setting up MSP of type bccsp from directory /home/tianzhiwei/hyperledger/fabric/scripts/fabric-samples/test-network/organizations/peerOrganizations/org1.example.com/users/Admin@org1.example.com/msp: KeyMaterial not found in SigningIdentityInfo

解决办法:

cd ~/hyperledger

sudo chmod 777 * -R

成功,输出:

-> INFO 001 Chaincode invoke successful. result: status:200

运行以下命令以获取已添加到渠道分类帐的资产列表。

peer chaincode query -C mychannel -n basic -c '{"Args":["GetAllAssets"]}'

如果成功,应该看到以下输出:

[
  {"ID": "asset1", "color": "blue", "size": 5, "owner": "Tomoko", "appraisedValue": 300},
  {"ID": "asset2", "color": "red", "size": 5, "owner": "Brad", "appraisedValue": 400},
  {"ID": "asset3", "color": "green", "size": 10, "owner": "Jin Soo", "appraisedValue": 500},
  {"ID": "asset4", "color": "yellow", "size": 10, "owner": "Max", "appraisedValue": 600},
  {"ID": "asset5", "color": "black", "size": 15, "owner": "Adriana", "appraisedValue": 700},
  {"ID": "asset6", "color": "white", "size": 15, "owner": "Michel", "appraisedValue": 800}
]

当一个网络成员希望在账本上转一些或者改变一些资产,链码会被调用。使用以下的指令来通过调用 asset-transfer (basic) 链码改变账本上的资产所有者:

peer chaincode invoke -o localhost:7050 --ordererTLSHostnameOverride orderer.example.com --tls --cafile ${PWD}/organizations/ordererOrganizations/example.com/orderers/orderer.example.com/msp/tlscacerts/tlsca.example.com-cert.pem -C mychannel -n basic --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":"TransferAsset","Args":["asset6","Christopher"]}'

如果命令成功,您应该看到以下响应:

2019-12-04 17:38:21.048 EST [chaincodeCmd] chaincodeInvokeOrQuery -> INFO 001 Chaincode invoke successful. result: status:200

因为 asset-transfer (basic) 链码的背书策略需要交易同时被 Org1 和 Org2 签名,链码调用指令需要使用 --peerAddresses 标签来指向 peer0.org1.example.compeer0.org2.example.com。因为网络的 TLS 被开启,指令也需要用 --tlsRootCertFiles 标签指向每个 peer 节点的 TLS 证书。

调用链码之后,我们可以使用另一个查询来查看调用如何改变了区块链账本的资产。因为我们已经查询了 Org1 的 peer,我们可以把这个查询链码的机会通过 Org2 的 peer 来运行。设置以下的环境变量来操作 Org2:

# 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 asset-transfer (basic) 链码:

peer chaincode query -C mychannel -n basic -c '{"Args":["ReadAsset","asset6"]}'

结果显示 "asset6" 转给了 Christopher:

{"ID":"asset6","color":"white","size":15,"owner":"Christopher","appraisedValue":800}

测试完毕,关闭网络。

sudo ./network.sh down