[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 "#################################################################"
  set -x
  configtxgen -profile TwoOrgsChannel -outputAnchorPeersUpdate ./channel-artifacts/Org1MSPanchors.tx -channelID $CHANNEL_NAME -asOrg Org1MSP
  res=$?
  set +x
  if [ $res -ne 0 ]; then
    echo "Failed to generate anchor peer update for Org1MSP..."
    exit 1
  fi

  echo
  echo "#################################################################"
  echo "#######    Generating anchor peer update for Org2MSP   ##########"
  echo "#################################################################"
  set -x
  configtxgen -profile TwoOrgsChannel -outputAnchorPeersUpdate \
    ./channel-artifacts/Org2MSPanchors.tx -channelID $CHANNEL_NAME -asOrg Org2MSP
  res=$?
  set +x
  if [ $res -ne 0 ]; then
    echo "Failed to generate anchor peer update for Org2MSP..."
    exit 1
  fi
  echo
}

13. 一些配置信息

# 获取将用于为您的平台选择正确本机二进制文件的操作系统和架构字符串,例如 darwin-amd64 或 linux-amd64
OS_ARCH=$(echo "$(uname -s | tr '[:upper:]' '[:lower:]' | sed 's/mingw64_nt.*/windows/')-$(uname -m | sed 's/x86_64/amd64/g')" | awk '{print tolower($0)}')
# timeout duration - CLI 在放弃之前应该等待来自另一个容器的响应的持续时间
CLI_TIMEOUT=10
# 命令之间的默认延迟
CLI_DELAY=3
# 系统通道名称默认为“byfn-sys-channel”
SYS_CHANNEL="byfn-sys-channel"
# 通道默认名
CHANNEL_NAME="mychannel"
# 默认使用的docker-compose.yaml文件
COMPOSE_FILE=docker-compose-cli.yaml
#
COMPOSE_FILE_COUCH=docker-compose-couch.yaml
# org3 docker compose file
COMPOSE_FILE_ORG3=docker-compose-org3.yaml
# kafka and zookeeper compose file
COMPOSE_FILE_KAFKA=docker-compose-kafka.yaml
# two additional etcd/raft orderers
COMPOSE_FILE_RAFT2=docker-compose-etcdraft2.yaml
# certificate authorities compose file
COMPOSE_FILE_CA=docker-compose-ca.yaml
#
# use golang as the default language for chaincode
LANGUAGE=golang
# default image tag
IMAGETAG="latest"
# default consensus type
CONSENSUS_TYPE="solo"


# Parse commandline args
# 检验 byfn.sh 后面的参数
if [ "$1" = "-m" ]; then # supports old usage, muscle memory is powerful!
  shift
fi
MODE=$1
shift
# Determine whether starting, stopping, restarting, generating or upgrading
if [ "$MODE" == "up" ]; then
  EXPMODE="Starting"
elif [ "$MODE" == "down" ]; then
  EXPMODE="Stopping"
elif [ "$MODE" == "restart" ]; then
  EXPMODE="Restarting"
elif [ "$MODE" == "generate" ]; then
  EXPMODE="Generating certs and genesis block"
elif [ "$MODE" == "upgrade" ]; then
  EXPMODE="Upgrading the network"
else
  printHelp
  exit 1
fi

# 输入不同参数的操作
while getopts "h?c:t:d:f:s:l:i:o:anv" opt; do
  case "$opt" in
  h | \?)
    printHelp
    exit 0
    ;;
  c)
    CHANNEL_NAME=$OPTARG
    ;;
  t)
    CLI_TIMEOUT=$OPTARG
    ;;
  d)
    CLI_DELAY=$OPTARG
    ;;
 
  f)
    COMPOSE_FILE=$OPTARG
    ;;
  s)
    IF_COUCHDB=$OPTARG
    ;;
  l)
    LANGUAGE=$OPTARG
    ;;
  i)
    IMAGETAG=$(go env GOARCH)"-"$OPTARG
    ;;
  o)
    CONSENSUS_TYPE=$OPTARG
    ;;
  a)
    CERTIFICATE_AUTHORITIES=true
    ;;
  n)
    NO_CHAINCODE=true
    ;;
  v)
    VERBOSE=true
    ;;
  esac
done

# 选了couchdb 会调用上面的是否确认

if [ "${IF_COUCHDB}" == "couchdb" ]; then
  echo
  echo "${EXPMODE} for channel '${CHANNEL_NAME}' with CLI timeout of '${CLI_TIMEOUT}' seconds and CLI delay of '${CLI_DELAY}' seconds and using database '${IF_COUCHDB}'"
else
  echo "${EXPMODE} for channel '${CHANNEL_NAME}' with CLI timeout of '${CLI_TIMEOUT}' seconds and CLI delay of '${CLI_DELAY}' seconds"
fi
# ask for confirmation to proceed
 askProceed
 
 #使用docker-compose 构建网络
 if [ "${MODE}" == "up" ]; then
  networkUp
elif [ "${MODE}" == "down" ]; then ## Clear the network
  networkDown
elif [ "${MODE}" == "generate" ]; then ## Generate Artifacts
  generateCerts
  replacePrivateKey
  generateChannelArtifacts
elif [ "${MODE}" == "restart" ]; then ## Restart the network
  networkDown
  networkUp
elif [ "${MODE}" == "upgrade" ]; then ## Upgrade the network from version 1.2.x to 1.3.x
  upgradeNetwork
else
  printHelp
  exit 1
fi

四、输出的日志信息

1. generate

gengerate 作用为生成网络初始化配置,包括MSP证书、私钥、创世区块和配置交易等文件,MSP相关的信息在crypto-config文件夹中,创世区块在channel-artifacts文件夹中,MSP证书和私钥用于不同的网络实体,创世块用于启动排序服务,配置交易文件用于配置通道。

  • 日志信息
root@VM-0-17-ubuntu:/opt/gopath/src/github.com/hyperledger/fabric-samples/first-network# ./byfn.sh -m generate
Generating certs and genesis block for with channel 'mychannel' and CLI timeout of '10' seconds and CLI delay of '3' seconds
Continue (y/n)? y
proceeding ...
/opt/gopath/src/github.com/hyperledger/fabric-samples/first-network/../bin/cryptogen

##########################################################
##### Generate certificates using cryptogen tool #########(1)创建证书
##########################################################
org1.example.com
org2.example.com

/opt/gopath/src/github.com/hyperledger/fabric-samples/first-network/../bin/configtxgen
##########################################################
######### Generating Orderer Genesis block ##############(2)生成创世块
##########################################################
2018-04-17 00:41:28.412 CST [common/configtx/tool] main -> INFO 001 Loading configuration
2018-04-17 00:41:28.454 CST [common/configtx/tool] doOutputBlock -> INFO 002 Generating genesis block
2018-04-17 00:41:28.455 CST [common/configtx/tool] doOutputBlock -> INFO 003 Writing genesis block

#################################################################
### Generating channel configuration transaction 'channel.tx' ###(3)生成通道配置交易文件
#################################################################
2018-04-17 00:41:28.463 CST [common/configtx/tool] main -> INFO 001 Loading configuration
2018-04-17 00:41:28.467 CST [common/configtx/tool] doOutputChannelCreateTx -> INFO 002 Generating new channel configtx
2018-04-17 00:41:28.467 CST [common/configtx/tool] doOutputChannelCreateTx -> INFO 003 Writing new channel tx

#################################################################
####### Generating anchor peer update for Org1MSP ##########(4)在通道上为Org1定义一个锚节点
#################################################################
2018-04-17 00:41:28.475 CST [common/configtx/tool] main -> INFO 001 Loading configuration
2018-04-17 00:41:28.479 CST [common/configtx/tool] doOutputAnchorPeersUpdate -> INFO 002 Generating anchor peer update
2018-04-17 00:41:28.479 CST [common/configtx/tool] doOutputAnchorPeersUpdate -> INFO 003 Writing anchor peer update

#################################################################
####### Generating anchor peer update for Org2MSP ##########(5)在通道上为Org2定义一个锚节点
#################################################################
2018-04-17 00:41:28.487 CST [common/configtx/tool] main -> INFO 001 Loading configuration
2018-04-17 00:41:28.490 CST [common/configtx/tool] doOutputAnchorPeersUpdate -> INFO 002 Generating anchor peer update
2018-04-17 00:41:28.491 CST [common/configtx/tool] doOutputAnchorPeersUpdate -> INFO 003 Writing anchor peer update

在byfn.sh脚本上,依次执行了 generateCerts、 replacePrivateKey、 generateChannelArtifacts三个函数,其中:

generateCerts执行上述(1)中操作;replacePrivateKey将Org1、Org2的证书私钥文件配置到docker-compose-e2e.yaml文件中,以便于后续网络启动时候使用;generateChannelArtifacts执行上述中(2)-(5)中的操作。

2. up

up的功能为启动fabric网络,在启动之前会先检查本地是否有crypto-config文件夹,若没有则会执行generate操作,有则直接根IF_COUCHDB和COMPOSE_FILE变量来选择对应的docker compose配置文件,进而启动网络,默认的goleveldb数据库对应的配置文件为docker-compose-cli.yaml,若启动参数设置为couchdb则对应的配置文件为docker-compose-couch.yaml。docker compose启动docker-compose-cli.yaml 后最后创建的为cli容器,并执行了fabric-samples/first-network/scripts/script.sh脚本,srcipt.sh脚本完成创建通道、加入通道、更新锚节点、安装-初始化-执行链码等一系列的操作。

  • 日志信息
root@VM-0-17-ubuntu:/opt/gopath/src/github.com/hyperledger/fabric-samples/first-network# ./byfn.sh -m up
Starting with channel 'mychannel' and CLI timeout of '10' seconds and CLI delay of '3' seconds
Continue (y/n)? y
proceeding ... #(1)配置容器网络,创建各类容器
Creating peer1.org1.example.com ... done
Creating cli ... done
Creating orderer.example.com ...
Creating peer0.org1.example.com ...
Creating peer1.org1.example.com ...
Creating peer1.org2.example.com ...
Creating cli ...

____ _____ _ ____ _____
/ ___| |_ _| / \ | _ \ |_ _|
\___ \ | | / _ \ | |_) | | |
___) | | | / ___ \ | _ < | |
|____/ |_| /_/ \_\ |_| \_\ |_|

Build your first network (BYFN) end-to-end test
Channel name : mychannel
Creating channel... #(2)创建通道
#核心 peer 节点 的 TLS 证书 文件
CORE_PEER_TLS_ROOTCERT_FILE=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org1.example.com/peers/peer0.org1.example.com/tls/ca.crt
#核心 peer 节点 的 TLS 的 key 文件
CORE_PEER_TLS_KEY_FILE=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org1.example.com/peers/peer0.org1.example.com/tls/server.key

