时隔很久没有学习区块链了,今天重新搭建一下区块链网络,有了更多新的体会。

我是跟着b站up主 DevX_ 一步一步往下搭建的。这是大神的视频,简洁易懂而且很符合我目前的技术栈(java应用端+java链码),而且代码开源,非常适合新手学习!!

DevX亡命天涯的个人空间-DevX亡命天涯个人主页-哔哩哔哩视频

经过测试已成功。为了今后学习便利,记录一遍搭建过程。

一、区块链搭建网络拓扑结构:

本次环境搭建要求:3个Orderer节点以满足raft共识;2个组织:org1、org2;两个组织内都有两个peer节点。

但是我懒得开多台虚拟机,索性利用一台虚拟机整多个端口来搞了,划分清楚端口就好。

资源规划如下:

节点iphosts端口
cli容器192.168.235.129N/AN/A
orderer0192.168.235.129orderer0.example.com7050:7050
8443:8443
orderer1192.168.235.129orderer1.example.com

8050:7050

8444:8443

orderer2192.168.235.129orderer2.example.com9050:7050
8445:8553
org1.peer0192.168.235.129peer0.org1.example.com7051:7051
7052:7052
9443:9443
org1.peer1192.168.235.129peer1.org1.example.com8051:7051
8052:7052
9444:9443
org2.peer0192.168.235.129peer0.org2.example.com9051:7051
9052:7052
9445:9443
org2.peer1192.168.235.129peer1.org2.example.com10051:7051
10052:7052
9446:9443

之后我们可以在hosts文件夹下保存一下映射的关系:

这里是我的虚拟机ip,换成自己的虚拟机ip就好,如果多机的就换成多个机子的ip。

vim /etc/hosts192.168.235.129 orderer0.example.com192.168.235.129 orderer1.example.com192.168.235.129 orderer2.example.com192.168.235.129 peer0.org1.example.com192.168.235.129 peer1.org1.example.com192.168.235.129 peer0.org2.example.com192.168.235.129 peer1.org2.example.com

二、编写生成身份证书文件

生成证书文件的配置文件:crypto-config.yaml

新建一个文件夹 ,名为3orderer-org1-2peer-org2-2peer-network:

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

为了后续操作便利可以将fabric的可执行文件夹bin放入其中:(这样是为了方便,如果export成环境变量也行)

在fabric-samples下是有这么一个东西的,给他copy一下。

完了以后进入到你新建的文件夹的bin目录下,执行:

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

生成了证书文件的模板,并将文件放到config文件夹中,然后我们对其进行修改:

vim ../config/crypto-config.yaml

这里要修改的是Specs的HostName要把三个orderer节点都写上;EnableNodeOUs设置为true;每一个组织template的count设置为2,意思是有两个peer节点。

# ---------------------------------------------------------------------------# "OrdererOrgs" - Definition of organizations managing orderer nodes# ---------------------------------------------------------------------------OrdererOrgs:# ---------------------------------------------------------------------------# Orderer# ---------------------------------------------------------------------------- Name: OrdererDomain: example.comEnableNodeOUs: true# ---------------------------------------------------------------------------# "Specs" - See PeerOrgs below for complete description# ---------------------------------------------------------------------------Specs:- Hostname: orderer0- Hostname: orderer1- Hostname: orderer2SANS: - "*" - "192.168.235.129" # ---------------------------------------------------------------------------# "PeerOrgs" - Definition of organizations managing peer nodes# ---------------------------------------------------------------------------PeerOrgs:# ---------------------------------------------------------------------------# Org1# ---------------------------------------------------------------------------- Name: Org1Domain: org1.example.comEnableNodeOUs: 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: Org2Domain: org2.example.comEnableNodeOUs: trueTemplate:Count: 2SANS:- "*"- "192.168.235.139"Users:Count: 1

文件编辑完后利用bin文件下的cryptogen工具,根据crypto-config.yaml配置文件生成证书:

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

如果修改了配置还可以extend子命令来更新crypto-config目录:

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

