區(qū)塊鏈之Fabric(三)動態(tài)增刪機構

Fabric 是聯(lián)盟鏈,一個 channel 就好比一個聯(lián)盟,如果有新的機構需要加入,則必須得到聯(lián)盟內的成員的認可。

正是基于這樣的場景,fabric 在為 channel 新增 org 時,會涉及諸多的權限和證書操作。


為 Channel 動態(tài)新增 Org 有以下幾步:

  1. 為新 org 生成證書
  2. 為新 org 生成配置文件
  3. 生成和提交新 org 的配置
    1. peer channel fetch config 創(chuàng)建添加新 org 的配置交易,為網絡新增 org
    2. peer channel signconfigtx 為配置交易簽名,需網絡中 MAJORITY 的 org 都簽名
    3. peer channel update 提交簽名后的配置交易至 orderer
  4. 將新 org 添加入 channel
    1. 啟動新 org 集群,一般會有一個 cli 和多個 peer
    2. peer channel fetch 于 cli 中從 orderer 中獲取 channel 創(chuàng)世塊
    3. peer channel join 將新 org 下的 peer 加入 channel
  5. 升級chaincode和背書策略
    1. peer chaincode install 為新 org 的 peer 安裝 chaincode,于新 org 的 cli 中完成
    2. peer chaincode install, 為其他 org 升級 chaincode,于原 org 的 cli 中完成
    3. peer chaincode upgrade 升級背書策略,于原 org 的 cli 中完成
  6. 測試是否成功

此文通過 fabric-samples 下的 first-network 樣例為基礎,在其區(qū)塊鏈網絡上,為通道 mychannel 新增一個 Org3,Org3 包含兩個 peer。

初始環(huán)境

fabric-samples 地址為 https://github.com/hyperledger/fabric-samples , 本文采用其中的 first-network 實驗。

first-network 啟動后,會默認創(chuàng)建 1 個 orderer 節(jié)點,4個 peer 節(jié)點(其中 2個屬于 org1,2個屬于 org2),并提供一個 cli 用于相關操作。

docker ps 之后輸出如下:

CONTAINER ID        IMAGE                                                                                                  COMMAND                  CREATED              STATUS              PORTS                                              NAMES
a36d576296f4        dev-peer1.org2.example.com-mycc-1.0-26c2ef32838554aac4f7ad6f100aca865e87959c9a126e86d764c8d01f8346ab   "chaincode -peer.add…"   About a minute ago   Up About a minute                                                      dev-peer1.org2.example.com-mycc-1.0
70789dd829f0        dev-peer0.org1.example.com-mycc-1.0-384f11f484b9302df90b453200cfb25174305fce8f53f4e94d45ee3b6cab0ce9   "chaincode -peer.add…"   About a minute ago   Up About a minute                                                      dev-peer0.org1.example.com-mycc-1.0
c961ab191471        dev-peer0.org2.example.com-mycc-1.0-15b571b3ce849066b7ec74497da3b27e54e0df1345daff3951b94245ce09c42b   "chaincode -peer.add…"   About a minute ago   Up About a minute                                                      dev-peer0.org2.example.com-mycc-1.0
8314e683df95        hyperledger/fabric-tools:latest                                                                        "/bin/bash"              About a minute ago   Up About a minute                                                      cli
c80bb0cdbb3e        hyperledger/fabric-peer:latest                                                                         "peer node start"        About a minute ago   Up About a minute   0.0.0.0:8051->7051/tcp, 0.0.0.0:8053->7053/tcp     peer1.org1.example.com
656efc4c4b94        hyperledger/fabric-orderer:latest                                                                      "orderer"                About a minute ago   Up About a minute   0.0.0.0:7050->7050/tcp                             orderer.example.com
1f6777d60647        hyperledger/fabric-peer:latest                                                                         "peer node start"        About a minute ago   Up About a minute   0.0.0.0:10051->7051/tcp, 0.0.0.0:10053->7053/tcp   peer1.org2.example.com
8be768d5aed0        hyperledger/fabric-peer:latest                                                                         "peer node start"        About a minute ago   Up About a minute   0.0.0.0:9051->7051/tcp, 0.0.0.0:9053->7053/tcp     peer0.org2.example.com
0680044f68b9        hyperledger/fabric-peer:latest                                                                         "peer node start"        About a minute ago   Up About a minute   0.0.0.0:7051->7051/tcp, 0.0.0.0:7053->7053/tcp     peer0.org1.example.com


自動化動態(tài)添加

first-network 直接提供了自動化添加的腳本 eyfn.sh。執(zhí)行 ./eyfn.sh up 即可自動化為 channel 添加 org3。此法因不具擴展性,且不方便理解 fabric,因此不再贅述。以下是執(zhí)行后的輸出,若成功,會輸出 All GOOD 。

[work@gzhxy-fsg-fpu-hyperledger01 first-network]$ ./eyfn.sh up
Starting with channel 'mychannel' and CLI timeout of '10' seconds and CLI delay of '3' seconds
Continue? [Y/n] Y
proceeding ...
/home/work/go/src/github.com/hyperledger/fabric/release/linux-amd64/bin/cryptogen
... ...
... ...
... ...
2018-04-09 03:37:24.644 UTC [msp/identity] Sign -> DEBU 007 Sign: digest: 1B7235C3DC2AF4B066928DDEA387D4A0524357DEB4978C23DB70B01B893DBC3A
Query Result: 80
2018-04-09 03:37:24.651 UTC [main] main -> INFO 008 Exiting.....
===================== Query on peer0.org3 on channel 'mychannel' is successful =====================
========= All GOOD, EYFN test execution completed ===========
 _____   _   _   ____
| ____| | \ | | |  _ \
|  _|   |  \| | | | | |
| |___  | |\  | | |_| |
|_____| |_| \_| |____/

雖然不贅述 eyfn.sh,但腳本和手動部署原理是一致的,可以仔細學習。


為 channel 動態(tài)添加 Org

step1: 為新 org 生成證書

