(Fabric Learning 7) Fabric2.4.x Blockchain Multi-machine Deployment (Re-order)

It’s been a long time since I’ve studied the blockchain. Today, I rebuilt the blockchain network and gained more new experiences.

I followed the up master DevX_ of station b to build it step by step. This is the video of the great god. It is concise and easy to understand and is in line with my current technology stack (java application + java chain code), and the code is open source, which is very suitable for novices to learn! !

DevX's Desperate World's Personal Space-DevX's Desperate World Personal Homepage-哔哩哔哩Video

Tested successfully. For the convenience of future study, record the construction process again.

1. Block chain network topology structure:

The requirements for this environment construction: 3 Orderer nodes to meet the raft consensus; 2 organizations: org1, org2; two peer nodes in both organizations.

But I am too lazy to open multiple virtual machines, so I simply use one virtual machine with multiple ports to do it, just divide the ports clearly.

The resource planning is as follows:

node  ip hosts port
cli-container 192.168.235.129 N/A N/A
orderer0 192.168.235.129 orderer0.example.com 7050:7050
8443:8443
orders 1 192.168.235.129 orderer1.example.com

8050:7050

8444:8443

orderer2 192.168.235.129 orderer2.example.com 9050:7050
8445:8553
org1.peer0 192.168.235.129 peer0.org1.example.com 7051:7051
7052:7052
9443:9443
org1.peer1 192.168.235.129 peer1.org1.example.com 8051:7051
8052:7052
9444:9443
org2.peer0 192.168.235.129 peer0.org2.example.com 9051:7051
9052:7052
9445:9443
org2.peer1 192.168.235.129 peer1.org2.example.com 10051:7051
10052:7052
9446:9443

 Then we can save the mapping relationship in the hosts folder:

Here is my virtual machine ip, just replace it with your own virtual machine ip, if there are multiple machines, replace it with the ip of multiple machines.

vim /etc/hosts

192.168.235.129 orderer0.example.com
192.168.235.129 orderer1.example.com
192.168.235.129 orderer2.example.com

192.168.235.129 peer0.org1.example.com
192.168.235.129 peer1.org1.example.com

192.168.235.129 peer0.org2.example.com
192.168.235.129 peer1.org2.example.com

2. Write and generate the identity certificate file

Configuration file for generating certificate files: crypto-config.yaml

Create a new folder named 3orderer-org1-2peer-org2-2peer-network:

mkdir 3orderer-org1-2peer-org2-2peer-network

For the convenience of subsequent operations, you can put the executable folder bin of fabric into it: (this is for convenience, if it is exported as an environment variable)

There is such a thing under fabric-samples, give him a copy.

 After you are done, go to the bin directory of your newly created folder and execute:

./cryptogen showtemplate > ../config/crypto-config.yaml

The template of the certificate file is generated, and the file is placed in the config folder, and then we modify it:

vim ../config/crypto-config.yaml

What needs to be modified here is that the HostName of Specs should be written on all three orderer nodes; EnableNodeOUs is set to true; the count of each organization template is set to 2, which means that there are two peer nodes.


# ---------------------------------------------------------------------------
# "OrdererOrgs" - Definition of organizations managing orderer nodes
# ---------------------------------------------------------------------------
OrdererOrgs:
  # ---------------------------------------------------------------------------
  # Orderer
  # ---------------------------------------------------------------------------
  - Name: Orderer
    Domain: example.com
    EnableNodeOUs: true

    # ---------------------------------------------------------------------------
    # "Specs" - See PeerOrgs below for complete description
    # ---------------------------------------------------------------------------
    Specs:
      - Hostname: orderer0
      - Hostname: orderer1
      - Hostname: orderer2
        SANS:
             - "*"
             - "192.168.235.129"   

# ---------------------------------------------------------------------------
# "PeerOrgs" - Definition of organizations managing peer nodes
# ---------------------------------------------------------------------------
PeerOrgs:
  # ---------------------------------------------------------------------------
  # Org1
  # ---------------------------------------------------------------------------
  - Name: Org1
    Domain: org1.example.com
    EnableNodeOUs: true

    # ---------------------------------------------------------------------------
    # "CA"
    # ---------------------------------------------------------------------------
    # Uncomment this section to enable the explicit definition of the CA for this
    # organization.  This entry is a Spec.  See "Specs" section below for details.
    # ---------------------------------------------------------------------------
    # CA:
    #    Hostname: ca # implicitly ca.org1.example.com
    #    Country: US
    #    Province: California
    #    Locality: San Francisco
    #    OrganizationalUnit: Hyperledger Fabric
    #    StreetAddress: address for org # default nil
    #    PostalCode: postalCode for org # default nil

    # ---------------------------------------------------------------------------
    # "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.
    #   - SANS:       (Optional) Specifies one or more Subject Alternative Names
    #                 to be set in the resulting x509. Accepts template
    #                 variables {
   
   {.Hostname}}, {
   
   {.Domain}}, {
   
   {.CommonName}}. IP
    #                 addresses provided here will be properly recognized. Other
    #                 values will be taken as DNS names.
    #                 NOTE: Two implicit entries are created for you:
    #                     - {
   
   { .CommonName }}
    #                     - {
   
   { .Hostname }}
    # ---------------------------------------------------------------------------
    # Specs:
    #   - Hostname: foo # implicitly "foo.org1.example.com"
    #     CommonName: foo27.org5.example.com # overrides Hostname-based FQDN set above
    #     SANS:
    #       - "bar.{
   
   {.Domain}}"
    #       - "altfoo.{
   
   {.Domain}}"
    #       - "{
   
   {.Hostname}}.org6.net"
    #       - 172.16.10.31
    #   - 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
      # Start: 5
      # Hostname: {
   
   {.Prefix}}{
   
   {.Index}} # default
      # SANS:
      #   - "{
   
   {.Hostname}}.alt.{
   
   {.Domain}}"
      SANS:
           - "*"
           - "192.168.235.129"

    # ---------------------------------------------------------------------------
    # "Users"
    # ---------------------------------------------------------------------------
    # Count: The number of user accounts _in addition_ to Admin
    # ---------------------------------------------------------------------------
    Users:
      Count: 1

  # ---------------------------------------------------------------------------
  # Org2: See "Org1" for full specification
  # ---------------------------------------------------------------------------
  - Name: Org2
    Domain: org2.example.com
    EnableNodeOUs: true
    Template:
      Count: 2
      SANS:
        - "*"
        - "192.168.235.139"
    Users:
      Count: 1

After editing the file, use the cryptogen tool under the bin file to generate a certificate according to the crypto-config.yaml configuration file:

./cryptogen generate --config=../config/crypto-config.yaml --output ../crypto-config

If you modify the configuration, you can also extend the subcommand to update the crypto-config directory:

./cryptogen extend --config=../crypto-config.yaml --input ../crypto-config

After the end, check whether the identity certificate file is really generated, and confirm whether the node information is complete and there is no omission.

tree ../crypto-config

3. Write and generate channel initial blocks, channel files, and anchor node configuration update files

Generate a configuration file for the channel file: configtx.yaml

We can use the configtxgen tool under the bin file shelf to generate network configuration and topology information.

Edit the configtx.yaml file:

The main thing to change here is that some file directories must be correct, such as MSPDir, etc.; OrdererEndpoints, Addresses (the port number of the Order node), and the tls certificate directory of each orderer node that completed the raft consensus.

Note: The anchor nodes of org1 and org2 I defined here are their peer0 nodes.

# Copyright IBM Corp. All Rights Reserved.

#

# SPDX-License-Identifier: Apache-2.0

#



---

################################################################################

#

#   ORGANIZATIONS

#

#   This section defines the organizational identities that can be referenced

#   in the configuration profiles.

#

################################################################################

