mirror of
https://github.com/hyperledger/fabric-samples.git
synced 2026-06-17 15:35:09 +00:00
Add new chaincode and javascript application to demostrate the use of chaincode events and block events with private data. Signed-off-by: Bret Harrison <beharrison@nc.rr.com>
361 lines
13 KiB
Bash
Executable file
361 lines
13 KiB
Bash
Executable file
#!/bin/bash
|
|
|
|
source scriptUtils.sh
|
|
|
|
CHANNEL_NAME=${1:-"mychannel"}
|
|
CC_NAME=${2:-"basic"}
|
|
CC_SRC_PATH=${3:-"NA"}
|
|
CC_SRC_LANGUAGE=${4:-"go"}
|
|
CC_VERSION=${5:-"1.0"}
|
|
CC_SEQUENCE=${6:-"1"}
|
|
CC_INIT_FCN=${7:-"NA"}
|
|
CC_END_POLICY=${8:-"NA"}
|
|
CC_COLL_CONFIG=${9:-"NA"}
|
|
DELAY=${10:-"3"}
|
|
MAX_RETRY=${11:-"5"}
|
|
VERBOSE=${12:-"false"}
|
|
|
|
println "executing with the following"
|
|
println "- CHANNEL_NAME: ${C_GREEN}${CHANNEL_NAME}${C_RESET}"
|
|
println "- CC_NAME: ${C_GREEN}${CC_NAME}${C_RESET}"
|
|
println "- CC_SRC_PATH: ${C_GREEN}${CC_SRC_PATH}${C_RESET}"
|
|
println "- CC_SRC_LANGUAGE: ${C_GREEN}${CC_SRC_LANGUAGE}${C_RESET}"
|
|
println "- CC_VERSION: ${C_GREEN}${CC_VERSION}${C_RESET}"
|
|
println "- CC_SEQUENCE: ${C_GREEN}${CC_SEQUENCE}${C_RESET}"
|
|
println "- CC_END_POLICY: ${C_GREEN}${CC_END_POLICY}${C_RESET}"
|
|
println "- CC_COLL_CONFIG: ${C_GREEN}${CC_COLL_CONFIG}${C_RESET}"
|
|
println "- CC_INIT_FCN: ${C_GREEN}${CC_INIT_FCN}${C_RESET}"
|
|
println "- DELAY: ${C_GREEN}${DELAY}${C_RESET}"
|
|
println "- MAX_RETRY: ${C_GREEN}${MAX_RETRY}${C_RESET}"
|
|
println "- VERBOSE: ${C_GREEN}${VERBOSE}${C_RESET}"
|
|
|
|
CC_SRC_LANGUAGE=$(echo "$CC_SRC_LANGUAGE" | tr [:upper:] [:lower:])
|
|
|
|
FABRIC_CFG_PATH=$PWD/../config/
|
|
|
|
# User has not provided a path, therefore the CC_NAME must
|
|
# be the short name of a known chaincode sample
|
|
if [ "$CC_SRC_PATH" = "NA" ]; then
|
|
infoln "Determining the path to the chaincode"
|
|
# first see which chaincode we have. This will be based on the
|
|
# short name of the known chaincode sample
|
|
if [ "$CC_NAME" = "basic" ]; then
|
|
println $'\e[0;32m'asset-transfer-basic$'\e[0m' chaincode
|
|
CC_SRC_PATH="../asset-transfer-basic"
|
|
elif [ "$CC_NAME" = "events" ]; then
|
|
println $'\e[0;32m'asset-transfer-events$'\e[0m' chaincode
|
|
CC_SRC_PATH="../asset-transfer-events"
|
|
elif [ "$CC_NAME" = "secured" ]; then
|
|
println $'\e[0;32m'asset-transfer-secured-agreeement$'\e[0m' chaincode
|
|
CC_SRC_PATH="../asset-transfer-secured-agreement"
|
|
elif [ "$CC_NAME" = "ledger" ]; then
|
|
println $'\e[0;32m'asset-transfer-ledger-agreeement$'\e[0m' chaincode
|
|
CC_SRC_PATH="../asset-transfer-ledger-queries"
|
|
elif [ "$CC_NAME" = "private" ]; then
|
|
println $'\e[0;32m'asset-transfer-private-data$'\e[0m' chaincode
|
|
CC_SRC_PATH="../asset-transfer-private-data"
|
|
elif [ "$CC_NAME" = "sbe" ]; then
|
|
println $'\e[0;32m'asset-transfer-sbe$'\e[0m' chaincode
|
|
CC_SRC_PATH="../asset-transfer-sbe"
|
|
else
|
|
fatalln "The chaincode name ${CC_NAME} is not supported by this script. Supported chaincode names are: basic, events, ledger, private, sbe, secured"
|
|
fi
|
|
|
|
# now see what language it is written in
|
|
if [ "$CC_SRC_LANGUAGE" = "go" ]; then
|
|
CC_SRC_PATH="$CC_SRC_PATH/chaincode-go/"
|
|
elif [ "$CC_SRC_LANGUAGE" = "java" ]; then
|
|
CC_SRC_PATH="$CC_SRC_PATH/chaincode-java/"
|
|
elif [ "$CC_SRC_LANGUAGE" = "javascript" ]; then
|
|
CC_SRC_PATH="$CC_SRC_PATH/chaincode-javascript/"
|
|
elif [ "$CC_SRC_LANGUAGE" = "typescript" ]; then
|
|
CC_SRC_PATH="$CC_SRC_PATH/chaincode-typescript/"
|
|
fi
|
|
|
|
# check that the language is available for the sample chaincode
|
|
if [ ! -d "$CC_SRC_PATH" ]; then
|
|
fatalln "The smart contract language \"$CC_SRC_LANGUAGE\" is not yet available for the \"$CC_NAME\" sample smart contract"
|
|
fi
|
|
## Make sure that the path the chaincode exists if provided
|
|
elif [ ! -d "$CC_SRC_PATH" ]; then
|
|
fatalln "Path to chaincode does not exist. Please provide different path"
|
|
fi
|
|
|
|
# do some language specific preparation to the chaincode before packaging
|
|
if [ "$CC_SRC_LANGUAGE" = "go" ]; then
|
|
CC_RUNTIME_LANGUAGE=golang
|
|
|
|
infoln "Vendoring Go dependencies at $CC_SRC_PATH"
|
|
pushd $CC_SRC_PATH
|
|
GO111MODULE=on go mod vendor
|
|
popd
|
|
successln "Finished vendoring Go dependencies"
|
|
|
|
elif [ "$CC_SRC_LANGUAGE" = "java" ]; then
|
|
CC_RUNTIME_LANGUAGE=java
|
|
|
|
infoln "Compiling Java code..."
|
|
pushd $CC_SRC_PATH
|
|
./gradlew installDist
|
|
popd
|
|
successln "Finished compiling Java code"
|
|
CC_SRC_PATH=$CC_SRC_PATH/build/install/$CC_NAME
|
|
|
|
elif [ "$CC_SRC_LANGUAGE" = "javascript" ]; then
|
|
CC_RUNTIME_LANGUAGE=node
|
|
|
|
elif [ "$CC_SRC_LANGUAGE" = "typescript" ]; then
|
|
CC_RUNTIME_LANGUAGE=node
|
|
|
|
infoln "Compiling TypeScript code into JavaScript..."
|
|
pushd $CC_SRC_PATH
|
|
npm install
|
|
npm run build
|
|
popd
|
|
successln "Finished compiling TypeScript code into JavaScript"
|
|
|
|
else
|
|
fatalln "The chaincode language ${CC_SRC_LANGUAGE} is not supported by this script. Supported chaincode languages are: go, java, javascript, and typescript"
|
|
exit 1
|
|
fi
|
|
|
|
INIT_REQUIRED="--init-required"
|
|
# check if the init fcn should be called
|
|
if [ "$CC_INIT_FCN" = "NA" ]; then
|
|
INIT_REQUIRED=""
|
|
fi
|
|
|
|
if [ "$CC_END_POLICY" = "NA" ]; then
|
|
CC_END_POLICY=""
|
|
else
|
|
CC_END_POLICY="--signature-policy $CC_END_POLICY"
|
|
fi
|
|
|
|
if [ "$CC_COLL_CONFIG" = "NA" ]; then
|
|
CC_COLL_CONFIG=""
|
|
else
|
|
CC_COLL_CONFIG="--collections-config $CC_COLL_CONFIG"
|
|
fi
|
|
|
|
# import utils
|
|
. scripts/envVar.sh
|
|
|
|
packageChaincode() {
|
|
ORG=$1
|
|
setGlobals $ORG
|
|
set -x
|
|
peer lifecycle chaincode package ${CC_NAME}.tar.gz --path ${CC_SRC_PATH} --lang ${CC_RUNTIME_LANGUAGE} --label ${CC_NAME}_${CC_VERSION} >&log.txt
|
|
res=$?
|
|
{ set +x; } 2>/dev/null
|
|
cat log.txt
|
|
verifyResult $res "Chaincode packaging on peer0.org${ORG} has failed"
|
|
successln "Chaincode is packaged on peer0.org${ORG}"
|
|
}
|
|
|
|
# installChaincode PEER ORG
|
|
installChaincode() {
|
|
ORG=$1
|
|
setGlobals $ORG
|
|
set -x
|
|
peer lifecycle chaincode install ${CC_NAME}.tar.gz >&log.txt
|
|
res=$?
|
|
{ set +x; } 2>/dev/null
|
|
cat log.txt
|
|
verifyResult $res "Chaincode installation on peer0.org${ORG} has failed"
|
|
successln "Chaincode is installed on peer0.org${ORG}"
|
|
}
|
|
|
|
# queryInstalled PEER ORG
|
|
queryInstalled() {
|
|
ORG=$1
|
|
setGlobals $ORG
|
|
set -x
|
|
peer lifecycle chaincode queryinstalled >&log.txt
|
|
res=$?
|
|
{ set +x; } 2>/dev/null
|
|
cat log.txt
|
|
PACKAGE_ID=$(sed -n "/${CC_NAME}_${CC_VERSION}/{s/^Package ID: //; s/, Label:.*$//; p;}" log.txt)
|
|
verifyResult $res "Query installed on peer0.org${ORG} has failed"
|
|
successln "Query installed successful on peer0.org${ORG} on channel"
|
|
}
|
|
|
|
# approveForMyOrg VERSION PEER ORG
|
|
approveForMyOrg() {
|
|
ORG=$1
|
|
setGlobals $ORG
|
|
set -x
|
|
peer lifecycle chaincode approveformyorg -o localhost:7050 --ordererTLSHostnameOverride orderer.example.com --tls --cafile $ORDERER_CA --channelID $CHANNEL_NAME --name ${CC_NAME} --version ${CC_VERSION} --package-id ${PACKAGE_ID} --sequence ${CC_SEQUENCE} ${INIT_REQUIRED} ${CC_END_POLICY} ${CC_COLL_CONFIG} >&log.txt
|
|
res=$?
|
|
{ set +x; } 2>/dev/null
|
|
cat log.txt
|
|
verifyResult $res "Chaincode definition approved on peer0.org${ORG} on channel '$CHANNEL_NAME' failed"
|
|
successln "Chaincode definition approved on peer0.org${ORG} on channel '$CHANNEL_NAME'"
|
|
}
|
|
|
|
# checkCommitReadiness VERSION PEER ORG
|
|
checkCommitReadiness() {
|
|
ORG=$1
|
|
shift 1
|
|
setGlobals $ORG
|
|
infoln "Checking the commit readiness of the chaincode definition on peer0.org${ORG} on channel '$CHANNEL_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 -lt $MAX_RETRY ]; do
|
|
sleep $DELAY
|
|
infoln "Attempting to check the commit readiness of the chaincode definition on peer0.org${ORG}, Retry after $DELAY seconds."
|
|
set -x
|
|
peer lifecycle chaincode checkcommitreadiness --channelID $CHANNEL_NAME --name ${CC_NAME} --version ${CC_VERSION} --sequence ${CC_SEQUENCE} ${INIT_REQUIRED} ${CC_END_POLICY} ${CC_COLL_CONFIG} --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
|
|
infoln "Checking the commit readiness of the chaincode definition successful on peer0.org${ORG} on channel '$CHANNEL_NAME'"
|
|
else
|
|
fatalln "After $MAX_RETRY attempts, Check commit readiness result on peer0.org${ORG} is INVALID!"
|
|
fi
|
|
}
|
|
|
|
# commitChaincodeDefinition VERSION PEER ORG (PEER ORG)...
|
|
commitChaincodeDefinition() {
|
|
parsePeerConnectionParameters $@
|
|
res=$?
|
|
verifyResult $res "Invoke transaction failed on channel '$CHANNEL_NAME' due to uneven number of peer and org parameters "
|
|
|
|
# while 'peer chaincode' command can get the orderer endpoint from the
|
|
# peer (if join was successful), let's supply it directly as we know
|
|
# it using the "-o" option
|
|
set -x
|
|
peer lifecycle chaincode commit -o localhost:7050 --ordererTLSHostnameOverride orderer.example.com --tls --cafile $ORDERER_CA --channelID $CHANNEL_NAME --name ${CC_NAME} $PEER_CONN_PARMS --version ${CC_VERSION} --sequence ${CC_SEQUENCE} ${INIT_REQUIRED} ${CC_END_POLICY} ${CC_COLL_CONFIG} >&log.txt
|
|
res=$?
|
|
{ set +x; } 2>/dev/null
|
|
cat log.txt
|
|
verifyResult $res "Chaincode definition commit failed on peer0.org${ORG} on channel '$CHANNEL_NAME' failed"
|
|
successln "Chaincode definition committed on channel '$CHANNEL_NAME'"
|
|
}
|
|
|
|
# queryCommitted ORG
|
|
queryCommitted() {
|
|
ORG=$1
|
|
setGlobals $ORG
|
|
EXPECTED_RESULT="Version: ${CC_VERSION}, Sequence: ${CC_SEQUENCE}, Endorsement Plugin: escc, Validation Plugin: vscc"
|
|
infoln "Querying chaincode definition on peer0.org${ORG} on channel '$CHANNEL_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 -lt $MAX_RETRY ]; do
|
|
sleep $DELAY
|
|
infoln "Attempting to Query committed status on peer0.org${ORG}, 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 successful on peer0.org${ORG} on channel '$CHANNEL_NAME'"
|
|
else
|
|
fatalln "After $MAX_RETRY attempts, Query chaincode definition result on peer0.org${ORG} is INVALID!"
|
|
fi
|
|
}
|
|
|
|
chaincodeInvokeInit() {
|
|
parsePeerConnectionParameters $@
|
|
res=$?
|
|
verifyResult $res "Invoke transaction failed on channel '$CHANNEL_NAME' due to uneven number of peer and org parameters "
|
|
|
|
# while 'peer chaincode' command can get the orderer endpoint from the
|
|
# peer (if join was successful), let's supply it directly as we know
|
|
# it using the "-o" option
|
|
set -x
|
|
fcn_call='{"function":"'${CC_INIT_FCN}'","Args":[]}'
|
|
infoln "invoke fcn call:${fcn_call}"
|
|
peer chaincode invoke -o localhost:7050 --ordererTLSHostnameOverride orderer.example.com --tls --cafile $ORDERER_CA -C $CHANNEL_NAME -n ${CC_NAME} $PEER_CONN_PARMS --isInit -c ${fcn_call} >&log.txt
|
|
res=$?
|
|
{ set +x; } 2>/dev/null
|
|
cat log.txt
|
|
verifyResult $res "Invoke execution on $PEERS failed "
|
|
successln "Invoke transaction successful on $PEERS on channel '$CHANNEL_NAME'"
|
|
}
|
|
|
|
chaincodeQuery() {
|
|
ORG=$1
|
|
setGlobals $ORG
|
|
infoln "Querying on peer0.org${ORG} on channel '$CHANNEL_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 -lt $MAX_RETRY ]; do
|
|
sleep $DELAY
|
|
infoln "Attempting to Query peer0.org${ORG}, Retry after $DELAY seconds."
|
|
set -x
|
|
peer chaincode query -C $CHANNEL_NAME -n ${CC_NAME} -c '{"Args":["queryAllCars"]}' >&log.txt
|
|
res=$?
|
|
{ set +x; } 2>/dev/null
|
|
let rc=$res
|
|
COUNTER=$(expr $COUNTER + 1)
|
|
done
|
|
cat log.txt
|
|
if test $rc -eq 0; then
|
|
successln "Query successful on peer0.org${ORG} on channel '$CHANNEL_NAME'"
|
|
else
|
|
fatalln "After $MAX_RETRY attempts, Query result on peer0.org${ORG} is INVALID!"
|
|
fi
|
|
}
|
|
|
|
## package the chaincode
|
|
packageChaincode 1
|
|
|
|
## Install chaincode on peer0.org1 and peer0.org2
|
|
infoln "Installing chaincode on peer0.org1..."
|
|
installChaincode 1
|
|
infoln "Install chaincode on peer0.org2..."
|
|
installChaincode 2
|
|
|
|
## query whether the chaincode is installed
|
|
queryInstalled 1
|
|
|
|
## approve the definition for org1
|
|
approveForMyOrg 1
|
|
|
|
## check whether the chaincode definition is ready to be committed
|
|
## expect org1 to have approved and org2 not to
|
|
checkCommitReadiness 1 "\"Org1MSP\": true" "\"Org2MSP\": false"
|
|
checkCommitReadiness 2 "\"Org1MSP\": true" "\"Org2MSP\": false"
|
|
|
|
## now approve also for org2
|
|
approveForMyOrg 2
|
|
|
|
## check whether the chaincode definition is ready to be committed
|
|
## expect them both to have approved
|
|
checkCommitReadiness 1 "\"Org1MSP\": true" "\"Org2MSP\": true"
|
|
checkCommitReadiness 2 "\"Org1MSP\": true" "\"Org2MSP\": true"
|
|
|
|
## now that we know for sure both orgs have approved, commit the definition
|
|
commitChaincodeDefinition 1 2
|
|
|
|
## query on both orgs to see that the definition committed successfully
|
|
queryCommitted 1
|
|
queryCommitted 2
|
|
|
|
## Invoke the chaincode - this does require that the chaincode have the 'initLedger'
|
|
## method defined
|
|
if [ "$CC_INIT_FCN" = "NA" ]; then
|
|
infoln "Chaincode initialization is not required"
|
|
else
|
|
chaincodeInvokeInit 1 2
|
|
fi
|
|
|
|
exit 0
|