CORE_PEER_LOCALMSPID=Org1MSP
CORE_VM_ENDPOINT=unix:///host/var/run/docker.sock
CORE_PEER_TLS_CERT_FILE=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org1.example.com/peers/peer0.org1.example.com/tls/server.crt
#peer tls 启用
CORE_PEER_TLS_ENABLED=true
#MSP 配置环境/位置
CORE_PEER_MSPCONFIGPATH=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org1.example.com/users/Admin@org1.example.com/msp
CORE_PEER_ID=cli
#日志级别
CORE_LOGGING_LEVEL=DEBUG
#peer 的端口
CORE_PEER_ADDRESS=peer0.org1.example.com:7051
#日志省略
2018-04-16 16:49:44.134 UTC [channelCmd] readBlock -> DEBU 024 Received block:0
2018-04-16 16:49:44.135 UTC [main] main -> INFO 025 Exiting.....
===================== Channel "mychannel" is created successfully =====================
Having all peers join the channel... #(3)将所有的节点加入到该通道中
CORE_PEER_TLS_ROOTCERT_FILE=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org1.example.com/peers/peer0.org1.example.com/tls/ca.crt
CORE_PEER_TLS_KEY_FILE=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org1.example.com/peers/peer0.org1.example.com/tls/server.key
CORE_PEER_LOCALMSPID=Org1MSP
CORE_VM_ENDPOINT=unix:///host/var/run/docker.sock
CORE_PEER_TLS_CERT_FILE=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org1.example.com/peers/peer0.org1.example.com/tls/server.crt
CORE_PEER_TLS_ENABLED=true
CORE_PEER_MSPCONFIGPATH=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org1.example.com/users/Admin@org1.example.com/msp
CORE_PEER_ID=cli
CORE_LOGGING_LEVEL=DEBUG
CORE_PEER_ADDRESS=peer0.org1.example.com:7051
2018-04-16 16:49:44.272 UTC [channelCmd] executeJoin -> INFO 00a Peer joined the channel!
2018-04-16 16:49:44.272 UTC [main] main -> INFO 00b Exiting.....
===================== PEER0 joined on the channel "mychannel" ===================== #(3-1)PEER0(orgt1的peer0)加入到通道中
CORE_PEER_TLS_ROOTCERT_FILE=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org1.example.com/peers/peer0.org1.example.com/tls/ca.crt
CORE_PEER_TLS_KEY_FILE=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org1.example.com/peers/peer0.org1.example.com/tls/server.key
CORE_PEER_LOCALMSPID=Org1MSP
CORE_VM_ENDPOINT=unix:///host/var/run/docker.sock
CORE_PEER_TLS_CERT_FILE=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org1.example.com/peers/peer0.org1.example.com/tls/server.crt
CORE_PEER_TLS_ENABLED=true
CORE_PEER_MSPCONFIGPATH=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org1.example.com/users/Admin@org1.example.com/msp
CORE_PEER_ID=cli
CORE_LOGGING_LEVEL=DEBUG
CORE_PEER_ADDRESS=peer1.org1.example.com:7051
2018-04-16 16:49:47.450 UTC [channelCmd] executeJoin -> INFO 00a Peer joined the channel!
2018-04-16 16:49:47.450 UTC [main] main -> INFO 00b Exiting.....
===================== PEER1 joined on the channel "mychannel" ===================== #(3-2)PEER1(org1的peer1)加入通道
CORE_PEER_TLS_ROOTCERT_FILE=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org2.example.com/peers/peer0.org2.example.com/tls/ca.crt
CORE_PEER_TLS_KEY_FILE=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org1.example.com/peers/peer0.org1.example.com/tls/server.key
CORE_PEER_LOCALMSPID=Org2MSP
CORE_VM_ENDPOINT=unix:///host/var/run/docker.sock
CORE_PEER_TLS_CERT_FILE=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org1.example.com/peers/peer0.org1.example.com/tls/server.crt
CORE_PEER_TLS_ENABLED=true
CORE_PEER_MSPCONFIGPATH=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org2.example.com/users/Admin@org2.example.com/msp
CORE_PEER_ID=cli
CORE_LOGGING_LEVEL=DEBUG
CORE_PEER_ADDRESS=peer0.org2.example.com:7051
2018-04-16 16:49:50.595 UTC [channelCmd] executeJoin -> INFO 00a Peer joined the channel!
2018-04-16 16:49:50.595 UTC [main] main -> INFO 00b Exiting.....
===================== PEER2 joined on the channel "mychannel" ===================== #(3-3)PEER2(org2的peer0)加入通道
CORE_PEER_TLS_ROOTCERT_FILE=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org2.example.com/peers/peer0.org2.example.com/tls/ca.crt
CORE_PEER_TLS_KEY_FILE=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org1.example.com/peers/peer0.org1.example.com/tls/server.key
CORE_PEER_LOCALMSPID=Org2MSP
CORE_VM_ENDPOINT=unix:///host/var/run/docker.sock
CORE_PEER_TLS_CERT_FILE=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org1.example.com/peers/peer0.org1.example.com/tls/server.crt
CORE_PEER_TLS_ENABLED=true
CORE_PEER_MSPCONFIGPATH=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org2.example.com/users/Admin@org2.example.com/msp
CORE_PEER_ID=cli
CORE_LOGGING_LEVEL=DEBUG
CORE_PEER_ADDRESS=peer1.org2.example.com:7051
2018-04-16 16:49:53.765 UTC [channelCmd] executeJoin -> INFO 00a Peer joined the channel!
2018-04-16 16:49:53.765 UTC [main] main -> INFO 00b Exiting.....
===================== PEER3 joined on the channel "mychannel" =====================# (3-4)PEER3(org2的peer1)加入通道
Updating anchor peers for org1...#(4)配置锚节点 (4-1)为org1配置锚节点  配置通讯节点
CORE_PEER_TLS_ROOTCERT_FILE=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org1.example.com/peers/peer0.org1.example.com/tls/ca.crt
CORE_PEER_TLS_KEY_FILE=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org1.example.com/peers/peer0.org1.example.com/tls/server.key
CORE_PEER_LOCALMSPID=Org1MSP
CORE_VM_ENDPOINT=unix:///host/var/run/docker.sock
CORE_PEER_TLS_CERT_FILE=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org1.example.com/peers/peer0.org1.example.com/tls/server.crt
CORE_PEER_TLS_ENABLED=true
CORE_PEER_MSPCONFIGPATH=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org1.example.com/users/Admin@org1.example.com/msp
CORE_PEER_ID=cli
CORE_LOGGING_LEVEL=DEBUG
CORE_PEER_ADDRESS=peer0.org1.example.com:7051
2018-04-16 16:49:56.858 UTC [main] main -> INFO 014 Exiting.....
===================== Anchor peers for org "Org1MSP" on "mychannel" is updated successfully =====================
Updating anchor peers for org2...(4-2)为org2配置锚节点
CORE_PEER_TLS_ROOTCERT_FILE=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org2.example.com/peers/peer0.org2.example.com/tls/ca.crt
CORE_PEER_TLS_KEY_FILE=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org1.example.com/peers/peer0.org1.example.com/tls/server.key
CORE_PEER_LOCALMSPID=Org2MSP
CORE_VM_ENDPOINT=unix:///host/var/run/docker.sock
CORE_PEER_TLS_CERT_FILE=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org1.example.com/peers/peer0.org1.example.com/tls/server.crt
CORE_PEER_TLS_ENABLED=true
CORE_PEER_MSPCONFIGPATH=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org2.example.com/users/Admin@org2.example.com/msp
CORE_PEER_ID=cli
CORE_LOGGING_LEVEL=DEBUG
CORE_PEER_ADDRESS=peer0.org2.example.com:7051
2018-04-16 16:49:59.971 UTC [main] main -> INFO 014 Exiting.....
===================== Anchor peers for org "Org2MSP" on "mychannel" is updated successfully =====================
Installing chaincode on org1/peer0...#(5)链码操作 (5-1)在PEER0上安装链码
CORE_PEER_TLS_ROOTCERT_FILE=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org1.example.com/peers/peer0.org1.example.com/tls/ca.crt
CORE_PEER_TLS_KEY_FILE=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org1.example.com/peers/peer0.org1.example.com/tls/server.key
CORE_PEER_LOCALMSPID=Org1MSP
CORE_VM_ENDPOINT=unix:///host/var/run/docker.sock
CORE_PEER_TLS_CERT_FILE=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org1.example.com/peers/peer0.org1.example.com/tls/server.crt
CORE_PEER_TLS_ENABLED=true
CORE_PEER_MSPCONFIGPATH=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org1.example.com/users/Admin@org1.example.com/msp
CORE_PEER_ID=cli
CORE_LOGGING_LEVEL=DEBUG
CORE_PEER_ADDRESS=peer0.org1.example.com:7051

