Adding an Org to a Channel – 向通道添加组织

注解

Ensure that you have downloaded the appropriate images and binaries as outlined in Hyperledger Fabric 示例 and 预备知识 that conform to the version of this documentation (which can be found at the bottom of the table of contents to the left). In particular, your version of the fabric-samples folder must include the eyfn.sh (“Extending Your First Network”) script and its related scripts.

确保你已经下载了 Hyperledger Fabric 示例预备知识 中所罗列的和本文档版本(在左边内 容列表的底部可以查看)一致的镜像和二进制。特别注意,在你的版本中,fabric-samples 文件夹必须包含 eyfn.sh (“Extending Your First Network”)脚本和它相关的脚本。

This tutorial serves as an extension to the Building Your First Network - 构建你的第一个网络 (BYFN) tutorial, and will demonstrate the addition of a new organization – Org3 – to the application channel (mychannel) autogenerated by BYFN. It assumes a strong understanding of BYFN, including the usage and functionality of the aforementioned utilities.

本指南是 Building Your First Network - 构建你的第一个网络 (BYFN) 指南的扩展,将演示一个由 BYFN自动生成的新的组织– Org3 – 加入到应用通道 mychannel 的过程。本篇指南假设你对 BYFN有很好地理解,包括用法以及上面提及的实用工具的功能。

While we will focus solely on the integration of a new organization here, the same approach can be adopted when performing other channel configuration updates (updating modification policies or altering batch size, for example). To learn more about the process and possibilities of channel config updates in general, check out Updating a Channel Configuration). It’s also worth noting that channel configuration updates like the one demonstrated here will usually be the responsibility of an organization admin (rather than a chaincode or application developer).

虽然我们这里将只关注新组织的集成,但执行其他通道配置更新(如更新修改策略,调整批处理 大小)也可以采取相同的方式。查看 Updating a Channel Configuration 来了解更多的处理细节、 通道配置更新的其他可能通用场景。还有一点值得注意,像本文演示的这些通道配置更新通常是 组织管理者(而非链码或者应用开发者)的职责。

注解

Make sure the automated byfn.sh script runs without error on your machine before continuing. If you have exported your binaries and the related tools (cryptogen, configtxgen, etc) into your PATH variable, you’ll be able to modify the commands accordingly without passing the fully qualified path.

在继续本文前先确保自动化脚本 byfn.sh 运行无误。如果你已经把你的二进制和相关的 工具(如 cryptogenconfigtxgen)放在了PATH变量指定的路径下,你可以相应地修改命令 而不使用全量路径。

Setup the Environment – 环境构建

We will be operating from the root of the first-network subdirectory within your local clone of fabric-samples. Change into that directory now. You will also want to open a few extra terminals for ease of use.

我们后续的操作都在 fabric-samples 项目本地副本的 first-network 子目录下进行。现在切换 到该目录下。你同时需要打个几个额外的终端,以便于于操作。

First, use the byfn.sh script to tidy up. This command will kill any active or stale docker containers and remove previously generated artifacts. It is by no means necessary to bring down a Fabric network in order to perform channel configuration update tasks. However, for the sake of this tutorial, we want to operate from a known initial state. Therefore let’s run the following command to clean up any previous environments:

首先,使用 byfn.sh 脚本清理环境。这个命令会清除运行、终止状态的容器,并且移除之前构建 的部件等。移除Fabric网络并非执行通道配置升级的必要步骤。但是为了便于这个指南的书写, 我们希望从一个已知的初始状态开始,因此让我们运行以下命令来清理之前的环境:

./byfn.sh -m down

Now generate the default BYFN artifacts:

现在生成默认的BYFN部件:

./byfn.sh -m generate

And launch the network making use of the scripted execution within the CLI container:

然后通过执行CLI容器内的脚本来构建网络:

./byfn.sh -m up

Now that you have a clean version of BYFN running on your machine, you have two different paths you can pursue. First, we offer a fully commented script that will carry out a config transaction update to bring Org3 into the network.

现在你的机器上运行着一个干净的BYFN版本,你有两种不同的方式可选。第一种,我们提供了一 个通过实施配置交易更新来将Org3添加到网络中的全量注释的脚本。

Also, we will show a “manual” version of the same process, showing each step and explaining what it accomplishes (since we show you how to bring down your network before this manual process, you could also run the script and then look at each step).

我们也提供同样过程的手动版本,演示并说明每一个步骤的作用(因为我们刚演示了在继续手动 操作前如何移除你的网络,你可以先运行那个脚本,然后再来看每个步骤)。

Bring Org3 into the Channel with the Script - 使用脚本向通道加入Org3

You should be in first-network. To use the script, simply issue the following:

first-network 目录下,简单地执行以下命令来使用脚本:

./eyfn.sh up

The output here is well worth reading. You’ll see the Org3 crypto material being added, the config update being created and signed, and then chaincode being installed to allow Org3 to execute ledger queries.

此处的脚本输出值得一读。你可以看到添加了Org3的加密材料,配置更新被创建、签名,之后链 码被安装,Org3也被允许执行账本查询。

