Skip to content

Hyperledger Fabric v2.4联盟链+浏览器搭建

搭建Hyperledger Fabric联盟链

创建文件夹/root/fabric

bash
mkdir -p /root/fabric && cd /root/fabric

本实验所有操作均在文件夹/root/fabric下执行。

检查系统环境

确保系统中安装有Docker、docker-compose和vim。

检查docker是否已安装:

bash
docker --version

检查docker-compose是否已安装:

bash
docker-compose --version

拉取镜像

本实验需要如下3个镜像:

  • hyperledger/fabric-tools:包含了 Fabric 所有的二进制程序并且设置 PATH 变量,可以直接通过 Docker 执行相关命令。
  • hyperledger/fabric-peer:peer 节点镜像,安装了 peer 相关文件。
  • hyperledger/fabric-orderer:orderer 节点镜像,安装了 orderer 相关文件。

执行如下命令检查镜像是否已经拉取:

bash
docker images | grep hyperledger

生成密钥文件

创建crypto-config.yaml文件:

bash
vim crypto-config.yaml

输入:进入命令模式,输入命令set paste进入粘贴模式,将如下内容粘贴至文件中:

yaml
OrdererOrgs:
  - Name: Orderer
    Domin: flxdu.cn
    Specs:
      - Hostname: orderer

PeerOrgs:
  - Name: Org1
    Domain: org1.flxdu.cn
    EnableNodeOUs: true
    Template:
      Count: 2
    Users:
      Count: 1

  - Name: Org2
    Domain: org2.flxdu.cn
    EnableNodeOUs: true
    Template:
      Count: 2
    Users:
      Count: 1

注意:vim的粘贴模式有可能会丢失粘贴内容开头的几个字符,请注意检查粘贴完整。

按下ESC退出粘贴模式,随后输入:进入命令模式,输入wq保存并退出。

使用cryptogen generate生成密钥文件:

bash
docker run --privileged --rm -v /root/fabric:/data hyperledger/fabric-tools:2.4 cryptogen generate --config=/data/crypto-config.yaml --output=/data/crypto-config

程序结束后可以看到已经多了一个名为 crypto-config 的文件夹。

配置系统链创世块

创建 configtx.yaml 文件,粘贴如下内容:

yaml
Organizations:
  - &OrdererOrg
    Name: OrdererOrg
    ID: OrdererMSP
    MSPDir: crypto-config/ordererOrganizations/msp
    Policies:
      Readers:
        Type: Signature
        Rule: "OR('OrdererMSP.member')"
      Writers:
        Type: Signature
        Rule: "OR('OrdererMSP.member')"
      Admins:
        Type: Signature
        Rule: "OR('OrdererMSP.admin')"

  - &Org1
    Name: Org1MSP
    ID: Org1MSP
    MSPDir: crypto-config/peerOrganizations/org1.flxdu.cn/msp
    AnchorPeers:
      - Host: peer0.org1.flxdu.cn
        Port: 7051
    Policies:
      Readers:
        Type: Signature
        Rule: "OR('Org1MSP.admin', 'Org1MSP.peer', 'Org1MSP.client')"
      Writers:
        Type: Signature
        Rule: "OR('Org1MSP.admin', 'Org1MSP.client')"
      Admins:
        Type: Signature
        Rule: "OR('Org1MSP.admin')"
      Endorsement:
        Type: Signature
        Rule: "OR('Org1MSP.peer')"

  - &Org2
    Name: Org2MSP
    ID: Org2MSP
    MSPDir: crypto-config/peerOrganizations/org2.flxdu.cn/msp
    AnchorPeers:
      - Host: peer0.org2.flxdu.cn
        Port: 7051
    Policies:
      Readers:
        Type: Signature
        Rule: "OR('Org2MSP.admin', 'Org2MSP.peer', 'Org2MSP.client')"
      Writers:
        Type: Signature
        Rule: "OR('Org2MSP.admin', 'Org2MSP.client')"
      Admins:
        Type: Signature
        Rule: "OR('Org2MSP.admin')"
      Endorsement:
        Type: Signature
        Rule: "OR('Org2MSP.peer')"
        
Capabilities:
  Channel: &ChannelCapabilities
    V2_0: true
  Orderer: &OrdererCapabilities
    V2_0: true
  Application: &ApplicationCapabilities
    V2_0: true

Application: &ApplicationDefaults
  Organizations:
  Policies:
    Readers:
      Type: ImplicitMeta
      Rule: "ANY Readers"
    Writers:
      Type: ImplicitMeta
      Rule: "ANY Writers"
    Admins:
      Type: ImplicitMeta
      Rule: "MAJORITY Admins"
    LifecycleEndorsement:
      Type: ImplicitMeta
      Rule: "MAJORITY Endorsement"
    Endorsement:
      Type: ImplicitMeta
      Rule: "MAJORITY Endorsement"
  Capabilities:
    <<: *ApplicationCapabilities

Channel: &ChannelDefaults
  Policies:
    Readers:
      Type: ImplicitMeta
      Rule: "ANY Readers"
    Writers:
      Type: ImplicitMeta
      Rule: "ANY Writers"
    Admins:
      Type: ImplicitMeta
      Rule: "MAJORITY Admins"
  Capabilities:
    <<: *ChannelCapabilities

Orderer: &OrdererDefaults
  OrdererType: solo
  Addresses:
    - orderer.flxdu.cn:7050
  BatchTimeout: 2s
  BatchSize:
    MaxMessageCount: 10
    AbsoluteMaxBytes: 99MB
    PreferredMaxBytes: 512KB
  Kafka:
    Brokers:
      - 127.0.0.1:9092
  Organizations:
  Policies:
    Readers:
      Type: ImplicitMeta
      Rule: "ANY Readers"
    Writers:
      Type: ImplicitMeta
      Rule: "ANY Writers"
    Admins:
      Type: ImplicitMeta
      Rule: "MAJORITY Admins"
    BlockValidation:
      Type: ImplicitMeta
      Rule: "ANY Writers"
  Capabilities:
    <<: *OrdererCapabilities

Profiles:
  # TwoOrgsOrdererGenesis配置文件用于创建系统通道创世块
  TwoOrgsOrdererGenesis:
    <<: *ChannelDefaults
    # 定义排序服务
    Orderer:
      <<: *OrdererDefaults
      # 定义排序服务的管理员
      Organizations:
        - *OrdererOrg
    # 创建一个名为SampleConsortium的联盟,包含两个组织Org1,Org2
    Consortiums:
      SampleConsortium:
        Organizations:
          - *Org1
          - *Org2
  # 测试网络使用TwoOrgsChannel配置文件创建应用程序通道
  TwoOrgsChannel:
    <<: *ChannelDefaults
    Consortium: SampleConsortium
    Application:
      <<: *ApplicationDefaults
      Organizations:
        - *Org1
        - *Org2

新建文件夹configtx,用于存放生成的创世块配置。

bash
mkdir -p /root/fabric/configtx

使用configtxgen命令生成的创世块配置,其中-channelID hellodeploy定义了系统通道的名称,系统通道定义了形成排序服务的Orderer节点集合和充当排序服务管理员的组织集合。

bash
docker run --privileged -v /root/fabric:/data -e FABRIC_CFG_PATH=/data --rm hyperledger/fabric-tools:2.4 configtxgen -profile TwoOrgsOrdererGenesis -outputBlock /data/configtx/genesis.block -channelID hellodeploy

