hyperledger中文文档学习-4-构建第一个fabric网络

接下来的操作都将在hyperledge环境安装构建的虚拟机的环境下进行

参考https://hyperledgercn.github.io/hyperledgerDocs/build_network_zh/

1》运行实例

先下载hyperledger fabric samples示例

vagrant@ubuntu-xenial:~$ git clone https://github.com/hyperledger/fabric-samples.git
Cloning into 'fabric-samples'... remote: Enumerating objects: 2705, done. remote: Total 2705 (delta 0), reused 0 (delta 0), pack-reused 2705 Receiving objects: 100% (2705/2705), 923.26 KiB | 323.00 KiB/s, done. Resolving deltas: 100% (1350/1350), done. Checking connectivity... done.

然后进入其的first-network目录,因为下面要运行的目录都必须运行在这个目录下,否则提供的一些脚本可能无法找到对应的二进制:

vagrant@ubuntu-xenial:~$ ls
fabric-samples
vagrant@ubuntu-xenial:~$ cd fabric-samples/first-network/
vagrant@ubuntu-xenial:~/fabric-samples/first-network$ ls
base                docker-compose-cli.yaml           docker-compose-org3.yaml byfn.sh docker-compose-couch-org3.yaml eyfn.sh channel-artifacts docker-compose-couch.yaml org3-artifacts configtx.yaml docker-compose-e2e-template.yaml README.md crypto-config.yaml docker-compose-kafka.yaml scripts

在这个文档中提供一个完全注释的脚本byfn.sh,利用这些Docker镜像可以快速引导一个由4个代表2个不同组织的peer节点以及一个排序服务节点的Hyperledger fabric网络。它还将启动一个容器来运行一个将peer节点加入channel、部署实例化链码服务以及驱动已经部署的链码执行交易的脚本

首先我们能够使用命令./byfn.sh -h来查看脚本的帮助信息:

vagrant@ubuntu-xenial:~/fabric-samples/first-network$ ./byfn.sh -h
Usage: 
  byfn.sh <mode> [-c <channel name>] [-t <timeout>] [-d <delay>] [-f <docker-compose-file>] [-s <dbtype>] [-l <language>] [-o <consensus-type>] [-i <imagetag>] [-v]
    <mode> - one of 'up', 'down', 'restart', 'generate' or 'upgrade' - 'up' - bring up the network with docker-compose up - 'down' - clear the network with docker-compose down - 'restart' - restart the network - 'generate' - generate required certificates and genesis block - 'upgrade' - upgrade the network from version 1.3.x to 1.4.0 -c <channel name> - channel name to use (defaults to "mychannel") -t <timeout> - CLI timeout duration in seconds (defaults to 10),即如果你选择不设置它,那么CLI容器将会在脚本执行完之后退出 -d <delay> - delay duration in seconds (defaults to 3) -f <docker-compose-file> - specify which docker-compose file use (defaults to docker-compose-cli.yaml) -s <dbtype> - the database backend to use: goleveldb (default) or couchdb -l <language> - the chaincode language: golang (default) or node -o <consensus-type> - the consensus-type of the ordering service: solo (default) or kafka -i <imagetag> - the tag to be used to launch the network (defaults to "latest") -v - verbose mode byfn.sh -h (print this message) 一般来说,应该先生成需要的证书和创世区块,然后运行该网络,如:
(下面使用自定义的channel名,指明使用数据库couchdb,镜像标签为1.4.0,并声明使用node语言) byfn.sh generate -c mychannel byfn.sh up -c mychannel -s couchdb byfn.sh up -c mychannel -s couchdb -i 1.4.0 byfn.sh up -l node byfn.sh down -c mychannel byfn.sh upgrade -c mychannel 当然,你也可以完全使用默认的配置: byfn.sh generate byfn.sh up byfn.sh down

1)generate

首先我们先将需要的证书和创世区块构建好,运行的过程中出现一个问题:

vagrant@ubuntu-xenial:~/fabric-samples/first-network$ ./byfn.sh generate
Generating certs and genesis block for channel 'mychannel' with CLI timeout of '10' seconds and CLI delay of '3' seconds
Continue? [Y/n] y
proceeding ...
cryptogen tool not found. exiting

需要知道什么是cryptogen,可见:hyperledge工具-cryptogen

运行该./byfn.sh generate命令会执行三个函数:

  •   generateCerts :先生成证书
  •   replacePrivateKey :然后使用docker-compose-e2e-template.yaml文件,用上面那一步使用cryptogen工具生成的私钥文件名来替换docker-compose-e2e-template.yaml文件中的常量,即CA1_PRIVATE_KEY和CA2_PRIVATE_KEY,并输出到特定于此配置的docker-compose-e2e.yaml文件中,来构建docker-compose-e2e.yaml文件
  •   generateChannelArtifacts :生成排序服务节点使用的创世区块、创建通道使用的通道配置交易以及更新通道用的锚节点交易

generateChannelArtifacts中使用了configtxgen工具,详情可见hyperledge工具-configtxgen

然后现在重新运行一次该命令:

Using docker-compose-e2e-template.yaml, replace constants with private key file names generated by the cryptogen tool and output a docker-compose.yaml specific to this configuration



vagrant@ubuntu-xenial:~/fabric-samples/first-network$ ls #一开始的文档情况
base                docker-compose-cli.yaml           docker-compose-org3.yaml
byfn.sh             docker-compose-couch-org3.yaml    eyfn.sh
channel-artifacts   docker-compose-couch.yaml         org3-artifacts
configtx.yaml       docker-compose-e2e-template.yaml  README.md
crypto-config.yaml  docker-compose-kafka.yaml         scripts

vagrant@ubuntu-xenial:~/fabric-samples/first-network$ ./byfn.sh generate #成功执行命令
Generating certs and genesis block for channel 'mychannel' with CLI timeout of '10' seconds and CLI delay of '3' seconds
Continue? [Y/n] y
proceeding ...
/hyperledger/fabric/.build/bin/cryptogen #开始生成证书

##########################################################
##### Generate certificates using cryptogen tool #########
##########################################################
+ cryptogen generate --config=./crypto-config.yaml
org1.example.com
org2.example.com
+ res=0
+ set +x

/hyperledger/fabric/.build/bin/configtxgen
##########################################################
#########  Generating Orderer Genesis block ##############
##########################################################
CONSENSUS_TYPE=solo
+ '[' solo == solo ']'
+ configtxgen -profile TwoOrgsOrdererGenesis -channelID byfn-sys-channel -outputBlock ./channel-artifacts/genesis.block
2019-03-08 09:31:11.852 UTC [common.tools.configtxgen] main -> INFO 001 Loading configuration
2019-03-08 09:31:11.980 UTC [common.tools.configtxgen.localconfig] completeInitialization -> INFO 002 orderer type: solo
2019-03-08 09:31:11.981 UTC [common.tools.configtxgen.localconfig] Load -> INFO 003 Loaded configuration: /home/vagrant/fabric-samples/first-network/configtx.yaml
2019-03-08 09:31:12.009 UTC [common.tools.configtxgen.localconfig] completeInitialization -> INFO 004 orderer type: solo
2019-03-08 09:31:12.009 UTC [common.tools.configtxgen.localconfig] LoadTopLevel -> INFO 005 Loaded configuration: /home/vagrant/fabric-samples/first-network/configtx.yaml
2019-03-08 09:31:12.034 UTC [common.tools.configtxgen] doOutputBlock -> INFO 006 Generating genesis block
2019-03-08 09:31:12.040 UTC [common.tools.configtxgen] doOutputBlock -> INFO 007 Writing genesis block
+ res=0
+ set +x

#################################################################
### Generating channel configuration transaction 'channel.tx' ###
#################################################################
+ configtxgen -profile TwoOrgsChannel -outputCreateChannelTx ./channel-artifacts/channel.tx -channelID mychannel
2019-03-08 09:31:12.181 UTC [common.tools.configtxgen] main -> INFO 001 Loading configuration
2019-03-08 09:31:12.230 UTC [common.tools.configtxgen.localconfig] Load -> INFO 002 Loaded configuration: /home/vagrant/fabric-samples/first-network/configtx.yaml
2019-03-08 09:31:12.260 UTC [common.tools.configtxgen.localconfig] completeInitialization -> INFO 003 orderer type: solo
2019-03-08 09:31:12.260 UTC [common.tools.configtxgen.localconfig] LoadTopLevel -> INFO 004 Loaded configuration: /home/vagrant/fabric-samples/first-network/configtx.yaml
2019-03-08 09:31:12.261 UTC [common.tools.configtxgen] doOutputChannelCreateTx -> INFO 005 Generating new channel configtx
2019-03-08 09:31:12.262 UTC [common.tools.configtxgen.encoder] NewChannelGroup -> WARN 006 Default policy emission is deprecated, please include policy specifications for the channel group in configtx.yaml
2019-03-08 09:31:12.274 UTC [common.tools.configtxgen.encoder] NewChannelGroup -> WARN 007 Default policy emission is deprecated, please include policy specifications for the channel group in configtx.yaml
2019-03-08 09:31:12.281 UTC [common.tools.configtxgen] doOutputChannelCreateTx -> INFO 008 Writing new channel tx
+ res=0
+ set +x

