docker 部署 hyperleger fabric v2.2.0 網(wǎng)絡(luò)環(huán)境

[toc]

環(huán)境

GoSDK安裝

下載 GO SDK

wget https://golang.google.cn/dl/go1.17.3.linux-amd64.tar.gz
tar xfv go1.14.4.linux-amd64.tar.gz  -C  /usr/local

配置環(huán)境變量

在文件最后添加以下內(nèi)容

vim /etc/profile
export PATH=$PATH:/usr/local/go/bin
export GOROOT=/usr/local/go
export GOPATH=$HOME/go
export PATH=$PATH:$GOPATH/bin
export GOPROXY="https://goproxy.cn,direct"
export GO111MODULE="auto"
source /etc/profile

查看go-SDK 是否安裝成功

go version

安裝 docker

安裝Docker-CE

卸載舊版本docker

sudo apt-get remove docker docker-engine docker.io

添加HTTPS協(xié)議晨汹,允許apt從HTTPS安裝軟件包

sudo apt-get -y install apt-transport-https ca-certificates curl software-properties-common

安裝GPG證書(shū)

curl -fsSL http://mirrors.aliyun.com/docker-ce/linux/ubuntu/gpg | sudo apt-key add -

寫(xiě)入軟件源信息

sudo add-apt-repository "deb [arch=amd64] http://mirrors.aliyun.com/docker-ce/linux/ubuntu $(lsb_release -cs) stable"

更新并安裝Docker-CE

sudo apt-get -y update && sudo apt-get -y install docker-ce
docker version

將當(dāng)前用戶添加到Docker用戶組

創(chuàng)建docker用戶組
sudo groupadd docker
將當(dāng)前用戶添加到docker用戶組
sudo usermod -aG docker $USER

配置鏡像加速器

針對(duì)Docker客戶端版本大于 1.10.0 的用戶

您可以通過(guò)修改daemon配置文件/etc/docker/daemon.json來(lái)使用加速器

sudo mkdir -p /etc/docker
sudo tee /etc/docker/daemon.json <<-'EOF'
{
  "registry-mirrors": ["https://x9u1rybt.mirror.aliyuncs.com"]
}
EOF
sudo systemctl daemon-reload
sudo systemctl restart docker

查看docker版本昧旨,看是否安裝成功

docker version
  • 執(zhí)行docker info拗小,如果結(jié)果中含有如下內(nèi)容則說(shuō)明鏡像配置成功
...
 Registry Mirrors:
  https://obou6wyb.mirror.aliyuncs.com/
  https://registry.docker-cn.com/
  http://hub-mirror.c.163.com/
 Live Restore Enabled: false
 ...

安裝Docker-Compose

  • 查看最新版本版本

https://github.com/docker/compose/releases

sudo curl -L https://github.com/docker/compose/releases/download/1.24.0/docker-compose-`uname -s`-`uname -m` -o /usr/local/bin/docker-compose

sudo curl -L https://get.daocloud.io/docker/compose/releases/download/1.29.2/docker-compose-`uname -s`-`uname -m` > /usr/local/bin/docker-compose

-下載完后要設(shè)置權(quán)限

sudo chmod +x /usr/local/bin/docker-compose
  • 檢查
docker-compose version

fabric源碼

下載源碼

git clone  https://gitee.com/mirrors/hyperledger-fabric.git fabric
cd fabric
  • 切換到v2.2.0版本
git checkout v2.2.0

下載二進(jìn)制文件(已經(jīng)準(zhǔn)備好)

wget https://github.com/hyperledger/fabric/releases/download/v2.2.0/hyperledger-fabric-linux-amd64-2.2.0.tar.gz
  • 解壓
tar -vxzf hyperledger-fabric-linux-amd64-2.2.0.tar.gz -C ./go/
  • 檢查
peer version

下載 fabric-sample 源碼

git clone https://gitee.com/Alikx/fabric-samples.git
  • 進(jìn)入項(xiàng)目
cd $GOPATH/src/github.com/hyperledger/fabric-samples/test-network
  • 切換版本
git checkout v2.2.0
  • 移動(dòng)配置文件,先進(jìn)gopath的 bin目錄下,之前解二進(jìn)制文件連同配置文件都在這里.
mv config ~/go/src/github.com/hyperledger/fabric-samples

啟動(dòng)網(wǎng)絡(luò)

  • 進(jìn)入測(cè)試網(wǎng)絡(luò)
cd $GOPATH/src/github.com/hyperledger/fabric-samples/test-network
  • 修改測(cè)試腳本
vim ./network.sh 

大概在51行,注釋掉二進(jìn)制文件檢查的那一項(xiàng)

