fabric2.2 测试网络部署及操作流程(Ubuntu 18+)

枫叶海棠 -
fabric2.2 测试网络部署及操作流程(Ubuntu 18+)
警告

在执行测试项目时,多次使用并修改此文件,部分地方没有及时更新.如果问题请联系 487008159 更正.

必看项目: fabric-samples

工作目录 : ~/go/src/github.com/hyperledger/fabric-samples/test-network

辅助脚本身份环境变量组织 1env-org1.sh
#!/bin/bash
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
组织 2env-org2.sh
#!/bin/bash
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
排序组织
#!/bin/bash
export CORE_PEER_TLS_ENABLED=true
export CORE_PEER_LOCALMSPID="OrdererMSP"
export CORE_PEER_MSPCONFIGPATH=${PWD}/organizations/ordererOrganizations/example.com/users/Admin@example.com/msp
修改脚本进入测试网络
cd $GOPATH/src/github.com/hyperledger/fabric-samples/test-network
修改测试脚本
vim ./network.sh 

大概在51行,注释掉二进制文件检查的那一项

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
项目环境变量
export COMPOSE_PROJECT_NAME=fabric
export IMAGETAG=2.2.0
清理脚本
#########################################################################
# File Name: clear.sh
# Author: zll
# mail: zhnlion@126.com
# Created Time: 二 12/28 17:18:54 2021
#########################################################################
echo "停止所有容器"

docker stop $(docker ps -aq)

echo "移除所有容器"
docker rm $(docker ps -aq)

echo "清理联盟数据"
./network.sh down

echo "移除 docker网络"
docker network prune -f

echo "清理卷"
docker volume prune -f

echo "设置环境变量"
export COMPOSE_PROJECT_NAME=fabric
export IMAGETAG=2.2.0

echo "启动联盟并创建通道"
./network.sh up createChannel
环境下载 fabric-sample 源码
mkdir -p $GOPATH/src/github.com/hyperledger/
cd   $GOPATH/src/github.com/hyperledger/
git clone https://gitee.com/Alikx/fabric-samples.git
进入项目
cd $GOPATH/src/github.com/hyperledger/fabric-samples/test-network
切换版本
git checkout v2.2.0
移动配置文件,先进gopath的 bin目录下,之前解二进制文件连同配置文件都在这里.
mv config ~/go/src/github.com/hyperledger/fabric-samples
fabric二进制及配置文件

https://github.com/hyperledge...

下载
wget https://github.91chi.fun//https://github.com//hyperledger/fabric/releases/download/v2.2.0/hyperledger-fabric-linux-amd64-2.2.0.tar.gz
查看压缩包中的文件
root@k8s_node01:~# tar --list -f  hyperledger-fabric-linux-amd64-2.2.0.tar.gz
bin/
bin/peer
bin/orderer
bin/discover
bin/configtxgen
bin/cryptogen
bin/idemixgen
bin/configtxlator
config/
config/configtx.yaml
config/core.yaml
config/orderer.yaml
解压
mkdir hyperledger-fabric-linux-amd64-2.2.0
tar -zxvf hyperledger-fabric-linux-amd64-2.2.0.tar.gz -C  hyperledger-fabric-linux-amd64-2.2.0
拷贝
mv config $GOPATH/src/github.com/hyperledger/fabric-samples/
日志监控开启监控

此步骤不是必需的,但对链码进行故障诊断非常有用。要监控智能合同的日志,管理员可以使用logspout工具查看一组Docker容器的聚合输出。该工具将来自不同Docker容器的输出流收集到一个地方,以便于从单个窗口查看正在发生的事情。这可以帮助管理员在安装智能合同时调试问题,帮助开发人员在调用智能合同时调试问题。由于一些容器的创建纯粹是为了启动智能合同,并且只存在很短的时间,因此从您的网络收集所有日志是有帮助的。

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

然后,您可以通过运行以下命令启动Logspout:

./monitordocker.sh fabric_test

您应该会看到类似于以下内容的输出:

Starting monitoring on all containers on the network docker_test
f96a6fae3c8cadcb8f3b5ac0f4fb808b45d1d30cc26498451974bd6a1b16a4b7

您一开始不会看到任何日志,但当我们部署链码时,这种情况会发生变化。使这个终端窗口宽,字体小可能会有帮助。

如果找不到网络,就使用个下面命令查看下网络,实际上网络名字就是上面修改过的名字.

docker network ls
启动网络刷新环境变量
source init-env.sh
export CHANNEL=mychannel
export ORDERER_TLS_CA=${PWD}/organizations/ordererOrganizations/example.com/orderers/orderer.example.com/msp/tlscacerts/tlsca.example.com-cert.pem
方式一启动
./network.sh up createChannel
方式二启动
./network.sh up 
生成通道交易文件
configtxgen \
-profile TwoOrgsChannel \
-outputCreateChannelTx ./channel-artifacts/$CHANNEL.tx \
-channelID $CHANNEL \
-configPath configtx
创建通道区块
peer channel create \
-o localhost:7050  \
--ordererTLSHostnameOverride orderer.example.com \
-c $CHANNEL \
-f ./channel-artifacts/$CHANNEL.tx \
--outputBlock ./channel-artifacts/channel1.block \
--tls \
--cafile 
组织1 的peer加入通道设置环境变量
source env-org1.sh
加入通道

由于我们已经以Org1管理员的身份使用peer CLI,因此让我们将Org1的Peer加入到通道中。由于Org1提交了通道创建交易,因此我们的文件系统上已经有了通道创世块。使用以下命令将Org1的Peer加入通道。

peer channel join -b ./channel-artifacts/$CHANNEL.block

环境变量CORE_PEER_ADDRESS已设置为以peer0.org1.example.com为目标。命令执行成功后将生成peer0.org1.example.com加入通道的响应:

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加入通道设置环境变量
source env-org2.sh
列出当前peer 加入的通道
peer channel  list
从排序服务中获取通道区块数据
peer channel fetch 0 \
./channel-artifacts/channel_org2.block \
-o localhost:7050 \
--ordererTLSHostnameOverride orderer.example.com \
-c $CHANNEL \
--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
查询结果
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
安装链码打包链码进去go语言链码包
cd ../chaincode/fabcar/go
下载依赖
GO111MODULE=on 
go mod vendor
回到工作目录
cd ../../../test-network
管理员1和管理员2 (一个打包另一个直接拿来用就好了)打包链码
peer lifecycle chaincode package fabcar.tar.gz --path ../chaincode/fabcar/go/  --lang golang --label fabcar_1

执行完该命令会在当前目录下生成 链码包文件 fabcar.tar.gz .

安装链码在Org1 的peer 上安装链码切换身份为组织 1 的管理员
source env-org1.sh
安装链码
peer lifecycle chaincode install fabcar.tar.gz
查询已安装的链码
peer lifecycle chaincode queryinstalled
在Org2的 peer 上安装链码切换身份为组织 2 的管理员
source env-org2.sh
安装链码
peer lifecycle chaincode install fabcar.tar.gz
查询已安装的链码
peer lifecycle chaincode queryinstalled
设置包 ID
peer lifecycle chaincode queryinstalled
Installed chaincodes on peer:
Package ID: fabcar_1:a5a64c81bd0ff978378580a452d6ea21f8c39ebce3645c712edab3b795b8d722, Label: fabcar_1
export CC_PACKAGE_ID=fabcar_1:a5a64c81bd0ff978378580a452d6ea21f8c39ebce3645c712edab3b795b8d722
默认策略下组织 1 批准
source env-org1.sh
peer lifecycle chaincode approveformyorg \
-o localhost:7050 \
--ordererTLSHostnameOverride orderer.example.com \
--channelID $CHANNEL \
--name fabcar \
--version 1.0 \
--package-id $CC_PACKAGE_ID \
--sequence 1 \
--tls \
--cafile $ORDERER_TLS_CA
组织 2 批准
source env-org2.sh
peer lifecycle chaincode approveformyorg \
-o localhost:7050 \
--ordererTLSHostnameOverride orderer.example.com \
--channelID $CHANNEL \
--name fabcar \
--version 1.0 \
--package-id $CC_PACKAGE_ID \
--sequence 1 \
--tls \
--cafile $ORDERER_TLS_CA
检查批准情况
peer lifecycle chaincode checkcommitreadiness  \
--channelID $CHANNEL  \
--name fabcar  \
--version 1.0  \
--sequence 1  \
--tls  \
--cafile $ORDERER_TLS_CA \
--output json
日志
{
    "approvals": {
        "Org1MSP": true,
        "Org2MSP": true
    }
}
提交
peer lifecycle chaincode commit  \
-o localhost:7050  \
--ordererTLSHostnameOverride orderer.example.com  \
--channelID $CHANNEL  \
--name fabcar  \
--version 1.0  \
--sequence 1  \
--tls  \
--cafile $ORDERER_TLS_CA  \
--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
修改策略方式(默认策略执行后,此策略不需要执行)

注意:升级策略可执行此步骤。

组织 1 批准
source env-org1.sh
peer lifecycle chaincode approveformyorg \
-signature-policy "AND ('Org1MSP.peer','Org2MSP.peer')" \
-o localhost:7050 \
--ordererTLSHostnameOverride orderer.example.com \
--channelID $CHANNEL \
--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
组织 2 批准
source env-org2.sh
peer lifecycle chaincode approveformyorg \
--signature-policy "AND ('Org1MSP.peer','Org2MSP.peer')" \
-o localhost:7050 \
--ordererTLSHostnameOverride orderer.example.com \
--channelID $CHANNEL \
--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
检查批准情况
peer lifecycle chaincode checkcommitreadiness  \
--signature-policy "AND ('Org1MSP.peer','Org2MSP.peer')" \
--channelID $CHANNEL  \
--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
提交
peer lifecycle chaincode commit  \
--signature-policy "AND ('Org1MSP.peer','Org2MSP.peer')" \
-o localhost:7050  \
--ordererTLSHostnameOverride orderer.example.com  \
--channelID $CHANNEL  \
--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
查询已提交
peer lifecycle chaincode querycommitted  \
--channelID $CHANNEL  \
--name fabcar  \
--cafile $ORDERER_TLS_CA
调用链码
peer chaincode invoke -o localhost:7050 \
--ordererTLSHostnameOverride orderer.example.com \
--tls \
--cafile $ORDERER_TLS_CA \
-C $CHANNEL \
-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 $CHANNEL  \
-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"}}]
写数据
source env-org1.sh
peer chaincode invoke  \
--tls \
-o localhost:7050 \
--ordererTLSHostnameOverride orderer.example.com \
--cafile $ORDERER_TLS_CA \
-C $CHANNEL \
-n fabcar  \
-c '{"Args":["createCar","CAR12","China","changan","red","Binny"]}' \
--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
peer chaincode query  \
-C $CHANNEL \
-n fabcar  \
-c '{"Args":["queryCar","CAR12"]}'
执行到此处,就可以调试 SDK 了

https://gitee.com/xubinbin102...

升级链码更新背书策略

You can use the chaincode definition to update an endorsement policy without having to repackage or re-install the chaincode. Channel members can approve a chaincode definition with a new endorsement policy and commit it to the channel.

批准

您可以使用链码定义来更新背书策略,而无需重新打包或重新安装链码。渠道成员可以批准带有新的背书策略的链码定义,并将其提交给渠道。

peer lifecycle chaincode approveformyorg \
-o localhost:7050 \
--ordererTLSHostnameOverride orderer.example.com \
--channelID mychannel \
--name fabcar \
--version 2.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 \
--signature-policy "AND ('Org1MSP.peer','Org2MSP.peer')" 
检查批准情况

这里我认为有一个 bug,如果是新定义的是更新背书策略,那么检查的时候也要携带新的背书策略这个选项.

peer lifecycle chaincode checkcommitreadiness  \
--signature-policy "AND ('Org1MSP.peer','Org2MSP.peer')" \
--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
    }
}
提交
peer lifecycle chaincode commit  \
--signature-policy "AND ('Org1MSP.peer','Org2MSP.peer')" \
-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]
修改通道中 orderer 相关配置

基于现有的网络,修改 Batch 块的 max_message_count.

单独测试此过程的步骤(unnecessary)清理网络
docker stop $(docker ps -a)
docker rm $(docker ps -a)
重启网络并创建通道
export COMPOSE_PROJECT_NAME=fabric
export IMAGE_TAG=2.2.0
export ORDERER_CONTAINER=localhost:7050
export TLS_ROOT_CA=${PWD}/organizations/ordererOrganizations/example.com/orderers/orderer.example.com/msp/tlscacerts/tlsca.example.com-cert.pem
export CH_NAME=mychannel
./network.sh up createChannel
获取通道配置
# 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
peer channel fetch config \
configtx/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
解码通道配置
rm update 
mkdir update
configtxlator proto_decode --input configtx/config_block.pb --type common.Block --output update/config_block.json
提取更新配置部分
jq '.data.data[0].payload.data.config' update/config_block.json > update/config.json
查看原始值
jq '.channel_group.groups.Orderer.values.BatchSize.value.max_message_count' update/config.json
赋值并写入新文件
jq '.channel_group.groups.Orderer.values.BatchSize.value.max_message_count=13' update/config.json > update/config13.json
查看新值
jq '.channel_group.groups.Orderer.values.BatchSize.value.max_message_count' update/config13.json
编码更新文件
configtxlator proto_encode --input update/config13.json --type common.Config --output update/config13.pb
configtxlator proto_encode --input update/config.json --type common.Config --output update/config.pb
configtxlator compute_update --channel_id mychannel --original update/config.pb --updated update/config13.pb --output update/config13_update.pb
configtxlator proto_decode --input update/config13_update.pb --type common.ConfigUpdate --output update/config13_update.json
echo '{"payload":{"header":{"channel_header":{"channel_id":"'mychannel'", "type":2}},"data":{"config_update":'$(cat update/config13_update.json)'}}}' | jq . > update/config13_update_in_envelope.json
configtxlator proto_encode --input update/config13_update_in_envelope.json --output update/config13_update_in_envelope.pb --type common.Envelope 
编码原始文件
configtxlator proto_encode --input update/config.json --type common.Config --output update/config.pb
计算增量
configtxlator compute_update --channel_id mychannel --original update/config.pb --updated update/config13.pb --output update/config13_update.pb
解码增量
configtxlator proto_decode --input update/config13_update.pb --type common.ConfigUpdate --output update/config13_update.json
封装增量
echo '{"payload":{"header":{"channel_header":{"channel_id":"'mychannel'", "type":2}},"data":{"config_update":'$(cat update/config13_update.json)'}}}' | jq . > update/config13_update_in_envelope.json
编码完成更新文件
configtxlator proto_encode --input update/config13_update_in_envelope.json --output update/config13_update_in_envelope.pb --type common.Envelope 
切换身份(关键)

因为更新的 orderer的部分,所以以 orderer 身份更新

切换身份
export CORE_PEER_TLS_ENABLED=true
export CORE_PEER_LOCALMSPID="OrdererMSP" 
export CORE_PEER_MSPCONFIGPATH=${PWD}/organizations/ordererOrganizations/example.com/users/Admin@example.com/msp
签名
peer channel signconfigtx \
-f update/config13_update_in_envelope.pb  \
-o localhost:7050 \
--tls \
--cafile ${PWD}/organizations/ordererOrganizations/example.com/orderers/orderer.example.com/msp/tlscacerts/tlsca.example.com-cert.pem 
提交
peer channel update -f  update/config13_update_in_envelope.pb -c mychannel -o localhost:7050 --tls --cafile ${PWD}/organizations/ordererOrganizations/example.com/orderers/orderer.example.com/msp/tlscacerts/tlsca.example.com-cert.pem 
2021-12-23 14:46:38.359 CST [channelCmd] InitCmdFactory -> INFO 001 Endorser and orderer connections initialized
2021-12-23 14:46:38.445 CST [channelCmd] update -> INFO 002 Successfully submitted channel update
检查拉取最新区块环境变量可以不改(非必须)
# 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

拉取

peer channel fetch config \
configtx/config_block1.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
解码通道配置
configtxlator proto_decode --input configtx/config_block1.pb --type common.Block --output update/config_block1.json
提取更新配置部分
jq '.data.data[0].payload.data.config' update/config_block1.json > update/config1.json
查看原始值
jq '.channel_group.groups.Orderer.values.BatchSize.value.max_message_count' update/config1.json
清理(如果需要)

清理
停止日志监控,停止网络,移除网络,移除卷

docker stop logspout && docker rm logspout && docker stop $(docker ps -aq) && docker rm $(docker ps -aq) && docker network prune && docker volume prune

移除链码相关镜像

docker rmi $(docker ps | grep "dev-peer" | awk '{print $3}')
查看运行中的容器
docker ps --format "table {{.ID}}\t{{.Names}}\t{{.IMAGE}}"

移除

docker rm $(docker ps | grep "hyperledger" | awk '{print $1}')
向组织中新增peer工作目录 :~/go/src/github.com/hyperledger/fabric-samples/test-network组织:org1

查看当前组织中pee的个数

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 证书文件编辑证书配置文件

启动网络的步骤中,查看输出日志

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

修改配置文件 ./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
执行网络拓展命令
cryptogen extend --config=./organizations/cryptogen/crypto-config-org1.yaml --input=organizations
再次查看目录结构
ls organizations/peerOrganizations/org1.example.com/peers
peer0.org1.example.com  peer1.org1.example.com
启动新peer节点查看当前节点
docker ps --format "table {{.ID}} \t {{.Names}}" | grep 'peer'
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
启动节点
docker-compose -f docker-compose.yaml up -d peer1.org1.example.com
查看节点信息
docker ps --format "table {{.ID}}\t{{.Names}}" --filter name=org1
3cce207d4570   peer1.org1.example.com
5513a783cb6a   peer0.org1.example.com
将新节点加入通道配置环境变量
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
批准链码
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
调用链码
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"}}]
向网络中新增组织为 Org3生成证书文件

在另一个终端中,addOrg3test-network.

cd addOrg3

首先,我们将为 Org3 对等方以及应用程序和管理员用户创建证书和密钥。因为我们正在更新一个示例通道,所以我们将使用 cryptogen 工具而不是使用证书颁发机构。以下命令使用 cryptogen 读取org3-crypto.yaml文件并在新org3.example.com文件夹中生成 Org3 加密材料:

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