结束之后查看一下是否真的生成了身份证书文件,并且确认一下节点信息是否完整,没有遗漏。

tree ../crypto-config

三、编写生成通道初始区块、通道文件、锚节点配置更新文件

生成通道文件的配置文件:configtx.yaml

我们可以利用bin文件架下的configtxgen工具来生成网络配置和拓补结构信息。

编辑configtx.yaml文件:

这里要改的主要是一些文件目录要对,比如MSPDir等;OrdererEndpoints、Addresses(Order节点的端口号),以及完成raft共识的各个orderer节点的tls证书目录。

注意:我这里定义的org1和org2的锚节点是他们的peer0节点。

# 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///Policies:Readers:Type: SignatureRule: "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: SignatureRule: "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: SignatureRule: "OR('OrdererMSP.admin')"Endorsement:Type: SignatureRule: "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- &Org1Name: Org1MSPID: Org1MSPMSPDir: ../crypto-config/peerOrganizations/org1.example.com/mspPolicies:Readers:Type: SignatureRule: "OR('Org1MSP.admin', 'Org1MSP.peer', 'Org1MSP.client')"Writers:Type: SignatureRule: "OR('Org1MSP.admin', 'Org1MSP.client')"Admins:Type: SignatureRule: "OR('Org1MSP.admin')"Endorsement:Type: SignatureRule: "OR('Org1MSP.peer')"AnchorPeers:- Host: peer0.org1.example.comPort: 7051- &Org2Name: Org2MSPID: Org2MSPMSPDir: ../crypto-config/peerOrganizations/org2.example.com/mspPolicies:Readers:Type: SignatureRule: "OR('Org2MSP.admin', 'Org2MSP.peer', 'Org2MSP.client')"Writers:Type: SignatureRule: "OR('Org2MSP.admin', 'Org2MSP.client')"Admins:Type: SignatureRule: "OR('Org2MSP.admin')"Endorsement:Type: SignatureRule: "OR('Org2MSP.peer')"AnchorPeers:- Host: peer0.org2.example.comPort: 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: &ApplicationDefaultsACLs: &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" functionlscc/ChaincodeExists: /Channel/Application/Readers# ACL policy for lscc's "getdepspec" functionlscc/GetDeploymentSpec: /Channel/Application/Readers# ACL policy for lscc's "getccdata" functionlscc/GetChaincodeData: /Channel/Application/Readers# ACL Policy for lscc's "getchaincodes" functionlscc/GetInstantiatedChaincodes: /Channel/Application/Readers#---Query System Chaincode (qscc) function to policy mapping for access control---## ACL policy for qscc's "GetChainInfo" functionqscc/GetChainInfo: /Channel/Application/Readers# ACL policy for qscc's "GetBlockByNumber" functionqscc/GetBlockByNumber: /Channel/Application/Readers# ACL policy for qscc's"GetBlockByHash" functionqscc/GetBlockByHash: /Channel/Application/Readers# ACL policy for qscc's "GetTransactionByID" functionqscc/GetTransactionByID: /Channel/Application/Readers# ACL policy for qscc's "GetBlockByTxID" functionqscc/GetBlockByTxID: /Channel/Application/Readers#---Configuration System Chaincode (cscc) function to policy mapping for access control---## ACL policy for cscc's "GetConfigBlock" functioncscc/GetConfigBlock: /Channel/Application/Readers# ACL policy for cscc's "GetChannelConfig" functioncscc/GetChannelConfig: /Channel/Application/Readers#---Miscellaneous peer function to policy mapping for access control---## ACL policy for invoking chaincodes on peerpeer/Propose: /Channel/Application/Writers# ACL policy for chaincode to chaincode invocationpeer/ChaincodeToChaincode: /Channel/Application/Writers#---Events resource to policy mapping for access control###---## ACL policy for sending block eventsevent/Block: /Channel/Application/Readers# ACL policy for sending filtered block eventsevent/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/Policies: &ApplicationDefaultPoliciesLifecycleEndorsement:Type: ImplicitMetaRule: "MAJORITY Endorsement"Endorsement:Type: ImplicitMetaRule: "MAJORITY Endorsement"Readers:Type: ImplicitMetaRule: "ANY Readers"Writers:Type: ImplicitMetaRule: "ANY Writers"Admins:Type: ImplicitMetaRule: "MAJORITY Admins"# Capabilities describes the application level capabilities, see the# dedicated Capabilities section elsewhere in this file for a full# descriptionCapabilities:<<: *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 definitionAddresses:- 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: 0Kafka:# 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.comPort: 7050ClientTLSCert: ../crypto-config/ordererOrganizations/example.com/orderers/orderer0.example.com/tls/server.crtServerTLSCert: ../crypto-config/ordererOrganizations/example.com/orderers/orderer0.example.com/tls/server.crt- Host: orderer1.example.comPort: 8050ClientTLSCert: ../crypto-config/ordererOrganizations/example.com/orderers/orderer1.example.com/tls/server.crtServerTLSCert: ../crypto-config/ordererOrganizations/example.com/orderers/orderer1.example.com/tls/server.crt- Host: orderer2.example.comPort: 9050ClientTLSCert: ../crypto-config/ordererOrganizations/example.com/orderers/orderer2.example.com/tls/server.crtServerTLSCert: ../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 takenSnapshotIntervalSize: 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/Policies:Readers:Type: ImplicitMetaRule: "ANY Readers"Writers:Type: ImplicitMetaRule: "ANY Writers"Admins:Type: ImplicitMetaRule: "MAJORITY Admins"# BlockValidation specifies what signatures must be included in the block# from the orderer for the peer to validate it.BlockValidation:Type: ImplicitMetaRule: "ANY Writers"# Capabilities describes the orderer level capabilities, see the# dedicated Capabilities section elsewhere in this file for a full# descriptionCapabilities:<<: *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/Policies:# Who may invoke the 'Deliver' APIReaders:Type: ImplicitMetaRule: "ANY Readers"# Who may invoke the 'Broadcast' APIWriters:Type: ImplicitMetaRule: "ANY Writers"# By default, who may modify elements at this config levelAdmins:Type: ImplicitMetaRule: "MAJORITY Admins"# Capabilities describes the channel level capabilities, see the# dedicated Capabilities section elsewhere in this file for a full# descriptionCapabilities:<<: *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:<<: *ChannelDefaultsOrderer:<<: *OrdererDefaultsOrganizations:- *OrdererOrgCapabilities:<<: *OrdererCapabilitiesConsortiums:SampleConsortium:Organizations:- *Org1- *Org2 TwoOrgsChannel:Consortium: SampleConsortium<<: *ChannelDefaultsApplication:<<: *ApplicationDefaultsOrganizations:- *Org1- *Org2Capabilities:<<: *ApplicationCapabilities