function checkPrereqs() {
  ## Check if your have cloned the peer binaries and configuration files.
  peer version > /dev/null 2>&1
    # 注釋下面的部分
  # if [[ $? -ne 0 || ! -d "../config" ]]; then
  #   errorln "Peer binary and configuration files not found.."
  #   errorln
  #   errorln "Follow the instructions in the Fabric docs to install the Fabric Binaries:"
  #   errorln "https://hyperledger-fabric.readthedocs.io/en/latest/install.html"
  #   exit 1
  # fi
  # 注釋上面的部分
  # use the fabric tools container to see if the samples and binaries match your
  # docker images

執(zhí)行腳本

export COMPOSE_PROJECT_NAME=fabric
export IMAGE_TAG=2.2
./network.sh up createChannel

啟動(dòng)日志

Creating channel 'mychannel'.
If network is not up, starting nodes with CLI timeout of '5' tries and CLI delay of '3' seconds and using database 'leveldb with crypto from 'cryptogen'
Bringing up network
LOCAL_VERSION=2.2.0
DOCKER_IMAGE_VERSION=2.2.0
/root/go/bin/cryptogen
Generating certificates using cryptogen tool
Creating Org1 Identities
+ cryptogen generate --config=./organizations/cryptogen/crypto-config-org1.yaml --output=organizations
org1.example.com # 新增peer參考配置文件
+ res=0
Creating Org2 Identities
+ cryptogen generate --config=./organizations/cryptogen/crypto-config-org2.yaml --output=organizations
org2.example.com
+ res=0
Creating Orderer Org Identities
+ cryptogen generate --config=./organizations/cryptogen/crypto-config-orderer.yaml --output=organizations
+ res=0
Generating CCP files for Org1 and Org2
/root/go/bin/configtxgen
Generating Orderer Genesis block
+ configtxgen -profile TwoOrgsOrdererGenesis -channelID system-channel -outputBlock ./system-genesis-block/genesis.block
2021-11-23 03:19:32.312 UTC [common.tools.configtxgen] main -> INFO 001 Loading configuration
2021-11-23 03:19:32.340 UTC [common.tools.configtxgen.localconfig] completeInitialization -> INFO 002 orderer type: etcdraft
2021-11-23 03:19:32.340 UTC [common.tools.configtxgen.localconfig] completeInitialization -> INFO 003 Orderer.EtcdRaft.Options unset, setting to tick_interval:"500ms" election_tick:10 heartbeat_tick:1 max_inflight_blocks:5 snapshot_interval_size:16777216
2021-11-23 03:19:32.340 UTC [common.tools.configtxgen.localconfig] Load -> INFO 004 Loaded configuration: /root/go/src/github.com/hyperledger/fabric-samples/test-network/configtx/configtx.yaml
2021-11-23 03:19:32.342 UTC [common.tools.configtxgen] doOutputBlock -> INFO 005 Generating genesis block
2021-11-23 03:19:32.343 UTC [common.tools.configtxgen] doOutputBlock -> INFO 006 Writing genesis block
+ res=0
Creating network "fabric_test" with the default driver
Creating volume "fabric_orderer.example.com" with default driver
Creating volume "fabric_peer0.org1.example.com" with default driver
Creating volume "fabric_peer0.org2.example.com" with default driver
Creating orderer.example.com    ... done
Creating peer0.org1.example.com ... done
Creating peer0.org2.example.com ... done
Creating cli                    ... done
CONTAINER ID   IMAGE                               COMMAND             CREATED         STATUS                  PORTS                                                 NAMES
f19399557a69   hyperledger/fabric-tools:latest     "/bin/bash"         2 seconds ago   Up Less than a second                                                         cli
263f14b81a51   hyperledger/fabric-peer:latest      "peer node start"   5 seconds ago   Up 2 seconds            7051/tcp, 0.0.0.0:9051->9051/tcp, :::9051->9051/tcp   peer0.org2.example.com
5513a783cb6a   hyperledger/fabric-peer:latest      "peer node start"   5 seconds ago   Up 3 seconds            0.0.0.0:7051->7051/tcp, :::7051->7051/tcp             peer0.org1.example.com
1eca52dd33b4   hyperledger/fabric-orderer:latest   "orderer"           5 seconds ago   Up 1 second             0.0.0.0:7050->7050/tcp, :::7050->7050/tcp             orderer.example.com
Generating channel create transaction 'mychannel.tx'
+ configtxgen -profile TwoOrgsChannel -outputCreateChannelTx ./channel-artifacts/mychannel.tx -channelID mychannel
2021-11-23 03:19:38.507 UTC [common.tools.configtxgen] main -> INFO 001 Loading configuration
2021-11-23 03:19:38.558 UTC [common.tools.configtxgen.localconfig] Load -> INFO 002 Loaded configuration: /root/go/src/github.com/hyperledger/fabric-samples/test-network/configtx/configtx.yaml
2021-11-23 03:19:38.558 UTC [common.tools.configtxgen] doOutputChannelCreateTx -> INFO 003 Generating new channel configtx
2021-11-23 03:19:38.570 UTC [common.tools.configtxgen] doOutputChannelCreateTx -> INFO 004 Writing new channel tx
+ res=0
Creating channel mychannel
Using organization 1
+ peer channel create -o localhost:7050 -c mychannel --ordererTLSHostnameOverride orderer.example.com -f ./channel-artifacts/mychannel.tx --outputBlock ./channel-artifacts/mychannel.block --tls --cafile /root/go/src/github.com/hyperledger/fabric-samples/test-network/organizations/ordererOrganizations/example.com/orderers/orderer.example.com/msp/tlscacerts/tlsca.example.com-cert.pem
+ res=0
2021-11-23 03:19:41.846 UTC [channelCmd] InitCmdFactory -> INFO 001 Endorser and orderer connections initialized
2021-11-23 03:19:41.970 UTC [cli.common] readBlock -> INFO 002 Expect block, but got status: &{NOT_FOUND}
2021-11-23 03:19:41.998 UTC [channelCmd] InitCmdFactory -> INFO 003 Endorser and orderer connections initialized
2021-11-23 03:19:42.203 UTC [cli.common] readBlock -> INFO 004 Expect block, but got status: &{SERVICE_UNAVAILABLE}
2021-11-23 03:19:42.210 UTC [channelCmd] InitCmdFactory -> INFO 005 Endorser and orderer connections initialized
2021-11-23 03:19:42.415 UTC [cli.common] readBlock -> INFO 006 Expect block, but got status: &{SERVICE_UNAVAILABLE}
2021-11-23 03:19:42.425 UTC [channelCmd] InitCmdFactory -> INFO 007 Endorser and orderer connections initialized
2021-11-23 03:19:42.628 UTC [cli.common] readBlock -> INFO 008 Expect block, but got status: &{SERVICE_UNAVAILABLE}
2021-11-23 03:19:42.634 UTC [channelCmd] InitCmdFactory -> INFO 009 Endorser and orderer connections initialized
2021-11-23 03:19:42.838 UTC [cli.common] readBlock -> INFO 00a Expect block, but got status: &{SERVICE_UNAVAILABLE}
2021-11-23 03:19:42.843 UTC [channelCmd] InitCmdFactory -> INFO 00b Endorser and orderer connections initialized
2021-11-23 03:19:43.072 UTC [cli.common] readBlock -> INFO 00c Received block: 0
Channel 'mychannel' created
Joining org1 peer to the channel...
Using organization 1
+ peer channel join -b ./channel-artifacts/mychannel.block
+ res=0
2021-11-23 03:19:46.169 UTC [channelCmd] InitCmdFactory -> INFO 001 Endorser and orderer connections initialized
2021-11-23 03:19:46.283 UTC [channelCmd] executeJoin -> INFO 002 Successfully submitted proposal to join channel
Joining org2 peer to the channel...
Using organization 2
+ peer channel join -b ./channel-artifacts/mychannel.block
+ res=0
2021-11-23 03:19:49.373 UTC [channelCmd] InitCmdFactory -> INFO 001 Endorser and orderer connections initialized
2021-11-23 03:19:49.607 UTC [channelCmd] executeJoin -> INFO 002 Successfully submitted proposal to join channel
Setting anchor peer for org1...
Using organization 1
Fetching channel config for channel mychannel
Using organization 1
Fetching the most recent configuration block for the channel
+ peer channel fetch config config_block.pb -o orderer.example.com:7050 --ordererTLSHostnameOverride orderer.example.com -c mychannel --tls --cafile /opt/gopath/src/github.com/hyperledger/fabric/peer/organizations/ordererOrganizations/example.com/orderers/orderer.example.com/msp/tlscacerts/tlsca.example.com-cert.pem
2021-11-23 03:19:49.852 UTC [channelCmd] InitCmdFactory -> INFO 001 Endorser and orderer connections initialized
2021-11-23 03:19:49.855 UTC [cli.common] readBlock -> INFO 002 Received block: 0
2021-11-23 03:19:49.855 UTC [channelCmd] fetch -> INFO 003 Retrieving last config block: 0
2021-11-23 03:19:49.857 UTC [cli.common] readBlock -> INFO 004 Received block: 0
Decoding config block to JSON and isolating config to Org1MSPconfig.json
+ configtxlator proto_decode + jq '.data.data[0].payload.data.config'
--input config_block.pb --type common.Block
Generating anchor peer update transaction for Org1 on channel mychannel
+ jq '.channel_group.groups.Application.groups.Org1MSP.values += {"AnchorPeers":{"mod_policy": "Admins","value":{"anchor_peers": [{"host": "peer0.org1.example.com","port": 7051}]},"version": "0"}}' Org1MSPconfig.json
+ configtxlator proto_encode --input Org1MSPconfig.json --type common.Config
+ configtxlator proto_encode --input Org1MSPmodified_config.json --type common.Config
+ configtxlator compute_update --channel_id mychannel --original original_config.pb --updated modified_config.pb
+ configtxlator proto_decode --input config_update.pb --type common.ConfigUpdate
+ ++ cat config_update.json
jq .
+ echo '{"payload":{"header":{"channel_header":{"channel_id":"mychannel", "type":2}},"data":{"config_update":{' '"channel_id":' '"mychannel",' '"isolated_data":' '{},' '"read_set":' '{' '"groups":' '{' '"Application":' '{' '"groups":' '{' '"Org1MSP":' '{' '"groups":' '{},' '"mod_policy":' '"",' '"policies":' '{' '"Admins":' '{' '"mod_policy":' '"",' '"policy":' null, '"version":' '"0"' '},' '"Endorsement":' '{' '"mod_policy":' '"",' '"policy":' null, '"version":' '"0"' '},' '"Readers":' '{' '"mod_policy":' '"",' '"policy":' null, '"version":' '"0"' '},' '"Writers":' '{' '"mod_policy":' '"",' '"policy":' null, '"version":' '"0"' '}' '},' '"values":' '{' '"MSP":' '{' '"mod_policy":' '"",' '"value":' null, '"version":' '"0"' '}' '},' '"version":' '"0"' '}' '},' '"mod_policy":' '"",' '"policies":' '{},' '"values":' '{},' '"version":' '"1"' '}' '},' '"mod_policy":' '"",' '"policies":' '{},' '"values":' '{},' '"version":' '"0"' '},' '"write_set":' '{' '"groups":' '{' '"Application":' '{' '"groups":' '{' '"Org1MSP":' '{' '"groups":' '{},' '"mod_policy":' '"Admins",' '"policies":' '{' '"Admins":' '{' '"mod_policy":' '"",' '"policy":' null, '"version":' '"0"' '},' '"Endorsement":' '{' '"mod_policy":' '"",' '"policy":' null, '"version":' '"0"' '},' '"Readers":' '{' '"mod_policy":' '"",' '"policy":' null, '"version":' '"0"' '},' '"Writers":' '{' '"mod_policy":' '"",' '"policy":' null, '"version":' '"0"' '}' '},' '"values":' '{' '"AnchorPeers":' '{' '"mod_policy":' '"Admins",' '"value":' '{' '"anchor_peers":' '[' '{' '"host":' '"peer0.org1.example.com",' '"port":' 7051 '}' ']' '},' '"version":' '"0"' '},' '"MSP":' '{' '"mod_policy":' '"",' '"value":' null, '"version":' '"0"' '}' '},' '"version":' '"1"' '}' '},' '"mod_policy":' '"",' '"policies":' '{},' '"values":' '{},' '"version":' '"1"' '}' '},' '"mod_policy":' '"",' '"policies":' '{},' '"values":' '{},' '"version":' '"0"' '}' '}}}}'
+ configtxlator proto_encode --input config_update_in_envelope.json --type common.Envelope
2021-11-23 03:19:50.269 UTC [channelCmd] InitCmdFactory -> INFO 001 Endorser and orderer connections initialized
2021-11-23 03:19:50.293 UTC [channelCmd] update -> INFO 002 Successfully submitted channel update
Anchor peer set for org 'Org1MSP' on channel 'mychannel'
Setting anchor peer for org2...
Using organization 2
Fetching channel config for channel mychannel
Using organization 2
Fetching the most recent configuration block for the channel
+ peer channel fetch config config_block.pb -o orderer.example.com:7050 --ordererTLSHostnameOverride orderer.example.com -c mychannel --tls --cafile /opt/gopath/src/github.com/hyperledger/fabric/peer/organizations/ordererOrganizations/example.com/orderers/orderer.example.com/msp/tlscacerts/tlsca.example.com-cert.pem
2021-11-23 03:19:50.577 UTC [channelCmd] InitCmdFactory -> INFO 001 Endorser and orderer connections initialized
2021-11-23 03:19:50.581 UTC [cli.common] readBlock -> INFO 002 Received block: 1
2021-11-23 03:19:50.581 UTC [channelCmd] fetch -> INFO 003 Retrieving last config block: 1
2021-11-23 03:19:50.583 UTC [cli.common] readBlock -> INFO 004 Received block: 1
Decoding config block to JSON and isolating config to Org2MSPconfig.json
+ configtxlator proto_decode --input + jq '.data.data[0].payload.data.config'
config_block.pb --type common.Block
Generating anchor peer update transaction for Org2 on channel mychannel
+ jq '.channel_group.groups.Application.groups.Org2MSP.values += {"AnchorPeers":{"mod_policy": "Admins","value":{"anchor_peers": [{"host": "peer0.org2.example.com","port": 9051}]},"version": "0"}}' Org2MSPconfig.json
+ configtxlator proto_encode --input Org2MSPconfig.json --type common.Config
+ configtxlator proto_encode --input Org2MSPmodified_config.json --type common.Config
+ configtxlator compute_update --channel_id mychannel --original original_config.pb --updated modified_config.pb
+ configtxlator proto_decode --input config_update.pb --type common.ConfigUpdate
+ ++ cat config_update.json
jq .
+ echo '{"payload":{"header":{"channel_header":{"channel_id":"mychannel", "type":2}},"data":{"config_update":{' '"channel_id":' '"mychannel",' '"isolated_data":' '{},' '"read_set":' '{' '"groups":' '{' '"Application":' '{' '"groups":' '{' '"Org2MSP":' '{' '"groups":' '{},' '"mod_policy":' '"",' '"policies":' '{' '"Admins":' '{' '"mod_policy":' '"",' '"policy":' null, '"version":' '"0"' '},' '"Endorsement":' '{' '"mod_policy":' '"",' '"policy":' null, '"version":' '"0"' '},' '"Readers":' '{' '"mod_policy":' '"",' '"policy":' null, '"version":' '"0"' '},' '"Writers":' '{' '"mod_policy":' '"",' '"policy":' null, '"version":' '"0"' '}' '},' '"values":' '{' '"MSP":' '{' '"mod_policy":' '"",' '"value":' null, '"version":' '"0"' '}' '},' '"version":' '"0"' '}' '},' '"mod_policy":' '"",' '"policies":' '{},' '"values":' '{},' '"version":' '"1"' '}' '},' '"mod_policy":' '"",' '"policies":' '{},' '"values":' '{},' '"version":' '"0"' '},' '"write_set":' '{' '"groups":' '{' '"Application":' '{' '"groups":' '{' '"Org2MSP":' '{' '"groups":' '{},' '"mod_policy":' '"Admins",' '"policies":' '{' '"Admins":' '{' '"mod_policy":' '"",' '"policy":' null, '"version":' '"0"' '},' '"Endorsement":' '{' '"mod_policy":' '"",' '"policy":' null, '"version":' '"0"' '},' '"Readers":' '{' '"mod_policy":' '"",' '"policy":' null, '"version":' '"0"' '},' '"Writers":' '{' '"mod_policy":' '"",' '"policy":' null, '"version":' '"0"' '}' '},' '"values":' '{' '"AnchorPeers":' '{' '"mod_policy":' '"Admins",' '"value":' '{' '"anchor_peers":' '[' '{' '"host":' '"peer0.org2.example.com",' '"port":' 9051 '}' ']' '},' '"version":' '"0"' '},' '"MSP":' '{' '"mod_policy":' '"",' '"value":' null, '"version":' '"0"' '}' '},' '"version":' '"1"' '}' '},' '"mod_policy":' '"",' '"policies":' '{},' '"values":' '{},' '"version":' '"1"' '}' '},' '"mod_policy":' '"",' '"policies":' '{},' '"values":' '{},' '"version":' '"0"' '}' '}}}}'
+ configtxlator proto_encode --input config_update_in_envelope.json --type common.Envelope
2021-11-23 03:19:50.927 UTC [channelCmd] InitCmdFactory -> INFO 001 Endorser and orderer connections initialized
2021-11-23 03:19:50.950 UTC [channelCmd] update -> INFO 002 Successfully submitted channel update
Anchor peer set for org 'Org2MSP' on channel 'mychannel'
Channel 'mychannel' joined
  • 檢查
docker ps --format "table {{.ID}}\t{{.Names}}"

輸出一下內(nèi)容,包含三個(gè)節(jié)點(diǎn):

CONTAINER ID   NAMES
e3c7b448125d   cli
dfdc10df3d98   peer0.org1.example.com
5c5a432150fe   orderer.example.com
36ad49aa080c   peer0.org2.example.com

清理網(wǎng)絡(luò)

  • 如果使用了日志監(jiān)控
docker stop logspout && docker rm logspout && ./network.sh down
  • 沒(méi)有使用日監(jiān)控
./network.sh down

日志監(jiān)控

此步驟不是必需的腻窒,但對(duì)鏈碼進(jìn)行故障診斷非常有用芽世。要監(jiān)控智能合同的日志服赎,管理員可以使用logspout工具查看一組Docker容器的聚合輸出驻右。該工具將來(lái)自不同Docker容器的輸出流收集到一個(gè)地方闪唆,以便于從單個(gè)窗口查看正在發(fā)生的事情。這可以幫助管理員在安裝智能合同時(shí)調(diào)試問(wèn)題,幫助開(kāi)發(fā)人員在調(diào)用智能合同時(shí)調(diào)試問(wèn)題巧勤。由于一些容器的創(chuàng)建純粹是為了啟動(dòng)智能合同嵌灰,并且只存在很短的時(shí)間,因此從您的網(wǎng)絡(luò)收集所有日志是有幫助的颅悉。

A script to install and configure Logspout, monitordocker.sh, is already included in the commercial-paper sample in the Fabric samples. We will use the same script in this tutorial as well. The Logspout tool will continuously stream logs to your terminal, so you will need to use a new terminal window. Open a new terminal and navigate to the test-network directory.

cd fabric-samples/test-network

You can run the monitordocker.sh script from any directory. For ease of use, we will copy the monitordocker.sh script from the commercial-paper sample to your working directory

cp ../commercial-paper/organization/digibank/configuration/cli/monitordocker.sh .
# if you're not sure where it is
find . -name monitordocker.sh

然后沽瞭,您可以通過(guò)運(yùn)行以下命令啟動(dòng)Logspout:

./monitordocker.sh fabric_test

您應(yīng)該會(huì)看到類似于以下內(nèi)容的輸出:

Starting monitoring on all containers on the network docker_test
f96a6fae3c8cadcb8f3b5ac0f4fb808b45d1d30cc26498451974bd6a1b16a4b7

您一開(kāi)始不會(huì)看到任何日志,但當(dāng)我們部署鏈碼時(shí)剩瓶,這種情況會(huì)發(fā)生變化驹溃。使這個(gè)終端窗口寬,字體小可能會(huì)有幫助延曙。

如果找不到網(wǎng)絡(luò),就使用個(gè)下面命令查看下網(wǎng)絡(luò),實(shí)際上網(wǎng)絡(luò)名字就是上面修改過(guò)的名字.

docker network ls

清理

使用完鏈碼后豌鹤,您也可以使用以下命令刪除Logspout工具。

docker stop logspout && docker rm logspout && ./network.sh down

然后枝缔,您可以通過(guò)從測(cè)試網(wǎng)絡(luò)目錄發(fā)出以下命令來(lái)關(guān)閉test-network

./network.sh down

安裝鏈碼

打包鏈碼

  • 進(jìn)去go語(yǔ)言鏈碼包
cd fabric-samples/chaincode/fabcar/go
  • 下載依賴
GO111MODULE=on 
go mod vendor
  • 回到工作目錄
cd ../../../test-network
  • 設(shè)置管理員1 的環(huán)境的變量
export FABRIC_CFG_PATH=$PWD/../config/
export CORE_PEER_TLS_ENABLED=true
export CORE_PEER_LOCALMSPID="Org1MSP"
export CORE_PEER_TLS_ROOTCERT_FILE=${PWD}/organizations/peerOrganizations/org1.example.com/peers/peer0.org1.example.com/tls/ca.crt
export CORE_PEER_MSPCONFIGPATH=${PWD}/organizations/peerOrganizations/org1.example.com/users/Admin@org1.example.com/msp
export CORE_PEER_ADDRESS=localhost:7051
  • 管理員1和管理員2 (一個(gè)打包另一個(gè)直接拿來(lái)用就好了)打包鏈碼
peer lifecycle chaincode package fabcar.tar.gz --path ../chaincode/fabcar/go/  --lang golang --label fabcar_1

執(zhí)行完該命令會(huì)在當(dāng)前目錄下生成 鏈碼包文件 fabcar.tar.gz .

安裝鏈碼

在Org1 的peer 上安裝鏈碼

peer lifecycle chaincode install fabcar.tar.gz
2021-11-23 03:32:34.978 UTC [cli.lifecycle.chaincode] submitInstallProposal -> INFO 001 Installed remotely: response:<status:200 payload:"\nIfabcar_1:762e0fe3dbeee0f7b08fb6200adeb4a3a20f649a00f168c0b3c2257e53b6e506\022\010fabcar_1" >
2021-11-23 03:32:34.978 UTC [cli.lifecycle.chaincode] submitInstallProposal -> INFO 002 Chaincode code package identifier: fabcar_1:762e0fe3dbeee0f7b08fb6200adeb4a3a20f649a00f168c0b3c2257e53b6e506
  • 查詢已安裝的鏈碼
peer lifecycle chaincode queryinstalled
Installed chaincodes on peer:
Package ID: fabcar_1:762e0fe3dbeee0f7b08fb6200adeb4a3a20f649a00f168c0b3c2257e53b6e506, Label: fabcar_1

在Org2的 peer 上安裝鏈碼

設(shè)置以下環(huán)境變量作為Org2管理員操作布疙,并瞄準(zhǔn)Org2對(duì)等機(jī)peer0.org2.example.com

export CORE_PEER_TLS_ENABLED=true
export CORE_PEER_LOCALMSPID="Org2MSP"
export CORE_PEER_TLS_ROOTCERT_FILE=${PWD}/organizations/peerOrganizations/org2.example.com/peers/peer0.org2.example.com/tls/ca.crt
export CORE_PEER_MSPCONFIGPATH=${PWD}/organizations/peerOrganizations/org2.example.com/users/Admin@org2.example.com/msp
export CORE_PEER_ADDRESS=localhost:9051

發(fā)出以下命令來(lái)安裝鏈碼:

peer lifecycle chaincode install fabcar.tar.gz
2021-11-23 03:33:56.305 UTC [cli.lifecycle.chaincode] submitInstallProposal -> INFO 001 Installed remotely: response:<status:200 payload:"\nIfabcar_1:762e0fe3dbeee0f7b08fb6200adeb4a3a20f649a00f168c0b3c2257e53b6e506\022\010fabcar_1" >
2021-11-23 03:33:56.305 UTC [cli.lifecycle.chaincode] submitInstallProposal -> INFO 002 Chaincode code package identifier: fabcar_1:762e0fe3dbeee0f7b08fb6200adeb4a3a20f649a00f168c0b3c2257e53b6e506
  • 查詢已安裝的鏈碼
peer lifecycle chaincode queryinstalled
Installed chaincodes on peer:
Package ID: fabcar_1:762e0fe3dbeee0f7b08fb6200adeb4a3a20f649a00f168c0b3c2257e53b6e506, Label: fabcar_1

批準(zhǔn)鏈碼

  • 設(shè)置環(huán)境變量
export CC_PACKAGE_ID=fabcar_1:762e0fe3dbeee0f7b08fb6200adeb4a3a20f649a00f168c0b3c2257e53b6e506
  • 批準(zhǔn)
peer lifecycle chaincode approveformyorg \
-o localhost:7050 \
--ordererTLSHostnameOverride orderer.example.com \
--channelID mychannel \
--name fabcar \
--version 1.0 \
--package-id $CC_PACKAGE_ID \
--sequence 1 \
--tls \
--cafile ${PWD}/organizations/ordererOrganizations/example.com/orderers/orderer.example.com/msp/tlscacerts/tlsca.example.com-cert.pem
  • 日志
2021-11-23 03:37:54.483 UTC [chaincodeCmd] ClientWait -> INFO 001 txid [377e45a0d4663c9afe9857656d31208bd70e9980373cc1a79256de0af7850311] committed with status (VALID) at
  • 設(shè)置環(huán)境變量為組織以的管理員
export CORE_PEER_LOCALMSPID="Org1MSP"
export CORE_PEER_MSPCONFIGPATH=${PWD}/organizations/peerOrganizations/org1.example.com/users/Admin@org1.example.com/msp
export CORE_PEER_TLS_ROOTCERT_FILE=${PWD}/organizations/peerOrganizations/org1.example.com/peers/peer0.org1.example.com/tls/ca.crt
export CORE_PEER_ADDRESS=localhost:7051
  • 批準(zhǔn)
peer lifecycle chaincode approveformyorg -o localhost:7050 --ordererTLSHostnameOverride orderer.example.com --channelID mychannel --name fabcar --version 1.0 --package-id $CC_PACKAGE_ID --sequence 1 --tls --cafile ${PWD}/organizations/ordererOrganizations/example.com/orderers/orderer.example.com/msp/tlscacerts/tlsca.example.com-cert.pem
  • 日志
2021-11-23 03:38:51.638 UTC [chaincodeCmd] ClientWait -> INFO 001 txid [6eddec6e2aaced7aac59d7f8f5b3718104f62be4560d49466f9e120390c85292] committed with status (VALID) at

提交鏈碼

  • 檢查批準(zhǔn)情況
peer lifecycle chaincode checkcommitreadiness  \
--channelID mychannel  \
--name fabcar  \
--version 1.0  \
--sequence 1  \
--tls  \
--cafile ${PWD}/organizations/ordererOrganizations/example.com/orderers/orderer.example.com/msp/tlscacerts/tlsca.example.com-cert.pem  \
--output json
  • 日志
{
    "approvals": {
        "Org1MSP": true,
        "Org2MSP": true
    }
}
  • 提交
peer lifecycle chaincode commit  \
-o localhost:7050  \
--ordererTLSHostnameOverride orderer.example.com  \
--channelID mychannel  \
--name fabcar  \
--version 1.0  \
--sequence 1  \
--tls  \
--cafile ${PWD}/organizations/ordererOrganizations/example.com/orderers/orderer.example.com/msp/tlscacerts/tlsca.example.com-cert.pem  \
--peerAddresses localhost:7051  \
--tlsRootCertFiles ${PWD}/organizations/peerOrganizations/org1.example.com/peers/peer0.org1.example.com/tls/ca.crt  \
--peerAddresses localhost:9051  \
--tlsRootCertFiles ${PWD}/organizations/peerOrganizations/org2.example.com/peers/peer0.org2.example.com/tls/ca.crt
  • 日志
2021-11-23 03:41:47.755 UTC [chaincodeCmd] ClientWait -> INFO 001 txid [1f08b845f0462c415d70799360cc9e72c41e9e768a26a5eef240ed14cd061d0e] committed with status (VALID) at localhost:9051
2021-11-23 03:41:47.806 UTC [chaincodeCmd] ClientWait -> INFO 002 txid [1f08b845f0462c415d70799360cc9e72c41e9e768a26a5eef240ed14cd061d0e] committed with status (VALID) at localhost:7051
  • 查詢已提交
peer lifecycle chaincode querycommitted  \
--channelID mychannel  \
--name fabcar  \
--cafile ${PWD}/organizations/ordererOrganizations/example.com/orderers/orderer.example.com/msp/tlscacerts/tlsca.example.com-cert.pem 
  • 日志
Committed chaincode definition for chaincode 'fabcar' on channel 'mychannel':
Version: 1.0, Sequence: 1, Endorsement Plugin: escc, Validation Plugin: vscc, Approvals: [Org1MSP: true, Org2MSP: true]

調(diào)用鏈碼

peer chaincode invoke -o localhost:7050 \
--ordererTLSHostnameOverride orderer.example.com \
--tls \
--cafile \
${PWD}/organizations/ordererOrganizations/example.com/orderers/orderer.example.com/msp/tlscacerts/tlsca.example.com-cert.pem \
-C mychannel \
-n fabcar \
--peerAddresses localhost:7051 \
--tlsRootCertFiles ${PWD}/organizations/peerOrganizations/org1.example.com/peers/peer0.org1.example.com/tls/ca.crt \
--peerAddresses localhost:9051 \
--tlsRootCertFiles ${PWD}/organizations/peerOrganizations/org2.example.com/peers/peer0.org2.example.com/tls/ca.crt \
-c '{"function":"initLedger","Args":[]}' 
  • 日志
2021-11-23 03:43:29.125 UTC [chaincodeCmd] chaincodeInvokeOrQuery -> INFO 001 Chaincode invoke successful. result: status:200
  • 查詢
peer chaincode query  \
-C mychannel  \
-n fabcar  \
-c '{"Args":["queryAllCars"]}'
  • 日志
[{"Key":"CAR0","Record":{"make":"Toyota","model":"Prius","colour":"blue","owner":"Tomoko"}},{"Key":"CAR1","Record":{"make":"Ford","model":"Mustang","colour":"red","owner":"Brad"}},{"Key":"CAR2","Record":{"make":"Hyundai","model":"Tucson","colour":"green","owner":"Jin Soo"}},{"Key":"CAR3","Record":{"make":"Volkswagen","model":"Passat","colour":"yellow","owner":"Max"}},{"Key":"CAR4","Record":{"make":"Tesla","model":"S","colour":"black","owner":"Adriana"}},{"Key":"CAR5","Record":{"make":"Peugeot","model":"205","colour":"purple","owner":"Michel"}},{"Key":"CAR6","Record":{"make":"Chery","model":"S22L","colour":"white","owner":"Aarav"}},{"Key":"CAR7","Record":{"make":"Fiat","model":"Punto","colour":"violet","owner":"Pari"}},{"Key":"CAR8","Record":{"make":"Tata","model":"Nano","colour":"indigo","owner":"Valeria"}},{"Key":"CAR9","Record":{"make":"Holden","model":"Barina","colour":"brown","owner":"Shotaro"}}]

升級(jí)鏈碼

創(chuàng)建通道

生成通道交易文件

configtxgen \
-profile TwoOrgsChannel \
-outputCreateChannelTx ./channel-artifacts/channel1.tx \
-channelID channel1 \
-configPath ./configtx/
  • 日志
2021-11-23 03:48:12.027 UTC [common.tools.configtxgen] main -> INFO 001 Loading configuration
2021-11-23 03:48:12.049 UTC [common.tools.configtxgen.localconfig] Load -> INFO 002 Loaded configuration: /root/go/src/github.com/hyperledger/fabric-samples/test-network/configtx/configtx.yaml
2021-11-23 03:48:12.049 UTC [common.tools.configtxgen] doOutputChannelCreateTx -> INFO 003 Generating new channel configtx
2021-11-23 03:48:12.051 UTC [common.tools.configtxgen] doOutputChannelCreateTx -> INFO 004 Writing new channel tx

創(chuàng)建通道區(qū)塊

peer channel create \
-o localhost:7050  \
--ordererTLSHostnameOverride orderer.example.com \
-c channel1 \
-f ./channel-artifacts/channel1.tx \
--outputBlock ./channel-artifacts/channel1.block \
--tls \
--cafile ${PWD}/organizations/ordererOrganizations/example.com/orderers/orderer.example.com/msp/tlscacerts/tlsca.example.com-cert.pem
  • 日志
2021-11-23 03:48:52.616 UTC [channelCmd] InitCmdFactory -> INFO 001 Endorser and orderer connections initialized
2021-11-23 03:48:52.727 UTC [cli.common] readBlock -> INFO 002 Expect block, but got status: &{SERVICE_UNAVAILABLE}
2021-11-23 03:48:52.734 UTC [channelCmd] InitCmdFactory -> INFO 003 Endorser and orderer connections initialized
2021-11-23 03:48:52.942 UTC [cli.common] readBlock -> INFO 004 Expect block, but got status: &{SERVICE_UNAVAILABLE}
2021-11-23 03:48:52.948 UTC [channelCmd] InitCmdFactory -> INFO 005 Endorser and orderer connections initialized
2021-11-23 03:48:53.159 UTC [cli.common] readBlock -> INFO 006 Expect block, but got status: &{SERVICE_UNAVAILABLE}
2021-11-23 03:48:53.163 UTC [channelCmd] InitCmdFactory -> INFO 007 Endorser and orderer connections initialized
2021-11-23 03:48:53.367 UTC [cli.common] readBlock -> INFO 008 Expect block, but got status: &{SERVICE_UNAVAILABLE}
2021-11-23 03:48:53.372 UTC [channelCmd] InitCmdFactory -> INFO 009 Endorser and orderer connections initialized
2021-11-23 03:48:53.577 UTC [cli.common] readBlock -> INFO 00a Expect block, but got status: &{SERVICE_UNAVAILABLE}
2021-11-23 03:48:53.583 UTC [channelCmd] InitCmdFactory -> INFO 00b Endorser and orderer connections initialized
2021-11-23 03:48:53.789 UTC [cli.common] readBlock -> INFO 00c Received block: 0

加入通道

組織1 的peer加入通道

由于我們已經(jīng)以O(shè)rg1管理員的身份使用peer CLI愿卸,因此讓我們將Org1的Peer加入到通道中灵临。由于Org1提交了通道創(chuàng)建交易,因此我們的文件系統(tǒng)上已經(jīng)有了通道創(chuàng)世塊趴荸。使用以下命令將Org1的Peer加入通道儒溉。

peer channel join -b ./channel-artifacts/channel1.block

環(huán)境變量CORE_PEER_ADDRESS已設(shè)置為以peer0.org1.example.com為目標(biāo)。命令執(zhí)行成功后將生成peer0.org1.example.com加入通道的響應(yīng):

2021-11-23 03:50:44.103 UTC [channelCmd] InitCmdFactory -> INFO 001 Endorser and orderer connections initialized
2021-11-23 03:50:44.234 UTC [channelCmd] executeJoin -> INFO 002 Successfully submitted proposal to join channel
  • 查詢已加入的通道
peer channel list
  • 日志
2021-11-23 03:51:13.257 UTC [channelCmd] InitCmdFactory -> INFO 001 Endorser and orderer connections initialized
Channels peers has joined:
channel1
mychannel

組織2 的peer加入通道

  • 設(shè)置環(huán)境變量
export CORE_PEER_TLS_ENABLED=true
export CORE_PEER_LOCALMSPID="Org2MSP"
export CORE_PEER_TLS_ROOTCERT_FILE=${PWD}/organizations/peerOrganizations/org2.example.com/peers/peer0.org2.example.com/tls/ca.crt
export CORE_PEER_MSPCONFIGPATH=${PWD}/organizations/peerOrganizations/org2.example.com/users/Admin@org2.example.com/msp
export CORE_PEER_ADDRESS=localhost:9051
  • 列出當(dāng)前peer 加入的通道
peer channel list
root@fabric:~/go/src/github.com/hyperledger/fabric-samples/test-network# peer channel list
2021-11-23 05:06:44.010 UTC [channelCmd] InitCmdFactory -> INFO 001 Endorser and orderer connections initialized
Channels peers has joined:
mychannel
  • 從排序服務(wù)中獲取通道區(qū)塊數(shù)據(jù)
peer channel fetch 0 \
./channel-artifacts/channel_org2.block \
-o localhost:7050 \
--ordererTLSHostnameOverride orderer.example.com \
-c channel1 \
--tls \
--cafile ${PWD}/organizations/ordererOrganizations/example.com/orderers/orderer.example.com/msp/tlscacerts/tlsca.example.com-cert.pem
2021-11-23 05:06:29.092 UTC [channelCmd] InitCmdFactory -> INFO 001 Endorser and orderer connections initialized
2021-11-23 05:06:29.097 UTC [cli.common] readBlock -> INFO 002 Received block: 0
  • 加入通道
peer channel join -b ./channel-artifacts/channel_org2.block
2021-11-23 05:11:20.912 UTC [channelCmd] InitCmdFactory -> INFO 001 Endorser and orderer connections initialized
2021-11-23 05:11:21.071 UTC [channelCmd] executeJoin -> INFO 002 Successfully submitted proposal to join channel
  • 查詢結(jié)果
peer channel list
root@fabric:~/go/src/github.com/hyperledger/fabric-samples/test-network# peer channel list
2021-11-23 05:12:03.257 UTC [channelCmd] InitCmdFactory -> INFO 001 Endorser and orderer connections initialized
Channels peers has joined:
channel1
mychannel

向組織中新增peer

  • 工作目錄 :~/go/src/github.com/hyperledger/fabric-samples/test-network
  • 組織:org1

查看當(dāng)前組織中pee的個(gè)數(shù)

tree -L 5
│   └── peerOrganizations
│       ├── org1.example.com
│       │   ├── ca
│       │   │   ├── ca.org1.example.com-cert.pem
│       │   │   └── priv_sk
│       │   ├── connection-org1.json
│       │   ├── connection-org1.yaml
│       │   ├── msp
│       │   │   ├── admincerts
│       │   │   ├── cacerts
│       │   │   ├── config.yaml
│       │   │   └── tlscacerts
│       │   ├── peers
│       │   │   └── peer0.org1.example.com
│       │   ├── tlsca
│       │   │   ├── priv_sk
│       │   │   └── tlsca.org1.example.com-cert.pem
│       │   └── users
│       │       ├── Admin@org1.example.com
│       │       └── User1@org1.example.com

新增peer 證書(shū)文件

編輯證書(shū)配置文件

啟動(dòng)網(wǎng)絡(luò)的步驟中,查看輸出日志

Creating Org1 Identities
+ cryptogen generate --config=./organizations/cryptogen/crypto-config-org1.yaml --output=organizations

修愛(ài)配置文件 ./organizations/cryptogen/crypto-config-org1.yaml.

vim ./organizations/cryptogen/crypto-config-org1.yaml
# Copyright IBM Corp. All Rights Reserved.
#
# SPDX-License-Identifier: Apache-2.0
#


# ---------------------------------------------------------------------------
# "PeerOrgs" - Definition of organizations managing peer nodes
# ---------------------------------------------------------------------------
PeerOrgs:
  # ---------------------------------------------------------------------------
  # Org1
  # ---------------------------------------------------------------------------
  - Name: Org1
    Domain: org1.example.com
    EnableNodeOUs: true
    # ---------------------------------------------------------------------------
    # "Specs"
    # ---------------------------------------------------------------------------
    # Uncomment this section to enable the explicit definition of hosts in your
    # configuration.  Most users will want to use Template, below
    #
    # Specs is an array of Spec entries.  Each Spec entry consists of two fields:
    #   - Hostname:   (Required) The desired hostname, sans the domain.
    #   - CommonName: (Optional) Specifies the template or explicit override for
    #                 the CN.  By default, this is the template:
    #
    #                              "{{.Hostname}}.{{.Domain}}"
    #
    #                 which obtains its values from the Spec.Hostname and
    #                 Org.Domain, respectively.
    # ---------------------------------------------------------------------------
    #   - Hostname: foo # implicitly "foo.org1.example.com"
    #     CommonName: foo27.org5.example.com # overrides Hostname-based FQDN set above
    #   - Hostname: bar
    #   - Hostname: baz
    # ---------------------------------------------------------------------------
    # "Template"
    # ---------------------------------------------------------------------------
    # Allows for the definition of 1 or more hosts that are created sequentially
    # from a template. By default, this looks like "peer%d" from 0 to Count-1.
    # You may override the number of nodes (Count), the starting index (Start)
    # or the template used to construct the name (Hostname).
    #
    # Note: Template and Specs are not mutually exclusive.  You may define both
    # sections and the aggregate nodes will be created for you.  Take care with
    # name collisions
    # ---------------------------------------------------------------------------
    Template:
      Count: 2 # 此處由1 改為 2 
      SANS:
        - localhost
      # Start: 5
      # Hostname: {{.Prefix}}{{.Index}} # default
    # ---------------------------------------------------------------------------
    # "Users"
    # ---------------------------------------------------------------------------
    # Count: The number of user accounts _in addition_ to Admin
    # ---------------------------------------------------------------------------
    Users:
      Count: 1
  • 執(zhí)行網(wǎng)絡(luò)拓展命令
cryptogen extend --config=./organizations/cryptogen/crypto-config-org1.yaml --input=organizations
  • 再次查看目錄結(jié)構(gòu)
ls organizations/peerOrganizations/org1.example.com/peers
peer0.org1.example.com  peer1.org1.example.com

啟動(dòng)新peer節(jié)點(diǎn)

查看當(dāng)前節(jié)點(diǎn)

docker ps --format "table {{.ID}} \t {{.Names}}"
root@fabric:~/go/src/github.com/hyperledger/fabric-samples/test-network# docker ps --format "table {{.ID}} \t {{.Names}}"
CONTAINER ID     NAMES
a6b9c523c562     dev-peer0.org2.example.com-fabcar_1-762e0fe3dbeee0f7b08fb6200adeb4a3a20f649a00f168c0b3c2257e53b6e506
a20f2648b557     dev-peer0.org1.example.com-fabcar_1-762e0fe3dbeee0f7b08fb6200adeb4a3a20f649a00f168c0b3c2257e53b6e506
f69bca3357cc     logspout
f19399557a69     cli
263f14b81a51     peer0.org2.example.com
5513a783cb6a     peer0.org1.example.com
1eca52dd33b4     orderer.example.com

新增 docker-compose 配置

#
# Copyright IBM Corp All Rights Reserved
#
# SPDX-License-Identifier: Apache-2.0
#
version: '2'

networks:
  fabric_test:
      driver: bridge
      external: true

services:
  peer1.org1.example.com:
    container_name: peer1.org1.example.com
    tty: true
    image: hyperledger/fabric-peer:$IMAGE_TAG
    environment:
      - CORE_VM_ENDPOINT=unix:///host/var/run/docker.sock
      - CORE_PEER_ID=peer1.org1.example.com
      - FABRIC_LOGGING_SPEC=INFO
      - CORE_PEER_TLS_ENABLED=true
      - CORE_PEER_TLS_CERT_FILE=/etc/hyperledger/fabric/tls/server.crt
      - CORE_PEER_TLS_KEY_FILE=/etc/hyperledger/fabric/tls/server.key
      - CORE_PEER_TLS_ROOTCERT_FILE=/etc/hyperledger/fabric/tls/ca.crt
      - CORE_CHAINCODE_LOGGING_LEVEL=INFO
      - CORE_PEER_LOCALMSPID=Org1MSP
      - CORE_PEER_ADDRESS=peer1.org1.example.com:7051
      - CORE_VM_DOCKER_HOSTCONFIG_NETWORKMODE=${COMPOSE_PROJECT_NAME}_test
    working_dir: /opt/gopath/src/github.com/hyperledger/fabric
    command: peer node start
    ports:
      - 8051:7051
      - 8053:7053
    volumes:
      - /var/run/:/host/var/run/
      - ./organizations/peerOrganizations/org1.example.com/peers/peer1.org1.example.com/msp:/etc/hyperledger/fabric/msp
      - ./organizations/peerOrganizations/org1.example.com/peers/peer1.org1.example.com/tls:/etc/hyperledger/fabric/tls
    networks:
      - fabric_test

啟動(dòng)節(jié)點(diǎn)

docker-compose -f docker-compose.yaml up -d peer1.org1.example.com
  • 查看節(jié)點(diǎn)信息
docker ps --format "table {{.ID}}\t{{.Names}}" --filter name=org1
3cce207d4570   peer1.org1.example.com
5513a783cb6a   peer0.org1.example.com

將新節(jié)點(diǎn)加入通道

  • 配置環(huán)境變量
export CORE_PEER_TLS_ENABLED=true
export CORE_PEER_LOCALMSPID="Org1MSP"
export CORE_PEER_MSPCONFIGPATH=${PWD}/organizations/peerOrganizations/org1.example.com/users/Admin@org1.example.com/msp
export CORE_PEER_TLS_ROOTCERT_FILE=${PWD}/organizations/peerOrganizations/org1.example.com/peers/peer1.org1.example.com/tls/ca.crt
export CORE_PEER_ADDRESS=localhost:8051
peer channel fetch 0 \
./channel-artifacts/channel_org1_peer1.block \
-o localhost:7050 \
--ordererTLSHostnameOverride orderer.example.com \
-c mychannel \
--tls \
--cafile ${PWD}/organizations/ordererOrganizations/example.com/orderers/orderer.example.com/msp/tlscacerts/tlsca.example.com-cert.pem
  • 加入通道 mychannel
peer channel join -b ./channel-artifacts/channel_org1_peer1.block
2021-11-23 06:10:44.200 UTC [channelCmd] InitCmdFactory -> INFO 001 Endorser and orderer connections initialized
2021-11-23 06:10:44.324 UTC [channelCmd] executeJoin -> INFO 002 Successfully submitted proposal to join channel
  • 查看
peer channel  list
2021-11-23 06:11:00.887 UTC [channelCmd] InitCmdFactory -> INFO 001 Endorser and orderer connections initialized
Channels peers has joined:
mychannel

安裝鏈碼

  • 安裝鏈碼
peer lifecycle chaincode install fabcar.tar.gz
  • 批準(zhǔn)鏈碼
peer lifecycle chaincode approveformyorg \
-o localhost:7050 \
--ordererTLSHostnameOverride orderer.example.com \
--channelID mychannel \
--name fabcar \
--version 1.0 \
--package-id $CC_PACKAGE_ID \
--sequence 2 \
--tls \
--cafile ${PWD}/organizations/ordererOrganizations/example.com/orderers/orderer.example.com/msp/tlscacerts/tlsca.example.com-cert.pem
  • 查詢
peer lifecycle chaincode checkcommitreadiness  \
--channelID mychannel  \
--name fabcar  \
--version 1.0  \
--sequence 2  \
--tls  \
--cafile ${PWD}/organizations/ordererOrganizations/example.com/orderers/orderer.example.com/msp/tlscacerts/tlsca.example.com-cert.pem  \
--output json
  • 調(diào)用鏈碼
peer chaincode query  \
-C mychannel  \
-n fabcar  \
-c '{"Args":["queryAllCars"]}'

參考日志

root@fabric:~/go/src/github.com/hyperledger/fabric-samples/test-network# peer lifecycle chaincode approveformyorg \
> -o localhost:7050 \
> --ordererTLSHostnameOverride orderer.example.com \
> --channelID mychannel \
> --name fabcar \
> --version 1.0 \
> --package-id $CC_PACKAGE_ID \
> --sequence 2 \
> --tls \
> --cafile ${PWD}/organizations/ordererOrganizations/example.com/orderers/orderer.example.com/msp/tlscacerts/tlsca.example.com-cert.pem
2021-11-23 07:26:01.492 UTC [chaincodeCmd] ClientWait -> INFO 001 txid [b1d45658ff7f90866adda7ff81199386cd8dff7cd05819c48228c63eecf6b56a] committed with status (VALID) at
root@fabric:~/go/src/github.com/hyperledger/fabric-samples/test-network# export CORE_PEER_TLS_ENABLED=true
root@fabric:~/go/src/github.com/hyperledger/fabric-samples/test-network# export CORE_PEER_LOCALMSPID="Org2MSP"
root@fabric:~/go/src/github.com/hyperledger/fabric-samples/test-network# export CORE_PEER_TLS_ROOTCERT_FILE=${PWD}/organizations/peerOrganizations/org2.example.com/peers/peer0.org2.example.com/tls/ca.crt
root@fabric:~/go/src/github.com/hyperledger/fabric-samples/test-network# export CORE_PEER_MSPCONFIGPATH=${PWD}/organizations/peerOrganizations/org2.example.com/users/Admin@org2.example.com/msp
root@fabric:~/go/src/github.com/hyperledger/fabric-samples/test-network# export CORE_PEER_ADDRESS=localhost:9051
root@fabric:~/go/src/github.com/hyperledger/fabric-samples/test-network# peer lifecycle chaincode approveformyorg \
> -o localhost:7050 \
> --ordererTLSHostnameOverride orderer.example.com \
> --channelID mychannel \
> --name fabcar \
> --version 1.0 \
> --package-id $CC_PACKAGE_ID \
> --sequence 2 \
> --tls \
> --cafile ${PWD}/organizations/ordererOrganizations/example.com/orderers/orderer.example.com/msp/tlscacerts/tlsca.example.com-cert.pem
2021-11-23 07:26:33.901 UTC [chaincodeCmd] ClientWait -> INFO 001 txid [078f3ee511dca0c29f0af021fdf154b3ca05a0ac62f2c7d05c8c77c804cb0f8a] committed with status (VALID) at
root@fabric:~/go/src/github.com/hyperledger/fabric-samples/test-network# peer lifecycle chaincode checkcommitreadiness  \
> --channelID mychannel  \
> --name fabcar  \
> --version 1.0  \
> --sequence 2  \
> --tls  \
> --cafile ${PWD}/organizations/ordererOrganizations/example.com/orderers/orderer.example.com/msp/tlscacerts/tlsca.example.com-cert.pem  \
> --output json
{
    "approvals": {
        "Org1MSP": true,
        "Org2MSP": true
    }
}
root@fabric:~/go/src/github.com/hyperledger/fabric-samples/test-network# export CORE_PEER_TLS_ENABLED=true
root@fabric:~/go/src/github.com/hyperledger/fabric-samples/test-network# export CORE_PEER_LOCALMSPID="Org1MSP"
root@fabric:~/go/src/github.com/hyperledger/fabric-samples/test-network# export CORE_PEER_MSPCONFIGPATH=${PWD}/organizations/peerOrganizations/org1.example.com/users/Admin@org1.example.com/msp
root@fabric:~/go/src/github.com/hyperledger/fabric-samples/test-network# export CORE_PEER_TLS_ROOTCERT_FILE=${PWD}/organizations/peerOrganizations/org1.example.com/peers/peer1.org1.example.com/tls/ca.crt
root@fabric:~/go/src/github.com/hyperledger/fabric-samples/test-network# export CORE_PEER_ADDRESS=localhost:8051
root@fabric:~/go/src/github.com/hyperledger/fabric-samples/test-network# peer chaincode query  \
> -C mychannel  \
> -n fabcar  \
> -c '{"Args":["queryAllCars"]}'
[{"Key":"CAR0","Record":{"make":"Toyota","model":"Prius","colour":"blue","owner":"Tomoko"}},{"Key":"CAR1","Record":{"make":"Ford","model":"Mustang","colour":"red","owner":"Brad"}},{"Key":"CAR2","Record":{"make":"Hyundai","model":"Tucson","colour":"green","owner":"Jin Soo"}},{"Key":"CAR3","Record":{"make":"Volkswagen","model":"Passat","colour":"yellow","owner":"Max"}},{"Key":"CAR4","Record":{"make":"Tesla","model":"S","colour":"black","owner":"Adriana"}},{"Key":"CAR5","Record":{"make":"Peugeot","model":"205","colour":"purple","owner":"Michel"}},{"Key":"CAR6","Record":{"make":"Chery","model":"S22L","colour":"white","owner":"Aarav"}},{"Key":"CAR7","Record":{"make":"Fiat","model":"Punto","colour":"violet","owner":"Pari"}},{"Key":"CAR8","Record":{"make":"Tata","model":"Nano","colour":"indigo","owner":"Valeria"}},{"Key":"CAR9","Record":{"make":"Holden","model":"Barina","colour":"brown","owner":"Shotaro"}}]

向網(wǎng)絡(luò)中新增組織

為 Org3生成證書(shū)文件

在另一個(gè)終端中发钝,addOrg3test-network.

cd addOrg3

首先顿涣,我們將為 Org3 對(duì)等方以及應(yīng)用程序和管理員用戶創(chuàng)建證書(shū)和密鑰。因?yàn)槲覀冋诟乱粋€(gè)示例通道笼平,所以我們將使用 cryptogen 工具而不是使用證書(shū)頒發(fā)機(jī)構(gòu)园骆。以下命令使用 cryptogen 讀取org3-crypto.yaml文件并在新org3.example.com文件夾中生成 Org3 加密材料:

cryptogen generate --config=org3-crypto.yaml --output="../organizations"

您可以在目錄中找到生成的 Org3 加密材料以及 Org1 和 Org2 的證書(shū)和密鑰:test-network/organizations/peerOrganizations.

一旦我們創(chuàng)建了 Org3 加密材料,我們就可以使用 configtxgen 工具打印出 Org3 組織定義寓调。

我們將通過(guò)告訴工具在當(dāng)前目錄中查找configtx.yaml 它需要攝取的文件來(lái)開(kāi)始命令锌唾。

export FABRIC_CFG_PATH=$PWD
configtxgen -printOrg Org3MSP > ../organizations/peerOrganizations/org3.example.com/org3.json

上面的命令創(chuàng)建了一個(gè) JSON 文件 org3.json 并將其寫(xiě)入下面文件夾。

test-network/organizations/peerOrganizations/org3.example.com/

組織定義包含 Org3 的策略定義夺英、Org3 的 NodeOU 定義以及兩個(gè)以 base64 格式編碼的重要證書(shū):

  • CA 根證書(shū)晌涕,用于建立組織間的信任根
  • 一個(gè) TLS 根證書(shū),由 gossip 協(xié)議用于標(biāo)識(shí) Org3 以進(jìn)行塊傳播和服務(wù)發(fā)現(xiàn)

