Pinvon's Blog

所见, 所闻, 所思, 所想

Hyperledger

词汇表

  • Anchor Peer(锚节点)

    锚节点是通道中能被所有对等节点探测, 并能与之进行通信的一种对等节点. 通道中的每个成员都有一个(或多个, 以防单点故障)锚节点, 允许属于不同成员身份的节点来发现通道中存在的其他节点.

    注: 网络中的节点.

  • Block(区块)

    在一个通道上, 区块是一组有序交易的集合. 区块往往通过密码学手段(Hash)连接到前一个区块.

  • Chain(链)

    链就是区块经过"哈希连接"结构化的交易日志. 对等节点(peer)从共识服务(order service)接收区块, 并根据背书策略和并发冲突标记区块的交易是否有效, 然后将该区块追加到对等节点文件系统的哈希链上.

  • Chaincode(链码)

    链码是一个运行在账本上的软件, 可以对资产进行编码, 其中的交易指令(或业务逻辑)也可以用来修改资产.

  • Channel(通道)

    通道是构建在"Fabric"网络上的私有区块链, 实现了数据的隔离和保密. 通道特定的账本在通道中是与所有对等节点共享的, 并且交易方必须通过该通道的正确验证才能与账本进行交互. 通道是由一个配置块来定义的.

    注: 有点像局部网络.

  • Commitment(提交)

    一个通道中的每个对等节点都会验证交易的有序区块, 然后将区块提交(写或追加)到该通道上账本的各个副本, 对等节点也会标记每个区块中的每笔交易的状态是有效还是无效.

    注: 采矿成功后, 增加新区块.

  • Concurrency Control Version Check(并发控制版本检查CCVC)

    CCVC是保持通道中各对等节点状态同步的一种方法.

    对等节点并行执行交易, 在交易提交到账本之前(将交易打包成区块添加到区块链之前), 对等节点会检查交易在执行期间读到的数据是否被修改. 执行后要提交, 在这两个事件之间如果数据被改动, 就会引发CCVC冲突, 该交易会被账本中标记为无效, 不会被写入区块链中.

  • Configuration Block(配置区块)

    为系统链或通道定义成员和策略的配置数据. 对某个通道或整个网络的配置修改都将导致生成一个新的配置区块, 并追加到适当的链上.

  • Consensus(共识)

    共识是贯穿整个交易流程的广义术语, 用于产生一个对于排序的同意书和确认构成区块的交易集的正确性.

  • Current State(当前状态)

    ledger的当前状态表示其chain交易log中所有key的最新值.

  • Ordering Service(排序服务或共识服务)

    Ordering Service独立于Peer, 以先到先得的方式为网络上所有的channel做交易排序, 包含与每个Member相关的加密材料.

    Orderer为区块链写入操作提供时序保证, 具体实现可以是共识算法或分布式的消息订阅消费系统(kafka).

简介

分布式账本

去中心化: 在整个区块链网络中, 每个参与者都保存着一个区块链账本的副本.

协作: 所有参与者共同维护着账本.

不可篡改: 加密技术保证交易一旦写入账本, 就无法篡改. 不可篡改性使得信息来源的确认变得容易.

智能合约

区块链网络使用智能合约来实现对账本的访问和控制.

智能合约不仅可用于在区块链网络中打包信息, 还可以用于自动执行参与者定义的特定交易操作. 如, 买卖双方可以定义一个智能合约, 以保证当卖方发货的商品运送到达时, 买方支付的货款会自动转账给卖方.

共识

共识就是保持网络中所有账本交易的同步流程. 它保证了账本只会在交易双方都确认后才进行更新. 同时在账本更新时, 交易双方能够在账本中的相同位置, 更新一个相同的交易信息.

目前, 我们只需把区块链理解为一个共享的, 通过智能合约更新的多副本交易系统, 同时这个系统通过协作共识机制保证了网络中所有账本副本的同步.

Hyperledger Fabric

2015年, Linux基金会启动了Hyperledger项目, 目标是发展跨行业的区块链技术. Hyperledger Fabric是Hyperledger的一个区块链项目.

