[Fabric] First-NetWork(byfn.sh文件分析)

Posted 长泽雅美你老婆

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了[Fabric] First-NetWork(byfn.sh文件分析)相关的知识,希望对你有一定的参考价值。

浏览顺序:

直接看最下面的输出日志信息。

一、前言

这个主要写的是脚本里面的一些方法主要是做什么的,其实不看也好,只要看日志信息,就足够了,我这里主要想了解一下运行过程,熟悉一下脚本文件的编写。

有的地方直接用的翻译出来的结果,我吃的也不是很透。

希望可以帮助到一些启动网络时,看不懂报错记录的同学。
日志记录写的没有特别详细,删除了一些东西。可以看自己的日志文件

我看的是fabric 1.4.6的版本。地址就不贴了。

因为我用的笔记块内不能放太多,这里直接全部替换成中文的,使用全文翻译也可以。

二、介绍

启动first-network的重要的脚本文件

end-to-end网络。这个记一下,别的贴子大部分这样写的 。

这个测试案例提供了 两个order节点,每个order下面有两个peer节点 ,而且是单机节点模式

这里面使用了两个重要的工具 cryptogenconfigtxgen。这两个就是搭建网络是解压出来的工具类文件bin目录下的东西。

  • cryptogen:用来产生加密证书的和秘钥的,用于传输加密和身份验证,生成的文件再crypto-config中。
  • configtxgen: 创建通道必要的工具 、

这两个工具都有自己依赖得yaml文件。

里面执行了两个sh 脚本文件,ccp-generate.sh(byfn.sh同目录),scripts.sh(scripts目录下的文件)
scripts.sh文件详解

另外写了贴子的,详情看主页。

三、详细部分

1. 配置环境变量

#!/bin/bash

#PWD 的地址就是你在的这个 /first-network目录
# 配置环境变量,让子shell也可以访问到
export PATH=$PWD/../bin:$PWD:$PATH
export FABRIC_CFG_PATH=$PWD
export VERBOSE=false

2. 帮助信息

# 这就是帮助信息,起始好多都有help命令的,只是大家不注意罢了。 ./byfn.sh -help
function printHelp() 
  echo "Usage: "
  echo "  byfn.sh <mode> [-c <channel name>] [-t <timeout>] [-d <delay>] [-f <docker-compose-file>] [-s <dbtype>] [-l <language>] [-o <consensus-type>] [-i <imagetag>] [-a] [-n] [-v]"
  # 就是后面可以加 up down restart generate upgrade
  echo "    <mode> - one of 'up', 'down', 'restart', 'generate' or 'upgrade'"
  # 使用docker-compose up 启动网络
  echo "      - 'up' - bring up the network with docker-compose up"
  # 使用docker-compose down 停止网络
  echo "      - 'down' - clear the network with docker-compose down"
  # 重启网络
  echo "      - 'restart' - restart the network"
  # 生成所需的证书和创世块
  echo "      - 'generate' - generate required certificates and genesis block"
  # 升级fabric网络版本
  echo "      - 'upgrade'  - upgrade the network from version 1.3.x to 1.4.0"
  # -c 后面加channel name 通道名,默认为 mychannel
  echo "    -c <channel name> - channel name to use (defaults to \\"mychannel\\")"
  # 下面这俩我也没整太明白,
  # -t 设置cli链接超时时间(s为单位,默认为10s)
  echo "    -t <timeout> - CLI timeout duration in seconds (defaults to 10)"
  # -d 设置延迟(s为单位,默认为3s)
  echo "    -d <delay> - delay duration in seconds (defaults to 3)"
  # -f 指定docker-compose.yaml文件(默认为docker-compose-cli.yaml)
  #    等我跑起来,这个贴子也出了。
  echo "    -f <docker-compose-file> - specify which docker-compose file use (defaults to docker-compose-cli.yaml)"
  # -s 指定数据库类型,默认是goleveldb 可以指定为couchdb
  echo "    -s <dbtype> - the database backend to use: goleveldb (default) or couchdb"
  # -l 指定链码默认的语言,目前不就是 go node.js java
  echo "    -l <language> - the chaincode language: golang (default) or node"
  # -o 指定共识类型(consensus-共识),order服务的模式:单机,kafka集群,etcdraft(是用于共享配置和服务发现的分布式,一致性的KV存储系统。)
  echo "    -o <consensus-type> - the consensus-type of the ordering service: solo (default), kafka, or etcdraft"
  # -i 启动网络的镜像用的配置,默认是最新的镜像
  echo "    -i <imagetag> - the tag to be used to launch the network (defaults to \\"latest\\")"
  # -a 启动ca 证书办法机构,默认啥都不启动
  echo "    -a - launch certificate authorities (no certificate authorities are launched by default)"
  # -n 不部署链码。默认是abstore链码
  echo "    -n - do not deploy chaincode (abstore chaincode is deployed by default)"
  # -v 详细模式(我也没试呢,试了写出来)
  echo "    -v - verbose mode"
  # -h 就是-help
  echo "  byfn.sh -h (print this message)"
  echo
  #下面就是官方说的正常人会执行的启动命令
  # 1. 先生成需要的证书和创世区块
  # 2. 然后开启网络

  echo "Typically, one would first generate the required certificates and "
  echo "genesis block, then bring up the network. e.g.:"
  echo "  上面写了"
  echo "  byfn.sh generate -c mychannel"
  echo "  byfn.sh up -c mychannel -s couchdb"
  echo "  byfn.sh up -c mychannel -s couchdb -i 1.4.0"
  echo "  byfn.sh up -l node"
  echo "  byfn.sh down -c mychannel"
  echo "  byfn.sh upgrade -c mychannel"
  echo "使用默认的就够了"
  echo "Taking all defaults:"
  echo "  byfn.sh generate"
  echo "  byfn.sh up"
  echo "  byfn.sh down"