我們將通過(guò)將此組織定義附加到通道配置來(lái)將 Org3 添加到通道中痛悯。

調(diào)出 Org3 組件

就是 啟動(dòng) 組織 3 的 peer 節(jié)點(diǎn)

創(chuàng)建 Org3 證書(shū)材料后余黎,我們現(xiàn)在可以啟動(dòng) Org3 對(duì)等體。從addOrg3目錄中载萌,發(fā)出以下命令:

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

如果命令成功惧财,您將看到 Org3 peer 的創(chuàng)建:

Creating peer0.org3.example.com ... done

此 Docker Compose 文件已配置為跨我們的初始網(wǎng)絡(luò)橋接巡扇,以便 Org3 對(duì)等節(jié)點(diǎn)與測(cè)試網(wǎng)絡(luò)的現(xiàn)有對(duì)等節(jié)點(diǎn)和排序節(jié)點(diǎn)進(jìn)行解析。

獲取配置

讓我們?nèi)カ@取頻道的最新配置塊 – channel1垮衷。

我們必須拉取最新版本的配置的原因是因?yàn)橥ǖ琅渲迷厥前姹净摹?/strong>

出于多種原因厅翔,版本控制很重要。它可以防止重復(fù)或重放配置更改(例如搀突,使用舊 CRL 恢復(fù)到通道配置將代表安全風(fēng)險(xiǎn))刀闷。它還有助于確保并發(fā)性(如果您想從頻道中刪除組織,例如仰迁,在添加新組織后甸昏,版本控制將有助于防止您刪除兩個(gè)組織,而不僅僅是要?jiǎng)h除的組織)徐许。

