function checkPrereqs() { ## Check if your have cloned the peer binaries and configuration files. peer version > /dev/null 2>&1
if [[ $? -ne 0 || ! -d "../config" ]]; then errorln "Peer binary and configuration files not found.." errorln errorln "Follow the instructions in the Fabric docs to install the Fabric Binaries:" errorln "https://hyperledger-fabric.readthedocs.io/en/latest/install.html" exit 1 fi # use the fabric tools container to see if the samples and binaries match your # docker images LOCAL_VERSION=$(peer version | sed -ne 's/^ Version: //p') DOCKER_IMAGE_VERSION=$(docker run --rm hyperledger/fabric-tools:latest peer version | sed -ne 's/^ Version: //p')
if [ "$LOCAL_VERSION" != "$DOCKER_IMAGE_VERSION" ]; then warnln "Local fabric binaries and docker images are out of sync. This may cause problems." fi
for UNSUPPORTED_VERSION in $NONWORKING_VERSIONS; do infoln "$LOCAL_VERSION" | grep -q $UNSUPPORTED_VERSION if [ $? -eq 0 ]; then fatalln "Local Fabric binary version of $LOCAL_VERSION does not match the versions supported by the test network." fi
infoln "$DOCKER_IMAGE_VERSION" | grep -q $UNSUPPORTED_VERSION if [ $? -eq 0 ]; then fatalln "Fabric Docker image version of $DOCKER_IMAGE_VERSION does not match the versions supported by the test network." fi done ## Check for fabric-ca if [ "$CRYPTO" == "Certificate Authorities" ]; then
fabric-ca-client version > /dev/null 2>&1 if [[ $? -ne 0 ]]; then errorln "fabric-ca-client binary not found.." errorln errorln "Follow the instructions in the Fabric docs to install the Fabric Binaries:" errorln "https://hyperledger-fabric.readthedocs.io/en/latest/install.html" exit 1 fi CA_LOCAL_VERSION=$(fabric-ca-client version | sed -ne 's/ Version: //p') CA_DOCKER_IMAGE_VERSION=$(docker run --rm hyperledger/fabric-ca:latest fabric-ca-client version | sed -ne 's/ Version: //p' | head -1) infoln "CA_LOCAL_VERSION=$CA_LOCAL_VERSION" infoln "CA_DOCKER_IMAGE_VERSION=$CA_DOCKER_IMAGE_VERSION"
if [ "$CA_LOCAL_VERSION" != "$CA_DOCKER_IMAGE_VERSION" ]; then warnln "Local fabric-ca binaries and docker images are out of sync. This may cause problems." fi fi }
function createOrgs() { if [ -d "organizations/peerOrganizations" ]; then rm -Rf organizations/peerOrganizations && rm -Rf organizations/ordererOrganizations fi # Create crypto material using cryptogen if [ "$CRYPTO" == "cryptogen" ]; then which cryptogen if [ "$?" -ne 0 ]; then fatalln "cryptogen tool not found. exiting" fi infoln "Generating certificates using cryptogen tool"
infoln "Creating Org1 Identities"
set -x cryptogen generate --config=./organizations/cryptogen/crypto-config-org1.yaml --output="organizations" res=$? { set +x; } 2>/dev/null if [ $res -ne 0 ]; then fatalln "Failed to generate certificates..." fi
infoln "Creating Org2 Identities"
set -x cryptogen generate --config=./organizations/cryptogen/crypto-config-org2.yaml --output="organizations" res=$? { set +x; } 2>/dev/null if [ $res -ne 0 ]; then fatalln "Failed to generate certificates..." fi
infoln "Creating Orderer Org Identities"
set -x cryptogen generate --config=./organizations/cryptogen/crypto-config-orderer.yaml --output="organizations" res=$? { set +x; } 2>/dev/null if [ $res -ne 0 ]; then fatalln "Failed to generate certificates..." fi
fi # Create crypto material using Fabric CA if [ "$CRYPTO" == "Certificate Authorities" ]; then infoln "Generating certificates using Fabric CA" docker-compose -f $COMPOSE_FILE_CA up -d 2>&1
. organizations/fabric-ca/registerEnroll.sh
while : do if [ ! -f "organizations/fabric-ca/org1/tls-cert.pem" ]; then sleep 1 else break fi done
infoln "Creating Org1 Identities"
createOrg1
infoln "Creating Org2 Identities"
createOrg2
infoln "Creating Orderer Org Identities"
createOrderer
fi
infoln "Generating CCP files for Org1 and Org2" ./organizations/ccp-generate.sh }
function createChannel() { # Bring up the network if it is not already up.
if [ ! -d "organizations/peerOrganizations" ]; then infoln "Bringing up network" networkUp fi # now run the script that creates a channel. This script uses configtxgen once # to create the channel creation transaction and the anchor peer updates. scripts/createChannel.sh $CHANNEL_NAME $CLI_DELAY $MAX_RETRY $VERBOSE }
# Using crpto vs CA. default is cryptogen CRYPTO="cryptogen" # timeout duration - the duration the CLI should waitfor a response from # another container before giving up MAX_RETRY=5 # default for delay between commands CLI_DELAY=3 # channel name defaults to "mychannel" CHANNEL_NAME="mychannel" # chaincode name defaults to "NA" CC_NAME="NA" # chaincode path defaults to "NA" CC_SRC_PATH="NA" # endorsement policy defaults to "NA". This would allow chaincodes to use the majority default policy. CC_END_POLICY="NA" # collection configuration defaults to "NA" CC_COLL_CONFIG="NA" # chaincode init function defaults to "NA" CC_INIT_FCN="NA" # use this as the default docker-compose yaml definition COMPOSE_FILE_BASE=docker/docker-compose-test-net.yaml # docker-compose.yaml file if you are using couchdb COMPOSE_FILE_COUCH=docker/docker-compose-couch.yaml # certificate authorities compose file COMPOSE_FILE_CA=docker/docker-compose-ca.yaml # use this as the docker compose couch file for org3 COMPOSE_FILE_COUCH_ORG3=addOrg3/docker/docker-compose-couch-org3.yaml # use this as the default docker-compose yaml definition for org3 COMPOSE_FILE_ORG3=addOrg3/docker/docker-compose-org3.yaml # # chaincode language defaults to "NA" CC_SRC_LANGUAGE="NA" # Chaincode version CC_VERSION="1.0" # Chaincode definition sequence CC_SEQUENCE=1 # default database DATABASE="leveldb" # Get docker sock path from environment variable SOCK="${DOCKER_HOST:-/var/run/docker.sock}" DOCKER_SOCK="${SOCK##unix://}"
最后是读取 命令行参数 执行命令
1 2 3 4 5 6 7 8 9 10 11 12
if [ "${MODE}" == "up" ]; then networkUp elif [ "${MODE}" == "createChannel" ]; then createChannel elif [ "${MODE}" == "deployCC" ]; then deployCC elif [ "${MODE}" == "down" ]; then networkDown else printHelp exit 1 fi
scripts/createChannel.sh
创建通道的细节。
创建通道的创世区块
1 2 3 4 5 6 7 8 9 10 11
createChannelGenesisBlock() { which configtxgen if [ "$?" -ne 0 ]; then fatalln "configtxgen tool not found." fi set -x configtxgen -profile TwoOrgsApplicationGenesis -outputBlock ./channel-artifacts/${CHANNEL_NAME}.block -channelID $CHANNEL_NAME res=$? { set +x; } 2>/dev/null verifyResult $res "Failed to generate channel configuration transaction..." }
创建通道
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
createChannel() { # 使用org1的证书信息 setGlobals 1 # Poll incase the raft leader is not set yet local rc=1 local COUNTER=1 while [ $rc -ne 0 -a $COUNTER -lt $MAX_RETRY ] ; do sleep $DELAY set -x osnadmin channel join --channelID $CHANNEL_NAME --config-block ./channel-artifacts/${CHANNEL_NAME}.block -o localhost:7053 --ca-file "$ORDERER_CA" --client-cert "$ORDERER_ADMIN_TLS_SIGN_CERT" --client-key "$ORDERER_ADMIN_TLS_PRIVATE_KEY" >&log.txt res=$? { set +x; } 2>/dev/null let rc=$res COUNTER=$(expr $COUNTER + 1) done cat log.txt verifyResult $res "Channel creation failed" }
FABRIC_CFG_PATH=$PWD/../config/ BLOCKFILE="./channel-artifacts/${CHANNEL_NAME}.block" ## Create channel infoln "Creating channel ${CHANNEL_NAME}" createChannel successln "Channel '$CHANNEL_NAME' created" ## Join all the peers to the channel infoln "Joining org1 peer to the channel..." joinChannel 1 infoln "Joining org2 peer to the channel..." joinChannel 2 ## Set the anchor peers for each org in the channel infoln "Setting anchor peer for org1..." setAnchorPeer 1 infoln "Setting anchor peer for org2..." setAnchorPeer 2
successln "Channel '$CHANNEL_NAME' joined"
scripts/deployCC.sh
部署链码的细节。
打包链码
1 2 3 4 5 6 7 8 9
packageChaincode() { 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 has failed" successln "Chaincode is packaged" }
安装链码(本地安装,未上链)
1 2 3 4 5 6 7 8 9 10 11
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}" }
查询已安装的链码(本地)
1 2 3 4 5 6 7 8 9 10 11 12
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" }
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=$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 }
链码初始化(update操作)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
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 ## 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
# NOTE: this must be run in a CLI container since it requires jq and configtxlator createAnchorPeerUpdate() { infoln "Fetching channel config for channel $CHANNEL_NAME" fetchChannelConfig $ORG $CHANNEL_NAME ${CORE_PEER_LOCALMSPID}config.json
infoln "Generating anchor peer update transaction for Org${ORG} on channel $CHANNEL_NAME"
if [ $ORG -eq 1 ]; then HOST="peer0.org1.example.com" PORT=7051 elif [ $ORG -eq 2 ]; then HOST="peer0.org2.example.com" PORT=9051 elif [ $ORG -eq 3 ]; then HOST="peer0.org3.example.com" PORT=11051 else errorln "Org${ORG} unknown" fi
set -x # 修改配置以附加锚节点 # Modify the configuration to append the anchor peer jq '.channel_group.groups.Application.groups.'${CORE_PEER_LOCALMSPID}'.values += {"AnchorPeers":{"mod_policy": "Admins","value":{"anchor_peers": [{"host": "'$HOST'","port": '$PORT'}]},"version": "0"}}' ${CORE_PEER_LOCALMSPID}config.json > ${CORE_PEER_LOCALMSPID}modified_config.json { set +x; } 2>/dev/null # Compute a config update, based on the differences between # {orgmsp}config.json and {orgmsp}modified_config.json, write # it as a transaction to {orgmsp}anchors.tx createConfigUpdate ${CHANNEL_NAME} ${CORE_PEER_LOCALMSPID}config.json ${CORE_PEER_LOCALMSPID}modified_config.json ${CORE_PEER_LOCALMSPID}anchors.tx }
# fetchChannelConfig <org> <channel_id> <output_json> # Writes the current channel config for a given channel to a JSON file # NOTE: this must be run in a CLI container since it requires configtxlator fetchChannelConfig() { ORG=$1 CHANNEL=$2 OUTPUT=$3
setGlobals $ORG
infoln "Fetching the most recent configuration block for the channel" set -x peer channel fetch config config_block.pb -o orderer.example.com:7050 --ordererTLSHostnameOverride orderer.example.com -c $CHANNEL --tls --cafile "$ORDERER_CA" { set +x; } 2>/dev/null
infoln "Decoding config block to JSON and isolating config to ${OUTPUT}" set -x configtxlator proto_decode --input config_block.pb --type common.Block | jq .data.data[0].payload.data.config >"${OUTPUT}" { set +x; } 2>/dev/null }
创建配置更新
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
# createConfigUpdate <channel_id> <original_config.json> <modified_config.json> <output.pb> # Takes an original and modified config, and produces the config update tx #which transitions between the two # NOTE: this must be run in a CLI container since it requires configtxlator createConfigUpdate() { CHANNEL=$1 ORIGINAL=$2 MODIFIED=$3 OUTPUT=$4
# signConfigtxAsPeerOrg <org> <configtx.pb> # Set the peerOrg admin of an org and sign the config update signConfigtxAsPeerOrg() { ORG=$1 CONFIGTXFILE=$2 setGlobals $ORG set -x peer channel signconfigtx -f "${CONFIGTXFILE}" { set +x; } 2>/dev/null }
增加新节点
addOrg3.sh为org3 生成证书
org3-scripts/joinChannel.sh
将org3加入通道。
加入通道
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
joinChannel() { ORG=$1 local rc=1 local COUNTER=1 ## Sometimes Join takes time, hence retry while [ $rc -ne 0 -a $COUNTER -lt $MAX_RETRY ] ; do sleep $DELAY set -x peer channel join -b $BLOCKFILE >&log.txt res=$? { set +x; } 2>/dev/null let rc=$res COUNTER=$(expr $COUNTER + 1) done cat log.txt verifyResult $res "After $MAX_RETRY attempts, peer0.org${ORG} has failed to join channel '$CHANNEL_NAME' " }
infoln "Creating config transaction to add org3 to network" # Fetch the config for the channel, writing it to config.json fetchChannelConfig 1 ${CHANNEL_NAME} config.json # Modify the configuration to append the new org set -x jq -s '.[0] * {"channel_group":{"groups":{"Application":{"groups": {"Org3MSP":.[1]}}}}}' config.json ./organizations/peerOrganizations/org3.example.com/org3.json > modified_config.json { set +x; } 2>/dev/null # Compute a config update, based on the differences between config.json and modified_config.json, write it as a transaction to org3_update_in_envelope.pb createConfigUpdate ${CHANNEL_NAME} config.json modified_config.json org3_update_in_envelope.pb
infoln "Submitting transaction from a different peer (peer0.org2) which also signs it" setGlobals 2 set -x peer channel update -f org3_update_in_envelope.pb -c ${CHANNEL_NAME} -o orderer.example.com:7050 --ordererTLSHostnameOverride orderer.example.com --tls --cafile "$ORDERER_CA" { set +x; } 2>/dev/null
successln "Config transaction to add org3 to network submitted"