介绍
在上一节我们已经介绍完了 configtx.yaml 配置文件,本节我们讲解如何使用该配置文件调用 fabric 提供的 configtxgen 工具生成创世区块。
首先,Orderer 节点在启动时,可以指定使用提前生成的创世区块文件作为系统通道的初始配置,创世区块中包括了排序服务的相关配置信息以及联盟信息。
生成创世区块
因为我们没有使用官方的示例,而是重新开启了一个空的 fabric 项目,因此没有包含创世区块,但是我们可以使用 configtxgen 工具生成一个新的创世区块。
生成的过程需要依赖 configtx.yaml 配置文件,其中 configtx.yaml 配置文件定义了整个网络中相关配置和拓扑结构信息。接下来,我们需要告诉 configtxgen 工具去哪儿找它需要的 configtx.yaml 配置文件。
- 首先我们需要告诉它当前工作的目录
export FABRIC_CFG_PATH=$PWD
- 创建用来存放生成内容的目录
mkdir channel-artifacts
- 生成创世区块
configtxgen -profile TwoOrgsOrdererGenesis -channelID byfn-sys-channel -outputBlock ./channel-artifacts/genesis.block
简单解释下上述命令的含义:
-profile TwoOrgsOrdererGenesis
-profile 指定了使用 configtx.yaml 配置文件中的 Profiles 配置中的哪一个创世区块参数配置,这里使用的是 TwoOrgsOrdererGenesis 配置。
可参考前一篇文章的 Profiles 部分配置,开头第一个配置项就是 TwoOrgsOrdererGenesis,实际上表示的是:与该联盟的创世区块相关的参数配置(由 2 个组织和一个排序服务组成的联盟)。
-channelID byfn-sys-channel
-channelID 指定了系统通道的 ID(即通道的名称),这里指的是默认的系统通道 ID,创建其他区块时使用的就是应用通道了。
-outputBlock ./channel-artifacts/genesis.block
-outputBlock 指定了生成的创世区块的路径和名称,执行完上述命令后,可以在 channel-artifacts 目录下看到 genesis.block 文件,为了方便查看,将创世区块文件的详细内容导入到 json 文件中。
configtxgen -inspectBlock channel-artifacts/genesis.block > channel-artifacts/genesis.block.json
您可以使用cat命令来查看json文件具体的内容:
cat ./channel-artifacts/genesis.block.json
生成通道配置交易
ok,我们已经成功生成了创世区块,接下来,我们可以以创世区块作为应用通道的初始配置来生成通道配置交易。使用以下命令:
configtxgen -profile TwoOrgsChannel -outputCreateChannelTx ./channel-artifacts/channel.tx -channelID mychannel
上述命令和生成创世区块很像,我们只解释不通部分。
-channelID mychannel
指定通道 ID 为 mychannel,这里指的就是应用通道 ID 了(仅在生成创世区块时才会使用默认的系统通道 ID,因为系统中默认保存了它的初始配置项,因此可以直接使用)。
-outputCreateChannelTx ./channle-artifacts/channel.tx
指定生成的通道配置交易路径和名称。
我们有必要深入分析一下 configtx.yaml 中 Profiles 中 TwoOrgsChannel 这一段配置,详细配置如下:
TwoOrgsChannel:
#定义联盟
Consortium: SampleConsortium
#需要实现通道默认定义的能力
<<: *ChannelDefaults
#需要实现应用默认定义的能力
Application:
<<: *ApplicationDefaults
#该联盟中包含组织1和组织2
Organizations:
- *Org1
- *Org2
Capabilities:
<<: *ApplicationCapabilities
TwoOrgsChannle 定义了包含两个组织的通道的详细配置,这两个组织同属于联盟 Sampleconsortium,并且定义了通道能力、应用能力等。我们延伸一个类似的通道定义来解释一下为什么需要通道配置项。
设想一下这样的场景:假设有渔民 A、饭店老板 B 和另一个饭店老板 C,渔民 A 同时向两个饭店供货,从实际角度考虑,渔民 A 卖给两个饭店同样的鱼,但可能卖的价格不同,那渔民 A 肯定不希望它与 B 谈的价格被 C 知道,也不希望它与 C 谈的价格被 B 知道,于是 A 和 B,A 和 C 之间就有了独立通信的需求。
此时我们就可以根据上述场景设计一个联盟,联盟中包含了 A 、 B 和 C 三个组织。然后为 A 和 B 以及 A 和 C 之间分别建立一个用于通信的通道,因为通道具有隔离通信的作用,因此 C 无法获得 A 和 B 的交易信息,B 也无法获得 A 和 C 的交易信息。这样就模拟实现了我们的现实需求,在此我们的自定义网络中,我们可以将 org1、org2、org3 抽象为 A、B、C,因为我们已经在 TwoOrgsChannel 中为 org1 和 org2 建立了通信通道,因此我们只要再为 org2 和 org3 定义一个通道配置即可(这里实际上应该是为 org1 和 org3 定义一个通道配置,因为后面文章用的都是这个配置,所以这里就不做修改了),具体配置如下:
ThreeOrgsChannel:
#定义联盟
Consortium: SampleConsortium
<<: *ChannelDefaults
Application:
<<: *ApplicationDefaults
#该联盟中包含组织 2 和组织 3
Organizations:
- *Org2
- *Org3
Capabilities:
<<: *ApplicationCapabilities
因为我们初始配置中为联盟设置的组织数为 2,因此添加 org3 还需要额外的操作,可以静态或者动态添加,在下面的章节会详细介绍如何静态、动态的向一个网络中添加一个新组织。
生成锚节点的更新配置文件
- 为组织1生成定义锚节点的更新配置文件
configtxgen -profile TwoOrgsChannel -outputAnchorPeersUpdate ./channel-artifacts/Org1MSPanchors.tx -channelID mychannel -asOrg Org1MSP
- 为组织2生成定义锚节点的更新配置文件
configtxgen -profile TwoOrgsChannel -outputAnchorPeersUpdate ./channel-artifacts/Org2MSPanchors.tx -channelID mychannel -asOrg Org2MSP
总结
到此为止,我们已经准备好启动各项服务所需要的文件和配置,接下来我们就开始启动服务(使用 docker 镜像)。