導(dǎo)航回test-network目錄施蜜。因?yàn)?Org3 還不是頻道的成員,我們需要以另一個(gè)組織的管理員身份操作來(lái)獲取頻道配置绊寻。因?yàn)?Org1 是頻道的成員花墩,所以 Org1 管理員有權(quán)從排序服務(wù)中獲取頻道配置悬秉。發(fā)出以下命令以作為 Org1 管理員進(jìn)行操作澄步。

# you can issue all of these commands at once
export FABRIC_CFG_PATH=${PWD}/../config/
export CORE_PEER_TLS_ENABLED=true
export CORE_PEER_LOCALMSPID="Org1MSP"
export CORE_PEER_TLS_ROOTCERT_FILE=${PWD}/organizations/peerOrganizations/org1.example.com/peers/peer0.org1.example.com/tls/ca.crt
export CORE_PEER_MSPCONFIGPATH=${PWD}/organizations/peerOrganizations/org1.example.com/users/Admin@org1.example.com/msp
export CORE_PEER_ADDRESS=localhost:7051

我們現(xiàn)在可以發(fā)出命令來(lái)獲取最新的配置塊:

peer channel fetch config channel-artifacts/config_block.pb \
-o localhost:7050 \
--ordererTLSHostnameOverride orderer.example.com \
-c mychannel \
--tls \
--cafile ${PWD}/organizations/ordererOrganizations/example.com/orderers/orderer.example.com/msp/tlscacerts/tlsca.example.com-cert.pem

