Hyperledger Fabric1.4.4開發應用程序-建立您的第一個網絡

建立您的第一個網絡

注意

這些說明已通過驗證,可與提供的tar文件中的最新穩定Docker映像和預編譯的設置實用程序一起使用。如果使用當前主分支中的圖像或工具運行這些命令,則可能會看到配置和緊急錯誤。

構建您的第一個網絡(BYFN)方案將提供一個示例Hyperledger Fabric網絡,該網絡由兩個組織組成,每個組織維護兩個對等節點。盡管可以使用其他訂購服務實現,但默認情況下還將部署“ Solo”訂購服務。

安裝先決條件

在我們開始之前,如果您尚未這樣做,則不妨檢查一下是否已在要開發區塊鏈應用程序和/或運行Hyperledger Fabric的平臺上安裝了所有必備軟件。

您還需要安裝Samples,Binaries和Docker Images。您會注意到fabric-samples存儲庫中包含許多示例。我們將使用 first-network示例?,F在打開該子目錄。

cd fabric-samples/first-network

注意

本文檔中提供的命令必須從存儲庫克隆first-network的子目錄中運行 fabric-samples。如果選擇從其他位置運行命令,則提供的各種腳本將無法找到二進制文件。

要立即運行嗎?

我們提供了一個帶有完整注釋的腳本- byfn.sh利用這些Docker映像快速引導Hyperledger Fabric網絡,該網絡默認情況下由代表兩個不同組織的四個對等方和一個訂購者節點組成。它還將啟動一個容器來運行腳本執行,該腳本執行會將對等方加入到通道中,部署鏈碼并根據已部署的鏈碼推動事務的執行。

這是byfn.sh腳本的幫助文本:

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)"
  -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), node, or java"
  -o <consensus-type> - the consensus-type of the ordering service: solo (default), kafka, or etcdraft"
  -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.4.0"
  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"

如果選擇不提供標志,則腳本將使用默認值。

生成網絡工件

準備好嘗試了嗎?好吧!執行以下命令:

./byfn.sh generate

您將看到有關發生的情況的簡短說明,以及是/否命令行提示符。用a響應y或按回車鍵執行所描述的操作。

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 ...
/Users/xxx/dev/fabric-samples/bin/cryptogen

##########################################################
##### Generate certificates using cryptogen tool #########
##########################################################
org1.example.com
2017-06-12 21:01:37.334 EDT [bccsp] GetDefault -> WARN 001 Before using BCCSP, please call InitFactories(). Falling back to bootBCCSP.
...

/Users/xxx/dev/fabric-samples/bin/configtxgen
##########################################################
#########  Generating Orderer Genesis block ##############
##########################################################
2017-06-12 21:01:37.558 EDT [common/configtx/tool] main -> INFO 001 Loading configuration
2017-06-12 21:01:37.562 EDT [msp] getMspConfig -> INFO 002 intermediate certs folder not found at [/Users/xxx/dev/byfn/crypto-config/ordererOrganizations/example.com/msp/intermediatecerts]. Skipping.: [stat /Users/xxx/dev/byfn/crypto-config/ordererOrganizations/example.com/msp/intermediatecerts: no such file or directory]
...
2017-06-12 21:01:37.588 EDT [common/configtx/tool] doOutputBlock -> INFO 00b Generating genesis block
2017-06-12 21:01:37.590 EDT [common/configtx/tool] doOutputBlock -> INFO 00c Writing genesis block

#################################################################
### Generating channel configuration transaction 'channel.tx' ###
#################################################################
2017-06-12 21:01:37.634 EDT [common/configtx/tool] main -> INFO 001 Loading configuration
2017-06-12 21:01:37.644 EDT [common/configtx/tool] doOutputChannelCreateTx -> INFO 002 Generating new channel configtx
2017-06-12 21:01:37.645 EDT [common/configtx/tool] doOutputChannelCreateTx -> INFO 003 Writing new channel tx

#################################################################
#######    Generating anchor peer update for Org1MSP   ##########
#################################################################
2017-06-12 21:01:37.674 EDT [common/configtx/tool] main -> INFO 001 Loading configuration
2017-06-12 21:01:37.678 EDT [common/configtx/tool] doOutputAnchorPeersUpdate -> INFO 002 Generating anchor peer update
2017-06-12 21:01:37.679 EDT [common/configtx/tool] doOutputAnchorPeersUpdate -> INFO 003 Writing anchor peer update

#################################################################
#######    Generating anchor peer update for Org2MSP   ##########
#################################################################
2017-06-12 21:01:37.700 EDT [common/configtx/tool] main -> INFO 001 Loading configuration
2017-06-12 21:01:37.704 EDT [common/configtx/tool] doOutputAnchorPeersUpdate -> INFO 002 Generating anchor peer update
2017-06-12 21:01:37.704 EDT [common/configtx/tool] doOutputAnchorPeersUpdate -> INFO 003 Writing anchor peer update

