Hyperledger Fabric v1.1 在線更新配置的步驟

1. 概覽

因爲Hyperledger Fabric目前沒有提供動態更新配置的API,只能經過peer命令來發送protobuf數據,因此配置更新很是的繁瑣。
本例以向Orderer Group添加Capabilities Requirements和給Channel增長Organization爲例,詳細記錄Fabric v1.1下更新配置的步驟。html

2. 條件

2.1. 初始配置

本文的樣例初始配置來自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

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端口,也可指定端口docker

$ 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,不然只能拉取配置,不能推送回去。json

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文件curl

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

這裏是和更新配置相關度最高的一步,其餘步驟基本都是標準的流程.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"
}

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,遇到了以下錯誤: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.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就太複雜了.
clipboard.png

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...

相關文章
相關標籤/搜索