#################################################################
#######    Generating anchor peer update for Org1MSP   ##########
#################################################################
+ configtxgen -profile TwoOrgsChannel -outputAnchorPeersUpdate ./channel-artifacts/Org1MSPanchors.tx -channelID mychannel -asOrg Org1MSP
2019-03-08 09:31:12.424 UTC [common.tools.configtxgen] main -> INFO 001 Loading configuration
2019-03-08 09:31:12.472 UTC [common.tools.configtxgen.localconfig] Load -> INFO 002 Loaded configuration: /home/vagrant/fabric-samples/first-network/configtx.yaml
2019-03-08 09:31:12.498 UTC [common.tools.configtxgen.localconfig] completeInitialization -> INFO 003 orderer type: solo
2019-03-08 09:31:12.499 UTC [common.tools.configtxgen.localconfig] LoadTopLevel -> INFO 004 Loaded configuration: /home/vagrant/fabric-samples/first-network/configtx.yaml
2019-03-08 09:31:12.501 UTC [common.tools.configtxgen] doOutputAnchorPeersUpdate -> INFO 005 Generating anchor peer update
2019-03-08 09:31:12.506 UTC [common.tools.configtxgen] doOutputAnchorPeersUpdate -> INFO 006 Writing anchor peer update
+ res=0
+ set +x

#################################################################
#######    Generating anchor peer update for Org2MSP   ##########
#################################################################
+ configtxgen -profile TwoOrgsChannel -outputAnchorPeersUpdate ./channel-artifacts/Org2MSPanchors.tx -channelID mychannel -asOrg Org2MSP
2019-03-08 09:31:12.650 UTC [common.tools.configtxgen] main -> INFO 001 Loading configuration
2019-03-08 09:31:12.703 UTC [common.tools.configtxgen.localconfig] Load -> INFO 002 Loaded configuration: /home/vagrant/fabric-samples/first-network/configtx.yaml
2019-03-08 09:31:12.729 UTC [common.tools.configtxgen.localconfig] completeInitialization -> INFO 003 orderer type: solo
2019-03-08 09:31:12.729 UTC [common.tools.configtxgen.localconfig] LoadTopLevel -> INFO 004 Loaded configuration: /home/vagrant/fabric-samples/first-network/configtx.yaml
2019-03-08 09:31:12.729 UTC [common.tools.configtxgen] doOutputAnchorPeersUpdate -> INFO 005 Generating anchor peer update
2019-03-08 09:31:12.734 UTC [common.tools.configtxgen] doOutputAnchorPeersUpdate -> INFO 006 Writing anchor peer update
+ res=0
+ set +x

vagrant@ubuntu-xenial:~/fabric-samples/first-network$ ls #生成了一个新文件夹crypto-config,一个文件docker-compose-e2e.yaml,文件夹channel-artifacts中也有变动
base                docker-compose-cli.yaml           docker-compose-org3.yaml
byfn.sh             docker-compose-couch-org3.yaml    eyfn.sh
channel-artifacts   docker-compose-couch.yaml         org3-artifacts
configtx.yaml       docker-compose-e2e-template.yaml  README.md
crypto-config       docker-compose-e2e.yaml           scripts
crypto-config.yaml  docker-compose-kafka.yaml
View Code

查看生成的新文件夹:

vagrant@ubuntu-xenial:~/fabric-samples/first-network$ cd channel-artifacts/
#生成了对应的创世区块和交易文件
#其中系统链创世区块只包含Org1和Org2的msp信息,应用通道配置channel.tx中指定mychannel中包含组织Org1和Org2 vagrant@ubuntu-xenial:~/fabric-samples/first-network/channel-artifacts$ ls channel.tx genesis.block Org1MSPanchors.tx Org2MSPanchors.tx vagrant@ubuntu-xenial:~/fabric-samples/first-network/channel-artifacts$ cd ..
#该文件夹下存储的是生成的证书等信息
#在crypto-config中生成了Org1、Org2、Org3和Org4四个组织的msp信息 vagrant@ubuntu
-xenial:~/fabric-samples/first-network$ cd crypto-config/ vagrant@ubuntu-xenial:~/fabric-samples/first-network/crypto-config$ ls ordererOrganizations peerOrganizations vagrant@ubuntu-xenial:~/fabric-samples/first-network/crypto-config$ cd ordererOrganizations/ vagrant@ubuntu-xenial:~/fabric-samples/first-network/crypto-config/ordererOrganizations$ ls example.com vagrant@ubuntu-xenial:~/fabric-samples/first-network/crypto-config/ordererOrganizations$ cd .. vagrant@ubuntu-xenial:~/fabric-samples/first-network/crypto-config$ cd peerOrganizations/ vagrant@ubuntu-xenial:~/fabric-samples/first-network/crypto-config/peerOrganizations$ ls org1.example.com org2.example.com vagrant@ubuntu-xenial:~/fabric-samples/first-network/crypto-config/peerOrganizations$ cd org1.example.com/ vagrant@ubuntu-xenial:~/fabric-samples/first-network/crypto-config/peerOrganizations/org1.example.com$ ls ca msp peers tlsca users

新生成的docker-compose-e2e.yaml将相应的值给替换了,为:

FABRIC_CA_SERVER_TLS_KEYFILE=/etc/hyperledger/fabric-ca-server-config/CA1_PRIVATE_KEY
#变为:
FABRIC_CA_SERVER_TLS_KEYFILE=/etc/hyperledger/fabric-ca-server-config/b3eb7fc42dbd21...d535f51c53fe4067112e1f5034d_sk

command: sh -c 'fabric-ca-server start --ca.certfile /etc/hyperledger/fabric-ca-server-config/ca.org1.example.com-cert.pem --ca.keyfile /etc/hyperledger/fabric-ca-server-config/CA1_PRIVATE_KEY -b admin:adminpw -d'
#变为:
command: sh -c 'fabric-ca-server start --ca.certfile /etc/hyperledger/fabric-ca-server-config/ca.org1.example.com-cert.pem --ca.keyfile /etc/hyperledger/fabric-ca-server-config/b3eb7fc42dbd21...d535f51c53fe4067112e1f5034d_sk -b admin:adminpw -d'

FABRIC_CA_SERVER_TLS_KEYFILE=/etc/hyperledger/fabric-ca-server-config/CA2_PRIVATE_KEY
#变为:
FABRIC_CA_SERVER_TLS_KEYFILE=/etc/hyperledger/fabric-ca-server-config/9efd46a4ae0d71...7077b28639bf492b863c573cda85f78218_sk

command: sh -c 'fabric-ca-server start --ca.certfile /etc/hyperledger/fabric-ca-server-config/ca.org2.example.com-cert.pem --ca.keyfile /etc/hyperledger/fabric-ca-server-config/CA2_PRIVATE_KEY -b admin:adminpw -d'
#变为:
command: sh -c 'fabric-ca-server start --ca.certfile /etc/hyperledger/fabric-ca-server-config/ca.org2.example.com-cert.pem --ca.keyfile /etc/hyperledger/fabric-ca-server-config/9efd46a4ae0d71...7077b28639bf492b863c573cda85f78218_sk -b admin:adminpw -d'

上面第一步生成我们各种网络实体的所有证书和密钥,genesis block用于引导排序服务,以及配置Channel所需要的一组交易配置集合。

2)up——启动程序

出现一个问题:

vagrant@ubuntu-xenial:~/fabric-samples/first-network$ ./byfn.sh up
Starting for channel 'mychannel' with CLI timeout of '10' seconds and CLI delay of '3' seconds
Continue? [Y/n] y
proceeding ...
./byfn.sh: line 122: configtxlator: command not found

解决办法可见:hyperledge工具-configtxlator

编译好该工具后,再次运行该语句,返回结果为:

vagrant@ubuntu-xenial:~/fabric-samples/first-network$ ./byfn.sh up
Starting for channel 'mychannel' with CLI timeout of '10' seconds and CLI delay of '3' seconds
Continue? [Y/n] y
proceeding ...
LOCAL_VERSION=1.4.1
DOCKER_IMAGE_VERSION=1.4.0
=================== WARNING ===================
  Local fabric binaries and docker images are  
  out of  sync. This may cause problems.       
===============================================
/hyperledger/fabric/.build/bin/cryptogen

##########################################################
##### Generate certificates using cryptogen tool #########
##########################################################
+ cryptogen generate --config=./crypto-config.yaml
org1.example.com
org2.example.com
+ res=0
+ set +x

/hyperledger/fabric/.build/bin/configtxgen
##########################################################
#########  Generating Orderer Genesis block ##############
##########################################################
CONSENSUS_TYPE=solo
+ '[' solo == solo ']'
+ configtxgen -profile TwoOrgsOrdererGenesis -channelID byfn-sys-channel -outputBlock ./channel-artifacts/genesis.block
2019-03-10 02:00:42.879 UTC [common.tools.configtxgen] main -> INFO 001 Loading configuration
2019-03-10 02:00:42.970 UTC [common.tools.configtxgen.localconfig] completeInitialization -> INFO 002 orderer type: solo
2019-03-10 02:00:42.970 UTC [common.tools.configtxgen.localconfig] Load -> INFO 003 Loaded configuration: /home/vagrant/fabric-samples/first-network/configtx.yaml
2019-03-10 02:00:43.001 UTC [common.tools.configtxgen.localconfig] completeInitialization -> INFO 004 orderer type: solo
2019-03-10 02:00:43.002 UTC [common.tools.configtxgen.localconfig] LoadTopLevel -> INFO 005 Loaded configuration: /home/vagrant/fabric-samples/first-network/configtx.yaml
2019-03-10 02:00:43.027 UTC [common.tools.configtxgen] doOutputBlock -> INFO 006 Generating genesis block
2019-03-10 02:00:43.032 UTC [common.tools.configtxgen] doOutputBlock -> INFO 007 Writing genesis block
+ res=0
+ set +x

#################################################################
### Generating channel configuration transaction 'channel.tx' ###
#################################################################
+ configtxgen -profile TwoOrgsChannel -outputCreateChannelTx ./channel-artifacts/channel.tx -channelID mychannel
2019-03-10 02:00:43.135 UTC [common.tools.configtxgen] main -> INFO 001 Loading configuration
2019-03-10 02:00:43.176 UTC [common.tools.configtxgen.localconfig] Load -> INFO 002 Loaded configuration: /home/vagrant/fabric-samples/first-network/configtx.yaml
2019-03-10 02:00:43.201 UTC [common.tools.configtxgen.localconfig] completeInitialization -> INFO 003 orderer type: solo
2019-03-10 02:00:43.201 UTC [common.tools.configtxgen.localconfig] LoadTopLevel -> INFO 004 Loaded configuration: /home/vagrant/fabric-samples/first-network/configtx.yaml
2019-03-10 02:00:43.201 UTC [common.tools.configtxgen] doOutputChannelCreateTx -> INFO 005 Generating new channel configtx
2019-03-10 02:00:43.202 UTC [common.tools.configtxgen.encoder] NewChannelGroup -> WARN 006 Default policy emission is deprecated, please include policy specifications for the channel group in configtx.yaml
2019-03-10 02:00:43.209 UTC [common.tools.configtxgen.encoder] NewChannelGroup -> WARN 007 Default policy emission is deprecated, please include policy specifications for the channel group in configtx.yaml
2019-03-10 02:00:43.213 UTC [common.tools.configtxgen] doOutputChannelCreateTx -> INFO 008 Writing new channel tx
+ res=0
+ set +x

#################################################################
#######    Generating anchor peer update for Org1MSP   ##########
#################################################################
+ configtxgen -profile TwoOrgsChannel -outputAnchorPeersUpdate ./channel-artifacts/Org1MSPanchors.tx -channelID mychannel -asOrg Org1MSP
2019-03-10 02:00:43.322 UTC [common.tools.configtxgen] main -> INFO 001 Loading configuration
2019-03-10 02:00:43.361 UTC [common.tools.configtxgen.localconfig] Load -> INFO 002 Loaded configuration: /home/vagrant/fabric-samples/first-network/configtx.yaml
2019-03-10 02:00:43.388 UTC [common.tools.configtxgen.localconfig] completeInitialization -> INFO 003 orderer type: solo
2019-03-10 02:00:43.388 UTC [common.tools.configtxgen.localconfig] LoadTopLevel -> INFO 004 Loaded configuration: /home/vagrant/fabric-samples/first-network/configtx.yaml
2019-03-10 02:00:43.388 UTC [common.tools.configtxgen] doOutputAnchorPeersUpdate -> INFO 005 Generating anchor peer update
2019-03-10 02:00:43.391 UTC [common.tools.configtxgen] doOutputAnchorPeersUpdate -> INFO 006 Writing anchor peer update
+ res=0
+ set +x

#################################################################
#######    Generating anchor peer update for Org2MSP   ##########
#################################################################
+ configtxgen -profile TwoOrgsChannel -outputAnchorPeersUpdate ./channel-artifacts/Org2MSPanchors.tx -channelID mychannel -asOrg Org2MSP
2019-03-10 02:00:43.499 UTC [common.tools.configtxgen] main -> INFO 001 Loading configuration
2019-03-10 02:00:43.541 UTC [common.tools.configtxgen.localconfig] Load -> INFO 002 Loaded configuration: /home/vagrant/fabric-samples/first-network/configtx.yaml
2019-03-10 02:00:43.566 UTC [common.tools.configtxgen.localconfig] completeInitialization -> INFO 003 orderer type: solo
2019-03-10 02:00:43.566 UTC [common.tools.configtxgen.localconfig] LoadTopLevel -> INFO 004 Loaded configuration: /home/vagrant/fabric-samples/first-network/configtx.yaml
2019-03-10 02:00:43.566 UTC [common.tools.configtxgen] doOutputAnchorPeersUpdate -> INFO 005 Generating anchor peer update
2019-03-10 02:00:43.569 UTC [common.tools.configtxgen] doOutputAnchorPeersUpdate -> INFO 006 Writing anchor peer update
+ res=0
+ set +x

Creating network "net_byfn" with the default driver
Creating volume "net_peer0.org2.example.com" with default driver
Creating volume "net_peer1.org2.example.com" with default driver
Creating volume "net_peer1.org1.example.com" with default driver
Creating volume "net_peer0.org1.example.com" with default driver
Creating volume "net_orderer.example.com" with default driver
Creating orderer.example.com ... 
Creating peer0.org2.example.com ... 
Creating orderer.example.com
Creating peer0.org1.example.com ... 
Creating peer1.org1.example.com ... 
Creating peer1.org2.example.com ... 
Creating peer0.org2.example.com
Creating peer0.org1.example.com
Creating peer1.org1.example.com
Creating peer1.org1.example.com ... done
Creating cli ... 
Creating cli ... done

 ____    _____      _      ____    _____ 
/ ___|  |_   _|    / \    |  _ \  |_   _|
\___ \    | |     / _ \   | |_) |   | |  
 ___) |   | |    / ___ \  |  _ <    | |  
|____/    |_|   /_/   \_\ |_| \_\   |_|  

Build your first network (BYFN) end-to-end test

+ peer channel create -o orderer.example.com:7050 -c mychannel -f ./channel-artifacts/channel.tx --tls true --cafile /opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/ordererOrganizations/example.com/orderers/orderer.example.com/msp/tlscacerts/tlsca.example.com-cert.pem
Channel name : mychannel
Creating channel...
+ res=0
+ set +x
2019-03-10 02:00:46.000 UTC [channelCmd] InitCmdFactory -> INFO 001 Endorser and orderer connections initialized
2019-03-10 02:00:46.030 UTC [cli.common] readBlock -> INFO 002 Received block: 0
===================== Channel 'mychannel' created ===================== 

Having all peers join the channel...
+ peer channel join -b mychannel.block
+ res=0
+ set +x
2019-03-10 02:00:46.084 UTC [channelCmd] InitCmdFactory -> INFO 001 Endorser and orderer connections initialized
2019-03-10 02:00:46.105 UTC [channelCmd] executeJoin -> INFO 002 Successfully submitted proposal to join channel
===================== peer0.org1 joined channel 'mychannel' ===================== 

