1. 程式人生 > >區塊鏈學習——HyperLedger-Fabric v1.0 啟動過程分析

區塊鏈學習——HyperLedger-Fabric v1.0 啟動過程分析

本章我們從fabric v1.0e2e_cli示例開始分析整個啟動過程以及在過程中的一些配置檔案

首先呢,還是確保你的基本環境已經搭建完成,v1.0原始碼和映象也都下載完畢

fabric啟動過程中的相關指令碼檔案解析

network_setup.sh指令碼檔案

在原始碼目錄下的network_setup.sh檔案是官方提供的快速部署測試的一個自動化指令碼,接下來我們看一下在啟動這個檔案時都做了什麼:

在上圖中我們只是截取了啟動函式,在這個函式中可以清楚的看出在啟動中呼叫了generateArtifacts.shdocker-compose-cli.yaml兩個檔案,這兩個檔案的作用分別是:

generateArtifacts.sh:生成所需的證書(crypto-config資料夾)和通道相關的配置檔案(channel-artifacts資料夾)
docker-compose-cli.yaml:描述的是這個示例網路的拓撲結構

generateArtifacts.sh指令碼檔案

我們繼續分析在network_setup.sh中呼叫generateArtifacts.sh檔案具體又做了什麼呢
generateArtifacts.sh中一共有3個函式:replacePrivateKey()generateCerts()generateChannelArtifacts()
generateCerts():


在上圖中可以看到這個函式使用工具cryptogen和crypto-config.yaml檔案來生成所需的證書檔案和公私鑰。
我們可以看一下crypto-config.yaml檔案:
Name和Domain是指該org的名字和域名,Template.Count是指該org中的節點數量,Users.Count是指該org中包含的user數量.

OrdererOrgs:
  - Name: Orderer
    Domain: example.com
    Specs:
      - Hostname: orderer
# ---------------------------------------------------------------------------
PeerOrgs:
  - Name: Org1
    Domain: org1.example.com
    Template:
      Count: 2
    Users:
      Count: 1
  # ---------------------------------------------------------------------------
  - Name: Org2
    Domain: org2.example.com
    Template:
      Count: 2
    Users:
      Count: 1

generateChannelArtifacts():

在上圖中可以看到這個函式使用工具configtxgen和configtx.yaml檔案來生成創世區塊以及通道相關的配置檔案。而configtx.yaml檔案裡主要是一些org的配置項資訊,如ID、Host、Port等,除此之外還指明瞭orderer的共識方式為solo等一些的基礎的配置項資訊。

docker-compose-cli.yaml指令碼檔案

docker-compose-cli.yaml檔案描述了這個示例網路的拓撲結構,如下,包含:

  • orderer:1個
  • org1:peer0(錨節點),peer1
  • org2:peer0(錨節點),peer1
  • cli:對上面的容器節點進行管理
  • 為什麼cli能夠對上面的容器進行管理呢?
    因為cli是經過網路中其他節點進行授權認可的,而認可的憑證就是公私鑰

#command: /bin/bash -c './scripts/script.sh ${CHANNEL_NAME}; sleep $TIMEOUT'
檔案中上面這一行是筆者故意註釋掉的,使docker-compose-cli.yaml檔案啟動時不會自動去執行script.sh指令碼,而這個指令碼就是自動建立、加入通道以及鏈碼相關操作的自動化指令碼,而在下面,我們將自己動手來一步步完成這些步驟,從而加深對fabric啟動過程的理解。

version: '2'

services:

  orderer.example.com:
    extends:
      file:   base/docker-compose-base.yaml
      service: orderer.example.com
    container_name: orderer.example.com

  peer0.org1.example.com:
    container_name: peer0.org1.example.com
    extends:
      file:  base/docker-compose-base.yaml
      service: peer0.org1.example.com

  peer1.org1.example.com:
    container_name: peer1.org1.example.com
    extends:
      file:  base/docker-compose-base.yaml
      service: peer1.org1.example.com

  peer0.org2.example.com:
    container_name: peer0.org2.example.com
    extends:
      file:  base/docker-compose-base.yaml
      service: peer0.org2.example.com
  peer1.org2.example.com:
    container_name: peer1.org2.example.com
    extends:
      file:  base/docker-compose-base.yaml
      service: peer1.org2.example.com

  cli:
    container_name: cli
    image: hyperledger/fabric-tools
    tty: true
    environment:
      - GOPATH=/opt/gopath
      - CORE_VM_ENDPOINT=unix:///host/var/run/docker.sock
      - CORE_LOGGING_LEVEL=DEBUG
      - CORE_PEER_ID=cli
      - CORE_PEER_ADDRESS=peer0.org1.example.com:7051
      - CORE_PEER_LOCALMSPID=Org1MSP
      - CORE_PEER_TLS_ENABLED=true
      - CORE_PEER_TLS_CERT_FILE=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org1.example.com/peers/peer0.org1.example.com/tls/server.crt
      - CORE_PEER_TLS_KEY_FILE=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org1.example.com/peers/peer0.org1.example.com/tls/server.key
      - 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
    working_dir: /opt/gopath/src/github.com/hyperledger/fabric/peer
    #command: /bin/bash -c './scripts/script.sh ${CHANNEL_NAME}; sleep $TIMEOUT'
    volumes:
        - /var/run/:/host/var/run/
        - ../chaincode/go/:/opt/gopath/src/github.com/hyperledger/fabric/examples/chaincode/go
        - ./crypto-config:/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/
        - ./scripts:/opt/gopath/src/github.com/hyperledger/fabric/peer/scripts/
        - ./channel-artifacts:/opt/gopath/src/github.com/hyperledger/fabric/peer/channel-artifacts
    depends_on:
      - orderer.example.com
      - peer0.org1.example.com
      - peer1.org1.example.com
      - peer0.org2.example.com
      - peer1.org2.example.com

