Fabric组织动态管理

团队介绍

我们是光大科技有限公司智能化平台团队区块链项目组,致力于构建集团区块链基础设施平台,提供区块链技术在金融行业的完备解决方案,降低区块链的开发、运维难度,助力集团数字化转型。我们团队拥有经验丰富的区块链领域技术专家和研发工程师,将不定期分享区块链及相关领域的技术文章和解决方案,和大家共同探索金融行业区块链技术的落地实践和发展趋势。

区块链本质上是满足最终一致性的去中心化、点对点,同时可以自建信任的分布式网络。在中心化系统中,经过了多年的理论探索和实践发展,已经比较成熟。而在去中心化的系统中,各个节点因为网络拥堵、性能限制、甚至网络攻击、作恶节点等原因,带来各自状态的不确定性,要解决一致性问题绝非易事。为此,区块链通过共识机制来解决一致性问题。所谓共识机制就是一种多方协作的运行机制,协调网络中的多参与方达成可被接受的唯一结果,并保证此过程正确有效且能持续运行。常见的共识机制有PoW、PoS、PBFT、Raft等,后续文中的共识以fabric联盟链最常见的Raft展开。

在fabric联盟链的网络中,网络拓扑关系及各项配置以区块的形式保存在创世区块中。任何操作都是一笔交易,无论是调用智能合约执行业务操作或是对配置的更改,都需要形成共识以后出块。如果在已经运行起来的联盟链网络中添加新的业务主体,需要修改现有配置,形成新的配置并通过共识上链,这个过程叫做组织的动态管理,组织动态管理分为动态添加和动态删除。

01

组织动态添加

Fabric组织动态管理

组织动态添加的时序图

准备好一个已经在运行的fabric联盟链网络,由以下容器构成。

Fabric组织动态管理

接下来准备需要动态添加的组织org3,使用命令行工具cryptogen generate –config=./org3-crypto.yaml生成组织org3的证书;

使用命令行工具configtxgen -printOrg Org3MSP > ../channel-artifacts/org3.json生成组织org3的配置。

获取最新的配置区块

首先,进入到CLI容器:

docker exec -it cli bash

设置ORDERER_CA和CHANNEL_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

拉取最新版本的配置区块,以二进制protobuf的形式保存在config_block.pb中:

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

Fabric组织动态管理

新组织配置添加到通道配置上

借助configtxlator二进制工具解析并裁剪PB格式的配置,并输出为config.json:

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

使用jq工具把准备工作生成的org3组织配置添加到通道的应用组字段,输出文件:modified_config.json:

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

现在我们有两个非常重要的json配置文件,config.json和modified_config.json,前者是包含org1和org2的通道配置,后者共包含三个组织org1、org2和org3的配置。

重新编码两个json文件并计算差异

首先,将config.json文件倒回到protobuf格式,命名为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配置的差异,并输出一个新的PB二进制文件org3_update.pb:

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

包装差异封皮

首先,我们将这个差异PB文件解码成可编辑的json格式,并命名为org3_update.json:

configtxlator proto_decode --input org3_update.pb --type common.ConfigUpdate | jq . > org3_update.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

最后一次使用configtxlator工具将json转换为Fabric需要的完整独立的protobuf:

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

用通道现有组织的身份签名

现在我们有一个可以用来更新通道配置的org3_update_in_envelope.pb文件,在把配置文件提交到Orderer节点之前,我们需要通道内现有的两个组织Org1、Org2签名,以满足共识机制,否则Orderer节点会因为不满足策略而拒绝这个交易。

使用Org1管理员的身份签名:

peer channel signconfigtx -f org3_update_in_envelope.pb 

接下来我们将MSP身份切换为Org2的管理员,并使用Org2管理员的身份签名。

导出Org2的环境变量:

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.crtexport CORE_PEER_MSPCONFIGPATH=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org2.example.com/users/Admin@org2.example.com/mspexport CORE_PEER_ADDRESS=peer0.org2.example.com:9051 

使用Org2管理员的身份签名:

peer channel signconfigtx -f org3_update_in_envelope.pb

发起通道配置更新调用

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

将新组织Org3加入通道