3. 是否执行脚本

# Ask user for confirmation to proceed
# 客户确认了才进行
function askProceed() 
  read -p "Continue? [Y/n] " ans
  case "$ans" in
  y | Y | "")
    echo "proceeding ..."
    ;;
  n | N)
    echo "exiting..."
    exit 1
    ;;
  *)
    echo "invalid response"
    askProceed
    ;;
  esac

4. 删除容器

# 删除容器,默认全部删除的,也可以自己指定
function clearContainers() 
  #可以传参,awk https://www.cnblogs.com/cap-rq/p/11411415.html
  CONTAINER_IDS=$(docker ps -a | awk '($2 ~ /dev-peer.*/) print $1')
  if [ -z "$CONTAINER_IDS" -o "$CONTAINER_IDS" == " " ]; then
    #没有可以删除的容器
    echo "---- No containers available for deletion ----"
  else
    docker rm -f $CONTAINER_IDS
  fi

5. 删除镜像

# 删除作为此设置的一部分生成的镜像
function removeUnwantedImages() 
  DOCKER_IMAGE_IDS=$(docker images | awk '($1 ~ /dev-peer.*/) print $3')
  if [ -z "$DOCKER_IMAGE_IDS" -o "$DOCKER_IMAGE_IDS" == " " ]; then
    echo "---- No images available for deletion ----"
  else
    docker rmi -f $DOCKER_IMAGE_IDS
  fi

6. 版本是否冲突

# Versions of fabric known not to work with this release of first-network
# 不可以配置这个版本使用的fabric的版本
BLACKLISTED_VERSIONS="^1\\.0\\. ^1\\.1\\.0-preview ^1\\.1\\.0-alpha"

