美文网首页
docker 部署 hyperleger fabric v2.2

docker 部署 hyperleger fabric v2.2

作者: ag4kd | 来源:发表于2021-11-02 18:12 被阅读0次

    [toc]

    环境

    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
    

    配置环境变量

    在文件最后添加以下内容

    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协议,允许apt从HTTPS安装软件包

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

    安装GPG证书

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

    写入软件源信息

    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
    

    将当前用户添加到Docker用户组

    创建docker用户组
    sudo groupadd docker
    
    将当前用户添加到docker用户组
    sudo usermod -aG docker $USER
    

    配置镜像加速器

    针对Docker客户端版本大于 1.10.0 的用户

    您可以通过修改daemon配置文件/etc/docker/daemon.json来使用加速器

    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
    
    • 执行docker info,如果结果中含有如下内容则说明镜像配置成功
    ...
     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
    

    -下载完后要设置权限

    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
    

    下载二进制文件(已经准备好)

    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
    
    • 进入项目
    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
    

    启动网络

    • 进入测试网络
    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 IMAGE_TAG=2.2
    ./network.sh up createChannel
    

    启动日志

    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}}"
    

    输出一下内容,包含三个节点:

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

    清理网络

    • 如果使用了日志监控
    docker stop logspout && docker rm logspout && ./network.sh down
    
    • 没有使用日监控
    ./network.sh down
    

    日志监控

    此步骤不是必需的,但对链码进行故障诊断非常有用。要监控智能合同的日志,管理员可以使用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
    

    清理

    使用完链码后,您也可以使用以下命令删除Logspout工具。

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

    然后,您可以通过从测试网络目录发出以下命令来关闭test-network

    ./network.sh down
    

    安装链码

    打包链码

    • 进去go语言链码包
    cd fabric-samples/chaincode/fabcar/go
    
    • 下载依赖
    GO111MODULE=on 
    go mod vendor
    
    • 回到工作目录
    cd ../../../test-network
    
    • 设置管理员1 的环境的变量
    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 (一个打包另一个直接拿来用就好了)打包链码
    peer lifecycle chaincode package fabcar.tar.gz --path ../chaincode/fabcar/go/  --lang golang --label fabcar_1
    

    执行完该命令会在当前目录下生成 链码包文件 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 上安装链码

    设置以下环境变量作为Org2管理员操作,并瞄准Org2对等机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
    

    发出以下命令来安装链码:

    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
    

    批准链码

    • 设置环境变量
    export CC_PACKAGE_ID=fabcar_1:762e0fe3dbeee0f7b08fb6200adeb4a3a20f649a00f168c0b3c2257e53b6e506
    
    • 批准
    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
    
    • 设置环境变量为组织以的管理员
    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
    
    • 批准
    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
    

    提交链码

    • 检查批准情况
    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]
    

    调用链码

    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"}}]
    

    升级链码

    创建通道

    生成通道交易文件

    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
    

    创建通道区块

    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加入通道

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

    peer channel join -b ./channel-artifacts/channel1.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加入通道

    • 设置环境变量
    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 加入的通道
    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
    
    • 从排序服务中获取通道区块数据
    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
    
    • 查询结果
    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

    查看当前组织中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}}"
    
    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 block
    • block 1: Org1 anchor peer update
    • block 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 官方文档

    选项 解释 备注
    -s read (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
    

    相关文章

      网友评论

          本文标题:docker 部署 hyperleger fabric v2.2

          本文链接:https://www.haomeiwen.com/subject/elqpihtx.html