首先启动Org3的节点容器和cli容器:

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

docker-compose文件中已经桥接到了初始网络,cli容器和Org3的两个peer节点容器都可以连接到已经存在的节点和排序节点。

进入Org3的cli容器中:

docker exec -it Org3cli bash

和之前一样,设置好环境变量:

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

这时,我们去获取通道的创世区块。因为区块链中每一个账本都要保持一致性,所以必须要获取索引为0的区块:

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

在之前的步骤里,我们已经将Org3添加到通道配置中,所以Order节点可以成功校验这个请求中的Org3的签名,否则,Order节点会拒绝这个请求。

把Org3的第一个节点peer0加入到通道中(cli容器中默认env为peer0):

peer channel join -b mychannel.block

切换环境变量,把第二个节点peer1加入通道:

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:12051peer channel join -b mychannel.block

至此,我们成功的将新组织Org3动态加入到了已经运行的fabric联盟链网络。在裁剪新组织配置时进行了多次protobuf和json格式的转换,究其原因在于:fabric网络只接受完整的二进制protobuf格式文件,而profobuf仅能通过json的转换才可以做到可读的裁剪。同时,也由于fabric对于区块的定义复杂且庞大,UML类图如下:

Fabric组织动态管理

(图片来源于网络)

02

组织动态退出

Fabric组织动态管理

动态退出时序图

动态退出就是在已经运行中的联盟链网络中删除一个业务主体组织,实现步骤与动态添加正好相反,准备好的网络环境如下:

Fabric组织动态管理

获取最新通道配置块

进入cli容器:

docker exec -it cli bash

设置$ORDERER_CA和$CHANNEL_NAME环境变量:

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

获取通道配置:

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

删除通道上的现有组织Org3并生成新配置

将上一步获取到的配置config_block.pb转换为json:

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

删除json文件中的组织配置并生成新的json文件modify_config.json:

jq \'del(.channel_group.groups.Application.groups.Org3MSP)\' config.json > modify_config.json

把两个重要的json文件转换为PB:

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

计算两个配置的差异

使用二进制工具configtxlator计算差异并生成文件org3_delete.pb:

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

还原裁剪掉的头信息并包装成信封

把PB文件转换为json:

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

还原头信息并生成json org3_delete_in_envelope.json:

echo \'{\"payload\":{\"header\":{\"channel_header\":{\"channel_id\":\"\'$CHANNEL_NAME\'\", \"type\":2}},\"data\":{\"config_update\":\'$(cat org3_delete.json)\'}}}\' | jq . > org3_delete_in_envelope.json 

把json信封转成PB格式:

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

用通道组织身份签名

org1组织签名:

peer channel signconfigtx -f org3_delete_in_envelope.pb

导出org2组织身份的环境变量:

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.crtexport CORE_PEER_MSPCONFIGPATH=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org2.example.com/users/Admin@org2.example.com/mspexport CORE_PEER_ADDRESS=peer0.org2.example.com:9051

org2组织签名:

peer channel signconfigtx -f org3_delete_in_envelope.pb

发起通道配置更新调用

由组织org2的身份发起更新调用:

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

至此,组织org3就从通道mychannel中删除了。如果org3作为通道中某个链码的背书组织,参与了链码调用过程的背书。则原链码将无法执行任何invoke操作,此时可以通过upgrade链码,更新链码的背书策略,重新指定背书组织来实现链码正常运行。

通过对fabric联盟链的动态操作,可以灵活增减业务参与主体,细粒度的控制联盟内的成员。更好的支撑业务流转,满足不同业务模型,完成区块链网络的高效可信运转。

往期回顾

  1. 探秘微服务治理之Spring Cloud Netflix Eureka

  2. CDN加速原理

  3. mybatis框架的插件机制

  4. 玩转Selenium——Web页面自动化实战

欢迎关注EBCloud!

作者 | 栗石

原创文章,作者:EBCloud,如若转载,请注明出处:https://www.sudun.com/ask/33646.html

Like (0)
EBCloud的头像EBCloud
Previous 2024年4月2日 下午3:28
Next 2024年4月2日 下午3:28

相关推荐

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注