生成创世区块:

注意:这里的-channelID指的是系统通道,与下面peer所处的通道不同,系统通道取名为fabric-channel

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

操作后目录如下:

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

生成通道文件:

注意:我这里通道文件命名为businesschannel,你们可以自己改,后期在创建通道时要根据这个名字来

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

操作后目录如下:

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

生成锚节点配置更新文件:

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

操作后目录如下:

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

四、部署orderer节点

需要编写三个不同的docker-compose配置文件,这里我们先编写启动orderer的docker容器的文件,命名为docker-compose-3orderer.yaml。

编辑docker-compose-3orderer.yaml:

这里主要是将ip地址都改成对应的ip地址,端口号也改成上面定好的端口号。

version: '2.0'services:cli:image: hyperledger/fabric-tools:2.4.1restart: alwayscontainer_name: fabric-clihostname: fabric-clitty: trueextra_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/Admin@org1.example.com/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.pemvolumes:- ./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/chaincodesworking_dir: /opt/gopath/src/github.com/hyperledger/fabric/peercommand: bash -c 'cd /tmp; source scripts/func.sh; while true; do sleep 20170504; done'orderer0.example.com:# There can be multiple orderersimage: hyperledger/fabric-orderer:2.4.1restart: alwayscontainer_name: orderer0.example.comhostname: orderer0.example.comports:- 7050:7050- 8443:8443extra_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=DEBUGvolumes:- ./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.blockexpose:- "7050"# gRPC- "8443"# Operation RESTcommand: orderer startorderer1.example.com:image: hyperledger/fabric-orderer:2.4.1restart: alwayscontainer_name: orderer1.example.comhostname: orderer1.example.comports:- 8050:7050- 8444:8443extra_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=10volumes:- ./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.blockcommand: orderer startorderer2.example.com:image: hyperledger/fabric-orderer:2.4.1restart: alwayscontainer_name: orderer2.example.comhostname: orderer2.example.comports:- 9050:7050- 8445:8443extra_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=10volumes:- ./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.blockcommand: orderer start