您可以在目录中找到生成的 Org3 加密材料以及 Org1 和 Org2 的证书和密钥:test-network/organizations/peerOrganizations.

一旦我们创建了 Org3 加密材料,我们就可以使用 configtxgen 工具打印出 Org3 组织定义。

我们将通过告诉工具在当前目录中查找configtx.yaml 它需要摄取的文件来开始命令。

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

上面的命令创建了一个 JSON 文件 org3.json 并将其写入下面文件夹。

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

组织定义包含 Org3 的策略定义、Org3 的 NodeOU 定义以及两个以 base64 格式编码的重要证书:

CA 根证书,用于建立组织间的信任根一个 TLS 根证书,由 gossip 协议用于标识 Org3 以进行块传播和服务发现

我们将通过将此组织定义附加到通道配置来将 Org3 添加到通道中。

调出 Org3 组件

就是 启动 组织 3 的 peer 节点

创建 Org3 证书材料后,我们现在可以启动 Org3 对等体。从addOrg3目录中,发出以下命令:

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

如果命令成功,您将看到 Org3 peer 的创建:

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

此 Docker Compose 文件已配置为跨我们的初始网络桥接,以便 Org3 对等节点与测试网络的现有对等节点和排序节点进行解析。

获取配置

让我们去获取频道的最新配置块 – channel1

我们必须拉取最新版本的配置的原因是因为通道配置元素是版本化的。

出于多种原因,版本控制很重要。它可以防止重复或重放配置更改(例如,使用旧 CRL 恢复到通道配置将代表安全风险)。它还有助于确保并发性(如果您想从频道中删除组织,例如,在添加新组织后,版本控制将有助于防止您删除两个组织,而不仅仅是要删除的组织)。

导航回test-network目录。因为 Org3 还不是频道的成员,我们需要以另一个组织的管理员身份操作来获取频道配置。因为 Org1 是频道的成员,所以 Org1 管理员有权从排序服务中获取频道配置。发出以下命令以作为 Org1 管理员进行操作。

# 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

我们现在可以发出命令来获取最新的配置块:

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

此命令将二进制 protobuf 通道配置块保存到 config_block.pb. 请注意,名称和文件扩展名的选择是任意的。但是,建议遵循标识所表示的对象类型及其编码(protobuf 或 JSON)的约定。

peer channel fetch发出命令后,日志中会显示以下输出:

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实际上是块 2,而不是创世块。

默认情况下,该 命令返回目标通道的最新配置块,在这种情况下是第三个块。

这是因为测试网络脚本为我们的两个组织定义了锚点,并且在两个单独的通道更新事务中。因此,我们有以下配置序列:

block 0: genesis blockblock 1: Org1 anchor peer updateblock 2: Org2 anchor peer update

通道配置文件夹下新增块信息文件

├── channel-artifacts
│   ├── channel1.block
│   ├── channel1.tx
│   └── config_block.pb # 新增
将配置转换为 JSON 并对其进行修剪

通道配置块存储在channel-artifacts文件夹中,以使更新过程与其他工件分开。进入 channel-artifacts 文件夹以完成以下步骤:

cd channel-artifacts
使用该configtxlator工具将这个通道配置块解码为 JSON 格式(可以被人类读取和修改)
configtxlator proto_decode \
--input config_block.pb \
--type common.Block \
--output config_block.json
去除所有与我们想要进行的更改无关的标题、元数据、创建者签名等

带有数组的情况下,加引号,这个命令给我们留下了一个精简的 JSON 对象 config.json 它将作为我们配置更新的基线。

jq '.data.data[0].payload.data.config' config_block.json > config.json
添加 Org3 加密材jq 语法参考

jq 官方文档

选项解释备注-sread (slurp) all inputs into an array; apply filter to it使用-s 选项,jq 会将所有的 JSON 输入放入一个数组中并在这个数组上使用 filter。"-s"选项不但影响到 filter 的写法。如果在 filter 中需要对数据进行选择和映射,其还会影响最终结果。
jq -s '.[0] * .[1]' 输入流1 输入流2 > test.json 
.[0]:由第1个输入流产生的数组数据.[1]:由第2个输入流产生的数组数据*:参考官方文档
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添加到通道的应用程序组字段,并将输出命名为 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
增量计算,得到增

现在我们有两个感兴趣的 JSON 文件 config.jsonmodified_config.json. 初始文件仅包含 Org1 和 Org2 材料,而修改后的文件包含所有三个 Org。

此时,只需重新编码这两个 JSON 文件并计算增量即可。

