在剛接觸fabric的時候一般都是直接跟着wiki的教程一步步安裝配置,執行一系列命令,最終將其運行起來,但很多人對其中的運行流程及其基礎知識點可能不是很了解。基於此今天我將以$FABRIC_ROOT/examples/e2e_cli/ 經典Demo為例來分享一些我的理解,希望可以對入門者有所幫助。
生成證書
fabric是有准入門檻的聯盟鏈,通過MSP服務來進行對其中的成員進行統一管理。既然提到了MSP,那就肯定離不開證書這一概念。證書的作用一方面是用於驗證消息的簽名是否有效從而驗證交易是否有效,另一方面可以用於確認該證書的擁有者身份。
所以要運行起整個fabric網絡首先得生成證書,生成證書的配置文件在crypto-config.yaml中,根據自己的需求定義好OrdererOrgs和PeerOrgs信息,之后在generateArtifacts.sh腳本中執行generateCerts方法即可在當前目錄下生成包含證書文件的crypto-config目錄。
ordererOrganizations
example.com
ca # 包含給Orderer組織頒發MSP證書的ca的公私鑰
msp # 包含Orderer組織的msp相關證書(admincerts,cacerts,tlscacerts)
orderers
orderer.example.com
msp
admincerts # 管理員證書
cacerts # 給Orderer組織頒發MSP證書的ca的證書
keystore # 當前Orderer組織的私鑰
signcerts # 當前Orderer組織的證書(包含公鑰)
tlscacerts # 給Orderer組織頒發TLS證書的ca的證書
tls
ca.crt # 給Orderer組織頒發TLS證書的ca的證書
server.crt # 當前Orderer組織的tls證書(包含公鑰)
server.key # 當前Orderer組織的tls私鑰
tlsca # 包含給Orderer組織頒發TLS證書的ca的公私鑰
users # 包含Orderer下普通用戶和管理員用戶的msp和tls證書
以上是以Orderer組織為例說明了下生成的證書目錄層級結構及其對應的目錄或文件的含義,Peer組織的類似。
TLS(Transport Layer Security Protocol)是Https建立在SSL 3.0之上的一個標准的安全傳輸層協議。負責安全通信,安全傳輸數據包。需要做數字簽名的認證才能正常的去繼續做http的握手然后再做交互。
MSP(Membership Service Provider)是負責成員是否被認證過進入我們這個網絡里的安全管理
生成genesis.block
證書生成好之后接下來就可以定義Orderer的配置以生成genesis.block了。該配置在configtx.yaml中的Profiles.TwoOrgsOrdererGenesis下。
TwoOrgsOrdererGenesis:
Capabilities:
<<: *ChannelCapabilities
Orderer:
<<: *OrdererDefaults
Organizations:
- *OrdererOrg
Capabilities:
<<: *OrdererCapabilities
Consortiums:
SampleConsortium:
Organizations:
- *Org1
- *Org2
*OrdererDefaults:引用包含了Orderer的基本信息如下
- OrdererType(共識類型)是solo還是kafka。solo就是一個模擬kafka的本地的單機的文件系統實現的消息隊列,缺點是在執行速度和效率上肯定不如kafka,測試環境一般就用solo,生產環境用kafka。kafka目前是通過消息隊列保證所有的節點對transaction的時間有一個共識,並沒有具體的像比特幣之類的pow共識算法,以前的0.6版本有pbft算法,但1.0以后還沒有實現。
- Addresses:Orderer服務的地址列表
- BatchTimeout:Orderer節點的出塊時間
- BatchSize:區塊大小包含最大交易筆數(MaxMessageCount),最大區塊大小(AbsoluteMaxBytes)以及建議區塊大小(PreferredMaxBytes)
- Kafka:包含brokers列表。當設置了OrdererType為kafka才生效,如果是solo則該配置不生效。
*OrdererOrg:引用包含了OrdererOrg的MSP信息
- Name:OrdererOrg
- ID:Orderer的MSPID
- MSPDir:Orderer組織的MSP目錄(就是上面生成的msp目錄)
*Org1 同OrdererOrg引用一樣
*Org2 同OrdererOrg引用一樣
綜上,通過這些配置生成genesis.block之后,Orderer服務就會明確所使用的共識類型,服務地址列表,出塊時間,出塊大小。同時也就擁有了Orderer節點MSPID和MSP證書(包含Orderer的管理員證書,Orderer的CA證書,Orderer的TLS CA證書),以及聯盟里面的所有Org(這里是Org1和Org2)的MSPID和MSP證書(包含Org的管理員證書,Org的CA證書,Org的TLS CA證書),待整個fabric網絡運行起來之后Orderer服務便可以利用這些CA證書很容易的驗證節點傳過來的證書是否有效。
生成通道配置交易
Orderer配置好之后,同樣通過configtx.yaml中的Profiles.TwoOrgsChannel配置信息來生成一個通道配置類型的交易(ConfigUpdateEnvelope)。
TwoOrgsChannel:
Consortium: SampleConsortium
Application:
<<: *ApplicationDefaults
Organizations:
- *Org1
- *Org2
Capabilities:
<<: *ApplicationCapabilities
啟動網絡
在e2e_cli這個Demo項目里面我們是通過Docker的方式來運行fabric網絡的。正常我們的docker,比如在我們本地已經build出了很多docker image,比如我們有hyperledger/fabric-peer,如果想讓docker image運行起來,一般都是通過docker run這樣的命令,比如我單獨去run一個peer,docker run + 這個docker image的名字,然后加一些參數就啟動了一個docker container,docker container運行了這個docker image的環境。如果有多個image,我們手動的一個個去啟動太麻煩了,我們想有一個配置文件,能讓批量的很多很多的節點一起啟動,那這個功能就引出了docker-compose。簡單說,docker-compose就是把多個docker image啟動的定義和配置組合在一起放在一個文件里一起啟動起來。
# 啟動fabric網絡所需要的所有Docker Container並在后台掛起
docker-compose -f docker-compose-cli.yaml up -d
# 進入container_name為 orderer.example.com 的Docker Container
docker exec -it orderer.example.com bash
# 查看docker日志
docker logs -f containerID/containerName
docker logs -f orderer.example.com
正常情況下在docker-compose-cli.yaml里面名為“cli”的docker container在一運行起來以后就會執行腳本scripts/script.sh,該腳本中包含了創建通道、加入通道、更新錨節點、安裝chaincode、實例化chaincode、query/invoke chaincode等一系列操作,為了一步步進行,因此在啟動網絡前需要在docker-compose-cli.yaml中做如下修改
# 將名為“cli”的docker-container原來的命令注釋掉並改為如下
command: /bin/bash -c 'sleep 100000'
#command: /bin/bash -c './scripts/script.sh ${CHANNEL_NAME}; sleep $TIMEOUT'
操作網絡
通過docker-compose將fabric所需要的docker container都run起來之后,就可以通過 docker exec -it cli bash 進入相應的container,從而對fabric網絡進行操作。具體的操作命令在 scripts/script.sh 中都有,這里就不再贅述了。下面用一張圖來描述在對網絡進行一系列操作的過程中cli/sdk端、peer端、order端之間的交互過程。
說明:
- 如果在sdk/cli側設置 $CORE_PEER_TLS_ENABLED = TRUE,則需要且僅僅在Create Channel、UpdateAnchorPeers、Instantiate Chaincode、Invoke Chaincode的時候指定OrdererCA,該配置用於設置是否開啟TLS,TLS就是那個安全的SSL 3.0的時候安全的一個認證方式,相當於在數據傳輸之前做一個安全的認證,這里只是判斷它要不要做安全認證。
- 在fabric network中,orderer側其實也會保存有自己的區塊鏈也就是ledger,而剩下所有的Organization中的所有的peer側都會分別維護一個ledger和一個state db,圖中為了簡潔沒有文字標出,這里做下解釋。
- peer節點的本地賬本保存位置為:/var/hyperledger/production/ledgerData/chains/chains/mychannel
- orderer里面的mychannel目錄是orderer這邊來存放transaction和block的位置,所有的transaction都要提交到orderer這邊讓orderer做一個transaction的排序,排序好之后orderer
會把block分發下去給每一個Org的主節點(leader peer)節點去同步,所以orderer本地也是存在一個block的鏈(賬本)的,保存位置為:/var/hyperledger/production/orderer/chains/mychannel。 - 這里所說的查看peer和orderer的賬本路徑前提是要進入到其對應的docker container中。
實例化過程
fabric網絡啟動好,創建channel,加入channel,安裝chaincode之后必須實例化chaincode才可以進行query/invoke操作,而instantiate chaincode這一過程也是整個過程中花時間最久的,好多新入門的伙伴在這一塊也容易混淆,所以這里單獨摘出來分享一下。
chaincode的instantiate過程這樣的。首先peer節點需要對chaincode做編譯,它會在fabric-ccenv環境里面把chaincode build,利用fabric-ccenv創建一個新的docker container並把chaincode裝載進去,chaincode在這個新的docker container里面運行起來,chaincode首先會去到peer節點去注冊一下,然后peer節點會允許它注冊成功,peer節點做初始化,調用chaincode的init方法,之后等待別人調用。由於他們隔離在不同的container里面,之后chaincode和peer一直都會有一個keepalive的長鏈接(互相發送數據包)來保護他們之間的鏈接不被斷開。
說明:
- 在一個channel中同一個chaincode只需要做一次instantiate就可以了,其它的節點只需要安裝了就可以不需要再次實例化,當cli/sdk去調用到其它節點的chaincode時候,它會自動的在被調用的時候去做一次instantiate chaincode並把它裝載到一個新的container里面運行起來。
- chaincode是由peer觸發去build的,build好之后chaincode被裝載到一個新的container運行,它的整個生命周期是由peer管理的,peer在管理chaincode的時候通過一個叫lifecycle的系統chaincode(lscc)來管理我們裝載的用戶chaincode,所以需要模擬去install一下chaincode,讓peer知道有一個新的chaincode來了,peer知道去管理它的生命周期。
- chaincode運行階段是一個endorsement背書模擬執行的階段,它是在跟peer相同的機器上執行,peer創建一個新的container,然后裝載chaincode來執行相應的方法。
補充知識點
1、MSP證書解釋
- admincerts:管理員證書,它比普通的peer0證書有一些特殊的權限,比如對節點的修改或者配置等操作
- cacerts:里面放的是對這個peer0頒發證書的ca是誰,里面放的是ca的公鑰
- keystore:是peer0這個節點msp的自己的私鑰
- signcerts:里面放的是這個organization的ca(ca.org1.example.com-cert.pem)給peer0頒發的證書
- tlscacerts:里面放的是對這個peer0辦法TLS證書的ca是誰,里面放的是TLS ca的公鑰
- admincerts和signcerts都是簽發之后的證書,只是他們的角色不同,admincerts對peer0有一些特殊的管理權限,但signcerts只是一個普通的certs
2、TLS證書解釋
- ca.crt:TLS安全認證過程的時候驗證證書的ca
- server.crt:節點本身的TLS證書
- server.key:節點本身的TLS私鑰
3、命令行查看證書內容
openssl x509 -in peer0.org1.example.com-cert.pem -text
4、如果在當前的某個Organization中加入一個新的peer節點,則不需要更新orderer排序服務的配置,只需要給peer用所屬Organization的rootca給其頒發一套證書即可;而當新加入一個新的Organization的時候我們需要更新orderer排序服務的配置。即新的Organization它的root ca是什么(msp的root ca是什么,tls的root ca是什么),然后我們拿它去驗證一個成員在不在這個Organization里面
5、fabric-ca的作用是encroll注冊,准入,通過name和org去獲得token,以后訪問就用token訪問,跟msp證書是兩回事。token認證既不是msp認證,又不是tls認證
6、利用configtxlator工具查看genesis.block內容,其實它就是一個common.Block(protos/common/common.pb.go)格式的結構體序列化以后生成的文件,所以反序列化的時候需要用common.Block才能把它解開,具體步驟如下
vagrant@hyperledger-devenv:523f644:/opt/gopath/src/github.com/hyperledger/fabric/release/linux-amd64/bin$ ./configtxlator start
2018-05-01 09:32:12.726 UTC [configtxlator] startServer -> INFO 001 Serving HTTP requests on 0.0.0.0:7059
configtxlator start 啟動工具服務
http://127.0.0.1:7059/protolator/decode/common.Block
7、如果想要更改peer的功能,則在修改完peer部分的代碼之后需要在$FABRIC_HOME下重新執行maker docker命令以生成新的fabric-peer鏡像
8、fabric-baseos鏡像是在peer節點在編譯chaincode的時候它需要baseos作為編譯環境里的一個os的基礎
9、balance-transfer是一個完整的使用了fabric-node-sdk的一個client端,它能跟區塊鏈peer,orderer做交互,它可以去配置orderer,創建channel,它可以去配置peer,讓peer節點加入channel,都是可以做的。可以理解為之前通過CLI可以做的所有任務,在sdk下都可以完成,而且功能更強大,因為sdk是可編程的。
10、數字證書包含了證書原文、加密哈希算法以及ca私鑰簽名后的證書密文三部分內容。在驗證數字證書的有效性時只需要知道該證書的頒發組織/機構(CA)的公鑰即可。另外PKI體系中的公私鑰非對稱加密算法公鑰解密的場景只有在一種情況下會發生,就是在數字證書有效性校驗/數字簽名驗簽的時候。