写完后启动 orderer 节点:

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

如果想停止也可以删除:

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

如果想重新来,把容器先关掉再全删了,也可以:

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

五、部署org1peer节点

同上,我们命名为:

编辑docker-compose-org1-2peer.yaml :

这里也是主要修改端口号和ip地址

version: '2.0'services:peer0.org1.example.com:image: hyperledger/fabric-peer:2.4.1restart: alwayscontainer_name: peer0.org1.example.comhostname: peer0.org1.example.comports:- 7051:7051- 7052:7052- 9443:9443extra_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=adminpwvolumes:- /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/tlsexpose:- "7051"# gRPC- "9443"# Operation REST#command: bash -c 'bash /tmp/peer_build.sh; peer node start'command: peer node startdepends_on:- peer0.org1.couchdbpeer1.org1.example.com:image: hyperledger/fabric-peer:2.4.1restart: alwayscontainer_name: peer1.org1.example.comhostname: peer1.org1.example.comports:- 8051:7051- 8052:7052- 9444:9443extra_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=adminpwvolumes:- /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/tlsexpose:- "8051"# gRPC- "8052"# chaincode- "9444"# Operation REST#command: bash -c 'bash /tmp/peer_build.sh; peer node start'command: peer node startdepends_on:- peer1.org1.couchdbpeer0.org1.couchdb:image: couchdb:3.1.1container_name: peer0.org1.couchdbports:- 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=adminpwpeer1.org1.couchdb:image: couchdb:3.1.1container_name: peer1.org1.couchdbports:- 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

启动 org1 peer 节点:

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

六、部署org2 peer节点

同上,文件名为:docker-compose-org2-2peer.yaml

编辑docker-compose-org2-2peer.yaml:

这里也是主要修改端口号和ip地址

注意:最下面的couchdb端口号也要进行修改!!和上面org1要不一样才行。

version: '2.0'services:peer0.org2.example.com:image: hyperledger/fabric-peer:2.4.1restart: alwayscontainer_name: peer0.org2.example.comhostname: peer0.org2.example.comports:- 9051:7051- 9052:7052- 9445:9443extra_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=adminpwvolumes:- /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/tlsexpose:- "9051"# gRPC- "9445"# Operation REST#command: bash -c 'bash /tmp/peer_build.sh; peer node start'command: peer node startdepends_on:- peer0.org2.couchdbpeer1.org2.example.com:image: hyperledger/fabric-peer:2.4.1restart: alwayscontainer_name: peer1.org2.example.comhostname: peer1.org2.example.comports:- 10051:7051- 10052:7052- 9446:9443extra_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=adminpwvolumes:- /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/tlsexpose:- "10051"# gRPC- "9446"# Operation REST#command: bash -c 'bash /tmp/peer_build.sh; peer node start'command: peer node startdepends_on:- peer1.org2.couchdbpeer0.org2.couchdb:image: couchdb:3.1.1container_name: peer0.org2.couchdbports:- 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=adminpwpeer1.org2.couchdb:image: couchdb:3.1.1container_name: peer1.org2.couchdbports:- 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

启动 org2 peer 节点:

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

七、创建通道

进入 cli 容器:

docker exec -it fabric-cli bash
export APP_CHANNEL=businesschannelexport TIMEOUT=30export CORE_PEER_LOCALMSPID=Org1MSPexport CORE_PEER_MSPCONFIGPATH=/etc/hyperledger/fabric/crypto-config/peerOrganizations/org1.example.com/users/Admin@org1.example.com/msppeer 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

创建成功后会在当前路径下生成businesschannel.block文件。

mv businesschannel.block /tmp/channel-artifacts/

八、加入通道

进入 cli 容器:

docker exec -it fabric-cli bash

org1-peer0 加入通道:

export CORE_PEER_TLS_ENABLED=trueexport 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.crtexport CORE_PEER_MSPCONFIGPATH=/etc/hyperledger/fabric/crypto-config/peerOrganizations/org1.example.com/users/Admin@org1.example.com/mspexport CORE_PEER_ADDRESS=peer0.org1.example.com:7051peer channel join -b /tmp/channel-artifacts/businesschannel.block

结果如下:

org1-peer1 加入通道:

export CORE_PEER_TLS_ENABLED=trueexport 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.crtexport CORE_PEER_MSPCONFIGPATH=/etc/hyperledger/fabric/crypto-config/peerOrganizations/org1.example.com/users/Admin@org1.example.com/mspexport CORE_PEER_ADDRESS=peer1.org1.example.com:8051peer channel join -b /tmp/channel-artifacts/businesschannel.block

org2-peer0 加入通道:

export CORE_PEER_TLS_ENABLED=trueexport 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.crtexport CORE_PEER_MSPCONFIGPATH=/etc/hyperledger/fabric/crypto-config/peerOrganizations/org2.example.com/users/Admin@org2.example.com/mspexport CORE_PEER_ADDRESS=peer0.org2.example.com:9051peer channel join -b /tmp/channel-artifacts/businesschannel.block

org2-peer1 加入通道:

export CORE_PEER_TLS_ENABLED=trueexport 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.crtexport CORE_PEER_MSPCONFIGPATH=/etc/hyperledger/fabric/crypto-config/peerOrganizations/org2.example.com/users/Admin@org2.example.com/mspexport CORE_PEER_ADDRESS=peer1.org2.example.com:10051peer channel join -b /tmp/channel-artifacts/businesschannel.block

九、更新锚节点

更新锚节点的目的是使通道内不同组织间peer可以进行通信,共同维护账本。我们在之前配置文件configtx.yaml中设置了两个组织的peer0节点作为锚节点。

org1 更新锚节点:

export CORE_PEER_TLS_ENABLED=trueexport 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.crtexport CORE_PEER_MSPCONFIGPATH=/etc/hyperledger/fabric/crypto-config/peerOrganizations/org1.example.com/users/Admin@org1.example.com/mspexport CORE_PEER_ADDRESS=peer0.org1.example.com:7051peer 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 更新锚节点:

export CORE_PEER_TLS_ENABLED=trueexport 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.crtexport CORE_PEER_MSPCONFIGPATH=/etc/hyperledger/fabric/crypto-config/peerOrganizations/org2.example.com/users/Admin@org2.example.com/mspexport CORE_PEER_ADDRESS=peer0.org2.example.com:9051peer 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

锚节点配置更新后,同一通道内不同组织之间的 Peer 也可以进行 Gossip 通信,共同维护通道账本。

十、下载链码并打包

链码可以直接在cli容器中用git下来,我直接从宿主机中复制进来的。

我的链码使用的是DevX_写的demo,我把他的流程也一并复制下来的,在他流程后是我的流程。

DevX_的流程

进入 cli 容器:

docker exec -it fabric-cli bash

在宿主机和 docker cli 容器挂载的 chaincodes 目录下下载合约代码:

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

编译打包源码:

mvn compile package -DskipTests -Dmaven.test.skip=true
mv target/chaincode.jar $PWD# 删除编译后产生的 target 目录; src 源代码目录; pom.xmlrm -rf target/ src pom.xml

得到如下结构目录:

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

我的流程

由于java链码安装比较慢,我是通过idea中maven项目先clean再package然后将包和索引和私有数据集同时存在一个文件夹hyperledger-fabric-contract-java中