第一步將為我們的各種網絡實體生成所有證書和密鑰,用于引導訂購服務,以及配置Channel所需的配置事務的集合 。genesis block

建立網絡

接下來,您可以使用以下命令之一啟動網絡:

./byfn.sh up

上面的命令將編譯Golang鏈碼圖像并旋轉相應的容器。Go是默認的鏈碼語言,但是還支持Node.jsJava 鏈碼。如果您想使用節點鏈碼來完成本教程,請改用以下命令:

# we use the -l flag to specify the chaincode language
# forgoing the -l flag will default to Golang

./byfn.sh up -l node

注意

有關Node.js填充程序的更多信息,請參閱其 文檔。

注意

有關Java填充程序的更多信息,請參閱其 文檔

使樣本使用Java chaincode運行,您必須指定如下內容:-l java

./byfn.sh up -l java

注意

不要同時運行這兩個命令。除非您關閉并重新建立兩者之間的網絡,否則只能嘗試一種語言。

除了支持多種鏈碼語言外,您還可以發出一個標志,該標志將顯示一個五節點的Raft訂購服務或Kafka訂購服務,而不是一個節點的Solo訂購服務。有關當前支持的訂購服務實現的更多信息,請查看The Ordering Service。

要使用Raft訂購服務啟動網絡,請發出:

./byfn.sh up -o etcdraft

要使用Kafka訂購服務建立網絡,請發出:

./byfn.sh up -o kafka

再次提示您是否要繼續還是中止。回應一個y或點擊返回鍵:

Starting for channel 'mychannel' with CLI timeout of '10' seconds and CLI delay of '3' seconds
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 =====================

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

您可以滾動瀏覽這些日志以查看各種事務。如果未得到此結果,請跳至“ 故障排除”部分,讓我們看看我們是否可以幫助您發現問題所在。

中斷網絡

最后,讓我們將其全部介紹下來,以便我們一次可以探索網絡設置。以下內容將殺死您的容器,刪除加密材料和四個工件,并從Docker注冊表中刪除鏈碼映像:

./byfn.sh down

再次,您將被提示繼續,用a響應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
...

如果您想了解更多有關底層工具和引導機制的信息,請繼續閱讀。在接下來的幾節中,我們將逐步介紹構建一個功能齊全的Hyperledger Fabric網絡的各個步驟和要求。

注意

下面概述的手動步驟假定FABRIC_LOGGING_SPECcli容器被設置為DEBUG。您可以通過修改目錄中的docker-compose-cli.yaml文件來進行設置first-network。例如

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

加密發生器

我們將使用該cryptogen工具為我們的各種網絡實體生成加密材料(x509證書和簽名密鑰)。這些證書代表身份,它們允許在我們的實體進行通信和交易時進行簽名/驗證身份驗證。

它是如何工作的?

Cryptogen使用一個文件- crypto-config.yaml包含網絡拓撲,并允許我們為組織和屬于這些組織的組件生成一組證書和密鑰。每個組織都有一個唯一的根證書(ca-cert),它將特定組件(對等和訂購者)綁定到該組織。通過為每個組織分配唯一的CA證書,我們正在模仿一個典型的網絡,參與的成員將使用其自己的證書頒發機構。Hyperledger Fabric中的事務和通信由實體的私鑰(keystore)簽名,然后通過公鑰()進行驗證signcerts。

您會count在此文件中注意到一個變量。我們使用它來指定每個組織的對等點數;在我們的案例中,每個單位有兩個同級。我們現在不會深入研究x.509證書和公鑰基礎結構的細節 。如果您有興趣,可以自行研究這些主題。

運行該cryptogen工具后,生成的證書和密鑰將保存到名為的文件夾中crypto-config。請注意,該crypto-config.yaml 文件列出了五個與訂購者組織相關的訂購者。盡管該 cryptogen工具將為所有五個訂購者創建證書,除非使用了Raft或Kafka訂購服務,否則這些訂購者中只有一個將用于Solo訂購服務實現中并用于創建系統頻道和mychannel。

配置事務生成器

configtxgen工具用于創建四個配置工件:

  • 訂購者,genesis block
  • 通道,configuration transaction
  • 和兩個-每個對等組織一個。anchor peer transactions

有關此工具功能的完整說明,請參見configtxgen

訂購者模塊是訂購服務的創世紀模塊,并且在頻道創建時將頻道配置事務文件廣播到訂購者。顧名思義,錨點對等事務指定此通道上的每個組織的錨點對等體。

它是如何工作的?

