Hyperledger Fabric 应用实战(8)-- 智能合约部署脚本

1. 链码部署脚本思路

上章中分析了test-netwok的网络启动脚本,其中包含了链码部署部分,我们通过分析test-netwok的deployCC来梳理链码部署思路,进而编写freenet网络链码部署脚本。

在这里插入图片描述

  • pakeageChaincode(): 将链码链码打包为既定的格式(tar.gz文件);
  • installChaincode(): 将打包好的链码安装在需要的peer节点上;
  • queryInstalled(): 查询链码是否已经安装至peer节点上;
  • approveForMyOrg():多个成员对链码进行批准,每个peer上的节点都应该是一致的;
  • checkCommitReadiness():来审核一个链码是否符合通道的标准,也就是是否达到既定的多成员批准的设定;
  • commitChaincodeDefinition():将链码安装至通道上;
  • queryCommitted():通道的各组织查询是否已经被提交至通道上;

Fabric2.X版本对链码的生命周期做了优化,目前的链码逻辑较为清晰易懂,通道上各个组织按照一个代码逻辑去运行业务,每一步都蛮合理和易懂。

2. 链码部署脚本编写

链码部署脚本整体逻辑比较简单,test-network中脚本作为官方案例肯定是相当的完善,所以对shell脚本不熟悉看起来就会比较吃力,其中部分Shell脚本函数个人也仅将他作为一个整体去理解,以理解大体思路和调通链码部署脚本为最终目的,修改编写也非常容易出错。

2.1 链码打包与安装

链码脚本的公共参数配置,CC_COLL_CONFIG暂时还不需要。

CHANNEL_NAME="$1"
DELAY="$2"
MAX_RETRY="$3"
VERBOSE="$4"
CC_NAME="$5"
CC_VERSION="$6"
CC_END_POLICY="$9"
#CC_COLL_CONFIG="${10}"
CC_INIT_FCN="${11}"
CC_SRC_LANGUAGE="${12}"
: ${CHANNEL_NAME:="rentsign"}
: ${DELAY:="10"}
: ${MAX_RETRY:="3"}
: ${VERBOSE:="false"}
: ${CC_NAME:="freerent"}
: ${CC_VERSION:="v1"}
: ${CC_SEQUENCE:="1"}
# 结合cliup 工作目录
#: ${CC_COLL_CONFIG:="./network/artifacts/collections_config.json"}
: ${CC_INIT_FCN:="init"}
: ${CC_SRC_LANGUAGE:="golang"}

CC_RUNTIME_LANGUAGE=golang

# import utils
. scripts/env-var.sh

infoln "Deploy chaincode in $DOMAIN_OF_NETWORK network"
debugln "  - CHANNEL_NAME: '$CHANNEL_NAME'"
debugln "  - CC_NAME: '$CC_NAME'"
debugln "  - CC_SRC_PATH: '$CC_SRC_PATH'"
debugln "  - CC_SRC_LANGUAGE: '$CC_SRC_LANGUAGE'"
debugln "  - CC_VERSION: '$CC_VERSION'"
#debugln "  - CC_COLL_CONFIG: '$CC_COLL_CONFIG'"


## Install chaincode
infoln "Installing chaincode on supervisor"
for peer in 0 1 2 ; do
  installChaincode supervisor $peer
done

infoln "Installing chaincode on rentalcrop"
for peer in 0 1; do
  installChaincode rentalcrop $peer
done

infoln "Installing chaincode on agency"
for peer in 0 1; do
  installChaincode agency $peer
done

## query whether the chaincode is installed
queryInstalled supervisor 0
queryInstalled rentalcrop 0
queryInstalled agency 0

## approve the definition for dispatcher
approveForMyOrg supervisor 0

## check whether the chaincode definition is ready to be committed
checkCommitReadiness supervisor "\"SupervisorMSP\": true" "\"RentalcropMSP\": false" "\"AgencyMSP\": false"
checkCommitReadiness rentalcrop "\"SupervisorMSP\": true" "\"RentalcropMSP\": false" "\"AgencyMSP\": false"
checkCommitReadiness agency "\"SupervisorMSP\": true" "\"RentalcropMSP\": false" "\"AgencyMSP\": false"

## now approve also for aggregator
approveForMyOrg rentalcrop 0


链码打包--path为链码的位置,这里和官方脚本有所不同,注意是docker容器中的映射位置,因为该脚本的运行在cliup容器中;--label:用于指定链码标签,在安装后用来识别链码;--lang 标志用于指定链码语言。

