Build a stand-alone fabric1 based on Raft consensus 4 network

Build a stand-alone fabric1 based on Raft consensus 4 network environment

During this period, the fabric community has been updated to version 2.3, but most of the companies using fabric business still use fabric 1 Version 4. The purpose of writing this blog is to supplement the tool articles built by fabric.

1. Introduction to preparations for building fabric network environment

Fabric1 4. In the network environment, three orderer nodes are to be built to form a sequential consensus organization orderer; There are two organizations Org1 and Org2, in which each organization contains two peer nodes, as well as client nodes, couchdb, etc. see Table 1.1 for details:

fabric1.4 network nodes
orderer.example.com
orderer1.example.com
orderer2.example.com
peer0.org1.example.com
peer1.org1.example.com
peer0.org2.example.com
peer1.org2.example.com
cli
couchdb

First, set up the environment configuration of the host machine of the fabric network, including installing go language, installing docker, docker compose, etc. the specific installation steps are as follows:

  • Execute the command wget https://dl.google.com/go/go1.11.linux-amd64.tar.gz Download the go binary source package.
  • Execute the command tar -zxvf go1 11.linux-amd64. tar. GZ - C / usr / local / unzip.
  • Execute the command mkdir $HOME/code/go -p to create the project directory of go.
  • Execute the command VIM in the home directory Bashrc, and fill in the environment variable of go language at the end of the file, that is, add the configuration in the following code block to the end of the file.
export GOROOT="/usr/local/go"
export GOPATH="$HOME/code/go"
export GOBIN="$HOME/code/go/bin"
export PATH="$PATH:$GOROOT/bin:$GOPATH/bin"
  • Execute the command source Bashrc to make the newly configured environment variable take effect.
  • Execute the command go version to view the version of the current go language.
  • Execute the command go env to view the configuration environment of the current go language.
  • Check whether there is a in the home directory of the current host PIP directory, if not, execute the command MKDIR PIP and execute the command VIM pip Conf, write the contents of the following code block to PIP Conf file.
[global]
index-url=http://mirrors.aliyun.com/pypi/simple/

[install]
trusted-host=mirrors.aliyun.com
  • Execute the command PIP install docker compose to install docker compose (docker orchestration tool).
  • Execute the command docker compose version to view the currently installed version of docker compose tool.
  • Execute the command apt get install docker IO to install docker. If an error is reported, the docker cannot be located IO, execute the command apt get update first, and then install docker
  • Execute the command CD $gopath / SRC / GitHub COM / hyperledger enters the specified directory. The directory path is related to the binary source code tool pulled later. If the path is wrong, the binary tool pull will fail. Execute the command git clone https://github.com/hyperledger/fabric.git , pull down the fabric source code. If there is no git command in the host, download it by executing apt get install GIT.
  • Execute the command git clone https://github.com/hyperledger/fabric-samples.git Pull down fabric samples. Here are some official examples and fabric environment configurations in various modes.
  • Execute the command CD fabric samples / scripts, enter the scripts directory, and modify bootstrap The image version in SH is 1.4.0 - > 1.4.1, 0.4.14 - > 0.4.15. Building a fabric network under raft requires the latest docker image version. If the version is not new enough, the container will exit. For example, the order container will fail to recognize the etcdraft consensus.
  • Execute bootstrap The SH script is mainly used to pull the binary toolkit and the latest docker image. After the script is executed, the binary tools will be in the fabric samples / bin directory. You only need to execute the cp cryptogen configtxlator configtxgen /usr/local/bin command to use the tools globally.
  • If bootstrap cannot be executed successfully For the SH script, you need to pull the binary source code tool and docker image in two steps. First, for the binary tool, you can first enter the / fabric directory and execute git checkout - B v1 4.1, go to the current fabric source code branch v1 4.1. Execute make release to pull the binary source code tool. After execution, there will be a downloaded binary source code tool in the directory of fabric/release/linux-amd64/bin, and then execute the command CP cryptogen configtxgen configurator / usr / local / bin to set the tool to be used by the whole Bureau.
  • In addition, the latest image of docker can be pulled by shell script to execute the command vim docker_images.sh, fill in the following code block into the file, and then execute chmod +x docker_images.sh adds execution permission to the script file, and finally executes/ docker_images.sh will fabric1 4. Pull down the matched docker image.
#!/bin/bash

docker pull hyperledger/fabric-ca:1.4.1
docker tag hyperledger/fabric-ca:1.4.1 hyperledger/fabric-ca:latest

docker pull hyperledger/fabric-tools:1.4.1
docker tag hyperledger/fabric-tools:1.4.1 hyperledger/fabric-tools:latest

docker pull hyperledger/fabric-ccenv:1.4.1
docker tag hyperledger/fabric-ccenv:1.4.1 hyperledger/fabric-ccenv:latest

docker pull hyperledger/fabric-orderer:1.4.1 
docker tag hyperledger/fabric-orderer:1.4.1 hyperledger/fabric-orderer:latest

docker pull hyperledger/fabric-peer:1.4.1 
docker tag hyperledger/fabric-peer:1.4.1 hyperledger/fabric-peer:latest

docker pull hyperledger/fabric-javaenv:1.4.1
docker tag hyperledger/fabric-javaenv:1.4.1 hyperledger/fabric-javaenv:latest