接下来,我们要创建一个应用通道,通道成员为configtx.yaml文件最后部分TwoOrgsChannel所定义的两个组织Org1和Org2。

bash
docker run --privileged -v /root/fabric:/data -e FABRIC_CFG_PATH=/data --rm hyperledger/fabric-tools:2.4 configtxgen -profile TwoOrgsChannel -outputCreateChannelTx /data/configtx/hello.tx -channelID hello

我们根据configtx.yaml文件的profile-TwoOrgsChannel部分创建了新通道hello,通道文件为hello.tx,这个文件非常重要,接下来其他节点要加入这个通道就必须使用这个文件。注意文件后缀为tx,这是一个交易,是因为我们可以追加交易来更新对其的设置,最终的设置是由所有应用于此的交易生效后的结果。

接下来,我们要指定锚节点。我们在上面已经声明了两个组织:Org1和Org2,这两个组织分别有两个节点:peer0和peer1。我们计划使用通道hello将Org1和Org2两个组织连接起来,使其可以相互通信,形成联盟。当然也可以建立第二个通道hello2,让Org2和Org3连接起来形成联盟,此时Org2会维护两套账本(我们接下来不会这样做,只是为了说明)。

我们将会指定节点Org1.peer0和Org2.peer0作为通道hello上面各自组织的的锚节点。注意节点是否是锚节点取决于通道,比如Org2.peer0在通道hello上面是锚节点,但是对于连接Org2和Org3的通道hello2,我们可以指定Org2.peer1为锚节点,那么Org2.peer0在通道hello2就不是锚节点了。

执行如下命令,生成Org1组织的节点在通道hello上面更新为锚节点的配置交易。最后-asOrg Org1MSP是启动节点时的环境变量CORE_PEER_LOCALMSPID

bash
docker run --privileged -v /root/fabric:/data -e FABRIC_CFG_PATH=/data --rm hyperledger/fabric-tools:2.4 configtxgen -profile TwoOrgsChannel -outputAnchorPeersUpdate /data/configtx/Org1MSPanchors_hello.tx -channelID hello -asOrg Org1MSP

同理,生成Org2组织的节点在通道hello上面更新为锚节点的配置交易。

bash
docker run --privileged -v /root/fabric:/data -e FABRIC_CFG_PATH=/data --rm hyperledger/fabric-tools:2.4 configtxgen -profile TwoOrgsChannel -outputAnchorPeersUpdate /data/configtx/Org2MSPanchors_hello.tx -channelID hello -asOrg Org2MSP

启动私有集群

接下来,我们使用docker启动一个排序节点,2个组织各有2个节点的私有集群。

创建文件docker-compose.yaml

bash
version: '3'

networks:
  byfn:

services:
  orderer.flxdu.cn:
    container_name: orderer.flxdu.cn
    image: hyperledger/fabric-orderer:2.4
    restart: always
    privileged: true
    environment:
      - ORDERER_GENERAL_LOGLEVEL=debug
      - ORDERER_GENERAL_LISTENADDRESS=0.0.0.0
      - ORDERER_GENERAL_GENESISMETHOD=file
      - ORDERER_GENERAL_GENESISFILE=/etc/hyperledger/configtx/genesis.block
      - ORDERER_GENERAL_LOCALMSPID=OrdererMSP
      - ORDERER_GENERAL_LOCALMSPDIR=/etc/hyperledger/msp/orderer/msp
    volumes:
      - ./configtx/genesis.block:/etc/hyperledger/configtx/genesis.block
      - ./crypto-config/ordererOrganizations/orderers/orderer./msp:/etc/hyperledger/msp/orderer/msp
      - ./var/orderer.flxdu.cn:/var/hyperledger/production/orderer
    ports:
      - "7050:7050"
    command: orderer start
    networks:
      - byfn

  cli:
    container_name: cli
    image: hyperledger/fabric-tools:2.4
    tty: true
    privileged: true
    environment:
      - GOPATH=/opt/gopath
      - FABRIC_LOGGING_SPEC=DEBUG
      - CORE_PEER_ID=cli
      - CORE_CHAINCODE_KEEPALIVE=10
    command: /bin/bash
    volumes:
      - ./chaincode:/opt/gopath/src/github.com
      - ./crypto-config:/opt/crypto-config
      - ./configtx:/opt/configtx
    networks:
      - byfn

  peer0.org1.flxdu.cn:
    container_name: peer0.org1.flxdu.cn
    image: hyperledger/fabric-peer:2.4
    privileged: true
    environment:
      - CORE_VM_ENDPOINT=unix:///host/var/run/docker.sock
      - CORE_VM_DOCKER_HOSTCONFIG_NETWORKMODE=${PROJECT_NAME}_byfn
      - FABRIC_LOGGING_SPEC=INFO
      - CORE_PEER_MSPCONFIGPATH=/etc/hyperledger/peer/msp

      - CORE_PEER_ID=peer0.org1.flxdu.cn
      - CORE_PEER_ADDRESS=peer0.org1.flxdu.cn:7051
      - CORE_PEER_LOCALMSPID=Org1MSP

      - CORE_PEER_GOSSIP_EXTERNALENDPOINT=peer0.org1.flxdu.cn:7051
      - CORE_PEER_GOSSIP_ORGLEADER=false
      - CORE_PEER_GOSSIP_USELEADERELECTION=true
      - CORE_PEER_GOSSIP_STATE_ENABLED=true
      - CORE_CHAINCODE_NODE_RUNTIME=hyperledger/fabric-nodeenv:2.4
    command: peer node start
    volumes:
      - /var/run/docker.sock:/host/var/run/docker.sock
      - ./crypto-config/peerOrganizations/org1.flxdu.cn/peers/peer0.org1.flxdu.cn/msp:/etc/hyperledger/peer/msp
      - ./var/peer0.org1.flxdu.cn:/var/hyperledger/production
    ports:
      - "7051:7051"
      - "7053:7053"
    networks:
      - byfn

  peer1.org1.flxdu.cn:
    container_name: peer1.org1.flxdu.cn
    image: hyperledger/fabric-peer:2.4
    privileged: true
    environment:
      - CORE_VM_ENDPOINT=unix:///host/var/run/docker.sock
      - CORE_VM_DOCKER_HOSTCONFIG_NETWORKMODE=${PROJECT_NAME}_byfn
      - FABRIC_LOGGING_SPEC=INFO
      - CORE_PEER_MSPCONFIGPATH=/etc/hyperledger/peer/msp

      - CORE_PEER_ID=peer1.org1.flxdu.cn
      - CORE_PEER_ADDRESS=peer1.org1.flxdu.cn:7051
      - CORE_PEER_LOCALMSPID=Org1MSP

      - CORE_PEER_GOSSIP_BOOTSTRAP=peer0.org1.flxdu.cn:7051
      - CORE_PEER_GOSSIP_ORGLEADER=false
      - CORE_PEER_GOSSIP_USELEADERELECTION=true
      - CORE_PEER_GOSSIP_STATE_ENABLED=true
      - CORE_CHAINCODE_NODE_RUNTIME=hyperledger/fabric-nodeenv:2.4
    command: peer node start
    volumes:
      - /var/run/docker.sock:/host/var/run/docker.sock
      - ./crypto-config/peerOrganizations/org1.flxdu.cn/peers/peer1.org1.flxdu.cn/msp:/etc/hyperledger/peer/msp
      - ./var/peer1.org1.flxdu.cn:/var/hyperledger/production
    ports:
      - "8051:7051"
      - "8053:7053"
    networks:
      - byfn

  peer0.org2.flxdu.cn:
    container_name: peer0.org2.flxdu.cn
    image: hyperledger/fabric-peer:2.4
    privileged: true
    environment:
      - CORE_VM_ENDPOINT=unix:///host/var/run/docker.sock
      - CORE_VM_DOCKER_HOSTCONFIG_NETWORKMODE=${PROJECT_NAME}_byfn
      - FABRIC_LOGGING_SPEC=INFO
      - CORE_PEER_MSPCONFIGPATH=/etc/hyperledger/peer/msp

      - CORE_PEER_ID=peer0.org2.flxdu.cn
      - CORE_PEER_ADDRESS=peer0.org2.flxdu.cn:7051
      - CORE_PEER_LOCALMSPID=Org2MSP

      - CORE_PEER_GOSSIP_EXTERNALENDPOINT=peer0.org2.flxdu.cn:7051
      - CORE_PEER_GOSSIP_ORGLEADER=false
      - CORE_PEER_GOSSIP_USELEADERELECTION=true
      - CORE_PEER_GOSSIP_STATE_ENABLED=true
      - CORE_CHAINCODE_NODE_RUNTIME=hyperledger/fabric-nodeenv:2.4
    command: peer node start
    volumes:
      - /var/run/docker.sock:/host/var/run/docker.sock
      - ./crypto-config/peerOrganizations/org2.flxdu.cn/peers/peer0.org2.flxdu.cn/msp:/etc/hyperledger/peer/msp
      - ./var/peer0.org2.flxdu.cn:/var/hyperledger/production
    ports:
      - "9051:7051"
      - "9053:7053"
    networks:
      - byfn

  peer1.org2.flxdu.cn:
    container_name: peer1.org2.flxdu.cn
    image: hyperledger/fabric-peer:2.4
    privileged: true
    environment:
      - CORE_VM_ENDPOINT=unix:///host/var/run/docker.sock
      - CORE_VM_DOCKER_HOSTCONFIG_NETWORKMODE=${PROJECT_NAME}_byfn
      - FABRIC_LOGGING_SPEC=INFO
      - CORE_PEER_MSPCONFIGPATH=/etc/hyperledger/peer/msp

      - CORE_PEER_ID=peer1.org2.flxdu.cn
      - CORE_PEER_ADDRESS=peer1.org2.flxdu.cn:7051
      - CORE_PEER_LOCALMSPID=Org2MSP

      - CORE_PEER_GOSSIP_BOOTSTRAP=peer0.org2.flxdu.cn:7051
      - CORE_PEER_GOSSIP_ORGLEADER=false
      - CORE_PEER_GOSSIP_USELEADERELECTION=true
      - CORE_PEER_GOSSIP_STATE_ENABLED=true
      - CORE_CHAINCODE_NODE_RUNTIME=hyperledger/fabric-nodeenv:2.4
    command: peer node start
    volumes:
      - /var/run/docker.sock:/host/var/run/docker.sock
      - ./crypto-config/peerOrganizations/org2.flxdu.cn/peers/peer1.org2.flxdu.cn/msp:/etc/hyperledger/peer/msp
      - ./var/peer1.org2.flxdu.cn:/var/hyperledger/production
    ports:
      - "10051:7051"
      - "10053:7053"
    networks:
      - byfn