Configtxgen使用文件-- configtx.yaml包含示例網絡的定義。有三個成員-一個訂購者組織(OrdererOrg)和兩個對等組織(Org1Org2),每個成員都管理和維護兩個對等節點。該文件還指定了一個財團- SampleConsortium由我們的兩個對等組織組成。請特別注意此文件底部的“配置文件”部分。您會注意到我們有幾個唯一的配置文件。一些值得注意的地方:

  • TwoOrgsOrdererGenesis:生成獨奏訂購服務的創始塊。
  • SampleMultiNodeEtcdRaft:生成筏訂購服務的創始塊。僅在發出-o標志并指定時使用etcdraft
  • SampleDevModeKafka:為Kafka訂購服務生成創世塊。僅在發出-o標志并指定時使用kafka。
  • TwoOrgsChannel:為我們的頻道生成創世塊mychannel。

這些標題很重要,因為在創建工件時,我們會將它們作為參數傳遞。

注意

注意,我們SampleConsortium是在系統級配置文件中定義的,然后由我們的通道級配置文件引用。渠道存在于聯盟的權限范圍內,所有聯盟都必須在整個網絡范圍內定義。

該文件還包含兩個值得注意的附加規范。首先,我們為每個對等組織(peer0.org1.example.compeer0.org2.example.com)指定錨點對等體。其次,我們指向每個成員的MSP目錄的位置,從而允許我們將每個組織的根證書存儲在訂購者創始塊中。這是一個關鍵的概念?,F在,與訂購服務通信的任何網絡實體都可以驗證其數字簽名。

運行工具

您可以使用configtxgencryptogen命令手動生成證書/密鑰和各種配置工件?;蛘?,您可以嘗試改編byfn.sh腳本以實現目標。

手動生成工件

您可以generateCerts在byfn.sh腳本中引用該函數,以獲取生成用于crypto-config.yaml文件中定義的網絡配置的證書所需的命令。但是,為方便起見,我們還將在此處提供參考。

首先,讓我們運行該cryptogen工具。我們的二進制文件在bin 目錄中,因此我們需要提供工具所在的相對路徑。

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

您應該在終端中看到以下內容:

org1.example.com
org2.example.com

證書和密鑰(即MSP資料)將輸出到目錄crypto-config-位于目錄根first-network目錄下。

接下來,我們需要告訴該configtxgen工具在哪里尋找configtx.yaml需要提取的 文件。我們將在當前的工作目錄中告訴它:

export FABRIC_CFG_PATH=$PWD

然后,我們將調用該configtxgen工具來創建訂購者創始塊:

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

要輸出筏訂購服務的創始塊,此命令應為:

../bin/configtxgen -profile SampleMultiNodeEtcdRaft -channelID byfn-sys-channel -outputBlock ./channel-artifacts/genesis.block

請注意SampleMultiNodeEtcdRaft此處使用的配置文件。

要輸出Kafka訂購服務的創世塊,請發出:

../bin/configtxgen -profile SampleDevModeKafka -channelID byfn-sys-channel -outputBlock ./channel-artifacts/genesis.block

如果您未使用Raft或Kafka,則應看到類似于以下內容的輸出:

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該項目根目錄下的目錄中。上面命令中的<cite style="box-sizing: border-box;">channelID</cite>是系統通道的名稱。

創建渠道配置交易

接下來,我們需要創建通道事務構件。確保替換$CHANNEL_NAME或設置CHANNEL_NAME為可在以下說明中使用的環境變量:

# The channel.tx artifact contains the definitions for our sample channel

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

請注意,如果您使用的是Raft或Kafka訂購服務,則不必對通道發出特殊命令。該TwoOrgsChannel配置文件將使用您在創建網絡的創世紀模塊時指定的訂購服務配置。

如果您不使用Raft或Kafka訂購服務,則應在終端中看到類似于以下內容的輸出:

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

接下來,我們將在正在構建的通道上為Org1定義錨點。同樣,請確保$CHANNEL_NAME為以下命令替換或設置環境變量。終端輸出將模擬通道事務工件的輸出:

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

現在,我們將在同一通道上為Org2定義錨點:

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

啟動網絡

注意

如果您byfn.sh以前運行了上面的示例,請確保在繼續操作之前關閉了測試網絡(請參閱 關閉網絡)。

我們將利用腳本來啟動我們的網絡。docker-compose文件引用了我們先前下載的圖像,并使用我們先前生成的引導了訂購程序genesis.block。

我們希望手動檢查命令,以顯示每個調用的語法和功能。

首先,讓我們開始我們的網絡:

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

如果要查看網絡的實時日志,請不要提供該-d標志。如果讓日志流傳輸,則需要打開第二個終端以執行CLI調用。

創建并加入頻道

回想一下,我們使用上面configtxgen創建渠道配置交易”部分中的 工具創建了渠道配置交易。您可以使用configtx.yaml傳遞給configtxgen工具的相同或不同的配置文件,重復該過程以創建其他渠道配置事務。然后,您可以重復本節中定義的過程以在網絡中建立其他通道。

我們將使用以下命令輸入CLI容器:docker exec

docker exec -it cli bash