packageChaincode() {
  set -x
  go env -w GOPROXY=https://goproxy.io,direct
  go env -w GO111MODULE=on
  peer lifecycle chaincode package ${CC_NAME}.tar.gz --path ${CC_SRC_PATH} --lang ${CC_SRC_LANGUAGE} --label ${CC_NAME}_${CC_VERSION} >&log.txt
  res=$?
  { set +x; } 2>/dev/null
  cat log.txt
  verifyResult $res "Chaincode packaging has failed"
  successln "Chaincode is packaged"
}

**链码安装:**这里一共对7个节点进行链码的安装,脚本函数有两个参数,分别为组织名称和节点名称。

在这里插入图片描述

# installChaincode ORG PEER
installChaincode() {
  ORG=$1
  PEER=$2
  setGlobals $ORG $PEER
  peer lifecycle chaincode install /opt/gopath/src/github.com/hyperledger/fabric/${CC_NAME}.tar.gz >&log.txt
  res=$?
  { set +x; } 2>/dev/nulls
  cat log.txt
  verifyResult $res "Chaincode installation on peer$PEER.${ORG_NAME} has failed"
  successln "Chaincode is installed on peer$PEER.${ORG_NAME}"
}

## Install chaincode
infoln "Installing chaincode on supervisor"
for peer in 0 1 2 ; do
  installChaincode supervisor $peer
done

infoln "Installing chaincode on rentalcrop"
for peer in 0 1; do
  installChaincode rentalcrop $peer
done

infoln "Installing chaincode on agency"
for peer in 0 1; do
  installChaincode agency $peer
done

2.2 链码查询与批准

在进行链码的批准之前可以对链码安装的状态进行查询,批准链码主要是为了将链码的内容、版本、背书策略、数据集合等进行一个共识。一般情况通道上的大部分成员批准链码,链码就可以被提交至通道上。

approveForMyOrg()函数中通过setGlobals函数将环境变量设置为对应批准的节点;--sequence参数是一个整数,用于跟踪链码已定义或更新的次数;

# queryInstalled ORG PEER
queryInstalled() {
  ORG=$1
  PEER=$2
  peer lifecycle chaincode queryinstalled >&log.txt
  res=$?
  { set +x; } 2>/dev/null
  cat log.txt
}

# approveForMyOrg ORG PEER
approveForMyOrg() {
  ORG=$1
  PEER=$2
  setOrdererGlobals 0
  setGlobals $ORG $PEER

  peer lifecycle chaincode approveformyorg \
      -o "$CORE_ORDERER_ADDRESS" \
      --tls true\
      --cafile $CORE_ORDERER_TLS_ROOTCERT_FILE \
      --channelID $CHANNEL_NAME \
      --name ${CC_NAME} \
      --version ${CC_VERSION} \
      --package-id ${PACKAGE_ID} \
      --sequence ${CC_SEQUENCE} \
    res=$?
  verifyResult $res "Chaincode definition approved on peer$PEER.${ORG_NAME} failed"
  successln "Chaincode definition approved on peer$PEER.${ORG_NAME}"
}

## query whether the chaincode is installed
queryInstalled supervisor 0
queryInstalled rentalcrop 0
queryInstalled agency 0

## approve the definition for dispatcher
approveForMyOrg supervisor 0

