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/Admin@example.com/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/Admin@org1.example.com/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/Admin@org2.example.com/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/Admin@org3.example.com/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/Admin@org1.example.com/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

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM