本节主要基于fabric-samples/basic-network分析。查看generate.sh
这个脚本,里面主要执行了如下四个命令1
2
3
4
5
6
7
8
9
10
11// 生成msp模块需要的证书
cryptogen generate --config=./crypto-config.yaml
// 生成创世块
configtxgen -profile OneOrgOrdererGenesis -outputBlock ./config/genesis.block
// 生成创建channel的配置
configtxgen -profile OneOrgChannel -outputCreateChannelTx ./config/channel.tx -channelID $CHANNEL_NAME
// 生成设置anchor节点的配置
configtxgen -profile OneOrgChannel -outputAnchorPeersUpdate ./config/Org1MSPanchors.tx -channelID $CHANNEL_NAME -asOrg Org1MSP
cryptogen
和configtxgen
分别用于加密和配置的工具,其代码路径为hyperledger/fabric/common/tools/cryptogen
和hyperledger/fabric/common/tools/configtxgen
。cryptogen产生了各级msp,在peer,orderer里皆有用到,包括后面介绍的configtxgen里包含msp信息这些也是由此产生。这里暂且不展开分析。
在configtxgen/main.go
里,依然使用viper作为命令行管理工具。代码比较直观,阅读简单不展开分析,感兴趣可以参考Hyperledger Fabric(V1.2)源码深度解析-configtxgen命令解析,写的比较概述。其中读取配置文件的common/tools/configtxgen/localconfig/config.go#Load
方法里,主要由以下几行1
2
3
4const Prefix string = "CONFIGTX"
var configName = strings.ToLower(Prefix)
viper.SetConfigName(configName)
可见,默认读取的是当前目录的configtx.yaml
配置文件。生成创世块和创建channel的配置对应的分别是doOutputBlock
和doOutputChannelCreateTx
这两个方法。doOutputBlock
生成cb.Block
对象,这个对象通过ioutil.WriteFile(outputBlock, utils.MarshalOrPanic(genesisBlock), 0644)
写到指定的genesis.block
这个文件。这个对象可以使用configtxgen -inspectBlock genesis.block
这个命令查看。生成的JSON格式文件可参见JSON结构。其中ChannelHeaderType设置为HeaderType_CONFIG,block.number为0,previousHash为nil。payload里主要是ConfigGroup对象,包含有序号sequence,以及channel_group对象。channel_group主要是Consortium(包含version,policies,configtx.yaml里定义的orgs,此处orgs里又包含MSP和policies)和Orderer(包含policies,msp)。同时ConfigGroup还包含OrdererAddress,hashAlgorithm,BlockDataHashiungStructure这些。从中,还可以看出,每一级的设置,都包含不同的polocies。
doOutputChannelCreateTx
生成cb.Envelope
对象,写到channel.tx
。ChannelHeaderType设置为HeaderType_CONFIG_UPDATE,channel_id为命令后参数$CHANNEL_NAME。payload里是cb.ConfigUpdateEnvelope
对象,包含channel_id, read_set, write_set. 这里,read_set里policies为空,version为0;write_set里version为1,并且定义了policies。所以当使用该channel.tx文件再次创建已经存在的channel时,会报错verifyReadset失败。同样的可以用configtxgen --inspectChannelCreateTx channel.tx
这个命令查看其JSON结构。
查看start.sh
脚本,实际上在peer节点使用Admin角色执行了创建channel命令。peer channel create -o orderer.example.com:7050 -c mychannel -f /etc/hyperledger/configtx/channel.tx
。当顺利执行后,结果返回一个当前channel的首个block,名称为${CHANNEL_NAME}.block
。这里block的number为0,pre_hash为null,channel_header里的channel_id是当前channel名称,ChannelHeaderType还是HeaderType_CONFIG。这里因为使用了Admin角色创建,因此signature_header里记录了creator的信息。而payload同时包含了创世块genesis.block和创建channel配置文件channel.tx的信息,特别的是,里面last_update字段则完整记录了channel.tx
。同样的可以用configtxgen -inspectBlock ${CHANNEL_NAME}.block
这个命令查看其JSON结构。这个区块在start.sh
脚本里后续用于channel join -b mychannel.block
将节点加入到该channel。