cd org3-artifacts/
cryptogen generate --config=./org3-crypto.yaml

會依據 org3-crypto.yaml 生成,生成后的文件位于 org3-artifacts/crypto-config/ 下

org3-crypto.yaml 文件中 Org3 的配置如下:

PeerOrgs:
  - Name: Org3
    Domain: org3.example.com
    EnableNodeOUs: true
    Template:
      Count: 2
    Users:
      Count: 1


step2: 為新 org 生成配置文件

導入配置

export FABRIC_CFG_PATH=$PWD


將 org3 的配置以 json 格式輸出

configtxgen 命令會從 configtx.yaml 讀取 Org3 相關配置,生成 json 輸出至 org3.json

configtxgen -printOrg Org3MSP -profile ./configtx.yaml > ../channel-artifacts/org3.json

若成功,輸出如下:

2018-04-09 17:03:12.625 CST [common/tools/configtxgen] main -> INFO 001 Loading configuration
2018-04-09 17:03:12.626 CST [msp] getMspConfig -> INFO 002 Loading NodeOUs


configtx.yaml 配置如下

-printOrg Org3MSP 中的名字要與 configtx.yaml 配置中的 Organizations,Name 一致。

Organizations:
    - &Org3
        Name: Org3MSP
        ID: Org3MSP
        MSPDir: crypto-config/peerOrganizations/org3.example.com/msp
        AnchorPeers:
            - Host: peer0.org3.example.com
              Port: 7051


生成的 org3.json 結構大致如下

