Centos7 Fabric2.4 network construction (2)

Tip: The previous article talked about using cryptogen to issue certificates to the orderer and peer in the organization, then using docker to start the orderer and peer, and then creating the channel.


Table of contents

Preface

1. Create a channel in the main script

2. createChannel.sh

2.1 Create channel genesis block

2.2 Use osnadmin CLI to add orderer to the channel

2.3 peer joins channel

2.4 Set anchor node

 Summary of problems encountered


Preface

Part One: Centos7 Fabric2.4 Network Construction (1)_Big. boss’s blog-CSDN blog


提示:用的是官方的例子学习搭建自己的网络,本次是用cryptogen生成证书,单机多节点部署

1. Create a channel in the main script

To simplify the channel creation process and enhance the privacy and scalability of channels, it is now possible to create application channels (where transactions involving assets occur) without first creating a "system channel" managed by an orderer. This case is to create a new channel without a system channel by using the configtxgen tool to create a genesis block and using the osnadmin CLI (which runs on the REST API exposed by each orderer node) to connect the orderer node to the channel. This process allows orderer nodes to join (or leave) any number of channels as needed, similar to how peers can participate in multiple channels.

# Step4 创建通道
function createChannel() {
  # 如果网络尚未启动,请启动网络
  bringUpNetwork="false"

  if ! $CONTAINER_CLI info > /dev/null 2>&1 ; then
    fatalln "$CONTAINER_CLI network is required to be running to create a channel"
  fi

  # 检查是否所有容器是否准备好
  CONTAINERS=($($CONTAINER_CLI ps | grep hyperledger/ | awk '{print $2}'))
  len=$(echo ${#CONTAINERS[@]})

  if [[ $len -ge 8 ]] && [[ ! -d "organizations/peerOrganizations" ]]; then
    echo "Bringing network down to sync certs with containers"
    networkDown
  fi

  [[ $len -lt 8 ]] || [[ ! -d "organizations/peerOrganizations" ]] && bringUpNetwork="true" || echo "Network Running Already"

  if [ $bringUpNetwork == "true"  ]; then
    infoln "Bringing up network"
    networkUp
  fi

  # 现在运行创建频道的脚本。此脚本使用configtxgen一次性创建通道创建事务和锚节点对等更新
  scripts/createChannel.sh $CHANNEL_NAME $CLI_DELAY $MAX_RETRY $VERBOSE
}

2. createChannel.sh

2.1 Create channel genesis block

The process of creating a new channel starts by generating a genesis block for the channel , which is later submitted to the orderer in the request. Only one orderer is required to create the genesis block, and it can be shared out-of-band with other members on the channel, who can check it to ensure they agree with the channel configuration, which is then used by every orderer in the ordering service.

FABRIC_CFG_PATH=${PWD}/configtx

## Create channel genesis block
infoln "Generating channel genesis block '${CHANNEL_NAME}.block'"
createChannelGenesisBlock


# 函数 - 创建通道创世区块
createChannelGenesisBlock() {
  # 搜索configtxgen命令,判断是否存在此二进制文件,若不存在,打印错误信息,程序终止
	which configtxgen
	if [ "$?" -ne 0 ]; then
		fatalln "configtxgen tool not found."
	fi
	set -x  #脚本调试,会将下面执行的命令输出到屏幕上
	# 创建创世区块:生成创世区块mychannel.block文件,根据配置文件../configtx/configtx.yaml来创建Orderer系统通道的创世块
	configtxgen -profile TwoOrgsApplicationGenesis -outputBlock ./channel-artifacts/${CHANNEL_NAME}.block -channelID $CHANNEL_NAME
	res=$?
	{ set +x; } 2>/dev/null
  verifyResult $res "Failed to generate channel configuration transaction..."
}

It involves an important file configtx.yaml. For details, please refer to Hyperledger Fabric configuration file analysis - configtx.yaml_Big. boss's blog - CSDN blog

Different from Fabric2.2 process :

1. No more need for system channels: Besides representing an extra step, the establishment of system channels creates an additional layer of management layer that does not provide any tangible benefit for certain use cases.

2. Consortium is no longer needed: It is no longer necessary to define a group of organizations ("consortium") in configtx.yaml to allow the creation of channels on a specific orderer. In the new process, all channels are application channels, and there is no need to create an organizational list of channels. Any group of organizations can come together and create a channel using a defined set of ordering nodes.

3. Simplify the orderer node creation process: The genesis block of the system channel is no longer needed before creating the orderer node. The admin can now focus on the process of basic setup and ensure that its node is working properly before joining a specific application channel.

# Copyright IBM Corp. All Rights Reserved.
#
# SPDX-License-Identifier: Apache-2.0
#

---
################################################################################
#
#   Section: Organizations
#
#   - This section defines the different organizational identities which will
#   be referenced later in the configuration.
#
################################################################################
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
        # DefaultOrg defines the organization which is used in the sampleconfig
        # of the fabric.git development environment
        # 组织名称
        Name: OrdererOrg

        # ID to load the MSP definition as
        # 组织ID,ID是引用组织的关键
        ID: OrdererMSP

        # MSPDir is the filesystem path which contains the MSP configuration
        # 组织的MSP证书路径
        MSPDir: ../organizations/ordererOrganizations/hmw.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>
        # 定义本层级的组织策略,其权威路径为 /Channel/<Application|Orderer>/<OrgName>/<PolicyName>
        Policies:
            Readers:
                Type: Signature
                Rule: "OR('OrdererMSP.member')"
            Writers:
                Type: Signature
                Rule: "OR('OrdererMSP.member')"
            Admins:
                Type: Signature
                Rule: "OR('OrdererMSP.admin')"

        OrdererEndpoints:
            - orderer0.hmw.com:7050
            - orderer1.hmw.com:7052
            - orderer2.hmw.com:7054

    - &Org1
        # DefaultOrg defines the organization which is used in the sampleconfig
        # of the fabric.git development environment
        Name: Org1MSP

        # ID to load the MSP definition as
        ID: Org1MSP

        MSPDir: ../organizations/peerOrganizations/org1.hmw.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('Org1MSP.admin', 'Org1MSP.peer', 'Org1MSP.client')"
            Writers:
                Type: Signature
                Rule: "OR('Org1MSP.admin', 'Org1MSP.client')"
            Admins:
                Type: Signature
                Rule: "OR('Org1MSP.admin')"
            Endorsement:
                Type: Signature
                Rule: "OR('Org1MSP.peer')"

    - &Org2
        # DefaultOrg defines the organization which is used in the sampleconfig
        # of the fabric.git development environment
        Name: Org2MSP

        # ID to load the MSP definition as
        ID: Org2MSP

        MSPDir: ../organizations/peerOrganizations/org2.hmw.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('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')"

################################################################################
#
#   SECTION: 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 capability ensures that orderers and peers behave according
        # to v2.0 channel capabilities. Orderers and peers from
        # prior releases would behave in an incompatible way, and are therefore
        # not able to participate in channels at v2.0 capability.
        # 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
        # V2_0 orderer capability ensures that orderers behave according
        # to v2.0 orderer capabilities. Orderers from
        # prior releases would behave in an incompatible way, and are therefore
        # not able to participate in channels at v2.0 orderer capability.
        # Prior to enabling V2.0 orderer capabilities, ensure that all
        # orderers on 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 application capability ensures that peers behave according
        # to v2.0 application capabilities. Peers from
        # prior releases would behave in an incompatible way, and are therefore
        # not able to participate in channels at v2.0 application capability.
        # Prior to enabling V2.0 application capabilities, ensure that all
        # peers on channel are at v2.0.0 or later.
        V2_0: true

################################################################################
#
#   SECTION: Application
#
#   - This section defines the values to encode into a config transaction or
#   genesis block for application related parameters
#
################################################################################
Application: &ApplicationDefaults

    # Organizations is the list of orgs which are defined as participants 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:
        Readers:
            Type: ImplicitMeta
            Rule: "ANY Readers"
        Writers:
            Type: ImplicitMeta
            Rule: "ANY Writers"
        Admins:
            Type: ImplicitMeta
            Rule: "MAJORITY Admins"
        LifecycleEndorsement:
            Type: ImplicitMeta
            Rule: "MAJORITY Endorsement"
        Endorsement:
            Type: ImplicitMeta
            Rule: "MAJORITY Endorsement"

    Capabilities:
        <<: *ApplicationCapabilities
################################################################################
#
#   SECTION: 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
    # 定义order共识机制
    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.hmw.com:7050
        - orderer1.hmw.com:7052
        - orderer2.hmw.com:7054

    EtcdRaft:
        Consenters:
        - Host: orderer0.hmw.com
          Port: 7050
          ClientTLSCert: ../organizations/ordererOrganizations/hmw.com/orderers/orderer0.hmw.com/tls/server.crt
          ServerTLSCert: ../organizations/ordererOrganizations/hmw.com/orderers/orderer0.hmw.com/tls/server.crt
        - Host: orderer1.hmw.com
          Port: 7052
          ClientTLSCert: ../organizations/ordererOrganizations/hmw.com/orderers/orderer1.hmw.com/tls/server.crt
          ServerTLSCert: ../organizations/ordererOrganizations/hmw.com/orderers/orderer1.hmw.com/tls/server.crt
        - Host: orderer2.hmw.com
          Port: 7054
          ClientTLSCert: ../organizations/ordererOrganizations/hmw.com/orderers/orderer2.hmw.com/tls/server.crt
          ServerTLSCert: ../organizations/ordererOrganizations/hmw.com/orderers/orderer2.hmw.com/tls/server.crt

    # 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
    BatchSize:

        # Max Message Count: The maximum number of messages to permit in a batch
        # 区块消息数量
        MaxMessageCount: 10

        # Absolute Max Bytes: The absolute maximum number of bytes allowed for
        # the serialized messages in a batch.
        # 区块绝对最大字节数
        AbsoluteMaxBytes: 99 MB

        # Preferred Max Bytes: The preferred maximum number of bytes allowed for
        # the serialized messages in a batch. A message larger than the preferred
        # max bytes will result in a batch larger than preferred max bytes.
        # 建议消息字节数
        PreferredMaxBytes: 512 KB

    # Organizations is the list of orgs which are defined as participants 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"

################################################################################
#
#   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

################################################################################
#
#   Profile
#
#   - Different configuration profiles may be encoded here to be specified
#   as parameters to the configtxgen tool
#
################################################################################
Profiles:
    TwoOrgsApplicationGenesis:
        <<: *ChannelDefaults
        Orderer:
            <<: *OrdererDefaults
            Organizations:
                - *OrdererOrg
            Capabilities: *OrdererCapabilities
        Application:
            <<: *ApplicationDefaults
            Organizations:
                - *Org1
                - *Org2
            Capabilities: *ApplicationCapabilities

2.2 Use osnadmin CLI to add orderer to the channel

Now that the Genesis block has been created, the first ordering node that receives the osnadmin channel connect command effectively "activates" the channel, although the channel is not fully operational until a quorum frequency is established (at least if your policy lists three consents) There are two nodes in total, and you must use the osnadmin channel connection command to join)

# 函数 - 激活通道
createChannel() {
  # 调用脚本 envVar.sh中的函数setGlobals,为org1或org2的peer节点设置环境变量,参数01对应的是org1,02对应org2
  # 设置环境变量为org1
	setGlobals 01
	# Poll in case the raft leader is not set yet
	local rc=1
	local COUNTER=1
	# 创建通道若未成功,可尝试5次
	while [ $rc -ne 0 -a $COUNTER -lt $MAX_RETRY ] ; do
		sleep $DELAY
		set -x
		# 创建通道,将执行结果信息记录到log.txt文件中
		infoln "Orderer0 join channel"
		osnadmin channel join --channelID $CHANNEL_NAME --config-block ./channel-artifacts/${CHANNEL_NAME}.block -o localhost:7051 --ca-file "$ORDERER_CA" --client-cert "$ORDERER_ADMIN_TLS_SIGN_CERT" --client-key "$ORDERER_ADMIN_TLS_PRIVATE_KEY" >&log.txt
		infoln "Orderer1 join channel"
        osnadmin channel join --channelID $CHANNEL_NAME --config-block ./channel-artifacts/${CHANNEL_NAME}.block -o localhost:7053 --ca-file "$ORDERER_CA" --client-cert "$ORDERER1_ADMIN_TLS_SIGN_CERT" --client-key "$ORDERER1_ADMIN_TLS_PRIVATE_KEY" >&log.txt
		infoln "Orderer2 join channel"
        osnadmin channel join --channelID $CHANNEL_NAME --config-block ./channel-artifacts/${CHANNEL_NAME}.block -o localhost:7055 --ca-file "$ORDERER_CA" --client-cert "$ORDERER2_ADMIN_TLS_SIGN_CERT" --client-key "$ORDERER2_ADMIN_TLS_PRIVATE_KEY" >&log.txt
		res=$?
		{ set +x; } 2>/dev/null
		let rc=$res
		COUNTER=$(expr $COUNTER + 1)
	done
	# 打印log.txt,即打印创建通道结果信息
	cat log.txt
	# 调用脚本 envVar.sh 中的函数verifyResult,用来验证上面执行的命令是否报错,如果报错,则打印错误信息,程序终止
	verifyResult $res "Channel creation failed"
}

After success, the orderer will join the channel with a leader height of 1. Because this orderer was added from the genesis block, the status is displayed as "active". And orderer is the console of the channel, so consensusRelation is "consenter". 

2.3 peer joins channel

## Join all the peers to the channel
infoln "Joining peer0-org1 to the channel..."
joinChannel 01
infoln "Joining peer1-org1 to the channel..."
joinChannel 11
infoln "Joining peer0-org2 to the channel..."
joinChannel 02
infoln "Joining peer1-org2 to the channel..."
joinChannel 12

# joinChannel ORG
joinChannel() {
  FABRIC_CFG_PATH=${PWD}/config/
  ORG=$1
  # 根据传递的参数设置环境变量,切换组织使用
  setGlobals $ORG
	local rc=1
	local COUNTER=1
	# peer节点加入通道若未成功,可尝试5次
	while [ $rc -ne 0 -a $COUNTER -lt $MAX_RETRY ] ; do
    sleep $DELAY
    set -x
    # 将节点加入通道,将执行结果信息记录到log.txt文件中
    peer channel join -b $BLOCKFILE >&log.txt
    res=$?
    { set +x; } 2>/dev/null
		let rc=$res
		COUNTER=$(expr $COUNTER + 1)
	done
	cat log.txt
	verifyResult $res "After $MAX_RETRY attempts, peer0.org${ORG} has failed to join channel '$CHANNEL_NAME' "
}

2.4 Set anchor node

Finally, after an organization joins its peers to a channel, they should select at least one of them to be an anchor. In order to take advantage of features such as private data and service discovery, anchor nodes are required. Every organization should have multiple anchor nodes on a channel for redundancy. Endpoint information for each organization's anchor node is included in the channel configuration. Each channel member can specify their anchor node by updating the channel.

## Set the anchor peers for each org in the channel
infoln "Setting anchor peer for org1..."
setAnchorPeer 01
infoln "Setting anchor peer for org2..."
setAnchorPeer 02


# 函数 - 设置锚节点
setAnchorPeer() {
  ORG=$1
  ${CONTAINER_CLI} exec cli ./scripts/setAnchorPeer.sh $ORG $CHANNEL_NAME
}

Each channel member can specify their anchor node by updating the channel. We will use configtxlator to update the channel configuration for Org1 and Org2.

Org1 sets environment variables

export CORE_PEER_LOCALMSPID="Org1MSP"
export CORE_PEER_TLS_ROOTCERT_FILE=${PWD}/organizations/peerOrganizations/org1.hmw.com/tlsca/tlsca.org1.hmw.com-cert.pem
export CORE_PEER_MSPCONFIGPATH=${PWD}/organizations/peerOrganizations/org1.hmw.com/users/[email protected]/msp
export CORE_PEER_ADDRESS=localhost:8051

The channel configuration can be obtained through the following command

  infoln "Fetching the most recent configuration block for the channel"
  set -x
  # 获取通道配置
  peer channel fetch config config_block.pb -o orderer0.hmw.com:7050 --ordererTLSHostnameOverride orderer0.hmw.com -c $CHANNEL --tls --cafile "$ORDERER_CA"
  { set +x; } 2>/dev/null
  res=$?
  if [ $res -ne 0 ]; then
    fatalln "Failed to fetch the most recent configuration block..."
  fi

Since the most recent channel configuration block is the channel genesis block, the command returns block 0 from the channel

We can now start using the configtxlator tool to get started with channel configuration. The first step is to decode the chunks from protobuf into a json object that can be read and edited. We also got rid of unnecessary block data, leaving only the channel configuration.

  # 将配置块protobuf格式转成json格式
  configtxlator proto_decode --input config_block.pb --type common.Block --output config_block.json
  jq .data.data[0].payload.data.config config_block.json >"${OUTPUT}"

These commands convert the channel configuration block into a simplified json, config.json, which will serve as the baseline for our updates.

The org1 anchor node can be added to the channel configuration using the jq tool

  set -x
  # Modify the configuration to append the anchor peer
  # 将锚节点添加至配置文件中
  jq '.channel_group.groups.Application.groups.'${CORE_PEER_LOCALMSPID}'.values += {"AnchorPeers":{"mod_policy": "Admins","value":{"anchor_peers": [{"host": "'$HOST'","port": '$PORT'}]},"version": "0"}}' ${CORE_PEER_LOCALMSPID}config.json > ${CORE_PEER_LOCALMSPID}modified_config.json
  { set +x; } 2>/dev/null

After this step, we updated the updated version of the channel configuration in json format in the modified_config.json file. We can now convert the original and modified channel configurations back to protobuf format and calculate the difference between them

  # 将原始和修改的通道配置都转换回protobuf格式,并计算它们之间的差异
  configtxlator proto_encode --input "${ORIGINAL}" --type common.Config --output original_config.pb
  configtxlator proto_encode --input "${MODIFIED}" --type common.Config --output modified_config.pb
  configtxlator compute_update --channel_id "${CHANNEL}" --original original_config.pb --updated modified_config.pb --output config_update.pb

The new protobuf file is called config_update.pb and contains the anchor node updates that apply to the channel configuration. We can wrap the configuration updates in a transaction envelope to create a channel configuration update transaction.

  # 将配置更新包装在交易Envelope中,以创建通道配置更新交易
  configtxlator proto_decode --input config_update.pb --type common.ConfigUpdate --output config_update.json
  echo '{"payload":{"header":{"channel_header":{"channel_id":"'$CHANNEL'", "type":2}},"data":{"config_update":'$(cat config_update.json)'}}}' | jq . >config_update_in_envelope.json
  configtxlator proto_encode --input config_update_in_envelope.json --type common.Envelope --output "${OUTPUT}"
  { set +x; } 2>/dev/null

We can add anchor nodes by providing new channel configurations through the peer channel update command.

Because we are updating a part of the channel configuration that only affects org1, other channel members do not need to approve the channel update

peer channel update -o orderer0.hmw.com:7050 --ordererTLSHostnameOverride orderer0.hmw.com -c $CHANNEL_NAME -f ${CORE_PEER_LOCALMSPID}anchors.tx --tls --cafile "$ORDERER_CA" >&log.txt

In the same way, set the environment variables and add anchor nodes for Org2. 

You can confirm that the channel has been updated with the following command:

export FABRIC_CFG_PATH=${PWD}/config/
export CORE_PEER_TLS_ENABLED=true
export CORE_PEER_LOCALMSPID="Org1MSP"
export CORE_PEER_TLS_ROOTCERT_FILE=${PWD}/organizations/peerOrganizations/org1.hmw.com/tlsca/tlsca.org1.hmw.com-cert.pem
export CORE_PEER_MSPCONFIGPATH=${PWD}/organizations/peerOrganizations/org1.hmw.com/users/[email protected]/msp
export CORE_PEER_ADDRESS=localhost:8051
peer channel getinfo -c mychannel

By updating the anchor node above, add two channel configuration files to the genesis block to update the channel, so the block height of the channel becomes 3 and the hash value is also updated.

 Please refer to the relevant code: https://blog.csdn.net/humingwei11/article/details/124128401


 Summary of problems encountered

1.Error: can't read the block: &{SERVICE_UNAVAILABLE} 

​​

This problem has troubled me for a long time. It turns out that when joining the channel, not all orderers were added to the channel. 2

set -x
# 创建通道,将执行结果信息记录到log.txt文件中
infoln "Orderer0 join channel"
osnadmin channel join --channelID $CHANNEL_NAME --config-block ./channel-artifacts/${CHANNEL_NAME}.block -o orderer0.hmw.com:7051 --ca-file "$ORDERER_CA" --client-cert "$ORDERER_ADMIN_TLS_SIGN_CERT" --client-key "$ORDERER_ADMIN_TLS_PRIVATE_KEY" >&log.txt
infoln "Orderer1 join channel"
osnadmin channel join --channelID $CHANNEL_NAME --config-block ./channel-artifacts/${CHANNEL_NAME}.block -o orderer1.hmw.com:7053 --ca-file "$ORDERER_CA" --client-cert "$ORDERER1_ADMIN_TLS_SIGN_CERT" --client-key "$ORDERER1_ADMIN_TLS_PRIVATE_KEY" >&log.txt
infoln "Orderer2 join channel"
osnadmin channel join --channelID $CHANNEL_NAME --config-block ./channel-artifacts/${CHANNEL_NAME}.block -o orderer2.hmw.com:7055 --ca-file "$ORDERER_CA" --client-cert "$ORDERER2_ADMIN_TLS_SIGN_CERT" --client-key "$ORDERER2_ADMIN_TLS_PRIVATE_KEY" >&log.txt
res=$?
{ set +x; } 2>/dev/null

2. When the orderer joins the channel, -o I write localhost and the TLS certificate handshake fails.

 The reason is that in crypto-config-orderer.yaml, I forgot to add SANS under each Hostname in Specs.

Guess you like

Origin blog.csdn.net/humingwei11/article/details/123794122