Hyperledger Fabric 手動搭建
前面我們學習了區塊鏈是什麼、還有自動搭建學習東西我們就要從簡單到深入(入門到放棄),現在自動部署已經跑通了接下來就是手動搭建Fabric 網路可以更好的理解為什麼要這麼做。
使用cryptogen(密碼生成器)和configtxgen(配置交易生成器)手動生成證書/金鑰和各種配置構件(等同於執行./byfn.sh generate)
- 金鑰生成器 cryptogen
- cryptogen 工具為我們的網路實體生成各種加密材料( x509 證書和簽名祕鑰)。這些證書是身份的代表,在實體之間通訊和交易的時候,它們允許對身份驗證進行簽名和驗證
- crypto-config.yaml,為所有組織和屬於這些組織的元件生成一組證書和祕鑰。每一個組織被分配一個唯一的根證書(ca-cert),它繫結該組織的特定元件(Peer 節點和排序節點)。通過為每個組織分配一個唯一的 CA 證書,我們模擬了一個典型的網路,網路中的成員可以使用它自己的證書授權中心。Fabric 中的事務和通訊由一個實體的私鑰(keystore)簽名,然後通過公鑰(signcerts)驗證。
# crypto-config.yaml 檔案結構
OrdererOrgs: #定義一個Order組織
- Name: Orderer #order節點的名稱,當前網路模式為solo型別,所以只定義了一個Order節點
Domain: example.com #order節點的域
Specs: #暫時用不到
- Hostname: orderer
- Hostname: orderer2
- Hostname: orderer3
- Hostname: orderer4
- Hostname: orderer5
PeerOrgs: #定義Peer組織
- Name: Org1 #宣告Peer組織名稱為Org1
Domain: org1.example.com #Org1組織的域
EnableNodeOUs: true #暫時沒搞清楚該欄位的意義
Template: #在這裡可以定義所生成的Org1組織中的Peer節點證書數量,不包括Admin
Count: 2 #表明需要生成兩個Peer節點的證書,如果需要其他數量的Peer節點,只需要更改這裡的數量。
Users: #在這裡可以定義所生成的Org1組織中型別為User的證書數量,不包括Admin
Count: 1 #生成使用者的證書的數量
- Name: Org2 #宣告第二個Peer組織名稱為Org2,如果需要更多的Peer組織證書,只需要按該模板新增即可。
Domain: org2.example.com #與以上相同
EnableNodeOUs: true
Template:
Count: 2
Users:
Count: 1
- 配置交易生成器 configtxgen
- 使用configtxgen工具生成系統通道的創世區塊,並將系統的配置操作(建立通道,設定某組織的錨節點等)作為系統事務生成提交到系統通道的事務檔案(.tx),配置檔案為configtx.yaml,生成的配置元件位於channel-artifacts目錄下、分別為:genesis.block,channel.tx,Org1MSPanchors.tx,Org2MSPanchors.tx,genesis.block為系統通道的創世區塊,後三者分別為建立通道,設定組織一、組織二的錨節點的事務,這些配置操作作為系統事務提交到系統通道中。
# 會根據crypto-config.yaml檔案配置生成兩個錨節點交易,一個對應一個Peer組織
cryptogen generate --config=./crypto-config.yaml
#生成系統通道創世區塊genesis.block生成的配置元件位於channel-artifacts目錄下
configtxgen -profile SampleMultiNodeEtcdRaft -channelID byfn-sys-channel -outputBlock ./channel-artifacts/genesis.block
#通過環境變數設定通道名稱
export CHANNEL_NAME=mychannel
#建立 通道配置 事務
configtxgen -profile TwoOrgsChannel -outputCreateChannelTx ./channel-artifacts/channel.tx -channelID $CHANNEL_NAME
#建立 更新組織Org1在該通道上的錨節點(錨節點為某組織對order可見的節點) 的事務
configtxgen -profile TwoOrgsChannel -outputAnchorPeersUpdate ./channel-artifacts/Org1MSPanchors.tx -channelID $CHANNEL_NAME -asOrg Org1MSP
#建立 更新組織Org2在該通道上的錨節點 的事務
configtxgen -profile TwoOrgsChannel -outputAnchorPeersUpdate ./channel-artifacts/Org2MSPanchors.tx -channelID $CHANNEL_NAME -asOrg Org2MSP
啟動網路,建立並加入通道,更新組織錨節點,安裝、定義並呼叫一個鏈程式碼(等同於執行./byfn.sh up)
#啟動fabric網路 -d用於不顯示網路的實時日誌,若想檢視日誌流,則後續命令需要開啟另一個終端來執行
#首先將first-network目錄下的docker-compose-cli.yaml檔案中cli容器配置資訊中的FABRIC_LOGGING_SPEC=INFO修改為FABRIC_LOGGING_SPEC=DEBUG以看到更多的執行過程資訊
docker-compose -f docker-compose-cli.yaml -f docker-compose-etcdraft2.yaml up -d
啟動網路之後我們可以看到docker啟動的容器
進入容器 建立並加入通道,並指定(更新)組織的錨節點
#進入cli容器內部
docker exec -it cli bash
#配置CLI容器作為peer0.org1.example.com節點執行命令的環境變數
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
#以環境變數形式設定通道名稱,必須全部小寫,長度小於250個字元,並與正規表示式[a-z][a-z0-9.-]*匹配
export CHANNEL_NAME=mychannel
#將通道配置事務傳送給order節點以建立通道,指定order節點的證書以進行TLS握手,執行結束後該節點將收到來自order節點的對應於所建立通道的創世區塊$CHANNEL_NAME.block
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
#將peer0.org1.example.com加入通道,注意命令中的$CHANNEL_NAME.block,根據通道名稱而變化
peer channel join -b mychannel.block
#指定peer0.org1.example.com作為組織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
#配置CLI容器作為peer0.org2.example.com節點執行命令的環境變數
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
#將peer0.org2.example.com加入通道,注意命令中的$CHANNEL_NAME.block,根據通道名稱而變化
peer channel join -b mychannel.block
#指定peer0.org2.example.com作為組織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
#下載安裝並定義一個鏈程式碼
peer lifecycle chaincode package mycc.tar.gz --path github.com/hyperledger/fabric-samples/chaincode/abstore/go/ --lang golang --label mycc_1
#安裝鏈碼
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
#安裝鏈碼
peer lifecycle chaincode install mycc.tar.gz
#查詢已安裝的鏈碼
peer lifecycle chaincode queryinstalled
#後續命令將需要鏈碼包的ID,因此我們將它儲存為一個環境變數,這個ID是動態的(上面查詢出來的)
CC_PACKAGE_ID=mycc_1:3a8c52d70c36313cfebbaf09d8616e7a6318ababa01c7cbe40603c373bcfe173
#制定鏈碼初始化鏈碼TLS後面的命令是要許可權才能初始化
#通道中的組織需要就鏈碼的定義達成一致,以下命令用於批准一個chaincode定義,--init-required用於初始化chaincode時使init函式被呼叫,--package-id指定鏈碼包的ID,我們還可以提供--signature-policy或--channel-config-policy引數來設定chaincode背書策略,若未提供將使用預設設定-大多數通道成員背書,這種情況下若在該渠道中新增或刪除新組織,背書策略將自動更新,以要求更多或更少的背書。在本例中,預設策略將需要來自屬於Org1和Org2的peer的背書(即兩個背書)
peer lifecycle chaincode approveformyorg --channelID $CHANNEL_NAME --name mycc --version 1.0 --init-required --package-id $CC_PACKAGE_ID --sequence 1 --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
#更改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 lifecycle chaincode install mycc.tar.gz
#制定鏈碼初始化鏈碼TLS後面的命令是要許可權才能初始化
#通道中的組織需要就鏈碼的定義達成一致,以下命令用於批准一個chaincode定義,--init-required用於初始化chaincode時使init函式被呼叫,--package-id指定鏈碼包的ID,我們還可以提供--signature-policy或--channel-config-policy引數來設定chaincode背書策略,若未提供將使用預設設定-大多數通道成員背書,這種情況下若在該渠道中新增或刪除新組織,背書策略將自動更新,以要求更多或更少的背書。在本例中,預設策略將需要來自屬於Org1和Org2的peer的背書(即兩個背書)
peer lifecycle chaincode approveformyorg --channelID $CHANNEL_NAME --name mycc --version 1.0 --init-required --package-id $CC_PACKAGE_ID --sequence 1 --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
#一旦足夠多的通道成員組織批准了chaincode定義,一個成員組織就可以將定義提交給通道。可以通過發出以下查詢來檢查chaincode定義是否已準備好提交,並檢視當前組織的批准情況
#檢視各組織對chaincode定義的批准狀況
peer lifecycle chaincode checkcommitreadiness --channelID $CHANNEL_NAME --name mycc --version 1.0 --init-required --sequence 1 --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 --output json
#一旦就鏈碼定義達成一致,把兩個組織中的鏈碼提交到order組織--通知給其他節點我加入了
peer lifecycle chaincode commit -o orderer.example.com:7050 --channelID $CHANNEL_NAME --name mycc --version 1.0 --sequence 1 --init-required --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 --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
#呼叫chaincode 將--isInit標誌傳遞給鏈碼的第一次呼叫,並將引數提供給Init函式。第一個呼叫將啟動chaincode容器。我們可能需要等待容器啟動。(確保通道名稱和鏈碼名稱正確)
peer chaincode invoke -o orderer.example.com:7050 --isInit --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":["Init","a","100","b","100"]}' --waitForEvent
#查詢chaincode
peer chaincode query -C $CHANNEL_NAME -n mycc -c '{"Args":["query","a"]}'
#呼叫鏈碼的invoke函式,a向b轉賬十元
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"]}' --waitForEvent
#注:若通道成員組織的其它節點想和區塊鏈網路進行互動,只需要加入通道並安裝鏈碼包即可,而不需要提交鏈碼定義(每個組織批准一次鏈碼定義即可)。