docker pull hyperledger/fabric-zookeeper:0.4.15
docker tag hyperledger/fabric-zookeeper:0.4.15 hyperledger/fabric-zookeeper:latest

docker pull hyperledger/fabric-kafka:0.4.15 
docker tag hyperledger/fabric-kafka:0.4.15 hyperledger/fabric-kafka:latest

docker pull hyperledger/fabric-couchdb:0.4.15
docker tag hyperledger/fabric-couchdb:0.4.15 hyperledger/fabric-couchdb:latest

docker pull hyperledger/fabric-baseos:0.4.15 
docker tag hyperledger/fabric-baseos:0.4.15 hyperledger/fabric-baseos:latest

Here, we have completed the construction of the fabric network host environment. Now we go to the fabric network configuration section.

2. Multi machine fabric network deployment based on Raft consensus

This section is to configure each node in the fabric network, which mainly involves the node certificate, channel file, creation block file and dock er configuration file of each node in the fabric.

  • In the home directory or create the root directory of the fabric network project, execute MKDIR raft example.
  • Enter the root directory just created and create the static configuration file crypto config. Required to generate the certificates of each node of the fabric network Yaml, this file can be copied in fabric samples, or execute the command VI crypto config Yaml creates the file and copies the contents of the following code block into the file.
OrdererOrgs:
  - Name: Orderer
    Domain: example.com
    Specs:
      - Hostname: orderer
      - Hostname: orderer1
      - Hostname: orderer2
PeerOrgs:
  - Name: Org1
    Domain: org1.example.com
    EnableNodeOUs: true
    Template:
      Count: 2
    Users:
      Count: 2
  - Name: Org2
    Domain: org2.example.com
    EnableNodeOUs: true
    Template:
      Count: 2
    Users:
      Count: 2    

  • Execute the command cryptogen generate -- config/ crypto-config. Yaml generates certificates for each node in the current directory.
  • Next, configure the static configuration file configtx Yaml, this file can be copied in farbic samples, or execute the command VI configtx Yaml and fill in the following code blocks into the file.
---
Organizations:
    - &OrdererOrg
        Name: OrdererOrg
        ID: OrdererMSP
        MSPDir: crypto-config/ordererOrganizations/example.com/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.example.com/msp
        AnchorPeers:
            - Host: peer0.org1.example.com
              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')"
    - &Org2
        Name: Org2MSP
        ID: Org2MSP
        MSPDir: crypto-config/peerOrganizations/org2.example.com/msp
        AnchorPeers:
            - Host: peer0.org2.example.com
              Port: 9051
        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')"          
Capabilities:
    Channel: &ChannelCapabilities
        V1_3: true
    Orderer: &OrdererCapabilities
        V1_1: true
    Application: &ApplicationCapabilities
        V1_3: true
        V1_2: false
        V1_1: false
Application: &ApplicationDefaults
    Organizations:
    Policies:
        Readers:
            Type: ImplicitMeta
            Rule: "ANY Readers"
        Writers:
            Type: ImplicitMeta
            Rule: "ANY Writers"
        Admins:
            Type: ImplicitMeta
            Rule: "MAJORITY Admins"
    Capabilities:
        <<: *ApplicationCapabilities
Orderer: &OrdererDefaults
    OrdererType: solo
    Addresses:
        - orderer.example.com:7050
    BatchTimeout: 2s
    BatchSize:
        MaxMessageCount: 200
        AbsoluteMaxBytes: 2 MB
        PreferredMaxBytes: 512 KB
    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"
Channel: &ChannelDefaults
    Policies:
        Readers:
            Type: ImplicitMeta
            Rule: "ANY Readers"
        Writers:
            Type: ImplicitMeta
            Rule: "ANY Writers"
        Admins:
            Type: ImplicitMeta
            Rule: "MAJORITY Admins"
    Capabilities:
        <<: *ChannelCapabilities