如果成功,您應該看到以下內容:

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

為了使以下CLI命令起作用,我們需要在命令前添加以下四個環境變量。這些for peer0.org1.example.com的變量 被烘焙到CLI容器中,因此我們可以在不傳遞它們的情況下進行操作。但是,如果要將呼叫發送給其他對等方或訂購者,請在進行任何CLI呼叫時覆蓋環境變量,如以下示例所示:

# 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

接下來,作為創建通道請求的一部分,我們將把在“ 創建通道配置事務”部分(稱為channel.tx)中創建的生成的通道配置事務工件傳遞給訂購者。

我們用-c標志指定通道名稱,并用標志指定通道配置事務-f。在這種情況下為channel.tx,但是您可以使用其他名稱掛載自己的配置事務。再次,我們將CHANNEL_NAME在CLI容器中設置環境變量,以便我們不必顯式傳遞此參數。頻道名稱必須全部為小寫字母,少于250個字符,并且與正則表達式匹配 [a-z][a-z0-9.-]*。

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,我們作為此命令的一部分進行了傳遞。這是訂購者根證書的本地路徑,使我們可以驗證TLS握手。

此命令返回一個創世塊- <CHANNEL_NAME.block>我們將使用它來加入頻道。它包含在中指定的配置信息。channel.tx 如果您未對默認通道名稱進行任何修改,則該命令將返回標題為的原型mychannel.block。

注意

這些手動命令的其余部分將保留在CLI容器中。當定位除以外的對等對象時,您還必須記住在所有命令前加上相應的環境變量 peer0.org1.example.com。

現在讓我們加入peer0.org1.example.com頻道。

# By default, this joins ``peer0.org1.example.com`` only
# the <CHANNEL_NAME.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

 peer channel join -b mychannel.block

您可以通過在上面的“ 創建和加入頻道” 部分中使用的四個環境變量進行適當的更改,使其他對等節點加入頻道。

與其加入每個對等點,不如簡單地加入,peer0.org2.example.com以便我們可以正確地更新頻道中的錨點對等點定義。由于我們將覆蓋烘焙到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:9051 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


注意

在v1.4.1之前,docker網絡中的所有對等點都使用port `7051`。如果使用v1.4.1之前的版本的fabric-samples,請將`CORE_PEER_ADDRESS`本教程中所有出現的都修改為使用port `7051`。

另外,您可以選擇單獨設置這些環境變量,而不是傳入整個字符串。設置好之后,您只需再次發出命令,CLI容器將代表。`peer channel join``peer0.org2.example.com`

### 更新錨點

以下命令是通道更新,它們將傳播到通道的定義。本質上,我們在通道的創世塊之上添加了其他配置信息。請注意,我們不是在修改創世塊,而只是將增量添加到將定義錨點對等點的鏈中。

更新通道定義以將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


