1. 程式人生 > >Hyperledger Fabric 官方最新翻譯---使用指南(二)(Building Your First Network)

Hyperledger Fabric 官方最新翻譯---使用指南(二)(Building Your First Network)

  構建你第一個由兩個組織組成的Hyperledger fabric 網路(BYFN),每個都包含兩個peer節點,和一個”solo”的order 節點

1:安裝先決條件

  在我們開始前,保證所有的Prerequisites都安裝到你用於開發chaincode applications和操作fabric的環境。
  你還需要安裝示例、二進位制檔案和Docker映象( Install Samples, Binaries and Docker Images),你會發現在 fabric-samples倉庫有很多示例,我們將使用first-network 為樣例,讓我們進入到子目錄

cd fabric-samples
/first-network

  注意:本篇文件涉及到指令都需要在fabric-samples/first-network資料夾下執行,如果你在別的資料夾執行指令碼,指令碼有可能會提示找不到二進位制檔案。
  我們提供了一個全註釋指令碼byfn.sh,來快速啟動一個4個節點代表2個組織以及1個order節點組成的fabric網路。它同樣會啟動一個容器,容器中執行一個指令碼增加peer節點到channel,部署和例項化鏈碼,以及基於已部署的鏈碼推動交易(transactions)執行。
  下面是byfn.sh的幫助文字