Profiles:
    TwoOrgsOrdererGenesis:
        <<: *ChannelDefaults
        Capabilities:
            <<: *ChannelCapabilities
        Orderer:
            <<: *OrdererDefaults
            OrdererType: etcdraft
            EtcdRaft:
                Consenters:
                - Host: orderer.example.com
                  Port: 7050
                  ClientTLSCert: crypto-config/ordererOrganizations/example.com/orderers/orderer.example.com/tls/server.crt
                  ServerTLSCert: crypto-config/ordererOrganizations/example.com/orderers/orderer.example.com/tls/server.crt
                - Host: orderer1.example.com
                  Port: 8050
                  ClientTLSCert: crypto-config/ordererOrganizations/example.com/orderers/orderer1.example.com/tls/server.crt
                  ServerTLSCert: crypto-config/ordererOrganizations/example.com/orderers/orderer1.example.com/tls/server.crt
                - Host: orderer2.example.com
                  Port: 9050
                  ClientTLSCert: crypto-config/ordererOrganizations/example.com/orderers/orderer2.example.com/tls/server.crt
                  ServerTLSCert: crypto-config/ordererOrganizations/example.com/orderers/orderer2.example.com/tls/server.crt            
            Addresses:
                - orderer0.example.com:7050
                - orderer1.example.com:8050
                - orderer2.example.com:9050
            Organizations:
            - *OrdererOrg
            Capabilities:
                <<: *OrdererCapabilities
        Application:
            <<: *ApplicationDefaults
            Organizations:
            - <<: *OrdererOrg
        Consortiums:
            SampleConsortium:
                Organizations:
                    - *Org1
                    - *Org2
    TwoOrgsChannel:
        Consortium: SampleConsortium
        <<: *ChannelDefaults
        Application:
            <<: *ApplicationDefaults
            Organizations:
                - *Org1
                - *Org2
            Capabilities:
                <<: *ApplicationCapabilities
  • Next, you need to create a directory to place channel files, creation block files, etc. execute the command MKDIR channel artifacts to create a folder.
  • Generate the creation block file and execute the command configtxgen - profile twoorgorderergenesis - channelid systemchannel - outputblock/ channel-artifacts/genesis. Block generates the creation block of the system file.
  • Generate the application channel file and execute the command configtxgen - profile twoorgschannel - outputcreatechanneltx/ channel-artifacts/channel. TX - channelid testchnel generates a channel file for creating an application channel.
  • Generate the anchor node file of Org1 and execute the command configtxgen - profile twoorgschannel - outputanchorpeersupdate/ channel-artifacts/Org1MSPanchors. TX - channelid appchannel - asorg org1msp, generate Org1 to update the anchor node.
  • Generate the anchor node file of Org2 and execute the command configtxgen - profile twoorgschannel - outputanchorpeersupdate/ channel-artifacts/Org2MSPanchors. TX - channelid appchannel - asorg org2msp, generate Org2 to update the anchor node.
  • Next, you need to configure the docker configuration file of the orderer organization. This part will configure the configuration of the three orderer nodes under the orderer organization. Here, you need to configure two files. First, the first file is docker compose orderer Yaml, configure the non-public configuration of three orderer nodes here, and execute VI docker compose orderer Yaml and copy the contents of the following code block to a file.
version: '2'

volumes:
  orderer1.example.com:
  orderer2.example.com:
  orderer.example.com:

networks:
  byfn:

services:

  orderer1.example.com:
    extends:
      file: base/orderer-base.yaml
      service: orderer-base
    environment:
      - ORDERER_GENERAL_LISTENPORT=8050
    container_name: orderer1.example.com
    networks:
      - byfn
    volumes:
      - ./channel-artifacts/genesis.block:/var/hyperledger/orderer/orderer.genesis.block
      - ./crypto-config/ordererOrganizations/example.com/orderers/orderer1.example.com/msp:/var/hyperledger/orderer/msp
      - ./crypto-config/ordererOrganizations/example.com/orderers/orderer1.example.com/tls/:/var/hyperledger/orderer/tls
      - orderer1.example.com:/var/hyperledger/production/orderer
    ports:
      - 8050:8050

  orderer2.example.com:
    extends:
      file: base/orderer-base.yaml
      service: orderer-base
    environment:
      - ORDERER_GENERAL_LISTENPORT=9050
    container_name: orderer2.example.com
    networks:
      - byfn
    volumes:
      - ./channel-artifacts/genesis.block:/var/hyperledger/orderer/orderer.genesis.block
      - ./crypto-config/ordererOrganizations/example.com/orderers/orderer2.example.com/msp:/var/hyperledger/orderer/msp
      - ./crypto-config/ordererOrganizations/example.com/orderers/orderer2.example.com/tls/:/var/hyperledger/orderer/tls
      - orderer2.example.com:/var/hyperledger/production/orderer
    ports:
      - 9050:9050

  orderer.example.com:
    extends:
      file: base/orderer-base.yaml
      service: orderer-base
    environment:
      - ORDERER_GENERAL_LISTENPORT=7050
    container_name: orderer.example.com
    networks:
      - byfn
    volumes:
      - ./channel-artifacts/genesis.block:/var/hyperledger/orderer/orderer.genesis.block
      - ./crypto-config/ordererOrganizations/example.com/orderers/orderer.example.com/msp:/var/hyperledger/orderer/msp
      - ./crypto-config/ordererOrganizations/example.com/orderers/orderer.example.com/tls/:/var/hyperledger/orderer/tls
      - orderer.example.com:/var/hyperledger/production/orderer
    ports:
      - 7050:7050
  • The second file to configure orderer is orderer base Yaml, the public configuration of the orderer node is placed here. Because it belongs to the public basic configuration, it is recommended to create a base folder under the root directory raft example and execute the command VI orderer base Yaml and copy the contents of the following code block into the file.
version: '2'