首先,转换config.json回一个名为的protobuf config.pb
configtxlator proto_encode \
--input config.json \
--type common.Config \
--output config.pb
接下来,编码modified_config.jsonmodified_config.pb
configtxlator proto_encode \
--input modified_config.json \
--type common.Config \
--output modified_config.pb
在用于configtxlator计算这两个配置 protobufs 之间的增量。此命令将输出一个名为的新 protobuf 二进制文件org3_update.pb
configtxlator compute_update \
--channel_id channel1 \
--original config.pb \
--updated modified_config.pb \
--output org3_update.pb

这个新的 proto org3_update.pb包含 Org3 定义和指向 Org1 和 Org2 材料的高级指针。

封装更新信息

在提交频道更新之前,我们需要执行一些最后的步骤。

首先,让我们将此对象解码为可编辑的 JSON 格式并调用它org3_update.json
configtxlator proto_decode \
--input org3_update.pb \
--type common.ConfigUpdate \
--output org3_update.json

现在,我们有一个解码后的更新文件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最后一次利用该工具并将其转换为 Fabric 所需的完全成熟的 protobuf 格式。我们将命名我们的最终更新对象org3_update_in_envelope.pb:

configtxlator proto_encode \
--input org3_update_in_envelope.json \
--type common.Envelope \
--output org3_update_in_envelope.pb
签署并提交配置更签署

现在有一个 protobuf 二进制文件 org3_update_in_envelope.pb. 但是,在将配置写入分类帐之前,我们需要必需的管理员用户的签名。

我们频道应用程序组的修改策略 (mod_policy) 设置为默认值“MAJORITY”,这意味着我们需要大多数现有组织管理员对其进行签名。

因为我们只有两个组织——Org1 和 Org2——而且两个组织中的大多数是两个,==所以我们需要他们都签名==。

如果没有这两个签名,排序服务将拒绝未能满足策略的交易。

首先,让我们将此更新协议签名为 Org1。导航回test-network 目录:

请记住,我们导出了必要的环境变量以作为 Org1 管理员进行操作。因此,以下命令会将更新签名为 Org1。peer channel signconfigtx

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

最后一步是切换容器的身份以反映 Org2 Admin 用户。我们通过导出特定于 Org2 MSP 的四个环境变量来做到这一点。

设置 Org2 环境变量:

# 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
更新

最后,我们将发出peer channel update命令。Org2 Admin 的签名将附加到此调用中,因此无需再次手动签署 protobuf。(更新角色会自动签署并且更新通道配置信息)

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

成功的通道更新调用会向通道上的所有对等方返回一个新块:块 3

如果您还记得,块 0-2 是初始通道配置。Block 3 作为最新的通道配置,现在在通道上定义了 Org3。

您可以peer0.org1.example.com通过发出以下命令来检查日志:

docker logs -f peer0.org1.example.com
将 Org3的节点加入频道

此时,通道配置已更新为包括我们的新组织 Org3,这意味着它的对等节点现在可以加入channel1。

导出以下环境变量以作为 Org3 管理员进行操作:

# 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

作为通道更新成功的结果,排序服务将验证 Org3 是否可以拉取创世块并加入通道。如果 Org3 未成功附加到通道配置,则排序服务将拒绝此请求。

使用命令来检索这个块: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

请注意,我们正在传递 0以指示我们想要通道分类帐上的第一个块;即创世区块。

如果我们简单地传递命令 peer channel fetch config,那么我们将收到块 3——定义了 Org3 的更新配置。但是,我们不能从下游块开始我们的账本——我们必须从块 0 开始。

如果成功,该命令会将创世块返回名为channel1.block. 我们现在可以使用此块channel1.blockpeer加入通道。

发出命令peer channel join并传入创世块以将 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
查询结果

在 Org3的环境下查看该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
升级网络升级orderer节点

升级每个orderer时,都需要执行以下操作。

配置orderer容器中的环境变量
vim upgrade.orderer.sh

方便起见,orderer容器运行时需要的环境变量可以记录在文件中,具体内容如下:

FABRIC_LOGGING_SPEC=INFO
FABRIC_CFG_PATH=/etc/hyperledger/fabric
ORDERER_GENERAL_LISTENADDRESS=0.0.0.0
ORDERER_GENERAL_GENESISMETHOD=file
# 创世区块
ORDERER_GENERAL_GENESISFILE=/var/hyperledger/orderer/orderer.genesis.block
ORDERER_GENERAL_LOCALMSPID=OrdererMSP
ORDERER_GENERAL_LOCALMSPDIR=/var/hyperledger/orderer/msp
# enabled TLS
ORDERER_GENERAL_TLS_ENABLED=true
ORDERER_GENERAL_TLS_PRIVATEKEY=/var/hyperledger/orderer/tls/server.key
ORDERER_GENERAL_TLS_CERTIFICATE=/var/hyperledger/orderer/tls/server.crt
ORDERER_GENERAL_TLS_ROOTCAS=[/var/hyperledger/orderer/tls/ca.crt]
ORDERER_GENERAL_CLUSTER_CLIENTCERTIFICATE=/var/hyperledger/orderer/tls/server.crt
ORDERER_GENERAL_CLUSTER_CLIENTPRIVATEKEY=/var/hyperledger/orderer/tls/server.key
ORDERER_GENERAL_CLUSTER_ROOTCAS=[/var/hyperledger/orderer/tls/ca.crt]
设置升级时的环境变量