在supervisor组织批准完毕后,我们可以对链码在通道上的状态进行查询,查询哪些组织对什么样的链码进行了批准,查询会返回一个json,用来告知通道中哪些组织已经批在这里插入图片描述
准了。后续对Rentalcrop组织和AgencyMSP组织步骤都一样。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Ovuvmsvr-1679127201138)(https://secure2.wostatic.cn/static/j7MEiTSBmeUA2RG5z3tbxH/image.png?auth_key=1679125851-npXxabAFgaCJ1t4sgtRfDq-0-0cdfc9cd4cc0908d0bad1f16dcab322c)]

checkCommitReadiness() {
  ORG=$1
  shift 1
  local rc=1
  local COUNTER=1
  # continue to poll
  # we either get a successful response, or reach MAX RETRY
  while [ $rc -ne 0 -a $COUNTER -le $MAX_RETRY ]; do
    if [ $COUNTER -gt 1 ]; then sleep $DELAY; fi
    set -x
    peer lifecycle chaincode checkcommitreadiness \
      --channelID $CHANNEL_NAME \
      --name ${CC_NAME} \
      --version ${CC_VERSION} \
      --sequence ${CC_SEQUENCE} \
      --signature-policy "${CC_END_POLICY}" \
      --output json  >&log.txt
    res=$?
    { set +x; } 2>/dev/null
    let rc=0
    for var in "$@"; do
      grep "$var" log.txt &>/dev/null || let rc=1
    done
    COUNTER=$(expr $COUNTER + 1)
  done
  cat log.txt
  if test $rc -eq 0; then
  else
  fi
}

# 当前仅supervisor组织批准了。
checkCommitReadiness supervisor "\"SupervisorMSP\": true" "\"RentalcropMSP\": false" "\"AgencyMSP\": false"
checkCommitReadiness rentalcrop "\"SupervisorMSP\": true" "\"RentalcropMSP\": false" "\"AgencyMSP\": false"
checkCommitReadiness agency "\"SupervisorMSP\": true" "\"RentalcropMSP\": false" "\"AgencyMSP\": false"

经过三个组织的查询与批准后:

在这里插入图片描述

2.3 链码提交与查看

在满足链码安装的策略条件下就可以对链码在通道上对链码的定义进行确认,对链码定义确认会生成一笔交易,交易就需要经过排序与落块,最后一步就是各个节点到账本中去查询链码定义交易是否成功。函数的逻辑和参数含义上面基本都已经涉及,

commitChaincodeDefinition() {
  setOrdererGlobals 0
  parsePeerConnectionParameters $@
  res=$?
  verifyResult $res "Invoke transaction failed due to uneven number of peer and org parameters "
  set -x
  peer lifecycle chaincode commit \
    -o "$CORE_ORDERER_ADDRESS" \
    --tls \
    --cafile $CORE_ORDERER_TLS_ROOTCERT_FILE \
    --channelID $CHANNEL_NAME \
    --name $CC_NAME \
    $PEER_CONN_PARMS \
    --version ${CC_VERSION} \
    --sequence ${CC_SEQUENCE} \
    --signature-policy "${CC_END_POLICY}" \
    --waitForEventTimeout 300s >&log.txt
    res=$?
    { set +x; } 2>/dev/null

  cat log.txt
  verifyResult $res "Chaincode definition commit failed on peer0.${ORG_NAME} failed"
  successln "Chaincode definition committed"
}

# queryCommitted ORG
queryCommitted() {
  ORG=$1
  setGlobals $ORG 0
  EXPECTED_RESULT="Version: ${CC_VERSION}, Sequence: ${CC_SEQUENCE}, Endorsement Plugin: escc, Validation Plugin: vscc"
  infoln "Querying chaincode definition on peer0.${ORG_NAME}"
  local rc=1
  local COUNTER=1
  # continue to poll
  # we either get a successful response, or reach MAX RETRY
  while [ $rc -ne 0 -a $COUNTER -le $MAX_RETRY ]; do
    if [ $COUNTER -gt 1 ]; then sleep $DELAY; fi
    infoln "Attempting to Query committed status on peer0.${ORG_NAME}, Retry after $DELAY seconds."
    set -x
    peer lifecycle chaincode querycommitted --channelID $CHANNEL_NAME --name $CC_NAME >&log.txt
    res=$?
    { set +x; } 2>/dev/null
    test $res -eq 0 && VALUE=$(cat log.txt | grep -o '^Version: '$CC_VERSION', Sequence: [0-9], Endorsement Plugin: escc, Validation Plugin: vscc')
    test "$VALUE" = "$EXPECTED_RESULT" && let rc=0
    COUNTER=$(expr $COUNTER + 1)
  done
  cat log.txt
  if test $rc -eq 0; then
    successln "Query chaincode definition successfully on peer0.${ORG_NAME}"
  else
    fatalln "After $MAX_RETRY attempts, Query chaincode definition result on peer0.${ORG_NAME} is INVALID"
  fi
}

## now that we know for sure both orgs have approved, commit the definition
commitChaincodeDefinition supervisor 0 rentalcrop 0 agency 0

## query on both orgs to see that the definition committed successfully
queryCommitted supervisor
queryCommitted rentalcrop
queryCommitted agency

在这里插入图片描述

3.当前应用完整目录

当前一个基础的多节点网络已经部署完成,当前项目的主要目录如下,这里主要梳理一下network文件下目录。

在这里插入图片描述

network中的目录结构布局和test-network有点不同,可能设计的不是很合理,但最核心的还是docker-compose中对于目录的映射,比较容易出错,docker不会出错,路径文件不存在那就是不存在,不管是路径错误还是映射路径错误。

在这里插入图片描述

在这里插入图片描述

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值