{
  "groups": {},
  "mod_policy": "Admins",
  "policies": {
    "Admins": {
      "mod_policy": "Admins",
      "policy": {
        "type": 1,
        "value": {
          "identities": [
            {
              "principal": {
                "msp_identifier": "Org3MSP",
                "role": "ADMIN"
              },
              "principal_classification": "ROLE"
            }
          ],
          ... ...
      "version": "0"
    },
    "Readers": {
      ... ...
    },
    "Writers": {
      ... ...
    }
  },
  "values": {
    "MSP": {
      "mod_policy": "Admins",
      "value": {
        "config": {
          "FabricNodeOUs": {
            "Enable": true,
            "clientOUIdentifier": {
              "certificate": "LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS00... ....FURS0tLS0tCg==",
              "organizational_unit_identifier": "client"
            },
            "peerOUIdentifier": {
              "certificate": "LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS00... ....FURS0tLS0tCg==",
              "organizational_unit_identifier": "peer"
            }
          },
          "admins": [
            "certificate": "LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS00... ....FURS0tLS0tCg==",
          ],
          "crypto_config": {
            "identity_identifier_hash_function": "SHA256",
            "signature_hash_family": "SHA2"
          },
          "name": "Org3MSP",
          "root_certs": [
            "LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS00... ....FURS0tLS0tCg=="
          ],
          "tls_root_certs": [
            "LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS00... ....FURS0tLS0tCg=="
          ]
        },
        "type": 0
      },
      "version": "0"
    }
  },
  "version": "0"
}


將 orderer 的證書和密鑰拷貝至 org3 的 crypto-config 目錄下

cp -r ../crypto-config/ordererOrganizations crypto-config/


step3: 生成和提交新 org 的配置

通過 step 1~2,已經生成了 Org3 的證書和配置,但這僅僅是在本地文件系統(tǒng),還未于區(qū)塊鏈網絡產生關聯(lián)。

為 channel 新加 Org,對 Fabric 而言,是以一筆交易的形式提交的。

因此要使得這筆交易能順利完成,需要提交 org3 的配置,獲得權限認證;然后于網絡中發(fā)起更新的交易

登錄 cli 節(jié)點

docker exec -it cli bash


為 cli 節(jié)點新增配置

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


安裝 jq 工具

jq 是 Linux 下命令行處理 JSON 的工具,可以對 JSON 進行過濾、格式化、修改等等操作。

apt-get -y update && apt-get -y install jq


獲取當前 channel 的配置

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

參數 --tls 根據區(qū)塊鏈網絡配置添加,若區(qū)塊鏈網絡配置需要 tls,沒有 tls 會報

2018-04-09 07:34:00.783 UTC [channelCmd] getNewestBlock -> ERRO 00c Received error: rpc error: code = Unavailable desc = transport is closing
Error: rpc error: code = Unavailable desc = transport is closing 錯誤


若成功,會輸出

2018-04-09 07:34:40.358 UTC [msp] GetLocalMSP -> DEBU 001 Returning existing local MSP
2018-04-09 07:34:40.358 UTC [msp] GetDefaultSigningIdentity -> DEBU 002 Obtaining default signing identity
2018-04-09 07:34:40.363 UTC [channelCmd] InitCmdFactory -> INFO 003 Endorser and orderer connections initialized
2018-04-09 07:34:40.363 UTC [msp] GetLocalMSP -> DEBU 004 Returning existing local MSP
2018-04-09 07:34:40.363 UTC [msp] GetDefaultSigningIdentity -> DEBU 005 Obtaining default signing identity
2018-04-09 07:34:40.363 UTC [msp] GetLocalMSP -> DEBU 006 Returning existing local MSP
2018-04-09 07:34:40.363 UTC [msp] GetDefaultSigningIdentity -> DEBU 007 Obtaining default signing identity
2018-04-09 07:34:40.363 UTC [msp/identity] Sign -> DEBU 008 Sign: plaintext: 0AED060A1508021A060890AFACD60522...52D6438017E412080A020A0012020A00
2018-04-09 07:34:40.364 UTC [msp/identity] Sign -> DEBU 009 Sign: digest: DC1DEEDD462E9009BF249B5B0481D06333B699DF58764FDA9312B63144C443AE
2018-04-09 07:34:40.367 UTC [channelCmd] readBlock -> DEBU 00a Received block: 4
2018-04-09 07:34:40.368 UTC [msp] GetLocalMSP -> DEBU 00b Returning existing local MSP
2018-04-09 07:34:40.368 UTC [msp] GetDefaultSigningIdentity -> DEBU 00c Obtaining default signing identity
2018-04-09 07:34:40.368 UTC [msp] GetLocalMSP -> DEBU 00d Returning existing local MSP
2018-04-09 07:34:40.368 UTC [msp] GetDefaultSigningIdentity -> DEBU 00e Obtaining default signing identity
2018-04-09 07:34:40.368 UTC [msp/identity] Sign -> DEBU 00f Sign: plaintext: 0AED060A1508021A060890AFACD60522...2C68120C0A041A02080212041A020802
2018-04-09 07:34:40.368 UTC [msp/identity] Sign -> DEBU 010 Sign: digest: 15C3B41F571FCCAE261C280B4C3EB8A4F73DB7FA0A1E15FF11AE08072808D8A2
2018-04-09 07:34:40.371 UTC [channelCmd] readBlock -> DEBU 011 Received block: 2
2018-04-09 07:34:40.371 UTC [main] main -> INFO 012 Exiting.....


修改原配置文件,新增 org3 配置

1. 解碼原有網絡的配置文件 config_block.pb。

configtxlator proto_decode 命令將 protobuf 內容轉為 JSON 格式。

然后通過 jq 命令行將其中部分取出,輸出至 config.json

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

config_block.pb 內容是一堆配置和證書信息,部分如下:

 M?Ui??????
??F_z??'k?4?_O ??hy??#"??_?G?g?o?????????k?z
?z
?y
?
???"    mychannel?
?

OrdererMSP?-----BEGIN CERTIFICATE-----
MIICCzCCAbKgAwIBAgIQV2YjEb05t8NkbNvOF1xylDAKBggqhkjOPQQDAjBpMQsw
CQYDVQQGEwJVUzETMBEGA1UECBMKQ2FsaWZvcm5pYTEWMBQGA1UEBxMNU2FuIEZy
YW5jaXNjbzEUMBIGA1UEChMLZXhhbXBsZS5jb20xFzAVBgNVBAMTDmNhLmV4YW1w
bGUuY29tMB4XDTE4MDQwOTA2MDkxNloXDTI4MDQwNjA2MDkxNlowWDELMAkGA1UE
BhMCVVMxEzARBgNVBAgTCkNhbGlmb3JuaWExFjAUBgNVBAcTDVNhbiBGcmFuY2lz
Y28xHDAaBgNVBAMTE29yZGVyZXIuZXhhbXBsZS5jb20wWTATBgcqhkjOPQIBBggq
hkjOPQMBBwNCAAQMxQEdNLTLIU1paNblHQl9US27di5RXYu3cO0sdpjT58/l1eUP
5lNzneKx6Qg4iS/oZfJfX7mQhISKusLiyNnko00wSzAOBgNVHQ8BAf8EBAMCB4Aw
DAYDVR0TAQH/BAIwADArBgNVHSMEJDAigCAQY5DwOeZLuo8fL/jgwbf3b0OafLoE
6laY/dMS6N1mcjAKBggqhkjOPQQDAgNHADBEAiAl1yE4iRkX/OKKeNrwj3ZG/Zml
nWEF4ULvNh17oH5ZTQIgIHnp7cEZ2fSMBGE1gObW/ADBfXau2VCcLEwA2I0wWFo=
-----END CERTIFICATE-----
?u?z??K 14?8Y??"v|??s
??b?H

Application??#
Org2MSP??!
MSP?!?!?!
Org2MSP?-----BEGIN CERTIFICATE-----
... ...
... ...

輸出的 config.json 格式類似 step2 生成的 org3.json。


2. 修改 config.json,新增 org3

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


3. 將 config.json 和 modified_config.json 轉為 protobuf 格式

configtxlator proto_encode --input config.json --type common.Config > original_config.pb
configtxlator proto_encode --input modified_config.json --type common.Config > modified_config.pb


4. 根據 config.pb 和 modified_config.pb 計算出 org3_update.pb
類似于 diff 操作,但是針對 protobuf 格式,因此會多出好多操作。蛋疼

configtxlator compute_update --channel_id mychannel --original original_config.pb --updated modified_config.pb > config_update.pb


5. 解碼 config_update.pb 為 json,然后用 jq 修改,然后在編碼為 protobuf 格式,最終輸出 org3_update_in_envelope.pb

configtxlator proto_decode --input config_update.pb  --type common.ConfigUpdate > config_update.json
echo '{"payload":{"header":{"channel_header":{"channel_id":"mychannel", "type":2}},"data":{"config_update":'$(cat config_update.json)'}}}' | jq . > config_update_in_envelope.json
configtxlator proto_encode --input config_update_in_envelope.json --type common.Envelope > org3_update_in_envelope.pb


為 Org3 新配置簽名

為配置交易簽名,需要 channel 中的大多數 Org 對其進行簽名。

對于 mychannel 而言,已有了 org1,org2,因此新增 org3 時需要 org1、org2 都簽名。

簽名操作于 cli 中完成,通過更改環(huán)境變量,改變簽名者的身份。


切換至 Org1 進行簽名,Org1 有兩個 peer,需采用 Anchor Peer,即 peer0.org1.example.com

export CORE_PEER_LOCALMSPID="Org1MSP"
export CORE_PEER_TLS_ROOTCERT_FILE=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org1.example.com/peers/peer0.org1.example.com/tls/ca.crt
export CORE_PEER_MSPCONFIGPATH=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org1.example.com/users/Admin@org1.example.com/msp
export CORE_PEER_ADDRESS=peer0.org1.example.com:7051

切換至 Org2 進行簽名,Org2 有兩個 peer,需采用 Anchor Peer,即 peer0.org2.example.com

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


peer channel signconfigtx 命令是由 admin 為配置交易(configuration transaction)簽名。

需要分別于 org1 環(huán)境變量、org2 環(huán)境變量下分別執(zhí)行一次。

peer channel signconfigtx -f org3_update_in_envelope.pb

若成功,以下為 Org1 簽名后的輸出:

2018-04-09 08:28:52.786 UTC [msp] GetLocalMSP -> DEBU 001 Returning existing local MSP
2018-04-09 08:28:52.786 UTC [msp] GetDefaultSigningIdentity -> DEBU 002 Obtaining default signing identity
2018-04-09 08:28:52.786 UTC [channelCmd] InitCmdFactory -> INFO 003 Endorser and orderer connections initialized
2018-04-09 08:28:52.786 UTC [msp] GetLocalMSP -> DEBU 004 Returning existing local MSP
2018-04-09 08:28:52.786 UTC [msp] GetDefaultSigningIdentity -> DEBU 005 Obtaining default signing identity
2018-04-09 08:28:52.786 UTC [msp] GetLocalMSP -> DEBU 006 Returning existing local MSP
2018-04-09 08:28:52.786 UTC [msp] GetDefaultSigningIdentity -> DEBU 007 Obtaining default signing identity
2018-04-09 08:28:52.786 UTC [msp/identity] Sign -> DEBU 008 Sign: plaintext: 0AB6060A074F7267314D535012AA062D...72697465727312002A0641646D696E73
2018-04-09 08:28:52.787 UTC [msp/identity] Sign -> DEBU 009 Sign: digest: 7CC3CB504C7AC5588E1C347305262066757B45E8F99F39D18836B4A60EB22901
2018-04-09 08:28:52.787 UTC [msp] GetLocalMSP -> DEBU 00a Returning existing local MSP
2018-04-09 08:28:52.787 UTC [msp] GetDefaultSigningIdentity -> DEBU 00b Obtaining default signing identity
2018-04-09 08:28:52.787 UTC [msp] GetLocalMSP -> DEBU 00c Returning existing local MSP
2018-04-09 08:28:52.787 UTC [msp] GetDefaultSigningIdentity -> DEBU 00d Obtaining default signing identity
2018-04-09 08:28:52.787 UTC [msp/identity] Sign -> DEBU 00e Sign: plaintext: 0AED060A1508021A0608C4C8ACD60522...DBB67FA8B0E04B91898888F898CA2EF5
2018-04-09 08:28:52.787 UTC [msp/identity] Sign -> DEBU 00f Sign: digest: 8FCE6B4E8A5A9E89D1CE6F624D1CA0AE04EEC1448ACC3B67F294241DB7A96960
2018-04-09 08:28:52.787 UTC [main] main -> INFO 010 Exiting.....


提交簽名后的配置交易至 orderer

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
peer channel update -f org3_update_in_envelope.pb -c mychannel -o orderer.example.com:7050 --tls --cafile $ORDERER_CA


驗證 orderer 是否完成排序,并于 peer 入鏈

于宿主機下,查看 docker 內輸出

docker logs -ft peer0.org1.example.com
docker logs -ft peer0.org2.example.com

若入鏈,可以看到以下輸出:

2018-04-09T09:06:21.465870592Z 2018-04-09 09:06:21.465 UTC [kvledger] CommitWithPvtData -> INFO 03d Channel [mychannel]: Committed block [5] with 1 transaction(s)

輸出顯示,當前提交的塊號是 5。

塊 0 是創(chuàng)世塊;1~2 是一些初始化;3~4 是實例化與調用 chaincode ,更新配置。


step4: 將新 org 添加入 channel

啟動新 org 集群

Org3 集群包含一個 org3cli 和 2 個 peer

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

輸出

Creating volume "net_peer0.org3.example.com" with default driver
Creating volume "net_peer1.org3.example.com" with default driver
WARNING: Found orphan containers (cli, peer1.org1.example.com, peer1.org2.example.com, peer0.org2.example.com, peer0.org1.example.com, orderer.example.com) for this project. If you removed or renamed this service in your compose file, youCreating peer1.org3.example.com ... done
Creating Org3cli ... done
Creating peer1.org3.example.com ...
Creating Org3cli ...

docker ps 查看新啟動的鏡像,比之前會多出以下三個

CONTAINER ID        IMAGE                                                                                                  COMMAND                  CREATED             STATUS              PORTS                                              NAMES
7b80ce329182        hyperledger/fabric-tools:latest                                                                        "/bin/bash"              35 seconds ago      Up 33 seconds                                                          Org3cli
f7990009b206        hyperledger/fabric-peer:latest                                                                         "peer node start"        35 seconds ago      Up 34 seconds       0.0.0.0:12051->7051/tcp, 0.0.0.0:12053->7053/tcp   peer1.org3.example.com
9bff0310d237        hyperledger/fabric-peer:latest                                                                         "peer node start"        35 seconds ago      Up 34 seconds       0.0.0.0:11051->7051/tcp, 0.0.0.0:11053->7053/tcp   peer0.org3.example.com

docker-compose-org3.yaml 配置如下:

# Copyright IBM Corp. All Rights Reserved.
#
# SPDX-License-Identifier: Apache-2.0
#

version: '2'

volumes:
  peer0.org3.example.com:
  peer1.org3.example.com:

networks:
  byfn:

services:

  peer0.org3.example.com:
    container_name: peer0.org3.example.com
    extends:
      file: base/peer-base.yaml
      service: peer-base
    environment:
      - CORE_PEER_ID=peer0.org3.example.com
      - CORE_PEER_ADDRESS=peer0.org3.example.com:7051
      - CORE_PEER_GOSSIP_EXTERNALENDPOINT=peer0.org3.example.com:7051
      - CORE_PEER_LOCALMSPID=Org3MSP
    volumes:
        - /var/run/:/host/var/run/
        - ./org3-artifacts/crypto-config/peerOrganizations/org3.example.com/peers/peer0.org3.example.com/msp:/etc/hyperledger/fabric/msp
        - ./org3-artifacts/crypto-config/peerOrganizations/org3.example.com/peers/peer0.org3.example.com/tls:/etc/hyperledger/fabric/tls
        - peer0.org3.example.com:/var/hyperledger/production
    ports:
      - 11051:7051
      - 11053:7053
    networks:
      - byfn

  peer1.org3.example.com:
    container_name: peer1.org3.example.com
    extends:
      file: base/peer-base.yaml
      service: peer-base
    environment:
      - CORE_PEER_ID=peer1.org3.example.com
      - CORE_PEER_ADDRESS=peer1.org3.example.com:7051
      - CORE_PEER_GOSSIP_EXTERNALENDPOINT=peer1.org3.example.com:7051
      - CORE_PEER_GOSSIP_BOOTSTRAP=peer0.org3.example.com:7051
      - CORE_PEER_LOCALMSPID=Org3MSP
    volumes:
        - /var/run/:/host/var/run/
        - ./org3-artifacts/crypto-config/peerOrganizations/org3.example.com/peers/peer1.org3.example.com/msp:/etc/hyperledger/fabric/msp
        - ./org3-artifacts/crypto-config/peerOrganizations/org3.example.com/peers/peer1.org3.example.com/tls:/etc/hyperledger/fabric/tls
        - peer1.org3.example.com:/var/hyperledger/production
    ports:
      - 12051:7051
      - 12053:7053
    networks:
      - byfn


  Org3cli:
    container_name: Org3cli
    image: hyperledger/fabric-tools:$IMAGE_TAG
    tty: true
    stdin_open: true
    environment:
      - GOPATH=/opt/gopath
      - CORE_VM_ENDPOINT=unix:///host/var/run/docker.sock
      #- CORE_LOGGING_LEVEL=INFO
      - CORE_LOGGING_LEVEL=DEBUG
      - CORE_PEER_ID=Org3cli
      - CORE_PEER_ADDRESS=peer0.org3.example.com:7051
      - CORE_PEER_LOCALMSPID=Org3MSP
      - CORE_PEER_TLS_ENABLED=true
      - CORE_PEER_TLS_CERT_FILE=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org3.example.com/peers/peer0.org3.example.com/tls/server.crt
      - CORE_PEER_TLS_KEY_FILE=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org3.example.com/peers/peer0.org3.example.com/tls/server.key
      - CORE_PEER_TLS_ROOTCERT_FILE=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org3.example.com/peers/peer0.org3.example.com/tls/ca.crt
      - CORE_PEER_MSPCONFIGPATH=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org3.example.com/users/Admin@org3.example.com/msp
    working_dir: /opt/gopath/src/github.com/hyperledger/fabric/peer
    command: /bin/bash
    volumes:
        - /var/run/:/host/var/run/
        - ./../chaincode/:/opt/gopath/src/github.com/chaincode
        - ./org3-artifacts/crypto-config:/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/
        - ./scripts:/opt/gopath/src/github.com/hyperledger/fabric/peer/scripts/
    depends_on:
      - peer0.org3.example.com
      - peer1.org3.example.com
    networks:
      - byfn


登錄新 org 集群,獲取當前 channel 配置

1. 登錄 Org3Cli

docker exec -it Org3cli bash


2. 添加環(huán)境變量

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


3. 獲取當前 channel 的配置

Org3Cli 從 orderer 中獲取 channel 創(chuàng)世塊配置

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

輸出:

2018-04-09 09:40:57.475 UTC [msp] GetLocalMSP -> DEBU 001 Returning existing local MSP
2018-04-09 09:40:57.475 UTC [msp] GetDefaultSigningIdentity -> DEBU 002 Obtaining default signing identity
2018-04-09 09:40:57.479 UTC [channelCmd] InitCmdFactory -> INFO 003 Endorser and orderer connections initialized
2018-04-09 09:40:57.479 UTC [msp] GetLocalMSP -> DEBU 004 Returning existing local MSP
2018-04-09 09:40:57.479 UTC [msp] GetDefaultSigningIdentity -> DEBU 005 Obtaining default signing identity
2018-04-09 09:40:57.480 UTC [msp] GetLocalMSP -> DEBU 006 Returning existing local MSP
2018-04-09 09:40:57.480 UTC [msp] GetDefaultSigningIdentity -> DEBU 007 Obtaining default signing identity
2018-04-09 09:40:57.480 UTC [msp/identity] Sign -> DEBU 008 Sign: plaintext: 0AED060A1508021A0608A9EAACD60522...460550DD7A5812080A021A0012021A00
2018-04-09 09:40:57.480 UTC [msp/identity] Sign -> DEBU 009 Sign: digest: 4A8C7BC724EEDA0B6D132395D371938BA7328D8E7F8C49B34F765FE3859AC106
2018-04-09 09:40:57.485 UTC [channelCmd] readBlock -> DEBU 00a Received block: 0
2018-04-09 09:40:57.485 UTC [main] main -> INFO 00b Exiting.....


將 Org 所有 Peer 加入 channel

Org3 下?lián)碛?2 個 Peer,peer0 和 peer1,其下所有 peer 均需要執(zhí)行加入 channel 操作。

切換至 Peer0,即 peer0.org3.example.com,將其加入 channel

export CORE_PEER_TLS_ROOTCERT_FILE=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org3.example.com/peers/peer0.org3.example.com/tls/ca.crt
export CORE_PEER_ADDRESS=peer0.org3.example.com:7051

切換至 Peer1,即 peer1.org3.example.com,將其加入 channel

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:7051

需要分別于 peer0 環(huán)境變量、peer1 環(huán)境變量下分別執(zhí)行一次。

peer channel join -b mychannel.block

peer0 與 peer1 輸出差不多,如下:

2018-04-09 09:43:22.968 UTC [msp] GetLocalMSP -> DEBU 001 Returning existing local MSP
2018-04-09 09:43:22.968 UTC [msp] GetDefaultSigningIdentity -> DEBU 002 Obtaining default signing identity
2018-04-09 09:43:22.972 UTC [channelCmd] InitCmdFactory -> INFO 003 Endorser and orderer connections initialized
2018-04-09 09:43:22.974 UTC [msp/identity] Sign -> DEBU 004 Sign: plaintext: 0AB4070A5C08011A0C08BAEBACD60510...21BD37B89AAE1A080A000A000A000A00
2018-04-09 09:43:22.974 UTC [msp/identity] Sign -> DEBU 005 Sign: digest: 00E3992EDAC99AC1FCAD1181FFE1993435C02EEAF8A5311CBEB935A8A0F9A68A
2018-04-09 09:43:23.007 UTC [channelCmd] executeJoin -> INFO 006 Successfully submitted proposal to join channel
2018-04-09 09:43:23.008 UTC [main] main -> INFO 007 Exiting.....


step5: 升級chaincode和背書策略

最后一步,是增加 chaincode 版本號并更新背書策略。

為 Org3 安裝 2.0 版本的 chaincode

當前 Org1 和 Org2 的 chaincode 版本號是 1,Org3 需要更新此版本的 chaincode,因此為 Org3 直接安裝版本為 2 的 chaincode,省得先安裝再升級。

peer chaincode install -n mycc -v 2.0 -p github.com/chaincode/chaincode_example02/go/

輸出如下:

2018-04-09 10:24:46.493 UTC [msp] GetLocalMSP -> DEBU 001 Returning existing local MSP
2018-04-09 10:24:46.493 UTC [msp] GetDefaultSigningIdentity -> DEBU 002 Obtaining default signing identity
2018-04-09 10:24:46.493 UTC [chaincodeCmd] checkChaincodeCmdParams -> INFO 003 Using default escc
2018-04-09 10:24:46.493 UTC [chaincodeCmd] checkChaincodeCmdParams -> INFO 004 Using default vscc
2018-04-09 10:24:46.493 UTC [chaincodeCmd] getChaincodeSpec -> DEBU 005 java chaincode enabled
2018-04-09 10:24:46.543 UTC [golang-platform] getCodeFromFS -> DEBU 006 getCodeFromFS github.com/chaincode/chaincode_example02/go/
2018-04-09 10:24:46.661 UTC [golang-platform] func1 -> DEBU 007 Discarding GOROOT package fmt
2018-04-09 10:24:46.661 UTC [golang-platform] func1 -> DEBU 008 Discarding provided package github.com/hyperledger/fabric/core/chaincode/shim
2018-04-09 10:24:46.662 UTC [golang-platform] func1 -> DEBU 009 Discarding provided package github.com/hyperledger/fabric/protos/peer
2018-04-09 10:24:46.662 UTC [golang-platform] func1 -> DEBU 00a Discarding GOROOT package strconv
2018-04-09 10:24:46.662 UTC [golang-platform] GetDeploymentPayload -> DEBU 00b done
2018-04-09 10:24:46.662 UTC [container] WriteFileToPackage -> DEBU 00c Writing file to tarball: src/github.com/chaincode/chaincode_example02/go/chaincode_example02.go
2018-04-09 10:24:46.664 UTC [msp/identity] Sign -> DEBU 00d Sign: plaintext: 0AB4070A5C08031A0C08EEFEACD60510...CAF857000000FFFF354C5FFC001C0000
2018-04-09 10:24:46.664 UTC [msp/identity] Sign -> DEBU 00e Sign: digest: 0E27BFDD36A93200D1519FFACF65F1813491E3FAADD90AD5227245C6A4A1445A
2018-04-09 10:24:46.667 UTC [chaincodeCmd] install -> DEBU 00f Installed remotely response:<status:200 payload:"OK" >
2018-04-09 10:24:46.667 UTC [main] main -> INFO 010 Exiting.....


為 Org1 的 peer0、Org2 的 peer0 安裝 2.0 版本 chaincode

登錄原 cli,對 org1,org2 進行管理。

docker exec -it cli bash


切換至 Org1 進行環(huán)境

export CORE_PEER_LOCALMSPID="Org1MSP"
export CORE_PEER_TLS_ROOTCERT_FILE=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org1.example.com/peers/peer0.org1.example.com/tls/ca.crt
export CORE_PEER_MSPCONFIGPATH=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org1.example.com/users/Admin@org1.example.com/msp
export CORE_PEER_ADDRESS=peer0.org1.example.com:7051

切換至 Org2 進行環(huán)境

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

需執(zhí)行兩次,分別于 org1,org2 環(huán)境下

peer chaincode install -n mycc -v 2.0 -p github.com/chaincode/chaincode_example02/go


升級背書策略

升級背書策略,-v 2.0 指明版本號,-P "OR ('Org1MSP.peer','Org2MSP.peer','Org3MSP.peer')" 指明新的背書策略(添加了 Org3)。

peer chaincode upgrade -o orderer.example.com:7050 --tls $CORE_PEER_TLS_ENABLED --cafile /opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/ordererOrganizations/example.com/orderers/orderer.example.com/msp/tlscacerts/tlsca.example.com-cert.pem -C mychannel -n mycc -v 2.0 -c '{"Args":["init","a","90","b","210"]}' -P "OR ('Org1MSP.peer','Org2MSP.peer','Org3MSP.peer')"

若成功,輸出如下:

2018-04-09 10:45:30.132 UTC [msp] GetLocalMSP -> DEBU 001 Returning existing local MSP
2018-04-09 10:45:30.132 UTC [msp] GetDefaultSigningIdentity -> DEBU 002 Obtaining default signing identity
2018-04-09 10:45:30.136 UTC [chaincodeCmd] checkChaincodeCmdParams -> INFO 003 Using default escc
2018-04-09 10:45:30.136 UTC [chaincodeCmd] checkChaincodeCmdParams -> INFO 004 Using default vscc
2018-04-09 10:45:30.136 UTC [chaincodeCmd] getChaincodeSpec -> DEBU 005 java chaincode enabled
2018-04-09 10:45:30.136 UTC [chaincodeCmd] upgrade -> DEBU 006 Get upgrade proposal for chaincode <name:"mycc" version:"2.0" >
2018-04-09 10:45:30.136 UTC [msp/identity] Sign -> DEBU 007 Sign: plaintext: 0AC2070A6608031A0B08CA88ADD60510...535010030A04657363630A0476736363
2018-04-09 10:45:30.137 UTC [msp/identity] Sign -> DEBU 008 Sign: digest: 4C4F7827359FBEA37BF97D2BAD15FC9762360DF414BF277A22869CBF7A605DB8
2018-04-09 10:45:39.103 UTC [chaincodeCmd] upgrade -> DEBU 009 endorse upgrade proposal, get response <status:200 message:"OK" payload:"\n\004mycc\022\0032.0\032\004escc\"\004vscc*?\022\020\022\016\010\001\022\002\010\000\022\002\010\001\022\002\010\002\032\r\022\013\n\007Org1MSP\020\003\032\r\022\013\n\007Org2MSP\020\003\032\r\022\013\n\007Org3MSP\020\0032D\n \222G\373\202N!\320\207\017\376y<\360`$\346^\206\361\340\345\213d\351\014[\031On74\000\022 g\357,\324!\221P`u\035X\006\327\257\037\324\334\003\003\251\2628\321\345\262$\360\r\351\220^\\: \235\322J\005\214V\273\257\340\244\273$y\325\215iP\365\211\266'\267<p)\340\020\364`\247\307\323B?\022\020\022\016\010\001\022\002\010\000\022\002\010\001\022\002\010\002\032\r\022\013\n\007Org1MSP\020\001\032\r\022\013\n\007Org2MSP\020\001\032\r\022\013\n\007Org3MSP\020\001" >
2018-04-09 10:45:39.103 UTC [msp/identity] Sign -> DEBU 00a Sign: plaintext: 0AC2070A6608031A0B08CA88ADD60510...430D37D0D4AE72A17EB35E2DA134DA99
2018-04-09 10:45:39.103 UTC [msp/identity] Sign -> DEBU 00b Sign: digest: 23A320F7C7E644FBA5D097D472246F47FD33B7C6A077AFE50F60B36E8ECDC7DC
2018-04-09 10:45:39.103 UTC [chaincodeCmd] upgrade -> DEBU 00c Get Signed envelope
2018-04-09 10:45:39.104 UTC [chaincodeCmd] chaincodeUpgrade -> DEBU 00d Send signed envelope to orderer
2018-04-09 10:45:39.105 UTC [main] main -> INFO 00e Exiting.....


peer chaincode upgrade 命令將為區(qū)塊鏈新增一個塊,可以在 peer 的輸出中查看

docker logs -ft peer0.org1.example.com

可以看到,塊號已經升至 6.

2018-04-09T10:45:41.113103936Z 2018-04-09 10:45:41.112 UTC [committer/txvalidator] validateTx -> INFO 203 Find chaincode upgrade transaction for chaincode mycc on channel mychannel with new version 2.0
2018-04-09T10:45:41.113566483Z 2018-04-09 10:45:41.113 UTC [cceventmgmt] HandleStateUpdates -> INFO 204 Channel [mychannel]: Handling LSCC state update for chaincode [mycc]
2018-04-09T10:45:41.115440650Z 2018-04-09 10:45:41.115 UTC [kvledger] CommitWithPvtData -> INFO 205 Channel [mychannel]: Committed block [6] with 1 transaction(s)


step6: 測試是否成功

發(fā)起一筆查詢

peer chaincode query -C $CHANNEL_NAME -n mycc -c '{"Args":["query","a"]}'

得到以下結果,Query Result: 90

2018-04-09 10:46:56.063 UTC [msp] GetLocalMSP -> DEBU 001 Returning existing local MSP
2018-04-09 10:46:56.063 UTC [msp] GetDefaultSigningIdentity -> DEBU 002 Obtaining default signing identity
2018-04-09 10:46:56.063 UTC [chaincodeCmd] checkChaincodeCmdParams -> INFO 003 Using default escc
2018-04-09 10:46:56.063 UTC [chaincodeCmd] checkChaincodeCmdParams -> INFO 004 Using default vscc
2018-04-09 10:46:56.063 UTC [chaincodeCmd] getChaincodeSpec -> DEBU 005 java chaincode enabled
2018-04-09 10:46:56.064 UTC [msp/identity] Sign -> DEBU 006 Sign: plaintext: 0AC2070A6608031A0B08A089ADD60510...6D7963631A0A0A0571756572790A0161
2018-04-09 10:46:56.064 UTC [msp/identity] Sign -> DEBU 007 Sign: digest: 5C801C9C2085286736CEEDB46B6E7FDBB83C4B6C472E81BDF2A31E07FE76DAB5
Query Result: 90
2018-04-09 10:46:56.072 UTC [main] main -> INFO 008 Exiting.....

然后,發(fā)起一筆調用,調用是將 a10b

peer chaincode invoke -o orderer.example.com:7050  --tls $CORE_PEER_TLS_ENABLED --cafile $ORDERER_CA -C $CHANNEL_NAME -n mycc -c '{"Args":["invoke","a","b","10"]}'

輸出如下:

2018-04-09 10:47:21.151 UTC [msp] GetLocalMSP -> DEBU 001 Returning existing local MSP
2018-04-09 10:47:21.151 UTC [msp] GetDefaultSigningIdentity -> DEBU 002 Obtaining default signing identity
2018-04-09 10:47:21.155 UTC [chaincodeCmd] checkChaincodeCmdParams -> INFO 003 Using default escc
2018-04-09 10:47:21.155 UTC [chaincodeCmd] checkChaincodeCmdParams -> INFO 004 Using default vscc
2018-04-09 10:47:21.155 UTC [chaincodeCmd] getChaincodeSpec -> DEBU 005 java chaincode enabled
2018-04-09 10:47:21.155 UTC [msp/identity] Sign -> DEBU 006 Sign: plaintext: 0AC2070A6608031A0B08B989ADD60510...696E766F6B650A01610A01620A023130
2018-04-09 10:47:21.155 UTC [msp/identity] Sign -> DEBU 007 Sign: digest: 69ABEEFD6EC7327C6C6FA36F4302965F2C8DC69AD388634A5737726A6C2E8EE8
2018-04-09 10:47:21.163 UTC [msp/identity] Sign -> DEBU 008 Sign: plaintext: 0AC2070A6608031A0B08B989ADD60510...0EEC6E3A64572217C0ECC4FA2AF449FE
2018-04-09 10:47:21.163 UTC [msp/identity] Sign -> DEBU 009 Sign: digest: E4191E37ED4A0D742CF3C969E348350BA3BC68292A474B64D7B1F71104E5DC59
2018-04-09 10:47:21.165 UTC [chaincodeCmd] chaincodeInvokeOrQuery -> DEBU 00a ESCC invoke result: version:1 response:<status:200 message:"OK" > payload:"\n \240\361-\006{d\325!\321\017\323Y\254l\303\351\222W\226\275T\255\002\333\260\201\350\230Z<\234\320\022Y\nE\022\024\n\004lscc\022\014\n\n\n\004mycc\022\002\010\006\022-\n\004mycc\022%\n\007\n\001a\022\002\010\006\n\007\n\001b\022\002\010\006\032\007\n\001a\032\00280\032\010\n\001b\032\003220\032\003\010\310\001\"\013\022\004mycc\032\0032.0" endorsement:<endorser:"\n\007Org2MSP\022\246\006-----BEGIN CERTIFICATE-----\nMIICJzCCAc6gAwIBAgIQSt8xNetxpTvWnh7QS9Z9ojAKBggqhkjOPQQDAjBzMQsw\nCQYDVQQGEwJVUzETMBEGA1UECBMKQ2FsaWZvcm5pYTEWMBQGA1UEBxMNU2FuIEZy\nYW5jaXNjbzEZMBcGA1UEChMQb3JnMi5leGFtcGxlLmNvbTEcMBoGA1UEAxMTY2Eu\nb3JnMi5leGFtcGxlLmNvbTAeFw0xODA0MDkwODUzNDRaFw0yODA0MDYwODUzNDRa\nMGoxCzAJBgNVBAYTAlVTMRMwEQYDVQQIEwpDYWxpZm9ybmlhMRYwFAYDVQQHEw1T\nYW4gRnJhbmNpc2NvMQ0wCwYDVQQLEwRwZWVyMR8wHQYDVQQDExZwZWVyMC5vcmcy\nLmV4YW1wbGUuY29tMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEK3WWG/HkydkW\nZ8tjS+WEfEKbn7+O82akp5ckzEKsbN6ucK3rCCM9hUGizEikSXSnxGQ/thB1vkPU\nEZtwjlL+w6NNMEswDgYDVR0PAQH/BAQDAgeAMAwGA1UdEwEB/wQCMAAwKwYDVR0j\nBCQwIoAgLw9SFcdoizgo4xv+OMJoM5Ev5gnvDSXI+0AoQGjfXmowCgYIKoZIzj0E\nAwIDRwAwRAIgcsLdt9YS3xkyZ3w+7CPepULC9ScpvPjgbzhQJdWGt34CIHa1fDJp\nSpfEYkXxZVpKsAFDP/+TZ1CR/BipvZj6Ucvc\n-----END CERTIFICATE-----\n" signature:"0E\002!\000\340X\274\360\215\367\304\032\261e\351\225\026C9\262\177\037I\327\000.}\317.\016\245\223\026\374h\211\002 1\202\362\344IU\010\250=\364A\320\235\n\\H\016\354n:dW\"\027\300\354\304\372*\364I\376" >
2018-04-09 10:47:21.165 UTC [chaincodeCmd] chaincodeInvokeOrQuery -> INFO 00b Chaincode invoke successful. result: status:200
2018-04-09 10:47:21.165 UTC [main] main -> INFO 00c Exiting.....

peer chaincode invoke 會生成一個新塊,同上,可以通過 docker logs -ft peer0.org1.example.com 查看,此時塊號將變?yōu)?7。

