1. 概览
由于Hyperledger Fabric目前没有提供动态更新配置的API,只能通过peer命令来发送protobuf数据,所以配置更新非常的繁琐。
本例以向Orderer Group添加Capabilities Requirements和给Channel增加Organization为例,详细记录Fabric v1.1下更新配置的步骤。
2. 条件
2.1. 初始配置
本文的样例初始配置来自Fabric v1.0,包含1个Orderer服务节点和2个Organization.
configtx.yaml配置文件Orderer部分内容如下
Profiles:
TwoOrgsOrdererGenesis:
Orderer:
<<: *OrdererDefaults
Organizations:
- *OrdererOrg
Consortiums:
SampleConsortium:
Organizations:
- *Org1
- *Org2
TwoOrgsChannel:
Consortium: SampleConsortium
Application:
<<: *ApplicationDefaults
Organizations:
- *Org1
- *Org2
2.2. Fabric环境:
# docker ps
IMAGE NAMES
hyperledger/fabric-tools:x86_64-1.1.0 cli
hyperledger/fabric-peer:x86_64-1.1.0 peer0.org1.example.com
hyperledger/fabric-peer:x86_64-1.1.0 peer1.org2.example.com
hyperledger/fabric-peer:x86_64-1.1.0 peer0.org2.example.com
hyperledger/fabric-peer:x86_64-1.1.0 peer1.org1.example.com
hyperledger/fabric-ca:x86_64-1.1.0 ca_peerOrg2
hyperledger/fabric-ca:x86_64-1.1.0 ca_peerOrg1
hyperledger/fabric-orderer:x86_64-1.1.0 orderer.example.com
2.3. Tools:
# Fabric的peer,用来拉取和推送配置
$ peer --version
peer:
Version: 1.1.0
Go version: go1.9.2
OS/Arch: linux/amd64
Experimental features: false
Chaincode:
Base Image Version: 0.4.6
Base Docker Namespace: hyperledger
Base Docker Label: org.hyperledger.fabric
Docker Namespace: hyperledge
# Fabric的configtxlator, 用于在protobuf和json间做转换,以及计算配置的差异
$ configtxlator --help
usage: configtxlator [<flags>] <command> [<args> ...]
Utility for generating Hyperledger Fabric channel configurations
Flags:
--help Show context-sensitive help (also try --help-long and --help-man).
Commands:
help [<command>...]
Show help.
start [<flags>]
Start the configtxlator REST server
proto_encode --type=TYPE [<flags>]
Converts a JSON document to protobuf.
proto_decode --type=TYPE [<flags>]
Converts a proto message to JSON.
compute_update --channel_id=CHANNEL_ID [<flags>]
Takes two marshaled common.Config messages and computes the config update which transitions between the two.
version
Show version information
$ configtxlator version
configtxlator:
Version: 1.1.1-snapshot-c257bb3
Go version: go1.10.1
OS/Arch: linux/amd64
#jq, 用于读写json文件.
$ apt install jq
3. 更新Capabilities Requirements的步骤
3.1. 启动configtxlator.
configtxlator v1.0.x版本只能运行成server, v1.1.x可作为命令行工具单独使用,也可运行成server来提供服务
本例中运行为server, 工具默认会监听本地7059端口,也可指定端口
$ configtxlator start
2018-05-03 09:28:18.090 CST [configtxlator] startServer -> INFO 001 Serving HTTP requests on 0.0.0.0:7059
3.2. 设置Fabric CLI运行环境变量
$ env |grep CORE
CORE_PEER_LOCALMSPID=OrdererMSP
CORE_VM_ENDPOINT=unix:///host/var/run/docker.sock
CORE_PEER_TLS_ENABLED=true
CORE_PEER_MSPCONFIGPATH=/etc/hyperledger/crypto/users/Admin@example.com/msp
CORE_PEER_ID=cli
CORE_PEER_ADDRESS=peer0.org1.example.com:7051
ORDERER_CA=/etc/hyperledger/crypto/orderer/tls/ca.crt
CH_NAME=mychannel
其中CORE_PEER_LOCALMSPID 和 CORE_PEER_MSPCONFIGPATH要注意一定要使用Orderer的Admin,否则只能拉取配置,不能推送回去。
3.3 使用Fabric CLI拉取配置
$ peer channel fetch config config_block.pb -o orderer.example.com:7050 -c $CH_NAME --tls --cafile $ORDERER_CA
命令运行成功会把被encode的配置写入config_block.pb文件
3.4 把配置转成可读的json格式
$ curl -s -X POST --data-binary @config_block.pb http://localhost:7059/protolator/decode/common.Block" | jq . > config_block.json
这里根据消息类型的不同,调用的URL也会有不同,本例中用到的是common.Block
其他的类型我以后会深入研究一下。
3.5 从json中取出配置部分
$ jq .data.data[0].payload.data.config config_block.json > config.json
3.6 把要更新的内容加入当前的配置json
这里是和更新配置相关度最高的一步,其他步骤基本都是标准的流程.
$ jq -s '.[0] * {"channel_group":{"groups":{"Orderer": {"values": {"Capabilities": .[1]}}}}}' config.json capability.json > updated_config.json
这一步在channel_group.groups.Orderer.values中加入Capabilities这个key,value是capability.json中的内容:
{
"mod_policy": "Admins",
"value": {
"capabilities": {
"V1_1": {}
}
},
"version": "0"
}
3.7 把原始的配置的json数据转换成pb
$ curl -s -X POST --data-binary @config.json http://localhost:7059/protolator/encode/common.Config > config.pb
3.8 把更新后配置的json数据转换成pb
$ curl -s -X POST --data-binary @updated_config.json http://localhost:7059/protolator/encode/common.Config > updated_config.pb
3.9 获取更新后的配置和原始配置的相比需要update的部分
$ curl -s -X POST -F channel="${CH_NAME}" -F "original=@config.pb" -F "updated=@updated_config.pb" http://localhost:7059/configtxlator/compute/update-from-configs > config_update.pb
3.10 把update转换成可读的json
$ curl -s -X POST --data-binary @config_update.pb http://localhost:7059/protolator/decode/common.ConfigUpdate" | jq . > config_update.json
其中可以找到我们需要update的部分:
$ grep -A6 Capabilities config_update.json
"Capabilities": {
"mod_policy": "Admins",
"value": {
"capabilities": {
"V1_1": {}
}
},
3.11 把update打包成Fabric CLI协议的json格式
$ echo '{"payload":{"header":{"channel_header":{"channel_id":"'$CH_NAME'", "type":2}},"data":{"config_update":'$(cat config_update.json)'}}}' | jq . > config_update_in_envelope.json
3.12 把json编码成pb格式
$ curl -s -X POST --data-binary @config_update_in_envelope.json http://localhost:7059/protolator/encode/common.Envelope > config_update_in_envelope.pb
3.13 把最终的update提交到channel
$ peer channel update -f 'config_update_in_envelope.pb' -o orderer.example.com:7050 -c $CH_NAME --tls --cafile $ORDERER_CA
2018-05-03 03:01:56.403 UTC [channelCmd] InitCmdFactory -> INFO 001 Endorser and orderer connections initialized
2018-05-03 03:01:56.488 UTC [channelCmd] update -> INFO 002 Successfully submitted channel update
2018-05-03 03:01:56.488 UTC [main] main -> INFO 003 Exiting....
我最初没有使用Admin MSP,遇到了如下错误:
2018-05-02 15:04:24.739 UTC [channelCmd] InitCmdFactory -> INFO 002 Endorser and orderer connections initialized
Error: got unexpected status: BAD_REQUEST -- error authorizing update: error validating DeltaSet: policy for [Group] /Channel/Orderer not satisfied: Failed to reach implicit threshold of 1 sub-policies, required 1 remaining
3.14. 验证
使用3.3和3.4中的方法拉取并解析配置,发现配置文件中已经有了Capabilities的内容
$ peer channel fetch config config_block.pb -o orderer.example.com:7050 -c $CH_NAME --tls --cafile $ORDERER_CA
$ curl -s -X POST --data-binary @config_block.pb http://localhost:7059/protolator/decode/common.Block" | jq . > config_block.json
$ grep Capabilities -A6 config_block.json
"Capabilities": {
"mod_policy": "Admins",
"value": {
"capabilities": {
"V1_1": {}
}
},
整个过程用到的文件如下:
0.config_block.pb
1.config_block.json
2.config.json
3.updated_config.json
4.config.pb
5.updated_config.pb
6.config_update.pb
7.config_update.json
8.config_update_in_envelope.json
9.config_update_in_envelope.pb
capabilities.json
4. 给Channel添加Organization的步骤
更新Channel level的配置和更新Orderer类似,这节主要写的是和第3节差异的地方
4.1 更新Organization需要update哪些数据?
看看创世块, 使用configtxlator工具,把创世块解码成json,我们会发现
Organization的crypto信息也被写在了配置中,那么手动构造这些json就太复杂了.
4.2 生成新的Org配置
这里有2种方法
1:
在原有的cryptogen.yaml和configtx.yaml里添加Org3相关部分,使用cryptogen和configtxgen重新生成crypto和genesis block到独立的目录.
然后把新的crypto目录中org3的目录拷贝到原有的crypto目录下对应的路径.
再把原有的genesis block和新的genesis block使用configtxlator工具解码,使用diff工具比较解码后的json文件. 得出需要update的部分
2:
新建org3-crypto.yaml和configtx.yaml文件,其中只描述Org3相关内容,然后运行cryptogen和configtxgen.
把新的crypto目录中org3的目录拷贝到原有的crypto目录下对应的路径.
cryptogen.yaml配置样例:
PeerOrgs:
- Name: Org3
Domain: org3.example.com
EnableNodeOUs: true
Template:
Count: 2
Users:
Count: 1
cryptogen命令:
cryptogen generate --config=./org3-crypto.yaml
configtx.yaml配置样例:
Organizations:
- &Org3
Name: Org3MSP
ID: Org3MSP
MSPDir: crypto-config/peerOrganizations/org3.example.com/msp
AnchorPeers:
- Host: peer0.org3.example.com
Port: 7051
configtxgen命令:
$ configtxgen -printOrg Org3MSP > patch.json
这个patch.json就是要update给Channel的内容了.
我选择了方法2
4.3 更新步骤
步骤与3.3 - 3.13类似
与3.6不同之处:
jq -s '.[0] * {"channel_group":{"groups":{"Consortiums": {"groups": {"SampleConsortium": {"groups": {"Org3MSP": .[1]}}}}}}}' config.json patch.json > updated_config.json
与3.13不同之处:
由于这里更新的是Channel的Org配置,Channel的修改策略默认是超过半数通过.
假设此Channel中已经有2个Org,则需2个Org签名来通过block上链
Organization CLI:
首先切换当前CLI环境到Org1 Admin
$ env |grep CORE
CORE_PEER_TLS_ROOTCERT_FILE=/etc/hyperledger/crypto/peers/tls/ca.crt
CORE_PEER_LOCALMSPID=Org1MSP
CORE_PEER_TLS_ENABLED=true
CORE_PEER_MSPCONFIGPATH=/etc/hyperledger/crypto/users/Admin@org1.example.com/msp
CORE_PEER_ID=cli.org1
CORE_LOGGING_LEVEL=DEBUG
CORE_PEER_ADDRESS=peer0.org1.example.com:7051
Org1签名:
$ peer channel signconfigtx config_update_in_envelope.pb
Org1签名后pb文件追加了部分内容,把pb文件放在Org2 CLI可以访问的路径,切换CLI环境到Org2 Admin:
$ env |grep CORE
CORE_PEER_TLS_ROOTCERT_FILE=/etc/hyperledger/crypto/peers/tls/ca.crt
CORE_PEER_LOCALMSPID=Org2MSP
CORE_PEER_TLS_ENABLED=true
CORE_PEER_MSPCONFIGPATH=/etc/hyperledger/crypto/users/Admin@org2.example.com/msp
CORE_PEER_ID=cli.org2
CORE_LOGGING_LEVEL=DEBUG
CORE_PEER_ADDRESS=peer0.org2.example.com:7051
Org2提交update到Channel,会自动附上Org2的签名:
$ peer channel update -f 'config_update_in_envelope.pb' -o orderer.example.com:7050 -c $CH_NAME --tls --cafile $ORDERER_CA
2018-05-04 05:35:00.422 UTC [channelCmd] update -> INFO 010 Successfully submitted channel update
2018-05-04 05:35:00.423 UTC [main] main -> INFO 011 Exiting.....
完成,验证方法与3节一致.
至此,可以启动Org3的peer节点并让Org3加入Channel了.
5. 参考
http://hyperledger-fabric.rea...
http://hyperledger-fabric.rea...
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。