services:
  orderer-base:
    image: hyperledger/fabric-orderer:latest
    environment:
      - FABRIC_LOGGING_SPEC=INFO
      - ORDERER_GENERAL_LISTENADDRESS=0.0.0.0
      - ORDERER_GENERAL_BOOTSTRAPMETHOD=file
      - ORDERER_GENERAL_BOOTSTRAPFILE=/var/hyperledger/orderer/orderer.genesis.block
      - ORDERER_GENERAL_LOCALMSPID=OrdererMSP
      - ORDERER_GENERAL_LOCALMSPDIR=/var/hyperledger/orderer/msp
      # enabled TLS
      - ORDERER_GENERAL_TLS_ENABLED=true
      - ORDERER_GENERAL_TLS_PRIVATEKEY=/var/hyperledger/orderer/tls/server.key
      - ORDERER_GENERAL_TLS_CERTIFICATE=/var/hyperledger/orderer/tls/server.crt
      - ORDERER_GENERAL_TLS_ROOTCAS=[/var/hyperledger/orderer/tls/ca.crt]
      - ORDERER_GENERAL_CLUSTER_CLIENTCERTIFICATE=/var/hyperledger/orderer/tls/server.crt
      - ORDERER_GENERAL_CLUSTER_CLIENTPRIVATEKEY=/var/hyperledger/orderer/tls/server.key
      - ORDERER_GENERAL_CLUSTER_ROOTCAS=[/var/hyperledger/orderer/tls/ca.crt]
    working_dir: /opt/gopath/src/github.com/hyperledger/fabric
    command: orderer
  • Next, you need to configure the peer nodes of Org1 and Org2. Here, you need to configure two files. Like order, the first file needs to configure different configuration information between peers; The second file needs to configure the public configuration information between peers. First, the first file docker compose peer Yaml, execute the command VI docker-compose-peer Yaml, paste the contents of the following code block into the file.
version: '2'

services:

  peer0.org1.example.com:
    container_name: peer0.org1.example.com
    extends:
      file: peer-base.yaml
      service: peer-base
    environment:
      - CORE_PEER_ID=peer0.org1.example.com
      - CORE_PEER_ADDRESS=peer0.org1.example.com:7051
      - CORE_PEER_LISTENADDRESS=0.0.0.0:7051
      - CORE_PEER_CHAINCODEADDRESS=peer0.org1.example.com:7052
      - CORE_PEER_CHAINCODELISTENADDRESS=0.0.0.0:7052
      - CORE_PEER_GOSSIP_USELEADERELECTION=true  
      - CORE_PEER_GOSSIP_BOOTSTRAP=peer1.org1.example.com:8051
      - CORE_PEER_GOSSIP_EXTERNALENDPOINT=peer0.org1.example.com:7051
      - CORE_PEER_LOCALMSPID=Org1MSP
      - CORE_LEDGER_STATE_STATEDATABASE=CouchDB
      - CORE_LEDGER_STATE_COUCHDBCONFIG_COUCHDBADDRESS=couchdb:5984  
      - CORE_LEDGER_STATE_COUCHDBCONFIG_USERNAME=
      - CORE_LEDGER_STATE_COUCHDBCONFIG_PASSWORD=    
    volumes:
        - /var/run/:/host/var/run/
        - ../crypto-config/peerOrganizations/org1.example.com/peers/peer0.org1.example.com/msp:/etc/hyperledger/fabric/msp
        - ../crypto-config/peerOrganizations/org1.example.com/peers/peer0.org1.example.com/tls:/etc/hyperledger/fabric/tls
        - peer0.org1.example.com:/var/hyperledger/production
    ports:
      - 7051:7051
    networks:
        - byfn
  peer1.org1.example.com:
    container_name: peer1.org1.example.com
    extends:
      file: peer-base.yaml
      service: peer-base
    environment:
      - CORE_PEER_ID=peer1.org1.example.com
      - CORE_PEER_ADDRESS=peer1.org1.example.com:8051
      - CORE_PEER_LISTENADDRESS=0.0.0.0:8051
      - CORE_PEER_CHAINCODEADDRESS=peer1.org1.example.com:8052
      - CORE_PEER_CHAINCODELISTENADDRESS=0.0.0.0:8052  
      - CORE_PEER_GOSSIP_EXTERNALENDPOINT=peer1.org1.example.com:8051
      - CORE_PEER_GOSSIP_BOOTSTRAP=peer0.org1.example.com:7051
      - CORE_PEER_LOCALMSPID=Org1MSP
      - CORE_LEDGER_STATE_STATEDATABASE=CouchDB
      - CORE_LEDGER_STATE_COUCHDBCONFIG_COUCHDBADDRESS=couchdb:5984  
      - CORE_LEDGER_STATE_COUCHDBCONFIG_USERNAME=
      - CORE_LEDGER_STATE_COUCHDBCONFIG_PASSWORD= 
    volumes:
        - /var/run/:/host/var/run/
        - ../crypto-config/peerOrganizations/org1.example.com/peers/peer1.org1.example.com/msp:/etc/hyperledger/fabric/msp
        - ../crypto-config/peerOrganizations/org1.example.com/peers/peer1.org1.example.com/tls:/etc/hyperledger/fabric/tls
        - peer1.org1.example.com:/var/hyperledger/production

    ports:
      - 8051:8051
    networks:
        - byfn
  peer0.org2.example.com:
    container_name: peer0.org2.example.com
    extends:
      file: peer-base.yaml
      service: peer-base
    environment:
      - CORE_PEER_ID=peer0.org2.example.com
      - CORE_PEER_ADDRESS=peer0.org2.example.com:9051
      - CORE_PEER_LISTENADDRESS=0.0.0.0:9051
      - CORE_PEER_CHAINCODEADDRESS=peer0.org2.example.com:9052
      - CORE_PEER_CHAINCODELISTENADDRESS=0.0.0.0:9052
      - CORE_PEER_GOSSIP_USELEADERELECTION=true  
      - CORE_PEER_GOSSIP_EXTERNALENDPOINT=peer0.org2.example.com:9051
      - CORE_PEER_GOSSIP_BOOTSTRAP=peer1.org2.example.com:10051
      - CORE_PEER_LOCALMSPID=Org2MSP
      - CORE_LEDGER_STATE_STATEDATABASE=CouchDB
      - CORE_LEDGER_STATE_COUCHDBCONFIG_COUCHDBADDRESS=couchdb:5984
      - CORE_LEDGER_STATE_COUCHDBCONFIG_USERNAME=
      - CORE_LEDGER_STATE_COUCHDBCONFIG_PASSWORD=
    volumes:
        - /var/run/:/host/var/run/
        - ../crypto-config/peerOrganizations/org2.example.com/peers/peer0.org2.example.com/msp:/etc/hyperledger/fabric/msp
        - ../crypto-config/peerOrganizations/org2.example.com/peers/peer0.org2.example.com/tls:/etc/hyperledger/fabric/tls
        - peer0.org2.example.com:/var/hyperledger/production
    ports:
      - 9051:9051
    networks:
        - byfn
  peer1.org2.example.com:
    container_name: peer1.org2.example.com
    extends:
      file: peer-base.yaml
      service: peer-base
    environment:
      - CORE_PEER_ID=peer1.org2.example.com
      - CORE_PEER_ADDRESS=peer1.org2.example.com:10051
      - CORE_PEER_LISTENADDRESS=0.0.0.0:10051
      - CORE_PEER_CHAINCODEADDRESS=peer1.org2.example.com:10052
      - CORE_PEER_CHAINCODELISTENADDRESS=0.0.0.0:10052
      - CORE_PEER_GOSSIP_EXTERNALENDPOINT=peer1.org2.example.com:10051
      - CORE_PEER_GOSSIP_BOOTSTRAP=peer0.org2.example.com:9051
      - CORE_PEER_LOCALMSPID=Org2MSP
      - CORE_LEDGER_STATE_STATEDATABASE=CouchDB
      - CORE_LEDGER_STATE_COUCHDBCONFIG_COUCHDBADDRESS=couchdb:5984
      - CORE_LEDGER_STATE_COUCHDBCONFIG_USERNAME=
      - CORE_LEDGER_STATE_COUCHDBCONFIG_PASSWORD=
    volumes:
        - /var/run/:/host/var/run/
        - ../crypto-config/peerOrganizations/org2.example.com/peers/peer1.org2.example.com/msp:/etc/hyperledger/fabric/msp
        - ../crypto-config/peerOrganizations/org2.example.com/peers/peer1.org2.example.com/tls:/etc/hyperledger/fabric/tls
        - peer1.org2.example.com:/var/hyperledger/production
    ports:
      - 10051:10051
    networks:
        - byfn
  • The second file for configuring peer is peer base Yaml, associate this file with order base Yaml is placed in the base directory together, and execute the command VI peer base Yaml, copy the contents of the following code block to the file.