2018-04-16 16:50:03.064 UTC [msp] GetLocalMSP -> DEBU 005 Returning existing local MSP
2018-04-16 16:50:03.064 UTC [msp] GetDefaultSigningIdentity -> DEBU 006 Obtaining default signing identity
#使用默认的背书系统链码
2018-04-16 16:50:03.064 UTC [chaincodeCmd] checkChaincodeCmdParams -> INFO 007 Using default escc
#使用默认的验证系统链码 根据背书策略验证交易
2018-04-16 16:50:03.064 UTC [chaincodeCmd] checkChaincodeCmdParams -> INFO 008 Using default vscc
#go 平台 链码
2018-04-16 16:50:03.160 UTC [golang-platform] getCodeFromFS -> DEBU 009 getCodeFromFS github.com/chaincode/chaincode_example02/go/
#丢弃
2018-04-16 16:50:03.323 UTC [golang-platform] func1 -> DEBU 00a Discarding GOROOT package fmt
2018-04-16 16:50:03.323 UTC [golang-platform] func1 -> DEBU 00b Discarding provided package github.com/hyperledger/fabric/core/chaincode/shim
2018-04-16 16:50:03.323 UTC [golang-platform] func1 -> DEBU 00c Discarding provided package github.com/hyperledger/fabric/protos/peer
2018-04-16 16:50:03.323 UTC [golang-platform] func1 -> DEBU 00d Discarding GOROOT package strconv
2018-04-16 16:50:03.323 UTC [golang-platform] GetDeploymentPayload -> DEBU 00e done
2018-04-16 16:50:03.325 UTC [msp/identity] Sign -> DEBU 00f Sign: plaintext: 0A8A070A5C08031A0C08BBA8D3D60510...F619FF0E0000FFFFACD4020D001C0000
2018-04-16 16:50:03.325 UTC [msp/identity] Sign -> DEBU 010 Sign: digest: 25E15A5C9A37538928052AF2557C4D5093FAB5C8E6D77095A08CE076F01C1EE6
#远程安装 获取响应
2018-04-16 16:50:03.331 UTC [chaincodeCmd] install -> DEBU 011 Installed remotely response:<status:200 payload:"OK" >
2018-04-16 16:50:03.331 UTC [main] main -> INFO 012 Exiting.....
===================== Chaincode is installed on remote peer PEER0 =====================
Install chaincode on org2/peer2...#(5-2)在PEER2上安装链码
CORE_PEER_TLS_ROOTCERT_FILE=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org2.example.com/peers/peer0.org2.example.com/tls/ca.crt
CORE_PEER_TLS_KEY_FILE=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org1.example.com/peers/peer0.org1.example.com/tls/server.key
CORE_PEER_LOCALMSPID=Org2MSP
CORE_VM_ENDPOINT=unix:///host/var/run/docker.sock
CORE_PEER_TLS_CERT_FILE=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org1.example.com/peers/peer0.org1.example.com/tls/server.crt
CORE_PEER_TLS_ENABLED=true
CORE_PEER_MSPCONFIGPATH=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org2.example.com/users/Admin@org2.example.com/msp
CORE_PEER_ID=cli
CORE_LOGGING_LEVEL=DEBUG
CORE_PEER_ADDRESS=peer0.org2.example.com:7051
2018-04-16 16:50:03.388 UTC [msp] GetLocalMSP -> DEBU 005 Returning existing local MSP
2018-04-16 16:50:03.388 UTC [msp] GetDefaultSigningIdentity -> DEBU 006 Obtaining default signing identity
2018-04-16 16:50:03.388 UTC [chaincodeCmd] checkChaincodeCmdParams -> INFO 007 Using default escc
2018-04-16 16:50:03.388 UTC [chaincodeCmd] checkChaincodeCmdParams -> INFO 008 Using default vscc
2018-04-16 16:50:03.476 UTC [golang-platform] getCodeFromFS -> DEBU 009 getCodeFromFS github.com/chaincode/chaincode_example02/go/
2018-04-16 16:50:03.635 UTC [golang-platform] func1 -> DEBU 00a Discarding GOROOT package fmt
2018-04-16 16:50:03.635 UTC [golang-platform] func1 -> DEBU 00b Discarding provided package github.com/hyperledger/fabric/core/chaincode/shim
2018-04-16 16:50:03.635 UTC [golang-platform] func1 -> DEBU 00c Discarding provided package github.com/hyperledger/fabric/protos/peer
2018-04-16 16:50:03.635 UTC [golang-platform] func1 -> DEBU 00d Discarding GOROOT package strconv
2018-04-16 16:50:03.635 UTC [golang-platform] GetDeploymentPayload -> DEBU 00e done
2018-04-16 16:50:03.636 UTC [msp/identity] Sign -> DEBU 00f Sign: plaintext: 0A8A070A5C08031A0C08BBA8D3D60510...F619FF0E0000FFFFACD4020D001C0000
2018-04-16 16:50:03.636 UTC [msp/identity] Sign -> DEBU 010 Sign: digest: 52F065F4A5A31D2737E6A380AFD5FC302A15C3976B809F560627B1EECC0FA0BD
2018-04-16 16:50:03.644 UTC [chaincodeCmd] install -> DEBU 011 Installed remotely response:<status:200 payload:"OK" >
2018-04-16 16:50:03.644 UTC [main] main -> INFO 012 Exiting.....
===================== Chaincode is installed on remote peer PEER2 =====================
Instantiating chaincode on org2/peer2...#(5-3)在PEER2上初始化链码
CORE_PEER_TLS_ROOTCERT_FILE=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org2.example.com/peers/peer0.org2.example.com/tls/ca.crt
CORE_PEER_TLS_KEY_FILE=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org1.example.com/peers/peer0.org1.example.com/tls/server.key
CORE_PEER_LOCALMSPID=Org2MSP
CORE_VM_ENDPOINT=unix:///host/var/run/docker.sock
CORE_PEER_TLS_CERT_FILE=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org1.example.com/peers/peer0.org1.example.com/tls/server.crt
CORE_PEER_TLS_ENABLED=true
CORE_PEER_MSPCONFIGPATH=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org2.example.com/users/Admin@org2.example.com/msp
CORE_PEER_ID=cli
CORE_LOGGING_LEVEL=DEBUG
CORE_PEER_ADDRESS=peer0.org2.example.com:7051
2018-04-16 16:50:03.721 UTC [msp] GetLocalMSP -> DEBU 005 Returning existing local MSP
2018-04-16 16:50:03.721 UTC [msp] GetDefaultSigningIdentity -> DEBU 006 Obtaining default signing identity
2018-04-16 16:50:03.725 UTC [chaincodeCmd] checkChaincodeCmdParams -> INFO 007 Using default escc
2018-04-16 16:50:03.725 UTC [chaincodeCmd] checkChaincodeCmdParams -> INFO 008 Using default vscc
2018-04-16 16:50:03.726 UTC [msp/identity] Sign -> DEBU 009 Sign: plaintext: 0A95070A6708031A0C08BBA8D3D60510...324D53500A04657363630A0476736363
2018-04-16 16:50:03.726 UTC [msp/identity] Sign -> DEBU 00a Sign: digest: A28ADB7847779748A9D2C017443F44EC040E6B4C5AD5A65A1BD2E177346037A8
2018-04-16 16:50:33.340 UTC [msp/identity] Sign -> DEBU 00b Sign: plaintext: 0A95070A6708031A0C08BBA8D3D60510...F643949B1AAD248D2662B19249FB451B
2018-04-16 16:50:33.340 UTC [msp/identity] Sign -> DEBU 00c Sign: digest: 230E103BE1059EB3764AD6EAC0CE6C785063A5A597CA04535FA91A751A693534
2018-04-16 16:50:33.344 UTC [main] main -> INFO 00d Exiting.....
===================== Chaincode Instantiation on PEER2 on channel 'mychannel' is successful =====================
Querying chaincode on org1/peer0... #(5-4)执行query操作 在org1的peer0上查询
===================== Querying on PEER0 on channel 'mychannel'... =====================
CORE_PEER_TLS_ROOTCERT_FILE=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org1.example.com/peers/peer0.org1.example.com/tls/ca.crt
CORE_PEER_TLS_KEY_FILE=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org1.example.com/peers/peer0.org1.example.com/tls/server.key
CORE_PEER_LOCALMSPID=Org1MSP
CORE_VM_ENDPOINT=unix:///host/var/run/docker.sock
CORE_PEER_TLS_CERT_FILE=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org1.example.com/peers/peer0.org1.example.com/tls/server.crt
CORE_PEER_TLS_ENABLED=true
CORE_PEER_MSPCONFIGPATH=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org1.example.com/users/Admin@org1.example.com/msp
CORE_PEER_ID=cli
CORE_LOGGING_LEVEL=DEBUG
CORE_PEER_ADDRESS=peer0.org1.example.com:7051
#正在尝试查询
Attempting to Query PEER0 ...3 secs
#未在以下文件找到证书文件
2018-04-16 16:50:36.412 UTC [msp] getMspConfig -> WARN 001 Intermediate certs folder not found at [/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org1.example.com/users/Admin@org1.example.com/msp/intermediatecerts]. Skipping. [stat /opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org1.example.com/users/[email protected]/msp/intermediatecerts: no such file or directory]
2018-04-16 16:50:36.412 UTC [msp] getMspConfig -> WARN 002 TLS intermediate certs folder not found at [/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org1.example.com/users/Admin@org1.example.com/msp/tlsintermediatecerts]. Skipping. [stat /opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org1.example.com/users/[email protected]/msp/tlsintermediatecerts: no such file or directory]
2018-04-16 16:50:36.412 UTC [msp] getMspConfig -> WARN 003 crls folder not found at [/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org1.example.com/users/Admin@org1.example.com/msp/crls]. Skipping. [stat /opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org1.example.com/users/[email protected]/msp/crls: no such file or directory]
2018-04-16 16:50:36.412 UTC [msp] getMspConfig -> INFO 004 MSP configuration file not found at [/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org1.example.com/users/Admin@org1.example.com/msp/config.yaml]: [stat /opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org1.example.com/users/[email protected]/msp/config.yaml: no such file or directory]
2018-04-16 16:50:36.444 UTC [msp] GetLocalMSP -> DEBU 005 Returning existing local MSP
2018-04-16 16:50:36.444 UTC [msp] GetDefaultSigningIdentity -> DEBU 006 Obtaining default signing identity
2018-04-16 16:50:36.444 UTC [chaincodeCmd] checkChaincodeCmdParams -> INFO 007 Using default escc
2018-04-16 16:50:36.444 UTC [chaincodeCmd] checkChaincodeCmdParams -> INFO 008 Using default vscc
2018-04-16 16:50:36.444 UTC [msp/identity] Sign -> DEBU 009 Sign: plaintext: 0A95070A6708031A0C08DCA8D3D60510...6D7963631A0A0A0571756572790A0161
2018-04-16 16:50:36.444 UTC [msp/identity] Sign -> DEBU 00a Sign: digest: 79AD20D743C6A88C998AC1C4C77C704AE1D2D1267F05D7D32595F3D2F63E644C
Query Result: 100
2018-04-16 16:50:59.876 UTC [main] main -> INFO 00b Exiting.....
===================== Query on PEER0 on channel 'mychannel' is successful =====================
Sending invoke transaction on org1/peer0...#(5-5)执行invoke操作  发送 invoke  事务
CORE_PEER_TLS_ROOTCERT_FILE=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org1.example.com/peers/peer0.org1.example.com/tls/ca.crt
CORE_PEER_TLS_KEY_FILE=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org1.example.com/peers/peer0.org1.example.com/tls/server.key
CORE_PEER_LOCALMSPID=Org1MSP
CORE_VM_ENDPOINT=unix:///host/var/run/docker.sock
CORE_PEER_TLS_CERT_FILE=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org1.example.com/peers/peer0.org1.example.com/tls/server.crt
CORE_PEER_TLS_ENABLED=true
CORE_PEER_MSPCONFIGPATH=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org1.example.com/users/Admin@org1.example.com/msp
CORE_PEER_ID=cli
CORE_LOGGING_LEVEL=DEBUG
CORE_PEER_ADDRESS=peer0.org1.example.com:7051
2018-04-16 16:51:00.085 UTC [msp] GetLocalMSP -> DEBU 005 Returning existing local MSP
2018-04-16 16:51:00.085 UTC [msp] GetDefaultSigningIdentity -> DEBU 006 Obtaining default signing identity
2018-04-16 16:51:00.088 UTC [chaincodeCmd] checkChaincodeCmdParams -> INFO 007 Using default escc
2018-04-16 16:51:00.088 UTC [chaincodeCmd] checkChaincodeCmdParams -> INFO 008 Using default vscc
2018-04-16 16:51:00.089 UTC [msp/identity] Sign -> DEBU 009 Sign: plaintext: 0A94070A6608031A0B08F4A8D3D60510...696E766F6B650A01610A01620A023130
2018-04-16 16:51:00.089 UTC [msp/identity] Sign -> DEBU 00a Sign: digest: 4641A54D852486C075129E3F19CB7777DB38AA1BAB2652C3CFD92B5AFDB97C54
2018-04-16 16:51:00.107 UTC [msp/identity] Sign -> DEBU 00b Sign: plaintext: 0A94070A6608031A0B08F4A8D3D60510...3BE1BF33CC319B542AE9E5147739325E
2018-04-16 16:51:00.107 UTC [msp/identity] Sign -> DEBU 00c Sign: digest: 6245296F4A4DAAB60986EEAE31420B6A1163818AE62BE8D4DFEA913AD45E5BBB
#链码 调用 或 查询 背书系统链码 调用 结果
2018-04-16 16:51:00.110 UTC [chaincodeCmd] chaincodeInvokeOrQuery -> DEBU 00d ESCC invoke result: version:1 response:<status:200 message:"OK" >
#负担
payload:"\n \306\232\"\260\244,\234\324\263\021\376\325\312\370\002\030\221 \212R.q\246\007\001\307\271rV\237\334\005\022Y\nE\022\024\n\004lscc\022\014\n\n\n\004mycc\022\002\010\003\022-\n\004mycc\022%\n\007\n\001a\022\002\010\003\n\007\n\001b\022\002\010\003\032\007\n\001a\032\00290\032\010\n\001b\032\003210\032\003\010\310\001\"\013\022\004mycc\032\0031.0" 
#背书 代言人
endorsement:<endorser:"\n\007Org1MSP\022\374\005-----BEGIN -----\nMIICGDCCAb+gAwIBAgIQNMk/6oe9nv59nfY5UqOrGjAKBggqhkjOPQQDAjBzMQsw\nCQYDVQQGEwJVUzETMBEGA1UECBMKQ2FsaWZvcm5pYTEWMBQGA1UEBxMNU2FuIEZy\nYW5jaXNjbzEZMBcGA1UEChMQb3JnMS5leGFtcGxlLmNvbTEcMBoGA1UEAxMTY2Eu\nb3JnMS5leGFtcGxlLmNvbTAeFw0xODA0MTYxNjQ5MzlaFw0yODA0MTMxNjQ5Mzla\nMFsxCzAJBgNVBAYTAlVTMRMwEQYDVQQIEwpDYWxpZm9ybmlhMRYwFAYDVQQHEw1T\nYW4gRnJhbmNpc2NvMR8wHQYDVQQDExZwZWVyMC5vcmcxLmV4YW1wbGUuY29tMFkw\nEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEsJcLt2s0ZxSrHyMcgCXe9os8plqTtdX5\nfYNd61IZJ1Fv4a5rHMnXFPJ9NemoIDZjENGDX+pFFeEA3bj2QffVbKNNMEswDgYD\nVR0PAQH/BAQDAgeAMAwGA1UdEwEB/wQCMAAwKwYDVR0jBCQwIoAg2zNFuR8577Mf\neYc49BNvW7pZ6iR/h4WkhxU799509E4wCgYIKoZIzj0EAwIDRwAwRAIgerYUzXci\nyxW1S3/N3B+KelJmdpDp2YlhgPg00BAyCZoCIA/m0Ya3v559KucqOpd1havAw5T6\nsyg2wAVDlbtS7QUG\n-----END -----\n" 
#签名
signature:"0E\002!\000\3225\000K\t\\\2374\356ueu\244\032~\251\254ph\332\030+\222vG\327/\2506\337\032L\002 \005r\362\346\231u\355g\337z\221\005e\341\033o;\341\2773\3141\233T*\351\345\024w92^" >
2018-04-16 16:51:00.110 UTC [chaincodeCmd] chaincodeInvokeOrQuery -> INFO 00e Chaincode invoke successful. result: status:200
2018-04-16 16:51:00.110 UTC [main] main -> INFO 00f Exiting.....
===================== Invoke transaction on PEER0 on channel 'mychannel' is successful ===================== 、
Installing chaincode on org2/peer3...#5(5-6)在PEER3上安装链码
CORE_PEER_TLS_ROOTCERT_FILE=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org2.example.com/peers/peer0.org2.example.com/tls/ca.crt
CORE_PEER_TLS_KEY_FILE=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org1.example.com/peers/peer0.org1.example.com/tls/server.key
CORE_PEER_LOCALMSPID=Org2MSP
CORE_VM_ENDPOINT=unix:///host/var/run/docker.sock
CORE_PEER_TLS_CERT_FILE=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org1.example.com/peers/peer0.org1.example.com/tls/server.crt
CORE_PEER_TLS_ENABLED=true
CORE_PEER_MSPCONFIGPATH=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org2.example.com/users/Admin@org2.example.com/msp
CORE_PEER_ID=cli
CORE_LOGGING_LEVEL=DEBUG
CORE_PEER_ADDRESS=peer1.org2.example.com:7051
2018-04-16 16:51:00.168 UTC [msp] GetLocalMSP -> DEBU 005 Returning existing local MSP
2018-04-16 16:51:00.168 UTC [msp] GetDefaultSigningIdentity -> DEBU 006 Obtaining default signing identity
2018-04-16 16:51:00.168 UTC [chaincodeCmd] checkChaincodeCmdParams -> INFO 007 Using default escc
2018-04-16 16:51:00.168 UTC [chaincodeCmd] checkChaincodeCmdParams -> INFO 008 Using default vscc
2018-04-16 16:51:00.223 UTC [golang-platform] getCodeFromFS -> DEBU 009 getCodeFromFS github.com/chaincode/chaincode_example02/go/
2018-04-16 16:51:00.402 UTC [golang-platform] func1 -> DEBU 00a Discarding GOROOT package fmt
2018-04-16 16:51:00.402 UTC [golang-platform] func1 -> DEBU 00b Discarding provided package github.com/hyperledger/fabric/core/chaincode/shim
2018-04-16 16:51:00.402 UTC [golang-platform] func1 -> DEBU 00c Discarding provided package github.com/hyperledger/fabric/protos/peer
2018-04-16 16:51:00.402 UTC [golang-platform] func1 -> DEBU 00d Discarding GOROOT package strconv
2018-04-16 16:51:00.402 UTC [golang-platform] GetDeploymentPayload -> DEBU 00e done
2018-04-16 16:51:00.403 UTC [msp/identity] Sign -> DEBU 00f Sign: plaintext: 0A8A070A5C08031A0C08F4A8D3D60510...F619FF0E0000FFFFACD4020D001C0000
2018-04-16 16:51:00.403 UTC [msp/identity] Sign -> DEBU 010 Sign: digest: 315459862B61D5E51AB94A20DB7734951AC57913FA0D2DE6597C82778ACA88AA
2018-04-16 16:51:00.409 UTC [chaincodeCmd] install -> DEBU 011 Installed remotely response:<status:200 payload:"OK" >
2018-04-16 16:51:00.409 UTC [main] main -> INFO 012 Exiting.....
===================== Chaincode is installed on remote peer PEER3 =====================
Querying chaincode on org2/peer3...# (5-7)执行query操作 查询org2的 peer3节点
===================== Querying on PEER3 on channel 'mychannel'... =====================
CORE_PEER_TLS_ROOTCERT_FILE=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org2.example.com/peers/peer0.org2.example.com/tls/ca.crt
CORE_PEER_TLS_KEY_FILE=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org1.example.com/peers/peer0.org1.example.com/tls/server.key
CORE_PEER_LOCALMSPID=Org2MSP
CORE_VM_ENDPOINT=unix:///host/var/run/docker.sock
CORE_PEER_TLS_CERT_FILE=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org1.example.com/peers/peer0.org1.example.com/tls/server.crt
CORE_PEER_TLS_ENABLED=true
CORE_PEER_MSPCONFIGPATH=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org2.example.com/users/Admin@org2.example.com/msp
CORE_PEER_ID=cli
CORE_LOGGING_LEVEL=DEBUG
CORE_PEER_ADDRESS=peer1.org2.example.com:7051
Attempting to Query PEER3 ...3 secs
2018-04-16 16:51:03.497 UTC [msp] GetDefaultSigningIdentity -> DEBU 006 Obtaining default signing identity
2018-04-16 16:51:03.497 UTC [chaincodeCmd] checkChaincodeCmdParams -> INFO 007 Using default escc
2018-04-16 16:51:03.497 UTC [chaincodeCmd] checkChaincodeCmdParams -> INFO 008 Using default vscc
2018-04-16 16:51:03.497 UTC [msp/identity] Sign -> DEBU 009 Sign: plaintext: 0A95070A6708031A0C08F7A8D3D60510...6D7963631A0A0A0571756572790A0161
2018-04-16 16:51:03.497 UTC [msp/identity] Sign -> DEBU 00a Sign: digest: 71796FF598D19E3901EE73B08DBF550D8EA6FBFE8FE087B60EDEEA819BAA9306
Query Result: 90
2018-04-16 16:51:25.547 UTC [main] main -> INFO 00b Exiting.....
===================== Query on PEER3 on channel 'mychannel' is successful =====================
#一切正常,执行完毕
========= All GOOD, BYFN execution completed ===========