Organizations:



    # SampleOrg defines an MSP using the sampleconfig. It should never be used

    # in production but may be used as a template for other definitions.

    - &OrdererOrg

        # Name is the key by which this org will be referenced in channel

        # configuration transactions.

        # Name can include alphanumeric characters as well as dots and dashes.

        Name: OrdererOrg



        # SkipAsForeign can be set to true for org definitions which are to be

        # inherited from the orderer system channel during channel creation.  This

        # is especially useful when an admin of a single org without access to the

        # MSP directories of the other orgs wishes to create a channel.  Note

        # this property must always be set to false for orgs included in block

        # creation.

        SkipAsForeign: false



        # ID is the key by which this org's MSP definition will be referenced.

        # ID can include alphanumeric characters as well as dots and dashes.

        ID: OrdererMSP



        # MSPDir is the filesystem path which contains the MSP configuration.

        MSPDir: ../crypto-config/ordererOrganizations/example.com/msp



        # Policies defines the set of policies at this level of the config tree

        # For organization policies, their canonical path is usually

        #   /Channel/<Application|Orderer>/<OrgName>/<PolicyName>

        Policies:

            Readers:

                Type: Signature

                Rule: "OR('OrdererMSP.member')"

                # If your MSP is configured with the new NodeOUs, you might

                # want to use a more specific rule like the following:

                # Rule: "OR('SampleOrg.admin', 'SampleOrg.peer', 'SampleOrg.client')"

            Writers:

                Type: Signature

                Rule: "OR('OrdererMSP.member')"

                # If your MSP is configured with the new NodeOUs, you might

                # want to use a more specific rule like the following:

                # Rule: "OR('SampleOrg.admin', 'SampleOrg.client')"

            Admins:

                Type: Signature

                Rule: "OR('OrdererMSP.admin')"

            Endorsement:

                Type: Signature

                Rule: "OR('OrdererMSP.member')"



        # OrdererEndpoints is a list of all orderers this org runs which clients

        # and peers may to connect to to push transactions and receive blocks respectively.

        OrdererEndpoints:

            - "orderer0.example.com:7050"

            - "orderer1.example.com:8050"

            - "orderer2.example.com:9050"



        # AnchorPeers defines the location of peers which can be used for

        # cross-org gossip communication.

        #

        # NOTE: this value should only be set when using the deprecated

        # `configtxgen --outputAnchorPeersUpdate` command. It is recommended

        # to instead use the channel configuration update process to set the

        # anchor peers for each organization.

        #AnchorPeers:

        #    - Host: 127.0.0.1

        #      Port: 7051



    - &Org1



        Name: Org1MSP

        ID: Org1MSP

        MSPDir: ../crypto-config/peerOrganizations/org1.example.com/msp

        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')"

        AnchorPeers:

            - Host: peer0.org1.example.com

              Port: 7051





    - &Org2



        Name: Org2MSP

        ID: Org2MSP

        MSPDir: ../crypto-config/peerOrganizations/org2.example.com/msp

        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')"

        AnchorPeers:

            - Host: peer0.org2.example.com

              Port: 9051





################################################################################

#

#   CAPABILITIES

#

#   This section defines the capabilities of fabric network. This is a new

#   concept as of v1.1.0 and should not be utilized in mixed networks with

#   v1.0.x peers and orderers.  Capabilities define features which must be

#   present in a fabric binary for that binary to safely participate in the

#   fabric network.  For instance, if a new MSP type is added, newer binaries

#   might recognize and validate the signatures from this type, while older

#   binaries without this support would be unable to validate those

#   transactions.  This could lead to different versions of the fabric binaries

#   having different world states.  Instead, defining a capability for a channel

#   informs those binaries without this capability that they must cease

#   processing transactions until they have been upgraded.  For v1.0.x if any

#   capabilities are defined (including a map with all capabilities turned off)

#   then the v1.0.x peer will deliberately crash.

#

################################################################################

Capabilities:

    # Channel capabilities apply to both the orderers and the peers and must be

    # supported by both.

    # Set the value of the capability to true to require it.

    Channel: &ChannelCapabilities

        # V2.0 for Channel is a catchall flag for behavior which has been

        # determined to be desired for all orderers and peers running at the v2.0.0

        # level, but which would be incompatible with orderers and peers from

        # prior releases.

        # Prior to enabling V2.0 channel capabilities, ensure that all

        # orderers and peers on a channel are at v2.0.0 or later.

        V2_0: true



    # Orderer capabilities apply only to the orderers, and may be safely

    # used with prior release peers.

    # Set the value of the capability to true to require it.

    Orderer: &OrdererCapabilities

        # V1.1 for Orderer is a catchall flag for behavior which has been

        # determined to be desired for all orderers running at the v1.1.x

        # level, but which would be incompatible with orderers from prior releases.

        # Prior to enabling V2.0 orderer capabilities, ensure that all

        # orderers on a channel are at v2.0.0 or later.

        V2_0: true



    # Application capabilities apply only to the peer network, and may be safely

    # used with prior release orderers.

    # Set the value of the capability to true to require it.

    Application: &ApplicationCapabilities

        # V2.0 for Application enables the new non-backwards compatible

        # features and fixes of fabric v2.0.

        # Prior to enabling V2.0 orderer capabilities, ensure that all

        # orderers on a channel are at v2.0.0 or later.

        V2_0: true



################################################################################

#

#   APPLICATION

#

#   This section defines the values to encode into a config transaction or

#   genesis block for application-related parameters.

#

################################################################################

Application: &ApplicationDefaults

    ACLs: &ACLsDefault

        # This section provides defaults for policies for various resources

        # in the system. These "resources" could be functions on system chaincodes

        # (e.g., "GetBlockByNumber" on the "qscc" system chaincode) or other resources

        # (e.g.,who can receive Block events). This section does NOT specify the resource's

        # definition or API, but just the ACL policy for it.

        #

        # Users can override these defaults with their own policy mapping by defining the

        # mapping under ACLs in their channel definition



        #---New Lifecycle System Chaincode (_lifecycle) function to policy mapping for access control--#



        # ACL policy for _lifecycle's "CheckCommitReadiness" function

        _lifecycle/CheckCommitReadiness: /Channel/Application/Writers



        # ACL policy for _lifecycle's "CommitChaincodeDefinition" function

        _lifecycle/CommitChaincodeDefinition: /Channel/Application/Writers



        # ACL policy for _lifecycle's "QueryChaincodeDefinition" function

        _lifecycle/QueryChaincodeDefinition: /Channel/Application/Writers



        # ACL policy for _lifecycle's "QueryChaincodeDefinitions" function

        _lifecycle/QueryChaincodeDefinitions: /Channel/Application/Writers



        #---Lifecycle System Chaincode (lscc) function to policy mapping for access control---#



        # ACL policy for lscc's "getid" function

        lscc/ChaincodeExists: /Channel/Application/Readers



        # ACL policy for lscc's "getdepspec" function

        lscc/GetDeploymentSpec: /Channel/Application/Readers



        # ACL policy for lscc's "getccdata" function

        lscc/GetChaincodeData: /Channel/Application/Readers



        # ACL Policy for lscc's "getchaincodes" function

        lscc/GetInstantiatedChaincodes: /Channel/Application/Readers



        #---Query System Chaincode (qscc) function to policy mapping for access control---#



        # ACL policy for qscc's "GetChainInfo" function

        qscc/GetChainInfo: /Channel/Application/Readers



        # ACL policy for qscc's "GetBlockByNumber" function

        qscc/GetBlockByNumber: /Channel/Application/Readers



        # ACL policy for qscc's  "GetBlockByHash" function

        qscc/GetBlockByHash: /Channel/Application/Readers



        # ACL policy for qscc's "GetTransactionByID" function

        qscc/GetTransactionByID: /Channel/Application/Readers



        # ACL policy for qscc's "GetBlockByTxID" function

        qscc/GetBlockByTxID: /Channel/Application/Readers



        #---Configuration System Chaincode (cscc) function to policy mapping for access control---#



        # ACL policy for cscc's "GetConfigBlock" function

        cscc/GetConfigBlock: /Channel/Application/Readers



        # ACL policy for cscc's "GetChannelConfig" function

        cscc/GetChannelConfig: /Channel/Application/Readers



        #---Miscellaneous peer function to policy mapping for access control---#



        # ACL policy for invoking chaincodes on peer

        peer/Propose: /Channel/Application/Writers



        # ACL policy for chaincode to chaincode invocation

        peer/ChaincodeToChaincode: /Channel/Application/Writers



        #---Events resource to policy mapping for access control###---#



        # ACL policy for sending block events

        event/Block: /Channel/Application/Readers



        # ACL policy for sending filtered block events

        event/FilteredBlock: /Channel/Application/Readers



    # Organizations lists the orgs participating on the application side of the

    # network.

    Organizations:



    # Policies defines the set of policies at this level of the config tree

    # For Application policies, their canonical path is

    #   /Channel/Application/<PolicyName>

    Policies: &ApplicationDefaultPolicies

        LifecycleEndorsement:

            Type: ImplicitMeta

            Rule: "MAJORITY Endorsement"

        Endorsement:

            Type: ImplicitMeta

            Rule: "MAJORITY Endorsement"

        Readers:

            Type: ImplicitMeta

            Rule: "ANY Readers"

        Writers:

            Type: ImplicitMeta

            Rule: "ANY Writers"

        Admins:

            Type: ImplicitMeta

            Rule: "MAJORITY Admins"



    # Capabilities describes the application level capabilities, see the

    # dedicated Capabilities section elsewhere in this file for a full

    # description

    Capabilities:

        <<: *ApplicationCapabilities



################################################################################

#

#   ORDERER

#

#   This section defines the values to encode into a config transaction or

#   genesis block for orderer related parameters.

#

################################################################################