現在更新通道定義,將Org2的錨點對等定義為`peer0.org2.example.com`。與Org2對等方的命令相同,我們需要在此調用之前加上適當的環境變量。`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:9051 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


### 安裝并實例化Chaincode

注意

我們將利用一個簡單的現有鏈碼。要了解如何編寫自己的鏈碼,請參閱《[開發人員鏈碼》](https://hyperledger-fabric.readthedocs.io/en/release-1.4/chaincode4ade.html)教程。

應用程序通過進行與區塊鏈分類賬的交互`chaincode`。因此,我們需要在將執行并認可我們交易的每個對等方上安裝鏈碼,然后在通道上實例化鏈碼。

首先,將示例Go,Node.js或Java chaincode安裝到Org1中的peer0節點上。這些命令將指定的源代碼樣式放置到我們對等方的文件系統上。

注意

每個鏈碼名稱和版本只能安裝一個版本的源代碼。源代碼在鏈代碼名稱和版本的上下文中存在于對等方的文件系統上;它與語言無關。同樣,實例化的鏈碼容器將反映對等方上已安裝的任何語言。

**golang**

this installs the Go chaincode. For go chaincode -p takes the relative path from $GOPATH/src

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 to indicate "node" chaincode

for node chaincode -p takes the absolute path to the node.js chaincode

peer chaincode install -n mycc -v 1.0 -l node -p /opt/gopath/src/github.com/chaincode/chaincode_example02/node/


**Java**

make note of the -l flag to indicate "java" chaincode

for java chaincode -p takes the absolute path to the java chaincode

peer chaincode install -n mycc -v 1.0 -l java -p /opt/gopath/src/github.com/chaincode/chaincode_example02/java/


當我們實例化通道上的鏈碼時,將設置背書策略以要求來自Org1和Org2中的對等方的背書。因此,我們還需要在Org2的對等節點上安裝chaincode。

修改以下四個環境變量以對Org2中的peer0發出安裝命令:

Environment variables for PEER0 in 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:9051
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


現在,將示例Go,Node.js或Java鏈碼安裝到Org2中的peer0上。這些命令將指定的源代碼樣式放置到我們對等方的文件系統上。

**Golang**

this installs the Go chaincode. For go chaincode -p takes the relative path from $GOPATH/src

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 to indicate "node" chaincode

for node chaincode -p takes the absolute path to the node.js chaincode

peer chaincode install -n mycc -v 1.0 -l node -p /opt/gopath/src/github.com/chaincode/chaincode_example02/node/


**Java**

make note of the -l flag to indicate "java" chaincode

for java chaincode -p takes the absolute path to the java chaincode

peer chaincode install -n mycc -v 1.0 -l java -p /opt/gopath/src/github.com/chaincode/chaincode_example02/java/


接下來,實例化通道上的鏈碼。這將初始化通道上的鏈碼,為鏈碼設置背書策略,并為目標對等方啟動鏈碼容器。注意`-P` 論點。這是我們的政策,其中我們針對要驗證的鏈碼指定了交易所需的背書級別。

在下面的命令中,您會注意到我們將策略指定為 。這意味著我們需要來自Org1 **和** Org2 的對等方的“背書” (即兩次背書)。如果將語法更改為,則只需要一個背書即可。`-P "AND ('Org1MSP.peer','Org2MSP.peer')"``OR`

**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 "AND ('Org1MSP.peer','Org2MSP.peer')"


**Node.js**

注意

Node.js鏈代碼的實例化大約需要一分鐘。該命令未掛起;而是在編譯映像時安裝了fabric-shim層。

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 "AND ('Org1MSP.peer','Org2MSP.peer')"


**Java**

注意

請注意,Java鏈代碼實例化可能會花費一些時間,因為它會在Java環境中編譯鏈代碼并下載docker容器。

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 java -v 1.0 -c '{"Args":["init","a", "100", "b","200"]}' -P "AND ('Org1MSP.peer','Org2MSP.peer')"


有關 政策實施的更多詳細信息,請參閱[背書政策](http://hyperledger-fabric.readthedocs.io/en/latest/endorsement-policies.html)文檔。

如果希望其他對等方與分類帳進行交互,則需要將它們加入通道,并將鏈碼源的相同名稱,版本和語言安裝到適當的對等方的文件系統上。一旦每個對等方嘗試與該特定鏈式代碼進行交互,就會為每個對等者啟動一個鏈式代碼容器。同樣,請注意Node.js圖像的編譯速度較慢。

一旦鏈碼已在通道上實例化,我們就可以放棄該`l` 標志。我們只需要輸入通道標識符和鏈碼的名稱即可。

### 詢問

讓我們查詢值`a`以確保正確地實例化了鏈碼并填充了狀態數據庫。查詢的語法如下:

be sure to set the -C and -n flags appropriately

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


### 調用

現在讓我們`10`從`a`移至`b`。此事務將剪切一個新塊并更新狀態數據庫。調用的語法如下:

be sure to set the -C and -n flags appropriately

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


### 詢問

讓我們確認先前的調用已正確執行。我們`a`使用值初始化鍵,`100`并在`10`之前的調用中將其刪除。因此,針對的查詢`a`應返回`90`。查詢的語法如下。

be sure to set the -C and -n flags appropriately

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


我們應該看到以下內容:

Query Result: 90


隨意重新開始并操作鍵值對和后續調用。

### 安裝

現在,我們將鏈碼安裝在第三個對等節點Org2中的peer1上。修改以下四個環境變量以對Org2中的peer1發出安裝命令:

Environment variables for PEER1 in 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:10051
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


現在,將示例Go,Node.js或Java chaincode安裝到Org2中的peer1上。這些命令將指定的源代碼樣式放置到我們對等方的文件系統上。

**Golang**

this installs the Go chaincode. For go chaincode -p takes the relative path from $GOPATH/src

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 to indicate "node" chaincode

for node chaincode -p takes the absolute path to the node.js chaincode

peer chaincode install -n mycc -v 1.0 -l node -p /opt/gopath/src/github.com/chaincode/chaincode_example02/node/


**Java**

make note of the -l flag to indicate "java" chaincode

for java chaincode -p takes the absolute path to the java chaincode

peer chaincode install -n mycc -v 1.0 -l java -p /opt/gopath/src/github.com/chaincode/chaincode_example02/java/


### 詢問

讓我們確認我們可以向Org2中的Peer1發出查詢。我們`a`使用值初始化鍵,`100`并在`10`之前的調用中將其刪除。因此,針對的查詢`a`仍應返回`90`。

Org2中的peer1必須首先加入通道,然后它才能響應查詢。可以通過發出以下命令來加入通道:

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


連接命令返回后,可以發出查詢。查詢的語法如下。

<pre style="box-sizing: border-box; font-family: Consolas, &quot;Andale Mono WT&quot;, &quot;Andale Mono&quot;, &quot;Lucida Console&quot;, &quot;Lucida Sans Typewriter&quot;, &quot;DejaVu Sans Mono&quot;, &quot;Bitstream Vera Sans Mono&quot;, &quot;Liberation Mono&quot;, &quot;Nimbus Mono L&quot;, Monaco, &quot;Courier New&quot;, Courier, monospace; font-size: 12px; white-space: pre; margin: 0px; padding: 12px; line-height: normal; display: block; overflow: auto; color: rgb(64, 64, 64);"># be sure to set the -C and -n flags appropriately

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

我們應該看到以下內容:

<pre style="box-sizing: border-box; font-family: Consolas, "Andale Mono WT", "Andale Mono", "Lucida Console", "Lucida Sans Typewriter", "DejaVu Sans Mono", "Bitstream Vera Sans Mono", "Liberation Mono", "Nimbus Mono L", Monaco, "Courier New", Courier, monospace; font-size: 12px; white-space: pre; margin: 0px; padding: 12px; line-height: normal; display: block; overflow: auto; color: rgb(64, 64, 64);">Query Result: 90
</pre>

隨意重新開始并操作鍵值對和后續調用。

幕后發生了什么?

注意

這些步驟描述了script.sh由'./byfn.sh up'運行的情況 。使用清潔網絡,并確保此命令處于活動狀態。然后使用相同的docker-compose提示符再次啟動網絡./byfn.sh down

  • 腳本-- script.sh在CLI容器中烘焙。該腳本createChannel根據提供的通道名稱驅動命令,并使用channel.tx文件進行通道配置。
  • 的輸出createChannel是一個創世塊-- <your_channel_name>.block存儲在對等方的文件系統上,并包含從channel.tx指定的通道配置。
  • joinChannel對所有四個對等設備執行該命令,該命令將先前生成的創世塊作為輸入。此命令指示對等方加入<your_channel_name>并創建以開頭的鏈<your_channel_name>.block。
  • 現在,我們有一個由四個對等方和兩個組織組成的渠道。這是我們的TwoOrgsChannel個人資料。
  • peer0.org1.example.compeer1.org1.example.com屬于ORG1; peer0.org2.example.compeer1.org2.example.com屬于ORG2
  • 這些關系是通過定義的crypto-config.yaml,MSP路徑是在我們的docker compose中指定的。
  • 然后,更新Org1MSP(peer0.org1.example.com)和Org2MSP(peer0.org2.example.com)的錨點。為此,我們將Org1MSPanchors.txOrg2MSPanchors.tx工件以及渠道名稱一起傳遞給訂購服務。
  • 一個chaincode - chaincode_example02 -安裝在peer0.org1.example.compeer0.org2.example.com
  • 然后將鏈碼“實例化”到mychannel。實例化將鏈碼添加到通道,啟動目標對等方的容器,并初始化與鏈碼關聯的鍵值對。此示例的初始值為[“ a”,“ 100”,“ b”,“ 200”]。這種“實例化”產生了一個名為“ dev-peer0.org2.example.com-mycc-1.0starting ”的容器。
  • 實例化還為背書策略傳遞了一個參數。該策略定義為 ,這意味著任何事務都必須由與Org1和Org2綁定的對等方認可。-P "AND ('Org1MSP.peer','Org2MSP.peer')"
  • 向“ a”的值發出查詢peer0.org2.example.comdev-peer0.org2.example.com-mycc-1.0 實例化鏈碼時,已啟動名為Org2 peer0的容器。返回查詢結果。沒有發生寫操作,因此對“ a”的查詢仍將返回值“ 100”。
  • 發送調用并將 “ 10”從“ a”移動到“ b” peer0.org1.example.com并將peer0.org2.example.com其移動
  • 查詢發送到peer0.org2.example.com“ a”的值。返回值90,正確反映了先前的交易,在該交易中,鍵“ a”的值被修改了10。
  • 鏈碼-chaincode_example02-安裝在peer1.org2.example.com
  • 查詢發送到peer1.org2.example.com“ a”的值。這將啟動名為的第三個chaincode容器dev-peer1.org2.example.com-mycc-1.0。返回值90,正確反映了先前的交易,在該交易中,鍵“ a”的值被修改了10。

這說明了什么?

必須在對等方上安裝Chaincode ,以使其能夠對分類帳成功執行讀/寫操作。此外,直到init針對該鏈碼執行了傳統的交易(讀/寫)(例如,查詢“ a”的值)后,方才啟動鏈碼容器。事務導致容器啟動。而且,通道中的所有對等方都維護分類賬的精確副本,該副本包括將區塊,不可變的順序記錄存儲在塊中的區塊鏈,以及維護當前狀態快照的狀態數據庫。這包括未在其上安裝鏈碼的那些對等方(peer1.org1.example.com如上例所示)。最后,安裝鏈碼后即可訪問它(例如peer1.org2.example.com 在上面的示例中),因為它已被實例化。

我如何看待這些交易?

檢查CLI Docker容器的日志。

<pre style="box-sizing: border-box; font-family: Consolas, "Andale Mono WT", "Andale Mono", "Lucida Console", "Lucida Sans Typewriter", "DejaVu Sans Mono", "Bitstream Vera Sans Mono", "Liberation Mono", "Nimbus Mono L", Monaco, "Courier New", Courier, monospace; font-size: 12px; white-space: pre; margin: 0px; padding: 12px; line-height: normal; display: block; overflow: auto; color: rgb(64, 64, 64);">docker logs -f cli
</pre>

您應該看到以下輸出:

<pre style="box-sizing: border-box; font-family: Consolas, "Andale Mono WT", "Andale Mono", "Lucida Console", "Lucida Sans Typewriter", "DejaVu Sans Mono", "Bitstream Vera Sans Mono", "Liberation Mono", "Nimbus Mono L", Monaco, "Courier New", Courier, monospace; font-size: 12px; white-space: pre; margin: 0px; padding: 12px; line-height: normal; display: block; overflow: auto; color: rgb(64, 64, 64);">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 =====================


| ____| | \ | | | _
| | | | | | | | |
| |
__ | |\ | | || |
|_____| |
| _| |____/
</pre>

您可以滾動瀏覽這些日志以查看各種事務。

如何查看鏈碼日志?

檢查各個chaincode容器,以查看針對每個容器執行的單獨事務。這是每個容器的合并輸出:

<pre style="box-sizing: border-box; font-family: Consolas, "Andale Mono WT", "Andale Mono", "Lucida Console", "Lucida Sans Typewriter", "DejaVu Sans Mono", "Bitstream Vera Sans Mono", "Liberation Mono", "Nimbus Mono L", Monaco, "Courier New", Courier, monospace; font-size: 12px; white-space: pre; margin: 0px; padding: 12px; line-height: normal; display: block; overflow: auto; color: rgb(64, 64, 64);">$ 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"}
</pre>

了解Docker Compose拓撲

BYFN示例向我們提供了兩種Docker Compose文件,這兩種文件都是從擴展的docker-compose-base.yaml(位于base 文件夾中)。我們的第一個風格,docker-compose-cli.yaml為我們提供了一個CLI容器以及一個訂購者和四個對等方。我們將此文件用于此頁面上的全部說明。

注意

本節的其余部分介紹了為SDK設計的docker-compose文件。 有關運行這些測試的詳細信息,請參考Node SDK倉庫。

第二種風味docker-compose-e2e.yaml構造為使用Node.js SDK運行端到端測試。除了可以使用SDK之外,它的主要區別還在于,Fabric-ca服務器具有容器。因此,我們能夠將REST調用發送到組織CA,以進行用戶注冊和注冊。

如果要在docker-compose-e2e.yaml不先運行byfn.sh腳本的情況下使用,那么我們將需要進行四個小修改。我們需要指向本組織CA的私鑰。您可以在crypto-config文件夾中找到這些值。例如,要找到Org1的私鑰,我們將遵循以下路徑- crypto-config/peerOrganizations/org1.example.com/ca/。私鑰是一個長哈希值,后跟_sk。Org2的路徑為- crypto-config/peerOrganizations/org2.example.com/ca/

docker-compose-e2e.yaml更新中,ca0和ca1的FABRIC_CA_SERVER_TLS_KEYFILE變量。您還需要編輯命令中提供的路徑以啟動ca服務器。您為每個CA容器兩次提供相同的私鑰。

使用CouchDB

可以將狀態數據庫從默認(goleveldb)切換到CouchDB。CouchDB可以使用相同的鏈碼功能,但是,還具有對鏈碼數據建模為JSON的狀態數據庫數據內容執行豐富和復雜查詢的功能。

要使用CouchDB代替默認數據庫(goleveldb),請遵循前面概述的用于生成工件的過程,但同時也要啟動網絡傳遞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查詢功能,您將需要使用鏈數據編碼為JSON的鏈碼(例如,marbles02)。您可以在目錄中找到marbles02鏈碼 fabric/examples/chaincode/go。

我們將按照上述createandjoin一節中所述的相同過程來創建和加入渠道 。將同伴加入頻道后,請執行以下步驟與marbles02鏈碼進行交互:

  • 在以下位置安裝并實例化鏈碼peer0.org1.example.com
# be sure to modify the $CHANNEL_NAME variable accordingly for the instantiate command

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 ('Org1MSP.peer','Org2MSP.peer')"
  • 創建一些大理石并將其移動:
# be sure to modify the $CHANNEL_NAME variable accordingly

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端口,則現在可以通過打開瀏覽器并導航至以下URL,通過CouchDB Web界面(Fauxton)查看狀態數據庫:

    http://localhost:5984/_utils

您應該看到一個名為mychannel(或您唯一的頻道名稱)的數據庫以及其中的文檔。

注意

對于以下命令,請確保適當地更新$ CHANNEL_NAME變量。

您可以從CLI運行常規查詢(例如閱讀marble2):

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

為什么選擇CouchDB

CouchDB是一種NoSQL解決方案。它是一個面向文檔的數據庫,其中文檔字段存儲為鍵值映射。字段可以是簡單的鍵值對,列表或映射。除了LevelDB支持的鍵/復合鍵/鍵范圍查詢外,CouchDB還支持完整的數據豐富查詢功能,例如針對整個區塊鏈數據的非鍵查詢,因為其數據內容以JSON格式存儲,并且完全可查詢的。因此,CouchDB可以滿足LevelDB不支持的許多用例的鏈碼,審計,報告要求。

CouchDB還可以增強區塊鏈中合規性和數據保護的安全性。因為它能夠通過過濾和屏蔽事務中的各個屬性來實現字段級安全性,并且僅在需要時才授權只讀權限。

另外,CouchDB屬于CAP定理的AP類型(可用性和分區容差)。它使用帶有的主-主復制模型。在CouchDB文檔的“ 最終一致性”頁面上可以找到更多信息 。但是,在每個結構同位體下,沒有數據庫副本,可以保證對數據庫的寫入是一致且持久的(不是)。Eventual ConsistencyEventual Consistency

CouchDB是第一個用于Fabric的外部可插入狀態數據庫,并且可能并且應該有其他外部數據庫選項。例如,IBM為其區塊鏈啟用關系數據庫。并且可能還需要CP類型(一致性和分區容差)數據庫,以便在不保證應用程序級別的情況下實現數據一致性。

關于數據持久性的說明

如果需要在對等容器或CouchDB容器上保持數據持久性,一種選擇是將docker-host中的目錄掛載到容器中的相關目錄中。例如,您可以在docker-compose-base.yaml文件的對等容器規范中添加以下兩行:

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

對于CouchDB容器,您可以在CouchDB容器規范中添加以下兩行:

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

故障排除

  • 始終重新啟動網絡。使用以下命令刪除工件,加密,容器和鏈碼圖像:
./byfn.sh down
注意

你**會**看到錯誤,如果你不刪除舊容器和圖像。
  • 如果您看到Docker錯誤,請首先檢查您的Docker版本(Prerequisites),然后嘗試重新啟動Docker進程。Docker的問題通常無法立即識別。例如,您可能會看到由于無法訪問安裝在容器中的加密材料而導致的錯誤。

    如果它們仍然存在,請刪除您的圖像并從頭開始:

    docker rm -f $(docker ps -aq)
    docker rmi -f $(docker images -q)
  • 如果在創建,實例化,調用或查詢命令時看到錯誤,請確保已正確更新了通道名稱和鏈碼名稱。提供的示例命令中包含占位符值。

  • 如果看到以下錯誤:

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)
您可能具有先前運行的鏈碼圖像(例如`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}')
  • 如果您看到類似以下內容的內容:
    Error connecting: rpc error: code = 14 desc = grpc: RPC failed fast due to transport failure
    Error: rpc error: code = 14 desc = grpc: RPC failed fast due to transport failure