_____ _ _ ____
| ____| | \ | | | _ \
| _| | \| | | | | |
| |___ | |\ | | |_| |
|_____| |_| \_| |____/

在这里插入图片描述

执行过程

  1. 配置容器网络,创建各类容器

    docker-compose 根据 docker-compose-cli.yaml 配置容器网络和相应的容器

  2. 创建通道

    script.sh执行createChannel函数创建一个通道

  3. 将所有的节点加入到该通道中

    script.sh执行joinChannel函数依次将4个节点加入到通道中

    • PEER0 (org1的peer0)加入通道
    • PEER1 (org1的peer1)加入通道
    • PEER2(org2的peer0)加入通道
    • PEER3(org2的peer1)加入通道
  4. 配置锚节点

    scrip.sh脚本执行updateAnchorPeers函数依次为org1、Org2配置锚节点

    • 为org1配置锚节点
    • 为org2配置锚节点
  5. 链码操作

    script.sh 脚本执行installChainCode、instantiateChainCode、 chaincodeQuery、chaincodeInvoke等函数安装、实例化、查询、调用等操作

    • 在PEER0上安装链码
    • 在PEER2上安装链码
    • 在PEER2上初始化链码
    • 执行query操作
    • 执行invoke操作
    • 在PEER3上安装链码
    • 执行query操作

