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没有下载下来
- git clone https://github.com/hyperledger/fabric-samples.git
- $ cd ./fabric-samples
- $ git branch -a
- $ git checkout v2.3.0
- 将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_FILE
和CORE_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.com
和 peer0.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