If everything goes well, you’ll get this message:

如果诸事顺利,你会看到以下信息:

========= All GOOD, EYFN test execution completed ===========

eyfn.sh can be used with the same Node.js chaincode and database options as byfn.sh by issuing the following (instead of ./byfn.sh -m -up):

eyfn.sh 可以使用和 byfn.sh 一样的Node.js链码和数据库选项,如下所示(替代 ./byfn.sh -m -up):

./byfn.sh up -c testchannel -s couchdb -l node

And then:

然后:

./eyfn.sh up -c testchannel -s couchdb -l node

For those who want to take a closer look at this process, the rest of the doc will show you each command for making a channel update and what it does.

对于想要详细了解该过程的人,文档的剩余部分会为你展示通道升级的每个命令,以及命令的作 用。

Bring Org3 into the Channel Manually – 向通道手动添加Org3

注解

The manual steps outlined below assume that the CORE_LOGGING_LEVEL in the cli and Org3cli` containers is set to DEBUG.

下面的步骤均假设 CORE_LOGGING_LEVEL 变量在 cliOrg3cli 容器中设置为 DEBUG

For the cli container, you can set this by modifying the docker-compose-cli.yaml file in the first-network directory. e.g.

你可以通过修改 first-network 目录下的 docker-compose-cli.yaml 文件来配置 cli 容器。 例:

cli:
  container_name: cli
  image: hyperledger/fabric-tools:$IMAGE_TAG
  tty: true
  stdin_open: true
  environment:
    - GOPATH=/opt/gopath
    - CORE_VM_ENDPOINT=unix:///host/var/run/docker.sock
    #- CORE_LOGGING_LEVEL=INFO
    - CORE_LOGGING_LEVEL=DEBUG

For the Org3cli container, you can set this by modifying the docker-compose-org3.yaml file in the first-network directory. e.g.

你可以通过修改 first-network 目录下的 docker-compose-org3.yaml 文件来配置 Org3cli 容 器。例:

Org3cli:
  container_name: Org3cli
  image: hyperledger/fabric-tools:$IMAGE_TAG
  tty: true
  stdin_open: true
  environment:
    - GOPATH=/opt/gopath
    - CORE_VM_ENDPOINT=unix:///host/var/run/docker.sock
    #- CORE_LOGGING_LEVEL=INFO
    - CORE_LOGGING_LEVEL=DEBUG

If you’ve used the eyfn.sh script, you’ll need to bring your network down. This can be done by issuing:

如果你已经使用了 eyfn.sh 脚本,你需要先移除你的网络。通过如下所示命令来完成:

./eyfn.sh down

This will bring down the network, delete all the containers and undo what we’ve done to add Org3.

When the network is down, bring it back up again.

这会移除网络,删除所有的容器,并且撤销我们添加Org3的操作。

当网络移除后,再次将它建立起来。

./byfn.sh -m generate

Then:

然后:

./byfn.sh -m up

This will bring your network back to the same state it was in before you executed the eyfn.sh script.

这会将你的网络恢复到你执行 eyfn.sh 脚本之前的状态。

Now we’re ready to add Org3 manually. As a first step, we’ll need to generate Org3’s crypto material.

现在我们可以手动添加Org3。第一步,我们需要生成Org3的加密材料。

Generate the Org3 Crypto Material – 生成Org3加密材料

In another terminal, change into the org3-artifacts subdirectory from first-network.

在另一个终端,切换到 first-network 的子目录 org3-artifacts 中。

cd org3-artifacts

There are two yaml files of interest here: org3-crypto.yaml and configtx.yaml. First, generate the crypto material for Org3:

这里需要关注两个 yaml 文件:org3-crypto.yamlconfigtx.yaml。首先,生成Org3的加密 材料:

../../bin/cryptogen generate --config=./org3-crypto.yaml

This command reads in our new crypto yaml file – org3-crypto.yaml – and leverages cryptogen to generate the keys and certificates for an Org3 CA as well as two peers bound to this new Org. As with the BYFN implementation, this crypto material is put into a newly generated crypto-config folder within the present working directory (in our case, org3-artifacts).

该命令读取我们新的加密 yaml 文件 – org3-crypto.yaml – 然后调用 cryptogen 来为Org3 CA 和其他两个绑定到这个组织的peers生成秘钥和证书。如同BYFN实现,加密材料放到最近生成的 crypto-config 文件夹下,均在当前工作路径下(在我们例子中是 org3-artifacts)。

Now use the configtxgen utility to print out the Org3-specific configuration material in JSON. We will preface the command by telling the tool to look in the current directory for the configtx.yaml file that it needs to ingest.

现在使用 configtxgen 工具打印出Org3对应的配置材料,用JSON格式展示。我们将在执行命令 前,告诉这个工具去获取当前目录的 configtx.yaml 文件。

export FABRIC_CFG_PATH=$PWD && ../../bin/configtxgen -printOrg Org3MSP > ../channel-artifacts/org3.json

The above command creates a JSON file – org3.json – and outputs it into the channel-artifacts subdirectory at the root of first-network. This file contains the policy definitions for Org3, as well as three important certificates presented in base 64 format: the admin user certificate (which will be needed to act as the admin of Org3 later on), a CA root cert, and a TLS root cert. In an upcoming step we will append this JSON file to the channel configuration.

上面的命令会创建一个JSON文件 – org3.json – 并把文件输出到 first-networkchannel-artifacts 子目录下。这个文件包含了Org3的策略定义,还有base 64编码的重要的证 书:管理员用户证书(之后作为Org3的管理员角色),一个根证书,一个TLS根证书。之后的步 骤我们会用这个JSON文件去扩展通道配置。

Our final piece of housekeeping is to port the Orderer Org’s MSP material into the Org3 crypto-config directory. In particular, we are concerned with the Orderer’s TLS root cert, which will allow for secure communication between Org3 entities and the network’s ordering node.

我们最后的例行工作是拷贝排序Org的MSP材料到Org3的 crypto-config 目录下。我们尤其关注 排序服务的TLS根证书,它可以用于Org3的通信实体和网络的排序节点间的安全通信。

cd ../ && cp -r crypto-config/ordererOrganizations org3-artifacts/crypto-config/

Now we’re ready to update the channel configuration...

现在我们准备开始升级通道配置。

Prepare the CLI Environment 准备CLI环境

The update process makes use of the configuration translator tool – configtxlator. This tool provides a stateless REST API independent of the SDK. Additionally it provides a CLI, to simplify configuration tasks in Fabric networks. The tool allows for the easy conversion between different equivalent data representations/formats (in this case, between protobufs and JSON). Additionally, the tool can compute a configuration update transaction based on the differences between two channel configurations.

更新的步骤需要用到配置转化工具 – configtxlator,这个工具提供了和SDK无关的无状态REST API。 它还额外提供了CLI,用于简化Fabric网络中的配置任务。这个工具提供不同的数据表示/格 式间进行转化的便利功能(在这个例子中就是protobufs和JSON格式的互转)。另外,这个工具 能基于两个不同的通道配置计算出配置更新交易。

First, exec into the CLI container. Recall that this container has been mounted with the BYFN crypto-config library, giving us access to the MSP material for the two original peer organizations and the Orderer Org. The bootstrapped identity is the Org1 admin user, meaning that any steps where we want to act as Org2 will require the export of MSP-specific environment variables.

首先,进入到CLI容器。这个容器挂载了BYFN crypto-config 库,允许我们访问两个原始的peer节点组织和 Orderer排序组织。默认的身份是Org1的管理员用户,所以如果我们想作为Org2进行任何操作,需要设置和MSP相关的环境变量。

docker exec -it cli bash

Now install the jq tool into the container. This tool allows script interactions with JSON files returned by the configtxlator tool:

现在在容器里安装 jq 工具。这个工具可以解析 configtxlator 工具返回的JSON文件。

apt update && apt install -y jq

Export the ORDERER_CA and CHANNEL_NAME variables:

Export ORDERER_CACHANNEL_NAME 变量。

export ORDERER_CA=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/ordererOrganizations/example.com/orderers/orderer.example.com/msp/tlscacerts/tlsca.example.com-cert.pem  && export CHANNEL_NAME=mychannel

Check to make sure the variables have been properly set:

检查并确保环境变量已合理设置:

echo $ORDERER_CA && echo $CHANNEL_NAME

注解

If for any reason you need to restart the CLI container, you will also need to re-export the two environment variables – ORDERER_CA and CHANNEL_NAME. The jq installation will persist. You need not install it a second time.

如果因为什么原因需要重启CLI容器,你会需要重新设置 ORDERER_CACHANNEL_NAME 这两个 环境变量。jq安装会持久化,你不需要再次安装它。

Fetch the Configuration 获取配置

Now we have a CLI container with our two key environment variables – ORDERER_CA and CHANNEL_NAME exported. Let’s go fetch the most recent config block for the channel – mychannel.

现在我们有了一个设置了 ORDERER_CACHANNEL_NAME 环境变量的CLI容器。让我们获取通道 mychannel 的最近的配置区块。

The reason why we have to pull the latest version of the config is because channel config elements are versioned.. Versioning is important for several reasons. It prevents config changes from being repeated or replayed (for instance, reverting to a channel config with old CRLs would represent a security risk). Also it helps ensure concurrency (if you want to remove an Org from your channel, for example, after a new Org has been added, versioning will help prevent you from removing both Orgs, instead of just the Org you want to remove).

我们必须拉取最新版本配置的原因是通道配置元素是版本化的。版本管理由于一些原因显得很重 要。它可以防止通道配置更新被重复或者重放攻击(例如,回退到带有旧的CRLs的通道配置将会 产生安全风险)。同时它保证了并行性(例如如果你想从你的通道中添加新的Org后移除一个 Org,版本管理可以帮助你移除想移除的那个Org,防止移除两个Orgs)。

peer channel fetch config config_block.pb -o orderer.example.com:7050 -c $CHANNEL_NAME --tls --cafile $ORDERER_CA

This command saves the binary protobuf channel configuration block to config_block.pb. Note that the choice of name and file extension is arbitrary. However, following a convention which identifies both the type of object being represented and its encoding (protobuf or JSON) is recommended.

这个命令将通道配置区块以二进制protobuf形式保存在 config_block.pb。注意文件的名字和扩 展名可以任意指定。然而,我们建议之后根据区块存储对象的类型和编码格式(protobuf或 JSON)进行转换。

When you issued the peer channel fetch command, there was a decent amount of output in the terminal. The last line in the logs is of interest:

当你执行 peer channel fetch 命令后,在终端上会有相当数量的打印输出。日志的最后一行比较 有意思:

2017-11-07 17:17:57.383 UTC [channelCmd] readBlock -> DEBU 011 Received block: 2

This is telling us that the most recent configuration block for mychannel is actually block 2, NOT the genesis block. By default, the peer channel fetch config command returns the most recent configuration block for the targeted channel, which in this case is the third block. This is because the BYFN script defined anchor peers for our two organizations – Org1 and Org2 – in two separate channel update transactions.

这是告诉我们最近的 mychannel 的配置区块实际上是区块2, 初始区块。 peer channel fetch config 命令默认返回目标通道最新的配置区块,在这个例子里是第三个区 块。这是因为BYFN脚本分别在两个不同通道更新交易中为两个组织– Org1Org2 定义了锚节 点。

As a result, we have the following configuration sequence:

那么,我们有如下的配置块序列:

  • block 0: genesis block
  • block 1: Org1 anchor peer update
  • block 2: Org2 anchor peer update

Convert the Configuration to JSON and Trim It Down – 转换配置到JSON格式并裁剪

Now we will make use of the configtxlator tool to decode this channel configuration block into JSON format (which can be read and modified by humans). We also must strip away all of the headers, metadata, creator signatures, and so on that are irrelevant to the change we want to make. We accomplish this by means of the jq tool:

现在我们是用 configtxlator 的工具将这个通道配置转换为JSON格式(以便友好地被阅读和修 改)。我们也必须裁剪所有的头部,元数据,创建者签名等这些和我们即将做的无关的内容。我 们通过 jq 这个工具来实现:

configtxlator proto_decode --input config_block.pb --type common.Block | jq .data.data[0].payload.data.config > config.json

This leaves us with a trimmed down JSON object – config.json, located in the fabric-samples folder inside first-network – which will serve as the baseline for our config update.

我们得到一个裁剪后的JSON对象 – config.json ,放置在 fabric-samples 下的 first-network 文件夹下 – first-network 是我们配置更新的基准工作目录。

Take a moment to open this file inside your text editor of choice (or in your browser). Even after you’re done with this tutorial, it will be worth studying it as it reveals the underlying configuration structure and the other kind of channel updates that can be made. We discuss them in more detail in Updating a Channel Configuration.

花一些时间用你的text编辑器(或者你的浏览器)打开这个文件。即使你已经完成了这个指南, 也值得研究下它,因为它揭示了底层配置结构,和能做的其它类型的通道更新升级。我们将在 Updating a Channel Configuration 更详细地讨论。

Add the Org3 Crypto Material – 添加Org3加密材料

注解

The steps you’ve taken up to this point will be nearly identical no matter what kind of config update you’re trying to make. We’ve chosen to add an org with this tutorial because it’s one of the most complex channel configuration updates you can attempt.

目前到这里你做的步骤和其他任何类型的配置升级所需步骤几乎是一致的。我们之所以选择添 加一个org这样的指南,是因为这是能做的配置升级里最复杂的一个。

We’ll use the jq tool once more to append the Org3 configuration definition – org3.json – to the channel’s application groups field, and name the output – modified_config.json.

我们将再次使用 jq 工具去扩展Org3的配置定义 – org3.json – 对应到通道的应用组属性,同时定义输出文件是 – modified_config.json

jq -s '.[0] * {"channel_group":{"groups":{"Application":{"groups": {"Org3MSP":.[1]}}}}}' config.json ./channel-artifacts/org3.json > modified_config.json

Now, within the CLI container we have two JSON files of interest – config.json and modified_config.json. The initial file contains only Org1 and Org2 material, whereas “modified” file contains all three Orgs. At this point it’s simply a matter of re-encoding these two JSON files and calculating the delta.

现在,我们在CLI容器有两个重要的JSON文件 – config.jsonmodified_config.json。初始 的文件包含Org1和Org2的材料,而”modified”文件包含了总共三个Orgs。现在只需要将这两个 JSON文件重新编码并计算出差异部分。

First, translate config.json back into a protobuf called config.pb:

首先,将 config.json 文件倒回到protobuf格式,命名为 config.pb

configtxlator proto_encode --input config.json --type common.Config --output config.pb

Next, encode modified_config.json to modified_config.pb:

下一步,将 modified_config.json 编码成 modified_config.pb:

configtxlator proto_encode --input modified_config.json --type common.Config --output modified_config.pb

Now use configtxlator to calculate the delta between these two config protobufs. This command will output a new protobuf binary named org3_update.pb:

现在使用 configtxlator 去计算两个protobuf配置的差异。这条命令会输出一个新的protobuf二 进制文件,命名为 org3_update.pb

configtxlator compute_update --channel_id $CHANNEL_NAME --original config.pb --updated modified_config.pb --output org3_update.pb

This new proto – org3_update.pb – contains the Org3 definitions and high level pointers to the Org1 and Org2 material. We are able to forgo the extensive MSP material and modification policy information for Org1 and Org2 because this data is already present within the channel’s genesis block. As such, we only need the delta between the two configurations.

这个新的proto文件 – org3_update.pb – 包含了Org3定义和指向Org1和Org2材料的更高级别的指 针。我们可以抛弃Org1和Org2相关的MSP材料和修改策略信息,因为这些数据已经存在于通道 的初始区块。因此,我们只需要两个配置的差异部分。

Before submitting the channel update, we need to perform a few final steps. First, let’s decode this object into editable JSON format and call it org3_update.json:

在我们提交通道更新前,我们最后做几个操作。首先,我们将这个对象解码成可编辑的JSON格 式,并命名为 org3_update.json

configtxlator proto_decode --input org3_update.pb --type common.ConfigUpdate | jq . > org3_update.json

Now, we have a decoded update file – org3_update.json – that we need to wrap in an envelope message. This step will give us back the header field that we stripped away earlier. We’ll name this file org3_update_in_envelope.json:

现在,我们有了一个解码后的更新文件 – org3_update.json – 我们需要用信封消息来包装它。这 个步骤要把之前裁剪掉的头部信息还原回来。我们将命名这个新文件为 org3_update_in_envelope.json

echo '{"payload":{"header":{"channel_header":{"channel_id":"mychannel", "type":2}},"data":{"config_update":'$(cat org3_update.json)'}}}' | jq . > org3_update_in_envelope.json

Using our properly formed JSON – org3_update_in_envelope.json – we will leverage the configtxlator tool one last time and convert it into the fully fledged protobuf format that Fabric requires. We’ll name our final update object org3_update_in_envelope.pb:

使用我们格式化好的JSON – org3_update_in_envelope.json – 我们最后一次使用 configtxlator 工具将他转换为fabric需要的完整独立的protobuf格式。我们将最后的更新对象命名为 org3_update_in_envelope.pb

configtxlator proto_encode --input org3_update_in_envelope.json --type common.Envelope --output org3_update_in_envelope.pb

Sign and Submit the Config Update – 签名并提交配置更新

Almost done!

We now have a protobuf binary – org3_update_in_envelope.pb – within our CLI container. However, we need signatures from the requisite Admin users before the config can be written to the ledger. The modification policy (mod_policy) for our channel Application group is set to the default of “MAJORITY”, which means that we need a majority of existing org admins to sign it. Because we have only two orgs – Org1 and Org2 – and the majority of two is two, we need both of them to sign. Without both signatures, the ordering service will reject the transaction for failing to fulfill the policy.

差不多大功告成了!

我们现在有一个protobuf二进制 – org3_update_in_envelope.pb – 在我们的CLI容器内。但是,在 配置写入到账本前,我们需要必要的Admin用户的签名。我们通道应用组的修改策略(mod_policy)设置 为默认值”MAJORITY”,因此意味着我们需要大多数已经存在的组织管理员去签名这个更 新。因为我们只有两个组织 – Org1和Org2 – 也即两个的大多数也还是两个,我们需要它们都签 名。没有这两个签名,排序服务会以不满足策略为由拒绝这个交易。

First, let’s sign this update proto as the Org1 Admin. Remember that the CLI container is bootstrapped with the Org1 MSP material, so we simply need to issue the peer channel signconfigtx command:

首先,让我们以Org1管理员升级来签名这个更新proto。因为CLI容器是以Org1 MSP材料启动 的,我们只需要简单执行 peer channel signconfigtx 命令:

peer channel signconfigtx -f org3_update_in_envelope.pb

The final step is to switch the CLI container’s identity to reflect the Org2 Admin user. We do this by exporting four environment variables specific to the Org2 MSP.

最后一步,我们将CLI容器的身份切换为Org2管理员。为此,我们通过export和Org2 MSP相关的 四个环境变量。

注解

Switching between organizations to sign a config transaction (or to do anything else) is not reflective of a real-world Fabric operation. A single container would never be mounted with an entire network’s crypto material. Rather, the config update would need to be securely passed out-of-band to an Org2 Admin for inspection and approval.

切换不同的组织身份为配置交易签名(或者其他事情)不能反映真实世界里Fabric的操作。一 个单一容器不可能挂载了整个网络的加密材料。相反地,配置更新需要在网络外安全地递交 给Org2管理员来审查和批准。

Export the Org2 environment variables:

Export Org2的环境变量:

# you can issue all of these commands at once

export CORE_PEER_LOCALMSPID="Org2MSP"

export 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

export CORE_PEER_MSPCONFIGPATH=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org2.example.com/users/Admin@org2.example.com/msp

export CORE_PEER_ADDRESS=peer0.org2.example.com:7051

Lastly, we will issue the peer channel update command. The Org2 Admin signature will be attached to this call so there is no need to manually sign the protobuf a second time:

最后,我们执行 peer channel update 命令。Org2 管理员在这个命令中会附带签名,因此就没有 必要对protobuf进行两次签名。

注解

The upcoming update call to the ordering service will undergo a series of systematic signature and policy checks. As such you may find it useful to stream and inspect the ordering node’s logs. From another shell, issue a docker logs -f orderer.example.com command to display them.

将要做的对排序服务的更新调用,会经历一系列的系统级签名和策略检查。你会发现通过检视 排序节点的日志流会非常有用。在另外一个shell,执行 docker logs -f orderer.example.com 命令就能展示它们了。

Send the update call:

发起更新调用:

peer channel update -f org3_update_in_envelope.pb -c $CHANNEL_NAME -o orderer.example.com:7050 --tls --cafile $ORDERER_CA

You should see a message digest indication similar to the following if your update has been submitted successfully:

如果你的更新提交成功,将会看到一个类似如下的摘要提示信息:

2018-02-24 18:56:33.499 UTC [msp/identity] Sign -> DEBU 00f Sign: digest: 3207B24E40DE2FAB87A2E42BC004FEAA1E6FDCA42977CB78C64F05A88E556ABA

You will also see the submission of our configuration transaction:

你也会看到我们的配置交易的提交:

2018-02-24 18:56:33.499 UTC [channelCmd] update -> INFO 010 Successfully submitted channel update

The successful channel update call returns a new block – block 5 – to all of the peers on the channel. If you remember, blocks 0-2 are the initial channel configurations while blocks 3 and 4 are the instantiation and invocation of the mycc chaincode. As such, block 5 serves as the most recent channel configuration with Org3 now defined on the channel.

成功的通道更新调用返回一个新的区块 – 区块5 – 给所有在这个通道上的peers节点。如果你还记 得,区块0-2是初始的通道配置,而区块3和4是链码 mycc 的实例化和调用。至此,区块5就是带 有Org3定义的最新的通道配置。

Inspect the logs for peer0.org1.example.com:

查看 peer0.org1.example.com 的日志:

docker logs -f peer0.org1.example.com

Follow the demonstrated process to fetch and decode the new config block if you wish to inspect its contents.

如果你想查看新的配置区块的内容,可以跟着示范的过程获取和解码配置区块。

Configuring Leader Election – 配置领导选举

注解

This section is included as a general reference for understanding the leader election settings when adding organizations to a network after the initial channel configuration has completed. This sample defaults to dynamic leader election, which is set for all peers in the network in peer-base.yaml.

这个章节之所以引入,是用于理解在网络通道配置初始化之后,网络中加入组织时,领导选举 设置的作用。这个例子中,默认设置为动态领导选举,在 peer-base.yaml 文件中为所有的 peers节点进行了设置。

Newly joining peers are bootstrapped with the genesis block, which does not contain information about the organization that is being added in the channel configuration update. Therefore new peers are not able to utilize gossip as they cannot verify blocks forwarded by other peers from their own organization until they get the configuration transaction which added the organization to the channel. Newly added peers must therefore have one of the following configurations so that they receive blocks from the ordering service:

新加入的peer节点是根据初始区块启动,初始区块是不包含通道配置更新中新加入的组织信息 的。因此新的peer节点就无法利用gossip协议,因为它们无法验证从自己组织里其他peer节点发 送过来的区块,直到它们接收到加入组织到通道的那个配置交易。因此新加入的节点必须有以下 的一个配置来保证能从排序服务接收区块:

1. To utilize static leader mode, configure the peer to be an organization leader:

  1. 采用静态领导者模式,将peer节点配置为组织的领导者。
CORE_PEER_GOSSIP_USELEADERELECTION=false
CORE_PEER_GOSSIP_ORGLEADER=true

注解

This configuration must be the same for all new peers added to the channel.

这个配置对于新加入到通道中的所有peer节点必须一致。

2. To utilize dynamic leader election, configure the peer to use leader election:

  1. 采用动态领导者选举,配置peer节点采用领导选举:
CORE_PEER_GOSSIP_USELEADERELECTION=true
CORE_PEER_GOSSIP_ORGLEADER=false

注解

Because peers of the newly added organization won’t be able to form membership view, this option will be similar to the static configuration, as each peer will start proclaiming itself to be a leader. However, once they get updated with the configuration transaction that adds the organization to the channel, there will be only one active leader for the organization. Therefore, it is recommended to leverage this option if you eventually want the organization’s peers to utilize leader election.

因为新加入组织的peer节点,无法生成成员关系视图,这个配置和静态配置类似,每个节点启 动时宣称自己是领导者。但是,一旦它们更新到了将组织加入到通道的配置交易,组织中将 只会有一个激活状态的领导者。因此,如果你想最终组织的节点采用领导选举,建议你采用 这个配置。

Join Org3 to the Channel – 向通道添加Org3

At this point, the channel configuration has been updated to include our new organization – Org3 – meaning that peers attached to it can now join mychannel.

此时,通道的配置已经更新并包含了我们新的组织 – Org3 – 意味者这个组织下的peer节点可以加入 到 mychannel

First, let’s launch the containers for the Org3 peers and an Org3-specific CLI.

首先,让我们部署Org3 peer节点容器和Org3-specific CLI容器。

Open a new terminal and from first-network kick off the Org3 docker compose:

打开一个以 first-network 为工作目录的新的终端,开始Org3 docker compose的部署:

docker-compose -f docker-compose-org3.yaml up -d

This new compose file has been configured to bridge across our initial network, so the two peers and the CLI container will be able to resolve with the existing peers and ordering node. With the three new containers now running, exec into the Org3-specific CLI container:

这个新的compose文件配置为桥接我们的初始网络,因此两个peer容器和CLI容器可以融入到已经 存在的peer和排序节点中。当三个容器运行后,进入Org3-specific CLI容器:

docker exec -it Org3cli bash

Just as we did with the initial CLI container, export the two key environment variables: ORDERER_CA and CHANNEL_NAME:

和我们之前在初始CLI容器一样,export两个关键环境变量: ORDERER_CACHANNEL_NAME

export ORDERER_CA=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/ordererOrganizations/example.com/orderers/orderer.example.com/msp/tlscacerts/tlsca.example.com-cert.pem && export CHANNEL_NAME=mychannel

Check to make sure the variables have been properly set:

检查确保环境变量已经合理设置:

echo $ORDERER_CA && echo $CHANNEL_NAME

Now let’s send a call to the ordering service asking for the genesis block of mychannel. The ordering service is able to verify the Org3 signature attached to this call as a result of our successful channel update. If Org3 has not been successfully appended to the channel config, the ordering service should reject this request.

现在,我们向排序服务发送一个请求 mychannel 的初始区块的请求。如果通道更新成功执行,排 序服务会成功校验这个请求中Org3的签名。如果Org3没有成功地添加到通道配置中,排序服务会 拒绝这个请求。

注解

Again, you may find it useful to stream the ordering node’s logs to reveal the sign/verify logic and policy checks.

再次,你会发现打印排序节点的日志流可以帮助揭示签名/校验以及策略校验的逻辑。

Use the peer channel fetch command to retrieve this block:

使用 peer channel fatch 命令来检索这个区块:

peer channel fetch 0 mychannel.block -o orderer.example.com:7050 -c $CHANNEL_NAME --tls --cafile $ORDERER_CA

Notice, that we are passing a 0 to indicate that we want the first block on the channel’s ledger (i.e. the genesis block). If we simply passed the peer channel fetch config command, then we would have received block 5 – the updated config with Org3 defined. However, we can’t begin our ledger with a downstream block – we must start with block 0.

注意,我们传递了 0 去索引我们在这个通道账本上想要的区块(例如,初始区块)。如果我们 简单地执行 peer channel fetch config 命令,我们将会收到区块5 – 那个带有Org3定义的更新 后的配置。然而,我们的账本不能从一个下游的区块开始 – 我们必须从区块0开始。

Issue the peer channel join command and pass in the genesis block – mychannel.block:

执行 peer channel join 命令并指定初始区块 – mychannel.block:

peer channel join -b mychannel.block

If you want to join the second peer for Org3, export the TLS and ADDRESS variables and reissue the peer channel join command:

如果你想将第二个peer节点加入到Org3中,export TLSADDRESS 变量,再重新执行 peer channel join command

export CORE_PEER_TLS_ROOTCERT_FILE=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org3.example.com/peers/peer1.org3.example.com/tls/ca.crt && export CORE_PEER_ADDRESS=peer1.org3.example.com:7051

peer channel join -b mychannel.block

pgrade and Invoke Chaincode – 升级和调用链码

The final piece of the puzzle is to increment the chaincode version and update the endorsement policy to include Org3. Since we know that an upgrade is coming, we can forgo the futile exercise of installing version 1 of the chaincode. We are solely concerned with the new version where Org3 will be part of the endorsement policy, therefore we’ll jump directly to version 2 of the chaincode.

这个智力游戏的最后一部分是升级链码的版本,并升级背书策略以加入Org3。因为我们知道马上 要做的是升级,将无关紧要的安装第一个版本链码的过程抛诸脑后吧。我们只关心Org3会是背书 策略一部分的新的版本,因此我们直接跳到链码的第二个版本。

From the Org3 CLI:

从Org3 CLI执行:

peer chaincode install -n mycc -v 2.0 -p github.com/chaincode/chaincode_example02/go/

Modify the environment variables accordingly and reissue the command if you want to install the chaincode on the second peer of Org3. Note that a second installation is not mandated, as you only need to install chaincode on peers that are going to serve as endorsers or otherwise interface with the ledger (i.e. query only). Peers will still run the validation logic and serve as committers without a running chaincode container.

如果你要在Org3的第二个peer节点上安装链码,请相应地修改环境变量并再次执行命令。注意第 二次安装并不是强制的,因为你只需要在背书节点或者和账本有交互行为(如,只做查询)节点上 安装链码。即使没有运行链码容器,Peer节点仍然会运行检验逻辑,作为commiter角色工作。

Now jump back to the original CLI container and install the new version on the Org1 and Org2 peers. We submitted the channel update call with the Org2 admin identity, so the container is still acting on behalf of peer0.org2:

现在跳回 original CLI容器,在Org1和Org2 peer节点上安装新版本链码。我们使用Org2管理员身 份提交通道更新请求,所以容器仍然是代表”peer0.Org2”:

peer chaincode install -n mycc -v 2.0 -p github.com/chaincode/chaincode_example02/go/

Flip to the peer0.org1 identity:

切回 peer0.org1 身份:

export CORE_PEER_LOCALMSPID="Org1MSP"

export 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

export CORE_PEER_MSPCONFIGPATH=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org1.example.com/users/Admin@org1.example.com/msp

export CORE_PEER_ADDRESS=peer0.org1.example.com:7051

And install again:

然后再次安装:

peer chaincode install -n mycc -v 2.0 -p github.com/chaincode/chaincode_example02/go/

Now we’re ready to upgrade the chaincode. There have been no modifications to the underlying source code, we are simply adding Org3 to the endorsement policy for a chaincode – mycc – on mychannel.

现在我们已经准备好升级链码。底层的源代码没有任何变化,我们只是简单为在 mychannel 通道上的 mycc 链码的背书策略添加Org3组织。

注解

Any identity satisfying the chaincode’s instantiation policy can issue the upgrade call. By default, these identities are the channel Admins.

任何满足链码实例化策略的身份都可以执行升级调用。这些身份默认就是通道的管理者。

Send the call:

发送调用:

peer chaincode upgrade -o orderer.example.com:7050 --tls $CORE_PEER_TLS_ENABLED --cafile $ORDERER_CA -C $CHANNEL_NAME -n mycc -v 2.0 -c '{"Args":["init","a","90","b","210"]}' -P "OR ('Org1MSP.peer','Org2MSP.peer','Org3MSP.peer')"

You can see in the above command that we are specifying our new version by means of the v flag. You can also see that the endorsement policy has been modified to -P "OR ('Org1MSP.peer','Org2MSP.peer','Org3MSP.peer')", reflecting the addition of Org3 to the policy. The final area of interest is our constructor request (specified with the c flag).

你可以看到上面的命令,我们用 v 标志指定了我们的新的版本号。你也能看到背书策略修改为 -P "OR ('Org1MSP.peer','Org2MSP.peer','Org3MSP.peer')" ,说明Org3要被添加到策略中。最后一部分注意的是我们的构造请求(用 c 标志指定)。

As with an instantiate call, a chaincode upgrade requires usage of the init method. If your chaincode requires arguments be passed to the init method, then you will need to do so here.

链码升级和实例化一样需要用到 init 方法。 如果 你的链码需要传递参数给 init 方法,那你 需要在这里添加。

The upgrade call adds a new block – block 6 – to the channel’s ledger and allows for the Org3 peers to execute transactions during the endorsement phase. Hop back to the Org3 CLI container and issue a query for the value of a. This will take a bit of time because a chaincode image needs to be built for the targeted peer, and the container needs to start:

升级调用对于通道的账本添加一个新的区块 – 允许Org3的peer节点在背书阶段执行交易。跳回到 Org3 CLI容器,并执行对 a 值得查询。这需要花费一点时间,因为需要为目标peer构建链码镜 像,链码容器需要运行。

peer chaincode query -C $CHANNEL_NAME -n mycc -c '{"Args":["query","a"]}'

We should see a response of Query Result: 90.

我们能看到 Query Result:90 的响应。

Now issue an invocation to move 10 from a to b:

现在执行调用,从 a 转移 10b

peer chaincode invoke -o orderer.example.com:7050  --tls $CORE_PEER_TLS_ENABLED --cafile $ORDERER_CA -C $CHANNEL_NAME -n mycc -c '{"Args":["invoke","a","b","10"]}'

Query one final time:

peer chaincode query -C $CHANNEL_NAME -n mycc -c '{"Args":["query","a"]}'

We should see a response of Query Result: 80, accurately reflecting the update of this chaincode’s world state.

我们能看到 Query Result: 80 的响应,准确反映了链码的世界状态的更新。

Conclusion – 总结

The channel configuration update process is indeed quite involved, but there is a logical method to the various steps. The endgame is to form a delta transaction object represented in protobuf binary format and then acquire the requisite number of admin signatures such that the channel configuration update transaction fulfills the channel’s modification policy.

通道配置的更新过程是非常复杂的,但是仍然有一个诸多步骤对应的逻辑方法。终局就是为了构 建一个用protobuf二进制表达的差异化的交易对象,然后获取必要数量的管理员签名来满足通道 的修改策略。

The configtxlator and jq tools, along with the ever-growing peer channel commands, provide us with the functionality to accomplish this task.

configtxlatorjq 工具,和不断使用的 peer channel 命令,为我们提供了完成这个任务的基本功能。