具体教程请看:

解决Fabric安装java链码速度慢的问题(使用jar包安装链码)_FD—moremore的博客-CSDN博客

然后弄成一个文件夹后存到容器中:

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

之后打包链码:

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

结果如下:

十一、节点安装链码

cd /etc/hyperledger/fabric/chaincodes/

org1-peer0 节点:

export CORE_PEER_TLS_ENABLED=trueexport 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.crtexport CORE_PEER_MSPCONFIGPATH=/etc/hyperledger/fabric/crypto-config/peerOrganizations/org1.example.com/users/Admin@org1.example.com/mspexport CORE_PEER_ADDRESS=peer0.org1.example.com:7051peer lifecycle chaincode install hyperledger-fabric-contract-java-demo.tar.gz

结果如下:

org1-peer1 节点:

export CORE_PEER_TLS_ENABLED=trueexport 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.crtexport CORE_PEER_MSPCONFIGPATH=/etc/hyperledger/fabric/crypto-config/peerOrganizations/org1.example.com/users/Admin@org1.example.com/mspexport CORE_PEER_ADDRESS=peer1.org1.example.com:8051peer lifecycle chaincode install hyperledger-fabric-contract-java-demo.tar.gz

org2-peer0 节点:

export CORE_PEER_TLS_ENABLED=trueexport 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.crtexport CORE_PEER_MSPCONFIGPATH=/etc/hyperledger/fabric/crypto-config/peerOrganizations/org2.example.com/users/Admin@org2.example.com/mspexport CORE_PEER_ADDRESS=peer0.org2.example.com:9051peer lifecycle chaincode install hyperledger-fabric-contract-java-demo.tar.gz

org2-peer1 节点:

export CORE_PEER_TLS_ENABLED=trueexport 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.crtexport CORE_PEER_MSPCONFIGPATH=/etc/hyperledger/fabric/crypto-config/peerOrganizations/org2.example.com/users/Admin@org2.example.com/mspexport CORE_PEER_ADDRESS=peer1.org2.example.com:10051peer lifecycle chaincode install hyperledger-fabric-contract-java-demo.tar.gz

查询包 ID:

peer lifecycle chaincode queryinstalled

包 ID 是链码标签和链码二进制文件的哈希值的组合。每个 peer 节点将生成相同的包 ID。你应该看到类似于以下内容的输出:

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

将包 ID 保存为环境变量:

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

十二、批准链码定义

如果是有私有数据的话,这里就需要进行私有数据集配置了

org1 批准链码定义:

export CORE_PEER_TLS_ENABLED=trueexport 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.crtexport CORE_PEER_MSPCONFIGPATH=/etc/hyperledger/fabric/crypto-config/peerOrganizations/org1.example.com/users/Admin@org1.example.com/mspexport 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

结果如下:

org2 批准链码定义:

export CORE_PEER_TLS_ENABLED=trueexport 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.crtexport CORE_PEER_MSPCONFIGPATH=/etc/hyperledger/fabric/crypto-config/peerOrganizations/org2.example.com/users/Admin@org2.example.com/mspexport CORE_PEER_ADDRESS=peer0.org2.example.com:9051peer 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

结果如下:

检查通道成员是否已批准相同的链码定义:

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

输出结果如下:

将链码提交到通道:

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

结果如下:

此时说明链码已经提交给了通道了。

现在我们可以确认一下是否完成:

peer lifecycle chaincode querycommitted命令来确认链码定义已提交给通道:

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

结果如下:

十三、调用链码

这块就不是重点了,我直接复制了up主的链码就行了。

# 调用 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"]}'

运行结果如下:

同时,由于在我们在配置过程中设定了couchdb的容器,我们可以打开couchdb

couchdb的ip和端口为:

http://192.168.235.129:5984/_utils/#

端口号可以有四个,分别对应不同的peer节点(5984,6984,7984,8984)

进入后用户名和密码已经在容器配置文件中写过,我们这里默认是admin和adminpw

至于之后调用私有数据需要在批准链码那里配置的,以后再搞。