此命令將二進(jìn)制 protobuf 通道配置塊保存到 config_block.pb. 請(qǐng)注意,名稱和文件擴(kuò)展名的選擇是任意的和泌。但是村缸,建議遵循標(biāo)識(shí)所表示的對(duì)象類型及其編碼(protobuf 或 JSON)的約定。

peer channel fetch發(fā)出命令后武氓,日志中會(huì)顯示以下輸出:

2021-11-11 15:32:31.586 CST [channelCmd] InitCmdFactory -> INFO 001 Endorser and orderer connections initialized
2021-11-11 15:32:31.592 CST [cli.common] readBlock -> INFO 002 Received block: 2
2021-11-11 15:32:31.592 CST [channelCmd] fetch -> INFO 003 Retrieving last config block: 2
2021-11-11 15:32:31.595 CST [cli.common] readBlock -> INFO 004 Received block: 2

這告訴我們最近的配置塊channel1實(shí)際上是塊 2梯皿,而不是創(chuàng)世塊。

默認(rèn)情況下县恕,該 命令返回目標(biāo)通道的最新配置塊东羹,在這種情況下是第三個(gè)塊。

這是因?yàn)闇y(cè)試網(wǎng)絡(luò)腳本為我們的兩個(gè)組織定義了錨點(diǎn)忠烛,并且在兩個(gè)單獨(dú)的通道更新事務(wù)中属提。因此,我們有以下配置序列:

  • block 0: genesis block
  • block 1: Org1 anchor peer update
  • block 2: Org2 anchor peer update