# 判断configtxlator的版本和docker镜像的版本是否有冲突
# Do some basic sanity checking to make sure that the appropriate versions of fabric
# binaries/images are available.  In the future, additional checking for the presence
# of go or other items could be added.
function checkPrereqs() 
  # note, we check configtxlator externally because it does not require a config file, and peer in the
  # docker image because of fab-8551 that makes configtxlator return 'development version' in docker

  # 这里我也不太懂,希望大佬指点

  #本地的版本
  LOCAL_VERSION=$(configtxlator version | sed -ne 's/ Version: //p')
  # docker镜像的版本
  DOCKER_IMAGE_VERSION=$(docker run --rm hyperledger/fabric-tools:$IMAGETAG peer version | sed -ne 's/ Version: //p' | head -1)

  echo "LOCAL_VERSION=$LOCAL_VERSION"
  echo "DOCKER_IMAGE_VERSION=$DOCKER_IMAGE_VERSION"

  #判断两个版本,如果不一致可能出问题
  if [ "$LOCAL_VERSION" != "$DOCKER_IMAGE_VERSION" ]; then
    echo "=================== WARNING ==================="
    echo "  Local fabric binaries and docker images are  "
    echo "  out of  sync. This may cause problems.       "
    echo "==============================================="
  fi

  #   不支持的版本               列入黑名单的版本
  for UNSUPPORTED_VERSION in $BLACKLISTED_VERSIONS; do
    echo "$LOCAL_VERSION" | grep -q $UNSUPPORTED_VERSION
    if [ $? -eq 0 ]; then
      echo "ERROR! Local Fabric binary version of $LOCAL_VERSION does not match this newer version of BYFN and is unsupported. Either move to a later version of Fabric or checkout an earlier version of fabric-samples."
      exit 1
    fi

    echo "$DOCKER_IMAGE_VERSION" | grep -q $UNSUPPORTED_VERSION
    if [ $? -eq 0 ]; then
      echo "ERROR! Fabric Docker image version of $DOCKER_IMAGE_VERSION does not match this newer version of BYFN and is unsupported. Either move to a later version of Fabric or checkout an earlier version of fabric-samples."
      exit 1
    fi
  done


7. 启动网络

# 生成所需的证书、创世块并启动网络。
function networkup() 
  checkPrereqs
  # generate artifacts if they don't exist
  # crypto-config不是一个目录
  if [ ! -d "crypto-config" ]; then
    # 使用cryptogen工具生成证书
    generateCerts
    # 生成私钥
    replacePrivateKey
    # 生成通道文件
    generateChannelArtifacts
  fi
  # compose 的文件们
  COMPOSE_FILES="-f $COMPOSE_FILE"
  # 认证机构
  if [ "$CERTIFICATE_AUTHORITIES" == "true" ]; then
                                    # -f 检查后面的是不是普通文件
    COMPOSE_FILES="$COMPOSE_FILES -f $COMPOSE_FILE_CA"
    # ca1 的 私钥 _sk 结尾的文件
    export BYFN_CA1_PRIVATE_KEY=$(cd crypto-config/peerOrganizations/org1.example.com/ca && ls *_sk)
    export BYFN_CA2_PRIVATE_KEY=$(cd crypto-config/peerOrganizations/org2.example.com/ca && ls *_sk)
  fi
  # 判断共识类型
  if [ "$CONSENSUS_TYPE" == "kafka" ]; then
    COMPOSE_FILES="$COMPOSE_FILES -f $COMPOSE_FILE_KAFKA"
  elif [ "$CONSENSUS_TYPE" == "etcdraft" ]; then
    COMPOSE_FILES="$COMPOSE_FILES -f $COMPOSE_FILE_RAFT2"
  fi
  # 设置数据库类型
  if [ "$IF_COUCHDB" == "couchdb" ]; then
    COMPOSE_FILES="$COMPOSE_FILES -f $COMPOSE_FILE_COUCH"
  fi
  # docker 镜像版本   docker-compose 启动
  IMAGE_TAG=$IMAGETAG docker-compose $COMPOSE_FILES up -d 2>&1
  docker ps -a
  if [ $? -ne 0 ]; then
    echo "ERROR !!!! Unable to start network"
    exit 1
  fi

  # 设置休眠时间,让集群有足够的时间启动
  if [ "$CONSENSUS_TYPE" == "kafka" ]; then
    sleep 1
    echo "Sleeping 10s to allow $CONSENSUS_TYPE cluster to complete booting"
    sleep 9
  fi

  if [ "$CONSENSUS_TYPE" == "etcdraft" ]; then
    sleep 1
    echo "Sleeping 15s to allow $CONSENSUS_TYPE cluster to complete booting"
    sleep 14
  fi

  # cli 执行 script.sh脚本 后面是接入的参数,后面会整理这个脚本执行的内容的
  docker exec cli scripts/script.sh $CHANNEL_NAME $CLI_DELAY $LANGUAGE $CLI_TIMEOUT $VERBOSE $NO_CHAINCODE
  if [ $? -ne 0 ]; then
    echo "ERROR !!!! Test failed"
    exit 1
  fi
 

