在这个教程中,我们将介绍如何使用fabric-config库进行通道配置的更新。 我们将提供一个基于fabric-config的示例程序,该程序可以更改Hyperledger Fabric的块切割参数。此外,教程还包括如何开始使用fabric-config库和函数 的指南,以便你可以在项目中快速增加通道配置功能。
1、通道配置概述
Hyperledger Fabric网络由一些数据结构和过程构成,它们以及定义了如何与区块链 网络进行交互。其中,数据结构包括组织、对等节点、身份凭证、排序节点和CA等。
标识数据结构及其相应过程(即用于网络交互的管理指令)的数据包含在通道配置中。 这些配置又可以在已提交给通道帐本的区块中找到。因此,用于修改通道配置的过程 称为配置更新事务。下面列举了有关通道配置更新的一些常见需求:
- 更新一个区块中可以包含的最大交易数量。
- 更新在第一个交易到达之后切割区块之前需要继续等待交易的时间。
- 更新Raft排序服务参数。
- 更新区块签名的有效性要求。
- 将新组织添加到已有的通道。
- 将新组织添加到已经建立的联盟。
2、更新通道配置
迄今为止,官方推荐的更新通道配置的方法还是使用configtxlator 和jq工具。使用这些工具更新通道配置时的步骤可以概括如下:
- 获取通道的最新配置区块。
- 将最新的配置区块从protobuf格式解码为JSON。
- 使用jq从JSON配置区块中删除不必要的元数据。
- 创建JSON配置区块的副本。
- 对复制的JSON配置区块进行相应的更新(例如,更新一个块允许的最大交易数)。
- 将JSON更新的配置区块重新编码为protobuf格式。
- 计算两个protobuf配置(即原始配置块和更新的配置块)之间的差异。这会生成包含增量配置的protobuf数据。
- 将增量数据解码回JSON。
- 将必要的头数据添加到JSON增量中,以便使用jq将其包装在信封消息中。
- 将JSON增量编码为protobuf。
- 签名配置更新交易。
- 通过对等节点将配置更新交易提交给排序服务。
尽管上述方法可行,但它非常繁琐且容易出错。例如,很容易忘记在解码最新的配置块后 剥离头数据(步骤3)或将头数据添加到增量块(步骤9)。另外,第5步很容易搞砸。在 使用文本编辑器(例如Visual Studio或Atom)或使用jq手动编辑JSON块时,可能会在 JSON文档的错误部分进行修改从而引入错误。另外,理想情况下,在对JSON块进行任何更改之前, 你应该对JSON模式有透彻的了解,但现实情况是,并不是每个人都拥有这一知识。因此, 我们希望有一种不易出错并且更加简单的更新信道配置的机制。更好的方案井盖使用类型 安全且经过编译的语言,例如Go。在下一节中,我们将介绍这种新机制。
值得一提的是,我们鼓励用户使用下面详细介绍的config更新过程来开发自己的工具, 并最终弃用configtxlator工具。这也是为什么你应该开始熟悉用于更新通道配置的 最新机制的另一个原因。
注意:提供使用configtxlator和jq工具的底层详细信息和说明超出了本文的范围。 有关此操作的完整详细信息,请参见更新通道配置。
3、使用fabric-config库编辑通道配置
3.1 引入fabric-config库
Hyperledger fabric-config库引入了一种用于生成配置交易更新的替代方法,该方法消除了 前面描述的手动JSON解析过程中所需的许多繁琐且容易出错的步骤。fabric-config库被设计为独立的库, 它支持生成诸如应用程序和系统信道创建、通道配置更新操作等,并将背书签名附加到交易信封消息。 fabric-config库是用Go编写的,并提供了丰富的API 用于修改所提供的配置交易,以及计算现有配置和所需更新之间的增量(类似于configtxlator工具的功能)。
3.2 使用fabric-config库更新通道配置
请注意,fabric-config库不包含获取配置块的功能,你可以自己决定如何获取配置块以及如何向 网络提交配置更新交易。例如,你可以选择使用Fabric Peer CLI(Hyperledger Fabric二进制文件的一部分) 从通道中获取最新的配置块。如果你正在利用IBM区块链平台,那么还可以利用Ansible的IBM区块链 平台集合从通道中获取最新的配置块。
从相应的通道中获取最新的配置块后,可以使用Go语言编写如下代码,将该配置块读入内存:
1 | import ( |
getConfigFromBlock()
函数从指定的路径读取先前获取的块,并返回指向该Config结构实例的指针。
上面的函数是完全通用的,这意味着无论你打算进行什么配置更新,都可以在代码中使用此函数
来读取配置块。注意,Config实例封装了配置块中包含的数据,格式为配置交易protobuf类型。
另外,请注意,这个Config不是fabric-config库中定义的结构。Configprotobuf是在
fabric-protos-go模块中定义的。
将配置块读入内存后,就可以创建ConfigTx实例了,如下所示:
1 | import ( |
configtx.New()
函数返回ConfigTx结构的实例,该实例在fabric-config库中定义。
ConfigTx实例是应用程序代码用于对配置块进行必要更新的主要入口点。请注意,
要获取ConfigTx实例,你需要提供使用getConfigFromBlock()
方法读取的配置交易protobuf结构
作为参数。现在让我们展示如何利用ConfigTx结构来对配置块进行一些更新。
具体来说,我们将更改以下块切割参数:
- absolute_max_bytes:块最大字节数,即任何区块都不应大于absolute_max_bytes。
- max_message_count:区块可以包含的最大交易数,即一个区块的交易数不应超过max_message_count。
- preferred_max_bytes:块的首选大小,即如果可以在preferred_max_bytes下构造一个块,则将尽早切割一个块,大于该尺寸的交易将出现在另一个块中。
- batch_timeout:在第一个交易到达之后,在切割区块之前需要等待其他交易的时间。
注意:如果需要有关上述块切割参数的更多详细信息,请参阅Hyperledger Fabric官方文档中的 更新通道配置部分。
现在让我们定义一组变量来捕获上述参数:
1 | var ( |
在代码中,你可以为这些变量分别赋值。例如,可以从属性文件中读取它们,也可以将这些值作为 运行时参数传递给程序。无论如何向应用程序提供此类值,读取后就可以将它们分配给以下变量:
1 | batchSizeMaxMessage = ... |
完成此操作后,就可以继续使用fabric-config库中的以下API方法来更新配置块:
1 | // Obtain OrdererGroup instance from ConfigTx instance |
对块进行配置更新后,即可计算这些更改的增量:
1 | var ( |
在计算完增量之后,下一个可选的步骤是签名要进行的区块更新。在这样做之前,
让我们介绍下如何使用getSigningIdentity()
函数来解析从本地MSP图区的身份信息:
1 | func getSigningIdentity(sigIDPath string) *configtx.SigningIdentity { |
以下是上述功能中使用的辅助方法。首先,让我们定义readCertificate()
方法:
1 | func readCertificate(certPath string) (*x509.Certificate, error) { |
然后定义readPrivKey()
方法:
1 | func readPrivKey(keyPath string) (crypto.PrivateKey, error) { |
就像getConfigFromBlock()
方法一样,getSigningIdentity()
也可用于任何类型的方案。
因此,你可以将这个getSigningIdentity()
功能添加到你的应用程序代码中并加以利用,而无需
进行任何配置更新。getSigningIdentity()
方法的唯一参数是指向MSP根文件夹的路径,
该文件夹应具有一组子文件夹,其中包含MSP组织用户或管理员的相应证书和密钥。MSP根文件夹的
名称应遵循以下命名约定:<enrollment_id>@Admin@OrdererMSP
的文件夹下。在子文件夹下找到的证书和密钥的
名称应如下所示:
1 | <enrollment_id>@<MSP ID> // sigIDPath |
注意:如果你使用过cryptogen工具, 那么上面显示的文件夹结构应该看起来很熟悉。
请注意,getSigningIdentity()
方法返回指向configtx.SigningIdentity结构实例的指针,
该实例也在fabric-config库中定义。
对于每个应该签名通道配置更新的身份,都应该调用getSigningIdentity()
方法。
可以将调用此方法返回的身份标识存储在数组中。一旦拥有用于签名配置更新的所有必需身份,
就可以使用configtx.SigningIdentity结构的CreateConfigSignature()
方法来创建相应的签名:
1 | configSignatures := []*cb.ConfigSignature{} |
CreateConfigSignature
方法将我们之前通过调用ComputeMarshaledUpdate()
函数计算出的
增量作为参数,即configUpdateBytes。
生成必要的签名后,可以使用以下方法创建信封消息,其中包含配置更新以及签名:
1 | env, err := configtx.NewEnvelope(configUpdateBytes, configSignatures...) |
就像CreateConfigSignature, configUpdateBytes从ComputeMarshaledUpdate()函数调用中返回的 配置增量一样,configSignatures数组则包含所有必要的签名(即,指向ConfigSignature结构实例的指针)。 对于我们在本文中讨论的示例情况(即,切割参数的更改),只需要订购服务组织的管理员的签名。
你可能还希望使用将交易提交到排序节点的身份对从NewEvelope()函数返回的信封消息进行签名。 在我们的示例中,此身份也是排序服务机构的管理员。你还可以通过调用getSigningIdentity() 方法来获得此标识实例,正如我们已经提到的,该方法返回该configtx.SigningIdentity结构的实例:
1 | envelopeSigningIdentity := getSigningIdentity(pathToEnvelopeSigningIdentity) |
最后,我们将签名的信封写入文件系统:
1 | envelopeBytes, err := proto.Marshal(env) |
现在,你有了一个配置更新交易,其中包含更改和[签名],可以将 其提交给网络进行处理!作为参考,下面是示例程序的完整源代码:
1 | package main |
4、注意事项
尽管fabric-config库极大地改进了更新通道配置的过程,但是仍然需要考虑一些注意事项。
尽管您可以使用这个库来更新任何版本的Hyperledger Fabric的通道配置,但由于 不支持某些被弃用的配置项,因此强烈建议你将其用于更新Hyperledger Fabric v2通道或 迁移到Hyperledger Fabric v2。
由于fabric-config库是用Go语言编写的,因此该库只能由使用Go语言编写工具的开发者使用。 可以通过创建通用工具(例如命令行界面)来避免这种情况,这些通用工具不直接嵌入目标 应用程序中。这种方法将允许在外部使用该库来生成配置更新交易。或者,可以设置用Go语言编写 的服务器,该服务器用于可从输入配置块生成配置交易更新的端点。
Hyperledger Fabric的现有用户可能已经有稳定的方法来更新配置交易。因此,他们可能不愿意 修改现有的自动化过程。但是,随着在通道配置周围添加新功能,最终将难以维护当前的通道配置 方法。无需手动更新零散的解决方法代码,使用此库将成为通过简单扩展来采用新功能的一致方法。
5、结论
如本文所示,Hyperledger fabric-config库提供了一种可靠的机制来生成配置更新交易, 同时消除了手动进行此类更改时出现的机械步骤和易于出错的步骤。因此,fabric-config库 使你能够以可靠且一致的方式自动执行配置更新交易。
尽管未在本教程中显示,fabric-config库还支持生成用于应用程序和系统通道创建的配置 包络以及修改应用程序和通道功能。用Go语言编写的fabric-config库为此类操作提供了类型 安全且经过编译的选项。
我们鼓励你查看fabric-config库的官方GoDoc 文档,以便熟悉其直观且易于使用的API, 并查看其他示例和代码段。利用本文中共享的指导和功能,你可以立即在下一个项目中利用fabric-config库!
原文链接:Leveraging the Hyperledger fabric-config library for channel configuration updates
汇智网翻译整理,转载请标明出处