启动私有集群

bash
PROJECT_NAME=fabric docker-compose -f /root/fabric/docker-compose.yaml up -d

检查私有集群的运行状态:

bash
docker ps -a

接下来基于在文件hello.tx中的配置交易创建通道hello,使用的排序器端结点为orderer.flxdu.cn:7050

bash
docker exec -e CORE_PEER_MSPCONFIGPATH=/opt/crypto-config/peerOrganizations/org1.flxdu.cn/users/Admin@org1.flxdu.cn/msp -e CORE_PEER_LOCALMSPID="Org1MSP" cli peer channel create -o orderer.flxdu.cn:7050 -c hello -f /opt/configtx/hello.tx

此命令会生成一个名为hello.block的文件,说明通道hello已经成功创建,第0块已经加入到该通道的区块链中并返回给节点,该区块在本地文件中正是hello.block,路径为cli容器的/go/hello.block。

第0块通常被称为创世块,因为它提供了通道的起始配置。

我们把hello.block挪到我们自己的配置文件路径。

bash
docker exec cli mv /go/hello.block /opt/configtx/

接下来,我们将使用6个命令,将4个节点加入通道hello,将其中2个节点设置为锚节点。

将org1.peer0加入通道

bash
docker exec -e CORE_PEER_MSPCONFIGPATH=/opt/crypto-config/peerOrganizations/org1.flxdu.cn/users/Admin@org1.flxdu.cn/msp -e CORE_PEER_LOCALMSPID="Org1MSP" -e CORE_PEER_ADDRESS=peer0.org1.flxdu.cn:7051 cli peer channel join -b /opt/configtx/hello.block

将org1.peer1加入通道

bash
docker exec -e CORE_PEER_MSPCONFIGPATH=/opt/crypto-config/peerOrganizations/org1.flxdu.cn/users/Admin@org1.flxdu.cn/msp -e CORE_PEER_LOCALMSPID="Org1MSP" -e CORE_PEER_ADDRESS=peer1.org1.flxdu.cn:7051 cli peer channel join -b /opt/configtx/hello.block

将org2.peer0加入通道

bash
docker exec -e CORE_PEER_MSPCONFIGPATH=/opt/crypto-config/peerOrganizations/org2.flxdu.cn/users/Admin@org2.flxdu.cn/msp -e CORE_PEER_LOCALMSPID="Org2MSP" -e CORE_PEER_ADDRESS=peer0.org2.flxdu.cn:7051 cli peer channel join -b /opt/configtx/hello.block

将org2.peer1加入通道

bash
docker exec -e CORE_PEER_MSPCONFIGPATH=/opt/crypto-config/peerOrganizations/org2.flxdu.cn/users/Admin@org2.flxdu.cn/msp -e CORE_PEER_LOCALMSPID="Org2MSP" -e CORE_PEER_ADDRESS=peer1.org2.flxdu.cn:7051 cli peer channel join -b /opt/configtx/hello.block

将org1.peer0设置为锚节点

bash
docker exec -e CORE_PEER_MSPCONFIGPATH=/opt/crypto-config/peerOrganizations/org1.flxdu.cn/users/Admin@org1.flxdu.cn/msp -e CORE_PEER_LOCALMSPID="Org1MSP" -e CORE_PEER_ADDRESS=peer0.org1.flxdu.cn:7051 cli peer channel update -o orderer.flxdu.cn:7050 -c hello -f /opt/configtx/Org1MSPanchors_hello.tx

将org2.peer0设置为锚节点

bash
docker exec -e CORE_PEER_MSPCONFIGPATH=/opt/crypto-config/peerOrganizations/org2.flxdu.cn/users/Admin@org2.flxdu.cn/msp -e CORE_PEER_LOCALMSPID="Org2MSP" -e CORE_PEER_ADDRESS=peer0.org2.flxdu.cn:7051 cli peer channel update -o orderer.flxdu.cn:7050 -c hello -f /opt/configtx/Org2MSPanchors_hello.tx

这样,整个网络就搭起来了,可以进行链码(智能合约)部署等进一步操作。

停止网络

执行

bash
PROJECT_NAME=fabric docker-compose -f /root/fabric/docker-compose.yaml down

即可停止网络。

可通过

