1.Fabric基本架构与相关术语
Hyperledger基本架构如下图所示,包括三大类:会员制、区块链与链上代码。
会员制服务负责管理的是网络上的身份识别、隐私与机密。参与者通过注册来获取身份,然后属性授权机构才能发放密匙来进行交易。
区块链服务负责管理分布式账本,通过在超文本传输协议2.0建立的P2P协议进行。通过拜占庭容错算法来处理错误,通过崩溃容忍来处理延误与中断,或借助工作量证明方案来应对审查。
链上代码则是以一个去中心化的交易程序,在验证节点上进行,同时使用Docker来存放链上代码。
Channel - 通道
通道是构建在“Fabric”网络上的私有区块链,实现了数据的隔离和保密。通道特定的账本在通道 中是与所有对等节点共享的,并且交易方必须通过该通道的正确验证才能与账本逬行交互。通道 是由一个“配置块”来定义的。
Endorsement - 背书
Endorsement是指一个peer执行一个交易并返回YES-N0给生成交易proposal的client app的过程。Chaincode具有相应的endorsement policies,其中指指定了endorsing peer(即某一节点为此次交易做担保)。
Fabric-ca - 证书节点
Fabric-ca是默认的证书管理组件,它向网络成员及其用户颁发基于PKI的证书。CA为每个成员颁发一个根证书(rootCert),为每个授权用户颁发一个注册证书(eCert),为每个注册证书颁发大量交易证书(tCerts)。
Anchor Peer – 锚节点
锚节点是通道中能被所有对等节点探测、并能与之进行通信的一种对等节点。通道中的每个成员都有一个(或多个,以防单点故障)锚节点,允许属于不同成员身份的节点来发现通道中存在的其它节点。
Leading Peer – 主导节点
每一个Member在其订阅的channel上可以拥有多个peer,其中一个peer会作为channel的leading peer代表该Member与ordering service通信。Ordering service将block传递给leading peer,该peer再将此block分发给同一member下的其他peer。
Membership Service Provider – MSP
MSP是指为client和peer提供证书的系统抽象组件。Client用证书来认证他们的交易;peer用证书认证其交易背书。该接口与系统的交易处理组件密切相关,旨在使已定义的成员身份服务组件以这种方式顺利插入而不会修改系统的交易处理组件的核心。
2.Fabric网络搭建
- 2.1 生成Fabric网络
进入目录/fabric-samples/first-network下:
cd ~/hyperledger-fabric/fabric-samples/first-network/
./byfn.sh -m generate
自动化脚本 byfn.sh 可以自动帮我们创建网络环境运行时所需的所有内容,但在一些特定情况之下,我们根据不同的需求需要自定义一些设置。
- 2.2 生成组织结构与身份证书
在 /fabric-samples/first-network 目录下执行:
../bin/cryptogen generate --config=./crypto-config.yaml
得到如下输出:
org1.example.com
org2.example.com
配置文件 crypto-config.yaml 生成 Hyperledger Fabric 网络环境中所需的组织结构及身份证书信息,组织中的成员提供节点服务,相应的证书代表身份,可以在实体间进行通信以及交易时进行签名与验证。其配置文件包含有如下内容:
OrdererOrgs:
- Name: Orderer # Orderer的名称
Domain: Example Domain # 域名
Specs:
- Hostname: orderer # hostname + Domain的值组成Orderer节点的完整域名
PeerOrgs:
- Name: Org1
Domain: org1.example.com
EnableNodeOUs: true # 在msp下生成config.yaml文件
Template:
Count: 2
Users:
Count: 1
- Name: Org2
Domain: org2.example.com
EnableNodeOUs: true
Template:
Count: 2
Users:
Count: 1
该配置文件指定了 OrdererOrgs 及 PeerOrgs 两个组织信息。在 PeerOrgs 配置信息中指定了 Org1 与 Org2 两个组织。每个组织使用Template属性下的 Count 指定了两个节点,Users属性下的 Count 指定了一个用户。
证书和密钥(即MSP材料)将被输出到当前一个名为 crypto-config 的目录中,该目录下有两个子目录:
ordererOrganizations:子目录下包括构成 Orderer 组织(1个 Orderer 节点)的身份信息;
peerOrganizations:子目录下为所有的 Peer 节点组织(2个组织,4个节点)的相关身份信息。其中最关键的是 MSP 目录,代表了实体的身份信息。
- 2.3 生成初始区块
在 fabric-samples/first-network 目录下创建 Orderer 服务启动初始区,指定使用configtx.yaml 文件中定义的 TwoOrgsOrdererGenesis 模板,,生成 Orderer 服务系统通道的初始区块文件。
../bin/configtxgen -profile TwoOrgsOrdererGenesis-outputBlock ./channel-artifacts/genesis.block
configtx.yaml 文件用于创建服务启动初始区块及应用通道交易配置文件,同时指定了指定 Orderer 服务的相关配置以及当前的联盟信息
configtx.yaml 配置文件内容如下:
Organizations:
- &OrdererOrg
Name: OrdererOrg
ID: OrdererMSP
MSPDir: crypto-config/ordererOrganizations/example.com/msp
- &Org1
Name: Org1MSP
ID: Org1MSP
MSPDir: crypto-config/peerOrganizations/org1.example.com/msp
AnchorPeers:
- Host: peer0.org1.example.com
Port: 7051
- &Org2
Name: Org2MSP
ID: Org2MSP
MSPDir: crypto-config/peerOrganizations/org2.example.com/msp
AnchorPeers:
- Host: peer0.org2.example.com
Port: 7051
Capabilities:
Global: &ChannelCapabilities
V1_1: true
Orderer: &OrdererCapabilities
V1_1: true
Application: &ApplicationCapabilities
V1_2: true
Application: &ApplicationDefaults
Organizations:
Orderer: &OrdererDefaults
OrdererType: solo
Addresses:
- orderer.example.com:7050
BatchTimeout: 2s
BatchSize:
MaxMessageCount: 10
AbsoluteMaxBytes: 99 MB
PreferredMaxBytes: 512 KB
Kafka:
Brokers:
- 127.0.0.1:9092
Organizations:
Profiles:
TwoOrgsOrdererGenesis:
Capabilities:
<<: *ChannelCapabilities
Orderer:
<<: *OrdererDefaults
Organizations:
- *OrdererOrg
Capabilities:
<<: *OrdererCapabilities
Consortiums:
SampleConsortium:
Organizations:
- *Org1
- *Org2
TwoOrgsChannel:
Consortium: SampleConsortium
Application:
<<: *ApplicationDefaults
Organizations:
- *Org1
- *Org2
Capabilities:
<<: *ApplicationCapabilities
该配置文件中由 Organizations 定义了三个成员 Orderer Org、Org1、Org2,并且设置每个成员的 MSP 目录的位置,从而允许在 orderer genesis 块中存储每个 Org 的根证书。通过这些信息实现与Orderer 服务通信的任何网络实体都可以验证其数字签名。而且为每个 PeerOrg 指定了相应的锚节点(Org1 组织中 peer0.org1.example.com 与 Org2 组织中peer0.org2.example.com)。
Orderer部分指定了Orderer节点的信息:
- OrdererType 指定了共识排序服务的实现方式,有两种选择(solo 及 Kafka);
- Addresses 指定了 Orderer 节点的服务地址与端口号;
- BatchSize 指定了批处理大小,如最大交易数量,最大字节数及建议字节数。
Profiles 部分指定了两个模板:
- TwoOrgsOrdererGenesis 模板用来生成Orderer服务的初始区块文件;
- TwoOrgsChannel 模板用来生成应用通道交易配置文件。
- 2.4 生成应用通道的配置信息
指定通道名称的环境变量:
export CHANNEL_NAME=mychannel
指定使用 configtx.yaml 配置文件中的 TwoOrgsChannel 模板, 来生成新建通道的配置交易文件, TwoOrgsChannel 模板指定了 Org1 和 Org2 都属于后面新建的应用通道。
../bin/configtxgen -profile TwoOrgsChannel -outputCreateChannelTx ./channel-artifacts/channel.tx -channelID $CHANNEL_NAME
- 2.5 生成锚节点配置更新文件
同样基于 configtx.yaml 配置文件中的 TwoOrgsChannel 模板,为每个组织分别生成锚节点更新配置,且注意指定对应的组织名称。
../bin/configtxgen -profile TwoOrgsChannel -outputAnchorPeersUpdate ./channel-artifacts/Org1MSPanchors.tx -channelID $CHANNEL_NAME -asOrg Org1MSP
../bin/configtxgen -profile TwoOrgsChannel -outputAnchorPeersUpdate ./channel-artifacts/Org2MSPanchors.tx -channelID $CHANNEL_NAME -asOrg Org2MSP
- 2.6 启动Fabric网络
使用 docker-compose 这个工具个来实现一步到位的节点容器管理,控制提供网络服务的各个节点,实现方式只需要编写相应的配置文件即可。Hyperledger Fabric 同样给我们提供了一个 docker-compose 工具的示例配置文件,该配置文件在 fabric-samples/first-network 目录下,文件名称: docker-compose-cli.yaml, 该配置文件中指定了网络中各个节点容器(共计六个容器,一个Orderer,属于两个 Orgs 组织的四个 Peer,还有一个 CLI)的信息。
在启动 Hyperledger Fabric 网络中所有节点前,需要注释掉cli中command这一行,我们不需要CLI启动的时候自动执行脚本,而是手动执行。
# command: /bin/bash -c './scripts/script.sh ${CHANNEL_NAME}; sleep $TIMEOUT' volumes
启动网络:
docker-compose -f docker-compose-cli.yaml up -d
得到如下结果:
关闭网络的命令为:
docker-compose -f docker-compose-cli.yaml down
参数说明:
-f: 指定启动容器时用所使用的 docker-compose 配置文件;
-d: 指定是否显示网络启动过程中的实时日志信息,如果需要查看详细网络启动日志,则可以不提供此参数。
- 2.7 创建通道
1. 进入 Docker cli 容器:
docker exec -it cli bash
结果如下:
其中 @ 符号后面的内容根据不同的设备会显示不同的内容。
2. 设置环境变量
export CHANNEL_NAME=mychannel
3.创建通道
peer channel create -o orderer.example.com:7050 -c $CHANNEL_NAME -f ./channel-artifacts/channel.tx --tls --cafile /opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/ordererOrganizations/example.com/orderers/orderer.example.com/msp/tlscacerts/tlsca.example.com-cert.pem
该命令执行后,会自动在本地生成一个与应用通道名称同名的初始区块 mychannel.block, 网络节点只有拥有该文件才可以加入创建的应用通道中。
参数说明:
-o: 指定 orderer 节点的地址;
-c: 指定要创建的应用通道的名称(须与在创建应用通道交易配置文件时的通道名称一致);
-f: 指定创建应用通道时所使用的应用通道交易配置文件;
--tls: 开启 TLS 验证;
--cafile: 指定 TLS_CA 证书的所在路径;
执行代码出现如下结果:
Error: got unexpected status: BAD_REQUEST -- error authorizing update: error validating ReadSet: readset expected key [Group]
/Channel/Application at version 0, but got version 1
出现如上错误,说明指定的通道名称已经在当前处于运行状态的 Fabric 网络中存在,需要退出 docker 容器,删除docker 中正在运行的镜像,重启网络:
exit #退出docker
docker rm $(docker ps -aq) #清除镜像
./byfn.sh -m down
./byfn.sh -m generate
docker-compose -f docker-compose-cli.yaml up -d
- 2.8 将节点加入通道
在docker-composer-cli.yaml文件中,CLI默认连接的是peer0.org1,那么我们要将这个Peer加入mychannel就很简单,只需要运行如下命令:
peer channel join -b mychannel.block
得到如下结果:
修改CLI的环境变量,使其指向另外的Peer,将其他节点加入网络:
peer1.org1:
CORE_PEER_LOCALMSPID="Org1MSP"
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_MSPCONFIGPATH=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org1.example.com/users/Admin@org1.example.com/msp
CORE_PEER_ADDRESS=peer1.org1.example.com:7051
peer channel join -b mychannel.block
peer0.org2:
CORE_PEER_LOCALMSPID="Org2MSP"
CORE_PEER_TLS_ROOTCERT_FILE=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org2.example.com/peers/peer0.org2.example.com/tls/ca.crt
CORE_PEER_MSPCONFIGPATH=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org2.example.com/users/Admin@org2.example.com/msp
CORE_PEER_ADDRESS=peer0.org2.example.com:7051
peer channel join -b mychannel.block
peer1.org2:
CORE_PEER_LOCALMSPID="Org2MSP"
CORE_PEER_TLS_ROOTCERT_FILE=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org2.example.com/peers/peer1.org2.example.com/tls/ca.crt
CORE_PEER_MSPCONFIGPATH=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org2.example.com/users/Admin@org2.example.com/msp
CORE_PEER_ADDRESS=peer1.org2.example.com:7051
peer channel join -b mychannel.block
得到如下的Fabric网络拓扑图:
- 2.9 更新锚节点
对于Org1来说,peer0.org1是锚节点,我们需要连接上它并更新锚节点:
CORE_PEER_LOCALMSPID="Org1MSP"
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_MSPCONFIGPATH=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org1.example.com/users/Admin@org1.example.com/msp
CORE_PEER_ADDRESS=peer0.org1.example.com:7051
peer channel update -o orderer.example.com:7050 -c $CHANNEL_NAME -f ./channel-artifacts/Org1MSPanchors.tx --tls --cafile /opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/ordererOrganizations/example.com/orderers/orderer.example.com/msp/tlscacerts/tlsca.example.com-cert.pem
另外对于Org2,peer0.org2是锚节点,对应的更新代码是:
CORE_PEER_LOCALMSPID="Org2MSP"
CORE_PEER_TLS_ROOTCERT_FILE=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org2.example.com/peers/peer0.org2.example.com/tls/ca.crt
CORE_PEER_MSPCONFIGPATH=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org2.example.com/users/Admin@org2.example.com/msp
CORE_PEER_ADDRESS=peer0.org2.example.com:7051
peer channel update -o orderer.example.com:7050 -c $CHANNEL_NAME -f ./channel-artifacts/Org2MSPanchors.tx --tls --cafile /opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/ordererOrganizations/example.com/orderers/orderer.example.com/msp/tlscacerts/tlsca.example.com-cert.pem