因爲Hyperledger Fabric目前沒有提供動態更新配置的API,只能經過peer命令來發送protobuf數據,因此配置更新很是的繁瑣。
本例以向Orderer Group添加Capabilities Requirements和給Channel增長Organization爲例,詳細記錄Fabric v1.1下更新配置的步驟。html
本文的樣例初始配置來自Fabric v1.0,包含1個Orderer服務節點和2個Organization.linux
configtx.yaml配置文件Orderer部份內容以下 Profiles: TwoOrgsOrdererGenesis: Orderer: <<: *OrdererDefaults Organizations: - *OrdererOrg Consortiums: SampleConsortium: Organizations: - *Org1 - *Org2 TwoOrgsChannel: Consortium: SampleConsortium Application: <<: *ApplicationDefaults Organizations: - *Org1 - *Org2
# 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
# 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
configtxlator v1.0.x版本只能運行成server, v1.1.x可做爲命令行工具單獨使用,也可運行成server來提供服務
本例中運行爲server, 工具默認會監聽本地7059端口,也可指定端口docker
$ configtxlator start 2018-05-03 09:28:18.090 CST [configtxlator] startServer -> INFO 001 Serving HTTP requests on 0.0.0.0:7059
$ 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,不然只能拉取配置,不能推送回去。json
$ peer channel fetch config config_block.pb -o orderer.example.com:7050 -c $CH_NAME --tls --cafile $ORDERER_CA
命令運行成功會把被encode的配置寫入config_block.pb文件curl
$ curl -s -X POST --data-binary @config_block.pb http://localhost:7059/protolator/decode/common.Block" | jq . > config_block.json
這裏根據消息類型的不一樣,調用的URL也會有不一樣,本例中用到的是common.Block
其餘的類型我之後會深刻研究一下。工具
$ jq .data.data[0].payload.data.config config_block.json > config.json
這裏是和更新配置相關度最高的一步,其餘步驟基本都是標準的流程.fetch
$ 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中的內容:ui
{ "mod_policy": "Admins", "value": { "capabilities": { "V1_1": {} } }, "version": "0" }
$ curl -s -X POST --data-binary @config.json http://localhost:7059/protolator/encode/common.Config > config.pb
$ curl -s -X POST --data-binary @updated_config.json http://localhost:7059/protolator/encode/common.Config > updated_config.pb
$ 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
$ 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": {} } },
$ echo '{"payload":{"header":{"channel_header":{"channel_id":"'$CH_NAME'", "type":2}},"data":{"config_update":'$(cat config_update.json)'}}}' | jq . > config_update_in_envelope.json
$ curl -s -X POST --data-binary @config_update_in_envelope.json http://localhost:7059/protolator/encode/common.Envelope > config_update_in_envelope.pb
$ 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,遇到了以下錯誤:url
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.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
更新Channel level的配置和更新Orderer相似,這節主要寫的是和第3節差別的地方
看看創世塊, 使用configtxlator工具,把創世塊解碼成json,咱們會發現
Organization的crypto信息也被寫在了配置中,那麼手動構造這些json就太複雜了.
這裏有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
步驟與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了.
http://hyperledger-fabric.rea...
http://hyperledger-fabric.rea...