再次調用查詢命令peer chaincode query -C $CHANNEL_NAME -n mycc -c '{"Args":["query","a"]}', 得到以下輸出??梢钥吹?Query Result: 80,說明調用已經成功。

2018-04-09 10:47:40.210 UTC [msp] GetLocalMSP -> DEBU 001 Returning existing local MSP
2018-04-09 10:47:40.210 UTC [msp] GetDefaultSigningIdentity -> DEBU 002 Obtaining default signing identity
2018-04-09 10:47:40.210 UTC [chaincodeCmd] checkChaincodeCmdParams -> INFO 003 Using default escc
2018-04-09 10:47:40.210 UTC [chaincodeCmd] checkChaincodeCmdParams -> INFO 004 Using default vscc
2018-04-09 10:47:40.210 UTC [chaincodeCmd] getChaincodeSpec -> DEBU 005 java chaincode enabled
2018-04-09 10:47:40.211 UTC [msp/identity] Sign -> DEBU 006 Sign: plaintext: 0AC2070A6608031A0B08CC89ADD60510...6D7963631A0A0A0571756572790A0161
2018-04-09 10:47:40.211 UTC [msp/identity] Sign -> DEBU 007 Sign: digest: E0206FCC932E0928EBB8D980C0A485AB34FD3F31CCD01F433606DD76F57C5854
Query Result: 80
2018-04-09 10:47:40.219 UTC [main] main -> INFO 008 Exiting.....


參考資料

[1] Hyperledger Fabric 官方手冊, http://hyperledger-fabric.readthedocs.io/en/latest/channel_update_tutorial.html
[2] Fabric學習筆記(八) - cli動態(tài)添加Org, 作者 mumubin,https://segmentfault.com/a/1190000013521785

?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
【社區(qū)內容提示】社區(qū)部分內容疑似由AI輔助生成,瀏覽時請結合常識與多方信息審慎甄別。
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發(fā)布,文章內容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

相關閱讀更多精彩內容

友情鏈接更多精彩內容