Orderer: &OrdererDefaults



    # Orderer Type: The orderer implementation to start.

    # Available types are "solo", "kafka" and "etcdraft".

    OrdererType: etcdraft



    # Addresses used to be the list of orderer addresses that clients and peers

    # could connect to.  However, this does not allow clients to associate orderer

    # addresses and orderer organizations which can be useful for things such

    # as TLS validation.  The preferred way to specify orderer addresses is now

    # to include the OrdererEndpoints item in your org definition

    Addresses:

        - orderer0.example.com:7050

        - orderer1.example.com:8050

        - orderer2.example.com:9050



    # Batch Timeout: The amount of time to wait before creating a batch.

    BatchTimeout: 2s



    # Batch Size: Controls the number of messages batched into a block.

    # The orderer views messages opaquely, but typically, messages may

    # be considered to be Fabric transactions.  The 'batch' is the group

    # of messages in the 'data' field of the block.  Blocks will be a few kb

    # larger than the batch size, when signatures, hashes, and other metadata

    # is applied.

    BatchSize:



        # Max Message Count: The maximum number of messages to permit in a

        # batch.  No block will contain more than this number of messages.

        MaxMessageCount: 500



        # Absolute Max Bytes: The absolute maximum number of bytes allowed for

        # the serialized messages in a batch. The maximum block size is this value

        # plus the size of the associated metadata (usually a few KB depending

        # upon the size of the signing identities). Any transaction larger than

        # this value will be rejected by ordering.

        # It is recommended not to exceed 49 MB, given the default grpc max message size of 100 MB

        # configured on orderer and peer nodes (and allowing for message expansion during communication).

        AbsoluteMaxBytes: 10 MB



        # Preferred Max Bytes: The preferred maximum number of bytes allowed

        # for the serialized messages in a batch. Roughly, this field may be considered

        # the best effort maximum size of a batch. A batch will fill with messages

        # until this size is reached (or the max message count, or batch timeout is

        # exceeded).  If adding a new message to the batch would cause the batch to

        # exceed the preferred max bytes, then the current batch is closed and written

        # to a block, and a new batch containing the new message is created.  If a

        # message larger than the preferred max bytes is received, then its batch

        # will contain only that message.  Because messages may be larger than

        # preferred max bytes (up to AbsoluteMaxBytes), some batches may exceed

        # the preferred max bytes, but will always contain exactly one transaction.

        PreferredMaxBytes: 2 MB



    # Max Channels is the maximum number of channels to allow on the ordering

    # network. When set to 0, this implies no maximum number of channels.

    MaxChannels: 0



    Kafka:

        # Brokers: A list of Kafka brokers to which the orderer connects. Edit

        # this list to identify the brokers of the ordering service.

        # NOTE: Use IP:port notation.

        Brokers:

            - kafka0:9092

            - kafka1:9092

            - kafka2:9092



    # EtcdRaft defines configuration which must be set when the "etcdraft"

    # orderertype is chosen.

    EtcdRaft:

        # The set of Raft replicas for this network. For the etcd/raft-based

        # implementation, we expect every replica to also be an OSN. Therefore,

        # a subset of the host:port items enumerated in this list should be

        # replicated under the Orderer.Addresses key above.

        Consenters:

            - Host: orderer0.example.com

              Port: 7050

              ClientTLSCert: ../crypto-config/ordererOrganizations/example.com/orderers/orderer0.example.com/tls/server.crt

              ServerTLSCert: ../crypto-config/ordererOrganizations/example.com/orderers/orderer0.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



        # Options to be specified for all the etcd/raft nodes. The values here

        # are the defaults for all new channels and can be modified on a

        # per-channel basis via configuration updates.

        Options:

            # TickInterval is the time interval between two Node.Tick invocations.

            TickInterval: 500ms



            # ElectionTick is the number of Node.Tick invocations that must pass

            # between elections. That is, if a follower does not receive any

            # message from the leader of current term before ElectionTick has

            # elapsed, it will become candidate and start an election.

            # ElectionTick must be greater than HeartbeatTick.

            ElectionTick: 10



            # HeartbeatTick is the number of Node.Tick invocations that must

            # pass between heartbeats. That is, a leader sends heartbeat

            # messages to maintain its leadership every HeartbeatTick ticks.

            HeartbeatTick: 1



            # MaxInflightBlocks limits the max number of in-flight append messages

            # during optimistic replication phase.

            MaxInflightBlocks: 5



            # SnapshotIntervalSize defines number of bytes per which a snapshot is taken

            SnapshotIntervalSize: 16 MB



    # Organizations lists the orgs participating on the orderer side of the

    # network.

    Organizations:



    # Policies defines the set of policies at this level of the config tree

    # For Orderer policies, their canonical path is

    #   /Channel/Orderer/<PolicyName>

    Policies:

        Readers:

            Type: ImplicitMeta

            Rule: "ANY Readers"

        Writers:

            Type: ImplicitMeta

            Rule: "ANY Writers"

        Admins:

            Type: ImplicitMeta

            Rule: "MAJORITY Admins"

        # BlockValidation specifies what signatures must be included in the block

        # from the orderer for the peer to validate it.

        BlockValidation:

            Type: ImplicitMeta

            Rule: "ANY Writers"



    # Capabilities describes the orderer level capabilities, see the

    # dedicated Capabilities section elsewhere in this file for a full

    # description

    Capabilities:

        <<: *OrdererCapabilities



################################################################################

#

#   CHANNEL

#

#   This section defines the values to encode into a config transaction or

#   genesis block for channel related parameters.

#

################################################################################

Channel: &ChannelDefaults

    # Policies defines the set of policies at this level of the config tree

    # For Channel policies, their canonical path is

    #   /Channel/<PolicyName>

    Policies:

        # Who may invoke the 'Deliver' API

        Readers:

            Type: ImplicitMeta

            Rule: "ANY Readers"

        # Who may invoke the 'Broadcast' API

        Writers:

            Type: ImplicitMeta

            Rule: "ANY Writers"

        # By default, who may modify elements at this config level

        Admins:

            Type: ImplicitMeta

            Rule: "MAJORITY Admins"





    # Capabilities describes the channel level capabilities, see the

    # dedicated Capabilities section elsewhere in this file for a full

    # description

    Capabilities:

        <<: *ChannelCapabilities



################################################################################

#

#   PROFILES

#

#   Different configuration profiles may be encoded here to be specified as

#   parameters to the configtxgen tool. The profiles which specify consortiums

#   are to be used for generating the orderer genesis block. With the correct

#   consortium members defined in the orderer genesis block, channel creation

#   requests may be generated with only the org member names and a consortium

#   name.

#

################################################################################

Profiles:



     TwoOrgsOrdererGenesis:

        <<: *ChannelDefaults

        Orderer:

            <<: *OrdererDefaults

            Organizations:

                - *OrdererOrg

            Capabilities:

                <<: *OrdererCapabilities

        Consortiums:

            SampleConsortium:

                Organizations:

                    - *Org1

                    - *Org2

     TwoOrgsChannel:

        Consortium: SampleConsortium

        <<: *ChannelDefaults

        Application:

            <<: *ApplicationDefaults

            Organizations:

                - *Org1

                - *Org2

            Capabilities:

                <<: *ApplicationCapabilities

Generate the genesis block:

Note: The -channelID here refers to the system channel, which is different from the channel where the peer is located below. The system channel is named fabric-channel

./configtxgen -configPath ../config  -profile TwoOrgsOrdererGenesis -channelID fabric-channel -outputBlock ../channel-artifacts/orderer.genesis.block

The directory after operation is as follows: 

channel-artifacts/
└── orderer.genesis.block

Generate channel files:

Note: I named the channel file here as businesschannel, you can change it yourself, and you need to use this name when creating the channel later.

./configtxgen -configPath ../config  -profile TwoOrgsChannel  -channelID businesschannel -outputCreateChannelTx ../channel-artifacts/businesschannel.tx

The directory after operation is as follows: 

channel-artifacts/
├── businesschannel.tx
└── orderer.genesis.block

Generate the anchor node configuration update file:

./configtxgen -configPath ../config  -profile TwoOrgsChannel -channelID businesschannel -asOrg Org1MSP -outputAnchorPeersUpdate ../channel-artifacts/Org1MSPanchors.tx
./configtxgen -configPath ../config  -profile TwoOrgsChannel -channelID businesschannel -asOrg Org2MSP -outputAnchorPeersUpdate ../channel-artifacts/Org2MSPanchors.tx

The directory after operation is as follows: 

channel-artifacts/
├── businesschannel.tx
├── orderer.genesis.block
├── Org1MSPanchors.tx
└── Org2MSPanchors.tx

4. Deploy the orderer node

 Three different docker-compose configuration files need to be written. Here we first write the file of the docker container that starts the orderer, named docker-compose-3orderer.yaml.

Edit docker-compose-3orderer.yaml:

The main thing here is to change the ip address to the corresponding ip address, and change the port number to the port number set above.

version: '2.0'