8. 升级网网络

#将版本 1.3.x 的网络组件升级到 1.4.x
# 停止orderer和peer,备份orderer和peer的账本,清理链码容器和镜像,
# 并使用最新标版本重新启动order节点和peer节点
function upgradeNetwork() 
  if [[ "$IMAGETAG" == *"1.4"* ]] || [[ $IMAGETAG == "latest" ]]; then
    docker inspect -f '.Config.Volumes' orderer.example.com | grep -q '/var/hyperledger/production/orderer'
    if [ $? -ne 0 ]; then
      # 这个网络似乎不是从fabric-samples >= v1.3.x 开始的
      echo "ERROR !!!! This network does not appear to start with fabric-samples >= v1.3.x?"
      exit 1
    fi

    LEDGERS_BACKUP=./ledgers-backup

    # create ledger-backup directory
    mkdir -p $LEDGERS_BACKUP

    export IMAGE_TAG=$IMAGETAG
    COMPOSE_FILES="-f $COMPOSE_FILE"
    # 判断是否需要认证
    if [ "$CERTIFICATE_AUTHORITIES" == "true" ]; then
      COMPOSE_FILES="$COMPOSE_FILES -f $COMPOSE_FILE_CA"
      # 导入生成的私钥
      export BYFN_CA1_PRIVATE_KEY=$(cd crypto-config/peerOrganizations/org1.example.com/ca && ls *_sk)
      export BYFN_CA2_PRIVATE_KEY=$(cd crypto-config/peerOrganizations/org2.example.com/ca && ls *_sk)
    fi
    # 判断共识类型
    if [ "$CONSENSUS_TYPE" == "kafka" ]; then
      COMPOSE_FILES="$COMPOSE_FILES -f $COMPOSE_FILE_KAFKA"
    elif [ "$CONSENSUS_TYPE" == "etcdraft" ]; then
      COMPOSE_FILES="$COMPOSE_FILES -f $COMPOSE_FILE_RAFT2"
    fi
    # 判断数据库类型
    if [ "$IF_COUCHDB" == "couchdb" ]; then
      COMPOSE_FILES="$COMPOSE_FILES -f $COMPOSE_FILE_COUCH"
    fi

    # 移除Cli容器
    docker-compose $COMPOSE_FILES stop cli
    docker-compose $COMPOSE_FILES up -d --no-deps cli

    # 升级orderer和Peer
    echo "Upgrading orderer"
    docker-compose $COMPOSE_FILES stop orderer.example.com
    docker cp -a orderer.example.com:/var/hyperledger/production/orderer $LEDGERS_BACKUP/orderer.example.com
    docker-compose $COMPOSE_FILES up -d --no-deps orderer.example.com

    for PEER in peer0.org1.example.com peer1.org1.example.com peer0.org2.example.com peer1.org2.example.com; do
      echo "Upgrading peer $PEER"

      # 停止容器,备份账本
      docker-compose $COMPOSE_FILES stop $PEER
      docker cp -a $PEER:/var/hyperledger/production $LEDGERS_BACKUP/$PEER/

      # Remove any old containers and images for this peer
      CC_CONTAINERS=$(docker ps | grep dev-$PEER | awk 'print $1')
      if [ -n "$CC_CONTAINERS" ]; then
        docker rm -f $CC_CONTAINERS
      fi
      CC_IMAGES=$(docker images | grep dev-$PEER | awk 'print $1')
      if [ -n "$CC_IMAGES" ]; then
        docker rmi -f $CC_IMAGES
      fi

      # Start the peer again
      docker-compose $COMPOSE_FILES up -d --no-deps $PEER
    done

    # cli容器中 运行升级脚本
    docker exec cli sh -c "SYS_CHANNEL=$CH_NAME && scripts/upgrade_to_v14.sh $CHANNEL_NAME $CLI_DELAY $LANGUAGE $CLI_TIMEOUT $VERBOSE"    
    if [ $? -ne 0 ]; then
      echo "ERROR !!!! Test failed"
      exit 1
    fi
  else
    echo "ERROR !!!! Pass the v1.4.x image tag"
  fi

