翻译:https://hyperledger-fabric.readthedocs.io/en/latest/channel_update_tutorial.html
本目录拓展test network通过增加一个新的组织 -Org3 到应用通道。
现在我们集中在通道中增加一个新组织,你可以使用一个相似的过程来修改该通道其它配置(例如,修改策略或者更改大小)。进一步了解通道配置的更新过程和可能性,查看 Updating a channel configuration。值得注意的是,通道配置更新通常由组织管理员负责(而不是链码或应用开发者)。
设置环境
依然操作fabric-samples下的 test-network目录。
cd fabric-samples/test-network
首先,使用network.sh来整理干净。命令会清除所有活动的镜像和删除之前的残留文件。为了执行通道配置更新任务,无需关闭Fabric网络。然而,本文档为了保证确定的初始化状态,运行如下命令
./network.sh down
你可以使用脚本启动网络,且网络中有一个通道叫mychannel
./network.sh up createChannel
如果成功了会看到如下输出
========= Channel successfully joined ===========
现在有一个纯净的test network运行在本机上,你可以增加新组织到通道中。首先使用脚本来添加Org3到通道并确认过程没有问题。接着再一步一步添加Org3到通道中。
使用脚本添加Org3到通道
在test-network目录中,使用脚本
cd addOrg3
./addOrg3.sh up
这里输出是很值得读的。你会看到Org3加密素材被创建,Org3组织定义被创建。接着通道配置修改,签名,并且提交到通道。
如果运行顺利,你会看到如下信息
========= Finished adding Org3 to your test network! =========
现在我们已经确认Org3添加到通道中,接下来可以一步一步的执行
手动将Org3添加到通道
如果已经使用了addOrg3.sh脚本,首先需要将网络关掉。接下来的命令会关掉所有运行的组件且删除组织的加密素材
./addOrg3.sh down
当关闭结束后,再重新开启
cd ..
./network.sh up createChannel
回到执行addOrg3.sh脚本之前。
现在可以手动将Org3添加到通道中。第一步生成Org3的加密素材。
生成Org3的加密素材
在另一个终端中切换到test-network的子目录addOrg3
cd addOrg3
首先,对Org3的peer及应用程序和管理员创建证书和秘钥。因为我们要修改通道,我们打算使用cryptogen 工具来替代CA。下面的命令使用cryptogen来读org3-crypto.yaml文件并且在Org3加密素材中创建文件夹:
../../bin/cryptogen generate --config=org3-crypto.yaml --output="../organizations"
你会在test-network/organizations/peerOrganizations中看到Org3的加密素材(在Org1和Org2旁边)。
一旦我们创建了Org3的加密素材,我们可以使用configtxgen 来打印Org3的组织定义。我们将告诉工具在当前目录中查找configtx.yaml它需要接收的文件。
export FABRIC_CFG_PATH=$PWD
../../bin/configtxgen -printOrg Org3MSP > ../organizations/peerOrganizations/org3.example.com/org3.json
以上命令创建JSON文件 org3.json 并且写入到test-network/organizations/peerOrganizations/org3.example.com文件夹中。组织定义中包含了Org3的策略定义,以及base64格式编码的三个重要证书。
- CA根证书,用来建立组织的信任
- TLS根证书,gossip protocol用来验证Org3的区块传播和服务发现。
- 管理员证书(作为Org3的管理员)
我们会增加Org3到通道,通过增加组织定义到通道配置。
启动Org3组件
当我们创建Org3证书素材,我们就可以启动Org3的peer。在addOrg3目录中,触发如下命令
docker-compose -f docker/docker-compose-org3.yaml up -d
如果命令成功了,你会看到Org3的peer和一个叫做Org3CLI的容器
Creating peer0.org3.example.com ... done
Creating Org3cli ... done
此Docker Compose 文件已配置为跨我们的初始网络桥接,使Org3的peer和Org3CLI与测试网络的现有peer和排序节点解析。
我们会使用Org3CLI容器来和网络沟通且执行Org3加入通道的命令。
准备CLI环境
更新过程使用配置转换工具-configtxlator。此工具提供独立于SDK的无状态REST API。此外,它提供了一个CLI工具,可用于简化Fabric网络中的配置任务。该工具允许在不同的数据格式之间轻松转换(本案例是,protobuf和JSON)。此外,该工具可以基于两个通道配置之间的差异计算配置更新事务。
执行如下命令在Org3CLI容器中运行
docker exec -it Org3cli bash
容器挂载关联了organizations
文件夹,为所有组织提供了加密素材和TLS证书。可以使用环境变量来操作Org3CLI容器,作为Org1,Org2或Org3的管理员。首先,我们需要设置环境变量TLS证书和通道名称
export ORDERER_CA=/opt/gopath/src/github.com/hyperledger/fabric/peer/organizations/ordererOrganizations/example.com/orderers/orderer.example.com/msp/tlscacerts/tlsca.example.com-cert.pem
export CHANNEL_NAME=mychannel
检查变量已经被设置了
echo $ORDERER_CA && echo $CHANNEL_NAME
注意:重启Org3CLI容器后,需要重新设置变量ORDERER_CA
和 CHANNEL_NAME
获取配置
配置了上述的两个变量后,现在可以拉取最新的通道配置块-mychannel
拉取最新版的配置的原因是通道配置元素是版本化存储的。版本控制之所以重要有如下原因。它防止配置更改被重复和重放(例如,使用旧的CRL恢复通道配置可能会带来安全风险)。它还有助于保证并发性(如果你想从通道中删除一个组织,例如,在添加新组织后,版本控制将有助于防止您同时删除两个组织,而不仅仅是要删除的组织)。
Org3还不是通道成员,我们需要以其它组织的admin来拉取通道配置。我们选Org1的管理员
# you can issue all of these commands at once
export CORE_PEER_LOCALMSPID="Org1MSP"
export CORE_PEER_TLS_ROOTCERT_FILE=/opt/gopath/src/github.com/hyperledger/fabric/peer/organizations/peerOrganizations/org1.example.com/peers/peer0.org1.example.com/tls/ca.crt
export CORE_PEER_MSPCONFIGPATH=/opt/gopath/src/github.com/hyperledger/fabric/peer/organizations/peerOrganizations/org1.example.com/users/Admin@org1.example.com/msp
export CORE_PEER_ADDRESS=peer0.org1.example.com:7051
此时可以拉取配置区块
peer channel fetch config config_block.pb -o orderer.example.com:7050 -c $CHANNEL_NAME --tls --cafile $ORDERER_CA
此命令将会把配置区块保存成config_block.pb。注意,名称和文件扩展名的选择是任意的。但是,建议遵循一个即标识要标识的对象类型又标识其编码(protobuf或JSON)的约定。
当你执行了peer channel fetch命令,接下来的会显示输出:
2017-11-07 17:17:57.383 UTC [channelCmd] readBlock -> DEBU 011 Received block: 2
这是告诉我们最近的mychannel配置区块是区块2,不是创始区块。默认的,peer channel fetch config命令会返回通道的最新的配置区块,本例中是第三个区块。这是因为test network的脚本network.sh,为Org1和Org2定义了锚节点,有两个独立的通道更新事务。因此,我们有如下的配置次序:
- block 0:genesis block
- block 1: Org1锚节点升级
- block 2:Org2锚节点升级
将配置转换为JSON并将其精简
接下来使用configtxlator
来编码通道配置区块为JSON格式(人可读可编辑)。我们必须剥去所有的headers,metadata,作者签名,还有不相关的配置。我们完成这个通过jq工具:
configtxlator proto_decode --input config_block.pb --type common.Block | jq .data.data[0].payload.data.config > config.json
这个命令会生成一个剪切后的JSON,config.json,用来做本次升级的基础文件。
打开文件,即使你读完本文档,仍然值得学习其中的配置结构和其它通道升级的的配置。会在Updating a channel configuration中讨论。
添加Org3的秘钥素材
注意:无论修改什么配置到这一步都是相同的。我们选择增加通道是因为这可能是你尝试的最复杂的配置升级之一。
我们再次使用jq工具将Org3配置定义Org3.json附加到通道的application groups字段中,并将输出命名为modified_config.json。
jq -s '.[0] * {"channel_group":{"groups":{"Application":{"groups": {"Org3MSP":.[1]}}}}}' config.json ./organizations/peerOrganizations/org3.example.com/org3.json > modified_config.json
现在,在容器Org3CLI容器中我们有两个JSON文件需要关注,config.json和modified_config.json。初始的文件只包含Org1和Org2,鉴于modified文件包含了三个Orgs。此时只需要重新编码两个JSON文件并计算不同。
首先,转换 config.json到config.pb:
configtxlator proto_encode --input config.json --type common.Config --output config.pb
接下来,编译modified_config.json
到 modified_config.pb
configtxlator proto_encode --input modified_config.json --type common.Config --output modified_config.pb
现在使用configtxlator
来计算两个配置protobuf文件之间的不同。这个命令会输出一个新的文件org3_update.pb:
configtxlator compute_update --channel_id $CHANNEL_NAME --original config.pb --updated modified_config.pb --output org3_update.pb
新的org3_update.pb包含了Org3的定义和Org1和Org2的素材。我们可以放弃Org1和Org2的大量MSP材料和修改策略信息,因为这些数据已经存在于通道genesis块中。严格来说,我们只需要两个配置文件之间的不同。
在提交通道升级之前,我们需要执行接下来的步骤。首先,将其转换为JSON格式org3_update.json
configtxlator proto_decode --input org3_update.pb --type common.ConfigUpdate | jq . > org3_update.json
现在有了升级的文件 org3_update.json,我们需要将信息封装起来。这步我们会将header部分再加回去。命名为org3_update_in_envelope.json
echo '{"payload":{"header":{"channel_header":{"channel_id":"'$CHANNEL_NAME'", "type":2}},"data":{"config_update":'$(cat org3_update.json)'}}}' | jq . > org3_update_in_envelope.json
使用正确文件org3_update_in_envelope.json,我们将最后一次利用configtxlator工具来转化格式。最后的文件命名为org3_update_in_envelope.pb
configtxlator proto_encode --input org3_update_in_envelope.json --type common.Envelope --output org3_update_in_envelope.pb
签署并提交配置更新
差不多了!
在Org3CLI容器中有了org3_update_in_envelope.pb。但是,在将配置写入到账本之前,我们需要必要的管理员签名。通道应用组的修改策略(mod_policy)设置为默认的“MAJORITY”,意味着我们需要大多数现有的管理员来签署它。因为我们只有两个组织Org1和Org2,大多数就是2,需要两个组织都签名。如果不签名,ordering service会拒绝事务因为不满足策略。
首先,先以Org1来签名。我们现在是以Org1的环境变量在操作Org3CLI。因此,peer channel signconfigtx命令执行时是以Org1身份来操作
peer channel signconfigtx -f org3_update_in_envelope.pb
最后一步,切换到Org2管理员。通过指定4个环境变量。
注意:切换组织来签署配置事务(其它的配置也一样)并不能反应真实世界的Fabric操作。一个容器也不会挂在所有的秘钥素材。确切的讲,配置更新需要安全的传递给Org2的管理员以供视察和审议。
配置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/organizations/peerOrganizations/org2.example.com/peers/peer0.org2.example.com/tls/ca.crt
export CORE_PEER_MSPCONFIGPATH=/opt/gopath/src/github.com/hyperledger/fabric/peer/organizations/peerOrganizations/org2.example.com/users/Admin@org2.example.com/msp
export CORE_PEER_ADDRESS=peer0.org2.example.com:9051
最后,执行peer channel update命令。Org2管理员签名将附加到此调用,因此无需再次手动签署协议。
注意:即将对ordering service的更新调用将进行一些列系统签名和策略检查。因此,流式处理和检查排序节点的日志很有用。可以在Org3CL容器之外的终端执行docker logs -f orderer.example.com来显示。
调用升级:
peer channel update -f org3_update_in_envelope.pb -c $CHANNEL_NAME -o orderer.example.com:7050 --tls --cafile $ORDERER_CA
你会看到一个类似的信息输出:
2020-01-09 21:30:45.791 UTC [channelCmd] update -> INFO 002 Successfully submitted channel update
一个成功的通道升级调用返回一个新的区块 block 3,所有的peer都已经加入到通道。如果你记得block 0-2是通道的初始化配置。Block 3用作在当前通道上定义了Org3的最新通道配置。
你可以在Org3CLI容器之外检查peer0.org1.example.com的日志:
docker logs -f peer0.org1.example.com
将Org3加入到通道
至此,通道配置已经升级且包含了新的组织Org3,意味者相关peer已经可以加入到通道。
在OrgCLI容器中,设置如下环境变量来切换到Org3的管理员:
# you can issue all of these commands at once
export CORE_PEER_LOCALMSPID="Org3MSP"
export CORE_PEER_TLS_ROOTCERT_FILE=/opt/gopath/src/github.com/hyperledger/fabric/peer/organizations/peerOrganizations/org3.example.com/peers/peer0.org3.example.com/tls/ca.crt
export CORE_PEER_MSPCONFIGPATH=/opt/gopath/src/github.com/hyperledger/fabric/peer/organizations/peerOrganizations/org3.example.com/users/Admin@org3.example.com/msp
export CORE_PEER_ADDRESS=peer0.org3.example.com:11051
现在我们从ordering service调用mychannel创始区块。作为一次成功的通道升级,ordering service会验证Org3并且拉取创始区块并加入通道。如果Org3没有成功的加入到通道,则ordering service会拒绝请求。
注意:再一次,你可能会找到排序节点的日志会很有用,签名,验证逻辑和策略检查。
使用peer channel fetch命令来获取区块:
peer channel fetch 0 mychannel.block -o orderer.example.com:7050 -c $CHANNEL_NAME --tls --cafile $ORDERER_CA
注意,我们传递了0来标识想要通道上的第一个区块:创始区块。如果我们直接使用peer channel fetch config,我们会接收block 3 — 升级Org3定义的区块。然而我们不能从后续的区块开始,我们必须从区块0开始。
如果成功了,会返回创始区块且命名为mychannel.block,我们可以使用这个区块来将peer加入到通道中。使用peer channel join命令将peer加入通道。
peer channel join -b mychannel.block
配置领导选举
注意:在初始通道配置完成后,将组织添加到网络时,本节作为了解领导者选举设置的参考。此示例为动态领导者选举,需要所有peer在网络中共同设置。
创始区块引导新加入的peer节点,它不包含在通道配置更新中新添加的组织信息。因此,新的peer无法利用gossip,因为在获得将组织添加到通道配置事务之前,他们无法验证其它peer从自己的组织传来的区块。新加入的peer必须有如下配置,这样才能接收来自ordering service的区块:
1.选择静态领导模式,配置一个peer成为组织的领导:
CORE_PEER_GOSSIP_USELEADERELECTION=false
CORE_PEER_GOSSIP_ORGLEADER=true
注意:这个设置在通道上的所有peer必须一致
2.选用动态选举模式
CORE_PEER_GOSSIP_USELEADERELECTION=true
CORE_PEER_GOSSIP_ORGLEADER=false
注意:因为新加入组织的peer无法形成成员视图,此选项将类似于静态设置,因此每一个peer都会宣告自己是领导者。因此,一旦他们收到增加组织到通道的事务,他们中只会有一个成为组织领导者。如果你最终希望组织的peer利用选举模式,建议利用此项。
安装,定义和调用链码
我们确认下Org3可以在通道mychannel上安装,调用链码。如果之前通道成员已经提交了链码定义到通道,新组织可以在审议链码之后使用链码。
注意:本说明使用Fabric的v2.0版本链码lifecycle。如果想使用v1.4请访问 Adding an org to a channel tutorial
在我们以Org3的身份安装链码,我们可以使用./network.sh脚本来部署Fabcar链码。在Org3CLI容器之外打开一个新的终端并切换到test-network目录。可以使用test-network脚本来部署Fabcar链码:
cd fabric-samples/test-network
./network.sh deployCC
脚本会在Org1和Org2上安装Fabcar,为Org1和Org2审议了链码定义,然后提交链码定义到通道。一旦链码定义被提交到通道,链码会初始化并调用账本数据。下面的命令假设我们仍在使用通道mychannel。
链码部署后我们可以使用以下几步来作为以Org3身份调用链码。这些步骤全都在目录test-network中,不必非进入Org3CLI容器中,复制和黏贴接下来的环境变量:
export PATH=${PWD}/../bin:$PATH
export FABRIC_CFG_PATH=$PWD/../config/
export CORE_PEER_TLS_ENABLED=true
export CORE_PEER_LOCALMSPID="Org3MSP"
export CORE_PEER_TLS_ROOTCERT_FILE=${PWD}/organizations/peerOrganizations/org3.example.com/peers/peer0.org3.example.com/tls/ca.crt
export CORE_PEER_MSPCONFIGPATH=${PWD}/organizations/peerOrganizations/org3.example.com/users/Admin@org3.example.com/msp
export CORE_PEER_ADDRESS=localhost:11051
第一步打包链码:
peer lifecycle chaincode package fabcar.tar.gz --path ../chaincode/fabcar/go/ --lang golang --label fabcar_1
产生fabcar.tar.gz,并可以安装在Org3节点上。相应的修改命令如果链码使用Java或者Node.js。安装链码
peer lifecycle chaincode install fabcar.tar.gz
下一步是审议链码定义。Org3需要审议和Org1和Org2一样的链码定义并提交到通道中。为了调用链码,Org3需要包含定义标识在链码定义中。你可以通过peer查询来找链码标识:
peer lifecycle chaincode queryinstalled
你需要看到如下输出
Get installed chaincodes on peer:
Package ID: fabcar_1:25f28c212da84a8eca44d14cf12549d8f7b674a0d8288245561246fa90f7ab03, Label: fabcar_1
以后会用到package ID,所以将其放入环境变量中,注意更换成你自己的Packge ID
export CC_PACKAGE_ID=fabcar_1:25f28c212da84a8eca44d14cf12549d8f7b674a0d8288245561246fa90f7ab03
Org3审议链码定义
# use the --package-id flag to provide the package identifier
# use the --init-required flag to request the ``Init`` function be invoked to initialize the chaincode
peer lifecycle chaincode approveformyorg -o localhost:7050 --ordererTLSHostnameOverride orderer.example.com --channelID mychannel --name fabcar --version 1 --init-required --package-id $CC_PACKAGE_ID --sequence 1 --tls --cafile ${PWD}/organizations/ordererOrganizations/example.com/orderers/orderer.example.com/msp/tlscacerts/tlsca.example.com-cert.pem
使用peer lifecycle chaincode querycommitted命令查询审议过的链码定义是否以被提交到通道。
# use the --name flag to select the chaincode whose definition you want to query
peer lifecycle chaincode querycommitted --channelID mychannel --name fabcar --cafile ${PWD}/organizations/ordererOrganizations/example.com/orderers/orderer.example.com/msp/tlscacerts/tlsca.example.com-cert.pem
返回如下
Committed chaincode definition for chaincode 'fabcar' on channel 'mychannel':
Version: 1, Sequence: 1, Endorsement Plugin: escc, Validation Plugin: vscc, Approvals: [Org1MSP: true, Org2MSP: true, Org3MSP: true]
Org3可以使用自己已经审议且链码定义早已提交到通道的链码,链码定义使用默认的背书策略,需要大多数组织认可一项交易。这意味着,如果将组织添加到通道或从通道中删除,则会自动更新背书策略。之前需要Org1和Org2背书(2/2),现在需要三个组织中的两个(2/3).
查询账本确保链码已经在Org3节点运行。注意我们此时需要链码容器启动
peer chaincode query -C mychannel -n fabcar -c '{"Args":["queryAllCars"]}'
会看到初始化时加入的数据
接下来增加一条数据,从Org1和Org3中选一个peer来收集足够多的背书
peer chaincode invoke -o localhost:7050 --ordererTLSHostnameOverride orderer.example.com --tls --cafile ${PWD}/organizations/ordererOrganizations/example.com/orderers/orderer.example.com/msp/tlscacerts/tlsca.example.com-cert.pem -C mychannel -n fabcar --peerAddresses localhost:7051 --tlsRootCertFiles ${PWD}/organizations/peerOrganizations/org1.example.com/peers/peer0.org1.example.com/tls/ca.crt --peerAddresses localhost:11051 --tlsRootCertFiles ${PWD}/organizations/peerOrganizations/org3.example.com/peers/peer0.org3.example.com/tls/ca.crt -c '{"function":"createCar","Args":["CAR11","Honda","Accord","Black","Tom"]}'
我们可以在账本中看到新的数据
peer chaincode query -C mychannel -n fabcar -c '{"Args":["queryCar","CAR11"]}'
结论
通道配置更新过程确实非常复杂,但是有一个逻辑方法来完成各个步骤。最后,形成一个以protobuf二进制格式表示的delta事务对象,然后获取所需数量的管理签名,以便通道配置更新事务满足通道的修改策略。
configtxlator
,jq
,peer channel命令,提供了完成任务的功能。
更新通道配置以包含Org3的锚节点(可选)
因为Org1和Org2已经建立了锚节点链接,所以Org3可以建立gossip链接到Org1和Org2上。同样,像Org3这样新添加的组织也应该在通道配置中定义他们的锚节点,以便来自其它组织的新peer可以直接发现Org3的peer。这部分我们会做一个通道配置升级来定定义Org3的锚节点。过程和之前的类似,因此这次我们快点操作
进入到容器Org3CLI:
docker exec -it Org3cli bash
设置 $ORDERER_CA 和 $CHANNEL_NAME:
export ORDERER_CA=/opt/gopath/src/github.com/hyperledger/fabric/peer/organizations/ordererOrganizations/example.com/orderers/orderer.example.com/msp/tlscacerts/tlsca.example.com-cert.pem
export CHANNEL_NAME=mychannel
依旧,我们仍然拉取最新的通道配置来开始。在Org3CLI容器中,拉取通道最新的配置区块,使用如下命令:
peer channel fetch config config_block.pb -o orderer.example.com:7050 -c $CHANNEL_NAME --tls --cafile $ORDERER_CA
拉取之后转换到JSON格式。使用configtxlator工具,像之前添加组织Org3一样。转换时需要去掉headers,metadata,和signatures升级锚节点不需要的配置。提交更改的配置之前再加回来。
configtxlator proto_decode --input config_block.pb --type common.Block | jq .data.data[0].payload.data.config > config.json
config.json是我们即将修改的文件。
使用jq工具,增加Org3的锚节点
jq '.channel_group.groups.Application.groups.Org3MSP.values += {"AnchorPeers":{"mod_policy": "Admins","value":{"anchor_peers": [{"host": "peer0.org3.example.com","port": 11051}]},"version": "0"}}' config.json > modified_anchor_config.json
现在有两个文件了,config.json和更改后的modified_anchor_config.json。下一步将其转换到protobuf格式并且计算二者不同。
转换config.json到protobuf格式config.pb
configtxlator proto_encode --input config.json --type common.Config --output config.pb
转换modified_anchor_config.json到modified_anchor_config.pb
configtxlator proto_encode --input modified_anchor_config.json --type common.Config --output modified_anchor_config.pb
计算两者不同之处
configtxlator compute_update --channel_id $CHANNEL_NAME --original config.pb --updated modified_anchor_config.pb --output anchor_update.pb
现在我们已经对通道进行了所需的更新,我们必须将其包装在信封消息中,以便能够正确的读取。要做这些我们首先需要将protobuf转换到json。
使用configtxlator 将anchor_update.pb转换到anchor_update.json
configtxlator proto_decode --input anchor_update.pb --type common.ConfigUpdate | jq . > anchor_update.json
下一步包装信息,重新将之前去掉的内容加入进来,输出为anchor_update_in_envelope.json
echo '{"payload":{"header":{"channel_header":{"channel_id":"'$CHANNEL_NAME'", "type":2}},"data":{"config_update":'$(cat anchor_update.json)'}}}' | jq . > anchor_update_in_envelope.json
现在我们已经重新合并了信封,我们需要将其转换为protobuf,这样它就可以正确地签名并提交给order节点进行更新。
configtxlator proto_encode --input anchor_update_in_envelope.json --type common.Envelope --output anchor_update_in_envelope.pb
既然更新已经转换成正确的格式,现在是时候签名并提交它了。因为这是对Org3的更新,所以我们只需要让Org3在更新上签名。
配置环境变量以Org3管理员身份操作
# you can issue all of these commands at once
export CORE_PEER_LOCALMSPID="Org3MSP"
export CORE_PEER_TLS_ROOTCERT_FILE=/opt/gopath/src/github.com/hyperledger/fabric/peer/organizations/peerOrganizations/org3.example.com/peers/peer0.org3.example.com/tls/ca.crt
export CORE_PEER_MSPCONFIGPATH=/opt/gopath/src/github.com/hyperledger/fabric/peer/organizations/peerOrganizations/org3.example.com/users/Admin@org3.example.com/msp
export CORE_PEER_ADDRESS=peer0.org3.example.com:11051
在提交到排序节点之前,以Org3管理员身份运行peer channel update命令。
peer channel update -f anchor_update_in_envelope.pb -c $CHANNEL_NAME -o orderer.example.com:7050 --tls --cafile $ORDERER_CA
排序节点接收到升级并使用配置cut a block。当peer接收到了这个区块,它们会升级配置。
检查一个peer的日志。在处理来自新区块的事务时,会看到gossip重新和Org3的锚节点建立链接。这个证明配置升级已经成功了
docker logs -f peer0.org1.example.com
2019-06-12 17:08:57.924 UTC [gossip.gossip] learnAnchorPeers -> INFO 89a Learning about the configured anchor peers of Org1MSP for channel mychannel : [{peer0.org1.example.com 7051}]
2019-06-12 17:08:57.926 UTC [gossip.gossip] learnAnchorPeers -> INFO 89b Learning about the configured anchor peers of Org2MSP for channel mychannel : [{peer0.org2.example.com 9051}]
2019-06-12 17:08:57.926 UTC [gossip.gossip] learnAnchorPeers -> INFO 89c Learning about the configured anchor peers of Org3MSP for channel mychannel : [{peer0.org3.example.com 11051}]
恭喜,你已经完成了两项配置升级,一个是增加组织Org3到通道中,另一个是为Org3定义了锚节点。