????????使用docker服務搭建Hyperledger/fabric網絡的詳細教程,實現構建多節點的簡單聯盟鏈,并編寫、調用智能合約實現投票業務。
目錄
背景知識
?Hyperledger Fabric
?基本組件
交易(Transaction)
智能合約
實驗目的
實驗環境
基礎依賴
?安裝Golang
安裝docker
安裝基礎依賴包
以?root?戶的身份運?Docker
安裝docker-compose
搭建fabric環境
搭建測試網絡(可選)
chaincode 編寫
代碼下載
代碼投票
命令行投票
鏈碼部署 (deployCC)
環境變量設置
調用交易(invoke)
查詢投票(query)
背景知識
????????區塊鏈是一種分布式賬本技術,通過密碼學方法將數據區塊按時間順序連接形成鏈式結構。它具有去中心化、不可篡改、可追溯等特點。
-
公有鏈:完全開放,任何人可參與(如比特幣、以太坊)
-
聯盟鏈:需授權訪問,由多個組織共同維護(如Hyperledger Fabric)
-
私有鏈:單一組織完全控制
?Hyperledger Fabric
????????Hyperledger Fabric是Linux下的開源企業級區塊鏈平臺,專為商業應用設計,為聯盟鏈。將Blockchain的數據維護和共識服務進行分離,Orderer節點提供共識服務,實現多通道(channel)的結構。
????????特點:多chain和多channel;所謂的chain(鏈)實際上是包含Peer節點、賬本、ordering通道的邏輯結構,它將參與者與數據(包含chaincode在)進行隔離,一個peer節點也可以參與到多個chain中(通過接入多個channel)。
?基本組件
組件 | 作用 |
---|---|
Peer節點 | 維護賬本,執行鏈碼 |
Ordering節點 | 排序交易,生成區塊 |
CA(認證中心) | 頒發數字證書,身份認證 |
Channel(通道) | 數據隔離機制,ordering提供給peer的虛擬鏈路,保密性 |
交易(Transaction)
-
應用程序通過SDK發送請求道Peer節點(一個或多個)
-
peer節點分別執行交易(通過chaincode),但是并不將執行結果提交到本地的賬本中(可以認為是模擬執行,交易處于掛起狀態),參與背書的peer將執行結果返回給應用程序(其中包括自身對背書結果的簽名)
-
應用程序收集背書結果并將結果提交給Ordering服務節點
-
Ordering服務節點執行共識過程并生成block,通過消息通道發布給Peer節點,由peer節點各自驗證交易并提交到本地的賬本(ledger)中,包括狀態(state)的變化,本地的賬本稱為PeerLedger
智能合約
? ? ? ? 即Fabric中的Chaincode,編寫Chaincode程序實際上就是要編寫一個類,并且這個類要實現fabric預先定義的一個接口,在Fabric中,Chaincode的運行是生成Transaction的唯一來源,也因此Chaincode是外界與Fabric區塊鏈交互的唯一渠道。???????
實驗目的
????????在fabric1.4的架構下,使用docker的容器服務搭建一個具有5個節點的簡單聯盟鏈,了解基本的共識,出塊,部署、調用智能合約(chaincode)的功能。本實驗共有兩個任務:
- 搭建一個fabric1.4的基礎區塊鏈網絡
- 在fabric的架構下如何去編寫、調用智能合約(chaincode),根據簡單的業務需求(投票)來設計、實現chaincode。
實驗環境
- Ubuntu20.04(版本非必須)的VMware虛擬機
- curl
- Docker ?18.09.6-ce和?Docker Compose 1.24.0,支持更高版本
- Go programming language go1.12.5 (fabric1.4要求go版本為1.11.x或更高,Fabric1.0要求1.7.x或更高),在系統變量中設置相應的$GOPATH和$GOROOT變量
- Fabric 1.4的可執行文件
基礎依賴
# 安裝curl
sudo apt install curl
# 為了curl能夠?持https協議,安裝openssl
sudo apt install openssl libssl-dev
# 安裝git
sudo apt install git
# 安裝cmake
sudo apt install cmake
# 安裝jq
sudo apt install jq
# 安裝libtool
sudo apt install libtool libltdl-dev
檢查安裝是否成功:
?安裝Golang
后續區塊鏈智能合約用golang編寫;
直接下載地址:https://golang.google.cn/dl/
# 下載官?的linux x86-64 Archive
wget https://golang.google.cn/dl/go1.19.3.linux-amd64.tar.gz --no-check certificate
# 解壓
sudo tar -xzf go1.19.3.linux-amd64.tar.gz -C /usr/local
# 主?錄下建?goDir?件夾,做為GOPATH路徑
mkdir ~/goDir
下載后改配置文件添加路徑,這里將seed改為自己用戶名即可,編輯.zshrc:
# 在zsh配置?件中添加系統PATH
vim ~/.zshrc
export GOPATH=/home/seed/goDir
export GOROOT=/usr/local/go
export PATH=$PATH:$GOPATH/bin
export PATH=$PATH:$GOROOT/bin
# 刷新配置?件
source ~/.zshrc
?讓root也能執?go命令,改.zshrc或者?/root/.bashrc:
# 讓root也能執?go命令(如果root沒有安裝zsh,則修改 /root/.bashrc)
sudo su
vim ~/.zshrc
export GOPATH=/home/seed/goDir
export GOROOT=/usr/local/go
export PATH=$PATH:$GOPATH/bin
export PATH=$PATH:$GOROOT/bin
檢查:
安裝docker
安裝基礎依賴包
apt-transport-https允許 apt 包管理器通過 HTTPS 協議與軟件源通信;
ca-certificates提供權威機構頒發的根證書,防止中間人攻擊;
gnupg-agent用于管理和緩存 GPG(GNU Privacy Guard)密鑰(對軟件包進行數字簽名和驗證):
sudo apt install apt-transport-https ca-certificates curl gnupg-agent software-properties-common
從 Docker 官網下載其公鑰,驗證軟件包的簽名,并將其添加到系統的可信密鑰列表中:
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo apt-key add -
添加 Docker 的官方 APT 軟件源,add-apt-repository將一個新的軟件源添加到系統中,deb?表示這是一個二進制軟件包的倉庫地址:
sudo add-apt-repository "deb [arch=amd64] https://download.docker.com/linux/ubuntu $(lsb_release -cs) stable"
若拉取鏡像失敗則換源,阿里云上很多,多加一些,多試幾次:
更新本地軟件包緩存,安裝 Docker 引擎等組件:
sudo apt update
sudo apt install docker-ce docker-ce-cli containerd.io
以?root?戶的身份運?Docker
# 如果出現Cannot connect to the Docker daemon. Is the docker daemon running on this host?
# 解決辦法1
sudo chown seed:docker /var/run/docker.sock
# seed改成??的?戶名# 解決辦法2
# 創建?個名為docker的組
sudo groupadd docker
# 將你的?戶添加到docker組
sudo usermod –aG docker $USER
# 重啟
檢查是否安裝成功,看docker版本:
安裝docker-compose
運行下列環境安裝docker-compose,如下載失敗,可前往http://get.daocloud.io/#install-compose
sudo curl -L "https://github.com/docker/compose/releases/download/1.25.5/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose#給相應的二進制文件可執行權限:
sudo chmod +x /usr/local/bin/docker-compose#之后在命令行輸入
docker-compose version
檢查版本:
重新啟動并檢查狀態是active:
搭建fabric環境
從 GitHub 上克隆 Hyperledger Fabric 的官方樣本倉庫;
./install-fabric.sh docker再次執行安裝腳本,并指定b(binary) 作為參數,這個操作會下載與所拉取鏡像版本匹配的 Fabric 二進制工具文件到當前目錄的bin文件夾下;
mkdir ~/blockchain
cd blockchain
# github克隆fabric-samples
git clone https://github.com/hyperledger/fabric-samples
cd fabric-samples
# 下載安裝腳本并構建docker
wget https://raw.githubusercontent.com/hyperledger/fabric/main/scripts/install-fabric.sh --no-check-certificate
chmod +x install-fabric.sh
./install-fabric.sh docker
./install-fabric.sh b
并運行其中連通性測試腳本:
# 啟動網絡
cd test-network
./network.sh up#或者同時創建通道、指定狀態數據庫
./test-network/network.sh up createChannel -ca -c mychannel -s couchdb# 查看是否創建成功
docker ps# 關閉docker
./network.sh down
返回如下算成功:
? ? ? ?可選:若返回的版本信息不匹配,即出現如下行,fabric-samples/bin默認下載舊的 v2.5.4 版本二進制文件,install-fabric.sh使用新的 v3.0.0 版本的 Docker 鏡像,版本不匹配也能聯通,但后續可能有問題,可以升級本地二進制文件以匹配 Docker 鏡像 (v3.0.0)
LOCAL_VERSION=v2.5.4
DOCKER_IMAGE_VERSION=v3.0.0
Local fabric binaries and docker images are out of sync. This may cause problems.
# 確保你在 fabric-samples 目錄下
cd ~/blockchain/fabric-samples# 使用安裝腳本,指定版本,重新下載二進制文件
# 這將覆蓋 bin 目錄下的舊版工具
./install-fabric.sh --fabric-version 3.0.0 binary# 清理之前的網絡(如果正在運行)
./test-network/network.sh down#重新運行你的命令
./test-network/network.sh up createChannel -ca -c mychannel -s couchdb
搭建測試網絡(可選)
參考鏈接:?https://hyperledger-fabric.readthedocs.io/en/release-1.4/build_network.html
????????現在已經克隆 Hyperledger Fabric 的官方樣本倉庫,在執行前面的腳本后,會發現目錄下多了fabric-samples,包含了鏈碼示例、應用程序示例、以及部署腳本,現在將使用first-network這個例子。
cd $GOPATH/src/github.com/hyperledger/fabric/scripts/fabric-samples/first-network
????????官方提供一個完全注釋的腳本byfn.sh,利用這些Docker鏡像可以快速引導一個由4個代表2個不同組織的peer節點以及一個排序服務節點的Hyperledger fabric網絡。它還將啟動一個容器來運行一個將peer節點加入channel、部署實例化鏈碼服務以及驅動已經部署的鏈碼執行交易的腳本。
sudo ./byfn.sh
chaincode 編寫
????????使用Go語言編寫一個用于投票的chaincode,并完成其功能性測試(如投票,統計,查詢等)。可以選擇多種測試手段,如編寫chaincode的測試代碼,或者是在dev模式下,使用命令行測試。
golang教程:Go 語言之旅
代碼下載
可以從github下載課程相關代碼,完整代碼見倉庫:https://github.com/yy158775/blockchain-exp
cd ~/blockchain
git clone https://github.com/yy158775/blockchain-exp
cd blockchain-exp/vote-smartcontract
go mod tidy
# 修改main.go
cd ~/blockchain/blockchain-exp/vote-app
gedit main.go
# 將其中的cryptoPath改為如下路徑(之前的?件夾相對位置需要與 實驗環境搭建 部分所寫?致)
# cryptoPath = "../../fabric-samples/test-network/organizations/peerOrganizations/org1.example.com"
# certPath = cryptoPath +"/users/User1@org1.example.com/msp/signcerts/User1@org1.example.com-cert.pem"
# 下載依賴
go mod tidy
# 開啟network
cd ~/blockchain/fabric-samples/test-network
./network.sh down
./network.sh up
# 創建channel
./network.sh createChannel
# 運?
./network.sh deployCC -ccn basic -ccp ../../blockchain-exp/votesmartcontract -ccl go
代碼投票
修改main.go的cryptoPath和chaincodeName,通過應用程序調用智能合約:
# 運?客戶端
cd ~/blockchain/blockchain-exp/vote-app
go mod tidy
go run main.go
根據菜單就能直接投票了:
命令行投票
鏈碼部署 (deployCC)
-ccn: 指定Chaincode名為vote
-ccp指定Chaincode源代碼的路徑
./network.sh deployCC -ccl go -ccp ./HUST-blockchain-exp/vote-smartcontract/ -ccn vote
環境變量設置
????????在執行鏈碼調用invoke/query命令前,必須設置這些環境變量,以指定要操作哪個 Peer 節點和使用哪個身份。
# 設置核心配置路徑(假設當前在 test-network 目錄)
export FABRIC_CFG_PATH=$PWD/../config/# 啟用 TLS 通信
export CORE_PEER_TLS_ENABLED=true# 設置要操作的組織 MSP ID
export CORE_PEER_LOCALMSPID="Org1MSP"# 設置該組織的 TLS 根證書路徑(用于驗證通信)
export CORE_PEER_TLS_ROOTCERT_FILE=$PWD/organizations/peerOrganizations/org1.example.com/peers/peer0.org1.example.com/tls/ca.crt# 設置管理員用戶的 MSP 路徑(身份文件)
export CORE_PEER_MSPCONFIGPATH=$PWD/organizations/peerOrganizations/org1.example.com/users/Admin@org1.example.com/msp# 設置要連接的 Peer 節點地址
export CORE_PEER_ADDRESS=localhost:7051
切換到 Org2 時,需要重新設置以下變量:
export CORE_PEER_LOCALMSPID="Org2MSP"
export CORE_PEER_TLS_ROOTCERT_FILE=$PWD/organizations/peerOrganizations/org2.example.com/peers/peer0.org2.example.com/tls/ca.crt
export CORE_PEER_MSPCONFIGPATH=$PWD/organizations/peerOrganizations/org2.example.com/users/Admin@org2.example.com/msp
export CORE_PEER_ADDRESS=localhost:9051
調用交易(invoke)
調用鏈碼的VoteUser?函數,這是一個會修改賬本狀態的交易(Transaction)。
peer chaincode invoke \-o localhost:7050 \ # Orderer 地址--ordererTLSHostnameOverride orderer.example.com \--tls \--cafile "$PWD/organizations/ordererOrganizations/example.com/orderers/orderer.example.com/msp/tlscacerts/tlsca.example.com-cert.pem" \ # Orderer TLS CA-C mychannel \ # 通道名稱-n vote \ # 鏈碼名稱--peerAddresses localhost:7051 \ # 需要背書的 Peer 地址 (Org1)--tlsRootCertFiles "$PWD/organizations/peerOrganizations/org1.example.com/peers/peer0.org1.example.com/tls/ca.crt" \--peerAddresses localhost:9051 \ # 需要背書的 Peer 地址 (Org2)--tlsRootCertFiles "$PWD/organizations/peerOrganizations/org2.example.com/peers/peer0.org2.example.com/tls/ca.crt" \-c '{"function":"VoteUser","Args":["username"]}' # 調用方法和參數
查詢投票(query)
????????查詢單個用戶票數:Chaincode的?GetUserVote函數,這是一個僅查詢賬本狀態而不產生交易的查詢(Query):
peer chaincode query -C mychannel -n vote -c '{"Args":["GetUserVote", "usernane1"]}'
("id":2, "usernane":"usernane","votes":1)
????????查詢所有投票:Chaincode的GetAllVotes函數:
peer chaincode query -C mychannel -n vote -c '{"Args":["GetAllVotes"]}'
[{"id":0,"username":"Alice","votes":2},{"id":1,"username":"Mike","votes":1},{"id":2,"username":"usernane1","votes":1}]
恭喜成功!下一篇挖礦!