+ peer channel join -b mychannel.block
+ res=0
+ set +x
2019-03-10 02:00:49.165 UTC [channelCmd] InitCmdFactory -> INFO 001 Endorser and orderer connections initialized
2019-03-10 02:00:49.194 UTC [channelCmd] executeJoin -> INFO 002 Successfully submitted proposal to join channel
===================== peer1.org1 joined channel 'mychannel' ===================== 

+ peer channel join -b mychannel.block
+ res=0
+ set +x
2019-03-10 02:00:52.263 UTC [channelCmd] InitCmdFactory -> INFO 001 Endorser and orderer connections initialized
2019-03-10 02:00:52.292 UTC [channelCmd] executeJoin -> INFO 002 Successfully submitted proposal to join channel
===================== peer0.org2 joined channel 'mychannel' ===================== 

+ peer channel join -b mychannel.block
+ res=0
+ set +x
2019-03-10 02:00:55.354 UTC [channelCmd] InitCmdFactory -> INFO 001 Endorser and orderer connections initialized
2019-03-10 02:00:55.378 UTC [channelCmd] executeJoin -> INFO 002 Successfully submitted proposal to join channel
===================== peer1.org2 joined channel 'mychannel' ===================== 

Updating anchor peers for org1...
+ peer channel update -o orderer.example.com:7050 -c mychannel -f ./channel-artifacts/Org1MSPanchors.tx --tls true --cafile /opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/ordererOrganizations/example.com/orderers/orderer.example.com/msp/tlscacerts/tlsca.example.com-cert.pem
+ res=0
+ set +x
2019-03-10 02:00:58.440 UTC [channelCmd] InitCmdFactory -> INFO 001 Endorser and orderer connections initialized
2019-03-10 02:00:58.455 UTC [channelCmd] update -> INFO 002 Successfully submitted channel update
===================== Anchor peers updated for org 'Org1MSP' on channel 'mychannel' ===================== 

Updating anchor peers for org2...
+ peer channel update -o orderer.example.com:7050 -c mychannel -f ./channel-artifacts/Org2MSPanchors.tx --tls true --cafile /opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/ordererOrganizations/example.com/orderers/orderer.example.com/msp/tlscacerts/tlsca.example.com-cert.pem
+ res=0
+ set +x
2019-03-10 02:01:01.512 UTC [channelCmd] InitCmdFactory -> INFO 001 Endorser and orderer connections initialized
2019-03-10 02:01:01.526 UTC [channelCmd] update -> INFO 002 Successfully submitted channel update
===================== Anchor peers updated for org 'Org2MSP' on channel 'mychannel' ===================== 

Installing chaincode on peer0.org1...
+ peer chaincode install -n mycc -v 1.0 -l golang -p github.com/chaincode/chaincode_example02/go/
+ res=0
+ set +x
2019-03-10 02:01:04.590 UTC [chaincodeCmd] checkChaincodeCmdParams -> INFO 001 Using default escc
2019-03-10 02:01:04.590 UTC [chaincodeCmd] checkChaincodeCmdParams -> INFO 002 Using default vscc
2019-03-10 02:01:04.756 UTC [chaincodeCmd] install -> INFO 003 Installed remotely response:<status:200 payload:"OK" > 
===================== Chaincode is installed on peer0.org1 ===================== 

Install chaincode on peer0.org2...
+ peer chaincode install -n mycc -v 1.0 -l golang -p github.com/chaincode/chaincode_example02/go/
+ res=0
+ set +x
2019-03-10 02:01:04.816 UTC [chaincodeCmd] checkChaincodeCmdParams -> INFO 001 Using default escc
2019-03-10 02:01:04.816 UTC [chaincodeCmd] checkChaincodeCmdParams -> INFO 002 Using default vscc
2019-03-10 02:01:04.964 UTC [chaincodeCmd] install -> INFO 003 Installed remotely response:<status:200 payload:"OK" > 
===================== Chaincode is installed on peer0.org2 ===================== 

Instantiating chaincode on peer0.org2...
+ peer chaincode instantiate -o orderer.example.com:7050 --tls true --cafile /opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/ordererOrganizations/example.com/orderers/orderer.example.com/msp/tlscacerts/tlsca.example.com-cert.pem -C mychannel -n mycc -l golang -v 1.0 -c '{"Args":["init","a","100","b","200"]}' -P 'AND ('\''Org1MSP.peer'\'','\''Org2MSP.peer'\'')'
+ res=0
+ set +x
2019-03-10 02:01:05.023 UTC [chaincodeCmd] checkChaincodeCmdParams -> INFO 001 Using default escc
2019-03-10 02:01:05.023 UTC [chaincodeCmd] checkChaincodeCmdParams -> INFO 002 Using default vscc
===================== Chaincode is instantiated on peer0.org2 on channel 'mychannel' ===================== 

Querying chaincode on peer0.org1...
===================== Querying on peer0.org1 on channel 'mychannel'... ===================== 
Attempting to Query peer0.org1 ...3 secs
+ peer chaincode query -C mychannel -n mycc -c '{"Args":["query","a"]}'
+ res=0
+ set +x

100
===================== Query successful on peer0.org1 on channel 'mychannel' ===================== 
Sending invoke transaction on peer0.org1 peer0.org2...
+ peer chaincode invoke -o orderer.example.com:7050 --tls true --cafile /opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/ordererOrganizations/example.com/orderers/orderer.example.com/msp/tlscacerts/tlsca.example.com-cert.pem -C mychannel -n mycc --peerAddresses peer0.org1.example.com:7051 --tlsRootCertFiles /opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org1.example.com/peers/peer0.org1.example.com/tls/ca.crt --peerAddresses peer0.org2.example.com:9051 --tlsRootCertFiles /opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org2.example.com/peers/peer0.org2.example.com/tls/ca.crt -c '{"Args":["invoke","a","b","10"]}'
+ res=0
+ set +x
2019-03-10 02:01:35.812 UTC [chaincodeCmd] chaincodeInvokeOrQuery -> INFO 001 Chaincode invoke successful. result: status:200 
===================== Invoke transaction successful on peer0.org1 peer0.org2 on channel 'mychannel' ===================== 

Installing chaincode on peer1.org2...
+ peer chaincode install -n mycc -v 1.0 -l golang -p github.com/chaincode/chaincode_example02/go/
+ res=0
+ set +x
2019-03-10 02:01:35.864 UTC [chaincodeCmd] checkChaincodeCmdParams -> INFO 001 Using default escc
2019-03-10 02:01:35.864 UTC [chaincodeCmd] checkChaincodeCmdParams -> INFO 002 Using default vscc
2019-03-10 02:01:35.993 UTC [chaincodeCmd] install -> INFO 003 Installed remotely response:<status:200 payload:"OK" > 
===================== Chaincode is installed on peer1.org2 ===================== 

Querying chaincode on peer1.org2...
===================== Querying on peer1.org2 on channel 'mychannel'... ===================== 
+ peer chaincode query -C mychannel -n mycc -c '{"Args":["query","a"]}'
Attempting to Query peer1.org2 ...4 secs
+ res=0
+ set +x

90
===================== Query successful on peer1.org2 on channel 'mychannel' ===================== 

========= All GOOD, BYFN execution completed =========== 


 _____   _   _   ____   
| ____| | \ | | |  _ \  
|  _|   |  \| | | | | | 
| |___  | |\  | | |_| | 
|_____| |_| \_| |____/  

vagrant@ubuntu-xenial:~/fabric-samples/first-network$ 
View Code

查看实现代码:

 networkUp()函数首先回去检查是否存在crypto-config文件夹,如果不存在,会先执行一遍./byfn.sh generate实现的操作:

  # generate artifacts if they don't exist
  if [ ! -d "crypto-config" ]; then
    generateCerts
    replacePrivateKey
    generateChannelArtifacts
  fi

当各个条件都满足后,就会启动网络:

  # now run the end to end script
  docker exec cli scripts/script.sh $CHANNEL_NAME $CLI_DELAY $LANGUAGE $CLI_TIMEOUT $VERBOSE

scripts/script.sh代码为:

#!/bin/bash

echo
echo " ____    _____      _      ____    _____ "
echo "/ ___|  |_   _|    / \    |  _ \  |_   _|"
echo "\___ \    | |     / _ \   | |_) |   | |  "
echo " ___) |   | |    / ___ \  |  _ <    | |  "
echo "|____/    |_|   /_/   \_\ |_| \_\   |_|  "
echo
echo "Build your first network (BYFN) end-to-end test"
echo
CHANNEL_NAME="$1"
DELAY="$2"
LANGUAGE="$3"
TIMEOUT="$4"
VERBOSE="$5"
: ${CHANNEL_NAME:="mychannel"}
: ${DELAY:="3"}
: ${LANGUAGE:="golang"}
: ${TIMEOUT:="10"}
: ${VERBOSE:="false"}
LANGUAGE=`echo "$LANGUAGE" | tr [:upper:] [:lower:]`
COUNTER=1
MAX_RETRY=10