3. down

down的功能为关闭超级账本网络,具体包括删除容器和不必要的镜像文件,其主调函数为byfn.sh的networkDown,该函数会执行clearContainers、removeUnwantedImages函数,然后在删除generate产生的一系列文件和目录。

  • 日志信息
root@VM-0-17-ubuntu:/opt/gopath/src/github.com/hyperledger/fabric-samples/first-network# ./byfn.sh -m down
Stopping with channel 'mychannel' and CLI timeout of '10' seconds and CLI delay of '3' seconds
Continue (y/n)? y
proceeding ...#(1)删除相关的容器
WARNING: The CHANNEL_NAME variable is not set. Defaulting to a blank string.
WARNING: The DELAY variable is not set. Defaulting to a blank string.
WARNING: The TIMEOUT variable is not set. Defaulting to a blank string.
#停止节点
Stopping peer0.org1.example.com ... done
Stopping peer1.org2.example.com ... done
Stopping orderer.example.com ... done
Stopping peer1.org1.example.com ... done
Stopping peer0.org2.example.com ... done
#删除节点
Removing cli ... done
Removing peer0.org1.example.com ... done
Removing peer1.org2.example.com ... done
Removing orderer.example.com ... done
Removing peer1.org1.example.com ... done
Removing peer0.org2.example.com ... done
#移除docker配置的网络
Removing network net_byfn
WARNING: The CHANNEL_NAME variable is not set. Defaulting to a blank string.
WARNING: The DELAY variable is not set. Defaulting to a blank string.
WARNING: The TIMEOUT variable is not set. Defaulting to a blank string.
Removing network net_byfn
WARNING: Network net_byfn not found.
002e468cdba9
170f5d85d314
3b33620503ac
Untagged: dev-peer1.org2.example.com-mycc-1.0:latest #(2)删除镜像
Deleted: sha256:7fad397db58136ffbf954e0a72f3c434a3950259326c138d97fc86a7296b6642
Deleted: sha256:ef2096acef7eae3d1ab6b0b20f7f7d8c759125d3626f24905cb593b55e8b85ed
Deleted: sha256:eb5e22f8804403158339edb3a54a35a6c0e8402f0aee43eab26e5873119920a4
Deleted: sha256:e15cafcb79a3ed9652d231da057d775a0d9fb29b9b1ea496ffe4c3ac6a6c0a66
Deleted: sha256:79ef483a25f7c37d74fb9818e42e19583827d92d9f4fbd4fc8e7d91db6d12599
Deleted: sha256:8697581945d43243c4f948ec9a2aaad2d1150be284872c7e179f87194e7b5667
Deleted: sha256:e2eeb15c5867c453f7d334ad367ad57a5c5f298b7cb0a4cc75a137ff82ba1aa5
Untagged: dev-peer0.org1.example.com-mycc-1.0:latest
Deleted: sha256:450a145d8868220dc42a60f9a767207df65bba76cb25428f3966724150df739a
Deleted: sha256:174485b27a3f841009e5163d2b272b513ec1c1827e51fed82aa1561ff5181004
Deleted: sha256:200f28cfe057c90071a556a593900a45b6467085735b450355371cc2523ba324
Deleted: sha256:f469bc994653b1c9d880180b4d60a29f892562c5fdc951735a549d8a90d3a0ac
Deleted: sha256:94746de84825fd293ea7fa6266b40758ce4f173a6768b95861a7c1c7346f1aa8
Deleted: sha256:021ad292a7d4976239e4e29a1fed4a3661540d75aa8df05fbe13ed51b5a41eab
Deleted: sha256:7342cd488424d969db765a86d61be699556274cd02b3b3290adc2916063a31f3
Untagged: dev-peer0.org2.example.com-mycc-1.0:latest
Deleted: sha256:5cefcfdaf561bce2f3221c3adf900de1d07b7d3d8a940d01d7fd7c1217832a7f
Deleted: sha256:161b4f823bee25a150e15c3400816c05f2f92e627909406f33710c386b29ff07
Deleted: sha256:2ef7d8c764baa7cbccce0f2f8dcdb51053f5894ffa4350869e028b5382013a6d
Deleted: sha256:49a379a5d3ae4fc848119e4e001fe1d6e59c2210582ad3572342a273113facb8
Deleted: sha256:ae022b203e0f13d0b8355a8843dd9a8260ee4e4f23d9fd2be4ab5a656c83efb1
Deleted: sha256:5d82c68f6c22af99c660898c4ca34b730fe68beddbc4e1c9cb425fd2bbd5c4a3
Deleted: sha256:fa449353db192aa55f4064dff52e0a8516ee8389ffb19a7c87ca4f798e076a71
root@VM-0-17-ubuntu:/opt/gopath/src/github.com/hyperledger/fabric-samples/first-network#

此处需要注意的是,clearContainers函数会执行,CONTAINER_IDS=${docker ps -aq} docker rm -f $CONTAINER_IDS操作,该操作会删除所有的容器,

猜你喜欢

转载自blog.csdn.net/m0_56186460/article/details/122267627
今日推荐