Hyperledger Fabric需要登录才能加入网络.

通道功能: 允许参与者为交易新建一个单独的账本. 当网络中的一些参与者是竞争对手时, 这个功能尤为重要. 因为这些参与者并不希望所有的交易信息(如给部分客户优惠)都对网络中所有参与者公开. 只有在同一个通道中的参与者, 才会拥有该通道中的账本.

共享账本: Hyperledger Fabric的账本子系统包含世界状态和交易记录. 世界状态组件描述了账本在特定时间点的状态, 它是账本的数据库; 交易记录组件记录了产生世界状态当前值的所有交易, 它是世界状态的更新历史.

智能合约: 在Hyperledger Fabric中称为chaincode. 当一个区块链外部的应用程序需要访问账本时, 就会调用chaincode. 一般情况下, chaincode只会访问账本的世界状态, 不会查询交易记录. 目前使用Go编写chaincode.

快速入门

先决条件

在v1.0.0发行之前, 使用Ubuntu的Vagrant来作为开发环境. 而Docker容器可以为MacOS, Windows, Linux三个平台的开发人员提供一致的体验, 因此, 现在更推荐使用Docker容器进行开发环境的搭建.

本平台为Ubuntu 16.04LTS. 如果是其他系统, 请查看官网的环境搭建

Git安装

Go语言

安装 Go 1.9 或者更后的版本.

首先到官网下载压缩包. 最好选择稳定版本.

仅介绍Ubuntu 16.04 LTS的安装, 其他环境的安装, 请参考官网的安装教程

# 解压至/usr/local目录
sudo tar -C /usr/local -xzf go1.9.4.linux-amd64.tar.gz

# 打开配置
emacs ~/.bashrc

# 将 /usr/local/go/bin 添加到环境变量
export GOROOT=/usr/local/go
export GOPATH=$HOME/go # 配置GOPATH是为了后面需要
export PATH=$GOPATH/bin:$GOROOT/bin:$PATH

# 使配置生效
source ~/.bashrc

测试直接输入 go, 会有一些go命令的说明. 如果有异常, 说明没安装成功.

也可以直接测试文件: 新建文件 test.go, 输入代码:

package main
import "fmt"
func main() {
    fmt.Println("hello world")
}

运行:

go run test.go

如果出现"hello world", 则说明安装成功.

Docker

Docker是一个容器, 在这个容器中, 我们可以运行我们的实例. 可以把Docker大致当成一个虚拟机, 但是Docker不需要占用那么多空间.

每个Docker将在本地运行一个与Hyperledger网络相关的服务.

可以使用CLI或终端来安装Docker, 这边我们需要安装两个包: docker-engine和docker-compose.

docker-engine: 基础包, 它使得docker容器需要的所有必须的文件正常运行.

docker-compose: 用于配置Docker.

Ubuntu可以通过Docker官方提供的脚本进行安装:

curl -sSL https://get.docker.com | sh

修改Docker配置文件 /etc/default/docker, 增加Docker的socket绑定, 运行在Docker中的进程都能通过映射的Socket调用Docker的API执行镜像编译和创建容器等操作.

DOCKER_OPTS="-s=aufs -r=true --api-cors-header='*' -H tcp://0.0.0.0:2375 -H unix:///var/run/docker.sock"

重启Docker服务, 使得配置生效:

sudo service docker restart

配置Docker国内镜像, 使下载速度更快. 修改 /etc/default/docker:

DOCKER_OPTS="-s=aufs -r=true --api-cors-header='*' -H tcp://0.0.0.0:2375 -H unix:///var/run/docker.sock --registry-mirror=https://registry.docker-cn.com"

也可以把镜像地址改成阿里云的, DaoCloud等的地址. 配置完后再重启一次服务.

docker compose能够在一个主机上创建出相互隔离的网络, 通过命令行管理多个docker容器, 快速启动, 停止和更新容器. 安装方法很多, 这边通过pip安装:

# 先安装pip
sudo apt install python-pip
sudo apt install docker-compose

docker常用命令:

