美文网首页Hyperledger Fabric源码分析
Fabric源码分析-生成Channel文件

Fabric源码分析-生成Channel文件

作者: 史圣杰 | 来源:发表于2018-12-25 15:38 被阅读0次

    Channel提供了多账本的功能,我们创建Channel时首先就是要配置联盟和Channel中包含的组织,之后使用configtxgen生成Channel文件,这个文件内部其实就是创建账本所需要的配置更新。

    1.使用

    从fabric源码中复制一份configtx,对其进行修改

    cp $GOPATH/src/github.com/hyperledger/fabric/sampleconfig/configtx.yaml .
    

    设置一个生成Channe的配置,OrdererOrg/CoreOrg/SupplierOrg/BankOrg需要进行配置,在此省略

    TestTwoOrgsChannel:
            Consortium: SampleConsortium
            Application:
                Organizations:
                    - *CoreOrg
                    - *SupplierOrg
                    - *BankOrg
    

    最后,使用下面的命令就可以生成创世块了

    configtxgen -profile TestTwoOrgsChannel -outputCreateChannelTx ./mychannel.tx -channelID mychannel
    

    2.程序分析

    configtxgen的程序在common/tools/configtxgen/main.go中,主要的功能是获取配置文件,生成ConfigUpdate,包装为一个ConfigUpdate的交易并写入文件。主流程是:

    1. factory.InitFactories(nil) 初始化BCCSP,用来为加密提供服务。
    2. 获取指定profile的配置,将其序列化为Profile类型。
    3. 我们设置了outputChannelCreateTx,因此会执行doOutputChannelCreateTx方法。
    4. 创建一个用来创建Channel的交易,将其写入文件。

    2.1 创建Channel的交易文件

    有了Profile配置,首先创建一个ConfigUpdate,将其包装到ConfigUpdateEnvelope中,之后序列化作为Data,添加Header后形成Payload,最后添加签名,封装为Envelope并返回。


    channeltx的内容

    因此,我们需要将主要逻辑聚焦于ConfigUpdate的内容。

    2.2 ConfigGroup

    NewChannelCreateConfigUpdate方法会生成一个ConfigUpdate,ConfigUpdate会被发送到orderer来创建一个新的Channel,该方法根据指定的profile的配置中的Application,创建Application的ConfigGroup,ConfigGroup可以理解为一个配置树型,Application中包含了Organizations,Organizations中是三个Org,因此,最终会形成一个Application的配置树。ConfigGroup的结构可以参考ConfigGroup,Application的Groups中是组织的配置,在NewApplicationOrgGroup中,会对Org的配置组装,读取并验证MSP的相关证书。

    2.3 ConfigUpdate

    上面只是将配置转化为ConfigGroup组成的配置树,接下来就是计算ConfigUpdate了,也就是计算配置有那些更新。计算的程序如下,首先会创建一个新的ConfigGroup,其Groups子配置有一个Application,对应这我们之前生成的Application的Config,这是因为在TestTwoOrgsChannel中,Application是作为一个子级,需要将其放在一个Root配置下。

    newChannelGroup = &cb.ConfigGroup{
      Groups: map[string]*cb.ConfigGroup{
        channelconfig.ApplicationGroupKey: ag,
      },
    }
    
    template = proto.Clone(newChannelGroup).(*cb.ConfigGroup)
    template.Groups[channelconfig.ApplicationGroupKey].Values = nil
    template.Groups[channelconfig.ApplicationGroupKey].Policies = nil
    

    之后,克隆了一份新创建的ConfigGroup,将其Application的子ConfigGroup的Value和Policy设置为nil,之前我们在2.2节构造ConfigGroup时,ConfigGroup会设置默认的一些Ploicy,如果配置了Capabilities,已经设置Value

    addImplicitMetaPolicyDefaults(applicationGroup)
    
    if len(conf.Capabilities) > 0 {
      addValue(applicationGroup, channelconfig.CapabilitiesValue(conf.Capabilities), channelconfig.AdminsPolicyKey)
    }
    

    template的修改势必会造成配置发生变化,因此下一步就是计算两个ConfigGroup的更新了,我们以template作为原来的配置,newChannelGroup最为更新之后的配置,计算哪些配置发生了更新。虽然这里我们还容易看出来发生了那些变化,但是为了统一处理,还是进行了计算(如果设置了orderingSystemChannelGroup的话,template的方式就不是这么简单的克隆后修改了)。

    计算方法

    主要是遍历原ConfigGroup的Policy,Value和ConfigGroup,将未发生变化的部分保存到sameSet,发送变化后的配置保存到writeSet中且版本号加1。最后,如果未发生变化,返回的ConfigUpdate的ReadSet和WriteSet均为nil,如果发生了变化,将sameSet分别赋值给ReadSet和WriteSet,保证未发生变化的部分在两个Set中都存在。这样我们就知道了发生变化前后的配置。
    根据之前template的生成方式,我们可以查看最后的读写集合


    ConfigUpdate

    在上图中,ReadSet的Application的version为0,WriteSet中version为1,说明发生了变化,通过观察,我们看到ConfigGroup的Policies发生了变化,这与template的修改相符合。其实最终的ConfigUpdate就是要通知,Application的Policy发生了变化,如果设置了某些配置参数的话,Value也会发生变化。

    计算出来ConfigUpdate,最后封装为Envelope后,写入文件中,整个流程就结束了。

    相关文章

      网友评论

        本文标题:Fabric源码分析-生成Channel文件

        本文链接:https://www.haomeiwen.com/subject/vsxxlqtx.html