9. 停止网络

# 停止网络
function networkDown() 
  # 除了 org1 和 org2 之外,还停止 org3 容器,以防我们正在运行示例以添加 org3
  # 停止 kafka 和 zookeeper 容器,以防我们使用 kafka 共识类型运行
  docker-compose -f $COMPOSE_FILE -f $COMPOSE_FILE_COUCH -f $COMPOSE_FILE_KAFKA -f $COMPOSE_FILE_RAFT2 -f $COMPOSE_FILE_CA -f $COMPOSE_FILE_ORG3 down --volumes --remove-orphans

  # Don't remove the generated artifacts -- note, the ledgers are always removed
  if [ "$MODE" != "restart" ]; then

    # 停止网络,删除挂载,删除所有的账本备份
    docker run -v $PWD:/tmp/first-network --rm hyperledger/fabric-tools:$IMAGETAG rm -Rf /tmp/first-network/ledgers-backup
    # 调用上面的清除容器
    clearContainers
    # 调用上面的清除镜像
    removeUnwantedImages
    # 删除 orderer 块和其他通道配置交易和证书
    rm -rf channel-artifacts/*.block channel-artifacts/*.tx crypto-config ./org3-artifacts/crypto-config/ channel-artifacts/org3.json
    # 删除为示例定制的 docker-compose yaml 文件 就是下面这个
    rm -f docker-compose-e2e.yaml
  fi

10. 替换私钥

# 使用 docker-compose-e2e-template.yaml,
# 将常量替换为由 cryptogen 工具生成的私钥文件名,
# 并输出特定于此配置的 docker-compose.yaml
#替换私钥
function replacePrivateKey() 

# MacOSX 上的 sed 不支持带有空扩展名的 -i 标志。
# 我们将使用 't' 作为我们备份的扩展名,并在函数结束时将其删除
  ARCH=$(uname -s | grep Darwin)
  if [ "$ARCH" == "Darwin" ]; then
    OPTS="-it"
  else
    OPTS="-i"
  fi

  # 拷贝文件模板
  cp docker-compose-e2e-template.yaml docker-compose-e2e.yaml

# 接下来的步骤将使用两个 CA 的私钥文件名的实际值替换模板的内容
  # 当前目录
  CURRENT_DIR=$PWD
  cd crypto-config/peerOrganizations/org1.example.com/ca/
  PRIV_KEY=$(ls *_sk)
  cd "$CURRENT_DIR"
  sed $OPTS "s/CA1_PRIVATE_KEY/$PRIV_KEY/g" docker-compose-e2e.yaml
  cd crypto-config/peerOrganizations/org2.example.com/ca/
  PRIV_KEY=$(ls *_sk)
  cd "$CURRENT_DIR"
  sed $OPTS "s/CA2_PRIVATE_KEY/$PRIV_KEY/g" docker-compose-e2e.yaml
 # 如果是MacOSX,删除docker-compose文件的临时备份
  if [ "$ARCH" == "Darwin" ]; then
    rm docker-compose-e2e.yamlt
  fi

11. 生成组织证书

# 使用 cryptogen 工具生成组织证书
function generateCerts() 
  # 查找crytogen工具
  which cryptogen
  if [ "$?" -ne 0 ]; then
    echo "cryptogen tool not found. exiting"
    exit 1
  fi
  echo
  echo "##########################################################"
  echo "##### Generate certificates using cryptogen tool #########"
  echo "##########################################################"


  if [ -d "crypto-config" ]; then
    rm -Rf crypto-config
  fi
  set -x
  # 执行工具的命令
  cryptogen generate --config=./crypto-config.yaml
  res=$?
  set +x
  if [ $res -ne 0 ]; then
    echo "Failed to generate certificates..."
    exit 1
  fi
  echo
  echo "Generate CCP files for Org1 and Org2"
  # 执行另一个脚本,文件目录里可以看到的,里面放了一写组织的信息 pem文件的位置,启动节点占用的端口
  ./ccp-generate.sh

12. 调用configtxgen工具

# 生成通道工具配置文件,order 块 锚节点配置
# 主要使用configtxgen
# 然后将这些文件输出到“channel-artifacts”文件夹中。
function generateChannelArtifacts() 
  which configtxgen
  if [ "$?" -ne 0 ]; then
    echo "configtxgen tool not found. exiting"
    exit 1
  fi

  # 生成order 创世块
  echo "##########################################################"
  echo "#########  Generating Orderer Genesis block ##############"
  echo "##########################################################"
# 注意:由于某些未知原因(至少现在),块文件不能命名为 orderer.genesis.block 否则排序器将无法启动!
  echo "CONSENSUS_TYPE="$CONSENSUS_TYPE
  set -x
  # 根据公式类型 -profile 定了了公式类型,这是 configtx.yaml里面配置的
  if [ "$CONSENSUS_TYPE" == "solo" ]; then
    configtxgen -profile TwoOrgsOrdererGenesis -channelID $SYS_CHANNEL -outputBlock ./channel-artifacts/genesis.block
  elif [ "$CONSENSUS_TYPE" == "kafka" ]; then
    configtxgen -profile SampleDevModeKafka -channelID $SYS_CHANNEL -outputBlock ./channel-artifacts/genesis.block
  elif [ "$CONSENSUS_TYPE" == "etcdraft" ]; then
    configtxgen -profile SampleMultiNodeEtcdRaft -channelID $SYS_CHANNEL -outputBlock ./channel-artifacts/genesis.block
  else
    set +x
    # 无法识别共识类型
    echo "unrecognized CONSESUS_TYPE='$CONSENSUS_TYPE'. exiting"
    exit 1
  fi
  res=$?
  set +x
  if [ $res -ne 0 ]; then
    echo "Failed to generate orderer genesis block..."
    exit 1
  fi
  # 生成通道配置文件 channel.tx
  echo
  echo "#################################################################"
  echo "### Generating channel configuration transaction 'channel.tx' ###"
  echo "#################################################################"
  set -x
  configtxgen -profile TwoOrgsChannel -outputCreateChannelTx ./channel-artifacts/channel.tx -channelID $CHANNEL_NAME
  res=$?
  set +x
  if [ $res -ne 0 ]; then
    echo "Failed to generate channel configuration transaction..."
    exit 1
  fi
  
  # 生成锚节点
  echo
  echo "#################################################################"
  echo "#######    Generating anchor peer update for Org1MSP   ##########"
  echo "##################################

以上是关于[Fabric] First-NetWork(byfn.sh文件分析)的主要内容,如果未能解决你的问题,请参考以下文章

[Fabric]-First-Network(script.sh文件详解)

[Fabric] First-NetWork(byfn.sh文件分析)

Hyperledger Fabric first-network的初始化启动流程(二)

[Fabric]-First-Network (crypto-config.yaml详解)

Hyperledger Fabric 1.1安装部署-chaincode测试

Fabric 学习路线