version: '2'

services:
  peer-base:
    image: hyperledger/fabric-peer:latest
    environment:
      - CORE_VM_ENDPOINT=unix:///host/var/run/docker.sock
      # the following setting starts chaincode containers on the same
      # bridge network as the peers
      # https://docs.docker.com/compose/networking/
      - CORE_VM_DOCKER_HOSTCONFIG_NETWORKMODE=raft-example_byfn
      - GODEBUG=netdns=go  
      - FABRIC_LOGGING_SPEC=info
      #- FABRIC_LOGGING_SPEC=DEBUG
      - CORE_PEER_TLS_ENABLED=true
      - CORE_PEER_GOSSIP_USELEADERELECTION=true
      - CORE_PEER_GOSSIP_ORGLEADER=false
      - CORE_PEER_PROFILE_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
      # Allow more time for chaincode container to build on install.
      - CORE_CHAINCODE_EXECUTETIMEOUT=300s
    working_dir: /opt/gopath/src/github.com/hyperledger/fabric/peer
    command: peer node start
  • Next, configure the docker file of couchdb. couchdb is used as the index database of four peer s. Execute the command VI docker compose couchdb Yaml, copy the contents of the following code block to a file.
version: '2'

networks:
  byfn:

services:
  couchdb:
    container_name: couchdb
    image: couchdb:latest
    # Populate the COUCHDB_USER and COUCHDB_PASSWORD to set an admin user and password
    # for CouchDB.  This will prevent CouchDB from operating in an "Admin Party" mode.
    environment:
      - COUCHDB_USER=
      - COUCHDB_PASSWORD=
    # Comment/Uncomment the port mapping if you want to hide/expose the CouchDB service,
    # for example map it to utilize Fauxton User Interface in dev environments.
    ports:
      - "5984:5984"
    networks:
      - byfn
  • Finally, configure the client container for accessing the fabric network. The docker configuration of the container is actually the configuration of peers. The client container uses the identity of one of the peers to access the entire fabric network and executes the command VI docker compose cli Yaml, copy the contents of the following code block to a file.