services:

    cli:
        image: hyperledger/fabric-tools:2.4.1
        restart: always
        container_name: fabric-cli
        hostname: fabric-cli
        tty: true
        extra_hosts:
            - "orderer0.example.com:192.168.235.129"
            - "orderer1.example.com:192.168.235.129"
            - "orderer2.example.com:192.168.235.129"
            - "peer0.org1.example.com:192.168.235.129"
            - "peer1.org1.example.com:192.168.235.129"
            - "peer0.org2.example.com:192.168.235.129"
            - "peer1.org2.example.com:192.168.235.129"
        environment:
            - CORE_PEER_ID=fabric-cli
            - CORE_PEER_ADDRESS=peer0.org1.example.com:7051 # default to operate on peer0.org1
            - CORE_PEER_LOCALMSPID=Org1MSP
            - CORE_PEER_TLS_CERT_FILE=/etc/hyperledger/fabric/crypto-config/peerOrganizations/org1.example.com/peers/peer0.org1.example.com/tls/server.crt
            - CORE_PEER_TLS_KEY_FILE=/etc/hyperledger/fabric/crypto-config/peerOrganizations/org1.example.com/peers/peer0.org1.example.com/tls/server.key
            - CORE_PEER_TLS_ROOTCERT_FILE=/etc/hyperledger/fabric/crypto-config/peerOrganizations/org1.example.com/peers/peer0.org1.example.com/tls/ca.crt
            - CORE_PEER_MSPCONFIGPATH=/etc/hyperledger/fabric/crypto-config/peerOrganizations/org1.example.com/users/[email protected]/msp
            - FABRIC_LOGGING_SPEC=DEBUG
            - FABRIC_LOGGING_FORMAT=%{color}[%{id:03x} %{time:01-02 15:04:05.00 MST}] [%{module}] %{shortfunc} -> %{level:.4s}%{color:reset} %{message}
            - CORE_PEER_TLS_ENABLED=true  # to enable TLS, change to true
            - ORDERER_CA=/etc/hyperledger/fabric/crypto-config/ordererOrganizations/example.com/orderers/orderer0.example.com/msp/tlscacerts/tlsca.example.com-cert.pem
        volumes:
            - ./config/crypto-config.yaml:/etc/hyperledger/fabric/crypto-config.yaml
            - ./config/configtx.yaml:/etc/hyperledger/fabric/configtx.yaml
            - ./crypto-config:/etc/hyperledger/fabric/crypto-config
            - ./channel-artifacts:/tmp/channel-artifacts
            - ./chaincodes:/etc/hyperledger/fabric/chaincodes
        working_dir: /opt/gopath/src/github.com/hyperledger/fabric/peer
        command: bash -c 'cd /tmp; source scripts/func.sh; while true; do sleep 20170504; done'


    orderer0.example.com:  # There can be multiple orderers
        image: hyperledger/fabric-orderer:2.4.1
        restart: always
        container_name: orderer0.example.com
        hostname: orderer0.example.com
        ports:
            - 7050:7050
            - 8443:8443
        extra_hosts:
            - "orderer0.example.com:192.168.235.129"
            - "orderer1.example.com:192.168.235.129"
            - "orderer2.example.com:192.168.235.129"
            - "peer0.org1.example.com:192.168.235.129"
            - "peer1.org1.example.com:192.168.235.129"
            - "peer0.org2.example.com:192.168.235.129"
            - "peer1.org2.example.com:192.168.235.129"
        environment:
            - FABRIC_LOGGING_FORMAT="%{color}%{time:2006-01-02 15:04:05.000 MST} [%{module}] %{shortfunc} -> %{level:.4s} %{id:03x}%{color:reset} %{message}"
            - ORDERER_GENERAL_LISTENADDRESS=0.0.0.0 # default: 127.0.0.1
            - ORDERER_GENERAL_LISTENPORT=7050
            - ORDERER_GENERAL_GENESISMETHOD=file # default: provisional
            - ORDERER_GENERAL_BOOTSTRAPFILE=/etc/hyperledger/fabric/orderer.genesis.block # by default, all materials should be put under $FABRIC_CFG_PATH, which defaults to /etc/hyperledger/fabric
            - ORDERER_GENERAL_LOCALMSPID=OrdererMSP # default: DEFAULT
            - ORDERER_GENERAL_LOCALMSPDIR=/etc/hyperledger/fabric/msp
            - ORDERER_GENERAL_LEDGERTYPE=file
            #- ORDERER_GENERAL_LEDGERTYPE=json  # default: file
            - ORDERER_OPERATIONS_LISTENADDRESS=0.0.0.0:8443  # operation RESTful API
            - ORDERER_METRICS_PROVIDER=prometheus  # prometheus will pull metrics from orderer via /metrics RESTful API
            #- ORDERER_RAMLEDGER_HISTORY_SIZE=100  #only useful when use ram ledger
            # enabled TLS
            - ORDERER_GENERAL_TLS_ENABLED=true # default: false
            - ORDERER_GENERAL_TLS_PRIVATEKEY=/etc/hyperledger/fabric/tls/server.key
            - ORDERER_GENERAL_TLS_CERTIFICATE=/etc/hyperledger/fabric/tls/server.crt
            - ORDERER_GENERAL_TLS_ROOTCAS=[/etc/hyperledger/fabric/tls/ca.crt]
            # Only required by raft mode
            - ORDERER_GENERAL_CLUSTER_CLIENTPRIVATEKEY=/etc/hyperledger/fabric/tls/server.key
            - ORDERER_GENERAL_CLUSTER_CLIENTCERTIFICATE=/etc/hyperledger/fabric/tls/server.crt
            - ORDERER_GENERAL_CLUSTER_ROOTCAS=[/etc/hyperledger/fabric/tls/ca.crt]
            - FABRIC_LOGGING_SPEC=DEBUG
        volumes:
            - ./crypto-config/ordererOrganizations/example.com/orderers/orderer0.example.com/msp:/etc/hyperledger/fabric/msp
            - ./crypto-config/ordererOrganizations/example.com/orderers/orderer0.example.com/tls/:/etc/hyperledger/fabric/tls
            - ./channel-artifacts/orderer.genesis.block:/etc/hyperledger/fabric/orderer.genesis.block
        expose:
            - "7050"  # gRPC
            - "8443"  # Operation REST
        command: orderer start

    orderer1.example.com:
        image: hyperledger/fabric-orderer:2.4.1
        restart: always
        container_name: orderer1.example.com
        hostname: orderer1.example.com
        ports:
            - 8050:7050
            - 8444:8443
        extra_hosts:
            - "orderer0.example.com:192.168.235.129"
            - "orderer1.example.com:192.168.235.129"
            - "orderer2.example.com:192.168.235.129"
            - "peer0.org1.example.com:192.168.235.129"
            - "peer1.org1.example.com:192.168.235.129"
            - "peer0.org2.example.com:192.168.235.129"
            - "peer1.org2.example.com:192.168.235.129"
        environment:
            - FABRIC_LOGGING_SPEC=DEBUG
            - FABRIC_LOGGING_FORMAT="%{color}%{time:2006-01-02 15:04:05.000 MST} [%{module}] %{shortfunc} -> %{level:.4s} %{id:03x}%{color:reset} %{message}"
            - ORDERER_GENERAL_LISTENADDRESS=0.0.0.0 # default: 127.0.0.1
            - ORDERER_GENERAL_LISTENPORT=7050
            - ORDERER_GENERAL_GENESISMETHOD=file # default: provisional
            - ORDERER_GENERAL_BOOTSTRAPFILE=/etc/hyperledger/fabric/orderer.genesis.block # by default, all materials should be put under $FABRIC_CFG_PATH, which defaults to /etc/hyperledger/fabric
            - ORDERER_GENERAL_LOCALMSPID=OrdererMSP # default: DEFAULT
            - ORDERER_GENERAL_LOCALMSPDIR=/etc/hyperledger/fabric/msp
            - ORDERER_GENERAL_LEDGERTYPE=file
            #- ORDERER_GENERAL_LEDGERTYPE=json  # default: file
            - ORDERER_OPERATIONS_LISTENADDRESS=0.0.0.0:8443  # operation RESTful API
            - ORDERER_METRICS_PROVIDER=prometheus  # prometheus will pull metrics from orderer via /metrics RESTful API
            #- ORDERER_RAMLEDGER_HISTORY_SIZE=100  #only useful when use ram ledger
            # enabled TLS
            - ORDERER_GENERAL_TLS_ENABLED=true # default: false
            - ORDERER_GENERAL_TLS_PRIVATEKEY=/etc/hyperledger/fabric/tls/server.key
            - ORDERER_GENERAL_TLS_CERTIFICATE=/etc/hyperledger/fabric/tls/server.crt
            - ORDERER_GENERAL_TLS_ROOTCAS=[/etc/hyperledger/fabric/tls/ca.crt]
            # Only required by raft mode
            - ORDERER_GENERAL_CLUSTER_CLIENTPRIVATEKEY=/etc/hyperledger/fabric/tls/server.key
            - ORDERER_GENERAL_CLUSTER_CLIENTCERTIFICATE=/etc/hyperledger/fabric/tls/server.crt
            - ORDERER_GENERAL_CLUSTER_ROOTCAS=[/etc/hyperledger/fabric/tls/ca.crt]
            - ORDERER_GENERAL_CLUSTER_SENDBUFFERSIZE=10
        volumes:
            - ./crypto-config/ordererOrganizations/example.com/orderers/orderer1.example.com/msp:/etc/hyperledger/fabric/msp
            - ./crypto-config/ordererOrganizations/example.com/orderers/orderer1.example.com/tls/:/etc/hyperledger/fabric/tls
            - ./channel-artifacts/orderer.genesis.block:/etc/hyperledger/fabric/orderer.genesis.block
        command: orderer start    


    orderer2.example.com:
        image: hyperledger/fabric-orderer:2.4.1
        restart: always
        container_name: orderer2.example.com
        hostname: orderer2.example.com
        ports:
            - 9050:7050
            - 8445:8443
        extra_hosts:
            - "orderer0.example.com:192.168.0.105"
            - "orderer1.example.com:192.168.0.105"
            - "orderer2.example.com:192.168.0.105"
            - "peer0.org1.example.com:192.168.0.109"
            - "peer1.org1.example.com:192.168.0.109"
            - "peer0.org2.example.com:192.168.0.110"
            - "peer1.org2.example.com:192.168.0.110"
        environment:
            - FABRIC_LOGGING_SPEC=DEBUG  # default: INFO
            - FABRIC_LOGGING_FORMAT="%{color}%{time:2006-01-02 15:04:05.000 MST} [%{module}] %{shortfunc} -> %{level:.4s} %{id:03x}%{color:reset} %{message}"
            - ORDERER_GENERAL_LISTENADDRESS=0.0.0.0 # default: 127.0.0.1
            - ORDERER_GENERAL_LISTENPORT=7050
            - ORDERER_GENERAL_GENESISMETHOD=file # default: provisional
            - ORDERER_GENERAL_BOOTSTRAPFILE=/etc/hyperledger/fabric/orderer.genesis.block # by default, all materials should be put under $FABRIC_CFG_PATH, which defaults to /etc/hyperledger/fabric
            - ORDERER_GENERAL_LOCALMSPID=OrdererMSP # default: DEFAULT
            - ORDERER_GENERAL_LOCALMSPDIR=/etc/hyperledger/fabric/msp
            - ORDERER_GENERAL_LEDGERTYPE=file
            #- ORDERER_GENERAL_LEDGERTYPE=json  # default: file
            - ORDERER_OPERATIONS_LISTENADDRESS=0.0.0.0:8443  # operation RESTful API
            - ORDERER_METRICS_PROVIDER=prometheus  # prometheus will pull metrics from orderer via /metrics RESTful API
            #- ORDERER_RAMLEDGER_HISTORY_SIZE=100  #only useful when use ram ledger
            # enabled TLS
            - ORDERER_GENERAL_TLS_ENABLED=true # default: false
            - ORDERER_GENERAL_TLS_PRIVATEKEY=/etc/hyperledger/fabric/tls/server.key
            - ORDERER_GENERAL_TLS_CERTIFICATE=/etc/hyperledger/fabric/tls/server.crt
            - ORDERER_GENERAL_TLS_ROOTCAS=[/etc/hyperledger/fabric/tls/ca.crt]
            # Only required by raft mode
            - ORDERER_GENERAL_CLUSTER_CLIENTPRIVATEKEY=/etc/hyperledger/fabric/tls/server.key
            - ORDERER_GENERAL_CLUSTER_CLIENTCERTIFICATE=/etc/hyperledger/fabric/tls/server.crt
            - ORDERER_GENERAL_CLUSTER_ROOTCAS=[/etc/hyperledger/fabric/tls/ca.crt]
            - ORDERER_GENERAL_CLUSTER_SENDBUFFERSIZE=10
        volumes:
            - ./crypto-config/ordererOrganizations/example.com/orderers/orderer2.example.com/msp:/etc/hyperledger/fabric/msp
            - ./crypto-config/ordererOrganizations/example.com/orderers/orderer2.example.com/tls/:/etc/hyperledger/fabric/tls
            - ./channel-artifacts/orderer.genesis.block:/etc/hyperledger/fabric/orderer.genesis.block
        command: orderer start