Usage:
  byfn.sh <mode> [-c <channel name>] [-t <timeout>] [-d <delay>] [-f <docker-compose-file
>] [-s <dbtype>] [-l <language>] [-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 v1.0.x to v1.1 -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 -i <imagetag> - the tag to be used to launch the network (defaults to "latest") -v - verbose mode byfn.sh -h (print this message) Typically, one would first generate the required certificates and genesis block, then bring up the network. e.g.: byfn.sh generate -c mychannel byfn.sh up -c mychannel -s couchdb byfn.sh up -c mychannel -s couchdb -i 1.1.0-alpha byfn.sh up -l node byfn.sh down -c mychannel byfn.sh upgrade -c mychannel Taking all defaults: byfn.sh generate byfn.sh up byfn.sh down

  如果你選擇不提供channel名稱,那麼指令碼會使用一個預設名稱mychannel。CLI超時引數是一個可選引數(-t),如果你選擇不設定它,那麼CLI會放棄超過預設設定10秒的查詢請求。

2 想讓它執行起來

2.1 生成網路基礎檔案

執行下面的命令
./byfn.sh generate
  你會看到後續要發生什麼的簡短描述,伴隨著yes/no的命令提示行。
按下y或者敲回車會執行描述的動作。
截圖略過。。。。。
  第一步首先建立各類網路元件所需要的證書和私鑰,引導ordering服務的創世區塊(genesis block),配置一個channel所需要的配置事務(transactions)集合。

2.2 啟動網路

現在你可以啟動網路使用下列指令

./byfn.sh up

  上面的命令會編譯Golang鏈碼映象並且啟動相關的容器。Go是預設是支援語言,同時也支援Node。如果你想執行node鏈碼,可以改為一下命令

./byfn.sh up –l node

注意:檢視Hyperledger Fabric Shim 文件瞭解更多關於node.js chaincode shim API
再一次會提示你希望繼續還是終端。按下y按鈕或者敲回車

Starting with channel 'mychannel' and CLI timeout of '10'
Continue? [Y/n]
proceeding ...
Creating network "net_byfn" with the default driver
Creating peer0.org1.example.com
Creating peer1.org1.example.com
Creating peer0.org2.example.com
Creating orderer.example.com
Creating peer1.org2.example.com
Creating cli


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

Channel name : mychannel
Creating channel...

  這將會啟動所有的容器,並建立一個端對端的應用場景。成功完成後,你的終端會顯示

Query Result: 90
2017-05-16 17:08:15.158 UTC [main] main -> INFO 008 Exiting.....
===================== Query successful on peer1.org2 on channel 'mychannel' =====================

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


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

  你可以滾動這些日誌檢視各種交易。如果你沒有得到這個結果,可以跳到下面Troubleshooting章節,讓我們看看是否能幫助你發現錯誤

2.3關閉網路

  最後,讓我把它們都一次關閉掉讓我們可以探索網路設定。以下命令會殺掉容器,刪除加密素材和四個網路基礎檔案,從你的docker倉庫中刪除鏈碼映象

./byfn.sh down

再一次,會提示你繼續還是終端,按下Y或者回車

Stopping with channel 'mychannel' and CLI timeout of '10'
Continue? [Y/n] y
proceeding ...
WARNING: The CHANNEL_NAME variable is not set. Defaulting to a blank string.
WARNING: The TIMEOUT variable is not set. Defaulting to a blank string.
Removing network net_byfn
468aaa6201ed
...
Untagged: dev-peer1.org2.example.com-mycc-1.0:latest
Deleted: sha256:ed3230614e64e1c83e510c0c282e982d2b06d148b1c498bbdcc429e2b2531e91
...

  如果你想了解更多關於潛在的工具和啟動機制,繼續往下讀。在下面的章節,我們將介紹構建功能齊全的fabric網路的各個步驟和要求
。
  注意:下面的步驟假定將cli容器中的CORE_LOGGING_LEVEL引數設定為DEBUG
。你可以通過修改first-network資料夾下的docker-compose-cli.yaml配置檔案來完成這樣的修改。

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

3 加密發生器

  我們將使用cryptogen工具來生成我們各種網路元件的加密材料(X509證書以及簽名祕鑰),這些證書是身份的代表,他們准許在我們實體通訊和交易的過程中籤名和驗證身份驗證。

3.1 它是怎樣工作的

  Cryptogen使用包含網路拓撲的檔案crypto-config.yaml,並准許我們為組織以及屬於這些組織的元件,生成一組證書和金鑰。每個組織配備了一個根證書(ca-cert)將特定的元件(peer和order節點)繫結到該組織。通過分配每個組織一個唯一的根證書,我們模擬一個經典的網路,其中一個成員將使用自己的證書頒發機構,fabric中的交易和通訊將會被一個實體的私鑰(keystore)簽名,公鑰驗證 (signcerts).
  你將會注意到這個檔案中的count變數,我們用它指定每個組織中有多少peer節點,在我們這個例子裡面一個組織有兩個peer節點。我們現在不會深入到x.509 certificates and public key infrastructure 細節。如果你感興趣,你可以在空閒時間細讀這些主題。
  在執行這些工具前,讓我們快速瀏覽一下 crypto-config.yaml的一個片段。注意OrdererOrgs節點下的“Name”, “Domain” and “Specs” parameters引數
  

OrdererOrgs:
#---------------------------------------------------------
# Orderer
# --------------------------------------------------------
- Name: Orderer
  Domain: example.com
  CA:
      Country: US
      Province: California
      Locality: San Francisco
  #   OrganizationalUnit: Hyperledger Fabric
  #   StreetAddress: address for org # default nil
  #   PostalCode: postalCode for org # default nil
  # ------------------------------------------------------
  # "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

  網路實體的命名規則如下: “{{.Hostname}}.{{.Domain}}”,所以用我們的排序節點作為參考點,我們留下了一個排序節點名稱:orderer.example.com。該節點繫結到了Orderer的MSP ID。這個檔案包含大量的定義和語法文件。你還可以參閱 Membership Service Providers (MSP) 文件,深入學習更多關於MSP的內容。
  在我們執行完 cryptogen工具,產生的證書和私鑰將會被儲存到資料夾crypto-config。
  

4 配置交易生成器

  configtxgen工具被用來建立四個配置基礎檔案:

  • 排序創世塊
  • channel配置交易
  • 兩個錨節點交易,每個機構各一個

      可以檢視configtxgen關於這個工具功能性的完整描述,
    排序區塊是排序服務的創世區塊,並且在channel建立時 channel
    配置交易檔案就被廣播到了order節點。錨節點交易,顧名思義,指明這個channel上每個組織的錨節點。

4.1 它是怎樣工作的

  Configtxgen使用一個檔案- configtx.yaml裡面包含了樣例網路的定義。有三個成員:一個排序組織和兩個分別管理著兩個peer節點的peer組織。這個檔案同時還指定了一個聯合體- SampleConsortium-由兩個peer組織構成,注意檔案頭部的 “Profiles” 部分。你會注意到有兩個獨特的標題。
  一個用於order創世區塊- TwoOrgsOrdererGenesis,另一個用於channel- TwoOrgsChannel。
  這些標頭檔案很重要,因為我們將在建立基礎檔案時將它們作為引數傳入。
  注意:SampleConsortium是在系統級配置定義,然後在channel級配置中引入。Channel存在於聯合體範圍之內,所有的聯合體必須在網路範圍內定義。
  這個檔案同樣包含兩個附加的規範值得注意。
  第一,我們定義了每個peer組織的錨節點(peer0.org1.example.com & peer0.org2.example.com)。

5 執行工具

  你可以使用configtxgen 和 cryptogen命令建立證書/私鑰和各種各樣的配置基礎檔案。或者你可以試著修改byfn.sh檔案來實現你自己的小目標。
  

5.1 手動生成基礎檔案

  你可以參考byfn.sh中的 generateCerts函式獲取必要的命令用於建立證書,這些證書用於crypto-config.yaml檔案中定義的網路配置,但是為了方便起見,我們這裡也提供了參考。
  首先讓我們執行cryptogen工具,我們的二進位制檔案位於bin目錄,所以我們需要提供工具所在的相對路徑。
  

../bin/cryptogen generate --config=./crypto-config.yaml

你可以在終端看到以下內容

org1.example.com
org2.example.com

  證書和私鑰檔案將會被輸出到first-network目錄下的crypto-config目錄。
  下一步我們需要告訴configtxgen 工具哪裡去尋找他需要攝取的configtx.yaml檔案。我們需要告訴它在我們當前的工作目錄中找尋
export FABRIC_CFG_PATH=$PWD,然後我們將要呼叫configtxgen工具去建立排序創世區塊。

../bin/configtxgen -profile TwoOrgsOrdererGenesis -outputBlock ./channel-artifacts/genesis.block

你將會在終端看到下面的類似輸出

2017-10-26 19:21:56.301 EDT [common/tools/configtxgen] main -> INFO 001 Loading configuration
2017-10-26 19:21:56.309 EDT [common/tools/configtxgen] doOutputBlock -> INFO 002 Generating genesis block
2017-10-26 19:21:56.309 EDT [common/tools/configtxgen] doOutputBlock -> INFO 003 Writing genesis block

注意:排序創世節點和後續的基礎檔案我們都將輸出到根目錄的channel-artifacts資料夾。

5.2 建立一個渠道配置交易

  下一步我們需要建立一個channel事務基礎檔案。確認替換了$CHANNEL_NAME
  引數或者設定了環境變數CHANNEL_NAME,它將貫穿這些文件被使用
  

生成channel.tx

export CHANNEL_NAME=mychannel  && ../bin/configtxgen -profile TwoOrgsChannel -outputCreateChannelTx ./channel-artifacts/channel.tx -channelID $CHANNEL_NAME

你的控制檯會有如下的類似輸出

2017-10-26 19:24:05.324 EDT [common/tools/configtxgen] main -> INFO 001 Loading configuration
2017-10-26 19:24:05.329 EDT [common/tools/configtxgen] doOutputChannelCreateTx -> INFO 002 Generating new channel configtx
2017-10-26 19:24:05.329 EDT [common/tools/configtxgen] doOutputChannelCreateTx -> INFO 003 Writing new channel tx

  下一步我們要在我們構建的channel中為org1定義錨節點,再次提醒替換$CHANNEL_NAME引數或者設定環境變數。終端輸出將會類似channel交易基礎檔案。

../bin/configtxgen -profile TwoOrgsChannel -outputAnchorPeersUpdate ./channel-artifacts/Org1MSPanchors.tx -channelID $CHANNEL_NAME -asOrg Org1MSP

  現在,我們定義channel上另一個org2的錨節點
  

../bin/configtxgen -profile TwoOrgsChannel -outputAnchorPeersUpdate ./channel-artifacts/Org2MSPanchors.tx -channelID $CHANNEL_NAME -asOrg Org2MSP

6 啟動網路

6.1 環境變數

  為了一下針對peer0.org1.example.com的CLI命令能執行,我們需要設定如下四個環境變數。這些針對peer0.org1.example.com的變數已經預植到CLI容器,因此我們可以直接操作命令不需要傳入他們。但是如果你要呼叫其他peer或者order,你需要相應的提供這些值。檢查docker-compose-base.yaml這些特殊路徑
  

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

6.2 建立和加入channel

  回想一下,我們使用上面“建立一個渠道配置交易“部分中的configtxgen工具建立了通道配置事務。你可以重複這個步驟建立額外的channel配置交易,使用相同或者不同configtx.yaml 中的配置傳遞給configtxgen工具。然後你可以重複本節中的步驟去給你的網路建立其他channel。
  我們將使用如下命令進入CLI容器

docker exec -it cli bash

  如果成功你會看到如下資訊
 

root@0d78bb69300d:/opt/gopath/src/github.com/hyperledger/fabric/peer#

  接下來,我們要傳入建立的渠道配置交易檔案,即“建立一個渠道配置交易”中建立的channel.tx檔案,作為建立channel請求的一部分傳給order。
  我們指定我們的-c指定我們的channel名稱以及-f指定我們的渠道交易配置基礎檔案。在這個例子中,它是channel.tx,但是你也可以掛在你自己的交易配置檔案用不同的名字,一旦你在CLI容器中設定了CHANNEL_NAME環境變數,那麼你就不用顯示傳入-c引數。

export CHANNEL_NAME=mychannel
#我們還傳入了order的ca證書,為了TLS 握手
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,它是order的根證書本地路徑,准許我們來驗證TLS握手。
  這個指令返回一個創世區塊channel-ID.block,我們用來加入channel。
  它包含channel.tx中的配置資訊,如果你沒有對預設的channel名字做任何修改,那麼這個命令會返回你一個原標題mychannel.block.
  現在,我們將peer0.org1.example.com加入到channel
peer channel join -b mychannel.block。你可以修改“環境變數”那一節提到的四個環境變數來讓其他節點也加入到channel。
  我們可以簡單將錨節點peer0.org2.example.com 加入到channel而不是將每個節點都加入。當我們重寫CLI容器中的預設環境變數配置。完整的命令如下:
  

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

  或者你可以單獨選擇設定這些環境變數而不是傳入整個字串。一旦設定好,你只需要再執行channel join 命令,CLI容器將進行peer0.org2.example.com相關操作。
  

6.3 更新錨節點

  以下命令是channel更新,他們將要傳播channel的定義。本質來說,我們將要在channel的創世節點上新增額外的配置資訊。注意我們沒有修改創世區塊,而是簡單地將增量新增到定義錨節點的鏈中。
將org1的錨節點修改為peer0.org1.example.com

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

  現在修改channel定義將org2錨節點設定為peer0.org2.example.com,與peer channel join命令對等,我們也需要在執行命令前預設環境變數
  

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 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

6.4 安裝&例項化碼鏈

  注意:我們將利用一個簡單的碼鏈做演示。想學習怎樣編寫自己的碼鏈,請檢視“ Chaincode for Developers”指南。

  應用程式通過鏈碼與超級賬本互動。因此,我們需要在每個執行和背書我們交易的節點上安裝鏈碼,然後在channel上初始化鏈碼。
首先,安裝樣例Go或者Node鏈碼到四個Peer節點中的一個。如下指令安裝特定的原始碼到我們的peer節點檔案系統上去。
注意:每個鏈碼,每個版本,你只能安裝一個版本的原始碼。

# 安裝go鏈碼
peer chaincode install -n mycc -v 1.0 -p  github.com/chaincode/chaincode_example02/go/
# 安裝Node.js鏈碼,-l 用來指定語言
peer chaincode install -n mycc -v 1.0 -l node -p /opt/gopath/src/github.com/chaincode/chaincode_example02/node/

  下一步,在channel上例項化鏈碼。Channel上例項化鏈碼、設定鏈碼的背書策略、為目標peer啟動一個鏈碼容器。注意-p引數,這是指定該鏈碼的交易被驗證時的背書策略水平。
  下面的命令中,你會注意到我們設定的策略是
-P “OR (‘Org1MSP.peer’,’Org2MSP.peer’)”,意思是需要Org1或者Org2一個背書即可。如果我們把語法改成AND,那我們需要兩個組織都進行了背書。

Golang
# 注意-C 後面的系統引數
# 如果你沒有安裝mycc名稱的鏈碼,那麼注意同步修改
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鏈碼將會需要大約一分鐘,不是這個命令被掛起了,相反,它正在編譯docker映象安裝fabric-shim層。

# 注意-l指定語言
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')"

  檢視“endorsement policies”文件,瞭解更多策略實施的細節。

  如果你想要更多的peer節點與賬本互動。你可以將他們加入channel,然後安裝相同名稱、版本、語言的鏈碼原始碼到適當的peer節點檔案系統上。當指定的鏈碼與每個peer節點互動時都會啟動一個鏈碼容器,當然,node編寫的鏈碼映象都會編譯慢一些。

  一旦鏈碼被初始化,我們就不需要 –l引數了。我們只需要傳入channel的識別符號和鏈碼的名稱。

6.5 查詢

  讓我們查詢值a來確定鏈碼已經被恰當的例項化以及狀態DB被填充(the state DB was populated)。查詢語法如下:

peer chaincode query -C $CHANNEL_NAME -n mycc -c '{"Args":["query","a"]}'

6.6 呼叫

  現在讓我們把10從a移動到b,這個交易將會建立一個新的block,更新DB狀態。呼叫語法如下:

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"]}'

6.7 查詢結果

  確認一下上一步查詢結果,初始化a為100,上一步呼叫移動了10,那麼應該在查詢a應該顯示90。查詢語句如下:

peer chaincode query -C $CHANNEL_NAME -n mycc -c '{"Args":["query","a"]}'

  查詢結果為

Query Result: 90

6.8 後臺發生了什麼?

  注意:這些步驟描述script.sh由’./byfn.sh up’執行的場景。 使用./byfn.sh清理網路並確保該命令處於活動狀態。 然後使用相同的docker-compose重新啟動您的網路

  • A Scrip-Script.sh是在CLI容器內部執行的指令碼,這個配置檔案使用提供的channel名稱及channel.tx中的channel配置來執行createChannel指令。
  • createChannel的輸出是創世區塊– .block。它將會儲存在peer節點的檔案系統中,包含從channel.tx獲取到的channel配置。
  • joinChannel命令用上一步建立的創世區塊作為輸入對四個peer節點執行,這個命令將peer節點加入your_channel_name同時建立.block開始的鏈。
  • 現在我們擁有一個channel包含四個peer節點以及兩個組織,這就是我們的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中定義
  • Org1MSP (peer0.org1.example.com) 和Org2MSP (peer0.org2.example.com)的錨節點被修改了,我們將Org1MSPanchors.tx和Org2MSPanchors.tx基礎檔案以及channel名字一起傳遞給ordering 服務
  • 一個鏈碼chaincode_example02被安裝在了peer0.org1.example.com和peer0.org2.example.com
  • 鏈碼在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的peer節點背書。
  • 一個關於a的值查詢傳送給了peer0.org1.example.com,鏈碼之前已經被安裝在了peer0.org1.example.com,所以這會啟動一個org1 peer0的容器dev-peer0.org1.example.com-mycc-1.0,查詢的結果也會同時返回,因為沒有寫的d工作發生,所以返回a的值100.
  • 一個呼叫被髮送給peer0.org1.example.com將10從a移到b
  • 鏈碼之後被安裝到了peer1.org2.example.com
  • 一個查詢被髮送到peer1.org2.example.com查詢a的值,這會2啟動第三個鏈碼容器dev-peer1.org2.example.com-mycc-1.0。A的值90會被返回,說明之前a的值被修改了10的交易生效了。
  • -

6.9 這說明了什麼

  鏈碼必須被安裝到一個peer節點上,以保證他能成功對賬本進行讀/寫操作。此外,只有在一個鏈碼init或者對它進行傳統讀/寫交易操作才會啟動一個鏈碼容器。

6.10 我怎樣檢視這些交易

檢查CLI 的Docker容器

docker logs -f cli

你會看到如下輸出

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 successful on peer1.org2 on channel 'mychannel' =====================

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


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

  你可以滾動這些日誌檢視各類交易日期

6.11 我怎樣檢視鏈碼日誌

  檢查個別鏈碼容器,檢視每個容器交易的分別執行情況。這是每個容器的合併輸出

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

7 瞭解Docker Compose的拓撲結構

  BYFN示例為我們提供了兩種Docker Compose檔案,每個都是docker-compose-base.yaml的擴充套件(位於base資料夾)。
  第一個docker-compose-cli.yaml提供給我們一個CLI容器,一個order節點,4個peer節點。我們用這個檔案來檢視此頁面的所有說明。
注意:本章的剩餘部分涉及到了為SDK設計的docker compose檔案。有關這個測試的詳細情況,可以檢視 Node SDK
  第二個,docker-compose-e2e.yaml被用來執行使用node.js SDK來執行端對端的測試。除了SDK的功能,它主要的不同是涉及到了fabric-ca服務容器。結果是,我們可以傳送REST請求到CAs組織來完成使用者的登記和註冊。
  如果你想在不執行byfn.sh檔案情況下使用docker-compose-e2e.yaml,我們需要做四個請問的修改。我們需要將私鑰指向我們的CA組織。你可以在crypto-config資料夾找到這個值。例如org1路徑是crypto-config/peerOrganizations/org1.example.com/ca/.私鑰是一個很長的hash值以_sk結尾。Org2的路徑是crypto-config/peerOrganizations/org2.example.com/ca/。
  在docker-compose-e2e.yaml中更新ca0和ca1的FABRIC_CA_SERVER_TLS_KEYFILE 變數。你還需要修改命令中的路徑去啟動ca伺服器。你為每個CA容器提供兩次相同的私鑰。

8 使用CouchDB

  狀態資料庫能從預設的goleveldb切換為CouchDB。CouchDB
可以使用相同的鏈碼函式,但是它增加能力對狀態資料庫進行執行豐富和複雜查詢,當鏈碼資料被建模為JSON格式時。
  當使用CouchDB資料庫替換預設資料庫時,遵循上面列出生成基礎檔案相同的步驟,除了啟動網路時傳入docker-compose-couch.yaml。如下:

docker-compose -f docker-compose-cli.yaml -f docker-compose-couch.yaml up –d

chaincode_example02現在可以使用CouchDB了

注意:如果你選擇將fabric-couchdb容器埠對映到宿主機埠,請確認你瞭解安全隱患。在開發環境對映CouchDB REST API介面是可實現的,同時允許通過CouchDB的web介面(Fauxton)對資料庫進行了視覺化。生產環境不建議進行埠對映,為了限制對CouchDB的外部訪問。

  你可以基於上面列出的步驟,在CouchDB的狀態資料庫上
使用chaincode_example02的鏈碼,但是為了應用CouchDB查詢能力你需要將chaincode的資料模式設定為JSON(例如marbles02)。你可以查詢到marbles02鏈碼在fabric/examples/chaincode/go資料夾中。
  我們將遵守上面列出的“建立和加入channel”章節來建立和加入channel。一旦你把peer節點加入到channel,使用下面的步驟與marbles02鏈碼互動。

  • 在peer0.org1.example.com上安裝和例項化鏈碼
peer chaincode install -n marbles -v 1.0 -p github.com/chaincode/marbles02/go
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')"
  • 建立一些彈珠然後移動它們
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)
http://localhost:5984/_utils

  你可以看到一個名為mychannel的資料庫(或者你自定義的channl名稱)以及它裡面的檔案

  你在CLI中執行常規查詢(例如讀取彈珠)

 peer chaincode query -C $CHANNEL_NAME -n marbles -c '{"Args":["readMarble","marble2"]}'

  marble2的輸出是