version: '2'
cli:
    container_name: cli
    image: hyperledger/fabric-tools:latest
    tty: true
    stdin_open: true
    environment:
      - GOPATH=/opt/gopath
      - CORE_VM_ENDPOINT=unix:///host/var/run/docker.sock
      #- FABRIC_LOGGING_SPEC=DEBUG
      - FABRIC_LOGGING_SPEC=INFO
      - CORE_PEER_ID=cli
      - CORE_PEER_ADDRESS=peer0.org1.example.com:7051
      - CORE_PEER_LOCALMSPID=Org1MSP
      - CORE_PEER_TLS_ENABLED=true
      - CORE_PEER_TLS_CERT_FILE=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org1.example.com/peers/peer0.org1.example.com/tls/server.crt
      - CORE_PEER_TLS_KEY_FILE=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org1.example.com/peers/peer0.org1.example.com/tls/server.key
      - CORE_PEER_TLS_ROOTCERT_FILE=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org1.example.com/peers/peer0.org1.example.com/tls/ca.crt
      - CORE_PEER_MSPCONFIGPATH=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org1.example.com/users/Admin@org1.example.com/msp
    working_dir: /opt/gopath/src/github.com/hyperledger/fabric/peer
    command: /bin/bash
    volumes:
        - /var/run/:/host/var/run/
        - ./chaincode/:/opt/gopath/src/github.com/hyperledger/fabric-samples/chaincode
        - ./crypto-config:/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/
        - ./scripts:/opt/gopath/src/github.com/hyperledger/fabric/peer/scripts/
        - ./channel-artifacts:/opt/gopath/src/github.com/hyperledger/fabric/peer/channel-artifacts
    depends_on:
      - peer0.org1.example.com
      - peer1.org1.example.com
      - peer0.org2.example.com
      - peer1.org2.example.com
    networks:
      - byfn
  • Here, the docker configuration of each node in the fabric has been configured. Next, create a chain code folder in the root directory to store the chain code, and put the chain code in the chain code folder. The chain code I use this time is the chain code of the official instance, as shown in the following code block.
/*
Copyright IBM Corp. 2016 All Rights Reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
		 http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

package main

//WARNING - this chaincode's ID is hard-coded in chaincode_example04 to illustrate one way of
//calling chaincode from a chaincode. If this example is modified, chaincode_example04.go has
//to be modified as well with the new ID of chaincode_example02.
//chaincode_example05 show's how chaincode ID can be passed in as a parameter instead of
//hard-coding.

import (
	"fmt"
	"strconv"

	"github.com/hyperledger/fabric/core/chaincode/shim"
	pb "github.com/hyperledger/fabric/protos/peer"
)

// SimpleChaincode example simple Chaincode implementation
type SimpleChaincode struct {
}

func (t *SimpleChaincode) Init(stub shim.ChaincodeStubInterface) pb.Response {
	fmt.Println("ex02 Init")
	_, args := stub.GetFunctionAndParameters()
	var A, B string    // Entities
	var Aval, Bval int // Asset holdings
	var err error

	if len(args) != 4 {
		return shim.Error("Incorrect number of arguments. Expecting 4")
	}

	// Initialize the chaincode
	A = args[0]
	Aval, err = strconv.Atoi(args[1])
	if err != nil {
		return shim.Error("Expecting integer value for asset holding")
	}
	B = args[2]
	Bval, err = strconv.Atoi(args[3])
	if err != nil {
		return shim.Error("Expecting integer value for asset holding")
	}
	fmt.Printf("Aval = %d, Bval = %d\n", Aval, Bval)

	// Write the state to the ledger
	err = stub.PutState(A, []byte(strconv.Itoa(Aval)))
	if err != nil {
		return shim.Error(err.Error())
	}

	err = stub.PutState(B, []byte(strconv.Itoa(Bval)))
	if err != nil {
		return shim.Error(err.Error())
	}

	return shim.Success(nil)
}

func (t *SimpleChaincode) Invoke(stub shim.ChaincodeStubInterface) pb.Response {
	fmt.Println("ex02 Invoke")
	function, args := stub.GetFunctionAndParameters()
	if function == "invoke" {
		// Make payment of X units from A to B
		return t.invoke(stub, args)
	} else if function == "delete" {
		// Deletes an entity from its state
		return t.delete(stub, args)
	} else if function == "query" {
		// the old "Query" is now implemtned in invoke
		return t.query(stub, args)
	}

	return shim.Error("Invalid invoke function name. Expecting \"invoke\" \"delete\" \"query\"")
}

// Transaction makes payment of X units from A to B
func (t *SimpleChaincode) invoke(stub shim.ChaincodeStubInterface, args []string) pb.Response {
	var A, B string    // Entities
	var Aval, Bval int // Asset holdings
	var X int          // Transaction value
	var err error

	if len(args) != 3 {
		return shim.Error("Incorrect number of arguments. Expecting 3")
	}

	A = args[0]
	B = args[1]

	// Get the state from the ledger
	// TODO: will be nice to have a GetAllState call to ledger
	Avalbytes, err := stub.GetState(A)
	if err != nil {
		return shim.Error("Failed to get state")
	}
	if Avalbytes == nil {
		return shim.Error("Entity not found")
	}
	Aval, _ = strconv.Atoi(string(Avalbytes))

	Bvalbytes, err := stub.GetState(B)
	if err != nil {
		return shim.Error("Failed to get state")
	}
	if Bvalbytes == nil {
		return shim.Error("Entity not found")
	}
	Bval, _ = strconv.Atoi(string(Bvalbytes))

	// Perform the execution
	X, err = strconv.Atoi(args[2])
	if err != nil {
		return shim.Error("Invalid transaction amount, expecting a integer value")
	}
	Aval = Aval - X
	Bval = Bval + X
	fmt.Printf("Aval = %d, Bval = %d\n", Aval, Bval)

	// Write the state back to the ledger
	err = stub.PutState(A, []byte(strconv.Itoa(Aval)))
	if err != nil {
		return shim.Error(err.Error())
	}

	err = stub.PutState(B, []byte(strconv.Itoa(Bval)))
	if err != nil {
		return shim.Error(err.Error())
	}

	return shim.Success(nil)
}

// Deletes an entity from state
func (t *SimpleChaincode) delete(stub shim.ChaincodeStubInterface, args []string) pb.Response {
	if len(args) != 1 {
		return shim.Error("Incorrect number of arguments. Expecting 1")
	}

	A := args[0]

	// Delete the key from the state in ledger
	err := stub.DelState(A)
	if err != nil {
		return shim.Error("Failed to delete state")
	}

	return shim.Success(nil)
}

// query callback representing the query of a chaincode
func (t *SimpleChaincode) query(stub shim.ChaincodeStubInterface, args []string) pb.Response {
	var A string // Entities
	var err error

	if len(args) != 1 {
		return shim.Error("Incorrect number of arguments. Expecting name of the person to query")
	}

	A = args[0]

	// Get the state from the ledger
	Avalbytes, err := stub.GetState(A)
	if err != nil {
		jsonResp := "{\"Error\":\"Failed to get state for " + A + "\"}"
		return shim.Error(jsonResp)
	}

	if Avalbytes == nil {
		jsonResp := "{\"Error\":\"Nil amount for " + A + "\"}"
		return shim.Error(jsonResp)
	}

	jsonResp := "{\"Name\":\"" + A + "\",\"Amount\":\"" + string(Avalbytes) + "\"}"
	fmt.Printf("Query Response:%s\n", jsonResp)
	return shim.Success(Avalbytes)
}

func main() {
	err := shim.Start(new(SimpleChaincode))
	if err != nil {
		fmt.Printf("Error starting Simple chaincode: %s", err)
	}
}

  • Create a script to start the fabric network, create a directory scripts under the root directory to store the script, and execute the command VI up SH, copy the contents of the following code block to the file.
docker-compose -f ../docker-compose-orderer.yaml up -d
sleep 5
docker-compose -f ../docker-compose-couchdb.yaml up -d
docker-compose -f ../docker-compose-peer.yaml up -d
docker-compose -f ../docker-compose-cli.yaml up -d

-Create a script to close the fabric network. Similarly, in the scripts directory, execute the command VI down SH, copy the contents of the following code block to the file.

docker-compose -f ../docker-compose-orderer.yaml down --volume --remove-orphans
docker-compose -f ../docker-compose-couchdb.yaml down --volume --remove-orphans
docker-compose -f ../docker-compose-peer.yaml down --volume --remove-orphans
docker-compose -f ../docker-compose-cli.yaml down. --volume --remove-orphans
docker network prune
  • The last step is to add dns mapping for the container on the host, execute the command vi /etc/hosts, enter the host file, and copy the contents in the following code block to the last line of the file.
127.0.0.1 couchdb orderer.example.com orderer1.example.com orderer2.example.com peer0.org1.example.com peer1.org1.example.com peer0.org2.example.com peer1.org2.example.com cli 
  • Execute script up SH starts the whole fabric network, and then enters the part of interacting with the fabric network.

Using cli container to interact with fabric underlying network

This part interacts with fabric network through cli container, including channel creation, node joining channel, node installation chain code, invoke call chain code, etc.

  • First, enter the CLI container and execute the command docker exec -it cli bash to enter the CLI container. The default working path of the CLI container is / opt / gopath / SRC / GitHub COM / hyperledger / fabric / peer, which is on docker-compose-cli.com Working directory configured in yaml container.
  • First, create the application channel. This will use the previously generated channel file. This file has been mounted in the channel artifacts folder in the current working directory through the data volume. Execute the command peer channel create - O orderer exam ple. com:7050 -c testchannel -f ./ channel-artifacts/channel. tx --tls true --cafile /opt/gopath/src/github. com/hyperledger/fabric/peer/crypto/ordererOrganizations/example. com/orderers/orderer. example. com/msp/tlscacerts/tlsca. example. Com-cert.pem creates a channel. After successful creation, a block file with the channel name command will be generated in the current directory. For example, the currently generated file is testchanel block.
  • Next, update the anchor node of org1. This operation can be performed once on any node of each organization. Execute the command peer channel update - O order example. com:7050 -c testchannel -f ./ channel-artifacts/Org1MSPanchors. tx --tls true --cafile /opt/gopath/src/github. com/hyperledger/fabric/peer/crypto/ordererOrganizations/example. com/orderers/orderer. example. com/msp/tlscacerts/tlsca. example. com-cert.pem
  • Next, add the of the current peer node to the channel. The current node refers to the node configured in the c li environment variable. Here, it is in docker compose cli Peer0.0 is configured in yaml org1. example. COM, execute the command peer channel join - B testchnel Block, peer0 org1. example. The com node has joined the channel. You can view the channels joined by the current node by executing the command peer channel list.
  • Next, install the chain code for the current node and execute the command peer chaincode install - n MYCC - v 1.0 - L golang - P GitHub COM / chaincode, peer0 org1. example. Com node has installed the chain code.
  • Next, you need to perform the operations of adding channels and installing chain codes for other peer nodes. You need to switch the nodes by switching the environment variables of cli. The following code block has the settings for switching the environment variables of the other three nodes, which can be executed according to the rules.
#Switch to peer1 org1. example. Com node
export CORE_PEER_ADDRESS=peer1.org1.example.com:8051
export CORE_PEER_TLS_CERT_FILE=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org1.example.com/peers/peer1.org1.example.com/tls/server.crt
export CORE_PEER_TLS_KEY_FILE=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org1.example.com/peers/peer1.org1.example.com/tls/server.key
export CORE_PEER_TLS_ROOTCERT_FILE=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org1.example.com/peers/peer1.org1.example.com/tls/ca.crt
#Set peer1 org1. example. The com node is added to the channel
peer channel join -b testchannel.block
#Is peer1 org1. example. Com node installation chain code
peer chaincode install -n mycc -v 1.0 -l golang -p github.com/chaincode

#Switch to peer0 org2. example. Com node
export CORE_PEER_LOCALMSPID=Org2MSP
export CORE_PEER_ADDRESS=peer0.org2.example.com:9051
export CORE_PEER_TLS_CERT_FILE=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org2.example.com/peers/peer0.org2.example.com/tls/server.crt
export CORE_PEER_TLS_KEY_FILE=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org2.example.com/peers/peer0.org2.example.com/tls/server.key
export CORE_PEER_TLS_ROOTCERT_FILE=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org2.example.com/peers/peer0.org2.example.com/tls/ca.crt
export CORE_PEER_MSPCONFIGPATH=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org2.example.com/users/Admin@org2.example.com/msp
#Update the anchor node for org2
peer channel update -o orderer.example.com:7050 -c testchannel -f ./channel-artifacts/Org2MSPanchors.tx --tls true --cafile /opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/ordererOrganizations/example.com/orderers/orderer.example.com/msp/tlscacerts/tlsca.example.com-cert.pem
#Set peer0 org2. example. Com node join channel
peer channel join -b testchannel.block
#Is peer0 org2. example. Com node installation chain code
peer chaincode install -n mycc -v 1.0 -l golang -p github.com/chaincode

#Switch to peer1 org2. example. Com node
export CORE_PEER_ADDRESS=peer1.org2.example.com:10051
export CORE_PEER_TLS_CERT_FILE=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org2.example.com/peers/peer1.org2.example.com/tls/server.crt
export CORE_PEER_TLS_KEY_FILE=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org2.example.com/peers/peer1.org2.example.com/tls/server.key
export CORE_PEER_TLS_ROOTCERT_FILE=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org2.example.com/peers/peer1.org2.example.com/tls/ca.crt
#Set peer1 org2. example. The com node is added to the channel
peer channel join -b testchannel.block
#Is peer1 org2. example. Com node installation chain code
peer chaincode install -n mycc -v 1.0 -l golang -p github.com/chaincode
  • Here, all peers have been added to the channel and the chain code has been installed. Now instantiate the chain code. This operation can be performed on any node. Execute the command peer chaincode instantiate iate - O order example. com:7050 --tls true --cafile /opt/gopath/src/github. com/hyperledg er/fabric/peer/crypto/ordererOrganizations/example. com/orderers/orderer. example. com /msp/tlscacerts/tlsca. example. com-cert.pem -C testchannel -n mycc -l golang -v 1.0 -c '{"Arg s":["init","a","100","b","200"]}' -P 'AND("Org1MSP.peer")'
  • The following operation is to initialize the chain code. This operation corresponds to the init function in the chain code. Execute the command peer chaincode instantiate iate - O order example. com:7050 --tls true --cafile /opt/gopath/src/github. com/hyperledg er/fabric/peer/crypto/ordererOrganizations/example. com/orderers/orderer. example. com /msp/tlscacerts/tlsca. example. com-cert.pem -C testchannel -n mycc -l golang -v 1.0 -c '{"Arg s":["init","a","100","b","200"]}' -P 'AND("Org1MSP.peer")'.
  • Next, perform an invoke operation on the chain code, transfer 10 yuan from a to B, and execute the command peer chaincode invoke - O order example. com:7050 --tls true --cafile /opt/gopath/src /github. com/hyperledger/fabric/peer/crypto/ordererOrganizations/example. com/orderers/orderer0. example. com/msp/tlscacerts/tlsca. example. com-cert.pem -C testchannel -n myc c --peerAddresses peer0. org1. example. com:7051 --tlsRootCertFiles /opt/gopath/src/github. com/hyperledger/fabric/peer/crypto/peerOrganization/org1. example. com/peers/peer0. org1. example. com/tls/ca.crt -c '{"Args":["invoke","a","b","10"]}'.
  • Next, query the chain code to find out how much money a has left. Execute the command peer chaincode query - C testchnel - n MYCC - C '{args ": [" query "," a "]}'.

This is the Raft based fabric1 This is the end of the stand-alone network of 4. Welcome to discuss in the comment area or put forward your opinions on my blog.

Keywords: Blockchain

Added by brash on Mon, 10 Jan 2022 23:59:39 +0200