Start the orderer node after writing:

docker-compose -f docker-compose-3orderer.yaml up -d

You can also delete if you want to stop: 

docker-compose -f docker-compose-3orderer.yaml down

If you want to start over, close the container first and then delete it all, you can also:

docker stop $(docker ps -a | awk '{ print $1}' | tail -n +2)
docker rm $(docker ps -a | awk '{ print $1}' | tail -n +2)

5. Deploy the org1 peer node

Same as above, we named it as:

Edit docker-compose-org1-2peer.yaml:

Here is also the main modification of the port number and ip address

version: '2.0'

services:

    peer0.org1.example.com:
        image: hyperledger/fabric-peer:2.4.1
        restart: always
        container_name: peer0.org1.example.com
        hostname: peer0.org1.example.com
        ports:
            - 7051:7051
            - 7052:7052
            - 9443:9443
        extra_hosts:
            - "orderer0.example.com:192.168.235.129"
            - "orderer1.example.com:192.168.235.129"
            - "orderer2.example.com:192.168.235.129"
            - "peer0.org1.example.com:192.168.235.129"
            - "peer1.org1.example.com:192.168.235.129"
            - "peer0.org2.example.com:192.168.235.129"
            - "peer1.org2.example.com:192.168.235.129"
        environment:
            - FABRIC_LOGGING_SPEC=INFO
            - FABRIC_LOGGING_FORMAT="%{color}%{time:2006-01-02 15:04:05.000 MST} [%{module}] %{shortfunc} -> %{level:.4s} %{id:03x}%{color:reset} %{message}"
            - CORE_PEER_ADDRESSAUTODETECT=false
            - CORE_VM_DOCKER_HOSTCONFIG_NETWORKMODE=host  # uncomment this to use specific network
            - CORE_PEER_GOSSIP_USELEADERELECTION=true
            - CORE_PEER_GOSSIP_ORGLEADER=false  # whether this node is the org leader, default to false
            - CORE_OPERATIONS_LISTENADDRESS=0.0.0.0:9443  # operation RESTful API
            - CORE_METRICS_PROVIDER=prometheus  # prometheus will pull metrics from fabric via /metrics RESTful API
            - CORE_PEER_PROFILE_ENABLED=false
            - 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_BUILDER=hyperledger/fabric-ccenv:2.4.1
            - CORE_CHAINCODE_GOLANG_RUNTIME=hyperledger/fabric-baseos:2.4.1
            - CORE_CHAINCODE_JAVA_RUNTIME=hyperledger/fabric-javaenv:2.4.1
            - CORE_CHAINCODE_NODE_RUNTIME=hyperledger/fabric-nodeenv:2.4.1
            - CORE_PEER_ID=peer0.org1.example.com
            - CORE_PEER_ADDRESS=peer0.org1.example.com:7051
            - CORE_PEER_CHAINCODELISTENADDRESS=0.0.0.0:7052
            - CORE_PEER_CHAINCODEADDRESS=peer0.org1.example.com:7052
            - CORE_PEER_GOSSIP_EXTERNALENDPOINT=peer0.org1.example.com:7051
            - CORE_PEER_GOSSIP_BOOTSTRAP=peer0.org1.example.com:7051
            - CORE_PEER_LOCALMSPID=Org1MSP
            - FABRIC_LOGGING_SPEC=DEBUG # info:core.chaincode=debug
            - CORE_LEDGER_STATE_STATEDATABASE=CouchDB
            - CORE_LEDGER_STATE_COUCHDBCONFIG_COUCHDBADDRESS=peer0.org1.couchdb:5984
            - CORE_LEDGER_STATE_COUCHDBCONFIG_USERNAME=admin
            - CORE_LEDGER_STATE_COUCHDBCONFIG_PASSWORD=adminpw
        volumes:
            - /var/run/docker.sock:/var/run/docker.sock
            - ./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
        expose:
            - "7051"  # gRPC
            - "9443"  # Operation REST
        #command: bash -c 'bash /tmp/peer_build.sh; peer node start'
        command: peer node start
        depends_on:
            - peer0.org1.couchdb


    peer1.org1.example.com:
        image: hyperledger/fabric-peer:2.4.1
        restart: always
        container_name: peer1.org1.example.com
        hostname: peer1.org1.example.com
        ports:
            - 8051:7051
            - 8052:7052
            - 9444:9443
        extra_hosts:
            - "orderer0.example.com:192.168.235.129"
            - "orderer1.example.com:192.168.235.129"
            - "orderer2.example.com:192.168.235.129"
            - "peer0.org1.example.com:192.168.235.129"
            - "peer1.org1.example.com:192.168.235.129"
            - "peer0.org2.example.com:192.168.235.129"
            - "peer1.org2.example.com:192.168.235.129"
        environment:
            - FABRIC_LOGGING_SPEC=INFO
            - FABRIC_LOGGING_FORMAT="%{color}%{time:2006-01-02 15:04:05.000 MST} [%{module}] %{shortfunc} -> %{level:.4s} %{id:03x}%{color:reset} %{message}"
            - CORE_PEER_ADDRESSAUTODETECT=false
            - CORE_VM_DOCKER_HOSTCONFIG_NETWORKMODE=host  # uncomment this to use specific network
            - CORE_PEER_GOSSIP_USELEADERELECTION=true
            - CORE_PEER_GOSSIP_ORGLEADER=false  # whether this node is the org leader, default to false
            - CORE_OPERATIONS_LISTENADDRESS=0.0.0.0:9443  # operation RESTful API
            - CORE_METRICS_PROVIDER=prometheus  # prometheus will pull metrics from fabric via /metrics RESTful API
            - CORE_PEER_PROFILE_ENABLED=false
            - 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_BUILDER=hyperledger/fabric-ccenv:2.4.1
            - CORE_CHAINCODE_GOLANG_RUNTIME=hyperledger/fabric-baseos:2.4.1
            - CORE_CHAINCODE_JAVA_RUNTIME=hyperledger/fabric-javaenv:2.4.1
            - CORE_CHAINCODE_NODE_RUNTIME=hyperledger/fabric-nodeenv:2.4.1
            - CORE_PEER_ID=peer1.org1.example.com
            - CORE_PEER_ADDRESS=peer1.org1.example.com:8051
            - CORE_PEER_CHAINCODELISTENADDRESS=0.0.0.0:7052
            - CORE_PEER_CHAINCODEADDRESS=peer1.org1.example.com:8052
            - CORE_PEER_GOSSIP_EXTERNALENDPOINT=peer1.org1.example.com:8051
            - CORE_PEER_GOSSIP_BOOTSTRAP=peer1.org1.example.com:8051
            - CORE_PEER_LOCALMSPID=Org1MSP
            - FABRIC_LOGGING_SPEC=DEBUG # info:core.chaincode=debug
            - CORE_LEDGER_STATE_STATEDATABASE=CouchDB
            - CORE_LEDGER_STATE_COUCHDBCONFIG_COUCHDBADDRESS=peer1.org1.couchdb:5984
            - CORE_LEDGER_STATE_COUCHDBCONFIG_USERNAME=admin
            - CORE_LEDGER_STATE_COUCHDBCONFIG_PASSWORD=adminpw
        volumes:
            - /var/run/docker.sock:/var/run/docker.sock
            - ./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
        expose:
            - "8051"  # gRPC
            - "8052"  # chaincode
            - "9444"  # Operation REST
        #command: bash -c 'bash /tmp/peer_build.sh; peer node start'
        command: peer node start
        depends_on:
            - peer1.org1.couchdb

    
                    
    peer0.org1.couchdb:
        image: couchdb:3.1.1
        container_name: peer0.org1.couchdb
        ports:
            - 5984:5984  # this is the restful API addr, can also access fauxton web ui thru http://localhost:5984/_utils/
        environment:
            - COUCHDB_USER=admin
            - COUCHDB_PASSWORD=adminpw

    peer1.org1.couchdb:
        image: couchdb:3.1.1
        container_name: peer1.org1.couchdb
        ports:
            - 6984:5984  # this is the restful API addr, can also access fauxton web ui thru http://localhost:5984/_utils/
        environment:
            - COUCHDB_USER=admin
            - COUCHDB_PASSWORD=adminpw

