1. Chaincode deployment script idea
In the previous chapter, we analyzed the network startup script of test-netwok, which includes the chain code deployment part. We sorted out the chain code deployment ideas by analyzing the deployCC of test-netwok, and then wrote the freenet network chain code deployment script.
pakeageChaincode()
: Pack the chaincode chaincode into a predetermined format (tar.gz file);installChaincode()
: Install the packaged chaincode on the required peer node;queryInstalled()
: Query whether the chaincode has been installed on the peer node;approveForMyOrg():
Multiple members approve the chain code, and the nodes on each peer should be consistent;checkCommitReadiness()
: to check whether a chaincode meets the standard of the channel, that is, whether it reaches the established multi-member approval setting;commitChaincodeDefinition()
: install the chaincode to the channel;queryCommitted()
: Whether the organization query of the channel has been submitted to the channel;
The Fabric2.X version optimizes the chaincode life cycle. The current chaincode logic is relatively clear and easy to understand. Each organization on the channel runs the business according to a code logic, and each step is quite reasonable and easy to understand.
2. Chaincode deployment script writing
The overall logic of the chaincode deployment script is relatively simple. As an official case, the script in test-network must be quite complete, so if you are not familiar with the shell script, it will seem difficult. Some of the shell script functions are only used as a whole. Understand, with the ultimate goal of understanding the general idea and adjusting the chaincode deployment script, it is very error-prone to modify and write.
2.1 Chaincode packaging and installation
The public parameter configuration of the chaincode script, CC_COLL_CONFIG is not needed yet.
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"} # combined with cliup working directory #: ${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'" #debuglen " - CC_COLL_CONFIG: '$CC_COLL_CONFIG'" ## Install chaincode infoln "Installing chaincode on supervisor" for peer in 0 1 2 ; installChaincode supervisor $peer done infoln "Installing chaincode on rentalcrop" for peer in 0 1; installChaincode rentalcrop $peer done infoln "Installing chaincode on agency" for peer in 0 1; 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
Chaincode packaging: --path
is the location of the chaincode, which is different from the official script. Note that it is the mapping location in the docker container, because the script runs in In the cliup container; --label
: used to specify the chaincode label, which is used to identify the chaincode after installation; the --lang
flag is used to specify the chaincode language.
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" }
**Chaincode installation:** Here, a total of 7 nodes are installed with chaincode. The script function has two parameters, which are the organization name and the node name.
# 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 ; installChaincode supervisor $peer done infoln "Installing chaincode on rentalcrop" for peer in 0 1; installChaincode rentalcrop $peer done infoln "Installing chaincode on agency" for peer in 0 1; installChaincode agency $peer done
2.2 Chaincode query and approval
Before the approval of the chain code, you can query the status of the chain code installation. The main purpose of approving the chain code is to achieve a consensus on the content, version, endorsement policy, and data collection of the chain code. Generally, most members on the channel approve the chaincode, and the chaincode can be submitted to the channel.
In the approveForMyOrg()
function, the environment variable is set to the corresponding approved node through the setGlobals
function; the --sequence
parameter is an integer for tracking The number of times the chaincode has been defined or updated;
# 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
After the supervisor organization approves, we can query the status of the chaincode on the channel, which organizations have approved which chaincode, and the query will return a json to inform which organizations in the channel have approved
Ready. Subsequent steps are the same for Rentalcrop organization and AgencyMSP organization.
[External link picture transfer failed, the source site may have an anti-leeching mechanism, it is recommended to save the picture and upload it directly (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; set -x peer lifecycle chaincode checkcommit readiness \ --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 & amp;>/dev/null || let rc=1 done COUNTER=$(expr $COUNTER + 1) done cat log.txt if test $rc -eq 0; then else the fi } # Currently only approved by the supervisor organization. checkCommitReadiness supervisor ""SupervisorMSP": true" ""RentalcropMSP": false" ""AgencyMSP": false" checkCommitReadiness rentalcrop ""SupervisorMSP": true" ""RentalcropMSP": false" ""AgencyMSP": false" checkCommitReadiness agency ""SupervisorMSP": true" ""RentalcropMSP": false" ""AgencyMSP": false"
After inquiry and approval by three organizations:
2.3 Chaincode submission and viewing
The definition of the chain code on the channel can be confirmed if the policy conditions of the chain code installation are met. Confirming the definition of the chain code will generate a transaction, and the transaction needs to be sorted and dropped. The last step is each node Go to the ledger to query whether the chaincode definition transaction is successful. The logic of the function and the meaning of the parameters have basically been covered above.
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; 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 & amp; & amp; VALUE=$(cat log.txt | grep -o '^Version: '$CC_VERSION', Sequence: [0-9], Endorsement Plugin: escc, Validation Plugin: vscc') test "$VALUE" = "$EXPECTED_RESULT" & amp; & amp; 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" the 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 query Committed rental crop query Committed agency
3. Current application complete directory
At present, a basic multi-node network has been deployed. The main directory of the current project is as follows. Here we mainly sort out the directories under the network file.
The directory structure layout in network is a bit different from test-network, and the design may not be very reasonable, but the core is the mapping of directories in docker-compose, which is relatively error-prone, docker will not make mistakes, and if the path file does not exist, it will not exists, whether it is a path error or a mapping path error.