Building you first network
網絡結構:
2個Orgnizations(每個Org包含2個peer節點)+1個solo ordering service
打開fabric-sample下的示例first-network
其中byfn.sh為啟動這個網絡的啟動腳本,啟動腳本中除建立一個包含4個節點和1個Order service的網絡外,還會啟動一個容器用來執行腳本在channel中加入節點,部署和初始化chaincode,以及在部署的chaincode上執行交易。
啟動腳本
第一步,生成必要文件,執行命令:
默認channel名稱為mychannel
上述是否繼續選擇y,腳本程序會給網絡實例生成數字證書和密鑰;生成genesis block用來啟動ordering service;一些用來配置channel的配置交易
1、生成數字證書和密鑰
2、生成genesis block
3、生成channel配置交易
4、生成anchor peer update for Org1MSP
5、生成anchor peer update for Org2MSP
執行上述命令后,查看證書目錄:
2、第二步,啟動網絡,執行命令./byfn.sh -m up
上圖顯示在一個節點上安裝chaincode所配置的環境變量,其中配置了節點所擁有的證書信息。
執行結束后,終端顯示如下:
上述命令會啟動所有的containers,
上面通過腳本./byfn.sh生成了一個fabric網絡,接下來詳細說明腳本中所執行的命令信息:
1、Crypto Generator
cryptogen工具會對網絡節點生成證書信息,證書信息可以代表每一個實例節點,用於節點間通信和交易。
cryptogen使用的配置文件為crypto-config.yaml。配置文件中描述了網絡的拓撲結構同時會為Orgnizations和Orgnizations下的節點生成一系列的證書。每個Orgnization會有一個根證書ca-cert用來綁定特定節點(peer或者order)到該Orgnization。通過對每個Orgnization頒發一個唯一的數字證書,我們可以模仿典型的區塊鏈網絡,每個加入鏈的成員使用自己的數字證書進行獲取授權。交易和通信使用節點的私鈅,驗證使用節點的公鑰(數字證書)。配置文件里的count參數用來指定每個Orgnization的節點數量,本例子中一個Orgnization下面包含兩個節點,所以count的值在本例中設定為2。
在運行這個命令之前,我們快速的看一下crypto-config.yaml里的配置信息。特別關注OrderOrgs header下的Name,Domain和Specs幾個參數。
使用命令:
sed 's/^[ ]*#.*$//g' crypto-config.yaml > crypt.yaml
sed -i '/^$/d' crypt.yaml
去掉配置文件中的注釋部分如下:
網絡節點的命名規則為{Hostname}.{Domain}。以上述配置文件中order節點為例,order節點的命名為orderer.example.com,對應的MSP Id為Orderer。
運行cryptogen命令后,生成的數字證書和密鑰信息保存在crypto-config文件夾中。
Configuration Transaction Generation
配置交易生成工具:configtxgen 用來生成4個配置信息
orderer genesis block
fabric channel configuration transaction
2個anchor peer transaction (每個Peer Org生成一個)
orderer block是ordering service的起始block,channel配置交易文件在channel創建時廣播到orderer。anchor peer交易用來指定channel上每個Org的Anchor Peer。
configxgen的配置文件為configtx.yaml,其中包含對我們所創建的示例網絡的定義。配置文件包含3個角色,一個Orderer Org(OrderOrg)和兩個Peer Orgs(Org1和Org2)。配置文件也指定了一個組合SampleConsortium,包含2個Peer Org。打開配置文件,配置文件頂部Profiles部分有兩個唯一的headers。其中TwoOrgsOrderedGenesis用來配置orderer genesis block,TwoOrgChannel用來配置我們的channel。
上述配置文件中還包含兩個沒有特別意義的指定信息。第一個,我們為每一個Peer Org指定了Anchor Peer(peer0.org1.example.com和peer0.org2.example.com)。第二點,我們指定了每個角色的MSP路徑,從而允許我們把每個Org的根證書存儲在orderer genesis block中。這是一個重要的概念。現在每個節點和ordering service通信都需要驗證通過他們的數字證書。
運行cryptogen和configtxgen命令
可以手動運行上述兩個命令生成數字證書/密鑰或者生成配置交易。也可以通過修改腳本byfn.sh腳本實現上述目標。
手動生成證書和配置交易
可以參考byfn.sh腳本中的generateCerts函數理解生成網絡配置中數字證書的命令。為了便利,這里我們也提供了一種參考方法。
首先運行cryptogen工具。cryptogen命令在first network子目錄的bin目錄下,下面運行命令使用了該命令所在位置的相對路徑。
../bin/cryptogen generate --config=./crypto-config.yaml
也許你會遇到提示如下警告,直接忽略就可以
[bccsp] GetDefault -> WARN 001 Before using BCCSP, please call InitFactories(). Falling back to bootBCCSP.
接下來,我們需要告訴configtxgen工具引用哪里的配置文件configtx.yaml。這里我們通過設置環境變量來設定配置文件的路徑。
export FABRIC_CFG_PATH=$PWD
../bin/configtxgen -profile TwoOrgsOrdererGenesis -outputBlock ./channel-artifacts/genesis.block
你可以忽略掉關於intermediate certificates, certificate revocation lists (crls) and MSP configurations的警告信息,在本例中的網絡中,我們不會用到上述信息。
接下來,我們創建channel交易。確保替換$CHANNEL_NAME的值或者設置CHANNEL_NAME作為一個環境變量。創建命令如下:
export CHANNEL_NAME=mychannel
# this file contains the definitions for our sample channel
../bin/configtxgen -profile TwoOrgsChannel -outputCreateChannelTx ./channel-artifacts/channel.tx -channelID $CHANNEL_NAME
接下來,在我們創建的channel上定義Org1的Anchor Peer節點。執行命令為:
../bin/configtxgen -profile TwoOrgsChannel -outputAnchorPeersUpdate ./channel-artifacts/Org1MSPanchors.tx -channelID $CHANNEL_NAME -asOrg Org1MSP
在channel上定義Org2的Anchor Peer節點:
../bin/configtxgen -profile TwoOrgsChannel -outputAnchorPeersUpdate ./channel-artifacts/Org2MSPanchors.tx -channelID $CHANNEL_NAME -asOrg Org2MSP
啟動網絡
我們引用一個docker-compose腳本啟動網絡,docker-compose文件引用了我們之前下載的鏡像文件同時根據之前生成的genesis.block引導orderer。
working_dir: /opt/gopath/src/github.com/hyperledger/fabric/peer
# command: /bin/bash -c './scripts/script.sh ${CHANNEL_NAME}; sleep $TIMEOUT'
volumes
如果去掉注釋部分,網絡啟動時腳本會執行所有的CLI命令。這里我們手動的執行每一條命令,以便於我們了解命令的語法和功能。
給TIMEOUT參數傳遞一個相對較大的值(單位為秒);否則CLI容器默認會在60s后退出。
啟動網絡:
CHANNEL_NAME=$CHANNEL_NAME
TIMEOUT=<pick_a_value>
docker-compose -f docker-compose-cli.yaml up -d
如果你想實時查看執行上述命令的日志信息,那么去掉上面的-d選項(后台運行)。如果打開了上述日志流,那么你需要另外再打開一個終端用來執行CLI命令。
環境變量
為了在peer0.org1.example.com上執行下面的CLI命令,需要先配置下面4個環境變量。peer0.org1.example.com的這些變量我們已經在CLI容器中配置了,因此我們可以不用傳遞這些環境變量的值了。但是,如果你想發送命令到其他peer或者orderer,你需要提供這些變量相應的值。檢查docker-compose-base.yaml查看那指定的路徑。
# 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
執行docker exec命令進入CLI容器
docker exec -it cli bash
成功執行后,出現如下提示:
root@0d78bb69300d:/opt/gopath/src/github.com/hyperledger/fabric/peer#
之前,我們使用configtxgen工具生成了配置交易channel.tx。我們將會傳遞這個交易到orderer作為創建channel請求的一部分。
注意:--cafile選項是orderer的根證書存放在本地的路徑,該信息可以用來驗證TLS握手過程。
我們使用-c選項指定channel的名字,使用-f選項指定配置交易。在本例中為channel.tx,你也可以mount配置交易為一個不同的名字。(配置交易通過本地路徑mount到容器中)
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 replace the $CHANNEL_NAME variable appropriately
peer channel create -o orderer.example.com:7050 -c $CHANNEL_NAME -f ./channel-artifacts/channel.tx --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
這條命令返回一個genesis block <channel-ID.block>。該block可以用來加入channel時使用,block中包含了channel.tx中指定的配置信息。
你需要留在CLI容器中執行剩余的手動命令。如果發送命令的目標不是peer0.org1.example.com,那么要重新設置相應的環境變量。現在我們加入peer0.org1.example.com到channel中
# By default, this joins ``peer0.org1.example.com`` only
# the <channel-ID>.block was returned by the previous command
peer channel join -b <channel-ID.block>
你可以修改上邊4個環境變量的值為其他peer節點信息配置加入其他節點到channel中。
安裝和實例化chaincode
我們利用一個簡單的已寫好的chaincode。應用通過chaincode和區塊鏈的賬本進行交互,因此我們需要首先在每個peer節點上安裝chaincode用來執行交易和背書交易,然后在channel上實例化chaincode。
首先安裝例子go代碼到4個peer節點中的一個。這個命令會把go源碼放在peer節點的文件系統中。
peer chaincode install -n mycc -v 1.0 -p github.com/hyperledger/fabric/examples/chaincode/go/chaincode_example02
接下來,在channel上實例化chaincode。這將會在channel上初始化chaincode,為chaincode設置背書策略,為目標peer啟動一個chaincode容器。注意-P參數,這個參數指定了在該chaincode上一個交易被認可需要的背書級別。
接下來的命令中,我們設置-P參數為-P "OR ('Org0MSP.member','Org1MSP.member')"
。這表示我們需要
Org1
或者
Org2
中一個
peer
節點的背書。如果改變語法為
AND
,那么就需要兩個背書。
# be sure to replace the $CHANNEL_NAME environment variable
# 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 $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')"
上述命令中的mycc為上文中peer上安裝的chaincode的名稱。
下面查詢a的值,確認chaincode被正確的實例化,stateDB正常的運行。查詢的語法如下:
# be sure to set the -C and -n flags appropriately
peer chaincode query -C $CHANNEL_NAME -n mycc -c '{"Args":["query","a"]}'
現在從a轉移10到b。這個交易會產生一個新的區塊並更新stateDB。調用的語法是:
# be sure to set the -C and -n flags appropriately
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"]}'
現在再次查詢,查看上述轉移10的命令是否已經成功執行,執行的命令是:
# 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
下面描述docker-compose-cli.yaml文件中沒有注釋script.sh時的執行情況。去掉包含script.sh腳本執行的注釋,然后使用docker-compose命令再次啟動網絡。
1、Script.sh腳本在CLI容器里已經備份過,腳本執行createChannel命令根據設定的channel名字,使用channel.tx文件作為channel配置交易。
2、createChannel執行的輸出是一個genesis block-<your channel name>.block。輸出存儲在peer節點的文件系統上包含了channel.tx所指定的channel配置信息。
3、joinChannel命令被執行(4個peer節點),joinChannel命令使用上文生成的genesis block作為參數,該命令引導peer節點加入到<your channel name>並且建立一個以<your channel name>.block為起始的鏈。
4、目前我們建立了一個包含4個節點的channel,channel包含兩個orgnizations。類似TwoOrgsChannel文件的配置。
5、peer0.org1.example.com和peer1.org1.example.com屬於Org1;peer0.org2.example.com和peer1.org2.example.com屬於Org2
6、這些關系在crypto-config.yaml里定義,MSP的路徑在docker compose中指定
7、Org1MSP的Anchor Peer(peer0.org1.example.com)和Org2MSP的Anchor peer(peer0.org2.example.com)被更新。我們通過傳遞Org1MSPanchor.tx和Org2MSPanchor.tx以及channel的名字到ordering service來實現這一步。
8、將編寫好的chaincode_example02安裝在peer0.org1.example.com和peer0.org2.example.com上(這里並沒有安裝在所有peer上,而是僅安裝在anchor peer節點上,anchor peer節點之前每個Org設置了一個)
9、chaincode在peer0.org2.example.com上實例化。實例化過程添加chaincode到channel中,為目標peer啟動容器,同時初始化與chaincode相關的key-value鍵值對。本例中初始化的值為[“a”,”100” “b”,”200”]。實例化后會啟動一個容器dev-peer0.org2.example.com-mycc-1.0
。(
實例化過程發送至
peer0.
org2.example.com
上執行
)
10
、實例化過程也傳遞了一個背書策略的參數。背書策略類似形式:
-P "OR ('Org1MSP.member','Org2MSP.member')"
,代表任何交易必須被
Org1
或
Org2
的一個
peer
背書。
11
、在
peer0.org1.example.com
上執行查詢
a
的值。
chaincode
之前已經安裝在
peer0.org1.example.com
上了,因此查詢操作會為
Org1
的
peer0
節點啟動一個容器
dev-peer0.org1.example.com-mycc-1.0
。查詢結果也會返回回來,這個過程中沒有任何寫操作發生,所以
a
的值還是
100
。
12
、發送一個轉移賬戶金額的調用到
peer0.org1.example.com
,從
a
賬戶轉移
10
單位至
b
賬戶
13
、
chaincode
然后安裝在
peer1.org2.example.com
上
14
、發送查詢
a
賬戶操作至
peer1.org2.example.com
。這將啟動第三個
chaincode
容器
dev-peer1.org2.example.com-mycc-1.0
。返回金額
90
,說明之前帳號金額的轉移操作成功執行。
這說明了什么
為了在賬本上成功的執行讀寫操作,
chainc
ode
必須安裝在
peer
上。另外,
chaincode
容器直到實例化或者傳統交易
-
讀寫執行的時候(例:查詢
a
賬戶的值),
chaincode
容器才會啟動。
channel
中的每個節點都維護了賬本的完全復制,存儲了不可改變的、序列化的記錄區塊以及
state database
用於保存當前的
fabric
狀態。即便是那些沒有安裝
chaincode
的節點(例如
peer1.org1.example.com
)也會同步賬本。最終
chaincode
在安裝到
peer1.org1.example.com
后就可以被調用了,因為
chaincode
已經完成了實例化。
怎樣查看交易信息
查看
CLI docker
容器的日志信息
docker logs -f cli
可以看到交易的詳細過程
怎樣查看
chainc
ode
的日志
在每個
chaincode container
上可以查看當前
container
里所執行過的交易。具體查看命令如下:
docker logs dev-peer0.org2.example.com-mycc-1.0
docker logs dev-peer0.org1.example.com-mycc-1.0
docker logs dev-peer1.org2.example.com-mycc-1.0
理解
docker-compose
拓撲結構
BYFN
例子提供了兩種
docker-
compose
文件配置,每一種都是由
docker-compose-base.yaml
(文件存放在
base
文件夾中)文件拓展而來。第一個配置文件是
docker-compose-cli.yaml
,該配置文件配置了一個
CLI
容器,一個
orderer
,
4
個
peer
節點。使用該配置文件啟動可以實現本文中的所有操作指令。
第二種配置文件
docker-compose-e2e.yaml
是配置啟動一個使用
Node.js SDK
的點對點測試。這個配置文件的主要區別是包含了
fabric-ca-servers
容器。因此,我們可以使用
REST
接口實現向
CA
組織注冊和登記用戶。
如果你想使用
docker-compose-e2e.yaml
並且不先運行
byfn.sh
腳本,那么我們需要做
4
個微改動。我們需要設定
Organization CA
的私鈅。你可以設定這些值為你的
cryp
to-config
文件夾。例如設置
Org1
的私鈅路徑為:
crypto-config/peerOrganizations/org1.example.com/ca/
。私鈅文件是一個長
hash
值加上
_sk
組成。設定
Org2
的私鈅為
crypto-config/peerOrganizations/org2.example.com/ca/
另外
2
出改動是修改
docker-compose-e2e.yaml
中
ca0
和
ca1
配置中的
FABRIC_CA_SERVER_TLS_KEYFILE變量對應的值。需要指定
tls
證書所在的路徑。
按照一個簡單區塊鏈網絡的生成過程,制作執行過程如下:
執行步驟 |
執行命令和前置條件 |
生成必要信息 |
1、網路節點的證書文件 ../bin/cryptogen generate --config=./crypto-config.yaml 2、生成gensis block export FABRIC_CFG_PATH=$PWD ../bin/configtxgen -profile TwoOrgsOrdererGenesis -outputBlock ./channel-artifacts/genesis.block 3、生成channel.tx ../bin/configtxgen -profile TwoOrgsChannel -outputCreateChannelTx ./channel-artifacts/channel.tx -channelID $CHANNEL_NAME 4、生成anchor peer ../bin/configtxgen -profile TwoOrgsChannel -outputAnchorPeersUpdate ./channel-artifacts/Org1MSPanchors.tx -channelID $CHANNEL_NAME -asOrg Org1MSP |
創建channel |
peer channel create -o orderer.example.com:7050 -c $CHANNEL_NAME -f ./channel-artifacts/channel.tx 創建channel的命令由peer節點發起,使用上文生成的channel.tx,上述命令生成<channel_name>.block在當前文件夾中,該block中保存了channel.tx的信息。節點加入channel后,該區塊作為節點區塊鏈的第一個區塊。 |
加入peer節點到channel中 |
peer channel join -b $CHANNEL_NAME.block peer加入channel時使用創建channel時生成的block文件 加入哪個peer節點到channel中,需要通過在CLI容器中設置如下環境變量指定: 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 設置上述環境變量,加入peer0節點到channel中 |
更新Anchor peer |
peer channel update -o orderer.example.com:7050 -c $CHANNEL_NAME -f ./channel-artifacts/${CORE_PEER_LOCALMSPID}anchors.tx 使用configtxgen生成的anchor.tx文件 |
安裝chaincode |
peer chaincode install -n mycc -v 1.0 -p github.com/hyperledger/fabric/examples/chaincode/go/chaincode_example02 在CLI容器中設置環境變量指定在哪個peer節點上安裝chaincode |
在channel上實例化chaincode |
peer chaincode instantiate -o orderer.example.com:7050 --tls $CORE_PEER_TLS_ENABLED --cafile $ORDERER_CA -C $CHANNEL_NAME -n mycc -v 1.0 -c '{"Args":["init","a","100","b","200"]}' -P "OR ('Org1MSP.member','Org2MSP.member')" 需要設定環境變量指定在哪個peer節點上執行實例化chaincode命令 |
執行chaincode調用 |
|