Start the org1 peer node:

docker-compose -f docker-compose-org1-2peer.yaml up -d

6. Deploy the org2 peer node

Same as above, the file name is: docker-compose-org2-2peer.yaml

Edit docker-compose-org2-2peer.yaml:

Here is also the main modification of the port number and ip address

Note: The bottom couchdb port number should also be modified! ! It must be different from org1 above.




version: '2.0'

services:

    peer0.org2.example.com:
        image: hyperledger/fabric-peer:2.4.1
        restart: always
        container_name: peer0.org2.example.com
        hostname: peer0.org2.example.com
        ports:
            - 9051:7051
            - 9052:7052
            - 9445:9443
        extra_hosts:
            - "orderer0.example.com:192.168.235.129"
            - "orderer1.example.com:192.168.235.129"
            - "orderer2.example.com:192.168.235.129"
            - "peer0.org1.example.com:192.168.235.129"
            - "peer1.org1.example.com:192.168.235.129"
            - "peer0.org2.example.com:192.168.235.129"
            - "peer1.org2.example.com:192.168.235.129"
        environment:
            - FABRIC_LOGGING_SPEC=INFO
            - FABRIC_LOGGING_FORMAT="%{color}%{time:2006-01-02 15:04:05.000 MST} [%{module}] %{shortfunc} -> %{level:.4s} %{id:03x}%{color:reset} %{message}"
            - CORE_PEER_ADDRESSAUTODETECT=false
            - CORE_VM_DOCKER_HOSTCONFIG_NETWORKMODE=host  # uncomment this to use specific network
            - CORE_PEER_GOSSIP_USELEADERELECTION=true
            - CORE_PEER_GOSSIP_ORGLEADER=false  # whether this node is the org leader, default to false
            - CORE_OPERATIONS_LISTENADDRESS=0.0.0.0:9443  # operation RESTful API
            - CORE_METRICS_PROVIDER=prometheus  # prometheus will pull metrics from fabric via /metrics RESTful API
            - CORE_PEER_PROFILE_ENABLED=false
            - 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_BUILDER=hyperledger/fabric-ccenv:2.4.1
            - CORE_CHAINCODE_GOLANG_RUNTIME=hyperledger/fabric-baseos:2.4.1
            - CORE_CHAINCODE_JAVA_RUNTIME=hyperledger/fabric-javaenv:2.4.1
            - CORE_CHAINCODE_NODE_RUNTIME=hyperledger/fabric-nodeenv:2.4.1
            - CORE_PEER_ID=peer0.org2.example.com
            - CORE_PEER_ADDRESS=peer0.org2.example.com:9051
            - CORE_PEER_CHAINCODELISTENADDRESS=0.0.0.0:7052
            - CORE_PEER_CHAINCODEADDRESS=peer0.org2.example.com:9052
            - CORE_PEER_GOSSIP_EXTERNALENDPOINT=peer0.org2.example.com:9051
            - CORE_PEER_GOSSIP_BOOTSTRAP=peer0.org2.example.com:9051
            - CORE_PEER_LOCALMSPID=Org2MSP
            - FABRIC_LOGGING_SPEC=DEBUG # info:core.chaincode=debug
            - CORE_LEDGER_STATE_STATEDATABASE=CouchDB
            - CORE_LEDGER_STATE_COUCHDBCONFIG_COUCHDBADDRESS=peer0.org2.couchdb:5984
            - CORE_LEDGER_STATE_COUCHDBCONFIG_USERNAME=admin
            - CORE_LEDGER_STATE_COUCHDBCONFIG_PASSWORD=adminpw
        volumes:
            - /var/run/docker.sock:/var/run/docker.sock
            - ./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
        expose:
            - "9051"  # gRPC
            - "9445"  # Operation REST
        #command: bash -c 'bash /tmp/peer_build.sh; peer node start'
        command: peer node start
        depends_on:
            - peer0.org2.couchdb


    peer1.org2.example.com:
        image: hyperledger/fabric-peer:2.4.1
        restart: always
        container_name: peer1.org2.example.com
        hostname: peer1.org2.example.com
        ports:
            - 10051:7051
            - 10052:7052
            - 9446:9443
        extra_hosts:
            - "orderer0.example.com:192.168.235.129"
            - "orderer1.example.com:192.168.235.129"
            - "orderer2.example.com:192.168.235.129"
            - "peer0.org1.example.com:192.168.235.129"
            - "peer1.org1.example.com:192.168.235.129"
            - "peer0.org2.example.com:192.168.235.129"
            - "peer1.org2.example.com:192.168.235.129"
        environment:
            - FABRIC_LOGGING_SPEC=INFO
            - FABRIC_LOGGING_FORMAT="%{color}%{time:2006-01-02 15:04:05.000 MST} [%{module}] %{shortfunc} -> %{level:.4s} %{id:03x}%{color:reset} %{message}"
            - CORE_PEER_ADDRESSAUTODETECT=false
            - CORE_VM_DOCKER_HOSTCONFIG_NETWORKMODE=host  # uncomment this to use specific network
            - CORE_PEER_GOSSIP_USELEADERELECTION=true
            - CORE_PEER_GOSSIP_ORGLEADER=false  # whether this node is the org leader, default to false
            - CORE_OPERATIONS_LISTENADDRESS=0.0.0.0:9443  # operation RESTful API
            - CORE_METRICS_PROVIDER=prometheus  # prometheus will pull metrics from fabric via /metrics RESTful API
            - CORE_PEER_PROFILE_ENABLED=false
            - 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_BUILDER=hyperledger/fabric-ccenv:2.4.1
            - CORE_CHAINCODE_GOLANG_RUNTIME=hyperledger/fabric-baseos:2.4.1
            - CORE_CHAINCODE_JAVA_RUNTIME=hyperledger/fabric-javaenv:2.4.1
            - CORE_CHAINCODE_NODE_RUNTIME=hyperledger/fabric-nodeenv:2.4.1
            - CORE_PEER_ID=peer1.org2.example.com
            - CORE_PEER_ADDRESS=peer1.org2.example.com:10051
            - CORE_PEER_CHAINCODELISTENADDRESS=0.0.0.0:7052
            - CORE_PEER_CHAINCODEADDRESS=peer1.org2.example.com:10052
            - CORE_PEER_GOSSIP_EXTERNALENDPOINT=peer1.org2.example.com:10051
            - CORE_PEER_GOSSIP_BOOTSTRAP=peer1.org2.example.com:10051
            - CORE_PEER_LOCALMSPID=Org2MSP
            - FABRIC_LOGGING_SPEC=DEBUG # info:core.chaincode=debug
            - CORE_LEDGER_STATE_STATEDATABASE=CouchDB
            - CORE_LEDGER_STATE_COUCHDBCONFIG_COUCHDBADDRESS=peer1.org2.couchdb:5984
            - CORE_LEDGER_STATE_COUCHDBCONFIG_USERNAME=admin
            - CORE_LEDGER_STATE_COUCHDBCONFIG_PASSWORD=adminpw
        volumes:
            - /var/run/docker.sock:/var/run/docker.sock
            - ./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
        expose:
            - "10051"  # gRPC
            - "9446"  # Operation REST
        #command: bash -c 'bash /tmp/peer_build.sh; peer node start'
        command: peer node start
        depends_on:
            - peer1.org2.couchdb


    peer0.org2.couchdb:
        image: couchdb:3.1.1
        container_name: peer0.org2.couchdb
        ports:
            - 7984:5984  # this is the restful API addr, can also access fauxton web ui thru http://localhost:5984/_utils/
        environment:
            - COUCHDB_USER=admin
            - COUCHDB_PASSWORD=adminpw

    peer1.org2.couchdb:
        image: couchdb:3.1.1
        container_name: peer1.org2.couchdb
        ports:
            - 8984:5984  # this is the restful API addr, can also access fauxton web ui thru http://localhost:5984/_utils/
        environment:
            - COUCHDB_USER=admin
            - COUCHDB_PASSWORD=adminpw


Start the org2 peer node:

docker-compose -f docker-compose-org2-2peer.yaml up -d

 Seven, create a channel

Enter the cli container:

docker exec -it fabric-cli bash
export APP_CHANNEL=businesschannel
export TIMEOUT=30
export CORE_PEER_LOCALMSPID=Org1MSP
export CORE_PEER_MSPCONFIGPATH=/etc/hyperledger/fabric/crypto-config/peerOrganizations/org1.example.com/users/[email protected]/msp

peer channel create -o orderer0.example.com:7050 -c ${APP_CHANNEL} -f "/tmp/channel-artifacts/$APP_CHANNEL.tx" --timeout "${TIMEOUT}s" --tls --cafile /etc/hyperledger/fabric/crypto-config/ordererOrganizations/example.com/orderers/orderer0.example.com/msp/tlscacerts/tlsca.example.com-cert.pem

After the creation is successful, the file will be generated under the current path  businesschannel.block .

mv businesschannel.block /tmp/channel-artifacts/

Eight, join the channel

Enter the cli container:

docker exec -it fabric-cli bash

org1-peer0 joins the channel:

export CORE_PEER_TLS_ENABLED=true
export CORE_PEER_LOCALMSPID="Org1MSP"
export CORE_PEER_TLS_ROOTCERT_FILE=/etc/hyperledger/fabric/crypto-config/peerOrganizations/org1.example.com/peers/peer0.org1.example.com/tls/ca.crt
export CORE_PEER_MSPCONFIGPATH=/etc/hyperledger/fabric/crypto-config/peerOrganizations/org1.example.com/users/[email protected]/msp
export CORE_PEER_ADDRESS=peer0.org1.example.com:7051

peer channel join -b /tmp/channel-artifacts/businesschannel.block

The result is as follows:

org1-peer1 joins the channel:

export CORE_PEER_TLS_ENABLED=true
export CORE_PEER_LOCALMSPID="Org1MSP"
export CORE_PEER_TLS_ROOTCERT_FILE=/etc/hyperledger/fabric/crypto-config/peerOrganizations/org1.example.com/peers/peer1.org1.example.com/tls/ca.crt
export CORE_PEER_MSPCONFIGPATH=/etc/hyperledger/fabric/crypto-config/peerOrganizations/org1.example.com/users/[email protected]/msp
export CORE_PEER_ADDRESS=peer1.org1.example.com:8051


peer channel join -b /tmp/channel-artifacts/businesschannel.block

org2-peer0 joins the channel:

export CORE_PEER_TLS_ENABLED=true
export CORE_PEER_LOCALMSPID="Org2MSP"
export CORE_PEER_TLS_ROOTCERT_FILE=/etc/hyperledger/fabric/crypto-config/peerOrganizations/org2.example.com/peers/peer0.org2.example.com/tls/ca.crt
export CORE_PEER_MSPCONFIGPATH=/etc/hyperledger/fabric/crypto-config/peerOrganizations/org2.example.com/users/[email protected]/msp
export CORE_PEER_ADDRESS=peer0.org2.example.com:9051

peer channel join -b /tmp/channel-artifacts/businesschannel.block

org2-peer1 joins the channel:

export CORE_PEER_TLS_ENABLED=true
export CORE_PEER_LOCALMSPID="Org2MSP"
export CORE_PEER_TLS_ROOTCERT_FILE=/etc/hyperledger/fabric/crypto-config/peerOrganizations/org2.example.com/peers/peer0.org2.example.com/tls/ca.crt
export CORE_PEER_MSPCONFIGPATH=/etc/hyperledger/fabric/crypto-config/peerOrganizations/org2.example.com/users/[email protected]/msp
export CORE_PEER_ADDRESS=peer1.org2.example.com:10051

peer channel join -b /tmp/channel-artifacts/businesschannel.block

9. Update the anchor node

 The purpose of updating the anchor node is to enable peers of different organizations in the channel to communicate and jointly maintain the ledger. We set the peer0 nodes of the two organizations as anchor nodes in the previous configuration file configtx.yaml.

org1 updates the anchor node:

export CORE_PEER_TLS_ENABLED=true
export CORE_PEER_LOCALMSPID="Org1MSP"
export CORE_PEER_TLS_ROOTCERT_FILE=/etc/hyperledger/fabric/crypto-config/peerOrganizations/org1.example.com/peers/peer0.org1.example.com/tls/ca.crt
export CORE_PEER_MSPCONFIGPATH=/etc/hyperledger/fabric/crypto-config/peerOrganizations/org1.example.com/users/[email protected]/msp
export CORE_PEER_ADDRESS=peer0.org1.example.com:7051

peer channel update -o orderer0.example.com:7050 -c businesschannel -f /tmp/channel-artifacts/Org1MSPanchors.tx --tls --cafile /etc/hyperledger/fabric/crypto-config/ordererOrganizations/example.com/orderers/orderer0.example.com/msp/tlscacerts/tlsca.example.com-cert.pem

org2 updates the anchor node:

export CORE_PEER_TLS_ENABLED=true
export CORE_PEER_LOCALMSPID="Org2MSP"
export CORE_PEER_TLS_ROOTCERT_FILE=/etc/hyperledger/fabric/crypto-config/peerOrganizations/org2.example.com/peers/peer0.org2.example.com/tls/ca.crt
export CORE_PEER_MSPCONFIGPATH=/etc/hyperledger/fabric/crypto-config/peerOrganizations/org2.example.com/users/[email protected]/msp
export CORE_PEER_ADDRESS=peer0.org2.example.com:9051

peer channel update -o orderer0.example.com:7050 -c businesschannel -f /tmp/channel-artifacts/Org2MSPanchors.tx --tls --cafile /etc/hyperledger/fabric/crypto-config/ordererOrganizations/example.com/orderers/orderer0.example.com/msp/tlscacerts/tlsca.example.com-cert.pem

After the anchor node configuration is updated, peers between different organizations in the same channel can also perform Gossip communication to jointly maintain the channel ledger.

10. Download the chain code and package it

The chaincode can be downloaded directly in the cli container with git, and I copied it directly from the host machine.

My chaincode uses the demo written by DevX_, and I also copied his process. After his process is my process.

Process of DevX_

Enter the cli container:

docker exec -it fabric-cli bash

Download the contract code in the chaincodes directory mounted on the host and docker cli container:

git clone https://gitee.com/kernelHP/hyperledger-fabric-contract-java-demo.git

cd hyperledger-fabric-contract-java-demo/

Compile and package the source code:

mvn compile package -DskipTests -Dmaven.test.skip=true
mv target/chaincode.jar $PWD

# 删除编译后产生的 target 目录; src 源代码目录; pom.xml
rm -rf target/ src pom.xml

Get the following structure directory:

hyperledger-fabric-contract-java-demo/
├── chaincode.jar
├── collections_config.json
├── META-INF
│   └── statedb
│       └── couchdb
│           └── indexes
│               └── indexNameColor.json

my process

Because the java chain code installation is relatively slow, I first clean and then package through the maven project in the idea, and then store the package, index and private data set in a folder hyperledger-fabric-contract-java

For specific tutorials, please see:

Solve the problem of slow installation of Java chain code in Fabric (use jar package to install chain code)_FD—moremore's Blog-CSDN Blog

Then make it into a folder and save it in the container:

docker cp ./hyperledger-fabric-contract-java-demo/ fabric-cli:/etc/hyperledger/fabric/chaincodes/

Then package the chaincode:

peer lifecycle chaincode package hyperledger-fabric-contract-java-demo.tar.gz --path ./hyperledger-fabric-contract-java-demo/ --lang java --label hyperledger-fabric-contract-java-demo_1

The result is as follows:

11. Node installation chain code

cd /etc/hyperledger/fabric/chaincodes/

org1-peer0 node:

export CORE_PEER_TLS_ENABLED=true
export CORE_PEER_LOCALMSPID="Org1MSP"
export CORE_PEER_TLS_ROOTCERT_FILE=/etc/hyperledger/fabric/crypto-config/peerOrganizations/org1.example.com/peers/peer0.org1.example.com/tls/ca.crt
export CORE_PEER_MSPCONFIGPATH=/etc/hyperledger/fabric/crypto-config/peerOrganizations/org1.example.com/users/[email protected]/msp
export CORE_PEER_ADDRESS=peer0.org1.example.com:7051

peer lifecycle chaincode install hyperledger-fabric-contract-java-demo.tar.gz

The result is as follows:

 
 

org1-peer1 node:

export CORE_PEER_TLS_ENABLED=true
export CORE_PEER_LOCALMSPID="Org1MSP"
export CORE_PEER_TLS_ROOTCERT_FILE=/etc/hyperledger/fabric/crypto-config/peerOrganizations/org1.example.com/peers/peer1.org1.example.com/tls/ca.crt
export CORE_PEER_MSPCONFIGPATH=/etc/hyperledger/fabric/crypto-config/peerOrganizations/org1.example.com/users/[email protected]/msp
export CORE_PEER_ADDRESS=peer1.org1.example.com:8051

peer lifecycle chaincode install hyperledger-fabric-contract-java-demo.tar.gz

org2-peer0 node:

export CORE_PEER_TLS_ENABLED=true
export CORE_PEER_LOCALMSPID="Org2MSP"
export CORE_PEER_TLS_ROOTCERT_FILE=/etc/hyperledger/fabric/crypto-config/peerOrganizations/org2.example.com/peers/peer0.org2.example.com/tls/ca.crt
export CORE_PEER_MSPCONFIGPATH=/etc/hyperledger/fabric/crypto-config/peerOrganizations/org2.example.com/users/[email protected]/msp
export CORE_PEER_ADDRESS=peer0.org2.example.com:9051

peer lifecycle chaincode install hyperledger-fabric-contract-java-demo.tar.gz

org2-peer1 node:

export CORE_PEER_TLS_ENABLED=true
export CORE_PEER_LOCALMSPID="Org2MSP"
export CORE_PEER_TLS_ROOTCERT_FILE=/etc/hyperledger/fabric/crypto-config/peerOrganizations/org2.example.com/peers/peer1.org2.example.com/tls/ca.crt
export CORE_PEER_MSPCONFIGPATH=/etc/hyperledger/fabric/crypto-config/peerOrganizations/org2.example.com/users/[email protected]/msp
export CORE_PEER_ADDRESS=peer1.org2.example.com:10051

peer lifecycle chaincode install hyperledger-fabric-contract-java-demo.tar.gz

Query package ID:

peer lifecycle chaincode queryinstalled

The bundle ID is a combination of the chaincode label and a hash of the chaincode binary. Each peer node will generate the same package ID. You should see output similar to the following:

Installed chaincodes on peer:
Package ID: hyperledger-fabric-contract-java-demo_1:6b1c76b05811b82cc0101b84908cf0b4077df8f6e44ac447831ac8f0a0e6fc7c, Label: hyperledger-fabric-contract-java-demo_1

Save the bundle ID as an environment variable:

export CC_PACKAGE_ID=hyperledger-fabric-contract-java-demo_1:6b1c76b05811b82cc0101b84908cf0b4077df8f6e44ac447831ac8f0a0e6fc7c

12. Approve the chaincode definition

 If there is private data, private data set configuration is required here

org1 approves the chaincode definition:

export CORE_PEER_TLS_ENABLED=true
export CORE_PEER_LOCALMSPID="Org1MSP"
export CORE_PEER_TLS_ROOTCERT_FILE=/etc/hyperledger/fabric/crypto-config/peerOrganizations/org1.example.com/peers/peer0.org1.example.com/tls/ca.crt
export CORE_PEER_MSPCONFIGPATH=/etc/hyperledger/fabric/crypto-config/peerOrganizations/org1.example.com/users/[email protected]/msp
export CORE_PEER_ADDRESS=peer0.org1.example.com:7051

# 普通数据定义
peer lifecycle chaincode approveformyorg -o orderer0.example.com:7050 --ordererTLSHostnameOverride orderer0.example.com --channelID businesschannel --name hyperledger-fabric-contract-java-demo --version 1.0 --package-id $CC_PACKAGE_ID --sequence 1  --tls --cafile /etc/hyperledger/fabric/crypto-config/ordererOrganizations/example.com/orderers/orderer0.example.com/msp/tlscacerts/tlsca.example.com-cert.pem

The result is as follows:

org2 approved chaincode definition:

export CORE_PEER_TLS_ENABLED=true
export CORE_PEER_LOCALMSPID="Org2MSP"
export CORE_PEER_TLS_ROOTCERT_FILE=/etc/hyperledger/fabric/crypto-config/peerOrganizations/org2.example.com/peers/peer0.org2.example.com/tls/ca.crt
export CORE_PEER_MSPCONFIGPATH=/etc/hyperledger/fabric/crypto-config/peerOrganizations/org2.example.com/users/[email protected]/msp
export CORE_PEER_ADDRESS=peer0.org2.example.com:9051

peer lifecycle chaincode approveformyorg -o orderer0.example.com:7050 --ordererTLSHostnameOverride orderer0.example.com --channelID businesschannel --name hyperledger-fabric-contract-java-demo --version 1.0 --package-id $CC_PACKAGE_ID --sequence 1 --tls --cafile /etc/hyperledger/fabric/crypto-config/ordererOrganizations/example.com/orderers/orderer0.example.com/msp/tlscacerts/tlsca.example.com-cert.pem

 The result is as follows:

Check that channel members have approved the same chaincode definition:

peer lifecycle chaincode checkcommitreadiness --channelID businesschannel --name hyperledger-fabric-contract-java-demo --version 1.0 --sequence 1 --tls --cafile /etc/hyperledger/fabric/crypto-config/ordererOrganizations/example.com/orderers/orderer0.example.com/msp/tlscacerts/tlsca.example.com-cert.pem --output json

The output is as follows:

Submit the chaincode to the channel:

peer lifecycle chaincode commit -o orderer0.example.com:7050 --ordererTLSHostnameOverride orderer0.example.com --channelID businesschannel --name hyperledger-fabric-contract-java-demo --version 1.0 --sequence 1 --tls --cafile /etc/hyperledger/fabric/crypto-config/ordererOrganizations/example.com/orderers/orderer0.example.com/msp/tlscacerts/tlsca.example.com-cert.pem --peerAddresses peer0.org1.example.com:7051 --tlsRootCertFiles /etc/hyperledger/fabric/crypto-config/peerOrganizations/org1.example.com/peers/peer0.org1.example.com/tls/ca.crt --peerAddresses peer0.org2.example.com:9051 --tlsRootCertFiles /etc/hyperledger/fabric/crypto-config/peerOrganizations/org2.example.com/peers/peer0.org2.example.com/tls/ca.crt

The result is as follows:

 

 At this point, it means that the chaincode has been submitted to the channel.

Now we can confirm that we are done:

peer lifecycle chaincode querycommitted Confirm that the chaincode definition has been committed to the channel with the command

peer lifecycle chaincode querycommitted --channelID businesschannel --name hyperledger-fabric-contract-java-demo --cafile /etc/hyperledger/fabric/crypto-config/ordererOrganizations/example.com/orderers/orderer0.example.com/msp/tlscacerts/tlsca.example.com-cert.pem

The result is as follows:

 

Thirteen, call the chain code

This is not the point, I just copied the chain code of the up master.


# 调用 createCat 函数
peer chaincode invoke -o orderer0.example.com:7050 --ordererTLSHostnameOverride orderer0.example.com --tls --cafile /etc/hyperledger/fabric/crypto-config/ordererOrganizations/example.com/orderers/orderer0.example.com/msp/tlscacerts/tlsca.example.com-cert.pem -C businesschannel -n hyperledger-fabric-contract-java-demo --peerAddresses peer0.org1.example.com:7051 --tlsRootCertFiles /etc/hyperledger/fabric/crypto-config/peerOrganizations/org1.example.com/peers/peer0.org1.example.com/tls/ca.crt --peerAddresses peer0.org2.example.com:9051 --tlsRootCertFiles /etc/hyperledger/fabric/crypto-config/peerOrganizations/org2.example.com/peers/peer0.org2.example.com/tls/ca.crt -c '{"function":"createCat","Args":["cat-0" , "tom" ,  "3" , "蓝色" , "大懒猫"]}'

# 调用 queryCat 函数
peer chaincode query -C businesschannel -n hyperledger-fabric-contract-java-demo -c '{"Args":["queryCat" , "cat-0"]}'

The result of the operation is as follows:

At the same time, since we set the couchdb container during the configuration process, we can open couchdb

The ip and port of couchdb are:

http://192.168.235.129:5984/_utils/#

There can be four port numbers, corresponding to different peer nodes (5984, 6984, 7984, 8984)

After entering, the user name and password have been written in the container configuration file, and our default is admin and adminpw

As for calling private data in the future, it needs to be configured in the approval chain code, and it will be done later.

Guess you like

Origin blog.csdn.net/Wannabe_hacker/article/details/129220142