通道配置文件夾下新增塊信息文件

├── channel-artifacts
│   ├── channel1.block
│   ├── channel1.tx
│   └── config_block.pb # 新增

將配置轉(zhuǎn)換為 JSON 并對(duì)其進(jìn)行修剪

通道配置塊存儲(chǔ)在channel-artifacts文件夾中美尸,以使更新過(guò)程與其他工件分開(kāi)冤议。進(jìn)入 channel-artifacts 文件夾以完成以下步驟:

cd channel-artifacts
  • 使用該configtxlator工具將這個(gè)通道配置塊解碼為 JSON 格式(可以被人類讀取和修改)
configtxlator proto_decode \
--input config_block.pb \
--type common.Block \
--output config_block.json
  • 去除所有與我們想要進(jìn)行的更改無(wú)關(guān)的標(biāo)題、元數(shù)據(jù)师坎、創(chuàng)建者簽名等

帶有數(shù)組的情況下恕酸,加引號(hào),這個(gè)命令給我們留下了一個(gè)精簡(jiǎn)的 JSON 對(duì)象 config.json 它將作為我們配置更新的基線胯陋。

jq '.data.data[0].payload.data.config' config_block.json > config.json

添加 Org3 加密材

jq 語(yǔ)法參考

jq 官方文檔

選項(xiàng) 解釋 備注
-s read (slurp) all inputs into an array; apply filter to it 使用-s 選項(xiàng)蕊温,jq 會(huì)將所有的 JSON 輸入放入一個(gè)數(shù)組中并在這個(gè)數(shù)組上使用 filter袱箱。"-s"選項(xiàng)不但影響到 filter 的寫(xiě)法。如果在 filter 中需要對(duì)數(shù)據(jù)進(jìn)行選擇和映射义矛,其還會(huì)影響最終結(jié)果犯眠。
jq -s '.[0] * .[1]' 輸入流1 輸入流2 > test.json 
  • .[0]:由第1個(gè)輸入流產(chǎn)生的數(shù)組數(shù)據(jù)
  • .[1]:由第2個(gè)輸入流產(chǎn)生的數(shù)組數(shù)據(jù)
  • *:參考官方文檔
Multiplication, division, modulo: *, /, and %
These infix operators behave as expected when given two numbers. Division by zero raises an error. x % y computes x modulo y.

Multiplying a string by a number produces the concatenation of that string that many times. "x" * 0 produces null.

Dividing a string by another splits the first using the second as separators.

Multiplying two objects will merge them recursively: this works like addition but if both objects contain a value for the same key, and the values are objects, the two are merged with the same strategy.

增加配置信息

我們將jq再次使用該工具將 Org3 配置定義 org3.json添加到通道的應(yīng)用程序組字段,并將輸出命名為 modified_config.json症革。

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

增量計(jì)算,得到增

現(xiàn)在我們有兩個(gè)感興趣的 JSON 文件 config.jsonmodified_config.json. 初始文件僅包含 Org1 和 Org2 材料筐咧,而修改后的文件包含所有三個(gè) Org。

此時(shí)噪矛,只需重新編碼這兩個(gè) JSON 文件并計(jì)算增量即可量蕊。

  • 首先,轉(zhuǎn)換config.json回一個(gè)名為的protobuf config.pb
configtxlator proto_encode \
--input config.json \
--type common.Config \
--output config.pb
  • 接下來(lái)艇挨,編碼modified_config.jsonmodified_config.pb
configtxlator proto_encode \
--input modified_config.json \
--type common.Config \
--output modified_config.pb
  • 在用于configtxlator計(jì)算這兩個(gè)配置 protobufs 之間的增量残炮。此命令將輸出一個(gè)名為的新 protobuf 二進(jìn)制文件org3_update.pb
configtxlator compute_update \
--channel_id channel1 \
--original config.pb \
--updated modified_config.pb \
--output org3_update.pb

這個(gè)新的 proto org3_update.pb包含 Org3 定義和指向 Org1 和 Org2 材料的高級(jí)指針。

封裝更新信息

在提交頻道更新之前缩滨,我們需要執(zhí)行一些最后的步驟势就。

  • 首先,讓我們將此對(duì)象解碼為可編輯的 JSON 格式并調(diào)用它org3_update.json
configtxlator proto_decode \
--input org3_update.pb \
--type common.ConfigUpdate \
--output org3_update.json

現(xiàn)在脉漏,我們有一個(gè)解碼后的更新文件org3_update.json.我們需要將它包裝一下苞冯。

這一步將返回我們之前剝離的頭字段。我們將此文件命名為org3_update_in_envelope.json

echo '{"payload":{"header":{"channel_header":{"channel_id":"'channel1'", "type":2}},"data":{"config_update":'$(cat org3_update.json)'}}}' | jq . > org3_update_in_envelope.json

使用我們正確形成的 JSONorg3_update_in_envelope.json我們將configtxlator最后一次利用該工具并將其轉(zhuǎn)換為 Fabric 所需的完全成熟的 protobuf 格式侧巨。我們將命名我們的最終更新對(duì)象org3_update_in_envelope.pb:

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

簽署并提交配置更

簽署

現(xiàn)在有一個(gè) protobuf 二進(jìn)制文件 org3_update_in_envelope.pb. 但是舅锄,在將配置寫(xiě)入分類帳之前,我們需要必需的管理員用戶的簽名司忱。

我們頻道應(yīng)用程序組的修改策略 (mod_policy) 設(shè)置為默認(rèn)值“MAJORITY”皇忿,這意味著我們需要大多數(shù)現(xiàn)有組織管理員對(duì)其進(jìn)行簽名。