bash
PROJECT_NAME=fabric docker-compose -f /root/fabric/docker-compose.yaml up -d

再次启动网络。

部署链码

与实验一相同,本实验所有操作均在文件夹/root/fabric下执行,且确保系统中安装有Docker、docker-compose和vim。

需要确保实验一中的联盟链已经搭建并运行成功。

Go语言

打包链码sacc

创建目录/root/fabric/chaincode/sacc/

bash
mkdir -p /root/fabric/chaincode/sacc/

将链码sacc.go拷贝至目录/root/fabric/chaincode/sacc/下。

进入cli容器进行后续操作

bash
docker exec -it cli /bin/sh
# 接下来的命令均在容器内执行
cd /opt/gopath/src/github.com/sacc
# 设置代理
go env -w GOPROXY=https://goproxy.cn,direct
# 设置依赖
go mod init
go mod tidy
# 打包链码
peer lifecycle chaincode package sacc.tar.gz --path github.com/sacc/ --label sacc_1
# 退出容器
exit

打包完成后,会在目录/root/fabric/chaincode/sacc/下发现文件sacc.tar.gz

安装链码sacc

链码要安装至Org1和Org2。

在Org1安装链码

bash
docker exec -e CORE_PEER_MSPCONFIGPATH=/opt/crypto-config/peerOrganizations/org1.flxdu.cn/users/Admin@org1.flxdu.cn/msp -e CORE_PEER_LOCALMSPID="Org1MSP" -e CORE_PEER_ADDRESS=peer0.org1.flxdu.cn:7051 cli peer lifecycle chaincode install /opt/gopath/src/github.com/sacc/sacc.tar.gz

看到输出Chaincode code package identifier即为成功,如下图:

image-20230911152701370

在Org2安装链码

bash
docker exec -e CORE_PEER_MSPCONFIGPATH=/opt/crypto-config/peerOrganizations/org2.flxdu.cn/users/Admin@org2.flxdu.cn/msp -e CORE_PEER_LOCALMSPID="Org2MSP" -e CORE_PEER_ADDRESS=peer0.org2.flxdu.cn:7051 cli peer lifecycle chaincode install /opt/gopath/src/github.com/sacc/sacc.tar.gz

安装成功的输出与Org1安装链码的输出相同。

安装后的链码要在组织中确定。

在Org1中确定链码,注意--package-id后面是上一步的Chaincode code package identifier

bash
docker exec -e CORE_PEER_MSPCONFIGPATH=/opt/crypto-config/peerOrganizations/org1.flxdu.cn/users/Admin@org1.flxdu.cn/msp -e CORE_PEER_LOCALMSPID="Org1MSP" -e CORE_PEER_ADDRESS=peer0.org1.flxdu.cn:7051 cli peer lifecycle chaincode approveformyorg --channelID hello --name sacc --version 1.0 --init-required --package-id sacc_1:4b29ffe6a929d1253f3ed2f9ed6c6855ad9cff68b9a0a8237c1311a0df1927dd --sequence 1

安装成功后会输出,如下图:

image-20230911152906788

在Org2中确定链码,注意--package-id后面是上一步的Chaincode code package identifier

bash
docker exec -e CORE_PEER_MSPCONFIGPATH=/opt/crypto-config/peerOrganizations/org2.flxdu.cn/users/Admin@org2.flxdu.cn/msp -e CORE_PEER_LOCALMSPID="Org2MSP" -e CORE_PEER_ADDRESS=peer0.org2.flxdu.cn:7051 cli peer lifecycle chaincode approveformyorg --channelID hello --name sacc --version 1.0 --init-required --package-id sacc_1:4b29ffe6a929d1253f3ed2f9ed6c6855ad9cff68b9a0a8237c1311a0df1927dd --sequence 1

确定成功的输出与Org1确定链码的输出相同。

确定完成后,检查是否配置正常

bash
docker exec -e CORE_PEER_MSPCONFIGPATH=/opt/crypto-config/peerOrganizations/org1.flxdu.cn/users/Admin@org1.flxdu.cn/msp -e CORE_PEER_LOCALMSPID="Org1MSP" -e CORE_PEER_ADDRESS=peer0.org1.flxdu.cn:7051 cli peer lifecycle chaincode checkcommitreadiness --channelID hello --name sacc --version 1.0 --init-required --sequence 1 --output json

此时输出如下内容表示配置正常,如有 false 则表示安装有问题:

json
{
	"approvals": {
		"Org1MSP": true,
		"Org2MSP": true
	}
}

提交、初始化并执行链码

提交链码

bash
docker exec -e CORE_PEER_MSPCONFIGPATH=/opt/crypto-config/peerOrganizations/org1.flxdu.cn/users/Admin@org1.flxdu.cn/msp -e CORE_PEER_LOCALMSPID="Org1MSP" -e CORE_PEER_ADDRESS=peer0.org1.flxdu.cn:7051 cli peer lifecycle chaincode commit -o orderer.flxdu.cn:7050 --channelID hello --name sacc --version 1.0 --sequence 1 --init-required --peerAddresses peer0.org1.flxdu.cn:7051 --peerAddresses peer0.org2.flxdu.cn:7051

初始化

bash
docker exec -e CORE_PEER_MSPCONFIGPATH=/opt/crypto-config/peerOrganizations/org1.flxdu.cn/users/Admin@org1.flxdu.cn/msp -e CORE_PEER_LOCALMSPID="Org1MSP" -e CORE_PEER_ADDRESS=peer0.org1.flxdu.cn:7051 cli peer chaincode invoke -o orderer.flxdu.cn:7050 --isInit --channelID hello --name sacc --peerAddresses peer0.org1.flxdu.cn:7051 --peerAddresses peer0.org2.flxdu.cn:7051 -c '{"Args":["hello", "world"]}'

看到输出Chaincode invoke successful. result: status:200可认为成功。

查询

bash
docker exec -e CORE_PEER_MSPCONFIGPATH=/opt/crypto-config/peerOrganizations/org1.flxdu.cn/users/Admin@org1.flxdu.cn/msp -e CORE_PEER_LOCALMSPID="Org1MSP" -e CORE_PEER_ADDRESS=peer0.org1.flxdu.cn:7051 cli peer chaincode query --channelID hello -n sacc -c '{"Args":["query", "hello"]}'

可以得到结果为world,说明初始化的参数已被存储。

设置/修改

bash
docker exec -e CORE_PEER_MSPCONFIGPATH=/opt/crypto-config/peerOrganizations/org1.flxdu.cn/users/Admin@org1.flxdu.cn/msp -e CORE_PEER_LOCALMSPID="Org1MSP" -e CORE_PEER_ADDRESS=peer0.org1.flxdu.cn:7051 cli peer chaincode invoke -o orderer.flxdu.cn:7050 --channelID hello -n sacc --peerAddresses peer0.org1.flxdu.cn:7051 --peerAddresses peer0.org2.flxdu.cn:7051 -c '{"Args":["set", "hello", "block chain"]}'

再执行上一步查询,可以得到结果为block chain,说明修改成功。也可以set一个新键值对,在查询时同样可以查到。链码具体逻辑可以查看链码文件。

JavaScript语言

宿主机需先执行:

bash
echo 'net.ipv4.ip_forward=1' >> /etc/sysctl.conf && systemctl restart network

本实验需要如下1个镜像:

  • hyperledger/fabric-nodeenv:包含了NodeJS的所有二进制程序并且设置 PATH 变量,可以直接通过 Docker 执行相关命令。