命令 举例 说明
docker images docker images 查看主机上的镜像文件列表
docker pull docker pull hyperledger/fabric-peer 从镜像仓库中下载镜像文件
docker tag docker tag hyperledger/fabric-tools:x86_64-1.0.0 hyperledger/fabric-tools:latest 给镜像文件打标签, x86_64-1.0.0标记为latest
docker run docker run -it --name cli ubuntu /bin/bash 从镜像中启动容器. cli是容器名, ubuntu是镜像名, -it是以交互方式启动, /bin/bash是启动容器时执行的命令
docker logs docker logs -f cli 查看容器日志
docker ps docker ps -a 查看主机上的容器, -a会显示已经停止的容器
docker port docker port peer0.org1.example.com 查看容器映射的端口
docker rm docker rm cli 删除容器

docker-compose常用命令:

命令 举例 说明
docker-compose up docker-compose -f docker-compose-cli.yaml up -d 根据配置文件.yaml启动容器. -f指定配置文件, -d设置后台运行
docker-compose down docker-compose -f docker-compose-cli.yaml down 停止配置文件中的容器
docker-compose pull docker-compose -f docker-compose-cli.yaml pull 批量下载所需的镜像文件

安装Hyperledger Fabric

创建GOPATH

mkdir -p $GOPATH

cd $GOPATH
mkdir src
cd src
mkdir github.com
cd github.com
mkdir hyperledger
cd hyperledger

获取Fabric源码

在hyperledger目录下, 执行如下命令:

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

安装Go相关库

安装必要工具:

sudo apt install libtool libltdl-dev

如果直接使用 make docker, 在国内会碰到许多错误, 比如编译golint时因为下载超时报错. 这是因为hyperledger fabric是使用go语言编写的, 需要依赖一些工具或者第三方库, 但是因为谷歌有些东西被墙了, 所以要自己手动下载并安装.

mkdir -p $GOPATH/src/golang.org/x
cd $GOPATH/src/golang.org/x
git clone https://github.com/golang/tools.git

# 下载完成后执行以下命令
go get github.com/kardianos/govendor
go get github.com/golang/lint/golint
go get golang.org/x/tools/cmd/goimports
go get github.com/onsi/ginkgo/ginkgo
go get github.com/axw/gocov/...
go get github.com/client9/misspell/cmd/misspell
go get github.com/AlekSi/gocov-xml
go get github.com/golang/protobuf/protoc-gen-go

如果出现如下问题:

5.png

说明当前用户没有权限来运行docker. 执行以下语句:

sudo usermod -aG docker $USER
# 重启

Orderer节点的编译

Orderer节点容器里面运行的是Orderer服务, 要想生成Orderer镜像, 就需要先编译出Orderer程序.

make orderer

Peer节点的编译

Chaincode运行在Peer所在的机器上, 需要给Chaincode准备运行的基础环境, 即ccenv和javaenv两个镜像. 由于被墙, 需要先将之前go的工具拷贝进来.