Query Result: {"color":"red","docType":"marble","name":"marble2","owner":"jerry","size":50}

  你可以檢測特定彈珠的交易歷史-例如marble1

peer chaincode query -C $CHANNEL_NAME -n marbles -c '{"Args":["getHistoryForMarble","marble1"]}'

marble1的輸出是
Query Result: [{"TxId":"1c3d3caf124c89f91a4c0f353723ac736c58155325f02890adebaa15e16e6464", "Value":{"docType":"marble","name":"marble1","color":"blue","size":35,"owner":"tom"}},{"TxId":"755d55c281889eaeebf405586f9e25d71d36eb3d35420af833a20a2f53a3eefd", "Value":{"docType":"marble","name":"marble1","color":"blue","size":35,"owner":"jerry"}},{"TxId":"819451032d813dde6247f85e56a89262555e04f14788ee33e28b232eef36d98f", "Value":}]

你也可以對資料內容進行富查詢,例如所有者jerry的所有彈珠
peer chaincode query -C $CHANNEL_NAME -n marbles -c '{"Args":["queryMarblesByOwner","jerry"]}'
輸出將返回jerry的兩個彈珠
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}}]

9 為什麼使用CouchDB

  CouchDB是一種NoSQL解決方案。它是一種面向文件的資料庫,文件欄位被儲存為鍵值對映。欄位可以是簡單的鍵值對、列表或者對映。除了LevelDB支援的鍵查詢/複合鍵/鍵範圍查詢,CouchDB還具備完整的資料富查詢能力,例如對整個區塊鏈資料的無鍵查詢,當他的資料使用json方式儲存的就可以被完整查詢。所以CouchDB可以滿足很多LevelDB不支援的連結串列、審計、報告需求。
  CouchDB同樣也增加了區塊鏈的合規性和資料保護的安全性。因為它能夠通過過濾和遮蔽事務中的單個屬性來實現欄位級別的安全,如果需要能值允許讀許可權。
  
  另外,CouchDB屬於CAP定義中的AP型別(可用性和分割槽容錯性)。他使用最終以直線的主-主複製模型。更多的資訊可以檢視 Eventual Consistency page of the CouchDB documentation,但是在每個fabric