打包链码abstore

打包JavaScript链码所需的镜像hyperledger/fabric-nodeenv:2.4使用的npm源在国内无法访问,所以我们需要自己造一个镜像来使用:

bash
# 创建Dockerfile
cat <<EOF>> Dockerfile
FROM hyperledger/fabric-nodeenv:2.4
RUN npm config set registry http://mirrors.cloud.tencent.com/npm/
EOF

# 构建镜像
docker build -t temp/fabric-nodeenv:2.4 .

# 删除原有的hyperledger/fabric-nodeenv:2.4
docker rmi hyperledger/fabric-nodeenv:2.4

# 修改镜像标签
docker tag temp/fabric-nodeenv:2.4 docker.io/hyperledger/fabric-nodeenv:2.4 && docker rmi temp/fabric-nodeenv:2.4

创建目录/root/fabric/chaincode/abstore/

bash
mkdir -p /root/fabric/chaincode/abstore/

package.json和链码abstore.js拷贝至目录/root/fabric/chaincode/abstore/下。

打包链码:

bash
docker exec -e CORE_PEER_MSPCONFIGPATH=/opt/crypto-config/peerOrganizations/org1.flxdu.cn/users/Admin@org1.flxdu.cn/msp -e CORE_PEER_LOCALMSPID="Org1MSP" -e CORE_PEER_ADDRESS=peer0.org1.flxdu.cn:7051 cli peer lifecycle chaincode package /opt/gopath/src/github.com/abstore/abstore.tar.gz --path /opt/gopath/src/github.com/abstore --label abstore_1 -l node

打包完成后,会在目录/root/fabric/chaincode/abstore/下发现文件abstore.tar.gz

安装链码abstore

在org1中安装链码

bash
docker exec -e CORE_PEER_MSPCONFIGPATH=/opt/crypto-config/peerOrganizations/org1.flxdu.cn/users/Admin@org1.flxdu.cn/msp -e CORE_PEER_LOCALMSPID="Org1MSP" -e CORE_PEER_ADDRESS=peer0.org1.flxdu.cn:7051 cli peer lifecycle chaincode install /opt/gopath/src/github.com/abstore/abstore.tar.gz

看到输出Installed remotely: response:<status:200 payload:"OK" > 即为成功,如下图:

image-20230912122026851

在org2中安装链码

bash
docker exec -e CORE_PEER_MSPCONFIGPATH=/opt/crypto-config/peerOrganizations/org2.flxdu.cn/users/Admin@org2.flxdu.cn/msp -e CORE_PEER_LOCALMSPID="Org2MSP" -e CORE_PEER_ADDRESS=peer0.org2.flxdu.cn:7051 cli peer lifecycle chaincode install /opt/gopath/src/github.com/abstore/abstore.tar.gz

看到输出Installed remotely: response:<status:200 payload:"OK" > 即为成功。

安装后的链码要在组织中确定。

在Org1中确定链码,注意--package-id后面是上一步的Chaincode code package identifier

bash
docker exec -e CORE_PEER_MSPCONFIGPATH=/opt/crypto-config/peerOrganizations/org1.flxdu.cn/users/Admin@org1.flxdu.cn/msp -e CORE_PEER_LOCALMSPID="Org1MSP" -e CORE_PEER_ADDRESS=peer0.org1.flxdu.cn:7051 cli peer lifecycle chaincode approveformyorg --channelID hello --name abstore --version 1.0 --init-required --package-id abstore_1:1aff8f80f9b007823cd9be5523569a3088b5b2018c346ea72aeee426f5274f99 --sequence 1

在Org2中确定链码,

bash
docker exec -e CORE_PEER_MSPCONFIGPATH=/opt/crypto-config/peerOrganizations/org2.flxdu.cn/users/Admin@org2.flxdu.cn/msp -e CORE_PEER_LOCALMSPID="Org2MSP" -e CORE_PEER_ADDRESS=peer0.org2.flxdu.cn:7051 cli peer lifecycle chaincode approveformyorg --channelID hello --name abstore --version 1.0 --init-required --package-id abstore_1:1aff8f80f9b007823cd9be5523569a3088b5b2018c346ea72aeee426f5274f99 --sequence 1

确定成功的输出与Org1确定链码的输出相同。

确定完成后,检查是否配置正常

bash
docker exec -e CORE_PEER_MSPCONFIGPATH=/opt/crypto-config/peerOrganizations/org1.flxdu.cn/users/Admin@org1.flxdu.cn/msp -e CORE_PEER_LOCALMSPID="Org1MSP" -e CORE_PEER_ADDRESS=peer0.org1.flxdu.cn:7051 cli peer lifecycle chaincode checkcommitreadiness --channelID hello --name abstore --version 1.0 --init-required --sequence 1 --output json

此时输出如下内容表示配置正常,如有 false 则表示安装有问题:

json
{
	"approvals": {
		"Org1MSP": true,
		"Org2MSP": true
	}
}

提交、初始化并执行链码

提交链码

bash
docker exec -e CORE_PEER_MSPCONFIGPATH=/opt/crypto-config/peerOrganizations/org1.flxdu.cn/users/Admin@org1.flxdu.cn/msp -e CORE_PEER_LOCALMSPID="Org1MSP" -e CORE_PEER_ADDRESS=peer0.org1.flxdu.cn:7051 cli peer lifecycle chaincode commit -o orderer.flxdu.cn:7050 --channelID hello --name abstore --version 1.0 --sequence 1 --init-required --peerAddresses peer0.org1.flxdu.cn:7051 --peerAddresses peer0.org2.flxdu.cn:7051

初始化,初始化a和b两个主体,其各有100、200单位的余额:

bash
docker exec -e CORE_PEER_MSPCONFIGPATH=/opt/crypto-config/peerOrganizations/org1.flxdu.cn/users/Admin@org1.flxdu.cn/msp -e CORE_PEER_LOCALMSPID="Org1MSP" -e CORE_PEER_ADDRESS=peer0.org1.flxdu.cn:7051 cli peer chaincode invoke -o orderer.flxdu.cn:7050 --isInit --channelID hello --name abstore --peerAddresses peer0.org1.flxdu.cn:7051 --peerAddresses peer0.org2.flxdu.cn:7051 -c '{"Args":["init","a","100","b","200"]}'

看到输出Chaincode invoke successful. result: status:200可认为成功。

查询a的余额:

bash
docker exec -e CORE_PEER_MSPCONFIGPATH=/opt/crypto-config/peerOrganizations/org1.flxdu.cn/users/Admin@org1.flxdu.cn/msp -e CORE_PEER_LOCALMSPID="Org1MSP" -e CORE_PEER_ADDRESS=peer0.org1.flxdu.cn:7051 cli peer chaincode query --channelID hello -n abstore -c '{"Args":["query", "b"]}'

可以得到结果为100,说明初始化的参数已被存储。

a向b转账1个单位

bash
docker exec -e CORE_PEER_MSPCONFIGPATH=/opt/crypto-config/peerOrganizations/org1.flxdu.cn/users/Admin@org1.flxdu.cn/msp -e CORE_PEER_LOCALMSPID="Org1MSP" -e CORE_PEER_ADDRESS=peer0.org1.flxdu.cn:7051 cli peer chaincode invoke -o orderer.flxdu.cn:7050 --channelID hello -n abstore --peerAddresses peer0.org1.flxdu.cn:7051 --peerAddresses peer0.org2.flxdu.cn:7051 -c '{"Args":["invoke", "a", "b", "1"]}'

再执行上一步查询,可以看到a的余额变味了99,b的余额变为了201,说明修改成功。也可以把a和b删除,链码具体逻辑可以查看链码文件。链码中没有新增主体的函数,可以尝试修改链码以增加这个功能。

部署浏览器

创建文件夹/root/fabric-explorer

bash
mkdir -p /root/fabric-explorer && cd /root/fabric-explorer

本实验所有操作均在文件夹/root/fabric-explorer下执行,且确保系统中安装有Docker、docker-compose和vim。

需要确保实验一中的联盟链已经搭建并运行成功。

拉取镜像

本实验需要如下3个镜像:

  • hyperledger/explorer-db:浏览器所需的Postgresql数据库。
  • hyperledger/explorer:浏览器镜像。

执行如下命令检查镜像是否已经拉取:

bash
docker images | grep hyperledger/explorer

拷贝密钥文件

将我们在部署网络时生成的文件夹crypto-config拷贝到fabric-explorer,并重命名为organizations

bash
cp -a /root/fabric/crypto-config /root/fabric-explorer/organizations

fabric-explorer下新建文件夹connection-profile,后续浏览器会使用文件夹下的配置连接各个节点:

bash
mkdir -p /root/fabric-explorer/connection-profile

因为我们希望能查看两个组织的情况,所以我们要在connection-profile下放两个配置文件。

connection-profile下新建文件org1-network.json

json
{
	"name": "org1-network",
	"version": "1.0.0",
	"client": {
		"tlsEnable": false,
		"adminCredential": {
			"id": "exploreradmin",
			"password": "exploreradminpw"
		},
		"enableAuthentication": true,
		"organization": "Org1MSP",
		"connection": {
			"timeout": {
				"peer": {
					"endorser": "300"
				},
				"orderer": "300"
			}
		}
	},
	"channels": {
		"hello": {
			"peers": {
				"peer0.org1.flxdu.cn": {}
			}
		}
	},
	"organizations": {
		"Org1MSP": {
			"mspid": "Org1MSP",
			"adminPrivateKey": {
				"path": "/tmp/crypto/peerOrganizations/org1.flxdu.cn/users/Admin@org1.flxdu.cn/msp/keystore/priv_sk"
			},
			"peers": ["peer0.org1.flxdu.cn"],
			"signedCert": {
				"path": "/tmp/crypto/peerOrganizations/org1.flxdu.cn/users/Admin@org1.flxdu.cn/msp/signcerts/Admin@org1.flxdu.cn-cert.pem"
			}
		}
	},
	"peers": {
		"peer0.org1.flxdu.cn": {
			"tlsCACerts": {
				"path": "/tmp/crypto/peerOrganizations/org1.flxdu.cn/peers/peer0.org1.flxdu.cn/tls/ca.crt"
			},
			"url": "grpc://peer0.org1.flxdu.cn:7051"
		}
	}
}

connection-profile下新建文件org2-network.json

json
{
	"name": "org2-network",
	"version": "1.0.0",
	"client": {
		"tlsEnable": false,
		"adminCredential": {
			"id": "exploreradmin",
			"password": "exploreradminpw"
		},
		"enableAuthentication": true,
		"organization": "Org2MSP",
		"connection": {
			"timeout": {
				"peer": {
					"endorser": "300"
				},
				"orderer": "300"
			}
		}
	},
	"channels": {
		"hello": {
			"peers": {
				"peer0.org2.flxdu.cn": {}
			}
		}
	},
	"organizations": {
		"Org2MSP": {
			"mspid": "Org2MSP",
			"adminPrivateKey": {
				"path": "/tmp/crypto/peerOrganizations/org2.flxdu.cn/users/Admin@org2.flxdu.cn/msp/keystore/priv_sk"
			},
			"peers": ["peer0.org2.flxdu.cn"],
			"signedCert": {
				"path": "/tmp/crypto/peerOrganizations/org2.flxdu.cn/users/Admin@org2.flxdu.cn/msp/signcerts/Admin@org2.flxdu.cn-cert.pem"
			}
		}
	},
	"peers": {
		"peer0.org2.flxdu.cn": {
			"tlsCACerts": {
				"path": "/tmp/crypto/peerOrganizations/org2.flxdu.cn/peers/peer0.org2.flxdu.cn/tls/ca.crt"
			},
			"url": "grpc://peer0.org2.flxdu.cn:7051"
		}
	}
}

注意在org1-network.jsonorg2-network.json中,字段adminCredential配置了访问浏览器所需要的用户名和密码;字段tlsEnable配置了要连接的节点是否为TLS节点,因为我们的节点没开启TLS,所以此项为false,且位于最后面的字段peers.url前缀为grpc://,如果是TLS节点的话应写为grpcs://

fabric-explorer目录下创建浏览器的配置文件config.json,其配置了两个组织的网络。

json
{
	"network-configs": {
		"org1-network": {
			"name": "org1-network",
			"profile": "./connection-profile/org1-network.json"
		},
		"org2-network": {
			"name": "org2-network",
			"profile": "./connection-profile/org2-network.json"
		}
	},
	"license": "Apache-2.0"
}

以上配置文件文档在Github - README-CONFIG.md

fabric-explorer目录下创建docker-compose.yaml文件。

yaml
# SPDX-License-Identifier: Apache-2.0
version: '2.1'

volumes:
  pgdata:
  walletstore:

networks:
  mynetwork.com:
    external:
      name: fabric_byfn

services:
  explorerdb.mynetwork.com:
    image: hyperledger/explorer-db:1.1.8
    container_name: explorerdb.mynetwork.com
    hostname: explorerdb.mynetwork.com
    privileged: true
    environment:
      - DATABASE_DATABASE=fabricexplorer
      - DATABASE_USERNAME=hppoc
      - DATABASE_PASSWORD=password
    healthcheck:
      test: "pg_isready -h localhost -p 5432 -q -U postgres"
      interval: 30s
      timeout: 10s
      retries: 5
    volumes:
      - pgdata:/var/lib/postgresql/data
    networks:
      - mynetwork.com

  explorer.mynetwork.com:
    image: hyperledger/explorer:1.1.8
    container_name: explorer.mynetwork.com
    hostname: explorer.mynetwork.com
    privileged: true
    environment:
      - DATABASE_HOST=explorerdb.mynetwork.com
      - DATABASE_DATABASE=fabricexplorer
      - DATABASE_USERNAME=hppoc
      - DATABASE_PASSWD=password
      - LOG_LEVEL_APP=debug
      - LOG_LEVEL_DB=debug
      - LOG_LEVEL_CONSOLE=info
      - LOG_CONSOLE_STDOUT=true
      - DISCOVERY_AS_LOCALHOST=false
    volumes:
      - ./config.json:/opt/explorer/app/platform/fabric/config.json
      - ./connection-profile:/opt/explorer/app/platform/fabric/connection-profile
      - ./organizations:/tmp/crypto
      - walletstore:/opt/explorer/wallet
    ports:
      - "8080:8080"
    depends_on:
      explorerdb.mynetwork.com:
        condition: service_healthy
    networks:
      - mynetwork.com

文件中使用的网络是部署网络时创建的fabric_byfn,必须使用同一网络,否则浏览器无法通过域名连接节点。

接下来就可以启动浏览器了

bash
docker-compose up -d

等待浏览器完全启动后,在Chrome打开http://127.0.0.1:8080/,可以看到登录页面,输入用户名exploreradmin,密码exploreradminpw即可登录,如下图所示:

image-20230911162729873

向组织中添加新节点

目前我们的Fabric网络中包含两个组织,每个组织都有两个节点:

  • org1:
    • peer0.org1.flxdu.cn
    • peer1.org1.flxdu.cn
  • org2:
    • peer0.org2.flxdu.cn
    • peer1.org2.flxdu.cn

我们需要在 org1 中添加一个 peer2.org1.flxdu.cn 节点。

生成新节点证书

每个节点都有相应的证书才能连接网络,需要使用 cryptogen 工具生成新节点的证书。因为是新节点加入现有网络组织,因此,需要使用 cryptogen extend 命令首先对现有网络的证书文件进行扩展。在执行该命令之前需要首先修改 crypto-config.yaml 配置文件,将 org1 组织的节点数增加 1,其它的配置信息不要修改。

修改后的 crypto-config.yaml 配置文件:

yaml
OrdererOrgs:
  - Name: Orderer
    Domin: flxdu.cn
    Specs:
      - Hostname: orderer

PeerOrgs:
  - Name: Org1
    Domain: org1.flxdu.cn
    EnableNodeOUs: true
    Template:
      Count: 3
    Users:
      Count: 1

  - Name: Org2
    Domain: org2.flxdu.cn
    EnableNodeOUs: true
    Template:
      Count: 2
    Users:
      Count: 1

修改完成后即可使用 cryptogen extend 命令生成新节点证书,注意,这里需要使用 --config 选项指定刚才修改的配置文件:

bash
docker run --privileged --rm -v /root/fabric:/data hyperledger/fabric-tools:2.4 cryptogen extend --config=/data/crypto-config.yaml --input=/data/crypto-config

可以看到在/root/fabric/crypto-config/peerOrganizations/org1.flxdu.cn/peers目录下多了一个peer2.org1.flxdu.cn目录。

添加新节点配置信息

证书文件生成之后,需要在docker-compose.yaml 中添加新节点peer2.org1.flxdu.cn的配置信息,包括环境变量、映射的端口号、证书文件目录等信息。

修改后的 base/docker-compose.yaml 配置文件:

yaml
version: '3'

networks:
  byfn:

services:
  orderer.flxdu.cn:
    container_name: orderer.flxdu.cn
    image: hyperledger/fabric-orderer:2.4
    restart: always
    privileged: true
    environment:
      - ORDERER_GENERAL_LOGLEVEL=debug
      - ORDERER_GENERAL_LISTENADDRESS=0.0.0.0
      - ORDERER_GENERAL_GENESISMETHOD=file
      - ORDERER_GENERAL_GENESISFILE=/etc/hyperledger/configtx/genesis.block
      - ORDERER_GENERAL_LOCALMSPID=OrdererMSP
      - ORDERER_GENERAL_LOCALMSPDIR=/etc/hyperledger/msp/orderer/msp
    volumes:
      - ./configtx/genesis.block:/etc/hyperledger/configtx/genesis.block
      - ./crypto-config/ordererOrganizations/orderers/orderer./msp:/etc/hyperledger/msp/orderer/msp
      - ./var/orderer.flxdu.cn:/var/hyperledger/production/orderer
    ports:
      - "7050:7050"
    command: orderer start
    networks:
      - byfn

  cli:
    container_name: cli
    image: hyperledger/fabric-tools:2.4
    tty: true
    privileged: true
    environment:
      - GOPATH=/opt/gopath
      - FABRIC_LOGGING_SPEC=DEBUG
      - CORE_PEER_ID=cli
      - CORE_CHAINCODE_KEEPALIVE=10
    command: /bin/bash
    volumes:
      - ./chaincode:/opt/gopath/src/github.com
      - ./crypto-config:/opt/crypto-config
      - ./configtx:/opt/configtx
    networks:
      - byfn

  peer0.org1.flxdu.cn:
    container_name: peer0.org1.flxdu.cn
    image: hyperledger/fabric-peer:2.4
    privileged: true
    environment:
      - CORE_VM_ENDPOINT=unix:///host/var/run/docker.sock
      - CORE_VM_DOCKER_HOSTCONFIG_NETWORKMODE=${PROJECT_NAME}_byfn
      - FABRIC_LOGGING_SPEC=INFO
      - CORE_PEER_MSPCONFIGPATH=/etc/hyperledger/peer/msp

      - CORE_PEER_ID=peer0.org1.flxdu.cn
      - CORE_PEER_ADDRESS=peer0.org1.flxdu.cn:7051
      - CORE_PEER_LOCALMSPID=Org1MSP

      - CORE_PEER_GOSSIP_EXTERNALENDPOINT=peer0.org1.flxdu.cn:7051
      - CORE_PEER_GOSSIP_ORGLEADER=false
      - CORE_PEER_GOSSIP_USELEADERELECTION=true
      - CORE_PEER_GOSSIP_STATE_ENABLED=true
      - CORE_CHAINCODE_NODE_RUNTIME=hyperledger/fabric-nodeenv:2.4
    command: peer node start
    volumes:
      - /var/run/docker.sock:/host/var/run/docker.sock
      - ./crypto-config/peerOrganizations/org1.flxdu.cn/peers/peer0.org1.flxdu.cn/msp:/etc/hyperledger/peer/msp
      - ./var/peer0.org1.flxdu.cn:/var/hyperledger/production
    ports:
      - "7051:7051"
      - "7053:7053"
    networks:
      - byfn

  peer1.org1.flxdu.cn:
    container_name: peer1.org1.flxdu.cn
    image: hyperledger/fabric-peer:2.4
    privileged: true
    environment:
      - CORE_VM_ENDPOINT=unix:///host/var/run/docker.sock
      - CORE_VM_DOCKER_HOSTCONFIG_NETWORKMODE=${PROJECT_NAME}_byfn
      - FABRIC_LOGGING_SPEC=INFO
      - CORE_PEER_MSPCONFIGPATH=/etc/hyperledger/peer/msp

      - CORE_PEER_ID=peer1.org1.flxdu.cn
      - CORE_PEER_ADDRESS=peer1.org1.flxdu.cn:7051
      - CORE_PEER_LOCALMSPID=Org1MSP

      - CORE_PEER_GOSSIP_BOOTSTRAP=peer0.org1.flxdu.cn:7051
      - CORE_PEER_GOSSIP_ORGLEADER=false
      - CORE_PEER_GOSSIP_USELEADERELECTION=true
      - CORE_PEER_GOSSIP_STATE_ENABLED=true
      - CORE_CHAINCODE_NODE_RUNTIME=hyperledger/fabric-nodeenv:2.4
    command: peer node start
    volumes:
      - /var/run/docker.sock:/host/var/run/docker.sock
      - ./crypto-config/peerOrganizations/org1.flxdu.cn/peers/peer1.org1.flxdu.cn/msp:/etc/hyperledger/peer/msp
      - ./var/peer1.org1.flxdu.cn:/var/hyperledger/production
    ports:
      - "8051:7051"
      - "8053:7053"
    networks:
      - byfn

  peer2.org1.flxdu.cn:
    container_name: peer2.org1.flxdu.cn
    image: hyperledger/fabric-peer:2.4
    privileged: true
    environment:
      - CORE_VM_ENDPOINT=unix:///host/var/run/docker.sock
      - CORE_VM_DOCKER_HOSTCONFIG_NETWORKMODE=${PROJECT_NAME}_byfn
      - FABRIC_LOGGING_SPEC=INFO
      - CORE_PEER_MSPCONFIGPATH=/etc/hyperledger/peer/msp

      - CORE_PEER_ID=peer2.org1.flxdu.cn
      - CORE_PEER_ADDRESS=peer2.org1.flxdu.cn:7051
      - CORE_PEER_LOCALMSPID=Org1MSP

      - CORE_PEER_GOSSIP_BOOTSTRAP=peer0.org1.flxdu.cn:7051
      - CORE_PEER_GOSSIP_ORGLEADER=false
      - CORE_PEER_GOSSIP_USELEADERELECTION=true
      - CORE_PEER_GOSSIP_STATE_ENABLED=true
      - CORE_CHAINCODE_NODE_RUNTIME=hyperledger/fabric-nodeenv:2.4
    command: peer node start
    volumes:
      - /var/run/docker.sock:/host/var/run/docker.sock
      - ./crypto-config/peerOrganizations/org1.flxdu.cn/peers/peer2.org1.flxdu.cn/msp:/etc/hyperledger/peer/msp
      - ./var/peer2.org1.flxdu.cn:/var/hyperledger/production
    ports:
      - "11051:7051"
      - "11053:7053"
    networks:
      - byfn

  peer0.org2.flxdu.cn:
    container_name: peer0.org2.flxdu.cn
    image: hyperledger/fabric-peer:2.4
    privileged: true
    environment:
      - CORE_VM_ENDPOINT=unix:///host/var/run/docker.sock
      - CORE_VM_DOCKER_HOSTCONFIG_NETWORKMODE=${PROJECT_NAME}_byfn
      - FABRIC_LOGGING_SPEC=INFO
      - CORE_PEER_MSPCONFIGPATH=/etc/hyperledger/peer/msp

      - CORE_PEER_ID=peer0.org2.flxdu.cn
      - CORE_PEER_ADDRESS=peer0.org2.flxdu.cn:7051
      - CORE_PEER_LOCALMSPID=Org2MSP

      - CORE_PEER_GOSSIP_EXTERNALENDPOINT=peer0.org2.flxdu.cn:7051
      - CORE_PEER_GOSSIP_ORGLEADER=false
      - CORE_PEER_GOSSIP_USELEADERELECTION=true
      - CORE_PEER_GOSSIP_STATE_ENABLED=true
      - CORE_CHAINCODE_NODE_RUNTIME=hyperledger/fabric-nodeenv:2.4
    command: peer node start
    volumes:
      - /var/run/docker.sock:/host/var/run/docker.sock
      - ./crypto-config/peerOrganizations/org2.flxdu.cn/peers/peer0.org2.flxdu.cn/msp:/etc/hyperledger/peer/msp
      - ./var/peer0.org2.flxdu.cn:/var/hyperledger/production
    ports:
      - "9051:7051"
      - "9053:7053"
    networks:
      - byfn

  peer1.org2.flxdu.cn:
    container_name: peer1.org2.flxdu.cn
    image: hyperledger/fabric-peer:2.4
    privileged: true
    environment:
      - CORE_VM_ENDPOINT=unix:///host/var/run/docker.sock
      - CORE_VM_DOCKER_HOSTCONFIG_NETWORKMODE=${PROJECT_NAME}_byfn
      - FABRIC_LOGGING_SPEC=INFO
      - CORE_PEER_MSPCONFIGPATH=/etc/hyperledger/peer/msp

      - CORE_PEER_ID=peer1.org2.flxdu.cn
      - CORE_PEER_ADDRESS=peer1.org2.flxdu.cn:7051
      - CORE_PEER_LOCALMSPID=Org2MSP

      - CORE_PEER_GOSSIP_BOOTSTRAP=peer0.org2.flxdu.cn:7051
      - CORE_PEER_GOSSIP_ORGLEADER=false
      - CORE_PEER_GOSSIP_USELEADERELECTION=true
      - CORE_PEER_GOSSIP_STATE_ENABLED=true
      - CORE_CHAINCODE_NODE_RUNTIME=hyperledger/fabric-nodeenv:2.4
    command: peer node start
    volumes:
      - /var/run/docker.sock:/host/var/run/docker.sock
      - ./crypto-config/peerOrganizations/org2.flxdu.cn/peers/peer1.org2.flxdu.cn/msp:/etc/hyperledger/peer/msp
      - ./var/peer1.org2.flxdu.cn:/var/hyperledger/production
    ports:
      - "10051:7051"
      - "10053:7053"
    networks:
      - byfn

然后重新运行docker-compose.yaml文件

bash
PROJECT_NAME=fabricdev docker-compose up -d

输出为

peer0.org2.flxdu.cn is up-to-date
peer1.org1.flxdu.cn is up-to-date
peer1.org2.flxdu.cn is up-to-date
cli is up-to-date
peer0.org1.flxdu.cn is up-to-date
orderer.flxdu.cn is up-to-date
Creating peer2.org1.flxdu.cn ... done

至此,新节点 peer2.org1.flxdu.cn 已经启动。

新节点加入通道

此时该节点并没有加入到任何一个通道中,需要使用cli容器执行添加操作。

从 orderer 上拉取通道的创世区块:

bash
docker exec -e CORE_PEER_MSPCONFIGPATH=/opt/crypto-config/peerOrganizations/org1.flxdu.cn/users/Admin@org1.flxdu.cn/msp -e CORE_PEER_LOCALMSPID="Org1MSP" -e CORE_PEER_ADDRESS=peer2.org1.flxdu.cn:7051 cli peer channel fetch oldest hello.block -c hello -o orderer.flxdu.cn:7050

输出为

bash
2022-01-15 19:16:07.645 UTC 001f INFO [cli.common] readBlock -> Received block: 0

加入通道:

bash
docker exec -e CORE_PEER_MSPCONFIGPATH=/opt/crypto-config/peerOrganizations/org1.flxdu.cn/users/Admin@org1.flxdu.cn/msp -e CORE_PEER_LOCALMSPID="Org1MSP" -e CORE_PEER_ADDRESS=peer2.org1.flxdu.cn:7051 cli peer channel join -b hello.block -o orderer.flxdu.cn:7050

输出为

2022-01-15 19:19:00.131 UTC 001f INFO [channelCmd] executeJoin -> Successfully submitted proposal to join channel

安装链码

bash
docker exec -e CORE_PEER_MSPCONFIGPATH=/opt/crypto-config/peerOrganizations/org1.flxdu.cn/users/Admin@org1.flxdu.cn/msp -e CORE_PEER_LOCALMSPID="Org1MSP" -e CORE_PEER_ADDRESS=peer2.org1.flxdu.cn:7051 cli peer lifecycle chaincode install /opt/gopath/src/github.com/sacc/sacc.tar.gz

同一个通道内所有节点只需要对同样的链码实例化一次即可,该链码已经在之前的旧有节点初始化一次,所以新节点安装完链码后并不需要再次实例化,直接可以对链码进行调用。

调用链码

bash
docker exec -e CORE_PEER_MSPCONFIGPATH=/opt/crypto-config/peerOrganizations/org1.flxdu.cn/users/Admin@org1.flxdu.cn/msp -e CORE_PEER_LOCALMSPID="Org1MSP" -e CORE_PEER_ADDRESS=peer2.org1.flxdu.cn:7051 cli peer chaincode query -C hello -n sacc -c '{"Args":["query", "hello"]}'

可以看到输出成功即可,后续的设置/修改步骤也可以正常执行。