Hyperledger fabri 部署網路(單機環境)
title: Hyperledger fabri 部署網路(單機環境)
tags: Hyperledger, fabric ,區塊鏈
安裝預置環境
下載專案
首先我們需要配置好Hyperledger Fabric
開發環境,然後下載並安裝Hyperledger Fabric Samples
。你會注意到fabric-samples
資料夾中包含了許多示例。我們將使用first-network
這個例子。
你如果你不知道環境配置和Samlpes
使用指令碼自動部署
Hyperledger Fabric Samples
提供一個完全註釋的指令碼byfn.sh
,利用這些Docker映象可以快速引導一個由4個代表2個不同組織的peer節點以及一個排序服務節點的Hyperledger fabric網路。它還將啟動一個容器來執行一個將peer節點加入channel、部署例項化鏈碼服務以及驅動已經部署的鏈碼執行交易的指令碼。
為了使用byfn.sh
我們先切換到 first-network
目錄
```cd /home/go/src/fabric-samples/first-network`
1.檢視byfn.sh
幫助文件
./byfn.sh -h
注意:如果你選擇不提供channel名稱,則指令碼將使用預設名稱mychannel
- 生成配置
第一步先生成成我們各種網路實體的所有證書和金鑰。
./byfn.sh -m generate -i 1.0.0
注意:1.0.0是映象標籤 ,使用 -i可以指定標籤,如果不指定預設標籤為
latest
, 下面命令中的1.0.0類同。
- 啟動網路
現在我們開始使用命令啟動網路
./byfn.sh -m up -i 1.0.0
- 關閉網路
當然我們也可以關閉網路,使用下面的命令會將關閉你的容器,移除加密材料和4個配置資訊,並且從Docker倉庫刪除chaincode映象
./byfn.sh -m down -i 1.0.0
使用工具手動部署
瞭解工具
- 證書生成器
fabric使用cryptogen
工具,讀取描述了網路的拓撲結構crypto-config.yaml
的配置檔案,來為網路中的實體生成證書(certificates)。這些證書是身份的代表,它們允許在我們的網路實體進行交流和交易時進行簽名/驗證身份驗證。
通過對每個組織分配唯一的CA證書,每個鏈成員通過自己的證書獲取許可權。Hyperledger Fabric中的交易和通訊是通過儲存在keystore中的實體的私鑰簽名,然後通過公鑰手段進行驗證(signcerts)。
crypto-config.yaml
檔案裡的count
引數用來指指定每個組織中peer
的數量。
有興趣的小夥伴可以自己看本機的
crypto-config.yaml
檔案。
- 配置交易生成器
`configtxgen是Hyperledger Fabric提供的用於通道配置的實用程式,主要生成以下3種檔案:
order genesis block
:排序服務(ordering service)的創世區塊。channel configuration transaction
: 通道配置交易,會在channel建立時廣播給orderer。- 以及兩個
anchor peer transactions
:指定通道上兩個組織的錨節點(Anchor Peer)。
Configtxgen使用一個包含簡單網路的定義的configtx.yaml
檔案。該檔案還指定了一個SampleConsortium
的聯盟,2個節點組織構成。
請注意,我們SampleConsortium在系統級配置檔案中定義,然後由我們的通道級配置檔案引用。渠道存在於一個聯盟的範圍內,所有聯盟必須在整個網路的範圍內定義。
手動生成配置檔案
我們可以用configtxgen
和cryptogen
命令來手動生成證書/金鑰和各種配置檔案。
注意:
cryptogen
和configtxgen
都是需要我們手動編譯生成的,並且存放在$GOPATH/bin/
如何生成,可以檢視我之前的文章
https://blog.csdn.net/yang731227/article/details/83868333
- 生成證書
首先我們執行crytyogen
工具,我們的二進位制檔案位於bin 目錄中. 我們可以通過修改crypto-config.yaml
檔案來生成我們需要的證書。
首先進入存放crypto-config.yaml
的目錄
cd fabric-samples/first-network
然後執行工具生成證書
$GOPATH/bin/cryptogen generate --config=./crypto-config.yaml
執行命令返回資訊:
org1.example.com
org2.example.com
執行命令後,證書和金鑰(也就是MSP material)將輸出到crypto-config目錄中,裡面是各個組織的安全檔案。
- 生成創世區塊
接下來,我們需要告訴configtxgen
去哪找到需要的配置檔案configtx.yaml
,所以我們先先設定一個環境變數。
必須在fabric-samples/first-network
目錄下使用
export FABRIC_CFG_PATH=$PWD
然後,我們將呼叫configtxgen
工具去建立orderer genesis block
$GOPATH/bin/configtxgen -profile TwoOrgsOrdererGenesis -channelID byfn-sys-channel -outputBlock ./channel-artifacts/genesis.block
注意: orderer genesis塊和我們即將建立的後續工件將輸出到channel-artifacts該專案根目錄的目錄中。上述命令中的channelID是系統通道的名稱。
- 建立channel transaction配置(channel.tx)
接下來,我們需要建立channel transaction配置。執行命令前需要設定$CHANNEL_NAME
環境變數。
export CHANNEL_NAME=mychannel`
$GOPATH/bin/configtxgen -profile TwoOrgsChannel -outputCreateChannelTx ./channel-artifacts/channel.tx -channelID $CHANNEL_NAME`
接下來,在我們建立的channel上定義兩個Anchor Peer
節點 Org1
和Org2
。執行命令為:
$GOPATH/bin/configtxgen -profile TwoOrgsChannel -outputAnchorPeersUpdate ./channel-artifacts/Org1MSPanchors.tx -channelID $CHANNEL_NAME -asOrg Org1MSP`
$GOPATH/bin/configtxgen -profile TwoOrgsChannel -outputAnchorPeersUpdate ./channel-artifacts/Org2MSPanchors.tx -channelID $CHANNEL_NAME -asOrg Org2MSP `
order genesis block 和 channel transaction artifacts都將輸出到channel-artifacts目錄下。最終目錄包含4個檔案:genesis.block,channel.tx,Org1MSPanchors.tx和Org2MSPanchors.tx。
啟動網路
注意:如果你之前使用 byfn.sh指令碼開啟了網路,請確保在繼續操作之前已關閉測試網路。
我們將利用docker-compose
指令碼來啟動我們的區塊鏈網路。docker-compose檔案利用我們之前下載的映象,並用以前生成的genesis.block來引導orderer。
在執行之前,需要修改docker-compose-cli.yaml
檔案,使用#
註釋掉下面的程式碼:
#command: /bin/bash -c './scripts/script.sh ${CHANNEL_NAME} ${DELAY}; sleep $TIMEOUT'
該行程式碼會使cli容器執行的時候自動執行指令碼script.sh,會進行建立channel,加入節點等等一系列操作,此時如果再進行手動執行,並把CHANNEL_NAME
設定為mychannel
,就會出現channel名稱重複問題,從而報錯 Error: got unexpected status: BAD_REQUEST
。
1.執行docker-compose
命令啟動網路:
docker-compose -f docker-compose-cli.yaml up -d
CLI容器處於空閒狀態時只會會停留1000秒。你可以使用以下命令再次啟動它:
docker start cli
2.設定環境變數
下面是peer0.org1.example.com
的環境變數。每當在CLI命令中需要執行節點操作時,都要確認當前處於哪個節點下。
CORE_PEER_MSPCONFIGPATH=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org1.example.com/users/[email protected]/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
CLI容器針對peer0.org1.example.com
操作所需要的環境變數已經設定好了,但如果需要對其他peer或者orderer節點進行操作,則需要提供這些變數值。
例如,要切換至peer1.org1
節點,就需要將peer0.org1.example.com
在環境變數中進行替換。同理,如果切換到其他節點,需要對應的修改環境變數。
3.建立&加入通道
我們使用configtxgen工具建立channel transaction配置 。你可以重複使用相同或不同的configtx.yaml檔案,在你的網路建立其他的通道。
我首先進入CLI容器中:
docker exec -it cli bash
如果執行成功,你將看到下列資訊:opt/gopath/src/github.com/hyperledger/fabric/peer#
我們使用-c標誌指定channel的名字,-f標誌指定channel配置檔案。在這個例子中它是channel.tx,當然你也可以使用不同的名稱,掛載你自己的channel配置。再一次,我們將在CLI容器裡設定了CHANNEL_NAME
環境變數,所以不需要明確傳遞這個引數。
export CHANNEL_NAME=mychannel
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的本地路徑,允許我們去驗證TLS握手。
此命令返回一個創世區塊<channel-ID.block>
,我們將使用它加入通道。它包含了channel.tx
中的配置資訊。如果你沒有修改過channel.tx
檔案中預設的通道名稱,上面的命令會返回mychannel.block
。
現在讓我們將peer0.org1.example.com
加入channel。
peer channel join -b mychannel.block
前面我們說過,當需要加入其他節點的時候,需要設定環境變數
CORE_PEER_MSPCONFIGPATH=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org2.example.com/users/[email protected]/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
我們繼續加入peer0.org2.example.com
:
peer channel join -b mychannel.block
你可以修改環境變數來讓別的節點加入通道,這裡我就不演示了。
- 更新錨節點(anchor peers)
我最後新增到節點是peer1.org2.example.com
,所以執行完成後我們的命令列現在處於peer1.org2
下。而現在我們需要為Org1設定錨節點peer0.org1
,所以命令列需要先切回到peer0.org1
:
設定當前操作節點為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/[email protected]/msp
CORE_PEER_ADDRESS=peer0.org1.example.com:7051
然後更新Org1錨節點為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
接下來為Org2設定錨節點peer0.org2
設定當前操作節點為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/[email protected]/msp
CORE_PEER_ADDRESS=peer0.org2.example.com:7051
然後更新Org2錨節點為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
安裝和例項化鏈碼
我們將利用一個現有的簡單鏈碼,應用程式和區塊鏈賬本會相互影響通過chaincode
。因此,我們需要在每個會執行以及背書我們交易的peer節點安裝chaincode
,然後在通道上例項化chaincode
。
chaincode 支援很多語言,如Gland ,Node.js ,Java 。
安裝
在這裡我們使用Golang版本的,現在我們來安裝下
peer chaincode install -n mycc -v 1.0 -p github.com/hyperledger/fabric/examples/chaincode/go/chaincode_example02
接下來,在通道上例項化chaincode。這將初始化通道上的鏈碼,設定鏈碼的背書策略,為目標peer節點啟動一個chaincode容器注意-P
引數。這是我們需要指定的當這個chaincode的交易需要被驗證的時侯的背書策略。
在下面的命令中,你會注意到我們指定-P "OR ('Org0MSP.member','Org1MSP.member')"
作為背書策略。這意味著我們需要Org1或者Org2組織中的其中一個的節點的背書即可(即只有一個背書)。如果我們改變語法為AND那麼我們就需要2個背書者。
peer chaincode instantiate -o orderer.example.com:7050 --tls $CORE_PEER_TLS_ENABLED --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.member','Org2MSP.member')"
例項化
現在我們來進行實戰
1.查詢(Query)
讓我們查詢一下a的值,以確保鏈碼被正確例項化,state DB被填充。查詢的語法如下:
peer chaincode query -C $CHANNEL_NAME -n mycc -c '{"Args":["query","a"]}'
2.呼叫(Invoke)
現在讓我們從a賬戶轉10到b賬戶。這個交易將建立一個新的區塊並更新state DB。呼叫語法如:
peer chaincode invoke -o orderer.example.com:7050 --tls $CORE_PEER_TLS_ENABLED --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"]}'
3.我們再次查詢
讓我們確認下我們之前的呼叫被正確地執行了。我們初始化了a的值為100,在上一次呼叫的時侯轉移了10給b。因此,查詢a應該展示90。查詢的語法如下:
peer chaincode query -C $CHANNEL_NAME -n mycc -c '{"Args":["query","a"]}'
執行過程分析
以下是通過./byfn.sh -m up啟動網路時,執行script.sh指令碼所進行步驟
-
script.sh
指令碼被拷貝到CLI容器中。這個指令碼驅動了使用提供的channel name以及通道配置的channel.tx檔案的createChannel
命令。 -
createChannel
命令的產出是一個創世區塊-<your_channel_name>.block
-這個創世區塊被儲存在peer節點的檔案系統中同時包含了在channel.tx的通道配置。 -
joinChannel
命令被4個peer節點執行,作為之前產生的genesis block的輸入。這個命令介紹了peer節點加入<your_channel_name>
以及利用<your_channel_name>.block
去建立一條鏈。 -
現在我們有了由4個peer節點以及2個組織構成的通道。這是我們的
TwoOrgsChannel
配置檔案。 -
peer0.org1.example.com
和peer1.org1.example.com
屬於Org1;peer0.org2.example.com
和peer1.org2.example.com
屬於Org2 -
這些關係是通過crypto-config.yaml定義的,MSP路徑在docker-compose檔案中被指定。
-
Org1MSP(
peer0.org1.example.com
)和Org2MSP(peer0.org2.example.com
)的anchor peers將在後續被更新。我們通過攜帶channel的名字傳遞Org1MSPanchors.tx
和Org2MSPanchors.tx
配置到排序服務來實現anchor peer的更新。 -
一個鏈碼-
chaincode_example02
被安裝在peer0.org1.example.com
和peer0.org2.example.com
-
這個鏈碼在
peer0.org2.example.com
被例項化。例項化過程將鏈碼新增到通道上,並啟動peer節點對應的容器,並且初始化和鏈碼服務有關的鍵值對。示例的初始化的值是[”a“,”100“,”b“,”200“]
。例項化的結果是一個名為dev-peer0.org2.example.com-mycc-1.0
的容器啟動了。 -
例項化過程同樣為背書策略傳遞相關引數。策略被定義為
-P "OR ('Org1MSP.member','Org2MSP.member')"
,意思是任何交易必須被Org1或者Org2背書。 -
一個針對
a
的查詢發往peer0.org1.example.com
。鏈碼服務已經被安裝在了peer0.org1.example.com
,因此這次查詢將啟動一個名為dev-peer0.org1.example.com-mycc-1.0
的容器。查詢的結果也將被返回。沒有寫操作出現,因此查詢的結果的值將為100
。 -
一次
invoke
被髮往peer0.org1.example.com
,從a
轉移10
到b
。 -
然後鏈碼服務被安裝到
peer1.org2.example.com
-
一個
query
請求被髮往peer1.org2.example.com
用於查詢a
的值。這將啟動第三個鏈碼服務名為dev-peer1.org2.example.com-mycc-1.0
。返回a
的值為90,正確地反映了之前的交易,a
的值被轉移了10。