mkdir -p build/docker/gotools/bin/
cp $GOPATH/src/bin/* ./build/docker/gotools/bin/
make peer

成功之后显示如下: 7.png

使用命令 docker image 可查看已安装的镜像文件.

现在, 可以进入 example/e2e_cli, 使用脚本, 一键启动程序.

# 开启
./network_setup.sh up [channel-id is optional]

# 关闭
./network_setup.sh down

为了加快部署过程, hyperledger提供了一个脚本来执行所有任务. 该脚本会生成配置结果, 本地网络, Chaincode测试.

进入 examples/e2e_cli 目录, 从Docker Hub获取镜像:

# 使脚本可执行
chmod +x download-dockerimages.sh

# 执行脚本
./download-dockerimages.sh

编译Fabric工具

configtxgen工具用来配置Fabric的通道. 它的配置参数主要由 configtx.yaml 文件提供.

cryptogen工具可以快速地根据配置自动批量生成所需要的密钥及证书文件. 它的配置参数主要由 crypto-config.yaml 文件提供.

fabric 目录下, 编译 configtxgen:

make configtxgen

如果出现下图所示的提示, 说明编译成功. 3.png

编译后的执行文件放在 fabric/build/bin/configtxgen.

如果出现 find: `/src/github.com/hyperledger/fabric/core/chaincode/shim': 没有那个文件或目录, 说明 GOPATH 没有配置好, 或者配置了之后没有 source ~/.bashrc.

cryptogen工具的编译方式也一样:

make cryptogen

编译 configtxlator:

make configxlator

Docker镜像

前面只是生成了Fabric的二进制文件, 不能直接使用. 需要将这些文件打包到Docker镜像中.

# 生成Orderer镜像
make orderer-docker

# 生成Peer镜像
make peer-docker

# fabric-tools镜像
make tools-docker

# 查看docker镜像文件
docker images

其他Docker镜像

CouchDB做状态数据库, Kafka做共识, Zookeeper做Kafka的高可用支持. 直接使用以下命令生成:

make docker

运行

configtxgen工具会生成两个内容: Orderer的bootstrap block和Fabric的channel configuration transaction.

orderer block: ordering服务的创世区块(第一个区块).

channel transaction: 在 create channel 时会被广播给orderer.

configtx.yaml: 给出网络的定义, 拓扑结构.

crypto-config目录: 包含每个实体的admin证书, ca证书, 签名证书, 私钥等.

generateArtifacts.sh: 该脚本自动为我们生成启动网络所需的配置及创世区块. 如果之前使用过 network_setup.sh, 则先将 channel-artifact目录 里的可见文件都删除, 隐藏文件不用删, 再将 crypto-config 目录直接删除.

生成通道的区块和配置:

cd examples/e2e_cli
./generateArtifacts.sh

成功后会有类似如下的输出: 4.png

启动网络:

cd examples/e2e_cli
./network_setup.sh up [channel-id-optional]

出现如下界面, 说明网络启动运行, 并测试成功:

8.png

停止网络有两种方法:

第一种:

# 新开一个终端, 进入examples/e2e_cli
rm -f $(docker ps -aq)

# 查看镜像
docker images

# 将dev-peerx.orgx.example字样的镜像文件删除
# 输入其image id的前6位
docker rmi -f 07032a eb54b1 a9ad47

# 删除配置结果
rm ./ channel-artifacts/*.tx
rm -rf crypto-config

第二种:

./network_setup.sh down
# 该命令会自动删除启动网络时生成的镜像文件和配置文件

手动运行

之前是使用脚本一键启动, 关闭. 我们可以手动来做一遍, 这样就明白背后发生了什么事.

进入 examples/e2e_cli 目录.

打开 docker-compose-cli.yaml, 找到启动 script.sh 的语句, 注释掉.

working_dir: /opt/gopath/src/github.com/hyperledger/fabric/peer
# command: /bin/bash -c './scripts/script.sh ${CHANNEL_NAME}; sleep $TIMEOUT'

启动网络

docker-compose -f docker-compose-cli.yaml up

创建Channel

Channel在逻辑上将我们自己编写的Chaincode与其他的Chaincode区分开来.

进入Cli镜像:

docker exec -it cli bash

仅以peer0节点为例, 修改环境变量:


Having all peers join the channel...
CORE_PEER_TLS_ROOTCERT_FILE=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org1.example.com/peers/peer0.org1.example.com/tls/ca.crt
CORE_PEER_TLS_KEY_FILE=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org1.example.com/peers/peer0.org1.example.com/tls/server.key
CORE_PEER_LOCALMSPID=Org1MSP
CORE_VM_ENDPOINT=unix:///host/var/run/docker.sock
CORE_PEER_TLS_CERT_FILE=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org1.example.com/peers/peer0.org1.example.com/tls/server.crt
CORE_PEER_TLS_ENABLED=true
CORE_PEER_MSPCONFIGPATH=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org1.example.com/users/Admin@org1.example.com/msp
CORE_PEER_ID=cli
CORE_LOGGING_LEVEL=DEBUG
CORE_PEER_ADDRESS=peer0.org1.example.com:7051

Comments

使用 Disqus 评论
comments powered by Disqus