啟動e2e示例

接下來我們將實際動手啟動一下官方提供的示例:

生成證書以及金鑰

首先我們進入下載的fabric原始碼目錄/root/go/src/github.com/hyperledger/fabric,執行make cryptogen命令,生成cryptogen可執行程式,如有報錯,則在文章最後一部分有筆者自己遇到的錯誤,可自行檢視;

接下來進入cd examples/e2e_cli/目錄執行../../build/bin/cryptogen generate --config=./crypto-config.yaml,則會在本目錄下生成crypto-config資料夾,存放生成公私鑰和證書。

生成創世區塊以及通道相關的配置檔案

返回到fabric目錄,執行make configtxgen命令,生成configtxgen可執行程式

接下來還是進入cd examples/e2e_cli/目錄
生成創世區塊:

../../build/bin/configtxgen -profile TwoOrgsOrdererGenesis -outputBlock ./channel-artifacts/genesis.block

生成通道相關的配置檔案:

../../build/bin/configtxgen -profile TwoOrgsChannel -outputCreateChannelTx ./channel-artifacts/channel.tx -channelID mychannel

生成org1和org2錨節點所需的配置檔案:

../../build/bin/configtxgen -profile TwoOrgsChannel -outputAnchorPeersUpdate ./channel-artifacts/Org1MSPanchors.tx -channelID mychannel -asOrg Org1MSP
../../build/bin/configtxgen -profile TwoOrgsChannel -outputAnchorPeersUpdate ./channel-artifacts/Org2MSPanchors.tx -channelID mychannel -asOrg Org2MSP

執行完上述命令後,再執行tree channel-artifacts/(需安裝tree命令yum install tree),可以看見如下圖生成的檔案的目錄結構:

啟動

啟動所需的一切都準備完畢,接下來我們啟動fabric網路

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

另起一個終端,執行docker ps,可以看到如下圖,啟動了1個orderer,4個peer(分屬2個org),1個cli

建立通道

進入cli容器:docker exec -it cli bash
為了方便接下來我們的操作,先設定一些環境變數:

export ORDERER_CA=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/ordererOrganizations/example.com/orderers/orderer.example.com/msp/tlscacerts/tlsca.example.com-cert.pem
export CHANNEL_NAME=mychannel

建立通道:

peer channel create -o orderer.example.com:7050 -c $CHANNEL_NAME -f ./channel-artifacts/channel.tx --tls true --cafile $ORDERER_CA

執行完該命令後系統會打印出下圖,並且會在cli中生成1個mychannel.block檔案,在後續中,其他的節點想要加入我們建立的這個通道,就必須使用這個檔案。

將節點加入通道

  • docker-compose-cli.yaml檔案中其實指明瞭啟動時就預設連線的是org1.peer0節點,所以直接將其加入通道即可
peer channel join -b $CHANNEL_NAME.block

執行結果如下:

  • 在這裡我們只是將org1.peer0節點加入了mychannel這個通道,同樣我們再將org1.peer1節點也加入通道,不過這裡就需要修改環境變數,使其指向我們需要加入通道的節點後,再將節點加入通道。
export CORE_PEER_LOCALMSPID="Org1MSP"
export 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
export CORE_PEER_MSPCONFIGPATH=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org1.example.com/users/Admin\@org1.example.com/msp
export CORE_PEER_ADDRESS=peer1.org1.example.com:7051

peer channel join -b $CHANNEL_NAME.block

執行結果如下:

  • org2.peer0節點加入通道:
export CORE_PEER_LOCALMSPID="Org2MSP"
export 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
export CORE_PEER_MSPCONFIGPATH=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org2.example.com/users/Admin\@org2.example.com/msp
export CORE_PEER_ADDRESS=peer0.org2.example.com:7051