確保針對重新標記為“最新”的“ 1.0.0”圖像運行網絡。
  • 如果看到以下錯誤:
    [configtx/tool/localconfig] Load -> CRIT 002 Error reading configuration: Unsupported Config Type ""
    panic: Error reading configuration: Unsupported Config Type ""
然后,您沒有`FABRIC_CFG_PATH`正確設置環境變量。configtxgen工具需要此變量才能找到configtx.yaml。返回并執行一個,然后重新創建您的通道工件。`export FABRIC_CFG_PATH=$PWD`
  • 要清理網絡,請使用以下down選項:
./byfn.sh down
  • 如果看到錯誤消息指出您仍然具有“活動端點”,請修剪Docker網絡。這將清除以前的網絡,并為您提供一個全新的環境:
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`。
  • 如果看到類似于以下內容的錯誤:
/bin/bash: ./scripts/script.sh: /bin/bash^M: bad interpreter: No such file or directory
確保有問題的文件(在本示例中為**script.sh**)以Unix格式編碼。這很可能是由于未在Git配置中將設置`core.autocrlf`為引起的 `false`(請參閱 [Windows Extras](https://hyperledger-fabric.readthedocs.io/en/release-1.4/prereqs.html#windows-extras))。有幾種解決方法。例如,如果您有權訪問vim編輯器,請打開文件:
vim ./fabric-samples/first-network/scripts/script.sh
然后通過執行以下vim命令來更改其格式:
:set ff=unix

注意

如果仍然看到錯誤,請在Hyperledger Rocket ChatStackOverflow結構問題通道上 共享日志 。

?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容