CC_SRC_PATH="github.com/chaincode/chaincode_example02/go/"
if [ "$LANGUAGE" = "node" ]; then
    CC_SRC_PATH="/opt/gopath/src/github.com/chaincode/chaincode_example02/node/"
fi

if [ "$LANGUAGE" = "java" ]; then
    CC_SRC_PATH="/opt/gopath/src/github.com/chaincode/chaincode_example02/java/"
fi

echo "Channel name : "$CHANNEL_NAME

# import utils
. scripts/utils.sh

createChannel() {
    setGlobals 0 1

    if [ -z "$CORE_PEER_TLS_ENABLED" -o "$CORE_PEER_TLS_ENABLED" = "false" ]; then
                set -x
        peer channel create -o orderer.example.com:7050 -c $CHANNEL_NAME -f ./channel-artifacts/channel.tx >&log.txt
        res=$?
                set +x
    else
                set -x
        peer channel create -o orderer.example.com:7050 -c $CHANNEL_NAME -f ./channel-artifacts/channel.tx --tls $CORE_PEER_TLS_ENABLED --cafile $ORDERER_CA >&log.txt
        res=$?
                set +x
    fi
    cat log.txt
    verifyResult $res "Channel creation failed"
    echo "===================== Channel '$CHANNEL_NAME' created ===================== "
    echo
}

joinChannel () {
    for org in 1 2; do
        for peer in 0 1; do
        joinChannelWithRetry $peer $org #joinChannelWithRetry函数是scripts/utils.sh中定义的函数
        echo "===================== peer${peer}.org${org} joined channel '$CHANNEL_NAME' ===================== "
        sleep $DELAY
        echo
        done
    done
}

## Create channel,先创建通道
echo "Creating channel..."
createChannel

## Join all the peers to the channel,将org1的peer0、peer1和org2的peer0、peer1添加到通道中,以及利用$CHANNEL_NAME.block去创建一条链
echo "Having all peers join the channel..."
joinChannel
#现在我们有了由4个peer节点以及2个组织构成的信道。这是我们的TwoOrgsChannel配置文件。
#peer0.org1.example.com和peer1.org1.example.com属于Org1;peer0.org2.example.com和peer1.org2.example.com属于Org2
#这些关系是通过crypto-config.yaml定义的,MSP路径在docker-compose文件中被指定


## Set the anchor peers for each org in the channel,为每一个组织在通道中设置锚节点,updateAnchorPeers函数是scripts/utils.sh中定义的函数
#updateAnchorPeers函数通过携带channel的名字传递Org1MSPanchors.tx和Org2MSPanchors.tx配置到排序服务来实现anchor peer的更新
echo "Updating anchor peers for org1..."
updateAnchorPeers 0 1 #将组织org1中的peer0设置为锚节点
echo "Updating anchor peers for org2..."
updateAnchorPeers 0 2 #将组织org2中的peer0设置为锚节点

## Install chaincode on peer0.org1 and peer0.org2,在两个锚节点上安装链码,即智能合约
echo "Installing chaincode on peer0.org1..."
installChaincode 0 1
echo "Install chaincode on peer0.org2..."
installChaincode 0 2

# Instantiate chaincode on peer0.org2,然后实例化锚点peer0.org2上的链码,将链码上的值设为{"Args":["init","a","100","b","200"]}
# 这个链码在peer0.org2.example.com被实例化。实例化过程将链码添加到channel上,并启动peer节点对应的容器,并且初始化和链码服务有关的键值对。
# 示例的初始化的值是[”a“,”100“,”b“,”200“]。实例化的结果是一个名为dev-peer0.org2.example.com-mycc-1.0的容器启动了
# 实例化过程同样为背书策略传递相关参数。策略被定义为-P "AND ('Org1MSP.peer','Org2MSP.peer'),意思是任何交易必须被Org1和Org2同时背书。
# 只需要通过一个节点对链码进行实例化,用于将链码添加到channel上,之后从别的节点上调用或查询链码是就会直接生成容器来进行操作
echo "Instantiating chaincode on peer0.org2..."
instantiateChaincode 0 2

# Query chaincode on peer0.org1,然后我们从peer0.org1节点查看链码
# 一个针对a的查询发往peer0.org1.example.com。链码服务已经被安装在了peer0.org1.example.com,因此这次查询将启动一个名为dev-peer0.org1.example.com-mycc-1.0的容器。
# 查询的结果也将被返回。因为没有写操作,因此查询的结果的值将为100
# 第三个参数用于作为EXPECTED_RESULT,用于查看得到的值是否与期望相符
echo "Querying chaincode on peer0.org1..."
chaincodeQuery 0 1 100

# Invoke chaincode on peer0.org1 and peer0.org2
# 一次invoke被发往peer0.org1.example.com,从a转移10到b
# 输入参数为0 1 0 20 1说明invoke在peer0.org1上运行,0 1 0 2说明需要两者对交易进行背书
echo "Sending invoke transaction on peer0.org1 peer0.org2..."
chaincodeInvoke 0 1 0 2

## Install chaincode on peer1.org2
#然后链码被安装到peer1.org2.example.com
echo "Installing chaincode on peer1.org2..."
installChaincode 1 2

# Query on chaincode on peer1.org2, check if the result is 90
# 一个query请求被发往peer1.org2.example.com用于查询a的值。
# 这将启动第三个链码容器名为dev-peer1.org2.example.com-mycc-1.0。返回a的值为90,正确地反映了之前的交易,a的值被转移了10
echo "Querying chaincode on peer1.org2..."
chaincodeQuery 1 2 90

echo
echo "========= All GOOD, BYFN execution completed =========== "
echo

echo
echo " _____   _   _   ____   "
echo "| ____| | \ | | |  _ \  "
echo "|  _|   |  \| | | | | | "
echo "| |___  | |\  | | |_| | "
echo "|_____| |_| \_| |____/  "
echo

exit 0

调用的scripts/utils.sh代码为:

#
# Copyright IBM Corp All Rights Reserved
#
# SPDX-License-Identifier: Apache-2.0
#

# This is a collection of bash functions used by different scripts

ORDERER_CA=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/ordererOrganizations/example.com/orderers/orderer.example.com/msp/tlscacerts/tlsca.example.com-cert.pem
PEER0_ORG1_CA=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org1.example.com/peers/peer0.org1.example.com/tls/ca.crt
PEER0_ORG2_CA=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org2.example.com/peers/peer0.org2.example.com/tls/ca.crt
PEER0_ORG3_CA=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org3.example.com/peers/peer0.org3.example.com/tls/ca.crt

# verify the result of the end-to-end test
verifyResult() {
  if [ $1 -ne 0 ]; then
    echo "!!!!!!!!!!!!!!! "$2" !!!!!!!!!!!!!!!!"
    echo "========= ERROR !!! FAILED to execute End-2-End Scenario ==========="
    echo
    exit 1
  fi
}

# Set OrdererOrg.Admin globals
setOrdererGlobals() {
  CORE_PEER_LOCALMSPID="OrdererMSP"
  CORE_PEER_TLS_ROOTCERT_FILE=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/ordererOrganizations/example.com/orderers/orderer.example.com/msp/tlscacerts/tlsca.example.com-cert.pem
  CORE_PEER_MSPCONFIGPATH=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/ordererOrganizations/example.com/users/[email protected]/msp
}

#根据输入的参数来定义相应的变量值,用于之后的配置
setGlobals() {
  PEER=$1
  ORG=$2
  if [ $ORG -eq 1 ]; then
    CORE_PEER_LOCALMSPID="Org1MSP"
    CORE_PEER_TLS_ROOTCERT_FILE=$PEER0_ORG1_CA
    CORE_PEER_MSPCONFIGPATH=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org1.example.com/users/[email protected]/msp
    if [ $PEER -eq 0 ]; then
      CORE_PEER_ADDRESS=peer0.org1.example.com:7051
    else
      CORE_PEER_ADDRESS=peer1.org1.example.com:8051
    fi
  elif [ $ORG -eq 2 ]; then
    CORE_PEER_LOCALMSPID="Org2MSP"
    CORE_PEER_TLS_ROOTCERT_FILE=$PEER0_ORG2_CA
    CORE_PEER_MSPCONFIGPATH=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org2.example.com/users/[email protected]/msp
    if [ $PEER -eq 0 ]; then
      CORE_PEER_ADDRESS=peer0.org2.example.com:9051
    else
      CORE_PEER_ADDRESS=peer1.org2.example.com:10051
    fi

  elif [ $ORG -eq 3 ]; then
    CORE_PEER_LOCALMSPID="Org3MSP"
    CORE_PEER_TLS_ROOTCERT_FILE=$PEER0_ORG3_CA
    CORE_PEER_MSPCONFIGPATH=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org3.example.com/users/[email protected]/msp
    if [ $PEER -eq 0 ]; then
      CORE_PEER_ADDRESS=peer0.org3.example.com:11051
    else
      CORE_PEER_ADDRESS=peer1.org3.example.com:12051
    fi
  else
    echo "================== ERROR !!! ORG Unknown =================="
  fi

  if [ "$VERBOSE" == "true" ]; then
    env | grep CORE
  fi
}

updateAnchorPeers() {
  PEER=$1
  ORG=$2
  setGlobals $PEER $ORG #根据输入的参数来定义相应的变量值,用于之后的配置

  if [ -z "$CORE_PEER_TLS_ENABLED" -o "$CORE_PEER_TLS_ENABLED" = "false" ]; then
    set -x
    peer channel update -o orderer.example.com:7050 -c $CHANNEL_NAME -f ./channel-artifacts/${CORE_PEER_LOCALMSPID}anchors.tx >&log.txt
    res=$?
    set +x
  else
    set -x
    peer channel update -o orderer.example.com:7050 -c $CHANNEL_NAME -f ./channel-artifacts/${CORE_PEER_LOCALMSPID}anchors.tx --tls $CORE_PEER_TLS_ENABLED --cafile $ORDERER_CA >&log.txt
    res=$?
    set +x
  fi
  cat log.txt
  #查看添加锚节点操作结果是否错误,错误则返回错误信息
  verifyResult $res "Anchor peer update failed"
  echo "===================== Anchor peers updated for org '$CORE_PEER_LOCALMSPID' on channel '$CHANNEL_NAME' ===================== "
  sleep $DELAY
  echo
}

## Sometimes Join takes time hence RETRY at least 5 times
joinChannelWithRetry() {
  PEER=$1
  ORG=$2
  setGlobals $PEER $ORG #根据输入的参数来定义相应的变量值,用于之后的配置

  set -x
  peer channel join -b $CHANNEL_NAME.block >&log.txt
  res=$?
  set +x
  cat log.txt
  if [ $res -ne 0 -a $COUNTER -lt $MAX_RETRY ]; then
    COUNTER=$(expr $COUNTER + 1)
    echo "peer${PEER}.org${ORG} failed to join the channel, Retry after $DELAY seconds"
    sleep $DELAY
    joinChannelWithRetry $PEER $ORG
  else
    COUNTER=1
  fi
  #查看添加节点到通道操作结果是否错误,错误则返回错误信息
  verifyResult $res "After $MAX_RETRY attempts, peer${PEER}.org${ORG} has failed to join channel '$CHANNEL_NAME' "
}

installChaincode() {
  PEER=$1
  ORG=$2
  setGlobals $PEER $ORG
  VERSION=${3:-1.0}
  set -x
  peer chaincode install -n mycc -v ${VERSION} -l ${LANGUAGE} -p ${CC_SRC_PATH} >&log.txt
  res=$?
  set +x
  cat log.txt
  #查看添加链码到锚点的操作结果是否错误,错误则返回错误信息
  verifyResult $res "Chaincode installation on peer${PEER}.org${ORG} has failed"
  echo "===================== Chaincode is installed on peer${PEER}.org${ORG} ===================== "
  echo
}

instantiateChaincode() {
  PEER=$1
  ORG=$2
  setGlobals $PEER $ORG
  VERSION=${3:-1.0}

  # 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
  if [ -z "$CORE_PEER_TLS_ENABLED" -o "$CORE_PEER_TLS_ENABLED" = "false" ]; then
    set -x
    #-P "AND ('Org1MSP.peer','Org2MSP.peer')说明可以使用Org1MSP.peer和Org2MSP.peer同时进行背书
    peer chaincode instantiate -o orderer.example.com:7050 -C $CHANNEL_NAME -n mycc -l ${LANGUAGE} -v ${VERSION} -c '{"Args":["init","a","100","b","200"]}' -P "AND ('Org1MSP.peer','Org2MSP.peer')" >&log.txt
    res=$?
    set +x
  else
    set -x
    peer chaincode instantiate -o orderer.example.com:7050 --tls $CORE_PEER_TLS_ENABLED --cafile $ORDERER_CA -C $CHANNEL_NAME -n mycc -l ${LANGUAGE} -v 1.0 -c '{"Args":["init","a","100","b","200"]}' -P "AND ('Org1MSP.peer','Org2MSP.peer')" >&log.txt
    res=$?
    set +x
  fi
  cat log.txt
  verifyResult $res "Chaincode instantiation on peer${PEER}.org${ORG} on channel '$CHANNEL_NAME' failed"
  echo "===================== Chaincode is instantiated on peer${PEER}.org${ORG} on channel '$CHANNEL_NAME' ===================== "
  echo
}

upgradeChaincode() {
  PEER=$1
  ORG=$2
  setGlobals $PEER $ORG

  set -x
  peer chaincode upgrade -o orderer.example.com:7050 --tls $CORE_PEER_TLS_ENABLED --cafile $ORDERER_CA -C $CHANNEL_NAME -n mycc -v 2.0 -c '{"Args":["init","a","90","b","210"]}' -P "AND ('Org1MSP.peer','Org2MSP.peer','Org3MSP.peer')"
  res=$?
  set +x
  cat log.txt
  verifyResult $res "Chaincode upgrade on peer${PEER}.org${ORG} has failed"
  echo "===================== Chaincode is upgraded on peer${PEER}.org${ORG} on channel '$CHANNEL_NAME' ===================== "
  echo
}

chaincodeQuery() {
  PEER=$1
  ORG=$2
  setGlobals $PEER $ORG
  EXPECTED_RESULT=$3
  echo "===================== Querying on peer${PEER}.org${ORG} on channel '$CHANNEL_NAME'... ===================== "
  local rc=1
  local starttime=$(date +%s)

  # continue to poll
  # we either get a successful response, or reach TIMEOUT
  while
    test "$(($(date +%s) - starttime))" -lt "$TIMEOUT" -a $rc -ne 0
  do
    sleep $DELAY
    echo "Attempting to Query peer${PEER}.org${ORG} ...$(($(date +%s) - starttime)) secs"
    set -x
    peer chaincode query -C $CHANNEL_NAME -n mycc -c '{"Args":["query","a"]}' >&log.txt
    res=$?
    set +x
    test $res -eq 0 && VALUE=$(cat log.txt | awk '/Query Result/ {print $NF}')
    test "$VALUE" = "$EXPECTED_RESULT" && let rc=0
    # removed the string "Query Result" from peer chaincode query command
    # result. as a result, have to support both options until the change
    # is merged.
    test $rc -ne 0 && VALUE=$(cat log.txt | egrep '^[0-9]+$')
    test "$VALUE" = "$EXPECTED_RESULT" && let rc=0
  done
  echo
  cat log.txt
  if test $rc -eq 0; then
    echo "===================== Query successful on peer${PEER}.org${ORG} on channel '$CHANNEL_NAME' ===================== "
  else
    echo "!!!!!!!!!!!!!!! Query result on peer${PEER}.org${ORG} is INVALID !!!!!!!!!!!!!!!!"
    echo "================== ERROR !!! FAILED to execute End-2-End Scenario =================="
    echo
    exit 1
  fi
}

# fetchChannelConfig <channel_id> <output_json>
# Writes the current channel config for a given channel to a JSON file
fetchChannelConfig() {
  CHANNEL=$1
  OUTPUT=$2

  setOrdererGlobals

  echo "Fetching the most recent configuration block for the channel"
  if [ -z "$CORE_PEER_TLS_ENABLED" -o "$CORE_PEER_TLS_ENABLED" = "false" ]; then
    set -x
    peer channel fetch config config_block.pb -o orderer.example.com:7050 -c $CHANNEL --cafile $ORDERER_CA
    set +x
  else
    set -x
    peer channel fetch config config_block.pb -o orderer.example.com:7050 -c $CHANNEL --tls --cafile $ORDERER_CA
    set +x
  fi

  echo "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
}

