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:
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.