前言
官方英文:Building Your First Network
中文:構(gòu)建第一個fabric網(wǎng)絡(luò)
感謝中文翻譯闹击!不然這么長的英文以及各種名詞解釋實(shí)在頭疼咳促。有一些和官方英文不一樣的地方我已經(jīng)按官方英文進(jìn)行了補(bǔ)充和修正慧耍,并且盡量簡化了語言履因,因?yàn)橛行┓g過來有點(diǎn)拗口。如果希望看完整及原汁原味的文檔馒铃,推薦看官方英文文檔蟹腾。
本文基于Mac OS
以及Hyperledger Fabric 1.1.0
痕惋。
Building Your First Network
構(gòu)建你的第一個網(wǎng)絡(luò)(BYFN)場景提供了由兩個組織組成的示例Hyperledger Fabric網(wǎng)絡(luò),每個組織持有2個peer節(jié)點(diǎn)娃殖,以及一個“solo”排序服務(wù)值戳。
1.1. 安裝預(yù)置環(huán)境
在我們開始之前,如果你還沒有這樣做炉爆,你可能需要檢查一下在你開發(fā)區(qū)塊鏈應(yīng)用程序或者Hyperledger Fabric的平臺上是否已經(jīng)安裝了預(yù)置環(huán)境堕虹。
你還需要下載并安裝Hyperledger Fabric Samples。你會注意到fabric-samples
文件夾中包含了許多示例芬首。我們將使用first-network
這個例子「袄蹋現(xiàn)在讓我們打開這個子目錄。
cd fabric-samples/first-network
注意:本文檔中提供的命令必須運(yùn)行在
fabric-samples
的子目錄fabric-network
中郁稍。如果你選擇從其他位置運(yùn)行命令赦政,提供的一些腳本將無法找到對應(yīng)的二進(jìn)制。
1.2. 想要現(xiàn)在運(yùn)行嗎耀怜?
我們提供一個完全注釋的腳本byfn.sh
恢着,利用這些Docker鏡像可以快速引導(dǎo)一個由4個代表2個不同組織的peer節(jié)點(diǎn)以及一個排序服務(wù)節(jié)點(diǎn)的Hyperledger fabric網(wǎng)絡(luò)。它還將啟動一個容器來運(yùn)行一個將peer節(jié)點(diǎn)加入channel封寞、部署實(shí)例化鏈碼服務(wù)以及驅(qū)動已經(jīng)部署的鏈碼執(zhí)行交易的腳本然评。
以下是該byfn.sh
腳本的幫助文檔:
./byfn.sh --help
Usage:
byfn.sh up|down|restart|generate [-c <channel name>] [-t <timeout>] [-d <delay>] [-f <docker-compose-file>] [-s <dbtype>]
byfn.sh -h|--help (print this message)
-m <mode> - one of 'up', 'down', 'restart' or 'generate'
- '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
-c <channel name> - channel name to use (defaults to "mychannel")
-t <timeout> - CLI timeout duration in seconds (defaults to 10)
-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
-a - don't ask for confirmation before proceeding
Typically, one would first generate the required certificates and
genesis block, then bring up the network. e.g.:
byfn.sh -m generate -c mychannel
byfn.sh -m up -c mychannel -s couchdb
如果你選擇不提供channel名稱,則腳本將使用默認(rèn)名稱mychannel
狈究。CLI超時參數(shù)(用-t標(biāo)志指定)是一個可選值;如果你選擇不設(shè)置它碗淌,那么CLI容器將會在腳本執(zhí)行完之后退出。
1.3. 生成網(wǎng)絡(luò)
準(zhǔn)備好了嗎抖锥?好吧亿眠!執(zhí)行以下命令。
yuyangdeMacBook-Pro:~ yuyang$ cd /Users/yuyang/fabric-sample/fabric-samples/first-network
yuyangdeMacBook-Pro:first-network yuyang$ ./byfn.sh -m generate
命令行會提示將會發(fā)生什么磅废。當(dāng)提示yes/no時纳像,輸入y或回車鍵來執(zhí)行描述的動作。
Generating certs and genesis block for with channel 'mychannel' and CLI timeout of '10' seconds and CLI delay of '3' seconds
Continue? [Y/n] y
proceeding ...
/Users/yuyang/fabric-sample/fabric-samples/first-network/../bin/cryptogen
##########################################################
##### Generate certificates using cryptogen tool #########
##########################################################
+ cryptogen generate --config=./crypto-config.yaml
org1.example.com
org2.example.com
+ set +x
/Users/yuyang/fabric-sample/fabric-samples/first-network/../bin/configtxgen
##########################################################
######### Generating Orderer Genesis block ##############
##########################################################
+ configtxgen -profile TwoOrgsOrdererGenesis -outputBlock ./channel-artifacts/genesis.block
2018-03-17 21:56:10.295 CST [common/tools/configtxgen] main -> INFO 001 Loading configuration
2018-03-17 21:56:10.307 CST [msp] getMspConfig -> INFO 002 Loading NodeOUs
2018-03-17 21:56:10.307 CST [msp] getMspConfig -> INFO 003 Loading NodeOUs
2018-03-17 21:56:10.307 CST [common/tools/configtxgen] doOutputBlock -> INFO 004 Generating genesis block
2018-03-17 21:56:10.308 CST [common/tools/configtxgen] doOutputBlock -> INFO 005 Writing genesis block
+ set +x
#################################################################
### Generating channel configuration transaction 'channel.tx' ###
#################################################################
+ configtxgen -profile TwoOrgsChannel -outputCreateChannelTx ./channel-artifacts/channel.tx -channelID mychannel
2018-03-17 21:56:10.328 CST [common/tools/configtxgen] main -> INFO 001 Loading configuration
2018-03-17 21:56:10.339 CST [common/tools/configtxgen] doOutputChannelCreateTx -> INFO 002 Generating new channel configtx
2018-03-17 21:56:10.340 CST [msp] getMspConfig -> INFO 003 Loading NodeOUs
2018-03-17 21:56:10.341 CST [msp] getMspConfig -> INFO 004 Loading NodeOUs
2018-03-17 21:56:10.366 CST [common/tools/configtxgen] doOutputChannelCreateTx -> INFO 005 Writing new channel tx
+ set +x
#################################################################
####### Generating anchor peer update for Org1MSP ##########
#################################################################
+ configtxgen -profile TwoOrgsChannel -outputAnchorPeersUpdate ./channel-artifacts/Org1MSPanchors.tx -channelID mychannel -asOrg Org1MSP
2018-03-17 21:56:10.385 CST [common/tools/configtxgen] main -> INFO 001 Loading configuration
2018-03-17 21:56:10.393 CST [common/tools/configtxgen] doOutputAnchorPeersUpdate -> INFO 002 Generating anchor peer update
2018-03-17 21:56:10.393 CST [common/tools/configtxgen] doOutputAnchorPeersUpdate -> INFO 003 Writing anchor peer update
+ set +x
#################################################################
####### Generating anchor peer update for Org2MSP ##########
#################################################################
+ configtxgen -profile TwoOrgsChannel -outputAnchorPeersUpdate ./channel-artifacts/Org2MSPanchors.tx -channelID mychannel -asOrg Org2MSP
2018-03-17 21:56:10.413 CST [common/tools/configtxgen] main -> INFO 001 Loading configuration
2018-03-17 21:56:10.421 CST [common/tools/configtxgen] doOutputAnchorPeersUpdate -> INFO 002 Generating anchor peer update
2018-03-17 21:56:10.421 CST [common/tools/configtxgen] doOutputAnchorPeersUpdate -> INFO 003 Writing anchor peer update
+ set +x
第一步生成我們各種網(wǎng)絡(luò)實(shí)體的所有證書和密鑰拯勉,genesis block
用于引導(dǎo)排序服務(wù)竟趾,以及配置Channel
所需要的一組交易配置集合。
1.4. 啟動網(wǎng)絡(luò)
接下來宫峦,你可以使用以下命令來啟動整個網(wǎng)絡(luò)岔帽。
./byfn.sh -m up
上面的指令會編譯Golang智能合約鏡像并且啟動對應(yīng)的容器。Go語言是默認(rèn)的鏈碼語言导绷,當(dāng)然這里也支持 Node.js智能合約犀勒。如果你希望以node形式的智能合約完成教程,可以將剛才的指令替換為:
# 使用 -l 標(biāo)志指定智能合約語言
# 不指定默認(rèn)使用Golang
./byfn.sh -m up -l node
點(diǎn)擊 Hyperledger Fabric Shim來查看更多關(guān)于使用node.js 編寫智能合約的API文檔。
再次提示是否繼續(xù)贾费,輸入y或者鍵入回車:
yuyangdeMacBook-Pro:first-network yuyang$ ./byfn.sh -m up
Starting with channel 'mychannel' and CLI timeout of '10' seconds and CLI delay of '3' seconds
Continue? [Y/n] y
proceeding ...
2018-03-17 14:10:17.541 UTC [main] main -> INFO 001 Exiting.....
LOCAL_VERSION=1.1.0-rc1
DOCKER_IMAGE_VERSION=1.1.0-rc1
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 peer1.org2.example.com ... done
Creating cli ... done
Creating peer0.org1.example.com ...
Creating orderer.example.com ...
Creating peer0.org2.example.com ...
Creating peer1.org2.example.com ...
Creating cli ...
____ _____ _ ____ _____
/ ___| |_ _| / \ | _ \ |_ _|
\___ \ | | / _ \ | |_) | | |
___) | | | / ___ \ | _ < | |
|____/ |_| /_/ \_\ |_| \_\ |_|
Build your first network (BYFN) end-to-end test
Channel name : mychannel
Creating channel...
日志將從這里繼續(xù)钦购。然后啟動所有容器,驅(qū)動一個端到端的應(yīng)用場景褂萧。成功以后押桃,在終端窗口中會報(bào)告以下內(nèi)容:
Query Result: 90
2018-03-17 14:11:33.653 UTC [main] main -> INFO 003 Exiting.....
===================== Query on peer1.org2 on channel 'mychannel' is successful =====================
========= All GOOD, BYFN execution completed ===========
_____ _ _ ____
| ____| | \ | | | _ \
| _| | \| | | | | |
| |___ | |\ | | |_| |
|_____| |_| \_| |____/
你可以滾動這些日志去查看各種交易。如果你沒有獲得這個結(jié)果箱玷,請移步疑難解答部分Troubleshooting怨规,看看我們是否可以幫助你發(fā)現(xiàn)問題陌宿。
1.5. 關(guān)閉網(wǎng)絡(luò)
最后锡足,讓我們把它全部停下來,這樣我們可以一步一步地探索網(wǎng)絡(luò)設(shè)置壳坪。以下操作將關(guān)閉你的容器舶得,移除加密材料和4個配置信息,并且從Docker倉庫刪除智能合約鏡像爽蝴。你將再一次被提示是否繼續(xù)沐批,回答y或者鍵入回車:
yuyangdeMacBook-Pro:first-network yuyang$ ./byfn.sh -m down
如果你想了解關(guān)于底層工具和引導(dǎo)材料相關(guān)的更多信息,請繼續(xù)閱讀蝎亚。在接下來的章節(jié)中九孩,我們將瀏覽構(gòu)建功能齊全的Hyperledger fabric網(wǎng)絡(luò)的各種要求和步驟。
在上面的步驟中发框,默認(rèn)的
cli
容器日志輸出等級CORE_LOGGING_LEVEL
是INFO
躺彬。你可以在first-network
目錄中的docker-compose-cli.yaml
文件中進(jìn)行修改。
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
#- CORE_LOGGING_LEVEL=DEBUG
- CORE_LOGGING_LEVEL=INFO
1.6. 加密原理
我們將使用cryptogen
工具為我們生成各種網(wǎng)絡(luò)實(shí)體的加密材料(x509證書)梅惯。這些證書是身份的代表宪拥,它們允許在我們的網(wǎng)絡(luò)實(shí)體進(jìn)行交流和交易時進(jìn)行簽名/驗(yàn)證身份驗(yàn)證。
Fabric中有兩種類型的公私鑰和證書铣减,一種是給節(jié)點(diǎn)之前通訊安全而準(zhǔn)備的TLS證書她君,另一種是用戶登錄和權(quán)限控制的用戶證書。這些證書本來應(yīng)該是由CA來頒發(fā)葫哗,但是我們這里是測試環(huán)境缔刹,并沒有啟用CA節(jié)點(diǎn),所以Fabric幫我們提供了一個工具:cryptogen劣针。
1.6.1. 它是如何工作的校镐?
Cryptogen
使用crypto-config.yaml
,并允許我們?yōu)榻M織和屬于這些組織的組件生成一組證書和密鑰酿秸。每個組織都配置了唯一的根證書(ca-cert)
,它將特定組件(peers和orders)綁定到該組織灭翔。通過為每一個組織分配唯一的CA證書,我們正在模仿一個典型的網(wǎng)絡(luò),這個網(wǎng)絡(luò)中的成員將使用自己的證書頒發(fā)機(jī)構(gòu)肝箱。Hyperledger Fabric中的交易和通信是通過存儲在keystore
中的實(shí)體的私鑰簽名哄褒,然后通過公鑰手段進(jìn)行驗(yàn)證(signcerts
)。
你將注意到在這個文件里有一個count
變量煌张。我們將使用它來指定每個組織中peer
的數(shù)量;在我們的例子中呐赡,每個組織有兩個peer。我們現(xiàn)在不會深入研究x.509證書和公鑰基礎(chǔ)設(shè)施的細(xì)節(jié)骏融。如果你有興趣链嘀,你可以在自己的時間細(xì)讀這些主題。
在運(yùn)行該工具之前档玻,讓我們快速瀏覽一下這段代碼crypto-config.yaml
怀泊。特別注意在OrdererOrgs
頭下的Name,Domain和Specs參數(shù):
OrdererOrgs:
# ---------------------------------------------------------------------------
# Orderer
# ---------------------------------------------------------------------------
- Name: Orderer
Domain: example.com
# ---------------------------------------------------------------------------
# "Specs" - See PeerOrgs below for complete description
# ---------------------------------------------------------------------------
Specs:
- Hostname: orderer
# ---------------------------------------------------------------------------
# "PeerOrgs" - Definition of organizations managing peer nodes
# ---------------------------------------------------------------------------
PeerOrgs:
# ---------------------------------------------------------------------------
# Org1
# ---------------------------------------------------------------------------
- Name: Org1
Domain: org1.example.com
EnableNodeOUs: true
網(wǎng)絡(luò)實(shí)體的命名約定如下:”{{.Hostname}}.{{.Domain}}”误趴。所以使用我們的排序節(jié)點(diǎn)作為參考點(diǎn)霹琼,它與Order
的MSP ID相關(guān)聯(lián)。該文件包含了有關(guān)定義和語法的大量文檔凉当。你還可以參考Membership Service Providers(MSP)枣申,以便更深入地了解MSP。
我們運(yùn)行cryptogen
工具看杭,生成的證書和密鑰將被保存到名為crypto-config
的文件夾中忠藤。
1.7. 配置工作說明
configtxgen tool
用于創(chuàng)建4個配置工作:
order的
genesis block
創(chuàng)世區(qū)塊channel的
channel configuration transaction
以及兩個
anchor peer transactions
一個對應(yīng)一個Peer組織
有關(guān)此工具的完整說明,請參閱Channel Configuration(configtxgen)楼雹。
order block
是一個ordering service的創(chuàng)世區(qū)塊模孩,channel transaction
配置文件在Channel
創(chuàng)建的時侯廣播給order。anchor peer transactions
烘豹,正如名稱所示瓜贾,指定了每個組織在此channel上的錨節(jié)點(diǎn)。
1.7.1. 它是如何工作的携悯?
Configtxgen使用一個包含示例網(wǎng)絡(luò)的configtx.yaml
文件祭芦。有3個成員-一個排序服務(wù)組織OrdererOrg
以及兩個節(jié)點(diǎn)組織(Org1
&Org2
),每個組織管理和持有2個peer節(jié)點(diǎn)。該文件還指定了一個SampleConsortium
的聯(lián)盟憔鬼,由上述2個節(jié)點(diǎn)組織構(gòu)成龟劲。 請?zhí)貏e注意此文件頂部的”Profiles”部分。你會注意到我們有兩個獨(dú)特的標(biāo)題轴或。一個是orderer的創(chuàng)世區(qū)塊-TwoOrgsOrdererGenesis
-另一個是針對channel的TwoOrgsChannel
昌跌。
這些標(biāo)題很重要,因?yàn)樵谖覀儎?chuàng)建我們的工作的時侯它們將作為傳遞的參數(shù)照雁。
注意:請注意我們的
SampleConsortium
在系統(tǒng)級別的配置文件中定義蚕愤,然后由channel級別配置文件引用。
此文件還包含兩個值得注意的附加規(guī)格。首先萍诱,我們?yōu)槊總€組織指定了錨點(diǎn)節(jié)點(diǎn)(peer0.org1.example.com
和peer0.org2.example.com
)悬嗓。其次,我們?yōu)槊總€成員指定MSP文件夾裕坊,用來存儲每個組織在orderer genesis block
中指定的根證書包竹。這是一個關(guān)鍵的概念。現(xiàn)在任意和ordering service通信的網(wǎng)絡(luò)實(shí)體都可以對其數(shù)字簽名進(jìn)行驗(yàn)證籍凝。
這個文件里面配置了由2個Org參與的Orderer共識配置TwoOrgsOrdererGenesis周瞎,以及由2個Org參與的Channel配置:TwoOrgsChannel。Orderer可以設(shè)置共識的算法是Solo還是Kafka饵蒂,以及共識時區(qū)塊大小声诸,超時時間等,我們使用默認(rèn)值即可苹享,不用更改双絮。而Peer節(jié)點(diǎn)的配置包含了MSP的配置,錨節(jié)點(diǎn)的配置得问。如果我們有更多的Org,或者有更多的Channel软免,那么就可以根據(jù)模板進(jìn)行對應(yīng)的修改宫纬。
1.8. 生成公私鑰證書和創(chuàng)世區(qū)塊
你可以用configtxgen
和cryptogen
命令來手動生成證書/密鑰和各種配置文件「嘞簦或者漓骚,你可以嘗試使用byfn.sh
腳本來完成你的目標(biāo)。
1.8.1. 手動生成
必要的話榛泛,你可以參考byfn.sh腳本中的generateCerts
函數(shù)去生成相關(guān)定義在crypto-config.yaml
文件中用于你的網(wǎng)絡(luò)配置的相關(guān)證書蝌蹂。然而,為了方便起見曹锨,我們也將在此提供參考孤个。
首先,我們來運(yùn)行cryptogen
這個工具沛简。我們的二進(jìn)制文件在bin
目錄中齐鲤,所以我們需要提供工具所在的相對路徑。
yuyangdeMacBook-Pro:first-network yuyang$ ../bin/cryptogen generate --config=./crypto-config.yaml
你會看到以下內(nèi)容出現(xiàn)在命令行中:
org1.example.com
org2.example.com
證書和秘鑰(也就是MSP材料)會生成在位于first-network
文件夾下的crypto-config
文件夾中椒楣。
接下來给郊,我們需要告訴configtxgen
工具去哪里獲取configtx.yaml
文件。我們將告訴它在我們當(dāng)前的工作目錄獲取捧灰。
我們需要設(shè)置一個環(huán)境變量來告訴configtxgen
哪里去尋找configtx.yaml
淆九。
yuyangdeMacBook-Pro:first-network yuyang$ export FABRIC_CFG_PATH=$PWD
然后,我們將調(diào)用configtxgen
工具去創(chuàng)建orderer genesis block
:
yuyangdeMacBook-Pro:first-network yuyang$ ../bin/configtxgen -profile TwoOrgsOrdererGenesis -outputBlock ./channel-artifacts/genesis.block
你會看到以下內(nèi)容出現(xiàn)在命令行中:
2018-03-18 12:31:44.111 CST [common/tools/configtxgen] main -> INFO 001 Loading configuration
2018-03-18 12:31:44.123 CST [msp] getMspConfig -> INFO 002 Loading NodeOUs
2018-03-18 12:31:44.123 CST [msp] getMspConfig -> INFO 003 Loading NodeOUs
2018-03-18 12:31:44.123 CST [common/tools/configtxgen] doOutputBlock -> INFO 004 Generating genesis block
2018-03-18 12:31:44.124 CST [common/tools/configtxgen] doOutputBlock -> INFO 005 Writing genesis block
注意:剛才的指令會將生成的文件
genesis.block
放置在當(dāng)前目錄下的channel-artifacts
文件夾中。
1.8.2. 創(chuàng)建channel transaction配置
接下來炭庙,我們需要創(chuàng)建channel transaction
配置跪另。請確保替換$CHANNEL_NAME
或者將CHANNEL_NAME
設(shè)置為整個說明中可以使用的環(huán)境變量:
yuyangdeMacBook-Pro:first-network yuyang$ export CHANNEL_NAME=mychannel && ../bin/configtxgen -profile TwoOrgsChannel -outputCreateChannelTx ./channel-artifacts/channel.tx -channelID $CHANNEL_NAME
你會看到以下內(nèi)容出現(xiàn)在命令行中:
2018-03-18 12:42:33.661 CST [common/tools/configtxgen] main -> INFO 001 Loading configuration
2018-03-18 12:42:33.669 CST [common/tools/configtxgen] doOutputChannelCreateTx -> INFO 002 Generating new channel configtx
2018-03-18 12:42:33.669 CST [msp] getMspConfig -> INFO 003 Loading NodeOUs
2018-03-18 12:42:33.670 CST [msp] getMspConfig -> INFO 004 Loading NodeOUs
2018-03-18 12:42:33.702 CST [common/tools/configtxgen] doOutputChannelCreateTx -> INFO 005 Writing new channel tx
注意:剛才的指令會將生成的文件
channel.tx
放置在當(dāng)前目錄下的channel-artifacts
文件夾中辑奈。
接下來刺下,我們將在正在構(gòu)建的通道上定義Org1
的anchor peer
。請?jiān)俅未_認(rèn)$CHANNEL_NAME已被替換或者為以下命令設(shè)置了環(huán)境變量:
yuyangdeMacBook-Pro:first-network yuyang$ ../bin/configtxgen -profile TwoOrgsChannel -outputAnchorPeersUpdate ./channel-artifacts/Org1MSPanchors.tx -channelID $CHANNEL_NAME -asOrg Org1MSP
現(xiàn)在零渐,我們將在同一個通道定義Org2
的anchor peer
:
yuyangdeMacBook-Pro:first-network yuyang$ ../bin/configtxgen -profile TwoOrgsChannel -outputAnchorPeersUpdate ./channel-artifacts/Org2MSPanchors.tx -channelID $CHANNEL_NAME -asOrg Org2MSP
注意:剛才的指令會將生成的文件
Org1MSPanchors.tx
和Org2MSPanchors.tx
放置在當(dāng)前目錄下的channel-artifacts
文件夾中擦盾。
1.9. 啟動網(wǎng)絡(luò)
我們將利用docker-compose
腳本來啟動我們的區(qū)塊鏈網(wǎng)絡(luò)嘲驾。docker-compose
文件會利用我們之前下載的鏡像,并用以前生成的genesis.block
來引導(dǎo)orderer
迹卢。
我們想手動執(zhí)行命令辽故,以便說明每個調(diào)用的語法和功能。
首先啟動你的網(wǎng)絡(luò):
yuyangdeMacBook-Pro:first-network yuyang$ docker-compose -f docker-compose-cli.yaml up -d
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 peer0.org2.example.com ... done
Creating cli ... done
Creating peer0.org1.example.com ...
Creating peer0.org2.example.com ...
Creating orderer.example.com ...
Creating peer1.org2.example.com ...
Creating cli ...
如果要實(shí)時查看你的區(qū)塊鏈網(wǎng)絡(luò)的日志腐碱,請不要提供-d
標(biāo)志誊垢。如果你需要日志流,你需要打開第二個終端來執(zhí)行CLI命令症见。
CLI容器處于空閑狀態(tài)時只會會停留1000秒喂走。你可以使用以下命令再次啟動它:
docker start cli
1.9.1. 環(huán)境變量
下面是peer0.org1.example.com
的環(huán)境變量。每當(dāng)在CLI命令中需要執(zhí)行節(jié)點(diǎn)操作時谋作,都要確認(rèn)當(dāng)前處于哪個節(jié)點(diǎn)下芋肠。如果要切換至peer0.org1
節(jié)點(diǎn),就需要將其環(huán)境變量復(fù)制到命令行中執(zhí)行遵蚜。同理帖池,如果切換到其他節(jié)點(diǎn),需要對應(yīng)的修改環(huán)境變量吭净。后面會進(jìn)行實(shí)際操作睡汹。
# Environment variables for PEER0
CORE_PEER_MSPCONFIGPATH=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org1.example.com/users/Admin@org1.example.com/msp
CORE_PEER_ADDRESS=peer0.org1.example.com:7051
CORE_PEER_LOCALMSPID="Org1MSP"
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
1.9.2. 創(chuàng)建&加入信道
回憶在之前的1.8.2. 創(chuàng)建channel transaction配置,我們使用configtxgen
工具創(chuàng)建channel transaction配置 寂殉。你可以重復(fù)使用相同或不同的configtx.yaml
文件囚巴,在你的網(wǎng)絡(luò)創(chuàng)建其他的信道。
我們將使用docker exec
命令進(jìn)入CLI容器:
yuyangdeMacBook-Pro:first-network yuyang$ docker exec -it cli bash
如果成功不撑,你將看到下列信息:
root@cfbda07a993d:/opt/gopath/src/github.com/hyperledger/fabric/peer#
我們使用-c
標(biāo)志指定channel的名字文兢,-f
標(biāo)志指定channel配置文件。在這個例子中它是channel.tx
焕檬,當(dāng)然你也可以使用不同的名稱姆坚,掛載你自己的channel配置。再一次实愚,我們將在CLI容器里設(shè)置了CHANNEL_NAME
環(huán)境變量兼呵,所以不需要明確傳遞這個參數(shù)兔辅。
export CHANNEL_NAME=mychannel
# the channel.tx file is mounted in the channel-artifacts directory within your CLI container
# as a result, we pass the full path for the file
# we also pass the path for the orderer ca-cert in order to verify the TLS handshake
# be sure to export or replace the $CHANNEL_NAME variable appropriately
peer channel create -o orderer.example.com:7050 -c $CHANNEL_NAME -f ./channel-artifacts/channel.tx --tls --cafile /opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/ordererOrganizations/example.com/orderers/orderer.example.com/msp/tlscacerts/tlsca.example.com-cert.pem
注意:
-- cafile
會作為命令的一部分。這是orderer的root cert的本地路徑击喂,允許我們?nèi)ヲ?yàn)證TLS握手维苔。
此命令返回一個創(chuàng)世區(qū)塊-<channel-ID.block>
-我們將使用它加入信道。它包含了channel.tx中的配置信息懂昂。如果你沒有修改過channel.tx
文件中默認(rèn)的通道名稱介时,上面的命令會返回mychannel.block
。
2018-03-19 05:15:15.385 UTC [channelCmd] InitCmdFactory -> INFO 001 Endorser and orderer connections initialized
2018-03-19 05:15:15.419 UTC [channelCmd] InitCmdFactory -> INFO 002 Endorser and orderer connections initialized
2018-03-19 05:15:15.624 UTC [main] main -> INFO 003 Exiting.....
注意:這里我的返回信息并沒有區(qū)塊
mychannel.block
凌彬,而是INFO 003 Exiting.....
沸柔,是直接退出了。因?yàn)槲铱吹墓俜轿臋n和網(wǎng)上其他人寫的示例都是返回了區(qū)塊信息铲敛,所以我以為我這里出問題了褐澎,然后想了很多辦法查了很多資料,重來了很多次都不行伐蒋。接著我發(fā)現(xiàn)之前官方寫的腳本byfn.sh
運(yùn)行是沒有問題的工三,所以我試著再次運(yùn)行,發(fā)現(xiàn)它在創(chuàng)建channel的時候也是INFO 003 Exiting.....
先鱼,應(yīng)該是成功了的俭正。如果有朋友有更好的解釋,麻煩留言告知型型,謝謝段审!
另外這里有一個方法可以查看容器啟動后docker-compose -f docker-compose-cli.yaml up -d
的狀態(tài):
yuyangdeMacBook-Pro:first-network yuyang$ docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
45b3f41ae42f hyperledger/fabric-tools:latest "/bin/bash" 20 seconds ago Up 21 seconds cli
26dadcb90749 hyperledger/fabric-peer:latest "peer node start" 22 seconds ago Up 22 seconds 0.0.0.0:7051->7051/tcp, 0.0.0.0:7053->7053/tcp peer0.org1.example.com
053b317fc840 hyperledger/fabric-peer:latest "peer node start" 22 seconds ago Up 22 seconds 0.0.0.0:8051->7051/tcp, 0.0.0.0:8053->7053/tcp peer1.org1.example.com
0622660b60cd hyperledger/fabric-peer:latest "peer node start" 22 seconds ago Up 23 seconds 0.0.0.0:10051->7051/tcp, 0.0.0.0:10053->7053/tcp peer1.org2.example.com
5b6d636ab4ed hyperledger/fabric-peer:latest "peer node start" 22 seconds ago Up 23 seconds 0.0.0.0:9051->7051/tcp, 0.0.0.0:9053->7053/tcp peer0.org2.example.com
9c4da795db8c hyperledger/fabric-orderer:latest "orderer" 22 seconds ago Up 23 seconds 0.0.0.0:7050->7050/tcp orderer.example.com
可以看到1Orderer+4Peer+1CLI都啟動了。
現(xiàn)在讓我們將peer0.org1
加入頻道闹蒜。
# By default, this joins ``peer0.org1.example.com`` only
# the <channel-ID.block> was returned by the previous command
# if you have not modified the channel name, you will join with mychannel.block
# if you have created a different channel name, then pass in the appropriately named block
root@45b3f41ae42f:/opt/gopath/src/github.com/hyperledger/fabric/peer# peer channel join -b mychannel.block
2018-03-19 08:19:55.355 UTC [channelCmd] InitCmdFactory -> INFO 001 Endorser and orderer connections initialized
2018-03-19 08:19:55.477 UTC [channelCmd] executeJoin -> INFO 002 Successfully submitted proposal to join channel
2018-03-19 08:19:55.477 UTC [main] main -> INFO 003 Exiting.....
我們可以通過修改上面提到的四個環(huán)境變量來將其他的節(jié)點(diǎn)加入信道。
加入peer1.org1
:
CORE_PEER_MSPCONFIGPATH=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org1.example.com/users/Admin@org1.example.com/msp CORE_PEER_ADDRESS=peer1.org1.example.com:7051
CORE_PEER_LOCALMSPID="Org1MSP"
CORE_PEER_TLS_ROOTCERT_FILE=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org1.example.com/peers/peer1.org1.example.com/tls/ca.crt
peer channel join -b mychannel.block
加入peer0.org2
:
CORE_PEER_MSPCONFIGPATH=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org2.example.com/users/Admin@org2.example.com/msp
CORE_PEER_ADDRESS=peer0.org2.example.com:7051
CORE_PEER_LOCALMSPID="Org2MSP"
CORE_PEER_TLS_ROOTCERT_FILE=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org2.example.com/peers/peer0.org2.example.com/tls/ca.crt
peer channel join -b mychannel.block
加入peer1.org2
:
CORE_PEER_MSPCONFIGPATH=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org2.example.com/users/Admin@org2.example.com/msp CORE_PEER_ADDRESS=peer1.org2.example.com:7051
CORE_PEER_LOCALMSPID="Org2MSP"
CORE_PEER_TLS_ROOTCERT_FILE=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org2.example.com/peers/peer1.org2.example.com/tls/ca.crt
peer channel join -b mychannel.block
1.9.3. 更新錨節(jié)點(diǎn)
由于我們在剛才的步驟中最后加入的節(jié)點(diǎn)是peer1.org2
抑淫,所以執(zhí)行完成后我們的命令行現(xiàn)在處于peer1.org2
下绷落。而現(xiàn)在我們需要為Org1設(shè)置錨節(jié)點(diǎn)peer0.org1
,所以命令行需要先切回到peer0.org1
:
設(shè)置當(dāng)前操作節(jié)點(diǎn)為peer0.org1
CORE_PEER_LOCALMSPID="Org1MSP"
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
CORE_PEER_ADDRESS=peer0.org1.example.com:7051
然后更新Org1錨節(jié)點(diǎn)為peer0.org1
:
peer channel update -o orderer.example.com:7050 -c $CHANNEL_NAME -f ./channel-artifacts/Org1MSPanchors.tx --tls --cafile /opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/ordererOrganizations/example.com/orderers/orderer.example.com/msp/tlscacerts/tlsca.example.com-cert.pem
2018-03-19 09:00:21.829 UTC [channelCmd] InitCmdFactory -> INFO 001 Endorser and orderer connections initialized
2018-03-19 09:00:21.846 UTC [channelCmd] update -> INFO 002 Successfully submitted channel update
2018-03-19 09:00:21.846 UTC [main] main -> INFO 003 Exiting.....
接下來為Org2設(shè)置錨節(jié)點(diǎn)peer0.org2
設(shè)置當(dāng)前操作節(jié)點(diǎn)為peer0.org2
CORE_PEER_LOCALMSPID="Org2MSP"
CORE_PEER_TLS_ROOTCERT_FILE=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org2.example.com/peers/peer0.org2.example.com/tls/ca.crt
CORE_PEER_MSPCONFIGPATH=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org2.example.com/users/Admin@org2.example.com/msp
CORE_PEER_ADDRESS=peer0.org2.example.com:7051
然后更新Org2錨節(jié)點(diǎn)為peer0.org2
:
peer channel update -o orderer.example.com:7050 -c $CHANNEL_NAME -f ./channel-artifacts/Org2MSPanchors.tx --tls --cafile /opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/ordererOrganizations/example.com/orderers/orderer.example.com/msp/tlscacerts/tlsca.example.com-cert.pem
2018-03-19 09:05:58.149 UTC [channelCmd] InitCmdFactory -> INFO 001 Endorser and orderer connections initialized
2018-03-19 09:05:58.164 UTC [channelCmd] update -> INFO 002 Successfully submitted channel update
2018-03-19 09:05:58.164 UTC [main] main -> INFO 003 Exiting.....
1.9.4. 安裝和實(shí)例化鏈碼
我們將利用一個現(xiàn)有的簡單鏈碼始苇。要學(xué)習(xí)如何編寫自己的鏈碼砌烁,請參考鏈碼服務(wù)開發(fā)指南
應(yīng)用程序和區(qū)塊鏈賬本會通過chaincode相互影響。因此催式,我們需要在每個會執(zhí)行以及背書我們交易的peer節(jié)點(diǎn)安裝chaincode函喉,然后在Channel上實(shí)例化chaincode。
首先荣月,將Go或者Node.js示例代碼安裝到4個peer節(jié)點(diǎn)中的其中一個管呵。如果其他的節(jié)點(diǎn)也要安裝,需要執(zhí)行4此哺窄。這個命令將源代碼放到peer節(jié)點(diǎn)的文件系統(tǒng)中捐下。
你可以在每個節(jié)點(diǎn)上安裝任意一種語言的鏈碼账锹。并在稍后指定語言進(jìn)行初始化。
Golang
# this installs the Go chaincode
peer chaincode install -n mycc -v 1.0 -p github.com/chaincode/chaincode_example02/go/
Node.js
# this installs the Node.js chaincode
# make note of the -l flag; we use this to specify the language
peer chaincode install -n mycc -v 1.0 -l node -p /opt/gopath/src/github.com/chaincode/chaincode_example02/node/
我們先切換到peer0.org1這個節(jié)點(diǎn):
CORE_PEER_LOCALMSPID="Org1MSP"
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
CORE_PEER_ADDRESS=peer0.org1.example.com:7051
安裝指定的ChainCode并對其命名:
peer chaincode install -n mycc -v 1.0 -p github.com/chaincode/chaincode_example02/go/
2018-03-19 10:32:51.352 UTC [chaincodeCmd] checkChaincodeCmdParams -> INFO 001 Using default escc
2018-03-19 10:32:51.352 UTC [chaincodeCmd] checkChaincodeCmdParams -> INFO 002 Using default vscc
2018-03-19 10:32:51.532 UTC [main] main -> INFO 003 Exiting.....
安裝的過程其實(shí)就是對CLI中指定的代碼進(jìn)行編譯打包坷襟,并把打包好的文件發(fā)送到Peer奸柬,等待接下來的實(shí)例化。
接下來婴程,在channel上實(shí)例化chaincode廓奕。這將初始化channel上的鏈碼,設(shè)置鏈碼的背書策略档叔,為目標(biāo)peer節(jié)點(diǎn)啟動一個chaincode容器桌粉。注意-P
參數(shù)。這是我們需要指定的當(dāng)這個chaincode的交易需要被驗(yàn)證的時侯的背書策略蹲蒲。
在下面的命令中番甩,你會注意到我們指定-P "OR ('Org0MSP.member','Org1MSP.member')"
作為背書策略。這意味著我們需要Org1或者Org2組織中的其中一個的節(jié)點(diǎn)的背書即可(即只有一個背書)届搁。如果我們改變語法為AND
那么我們就需要2個背書者缘薛。
有關(guān)更多背書策略的詳細(xì)信息請參考背書策略。
Golang
# be sure to replace the $CHANNEL_NAME environment variable if you have not exported it
# if you did not install your chaincode with a name of mycc, then modify that argument as well
peer chaincode instantiate -o orderer.example.com:7050 --tls --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 $CHANNEL_NAME -n mycc -v 1.0 -c '{"Args":["init","a", "100", "b","200"]}' -P "OR ('Org1MSP.peer','Org2MSP.peer')"
Node.js
# be sure to replace the $CHANNEL_NAME environment variable if you have not exported it
# if you did not install your chaincode with a name of mycc, then modify that argument as well
# notice that we must pass the -l flag after the chaincode name to identify the language
peer chaincode instantiate -o orderer.example.com:7050 --tls --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 $CHANNEL_NAME -n mycc -l node -v 1.0 -c '{"Args":["init","a", "100", "b","200"]}' -P "OR ('Org1MSP.peer','Org2MSP.peer')"
初始化鏈碼:
2018-03-19 10:57:13.838 UTC [chaincodeCmd] checkChaincodeCmdParams -> INFO 001 Using default escc
2018-03-19 10:57:13.838 UTC [chaincodeCmd] checkChaincodeCmdParams -> INFO 002 Using default vscc
2018-03-19 10:57:24.179 UTC [main] main -> INFO 003 Exiting.....
可以使用以下命令查看peer0.org1日志:
docker logs -f peer0.org1.example.com
2018-03-19 10:57:13.847 UTC [golang-platform] GenerateDockerBuild -> INFO 036 building chaincode with ldflagsOpt: '-ldflags "-linkmode external -extldflags '-static'"'
2018-03-19 10:57:13.847 UTC [golang-platform] GenerateDockerBuild -> INFO 037 building chaincode with tags:
2018-03-19 10:57:26.196 UTC [cceventmgmt] HandleStateUpdates -> INFO 038 Channel [mychannel]: Handling LSCC state update for chaincode [mycc]
2018-03-19 10:57:26.202 UTC [kvledger] CommitWithPvtData -> INFO 039 Channel [mychannel]: Committed block [3] with 1 transaction(s)
使用docker ps
命令可以發(fā)現(xiàn)新的容器dev-peer0.org1.example.com-mycc-1.0
:
yuyangdeMacBook-Pro:first-network yuyang$ docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
d2fbe3a12558 dev-peer0.org1.example.com-mycc-1.0-384f11f484b9302df90b453200cfb25174305fce8f53f4e94d45ee3b6cab0ce9 "chaincode -peer.add…" 3 minutes ago Up 3 minutes dev-peer0.org1.example.com-mycc-1.0
45b3f41ae42f hyperledger/fabric-tools:latest "/bin/bash" 3 hours ago Up 3 hours cli
26dadcb90749 hyperledger/fabric-peer:latest "peer node start" 3 hours ago Up 3 hours 0.0.0.0:7051->7051/tcp, 0.0.0.0:7053->7053/tcp peer0.org1.example.com
053b317fc840 hyperledger/fabric-peer:latest "peer node start" 3 hours ago Up 3 hours 0.0.0.0:8051->7051/tcp, 0.0.0.0:8053->7053/tcp peer1.org1.example.com
0622660b60cd hyperledger/fabric-peer:latest "peer node start" 3 hours ago Up 3 hours 0.0.0.0:10051->7051/tcp, 0.0.0.0:10053->7053/tcp peer1.org2.example.com
5b6d636ab4ed hyperledger/fabric-peer:latest "peer node start" 3 hours ago Up 3 hours 0.0.0.0:9051->7051/tcp, 0.0.0.0:9053->7053/tcp peer0.org2.example.com
9c4da795db8c hyperledger/fabric-orderer:latest "orderer" 3 hours ago Up 3 hours 0.0.0.0:7050->7050/tcp orderer.example.com
使用node初始化鏈碼會慢點(diǎn)卡睦,因?yàn)闀热グ惭b相關(guān)鏡像宴胧。不過一旦在channel初始化過后,我們不再需要
-l
指定語言表锻,只要告訴channel對應(yīng)鏈碼的名稱即可恕齐。
實(shí)例化鏈上代碼主要是在Peer所在的機(jī)器上對前面安裝好的鏈上代碼進(jìn)行包裝,生成對應(yīng)Channel的Docker鏡像和Docker容器瞬逊。并且在實(shí)例化時我們可以指定背書策略显歧。
1.9.5. 查詢
讓我們查詢一下a
的值,以確保鏈碼被正確實(shí)例化确镊,state DB
被填充士骤。查詢的語法如下:
# be sure to set the -C and -n flags appropriately
peer chaincode query -C $CHANNEL_NAME -n mycc -c '{"Args":["query","a"]}'
2018-03-19 13:05:36.337 UTC [chaincodeCmd] checkChaincodeCmdParams -> INFO 001 Using default escc
2018-03-19 13:05:36.337 UTC [chaincodeCmd] checkChaincodeCmdParams -> INFO 002 Using default vscc
Query Result: 100
2018-03-19 13:05:36.342 UTC [main] main -> INFO 003 Exiting.....
1.9.6. 發(fā)起交易
現(xiàn)在讓我們從a
賬戶轉(zhuǎn)10
到b
賬戶。這個交易將創(chuàng)建一個新的區(qū)塊并更新state DB
蕾域。調(diào)用語法如下:
# be sure to set the -C and -n flags appropriately
peer chaincode invoke -o orderer.example.com:7050 --tls --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 $CHANNEL_NAME -n mycc -c '{"Args":["invoke","a","b","10"]}'
2018-03-19 13:08:24.534 UTC [chaincodeCmd] checkChaincodeCmdParams -> INFO 001 Using default escc
2018-03-19 13:08:24.534 UTC [chaincodeCmd] checkChaincodeCmdParams -> INFO 002 Using default vscc
2018-03-19 13:08:24.540 UTC [chaincodeCmd] chaincodeInvokeOrQuery -> INFO 003 Chaincode invoke successful. result: status:200
2018-03-19 13:08:24.541 UTC [main] main -> INFO 004 Exiting.....
1.9.7. 查詢
讓我們確認(rèn)下我們之前的調(diào)用被正確地執(zhí)行了拷肌。我們初始化了a
的值為100
,在上一次調(diào)用的時侯轉(zhuǎn)移了10
給b
旨巷。因此巨缘,查詢a
應(yīng)該展示90
。查詢的語法如下:
# be sure to set the -C and -n flags appropriately
peer chaincode query -C $CHANNEL_NAME -n mycc -c '{"Args":["query","a"]}'
2018-03-19 13:11:16.917 UTC [chaincodeCmd] checkChaincodeCmdParams -> INFO 001 Using default escc
2018-03-19 13:11:16.917 UTC [chaincodeCmd] checkChaincodeCmdParams -> INFO 002 Using default vscc
Query Result: 90
2018-03-19 13:11:16.923 UTC [main] main -> INFO 003 Exiting.....
1.9.8. 在另一個節(jié)點(diǎn)上查詢
前面的操作都是在org1
下面做的采呐,那么處于同一個區(qū)塊鏈(同一個Channel下)的org2
若锁,是否會看到org1
的更改呢?我們試著給peer0.org2
安裝鏈上代碼:
先切換到peer0.org2
節(jié)點(diǎn):
CORE_PEER_LOCALMSPID="Org2MSP"
CORE_PEER_TLS_ROOTCERT_FILE=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org2.example.com/peers/peer0.org2.example.com/tls/ca.crt
CORE_PEER_MSPCONFIGPATH=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org2.example.com/users/Admin@org2.example.com/msp
CORE_PEER_ADDRESS=peer0.org2.example.com:7051
安裝鏈碼:
peer chaincode install -n mycc -v 1.0 -p github.com/chaincode/chaincode_example02/go/
2018-03-19 13:16:41.437 UTC [chaincodeCmd] checkChaincodeCmdParams -> INFO 001 Using default escc
2018-03-19 13:16:41.437 UTC [chaincodeCmd] checkChaincodeCmdParams -> INFO 002 Using default vscc
2018-03-19 13:16:41.621 UTC [main] main -> INFO 003 Exiting.....
由于mycc
已經(jīng)在前面org1
的時候?qū)嵗诵竿颍簿褪钦f對應(yīng)的區(qū)塊已經(jīng)生成了拴清,所以在org2
不能再次初始化靶病。我們直接運(yùn)行查詢命令:
peer chaincode query -C $CHANNEL_NAME -n mycc -c '{"Args":["query","a"]}'
2018-03-19 13:18:57.513 UTC [chaincodeCmd] checkChaincodeCmdParams -> INFO 001 Using default escc
2018-03-19 13:18:57.513 UTC [chaincodeCmd] checkChaincodeCmdParams -> INFO 002 Using default vscc
Query Result: 90
2018-03-19 13:19:07.488 UTC [main] main -> INFO 003 Exiting.....
可以看到依然可以進(jìn)行查詢,且值都是同步的口予。
這里稍微比之前的查詢花費(fèi)的時間久點(diǎn)娄周,這是因?yàn)?code>peer0.org2也需要生成Docker鏡像,創(chuàng)建對應(yīng)的容器沪停,才能通過容器返回結(jié)果煤辨。我們回到終端,執(zhí)行docker ps木张,可以看到又多了一個容器:
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
927a7a89671d dev-peer0.org2.example.com-mycc-1.0-15b571b3ce849066b7ec74497da3b27e54e0df1345daff3951b94245ce09c42b "chaincode -peer.add…" 2 minutes ago Up 2 minutes dev-peer0.org2.example.com-mycc-1.0
d2fbe3a12558 dev-peer0.org1.example.com-mycc-1.0-384f11f484b9302df90b453200cfb25174305fce8f53f4e94d45ee3b6cab0ce9 "chaincode -peer.add…" 2 hours ago Up 2 hours dev-peer0.org1.example.com-mycc-1.0
45b3f41ae42f hyperledger/fabric-tools:latest "/bin/bash" 5 hours ago Up 5 hours cli
26dadcb90749 hyperledger/fabric-peer:latest "peer node start" 5 hours ago Up 5 hours 0.0.0.0:7051->7051/tcp, 0.0.0.0:7053->7053/tcp peer0.org1.example.com
053b317fc840 hyperledger/fabric-peer:latest "peer node start" 5 hours ago Up 5 hours 0.0.0.0:8051->7051/tcp, 0.0.0.0:8053->7053/tcp peer1.org1.example.com
0622660b60cd hyperledger/fabric-peer:latest "peer node start" 5 hours ago Up 5 hours 0.0.0.0:10051->7051/tcp, 0.0.0.0:10053->7053/tcp peer1.org2.example.com
5b6d636ab4ed hyperledger/fabric-peer:latest "peer node start" 5 hours ago Up 5 hours 0.0.0.0:9051->7051/tcp, 0.0.0.0:9053->7053/tcp peer0.org2.example.com
9c4da795db8c hyperledger/fabric-orderer:latest "orderer" 5 hours ago Up 5 hours 0.0.0.0:7050->7050/tcp orderer.example.com
1.9.9. 幕后發(fā)生了什么?
script.sh
腳本被拷貝到CLI容器中众辨。這個腳本驅(qū)動了使用提供的channel name
以及信道配置的channel.tx
文件的createChannel
命令。createChannel
命令的產(chǎn)出是一個創(chuàng)世區(qū)塊-<your_channel_name>.block
-這個創(chuàng)世區(qū)塊被存儲在peer
節(jié)點(diǎn)的文件系統(tǒng)中同時包含了在channel.tx
的信道配置舷礼。joinChannel
命令被4個peer
節(jié)點(diǎn)執(zhí)行鹃彻,作為之前產(chǎn)生的genesis block
的輸入。這個命令介紹了peer
節(jié)點(diǎn)加入<your_channel_name>
以及利用<your_channel_name>.block
去創(chuàng)建一條鏈妻献。現(xiàn)在我們有了由4個
peer
節(jié)點(diǎn)以及2個組織構(gòu)成的信道蛛株。這是我們的TwoOrgsChannel
配置文件。peer0.org1.example.com
和peer1.org1.example.com
屬于Org1;peer0.org2.example.com
和peer1.org2.example.com
屬于Org2育拨。這些關(guān)系是通過
crypto-config.yaml
定義的谨履,MSP路徑在docker-compose文件中被指定。Org1MSP(
peer0.org1.example.com
)和Org2MSP(peer0.org2.example.com
)的anchor peers將在后續(xù)被更新熬丧。我們通過攜帶channel的名字傳遞Org1MSPanchors.tx
和Org2MSPanchors.tx
配置到排序服務(wù)來實(shí)現(xiàn)anchor peer的更新笋粟。一個鏈碼-
chaincode_example02
被安裝在peer0.org1.example.com。這個鏈碼在
peer0.org1.example.com
被實(shí)例化析蝴。實(shí)例化過程將鏈碼添加到信道上害捕,并啟動peer節(jié)點(diǎn)對應(yīng)的容器,并且初始化和鏈碼服務(wù)有關(guān)的鍵值對闷畸。示例的初始化的值是[”a“,”100“吨艇,”b“,”200“]腾啥。實(shí)例化的結(jié)果是一個名為dev-peer0.org1.example.com-mycc-1.0
的容器啟動了。實(shí)例化過程同樣為背書策略傳遞相關(guān)參數(shù)冯吓。策略被定義為-P "OR ('Org1MSP.member','Org2MSP.member')"倘待,意思是任何交易必須被Org1或者Org2背書。
一個針對
a
的查詢發(fā)往peer0.org1.example.com组贺。鏈碼服務(wù)已經(jīng)被安裝在了peer0.org1.example.com凸舵。查詢的結(jié)果也將被返回。沒有寫操作出現(xiàn)失尖,因此查詢的結(jié)果的值將為100啊奄。一次交易被發(fā)往peer0.org1.example.com渐苏,從a轉(zhuǎn)移10到b。
一個查詢請求被發(fā)往
peer0.org1.example.com
用于查詢a的值菇夸。返回a的值為90,正確地反映了之前的交易琼富,a的值被轉(zhuǎn)移了10。在
peer0.org2.example.com
安裝鏈碼庄新,用于查詢a的值鞠眉。一個名為dev-peer0.org2.example.com-mycc-1.0
的容器啟動了。返回a的值為90,正確地反映了之前的交易择诈,a的值被轉(zhuǎn)移了10械蹋。
1.9.10. 這指明了什么?
為了能夠正確地在賬本上進(jìn)行讀寫操作羞芍,鏈碼服務(wù)必須被安裝在peer節(jié)點(diǎn)上哗戈。此外,每個peer節(jié)點(diǎn)的鏈碼服務(wù)的容器除了init
或者傳統(tǒng)的交易-讀/寫-針對該鏈碼服務(wù)執(zhí)行(例如查詢a的值)荷科,在其他情況下不會啟動唯咬。交易導(dǎo)致容器的啟動。當(dāng)然步做,所有信道中的節(jié)點(diǎn)都持有以塊的形式順序存儲的不可變的賬本精確的備份副渴,以及狀態(tài)數(shù)據(jù)庫來保存前狀態(tài)的快照。這包括了沒有在其上安裝鏈碼服務(wù)的peer節(jié)點(diǎn)(例如peer1.org1.example.com
和peer1.org2.example.com
)全度。最后煮剧,鏈碼在被安裝后將是可達(dá)狀態(tài),因?yàn)樗呀?jīng)被實(shí)例化了(例如peer0.org2.example.com
)将鸵。
1.9.11. 我如何查詢這些交易勉盅?
檢查CLI容器的日志。
docker logs -f cli
你應(yīng)該看到以下輸出:
2017-05-16 17:08:01.366 UTC [msp] GetLocalMSP -> DEBU 004 Returning existing local MSP
2017-05-16 17:08:01.366 UTC [msp] GetDefaultSigningIdentity -> DEBU 005 Obtaining default signing identity
2017-05-16 17:08:01.366 UTC [msp/identity] Sign -> DEBU 006 Sign: plaintext: 0AB1070A6708031A0C08F1E3ECC80510...6D7963631A0A0A0571756572790A0161
2017-05-16 17:08:01.367 UTC [msp/identity] Sign -> DEBU 007 Sign: digest: E61DB37F4E8B0D32C9FE10E3936BA9B8CD278FAA1F3320B08712164248285C54
Query Result: 90
2017-05-16 17:08:15.158 UTC [main] main -> INFO 008 Exiting.....
===================== Query on peer1.org2 on channel 'mychannel' is successful =====================
===================== All GOOD, BYFN execution completed =====================
_____ _ _ ____
| ____| | \ | | | _ \
| _| | \| | | | | |
| |___ | |\ | | |_| |
|_____| |_| \_| |____/
你可以滾動這些日志來查看各種交易顶掉。
1.9.12. 我如何查看鏈碼日志草娜?
檢查每個獨(dú)立的鏈碼服務(wù)容器來查看每個容器內(nèi)的分隔的交易。下面是每個鏈碼服務(wù)容器的日志的組合:
$ docker logs dev-peer0.org2.example.com-mycc-1.0
04:30:45.947 [BCCSP_FACTORY] DEBU : Initialize BCCSP [SW]
ex02 Init
Aval = 100, Bval = 200
$ docker logs dev-peer0.org1.example.com-mycc-1.0
04:31:10.569 [BCCSP_FACTORY] DEBU : Initialize BCCSP [SW]
ex02 Invoke
Query Response:{"Name":"a","Amount":"100"}
ex02 Invoke
Aval = 90, Bval = 210
$ docker logs dev-peer1.org2.example.com-mycc-1.0
04:31:30.420 [BCCSP_FACTORY] DEBU : Initialize BCCSP [SW]
ex02 Invoke
Query Response:{"Name":"a","Amount":"90"}
1.10. 了解 Docker Compose 技術(shù)
BYFN示例給我們提供了兩種風(fēng)格的Docker Compose文件痒筒,它們都繼承自docker-compose-base.yaml
(base
目錄下)宰闰。我們的第一種類型,docker-compose-cli.yaml
給我們提供了一個CLI容器簿透,以及一個orderer容器移袍,四個peer容器。
注意:本節(jié)的剩余部分涵蓋了為SDK設(shè)計(jì)的docker-compose文件老充。有關(guān)運(yùn)行這些測試的詳細(xì)信息葡盗,請參閱Node SDK倉庫。
第二種風(fēng)格是docker-compose-e2e.yaml
啡浊,被構(gòu)造為使用Node.js SDK來運(yùn)行端到端測試觅够。除了SDK的功能之外胶背,它主要的區(qū)別在于它有運(yùn)行fabric-ca服務(wù)的容器。因此喘先,我們能夠向組織的CA節(jié)點(diǎn)發(fā)送REST的請求用于注冊和登記钳吟。
如果你在沒有運(yùn)行byfn.sh
腳本的情況下,想使用docker-compose-e2e.yaml
苹祟,我們需要進(jìn)行4個輕微的修改砸抛。我們需要指出本組織CA的私鑰。你可以在crypto-config
文件夾中找到這些值树枫。舉個例子直焙,為了定位Org1的私鑰,我們將使用crypto-config/peerOrganizations/org1.example.com/ca/
砂轻。Org2的路徑為crypto-config/peerOrganizations/org2.example.com/ca/
奔誓。
在docker-compose-e2e.yaml
里為ca0和ca1更新FABRIC_CA_SERVER_TLS_KEYFILE變量。你同樣需要編輯command中去啟動ca server的路徑搔涝。你為每個CA容器提供了2次同樣的私鑰厨喂。
1.11. 使用CouchDB
狀態(tài)數(shù)據(jù)庫可以從默認(rèn)的goleveldb
切換到CouchDB
。鏈碼功能同樣能使用CouchDB
庄呈。但是蜕煌,CouchDB
提供了額外的能力,可以根據(jù)JSON形式的鏈碼服務(wù)數(shù)據(jù)诬留,提供更加豐富以及復(fù)雜的查詢斜纪。
使用CouchDB代替默認(rèn)的數(shù)據(jù)庫(goleveldb),除了在啟動網(wǎng)絡(luò)的時侯傳遞docker-compose-couch.yaml
之外文兑,請遵循前面提到的生成配置文件的過程:
使用CouchDB啟動網(wǎng)絡(luò):
docker-compose -f docker-compose-cli.yaml -f docker-compose-couch.yaml up -d
Creating couchdb0 ... done
Creating couchdb3 ... done
Creating couchdb2 ... done
Creating couchdb1 ... done
aml -f docker-compose-couch.yaml up -d
Starting orderer.example.com ...
Creating couchdb3 ...
Creating couchdb2 ...
Creating couchdb0 ...
Starting orderer.example.com ... done
Recreating peer0.org1.example.com ...
Recreating peer1.org2.example.com ...
Recreating peer0.org2.example.com ... done
Recreating peer1.org1.example.com ... done
Recreating cli ... done
注意:如果你選擇將fabric-couchdb容器端口映射到主機(jī)端口盒刚,請確保你意識到了安全性的影響。在開發(fā)環(huán)境中映射端口可以使CouchDB REST API可用绿贞,并允許通過CouchDB Web界面(Fauxton)對數(shù)據(jù)庫進(jìn)行可視化因块。生產(chǎn)環(huán)境將避免端口映射,以限制對CouchDB容器的外部訪問籍铁。
你可以使用上面列出的步驟使用CouchDB來執(zhí)行chaincode_example02涡上,然而為了執(zhí)行CouchDB的查詢能力,你將需要使用被格式化為JSON的數(shù)據(jù)(例如marbles02)拒名。你可以在fabric/examples/chaincode/go
目錄中找到marbles02
鏈碼吓懈。
使用docker ps
查看容器,可以看到除了1Orderer+4Peer+1CLI啟動外靡狞,還啟動了四個couchdb
:
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
608e57b03072 hyperledger/fabric-tools:latest "/bin/bash" 14 minutes ago Up 14 minutes cli
2de36bd8f69a hyperledger/fabric-peer:latest "peer node start" 14 minutes ago Up 14 minutes 0.0.0.0:8051->7051/tcp, 0.0.0.0:8053->7053/tcp peer1.org1.example.com
4f849ff5a190 hyperledger/fabric-peer:latest "peer node start" 14 minutes ago Up 14 minutes 0.0.0.0:9051->7051/tcp, 0.0.0.0:9053->7053/tcp peer0.org2.example.com
de8fac9c70ab hyperledger/fabric-peer:latest "peer node start" 14 minutes ago Up 14 minutes 0.0.0.0:10051->7051/tcp, 0.0.0.0:10053->7053/tcp peer1.org2.example.com
92928b49f85f hyperledger/fabric-peer:latest "peer node start" 14 minutes ago Up 14 minutes 0.0.0.0:7051->7051/tcp, 0.0.0.0:7053->7053/tcp peer0.org1.example.com
cb9dd19c38a3 hyperledger/fabric-couchdb "tini -- /docker-ent…" 14 minutes ago Up 14 minutes 4369/tcp, 9100/tcp, 0.0.0.0:6984->5984/tcp couchdb1
c34ca64ffd3e hyperledger/fabric-couchdb "tini -- /docker-ent…" 14 minutes ago Up 14 minutes 4369/tcp, 9100/tcp, 0.0.0.0:8984->5984/tcp couchdb3
8a6b82e9b7a4 hyperledger/fabric-couchdb "tini -- /docker-ent…" 14 minutes ago Up 14 minutes 4369/tcp, 9100/tcp, 0.0.0.0:7984->5984/tcp couchdb2
03c634c23010 hyperledger/fabric-couchdb "tini -- /docker-ent…" 14 minutes ago Up 14 minutes 4369/tcp, 9100/tcp, 0.0.0.0:5984->5984/tcp couchdb0
9c4da795db8c hyperledger/fabric-orderer:latest "orderer" 21 hours ago Up 14 minutes 0.0.0.0:7050->7050/tcp orderer.example.com
進(jìn)入CLI容器:
yuyangdeMacBook-Pro:first-network yuyang$ docker exec -it cli bash
切換節(jié)點(diǎn)到peer0.org1
:
CORE_PEER_LOCALMSPID="Org1MSP"
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
CORE_PEER_ADDRESS=peer0.org1.example.com:7051
安裝marbles02
鏈碼:
peer chaincode install -n marbles -v 1.0 -p github.com/chaincode/marbles02/go
設(shè)置下channel變量:
export CHANNEL_NAME=mychannel
實(shí)例化鏈碼:
peer chaincode instantiate -o orderer.example.com:7050 --tls --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 $CHANNEL_NAME -n marbles -v 1.0 -c '{"Args":["init"]}' -P "OR ('Org0MSP.peer','Org1MSP.peer')"
2018-03-20 05:11:55.424 UTC [chaincodeCmd] checkChaincodeCmdParams -> INFO 001 Using default escc
2018-03-20 05:11:55.424 UTC [chaincodeCmd] checkChaincodeCmdParams -> INFO 002 Using default vscc
2018-03-20 05:12:06.480 UTC [main] main -> INFO 003 Exiting.....
再次查看容器,發(fā)現(xiàn)一個新的docker產(chǎn)生了:
dev-peer0.org1.example.com-marbles-1.0
對數(shù)據(jù)進(jìn)行增刪改查:
peer chaincode invoke -o orderer.example.com:7050 --tls --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 $CHANNEL_NAME -n marbles -c '{"Args":["initMarble","marble1","blue","35","tom"]}'
peer chaincode invoke -o orderer.example.com:7050 --tls --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 $CHANNEL_NAME -n marbles -c '{"Args":["initMarble","marble2","red","50","tom"]}'
peer chaincode invoke -o orderer.example.com:7050 --tls --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 $CHANNEL_NAME -n marbles -c '{"Args":["initMarble","marble3","blue","70","tom"]}'
peer chaincode invoke -o orderer.example.com:7050 --tls --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 $CHANNEL_NAME -n marbles -c '{"Args":["transferMarble","marble2","jerry"]}'
peer chaincode invoke -o orderer.example.com:7050 --tls --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 $CHANNEL_NAME -n marbles -c '{"Args":["transferMarblesBasedOnColor","blue","jerry"]}'
peer chaincode invoke -o orderer.example.com:7050 --tls --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 $CHANNEL_NAME -n marbles -c '{"Args":["delete","marble1"]}'
如果你選擇在docker-compose文件中映射你的CouchDB的端口隔嫡,那么你可以通過CouchDB Web界面(Fauxton)通過打開瀏覽器輸入下列URL:http://localhost:5984/_utils查看數(shù)據(jù)的變化甸怕。
你可以CLI中運(yùn)行常規(guī)的查詢(例如讀取marble2):
peer chaincode query -C $CHANNEL_NAME -n marbles -c '{"Args":["readMarble","marble2"]}'
marble2的輸出應(yīng)該顯示為如下:
Query Result: {"color":"red","docType":"marble","name":"marble2","owner":"jerry","size":50}
你可以檢索特定marble的歷史記錄-例如marble1:
peer chaincode query -C $CHANNEL_NAME -n marbles -c '{"Args":["getHistoryForMarble","marble1"]}'
輸出應(yīng)該在marble1的記錄:
Query Result: [{"TxId":"c2b0db43718f40c0d787ebfe298663c4db38257271fba851629aa12fda2d9c71", "Value":{"docType":"marble","name":"marble1","color":"blue","size":35,"owner":"tom"}, "Timestamp":"2018-03-20 05:30:40.843542497 +0000 UTC", "IsDelete":"false"},{"TxId":"ea869117344ca23a3ee2f768a26added28eb23f46e66a54e3e750224fda6caea", "Value":{"docType":"marble","name":"marble1","color":"blue","size":35,"owner":"jerry"}, "Timestamp":"2018-03-20 05:34:14.029638632 +0000 UTC", "IsDelete":"false"},{"TxId":"93242722cfb605a46df083ad3111b34415624d07b3234963dcd58ca47ebd87ef", "Value":null, "Timestamp":"2018-03-20 05:35:48.618124625 +0000 UTC", "IsDelete":"true"}]
你還可以對數(shù)據(jù)內(nèi)容執(zhí)行豐富的查詢甘穿,例如通過擁有者jerry
查詢marble:
peer chaincode query -C $CHANNEL_NAME -n marbles -c '{"Args":["queryMarblesByOwner","jerry"]}'
輸出應(yīng)該顯示2個屬于jerry
的marble:
Query Result: [{"Key":"marble2", "Record":{"color":"red","docType":"marble","name":"marble2","owner":"jerry","size":50}},{"Key":"marble3", "Record":{"color":"blue","docType":"marble","name":"marble3","owner":"jerry","size":70}}]
1.12. 為何使用CouchDB
CouchDB is a kind of NoSQL solution. It is a document oriented database where document fields are stored as key-value mpas. Fields can be either a simple key/value pair, list, or map. In addition to keyed/composite-key/key-range queries which are supported by LevelDB, CouchDB also supports full data rich queries capability, such as non-key queries against the whole blockchain data, since its data content is stored in JSON format and fully queryable. Therefore, CouchDB can meet chaincode, auditing, reporting requirements for many use cases that not supported by LevelDB.
CouchDB can also enhance the security for compliance and data protection in the blockchain. As it is able to implement field-level security through the filtering and masking of individual attributes within a transaction, and only authorizing the read-only permission if needed.
In addition, CouchDB falls into the AP-type (Availability and Partition Tolerance) of the CAP theorem. It uses a master-master replication model with Eventual Consistency
. More information can be found on the Eventual Consistency page of the CouchDB documentation. However, under each fabric peer, there is no database replicas, writes to database are guaranteed consistent and durable (not Eventual Consistency
).
CouchDB is the first external pluggable state database for Fabric, and there could and should be other external database options. For example, IBM enables the relational database for its blockchain. And the CP-type (Consistency and Partition Tolerance) databases may also in need, so as to enable data consistency without application level guarantee.
怕翻譯的不準(zhǔn)確,誤人子弟梢杭。下面的內(nèi)容是我在其他地方摘取的温兼,可以了解一下:
狀態(tài)數(shù)據(jù)庫包括LevelDB和CouchDB。LevelDB是嵌入在peer進(jìn)程中的默認(rèn)鍵/值狀態(tài)數(shù)據(jù)庫武契,CouchDB是一個可選的外部狀態(tài)數(shù)據(jù)庫募判。與LevelDB鍵/值存儲一樣,CouchDB可以存儲任何以chaincode建模的二進(jìn)制數(shù)據(jù)(CouchDB附件函數(shù)在內(nèi)部用于非json二進(jìn)制數(shù)據(jù))咒唆。但是届垫,當(dāng)chaincode值(例如,資產(chǎn))被建模為JSON數(shù)據(jù)時全释,作為JSON文檔存儲装处,CouchDB支持對chaincode數(shù)據(jù)進(jìn)行豐富的查詢。
LevelDB和CouchDB都支持核心chaincode操作浸船,例如獲取和設(shè)置一個鍵(資產(chǎn))妄迁,并根據(jù)鍵進(jìn)行查詢。鍵可以通過范圍查詢李命,可以對組合鍵進(jìn)行建模登淘,以支持針對多個參數(shù)的等價查詢。例如封字,作為所有者的組合鍵黔州,資產(chǎn)id可以用于查詢某個實(shí)體擁有的所有資產(chǎn)。這些基于key的查詢可以用于針對賬本的只讀查詢周叮,以及更新總賬的事務(wù)辩撑。
如果將資產(chǎn)建模為JSON并使用CouchDB,那么就可以使用chaincode中的CouchDB JSON查詢語言對chaincode數(shù)據(jù)值執(zhí)行復(fù)雜的富查詢仿耽,這些類型的查詢對于理解賬本上的內(nèi)容很有幫助合冀。對于這些類型的查詢,事務(wù)協(xié)議響應(yīng)通常對客戶端應(yīng)用程序有用项贺,但通常不會作為事務(wù)提交到排序服務(wù)君躺。事實(shí)上,也無法保證結(jié)果集在chaincode執(zhí)行與富查詢提交時間之間的穩(wěn)定性开缎,因此使用富查詢的結(jié)果去執(zhí)行最終的事務(wù)更新操作是不合適的棕叫,除非可以保證結(jié)果集在chaincode執(zhí)行時間與提交時間之間的穩(wěn)定性,或者可以處理在后續(xù)交易中的潛在變化奕删。例如俺泣,如果對Alice所擁有的所有資產(chǎn)執(zhí)行一個富查詢并將其傳輸給Bob,那么一個新的資產(chǎn)可能會被另一個事務(wù)分配給Alice,這是在chaincode執(zhí)行時間和提交時間之間的另一個事務(wù)伏钠,可能此過程中會錯過這個“虛值”横漏。
CouchDB作為一個獨(dú)立的數(shù)據(jù)庫進(jìn)程與peer一起運(yùn)行,因此在設(shè)置熟掂、管理和操作方面有額外的考慮缎浇。我們可以考慮從默認(rèn)的嵌入式LevelDB開始,如果需要額外的復(fù)雜的富查詢赴肚,可以轉(zhuǎn)移到CouchDB素跺。將chaincode資產(chǎn)數(shù)據(jù)建模為JSON是一種很好的做法,這樣我們就可以在將來執(zhí)行需要的復(fù)雜的富查詢誉券。
1.13. 關(guān)于數(shù)據(jù)持久化的提示
如果需要在peer容器或者CouchDB容器進(jìn)行數(shù)據(jù)持久化指厌,一種選擇是將docker容器內(nèi)相應(yīng)的目錄掛載到容器所在的宿主機(jī)的一個目錄中。例如横朋,你可以添加下列的兩行到docker-compose-base.yaml
文件中peer的約定中:
volumes:
- /var/hyperledger/peer0:/var/hyperledger/production
對于CouchDB容器仑乌,你可以在CouchDB的約定中添加兩行:
volumes:
- /var/hyperledger/couchdb0:/opt/couchdb/data
1.14. 故障排除
- 始終保持你的網(wǎng)絡(luò)是全新的。使用以下命令來移除之前生成的artifacts,crypto,containers以及chaincode images:
./byfn.sh -m down
- 如果提示以下錯誤:
Error: Error endorsing chaincode: rpc error: code = 2 desc = Error installing chaincode code mycc:1.0(chaincode /var/hyperledger/production/chaincodes/mycc.1.0 exits)
你可能由于運(yùn)行了以前的鏈碼服務(wù)(例如dev-peer1.org2.example.com-mycc-1.0
或dev-peer0.org1.example.com-mycc-1.0
)琴锭。刪除它們晰甚,然后重試。
docker rmi -f $(docker images | grep peer[0-9]-peer[0-9] | awk '{print $3}')
- 如果提示以下錯誤:
[configtx/tool/localconfig] Load -> CRIT 002 Error reading configuration: Unsupported Config Type ""
panic: Error reading configuration: Unsupported Config Type ""
那么你沒有正確設(shè)置FABRIC_CFG_PATH
環(huán)境變量决帖。configtxgen工具需要這個變量才能找到configtx.yaml
厕九。返回并執(zhí)行export FABRIC_CFG_PATH=$PWD
,然后重新創(chuàng)建channel配置地回。
- 要清理網(wǎng)絡(luò)扁远,請使用
down
選項(xiàng):
./byfn.sh -m down
如果你看到一條指示你依然有“active endpoints”,執(zhí)行以下命令清理你的Docker網(wǎng)絡(luò)刻像。這將會清除你之前的網(wǎng)絡(luò)并且給你一個全新的環(huán)境:
docker network prune
你將看到以下消息:
WARNING! This will remove all networks not used by at least one container.
Are you sure you want to continue? [y/N]
選擇y
畅买。
參考
原文:深入理解Fabric環(huán)境搭建的詳細(xì)過程
作者:深藍(lán)