因?yàn)槲覀冎挥袃蓚€(gè)組織——Org1 和 Org2——而且兩個(gè)組織中的大多數(shù)是兩個(gè)坦仍,==所以我們需要他們都簽名==鳍烁。

如果沒(méi)有這兩個(gè)簽名,排序服務(wù)將拒絕未能滿足策略的交易繁扎。

  • 首先幔荒,讓我們將此更新協(xié)議簽名為 Org1。導(dǎo)航回test-network 目錄:

請(qǐng)記住锻离,我們導(dǎo)出了必要的環(huán)境變量以作為 Org1 管理員進(jìn)行操作铺峭。因此,以下命令會(huì)將更新簽名為 Org1汽纠。peer channel signconfigtx

peer channel signconfigtx -f channel-artifacts/org3_update_in_envelope.pb

最后一步是切換容器的身份以反映 Org2 Admin 用戶卫键。我們通過(guò)導(dǎo)出特定于 Org2 MSP 的四個(gè)環(huán)境變量來(lái)做到這一點(diǎn)。

設(shè)置 Org2 環(huán)境變量:

# you can issue all of these commands at once
export FABRIC_CFG_PATH=${PWD}/../config/
export CORE_PEER_TLS_ENABLED=true
export CORE_PEER_LOCALMSPID="Org2MSP"
export CORE_PEER_TLS_ROOTCERT_FILE=${PWD}/organizations/peerOrganizations/org2.example.com/peers/peer0.org2.example.com/tls/ca.crt
export CORE_PEER_MSPCONFIGPATH=${PWD}/organizations/peerOrganizations/org2.example.com/users/Admin@org2.example.com/msp
export CORE_PEER_ADDRESS=localhost:9051

更新

最后虱朵,我們將發(fā)出peer channel update命令莉炉。Org2 Admin 的簽名將附加到此調(diào)用中钓账,因此無(wú)需再次手動(dòng)簽署 protobuf。(更新角色會(huì)自動(dòng)簽署并且更新通道配置信息)

peer channel update -f channel-artifacts/org3_update_in_envelope.pb -c channel1 -o localhost:7050 --ordererTLSHostnameOverride orderer.example.com --tls --cafile ${PWD}/organizations/ordererOrganizations/example.com/orderers/orderer.example.com/msp/tlscacerts/tlsca.example.com-cert.pem

成功的通道更新調(diào)用會(huì)向通道上的所有對(duì)等方返回一個(gè)新塊:塊 3絮宁。

如果您還記得梆暮,塊 0-2 是初始通道配置。Block 3 作為最新的通道配置绍昂,現(xiàn)在在通道上定義了 Org3啦粹。

您可以peer0.org1.example.com通過(guò)發(fā)出以下命令來(lái)檢查日志:

docker logs -f peer0.org1.example.com

將 Org3的節(jié)點(diǎn)加入頻道

此時(shí),通道配置已更新為包括我們的新組織 Org3窘游,這意味著它的對(duì)等節(jié)點(diǎn)現(xiàn)在可以加入channel1唠椭。

導(dǎo)出以下環(huán)境變量以作為 Org3 管理員進(jìn)行操作:

# you can issue all of these commands at once
export FABRIC_CFG_PATH=${PWD}/../config/
export CORE_PEER_TLS_ENABLED=true
export CORE_PEER_LOCALMSPID="Org3MSP"
export CORE_PEER_TLS_ROOTCERT_FILE=${PWD}/organizations/peerOrganizations/org3.example.com/peers/peer0.org3.example.com/tls/ca.crt
export CORE_PEER_MSPCONFIGPATH=${PWD}/organizations/peerOrganizations/org3.example.com/users/Admin@org3.example.com/msp
export CORE_PEER_ADDRESS=localhost:11051

作為通道更新成功的結(jié)果,排序服務(wù)將驗(yàn)證 Org3 是否可以拉取創(chuàng)世塊并加入通道忍饰。如果 Org3 未成功附加到通道配置贪嫂,則排序服務(wù)將拒絕此請(qǐng)求。

使用命令來(lái)檢索這個(gè)塊:peer channel fetch

peer channel fetch 0 channel-artifacts/channel1.block \
-o localhost:7050 \
--ordererTLSHostnameOverride orderer.example.com \
-c channel1 \
--tls \
--cafile ${PWD}/organizations/ordererOrganizations/example.com/orderers/orderer.example.com/msp/tlscacerts/tlsca.example.com-cert.pem
2021-11-11 17:40:23.213 CST [channelCmd] InitCmdFactory -> INFO 001 Endorser and orderer connections initialized
2021-11-11 17:40:23.220 CST [cli.common] readBlock -> INFO 002 Received block: 0

請(qǐng)注意艾蓝,我們正在傳遞 0以指示我們想要通道分類帳上的第一個(gè)塊力崇;即創(chuàng)世區(qū)塊。

如果我們簡(jiǎn)單地傳遞命令 peer channel fetch config赢织,那么我們將收到塊 3——定義了 Org3 的更新配置亮靴。但是,我們不能從下游塊開(kāi)始我們的賬本——我們必須從塊 0 開(kāi)始敌厘。

如果成功台猴,該命令會(huì)將創(chuàng)世塊返回名為channel1.block. 我們現(xiàn)在可以使用此塊channel1.blockpeer加入通道。

發(fā)出命令peer channel join并傳入創(chuàng)世塊以將 Org3 peer 加入通道:

peer channel join -b channel-artifacts/channel1.block
2021-11-12 10:59:01.939 CST [channelCmd] InitCmdFactory -> INFO 001 Endorser and orderer connections initialized
2021-11-12 10:59:02.017 CST [channelCmd] executeJoin -> INFO 002 Successfully submitted proposal to join channel

查詢結(jié)果

在 Org3的環(huán)境下查看該peer peer0.org3.example.com加入的通道

# you can issue all of these commands at once
export FABRIC_CFG_PATH=${PWD}/../config/
export CORE_PEER_TLS_ENABLED=true
export CORE_PEER_LOCALMSPID="Org3MSP"
export CORE_PEER_TLS_ROOTCERT_FILE=${PWD}/organizations/peerOrganizations/org3.example.com/peers/peer0.org3.example.com/tls/ca.crt
export CORE_PEER_MSPCONFIGPATH=${PWD}/organizations/peerOrganizations/org3.example.com/users/Admin@org3.example.com/msp
export CORE_PEER_ADDRESS=localhost:11051
peer channel list
(base) test-network|5b8c439? ? peer channel list
2021-11-11 17:50:00.527 CST [channelCmd] InitCmdFactory -> INFO 001 Endorser and orderer connections initialized
Channels peers has joined:
channel1
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末俱两,一起剝皮案震驚了整個(gè)濱河市酬核,隨后出現(xiàn)的幾起案子妒蔚,更是在濱河造成了極大的恐慌剃执,老刑警劉巖难衰,帶你破解...
    沈念sama閱讀 212,718評(píng)論 6 492
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件好啰,死亡現(xiàn)場(chǎng)離奇詭異浪秘,居然都是意外死亡滞项,警方通過(guò)查閱死者的電腦和手機(jī)君丁,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,683評(píng)論 3 385
  • 文/潘曉璐 我一進(jìn)店門筹麸,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)活合,“玉大人,你說(shuō)我怎么就攤上這事物赶“字福” “怎么了?”我有些...
    開(kāi)封第一講書(shū)人閱讀 158,207評(píng)論 0 348
  • 文/不壞的土叔 我叫張陵酵紫,是天一觀的道長(zhǎng)告嘲。 經(jīng)常有香客問(wèn)我错维,道長(zhǎng),這世上最難降的妖魔是什么橄唬? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 56,755評(píng)論 1 284
  • 正文 為了忘掉前任赋焕,我火速辦了婚禮,結(jié)果婚禮上仰楚,老公的妹妹穿的比我還像新娘隆判。我一直安慰自己,他們只是感情好僧界,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,862評(píng)論 6 386
  • 文/花漫 我一把揭開(kāi)白布蜜氨。 她就那樣靜靜地躺著,像睡著了一般捎泻。 火紅的嫁衣襯著肌膚如雪飒炎。 梳的紋絲不亂的頭發(fā)上,一...
    開(kāi)封第一講書(shū)人閱讀 50,050評(píng)論 1 291
  • 那天笆豁,我揣著相機(jī)與錄音郎汪,去河邊找鬼。 笑死闯狱,一個(gè)胖子當(dāng)著我的面吹牛煞赢,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播哄孤,決...
    沈念sama閱讀 39,136評(píng)論 3 410
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼照筑,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了瘦陈?” 一聲冷哼從身側(cè)響起凝危,我...
    開(kāi)封第一講書(shū)人閱讀 37,882評(píng)論 0 268
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎晨逝,沒(méi)想到半個(gè)月后蛾默,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 44,330評(píng)論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡捉貌,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,651評(píng)論 2 327
  • 正文 我和宋清朗相戀三年支鸡,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片趁窃。...
    茶點(diǎn)故事閱讀 38,789評(píng)論 1 341
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡牧挣,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出醒陆,到底是詐尸還是另有隱情瀑构,我是刑警寧澤,帶...
    沈念sama閱讀 34,477評(píng)論 4 333
  • 正文 年R本政府宣布统求,位于F島的核電站检碗,受9級(jí)特大地震影響据块,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜折剃,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 40,135評(píng)論 3 317
  • 文/蒙蒙 一另假、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧怕犁,春花似錦边篮、人聲如沸。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 30,864評(píng)論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至阵子,卻和暖如春思杯,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背挠进。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 32,099評(píng)論 1 267
  • 我被黑心中介騙來(lái)泰國(guó)打工色乾, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人领突。 一個(gè)月前我還...
    沈念sama閱讀 46,598評(píng)論 2 362
  • 正文 我出身青樓暖璧,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親君旦。 傳聞我的和親對(duì)象是個(gè)殘疾皇子澎办,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,697評(píng)論 2 351

推薦閱讀更多精彩內(nèi)容