test-network启动流程
1 启动测试网络
此命令创建一个由两个对等节点和一个排序节点组成的Fabric网络。
./network.sh up
-
createOrgs 使用cryptogen工具或者Fabric CA来创建Org1、Org2、Orderer组织的身份证书
-
createConsortium 使用configtxgen工具来创建联盟,生成系统通道的创世区块genesis.block
1.1 createOrgs
(1)cryptogen工具创建组织的身份证书
cryptogen generate --config=./organizations/cryptogen/crypto-config-org1.yaml --output="organizations"
cryptogen generate --config=./organizations/cryptogen/crypto-config-org2.yaml --output="organizations"
cryptogen generate --config=./organizations/cryptogen/crypto-config-orderer.yaml --output="organizations"
crypto-config-org1.yaml
PeerOrgs:
- Name: Org1
Domain: org1.example.com
EnableNodeOUs: true
Template:
Count: 1
SANS:
- localhost
Users:
Count: 1
crypto-config-orderer.yaml
OrdererOrgs:
- Name: Orderer
Domain: example.com
EnableNodeOUs: true
Specs:
- Hostname: orderer
SANS:
- localhost
Template
:模板定义节点的配置模式
Specs
:另外一种配置模式
Count
:节点总数
Hostname
:全限定域名 命名格式
Domain
:域名
Users
:添加到管理员的用户帐户数
(2)执行ccp-generate.sh脚本创建Org1和Org2的ccp文件,生成json和yaml两种配置共四个文件。
- connection_org1.json
- connection_org1.yaml
- connection_org2.json
- connection_org2.yaml
1.2 createConsortium
cryptogen工具创建联盟,指定TwoOrgsOrdererGenesis和系统通道ID,生成genesis.block,configtx.yaml文件配置了系统通道、Orderer配置、联盟配置,这些配置信息都要保存到创始区块中。这个配置文件稍后分析
configtxgen -profile TwoOrgsOrdererGenesis -channelID system-channel -outputBlock ./system-genesis-block/genesis.block
fabric-samples/test-network/configtx/configtx.yaml
Profiles:
TwoOrgsOrdererGenesis:
<<: *ChannelDefaults
Orderer:
<<: *OrdererDefaults
Organizations:
- *OrdererOrg
Capabilities:
<<: *OrdererCapabilities
Consortiums:
SampleConsortium:
Organizations:
- *Org1
- *Org2
1.3 启动docker镜像
COMPOSE_FILE_BASE=docker/docker-compose-test-net.yaml
docker-compose ${COMPOSE_FILES} up -d 2>&1
docker-compose-test-net.yaml
启动了orderer.example.com、peer0.org1.example.com、peer0.org2.example.com三个镜像
image
:指定镜像
environment
:配置dockder容器内的环境变量
working_dir
:指定工作目录
command
:启动后执行的命令
volumes
:挂载卷,MPS证书、TLS证书,创始区块
ports
:指定端口
networks
:指定网络
2 创建应用通道
执行createChannel脚本,以下五个步骤
- createChannelTx
- createAncorPeerTx
- createChannel
- joinChannel
- updateAnchorPeers
2.1 createChannelTx创建通道配置文件
configtxgen工具创建mychannel.tx配置文件,指定configtx.yaml文件中的TwoOrgsChannel參數
createChannelTx() {
set -x
configtxgen -profile TwoOrgsChannel -outputCreateChannelTx ./channel-artifacts/${CHANNEL_NAME}.tx -channelID $CHANNEL_NAME
res=$?
{ set +x; } 2>/dev/null
if [ $res -ne 0 ]; then
fatalln "Failed to generate channel configuration transaction..."
fi
}
2.2 createAncorPeerTx创建锚节点配置文件
configtxgen工具创建Org1MSPanchors.tx和Org2MSPanchors.tx配置文件,指定configtx.yaml文件中的TwoOrgsChannel參數
createAncorPeerTx() {
for orgmsp in Org1MSP Org2MSP; do
infoln "Generating anchor peer update transaction for ${orgmsp}"
set -x
configtxgen -profile TwoOrgsChannel -outputAnchorPeersUpdate ./channel-artifacts/${orgmsp}anchors.tx -channelID $CHANNEL_NAME -asOrg ${orgmsp}
res=$?
{ set +x; } 2>/dev/null
if [ $res -ne 0 ]; then
fatalln "Failed to generate anchor peer update transaction for ${orgmsp}..."
fi
done
}
2.3 createChannel创建通道
setGlobals 1指定了Org1的peer,连接peer创建应用通道,指定通道配置文件,生成应用通道创始区块mychannel.block
createChannel() {
setGlobals 1
# Poll in case 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
peer channel create -o localhost:7050 -c $CHANNEL_NAME --ordererTLSHostnameOverride orderer.example.com -f ./channel-artifacts/${CHANNEL_NAME}.tx --outputBlock ./channel-artifacts/${CHANNEL_NAME}.block --tls --cafile $ORDERER_CA >&log.txt
res=$?
{ set +x; } 2>/dev/null
let rc=$res
COUNTER=$(expr $COUNTER + 1)
done
cat log.txt
verifyResult $res "Channel creation failed"
successln "Channel '$CHANNEL_NAME' created"
}
2.4 joinChannel组织加入通道
将Org1和Org2的peer都加入到通道中,需要传入通道创始区块
joinChannel() {
ORG=$1
setGlobals $ORG
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 ./channel-artifacts/$CHANNEL_NAME.block >&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' "
}
2.5 updateAnchorPeers更新锚节点
将Org1和Org2的peer,更新对应的锚节点配置文件
updateAnchorPeers() {
ORG=$1
setGlobals $ORG
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 update -o localhost:7050 --ordererTLSHostnameOverride orderer.example.com -c $CHANNEL_NAME -f ./channel-artifacts/${CORE_PEER_LOCALMSPID}anchors.tx --tls --cafile $ORDERER_CA >&log.txt
res=$?
{ set +x; } 2>/dev/null
let rc=$res
COUNTER=$(expr $COUNTER + 1)
done
cat log.txt
verifyResult $res "Anchor peer update failed"
successln "Anchor peers updated for org '$CORE_PEER_LOCALMSPID' on channel '$CHANNEL_NAME'"
sleep $DELAY
}
3 部署链码
执行deployCC.sh脚本,以下八个步骤
- packageChaincode
- installChaincode
- queryInstalled
- approveForMyOrg
- checkCommitReadiness
- commitChaincodeDefinition
- queryCommitted
- chaincodeInvokeInit
3.1 packageChaincode
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}"
}
3.2 installChaincode
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}"
}
3.3 queryInstalled
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"
}
3.4 approveForMyOrg
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'"
}
3.5 checkCommitReadiness
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
}
3.6 commitChaincodeDefinition
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'"
}
3.7 queryCommitted
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
}
3.8 chaincodeInvokeInit
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'"
}
4 启动过程详解
- ./network.sh为两个peer节点和一个order节点创建了证书和密钥,默认情况下,脚本会利用在organizations/cryptogen文件夹下的加密工具。
- 脚本利用configtxgen工具创建了系统的创世块,它使用configtx/configtx.yaml文件来创建创世块,并存储在system-genesis-block文件夹中。
- 当上述两步完成之后,./network.sh会启动网络,脚本利用在docker文件夹下的docker-compose-test-net.yaml文件创建peer和orderer节点。
- 如果使用了createChannel子命令,脚本还会运行script文件夹下的createChannel.sh脚本来创建所需要的channel,脚本会用peer命令来创建channel,加入两个组织。
- 如果运行了deployCC命令,脚本会在所有peers上运行script下的deployCC.sh脚本来安装fabcar chaincode,在chaincode的定义被提交到channel之后,peer命令会调用init函数来初始化chaincode,并将所需的数据放入chaincode中。