在升级排序节点前导入以下环境变量:

ORDERER_CONTAINER:排序节点的容器名称。注意,每个节点升级时你都样设置一遍。LEDGERS_BACKUP:存放备份数据的路径。就如下面的示例中,每个节点都有它自己的子目录来存放它的账本。目录如果不存在的话,你需要手动创建。IMAGE_TAG:你期望升级到的Fabric版本。

示例如下:

export ORDERER_CONTAINER=orderer.example.com
export LEDGERS_BACKUP=backup
export IMAGE_TAG=2.2.3
文件准备备份位置
mkdir -p $LEDGERS_BACKUP/$ORDERER_CONTAINER
创世块,msp,tls
cp ../system-genesis-block/genesis.block backup/orderer.genesis.block
cp -r ../organizations/ordererOrganizations/example.com/orderers/orderer.example.com/msp backup
cp -r ../organizations/ordererOrganizations/example.com/orderers/orderer.example.com/tls backup
停止容器
docker stop $ORDERER_CONTAINER
备份账本
docker cp $ORDERER_CONTAINER:/var/hyperledger/production/orderer $LEDGERS_BACKUP/$ORDERER_CONTAINER 
删除容器
docker rm -f $ORDERER_CONTAINER
升级容器
docker run -d \
-v /root/fabric-samples/test-network/backup/$ORDERER_CONTAINER/:/var/hyperledger/production/orderer/ \
-v /root/fabric-samples/test-network/backup:/var/hyperledger/orderer \
--env-file ./backup/env-update-container-orderer.yaml \
--name $ORDERER_CONTAINER \
--net fabric_test \
hyperledger/fabric-orderer:$IMAGE_TAG orderer
docker run -d \
-v /Users/binny/go/src/github.com/hyperledger/fabric-samples/test-network/upgrade/backup/$ORDERER_CONTAINER/:/var/hyperledger/production/orderer/ \
-v /Users/binny/go/src/github.com/hyperledger/fabric-samples/test-network/upgrade/backup/:/var/hyperledger/orderer/ \
--env-file ./upgrade.orderer.sh \
--name $ORDERER_CONTAINER \
hyperledger/fabric-orderer:$IMAGE_TAG orderer
升级peer节点

以peer0org1节点为例,以下操作每个peer节点都需要执行。

配置peer运行时的环境变量

方便起见,peer容器运行时需要的环境变量可以记录在文件中,具体内容如下:

CORE_PEER_LOCALMSPID=Org1MSP
CORE_PEER_GOSSIP_USELEADERELECTION=true
CORE_PEER_ID=peer0.org1.example.com
CORE_PEER_ADDRESS=peer0.org1.example.com:7051
FABRIC_CFG_PATH=/etc/hyperledger/fabric
CORE_VM_DOCKER_HOSTCONFIG_NETWORKMODE=net_byfn
CORE_PEER_GOSSIP_EXTERNALENDPOINT=peer0.org1.example.com:7051
CORE_PEER_PROFILE_ENABLED=true
CORE_VM_ENDPOINT=unix:///host/var/run/docker.sock
CORE_PEER_LISTENADDRESS=0.0.0.0:7051
CORE_PEER_GOSSIP_ORGLEADER=false
CORE_PEER_TLS_CERT_FILE=/etc/hyperledger/fabric/tls/server.crt
CORE_PEER_CHAINCODELISTENADDRESS=0.0.0.0:7052
CORE_PEER_TLS_KEY_FILE=/etc/hyperledger/fabric/tls/server.key
CORE_PEER_TLS_ROOTCERT_FILE=/etc/hyperledger/fabric/tls/ca.crt
CORE_PEER_GOSSIP_BOOTSTRAP=peer1.org1.example.com:8051
CORE_PEER_TLS_ENABLED=true
FABRIC_LOGGING_SPEC=INFO
CORE_PEER_CHAINCODEADDRESS=peer0.org1.example.com:7052
设置升级时的环境变量

在升级peer节点前导入以下环境变量:

PEER_CONTAINER:peer节点的容器名称。注意,每个节点升级时你都样设置一遍。LEDGERS_BACKUP:存放备份数据的路径。就如下面的示例中,每个节点都有它自己的子目录来存放它的账本。目录如果不存在的话,你需要手动创建。IMAGE_TAG:你期望升级到的Fabric版本,例如v2.0。