# signConfigtxAsPeerOrg <org> <configtx.pb>
# Set the peerOrg admin of an org and signing the config update
signConfigtxAsPeerOrg() {
  PEERORG=$1
  TX=$2
  setGlobals 0 $PEERORG
  set -x
  peer channel signconfigtx -f "${TX}"
  set +x
}

# 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
createConfigUpdate() {
  CHANNEL=$1
  ORIGINAL=$2
  MODIFIED=$3
  OUTPUT=$4

  set -x
  configtxlator proto_encode --input "${ORIGINAL}" --type common.Config >original_config.pb
  configtxlator proto_encode --input "${MODIFIED}" --type common.Config >modified_config.pb
  configtxlator compute_update --channel_id "${CHANNEL}" --original original_config.pb --updated modified_config.pb >config_update.pb
  configtxlator proto_decode --input config_update.pb --type common.ConfigUpdate >config_update.json
  echo '{"payload":{"header":{"channel_header":{"channel_id":"'$CHANNEL'", "type":2}},"data":{"config_update":'$(cat config_update.json)'}}}' | jq . >config_update_in_envelope.json
  configtxlator proto_encode --input config_update_in_envelope.json --type common.Envelope >"${OUTPUT}"
  set +x
}

# parsePeerConnectionParameters $@
# Helper function that takes the parameters from a chaincode operation
# (e.g. invoke, query, instantiate) and checks for an even number of
# peers and associated org, then sets $PEER_CONN_PARMS and $PEERS
parsePeerConnectionParameters() {
  # check for uneven number of peer and org parameters
  if [ $(($# % 2)) -ne 0 ]; then #$#即传入参数的个数
    exit 1
  fi

  PEER_CONN_PARMS=""
  PEERS=""
  while [ "$#" -gt 0 ]; do
    setGlobals $1 $2
    PEER="peer$1.org$2"
    PEERS="$PEERS $PEER"
    PEER_CONN_PARMS="$PEER_CONN_PARMS --peerAddresses $CORE_PEER_ADDRESS"
    if [ -z "$CORE_PEER_TLS_ENABLED" -o "$CORE_PEER_TLS_ENABLED" = "true" ]; then
      TLSINFO=$(eval echo "--tlsRootCertFiles \$PEER$1_ORG$2_CA")
      PEER_CONN_PARMS="$PEER_CONN_PARMS $TLSINFO"
    fi
    # shift by two to get the next pair of peer/org parameters
    shift
    shift #两个shift的作用就是将参数从$1指向了$3,因此下次循环$1 $2得到的是输入参数$3 $4的值,且$#由4变为2
  done
  # remove leading space for output
  PEERS="$(echo -e "$PEERS" | sed -e 's/^[[:space:]]*//')"
}

# chaincodeInvoke <peer> <org> ...
# Accepts as many peer/org pairs as desired and requests endorsement from each
chaincodeInvoke() {
  parsePeerConnectionParameters $@ #$@为传递给脚本或函数的所有参数,parsePeerConnectionParameters函数的作用是获取传入的参数来设置$PEER_CONN_PARMS和$PEERS,输入的参数个数需要为偶数,每个节点带着指定的组织
  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
  if [ -z "$CORE_PEER_TLS_ENABLED" -o "$CORE_PEER_TLS_ENABLED" = "false" ]; then
    set -x
    peer chaincode invoke -o orderer.example.com:7050 -C $CHANNEL_NAME -n mycc $PEER_CONN_PARMS -c '{"Args":["invoke","a","b","10"]}' >&log.txt
    res=$?
    set +x
  else
    set -x
    peer chaincode invoke -o orderer.example.com:7050 --tls $CORE_PEER_TLS_ENABLED --cafile $ORDERER_CA -C $CHANNEL_NAME -n mycc $PEER_CONN_PARMS -c '{"Args":["invoke","a","b","10"]}' >&log.txt
    res=$?
    set +x
  fi
  cat log.txt
  verifyResult $res "Invoke execution on $PEERS failed "
  echo "===================== Invoke transaction successful on $PEERS on channel '$CHANNEL_NAME' ===================== "
  echo
}
View Code

为了能够正确地在账本上进行读写操作,链码服务必须被安装在peer节点上。此外,每个peer节点的链码服务的容器除了init或者传统的交易-读/写-针对该链码服务执行(例如查询a的值),在其他情况下不会启动。

交易导致容器的启动。

当然,所有信道中的节点都持有以块的形式顺序存储的不可变的账本精确的备份,以及状态数据库来保存前状态的快照。这包括了没有在其上安装链码服务的peer节点(peer1.org2.example.com如上所示)。最后,链码在被安装后将是可达状态,因为它已经被实例化了。

此时使用docker查看容器状态:

vagrant@ubuntu-xenial:~/fabric-samples/first-network/channel-artifacts$ docker container ls
CONTAINER ID        IMAGE                                                                                                  COMMAND                  CREATED             STATUS              PORTS                      NAMES
ec6368e29288        dev-peer1.org2.example.com-mycc-1.0-26c2ef32838554aac4f7ad6f100aca865e87959c9a126e86d764c8d01f8346ab   "chaincode -peer.add…"   8 hours ago         Up 8 hours                                     dev-peer1.org2.example.com-mycc-1.0
8eb3f4c949f9        dev-peer0.org1.example.com-mycc-1.0-384f11f484b9302df90b453200cfb25174305fce8f53f4e94d45ee3b6cab0ce9   "chaincode -peer.add…"   8 hours ago         Up 8 hours                                     dev-peer0.org1.example.com-mycc-1.0
8614784a271a        dev-peer0.org2.example.com-mycc-1.0-15b571b3ce849066b7ec74497da3b27e54e0df1345daff3951b94245ce09c42b   "chaincode -peer.add…"   8 hours ago         Up 8 hours                                     dev-peer0.org2.example.com-mycc-1.0
aa96d57cf2fe        hyperledger/fabric-tools:latest                                                                        "/bin/bash"              8 hours ago         Up 8 hours                                     cli
35cd12cdebae        hyperledger/fabric-peer:latest                                                                         "peer node start"        8 hours ago         Up 8 hours          0.0.0.0:8051->8051/tcp     peer1.org1.example.com
9fbc87c27537        hyperledger/fabric-peer:latest                                                                         "peer node start"        8 hours ago         Up 8 hours          0.0.0.0:10051->10051/tcp   peer1.org2.example.com
fd76d0279fd2        hyperledger/fabric-peer:latest                                                                         "peer node start"        8 hours ago         Up 8 hours          0.0.0.0:9051->9051/tcp     peer0.org2.example.com
c7a8e06f4fe0        hyperledger/fabric-peer:latest                                                                         "peer node start"        8 hours ago         Up 8 hours          0.0.0.0:7051->7051/tcp     peer0.org1.example.com
6b7d3f42e11e        hyperledger/fabric-orderer:latest                                                                      "orderer"                8 hours ago         Up 8 hours          0.0.0.0:7050->7050/tcp     orderer.example.com

3)查看日志

1》容器日志

vagrant@ubuntu-xenial:~/fabric-samples/first-network/channel-artifacts$ docker logs -f cli

2》链码日志

vagrant@ubuntu-xenial:~/fabric-samples/first-network/channel-artifacts$ docker logs dev-peer1.org2.example.com-mycc-1.0
ex02 Invoke
Query Response:{"Name":"a","Amount":"90"}

vagrant@ubuntu-xenial:~/fabric-samples/first-network/channel-artifacts$ docker logs dev-peer0.org1.example.com-mycc-1.0
ex02 Invoke
Query Response:{"Name":"a","Amount":"100"}
ex02 Invoke
Aval = 90, Bval = 210

vagrant@ubuntu-xenial:~/fabric-samples/first-network/channel-artifacts$ docker logs dev-peer0.org2.example.com-mycc-1.0
ex02 Init
Aval = 100, Bval = 200
ex02 Invoke
Aval = 90, Bval = 210

4)使用的docker-compose

BYFN示例给我们提供了两种风格的Docker Compose文件,它们都继承自docker-compose-base.yaml

1》 docker-compose-cli.yaml

该文件提供了一个CLI容器,以及一个orderer容器,四个peer容器。我们用此文件来展开这个页面上的所有说明。

# Copyright IBM Corp. All Rights Reserved.
#
# SPDX-License-Identifier: Apache-2.0
#

version: '2'

volumes:
  orderer.example.com:
  peer0.org1.example.com:
  peer1.org1.example.com:
  peer0.org2.example.com:
  peer1.org2.example.com:

networks:
  byfn:

services:

  orderer.example.com:
    extends:
      file:   base/docker-compose-base.yaml
      service: orderer.example.com
    container_name: orderer.example.com
    networks:
      - byfn

  peer0.org1.example.com:
    container_name: peer0.org1.example.com
    extends:
      file:  base/docker-compose-base.yaml
      service: peer0.org1.example.com
    networks:
      - byfn

  peer1.org1.example.com:
    container_name: peer1.org1.example.com
    extends:
      file:  base/docker-compose-base.yaml
      service: peer1.org1.example.com
    networks:
      - byfn

  peer0.org2.example.com:
    container_name: peer0.org2.example.com
    extends:
      file:  base/docker-compose-base.yaml
      service: peer0.org2.example.com
    networks:
      - byfn

  peer1.org2.example.com:
    container_name: peer1.org2.example.com
    extends:
      file:  base/docker-compose-base.yaml
      service: peer1.org2.example.com
    networks:
      - byfn

  cli:
    container_name: cli
    image: hyperledger/fabric-tools:$IMAGE_TAG
    tty: true
    stdin_open: true
    environment:
      - GOPATH=/opt/gopath
      - CORE_VM_ENDPOINT=unix:///host/var/run/docker.sock
      #- FABRIC_LOGGING_SPEC=DEBUG
      - FABRIC_LOGGING_SPEC=INFO
      - CORE_PEER_ID=cli
      - CORE_PEER_ADDRESS=peer0.org1.example.com:7051
      - CORE_PEER_LOCALMSPID=Org1MSP
      - CORE_PEER_TLS_ENABLED=true
      - CORE_PEER_TLS_CERT_FILE=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org1.example.com/peers/peer0.org1.example.com/tls/server.crt
      - CORE_PEER_TLS_KEY_FILE=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org1.example.com/peers/peer0.org1.example.com/tls/server.key
      - CORE_PEER_TLS_ROOTCERT_FILE=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org1.example.com/peers/peer0.org1.example.com/tls/ca.crt
      - CORE_PEER_MSPCONFIGPATH=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org1.example.com/users/[email protected]/msp
    working_dir: /opt/gopath/src/github.com/hyperledger/fabric/peer
    command: /bin/bash
    volumes:
        - /var/run/:/host/var/run/
        - ./../chaincode/:/opt/gopath/src/github.com/chaincode
        - ./crypto-config:/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/
        - ./scripts:/opt/gopath/src/github.com/hyperledger/fabric/peer/scripts/
        - ./channel-artifacts:/opt/gopath/src/github.com/hyperledger/fabric/peer/channel-artifacts
    depends_on:
      - orderer.example.com
      - peer0.org1.example.com
      - peer1.org1.example.com
      - peer0.org2.example.com
      - peer1.org2.example.com
    networks:
      - byfn
View Code

2》docker-compose-e2e.yaml

该文件被构造为使用Node.js SDK来运行端到端测试。除了SDK的功能之外,它主要的区别在于它有运行fabric-ca服务的容器。因此,我们能够向组织的CA节点发送REST的请求用于注册和登记。

vagrant@ubuntu-xenial:~/fabric-samples/first-network$ cat docker-compose-e2e.yaml 
# Copyright IBM Corp. All Rights Reserved.
#
# SPDX-License-Identifier: Apache-2.0
#

version: '2'

volumes:
  orderer.example.com:
  peer0.org1.example.com:
  peer1.org1.example.com:
  peer0.org2.example.com:
  peer1.org2.example.com:

networks:
  byfn:
services:
  ca0:
    image: hyperledger/fabric-ca:$IMAGE_TAG
    environment:
      - FABRIC_CA_HOME=/etc/hyperledger/fabric-ca-server
      - FABRIC_CA_SERVER_CA_NAME=ca-org1
      - FABRIC_CA_SERVER_TLS_ENABLED=true
      - FABRIC_CA_SERVER_TLS_CERTFILE=/etc/hyperledger/fabric-ca-server-config/ca.org1.example.com-cert.pem
      - FABRIC_CA_SERVER_TLS_KEYFILE=/etc/hyperledger/fabric-ca-server-config/c46248ab640500ea3...e571e5df2a77f57e3a48_sk
    ports:
      - "7054:7054"
    command: sh -c 'fabric-ca-server start --ca.certfile /etc/hyperledger/fabric-ca-server-config/ca.org1.example.com-cert.pem --ca.keyfile /etc/hyperledger/fabric-ca-server-config/c46248ab640500ea3...e571e5df2a77f57e3a48_sk -b admin:adminpw -d'
    volumes:
      - ./crypto-config/peerOrganizations/org1.example.com/ca/:/etc/hyperledger/fabric-ca-server-config
    container_name: ca_peerOrg1
    networks:
      - byfn

  ca1:
    image: hyperledger/fabric-ca:$IMAGE_TAG
    environment:
      - FABRIC_CA_HOME=/etc/hyperledger/fabric-ca-server
      - FABRIC_CA_SERVER_CA_NAME=ca-org2
      - FABRIC_CA_SERVER_TLS_ENABLED=true
      - FABRIC_CA_SERVER_TLS_CERTFILE=/etc/hyperledger/fabric-ca-server-config/ca.org2.example.com-cert.pem
      - FABRIC_CA_SERVER_TLS_KEYFILE=/etc/hyperledger/fabric-ca-server-config/f9ec1c2b48d9cb...c013e6bad0b60_sk
    ports:
      - "8054:7054"
    command: sh -c 'fabric-ca-server start --ca.certfile /etc/hyperledger/fabric-ca-server-config/ca.org2.example.com-cert.pem --ca.keyfile /etc/hyperledger/fabric-ca-server-config/f9ec1c2b48d9cb...c013e6bad0b60_sk -b admin:adminpw -d'
    volumes:
      - ./crypto-config/peerOrganizations/org2.example.com/ca/:/etc/hyperledger/fabric-ca-server-config
    container_name: ca_peerOrg2
    networks:
      - byfn

  orderer.example.com:
    extends:
      file:   base/docker-compose-base.yaml
      service: orderer.example.com
    container_name: orderer.example.com
    networks:
      - byfn

  peer0.org1.example.com:
    container_name: peer0.org1.example.com
    extends:
      file:  base/docker-compose-base.yaml
      service: peer0.org1.example.com
    networks:
      - byfn

  peer1.org1.example.com:
    container_name: peer1.org1.example.com
    extends:
      file:  base/docker-compose-base.yaml
      service: peer1.org1.example.com
    networks:
      - byfn

  peer0.org2.example.com:
    container_name: peer0.org2.example.com
    extends:
      file:  base/docker-compose-base.yaml
      service: peer0.org2.example.com
    networks:
      - byfn

  peer1.org2.example.com:
    container_name: peer1.org2.example.com
    extends:
      file:  base/docker-compose-base.yaml
      service: peer1.org2.example.com
    networks:
      - byfn
View Code

如果你在没有运行byfn.sh脚本的情况下,想使用docker-compose-e2e.yaml,我们需要进行4个轻微的修改。因为

docker-compose-e2e.yaml是通过运行byfn.sh脚本在docker-compose-e2e-template.yaml文件的基础上生成的,需要将docker-compose-e2e-template.yaml文件中的CA1_PRIVATE_KEY和CA2_PRIVATE_KEY值进行手动更改为对应组织的私钥

我们需要指出本组织CA的私钥。你可以在crypto-config文件夹中找到这些值。举个例子,为了定位Org1的私钥,我们将使用crypto-config/peerOrganizations/org1.example.com/ca/。Org2的路径为crypto-config/peerOrganizations/org2.example.com/ca/,如下:

vagrant@ubuntu-xenial:~/fabric-samples/first-network/crypto-config/peerOrganizations/org1.example.com/ca$ ls
c46248ab640...1cca3c5f4c8dae571e5df2a77f57e3a48_sk  ca.org1.example.com-cert.pem

第一个文件夹的名字就是该组织的私钥值

5)使用CouchDB

没有试着使用这个,之后再补上

6)关于数据持久化的提示

如果需要在peer容器或者CouchDB容器进行数据持久化,一种选择是将docker容器内相应的目录挂载到容器所在的宿主机的一个目录中。例如,你可以添加下列的两行到docker-compose-base.yaml文件中peer的约定中:

volumes:
 - /var/hyperledger/peer0:/var/hyperledger/production

对于CouchDB容器,你可以在CouchDB的约定中添加两行:

volumes:
 - /var/hyperledger/couchdb0:/opt/couchdb/data

猜你喜欢

转载自www.cnblogs.com/wanghui-garcia/p/10491546.html
今日推荐