peer channel join -b $CHANNEL_NAME.block

執行結果如下:

  • org2.peer1節點加入通道:
export CORE_PEER_LOCALMSPID="Org2MSP"
export 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
export CORE_PEER_MSPCONFIGPATH=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org2.example.com/users/Admin\@org2.example.com/msp
export CORE_PEER_ADDRESS=peer1.org2.example.com:7051

peer channel join -b $CHANNEL_NAME.block

執行結果如下:

更新錨節點

錨節點的作用是為了方便組織(org)之間的通訊,1個組織(org)可以擁有1個或多個錨節點負責與其他組織進行通訊,然後將結果同步到其他節點。
更新org1的錨節點org1.peer0,首先連線到org1.peer0再執行更新

export CORE_PEER_LOCALMSPID="Org1MSP"
export 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
export CORE_PEER_MSPCONFIGPATH=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org1.example.com/users/Admin\@org1.example.com/msp
export CORE_PEER_ADDRESS=peer0.org1.example.com:7051

peer channel update -o orderer.example.com:7050 -c $CHANNEL_NAME -f ./channel-artifacts/Org1MSPanchors.tx --tls true --cafile $ORDERER_CA

更新org2的錨節點org2.peer0,首先連線到org2.peer0再執行更新

export CORE_PEER_LOCALMSPID="Org2MSP"
export 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
export CORE_PEER_MSPCONFIGPATH=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org2.example.com/users/Admin\@org2.example.com/msp
export CORE_PEER_ADDRESS=peer0.org2.example.com:7051

peer channel update -o orderer.example.com:7050 -c $CHANNEL_NAME -f ./channel-artifacts/Org2MSPanchors.tx --tls true --cafile $ORDERER_CA

部署測試鏈碼

在上上一步中我們已經將org1和org2的一共4個peer都加入名為mychannel的這個通道,接下來我們開始安裝鏈碼,此時我們在上一步命令執行結束後仍連線的是org2.pee1節點,因為鏈碼安裝時並沒有產生交易,因此是不會影響通道內的其他節點,可以說鏈碼安裝其實是一個本地化操作,所以,如果我們想在不同的節點中呼叫鏈碼的話,就需要安裝4次鏈碼(因為我們目前只有4個節點)

  • 安裝鏈碼:
peer chaincode install -n mycc -v 1.0 -p github.com/hyperledger/fabric/examples/chaincode/go/chaincode_example02

執行結果如下:

  • 例項化鏈碼(-o:指定orderer的地址)
    鏈碼例項化其實可以看作是一筆特殊的交易,鏈碼在某個節點例項化以後,其資訊就會被廣播到通道內的所有節點,如果另外1個節點又再一次對這個鏈碼例項化的話就會衝突。
peer chaincode instantiate -o orderer.example.com:7050 --tls true --cafile $ORDERER_CA -C $CHANNEL_NAME -n mycc -v 1.0 -c '{"Args":["init", "a", "100", "b", "200"]}' -P "OR        ('Org1MSP.member', 'Org2MSP.member')"
  • 呼叫鏈碼
    上面一步我們的鏈碼例項化已經完成,初始時a賬戶100元,b賬戶200元,我們先查詢一下a的餘額,驗證一下
peer chaincode query -C $CHANNEL_NAME -n mycc -c '{"Args":["query", "a"]}'

執行結果如下:

接下來我們呼叫鏈碼使a給b轉賬50元

peer chaincode invoke -o orderer.example.com:7050 --tls true --cafile $ORDERER_CA -C $CHANNEL_NAME -n mycc -c '{"Args":["invoke", "a","b","50"]}'

執行結果如下:

現在我們需要在另外1個節點org1.peer0上查詢org2.peer1節點上發生的交易是否成功
需要先連線到org1.peer0上,需要再一次安裝鏈碼,但不需要例項化

export CORE_PEER_LOCALMSPID="Org1MSP"
export 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
export CORE_PEER_MSPCONFIGPATH=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org1.example.com/users/Admin\@org1.example.com/msp
export CORE_PEER_ADDRESS=peer0.org1.example.com:7051

peer chaincode install -n mycc -v 1.0 -p github.com/hyperledger/fabric/examples/chaincode/go/chaincode_example02

再一次安裝完鏈碼後我們呼叫鏈碼查詢a的餘額

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

執行結果如下:

最後我們檢視正在執行中的容器,可以看到如下:

錯誤

  1. 執行make cryptogen命令如有報錯

    解決方案:yum install libtool-ltdl-devel


最後呢,說明一下,作者也是剛入坑的小白,這篇文章也就是分享一下個人的理解,方便以後檢視。如果對你有幫助的話,非常榮幸,如果有不對的地方,歡迎留言指正!

參考文章

部落格園深藍居