示例如下:

export PEER_CONTAINER=peer0.org1.example.com
export LEDGERS_BACKUP=backup
export IMAGE_TAG=2.2.3
停止容器
docker stop $PEER_CONTAINER
备份账本和MSPs
docker cp $PEER_CONTAINER:/var/hyperledger/production $LEDGERS_BACKUP/$PEER_CONTAINER
删除CC容器
CC_CONTAINERS=$(docker ps | grep dev-$PEER_CONTAINER | awk '{print $1}')
if [ -n "$CC_CONTAINERS" ] ; then docker rm -f $CC_CONTAINERS ; fi
删除peer容器
docker rm  $PEER_CONTAINER
升级peer节点
docker run -d \
-e FABRIC_CFG_PATH=/etc/hyperledger/fabric \
-v /Users/binny/go/src/github.com/hyperledger/fabric-samples/test-network/upgrade/$LEDGERS_BACKUP/$PEER_CONTAINER/:/var/hyperledger/production/ \
-v /Users/binny/go/src/github.com/hyperledger/fabric-samples/test-network/organizations/peerOrganizations/org1.example.com/peers/peer0.org1.example.com/:/etc/hyperledger/fabric/ \
-v /Users/binny/go/src/github.com/hyperledger/fabric-samples/config/core.yaml:/etc/hyperledger/fabric/core.yaml \
--env-file ./upgrade.org1.peer0.sh \
--name $PEER_CONTAINER \
hyperledger/fabric-peer:$IMAGE_TAG peer node start
升级peer节点数据库
docker run --rm \
-v $LEDGERS_BACKUP/$PEER_CONTAINER:/var/hyperledger/production/ \
-v /var/run/:/host/var/run/ \
-v $FABRIC_SAMPLES/first-network/crypto-config/peerOrganizations/org1.example.com/peers/peer0.org1.example.com/msp:/etc/hyperledger/fabric/msp \
-v $FABRIC_SAMPLES/first-network/crypto-config/peerOrganizations/org1.example.com/peers/peer0.org1.example.com/tls:/etc/hyperledger/fabric/tls \
-p 7051:7051 \
--env-file env_peer.list \
--net net_byfn \
--name $PEER_CONTAINER  \
hyperledger/fabric-peer:$IMAGE_TAG peer node upgrade-dbs
旧版本的链码进入源码
cd $GOPATH/src/github.com/hyperledger/fabric-samples/chaincode/sacc
下载依赖
GO111MODULE=on 
go mod vendor
cd ../../test-network/
打包
peer lifecycle chaincode package sacc.tar.gz --path ../chaincode/sacc/  --lang golang --label sacc_1
更新环境变量作为组织1管理员
source org1-env.sh
作为组织2管理员
source org2-env.sh
安装
peer lifecycle chaincode install sacc.tar.gz
查询
peer lifecycle chaincode queryinstalled
设置包ID
export CC_PACKAGE_ID=sacc_1:b33357c4012471d8bd96ba48fd2a12ada5fedfbfd6d623590295778500a0368d
批准
peer lifecycle chaincode approveformyorg \
--init-required \
-o localhost:7050 \
--ordererTLSHostnameOverride orderer.example.com \
--channelID mychannel \
--name sacc \
--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
检查批准情况
peer lifecycle chaincode checkcommitreadiness  \
--init-required \
--channelID mychannel  \
--name sacc  \
--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
提交
peer lifecycle chaincode commit  \
--init-required \
-o localhost:7050  \
--ordererTLSHostnameOverride orderer.example.com  \
--channelID mychannel  \
--name sacc  \
--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
查询
peer lifecycle chaincode querycommitted --channelID mychannel --name sacc
初始化
peer chaincode invoke -o localhost:7050 \
--isInit \
--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 sacc \
--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 '{"Args":["name","binny"]}'
调用
peer chaincode query -C mychannel -n sacc -c '{"Args":["get","name"]}'
清理
docker stop logspout && docker rm logspout &&
docker rm -f $(docker ps | grep "hyperledger" | awk '{print $1}')
移除链码相关镜像
docker rmi $(docker images | grep "dev-peer" | awk '{print $3}')
移除 fabric相关镜像
docker rmi $(docker images | grep "hyperledger" | awk '{print $3}')
docker network prune -f && docker volume prune -f
特别申明:本文内容来源网络,版权归原作者所有,如有侵权请立即与我们联系(cy198701067573@163.com),我们将及时处理。

Tags 标签

fabriclinux容器node.js

扩展阅读

加个好友,技术交流

1628738909466805.jpg