Hyperledger Fabric的test-network啟動過程Bash原始碼詳解

丿風色幻想發表於2022-04-07

前言

基於Debian搭建Hyperledger Fabric 2.4開發環境及執行簡單案例中,我們已經完成了Fabric 2.4的環境搭建及fabric-samples/test-network官方案例的執行。毫無疑問test-network是一個優秀的入門專案,讓我們僅僅通過幾行命令就能搭建起常用的Fabric聯盟鏈網路,但我相信很多人第一次使用./network.sh up成功啟動聯盟鏈網路時跟我一樣是懵的:網路是怎樣啟動的?它在背後做了什麼?該網路包含哪些節點?包含哪些功能?它有什麼用?為了解決這些問題,本文根據test-network中的幾個Bash指令碼原始碼,從啟動流程、建立通道、部署鏈碼等多個入口函式著手詳細分析了指令碼執行過程,對未來定製自己的Fabric網路提供參考。本文分析原始碼主要包含啟動預設網路、啟動CA網路、建立通道、部署鏈碼四個方面,每節分為官方呼叫和過程詳解:官方呼叫是使用官方Bash指令碼實現對應功能、過程詳解是該指令碼的實際實現流程,根據過程詳解中的程式碼能夠搭建出完全可用的網路。

準備

在開始前,需要準備好Fabric的開發環境,具體環境搭建和軟體版本可參考基於Debian搭建Hyperledger Fabric 2.4開發環境及執行簡單案例。之後將fabric-samples[1]下的test-network目錄拷貝到本地,由於官方示例中過於封裝導致難以單獨使用,因此本文對原test-network專案進行修改,修改內容包括但不限於以下幾個方面(建議直接將本案例倉庫 FabricLearn 下的 0_TestNetworkExplain 目錄拷貝到本地執行):

  1. 修改compose-test-net.yamlcompose-ca.yamldocker/docker-compose-test-net.yamldocker/docker-compose-ca.yaml檔案中映象版本:
hyperledger/fabric-tools:latest    ->  hyperledger/fabric-tools:2.4
hyperledger/fabric-peer:latest     ->  fabric-peer:2.4
hyperledger/fabric-orderer:latest  ->  fabric-orderer:2.4
hyperledger/fabric-ca:latest       ->  fabric-ca:1.5
  1. 基於Debian搭建Hyperledger Fabric 2.4開發環境及執行簡單案例中的/usr/local/fabric/config目錄複製到test-network根目錄下。如無特殊說明,環境變數FABRIC_CFG_PATH總是預設指向test-network/config目錄。
  2. 修改docker-compose-test-net.yaml,將${DOCKER_SOCK}改成/var/run/docker.sock
  3. 修改createChannel.shdeployCC.sh,將FABRIC_CFG_PATH=$PWD/../config/改成FABRIC_CFG_PATH=$PWD/config/
  4. 如無特殊說明,本文所有命令皆執行在test-network根目錄下。

啟動預設網路

官方呼叫

test-network中,包含一個預設最簡網路,該網路只包含兩個peer節點、一個orderer節點和一個cli節點,其中各節點的證書使用cryptogen工具靜態生成。可以直接執行以下命令啟動預設最簡網路:

./network.sh up

啟動預設網路

過程詳解

  1. 檢查依賴:
  • 檢查peer版本
  • 檢查./config配置目錄是否存在
  • 檢查peer版本與docker image版本是否匹配
  • 檢查fabric-ca環境是否正常,預設使用cryptogen
    檢查軟體、版本依賴
  1. 建立組織證書:
cryptogen generate --config=./organizations/cryptogen/crypto-config-org1.yaml --output="organizations"
cryptogen generate --config=./organizations/cryptogen/crypto-config-org2.yaml --output="organizations"
cryptogen generate --config=./organizations/cryptogen/crypto-config-orderer.yaml --output="organizations"
  1. docker-compose啟動所有容器:
docker-compose -f compose/compose-test-net.yaml -f compose/docker/docker-compose-test-net.yaml up -d

啟動預設網路-過程詳解
其中compose-test-net.yaml包含基本映象配置,docker-compose-test-net.yaml包含基礎通用變數,二者缺一不可。以上命令完成後即可實現與./network.sh up完全相同的效果,進行下節實驗前可使用./network.sh down關閉此網路。

啟動CA網路

官方呼叫

在test-network中,可以通過fabric-ca啟動網路,該網路使用fabric-ca管理所有節點的身份證書,其中包含三個ca節點、兩個peer節點、一個orderer節點和一個cli節點。可以直接執行以下命令啟動CA網路(後面所有實驗基於此網路):

./network.sh up -ca

啟動CA網路

過程詳解

  1. 檢查軟體、版本依賴:
    檢查軟體、版本依賴
  2. 啟動fabric-ca容器:
docker-compose -f compose/compose-ca.yaml -f compose/docker/docker-compose-ca.yaml up -d
  1. 建立org1證書目錄:
# 建立組織證書根目錄
mkdir -p organizations/peerOrganizations/org1.example.com/
  1. enroll管理員賬戶:
# enroll組織預設管理員賬戶,其配置對應在compose/compose-ca.yaml的command中,enroll過程會獲取該賬戶的全部證書並儲存至FABRIC_CA_CLIENT_HOME目錄下
export FABRIC_CA_CLIENT_HOME=${PWD}/organizations/peerOrganizations/org1.example.com/
fabric-ca-client enroll -u https://admin:adminpw@localhost:7054 --caname ca-org1 --tls.certfiles "${PWD}/organizations/fabric-ca/org1/ca-cert.pem"
  1. 建立org1組織的OU配置檔案:
# 建立組織msp的OU配置檔案
echo 'NodeOUs:
  Enable: true
  ClientOUIdentifier:
    Certificate: cacerts/localhost-7054-ca-org1.pem
    OrganizationalUnitIdentifier: client
  PeerOUIdentifier:
    Certificate: cacerts/localhost-7054-ca-org1.pem
    OrganizationalUnitIdentifier: peer
  AdminOUIdentifier:
    Certificate: cacerts/localhost-7054-ca-org1.pem
    OrganizationalUnitIdentifier: admin
  OrdererOUIdentifier:
    Certificate: cacerts/localhost-7054-ca-org1.pem
    OrganizationalUnitIdentifier: orderer' > "${PWD}/organizations/peerOrganizations/org1.example.com/msp/config.yaml"
  1. 構造tlscacerts證書目錄(用於不同組織通訊):
# 由於該CA同時充當組織CA和tlsca,因此直接將CA啟動時生成的組織根證書複製到組織級CA和TLS CA目錄中
mkdir -p "${PWD}/organizations/peerOrganizations/org1.example.com/msp/tlscacerts"
cp "${PWD}/organizations/fabric-ca/org1/ca-cert.pem" "${PWD}/organizations/peerOrganizations/org1.example.com/msp/tlscacerts/ca.crt"
  1. 構造tlsca證書目錄(用於組織內客戶端通訊):
mkdir -p "${PWD}/organizations/peerOrganizations/org1.example.com/tlsca"
cp "${PWD}/organizations/fabric-ca/org1/ca-cert.pem" "${PWD}/organizations/peerOrganizations/org1.example.com/tlsca/tlsca.org1.example.com-cert.pem"
  1. 構造ca證書目錄(用於組織內客戶端通訊):
mkdir -p "${PWD}/organizations/peerOrganizations/org1.example.com/ca"
cp "${PWD}/organizations/fabric-ca/org1/ca-cert.pem" "${PWD}/organizations/peerOrganizations/org1.example.com/ca/ca.org1.example.com-cert.pem"
  1. 為org1註冊新賬戶:
fabric-ca-client register --caname ca-org1 --id.name peer0 --id.secret peer0pw --id.type peer --tls.certfiles "${PWD}/organizations/fabric-ca/org1/ca-cert.pem"
fabric-ca-client register --caname ca-org1 --id.name user1 --id.secret user1pw --id.type client --tls.certfiles "${PWD}/organizations/fabric-ca/org1/ca-cert.pem"
fabric-ca-client register --caname ca-org1 --id.name org1admin --id.secret org1adminpw --id.type admin --tls.certfiles "${PWD}/organizations/fabric-ca/org1/ca-cert.pem"
  1. 構造peer0的身份證書目錄:
# 構造peer0的msp證書目錄,證書檔案會存在-M指定的資料夾下
fabric-ca-client enroll -u https://peer0:peer0pw@localhost:7054 --caname ca-org1 -M "${PWD}/organizations/peerOrganizations/org1.example.com/peers/peer0.org1.example.com/msp" --csr.hosts peer0.org1.example.com --tls.certfiles "${PWD}/organizations/fabric-ca/org1/ca-cert.pem"
cp "${PWD}/organizations/peerOrganizations/org1.example.com/msp/config.yaml" "${PWD}/organizations/peerOrganizations/org1.example.com/peers/peer0.org1.example.com/msp/config.yaml"
# 構造peer0的msp-tls證書目錄
fabric-ca-client enroll -u https://peer0:peer0pw@localhost:7054 --caname ca-org1 -M "${PWD}/organizations/peerOrganizations/org1.example.com/peers/peer0.org1.example.com/tls" --enrollment.profile tls --csr.hosts peer0.org1.example.com --csr.hosts localhost --tls.certfiles "${PWD}/organizations/fabric-ca/org1/ca-cert.pem"
# 構造peer0的tls證書目錄並格式化檔名——用於啟動peer docker容器
cp "${PWD}/organizations/peerOrganizations/org1.example.com/peers/peer0.org1.example.com/tls/tlscacerts/"* "${PWD}/organizations/peerOrganizations/org1.example.com/peers/peer0.org1.example.com/tls/ca.crt"
cp "${PWD}/organizations/peerOrganizations/org1.example.com/peers/peer0.org1.example.com/tls/signcerts/"* "${PWD}/organizations/peerOrganizations/org1.example.com/peers/peer0.org1.example.com/tls/server.crt"
cp "${PWD}/organizations/peerOrganizations/org1.example.com/peers/peer0.org1.example.com/tls/keystore/"* "${PWD}/organizations/peerOrganizations/org1.example.com/peers/peer0.org1.example.com/tls/server.key"
  1. 構造其它使用者身份證書目錄:
# 構造user1的msp證書目錄,因為不用於組織間通訊,所以不用配置tls
fabric-ca-client enroll -u https://user1:user1pw@localhost:7054 --caname ca-org1 -M "${PWD}/organizations/peerOrganizations/org1.example.com/users/User1@org1.example.com/msp" --tls.certfiles "${PWD}/organizations/fabric-ca/org1/ca-cert.pem"
cp "${PWD}/organizations/peerOrganizations/org1.example.com/msp/config.yaml" "${PWD}/organizations/peerOrganizations/org1.example.com/users/User1@org1.example.com/msp/config.yaml"

# 構造org1admin的msp證書目錄
fabric-ca-client enroll -u https://org1admin:org1adminpw@localhost:7054 --caname ca-org1 -M "${PWD}/organizations/peerOrganizations/org1.example.com/users/Admin@org1.example.com/msp" --tls.certfiles "${PWD}/organizations/fabric-ca/org1/ca-cert.pem"
cp "${PWD}/organizations/peerOrganizations/org1.example.com/msp/config.yaml" "${PWD}/organizations/peerOrganizations/org1.example.com/users/Admin@org1.example.com/msp/config.yaml"
  1. 構造org2的組織證書,關鍵程式碼如下(各程式碼含義如上):
mkdir -p organizations/peerOrganizations/org2.example.com/
export FABRIC_CA_CLIENT_HOME=${PWD}/organizations/peerOrganizations/org2.example.com/

fabric-ca-client enroll -u https://admin:adminpw@localhost:8054 --caname ca-org2 --tls.certfiles "${PWD}/organizations/fabric-ca/org2/ca-cert.pem"

echo 'NodeOUs:
Enable: true
ClientOUIdentifier:
Certificate: cacerts/localhost-8054-ca-org2.pem
OrganizationalUnitIdentifier: client
PeerOUIdentifier:
Certificate: cacerts/localhost-8054-ca-org2.pem
OrganizationalUnitIdentifier: peer
AdminOUIdentifier:
Certificate: cacerts/localhost-8054-ca-org2.pem
OrganizationalUnitIdentifier: admin
OrdererOUIdentifier:
Certificate: cacerts/localhost-8054-ca-org2.pem
OrganizationalUnitIdentifier: orderer' > "${PWD}/organizations/peerOrganizations/org2.example.com/msp/config.yaml"

mkdir -p "${PWD}/organizations/peerOrganizations/org2.example.com/msp/tlscacerts"
cp "${PWD}/organizations/fabric-ca/org2/ca-cert.pem" "${PWD}/organizations/peerOrganizations/org2.example.com/msp/tlscacerts/ca.crt"
mkdir -p "${PWD}/organizations/peerOrganizations/org2.example.com/tlsca"
cp "${PWD}/organizations/fabric-ca/org2/ca-cert.pem" "${PWD}/organizations/peerOrganizations/org2.example.com/tlsca/tlsca.org2.example.com-cert.pem"
mkdir -p "${PWD}/organizations/peerOrganizations/org2.example.com/ca"
cp "${PWD}/organizations/fabric-ca/org2/ca-cert.pem" "${PWD}/organizations/peerOrganizations/org2.example.com/ca/ca.org2.example.com-cert.pem"

fabric-ca-client register --caname ca-org2 --id.name peer0 --id.secret peer0pw --id.type peer --tls.certfiles "${PWD}/organizations/fabric-ca/org2/ca-cert.pem"
fabric-ca-client register --caname ca-org2 --id.name user1 --id.secret user1pw --id.type client --tls.certfiles "${PWD}/organizations/fabric-ca/org2/ca-cert.pem"
fabric-ca-client register --caname ca-org2 --id.name org2admin --id.secret org2adminpw --id.type admin --tls.certfiles "${PWD}/organizations/fabric-ca/org2/ca-cert.pem"

fabric-ca-client enroll -u https://peer0:peer0pw@localhost:8054 --caname ca-org2 -M "${PWD}/organizations/peerOrganizations/org2.example.com/peers/peer0.org2.example.com/msp" --csr.hosts peer0.org2.example.com --tls.certfiles "${PWD}/organizations/fabric-ca/org2/ca-cert.pem"
cp "${PWD}/organizations/peerOrganizations/org2.example.com/msp/config.yaml" "${PWD}/organizations/peerOrganizations/org2.example.com/peers/peer0.org2.example.com/msp/config.yaml"
fabric-ca-client enroll -u https://peer0:peer0pw@localhost:8054 --caname ca-org2 -M "${PWD}/organizations/peerOrganizations/org2.example.com/peers/peer0.org2.example.com/tls" --enrollment.profile tls --csr.hosts peer0.org2.example.com --csr.hosts localhost --tls.certfiles "${PWD}/organizations/fabric-ca/org2/ca-cert.pem"

cp "${PWD}/organizations/peerOrganizations/org2.example.com/peers/peer0.org2.example.com/tls/tlscacerts/"* "${PWD}/organizations/peerOrganizations/org2.example.com/peers/peer0.org2.example.com/tls/ca.crt"
cp "${PWD}/organizations/peerOrganizations/org2.example.com/peers/peer0.org2.example.com/tls/signcerts/"* "${PWD}/organizations/peerOrganizations/org2.example.com/peers/peer0.org2.example.com/tls/server.crt"
cp "${PWD}/organizations/peerOrganizations/org2.example.com/peers/peer0.org2.example.com/tls/keystore/"* "${PWD}/organizations/peerOrganizations/org2.example.com/peers/peer0.org2.example.com/tls/server.key"

fabric-ca-client enroll -u https://user1:user1pw@localhost:8054 --caname ca-org2 -M "${PWD}/organizations/peerOrganizations/org2.example.com/users/User1@org2.example.com/msp" --tls.certfiles "${PWD}/organizations/fabric-ca/org2/ca-cert.pem"
cp "${PWD}/organizations/peerOrganizations/org2.example.com/msp/config.yaml" "${PWD}/organizations/peerOrganizations/org2.example.com/users/User1@org2.example.com/msp/config.yaml"

fabric-ca-client enroll -u https://org2admin:org2adminpw@localhost:8054 --caname ca-org2 -M "${PWD}/organizations/peerOrganizations/org2.example.com/users/Admin@org2.example.com/msp" --tls.certfiles "${PWD}/organizations/fabric-ca/org2/ca-cert.pem"
cp "${PWD}/organizations/peerOrganizations/org2.example.com/msp/config.yaml" "${PWD}/organizations/peerOrganizations/org2.example.com/users/Admin@org2.example.com/msp/config.yaml"
  1. 構造orderer的組織證書,關鍵程式碼如下:
mkdir -p organizations/ordererOrganizations/example.com
export FABRIC_CA_CLIENT_HOME=${PWD}/organizations/ordererOrganizations/example.com

fabric-ca-client enroll -u https://admin:adminpw@localhost:9054 --caname ca-orderer --tls.certfiles "${PWD}/organizations/fabric-ca/ordererOrg/ca-cert.pem"

echo 'NodeOUs:
Enable: true
ClientOUIdentifier:
Certificate: cacerts/localhost-9054-ca-orderer.pem
OrganizationalUnitIdentifier: client
PeerOUIdentifier:
Certificate: cacerts/localhost-9054-ca-orderer.pem
OrganizationalUnitIdentifier: peer
AdminOUIdentifier:
Certificate: cacerts/localhost-9054-ca-orderer.pem
OrganizationalUnitIdentifier: admin
OrdererOUIdentifier:
Certificate: cacerts/localhost-9054-ca-orderer.pem
OrganizationalUnitIdentifier: orderer' > "${PWD}/organizations/ordererOrganizations/example.com/msp/config.yaml"

mkdir -p "${PWD}/organizations/ordererOrganizations/example.com/msp/tlscacerts"
cp "${PWD}/organizations/fabric-ca/ordererOrg/ca-cert.pem" "${PWD}/organizations/ordererOrganizations/example.com/msp/tlscacerts/tlsca.example.com-cert.pem"
mkdir -p "${PWD}/organizations/ordererOrganizations/example.com/tlsca"
cp "${PWD}/organizations/fabric-ca/ordererOrg/ca-cert.pem" "${PWD}/organizations/ordererOrganizations/example.com/tlsca/tlsca.example.com-cert.pem"

fabric-ca-client register --caname ca-orderer --id.name orderer --id.secret ordererpw --id.type orderer --tls.certfiles "${PWD}/organizations/fabric-ca/ordererOrg/ca-cert.pem"
fabric-ca-client register --caname ca-orderer --id.name ordererAdmin --id.secret ordererAdminpw --id.type admin --tls.certfiles "${PWD}/organizations/fabric-ca/ordererOrg/ca-cert.pem"
fabric-ca-client enroll -u https://orderer:ordererpw@localhost:9054 --caname ca-orderer -M "${PWD}/organizations/ordererOrganizations/example.com/orderers/orderer.example.com/msp" --csr.hosts orderer.example.com --csr.hosts localhost --tls.certfiles "${PWD}/organizations/fabric-ca/ordererOrg/ca-cert.pem"

cp "${PWD}/organizations/ordererOrganizations/example.com/msp/config.yaml" "${PWD}/organizations/ordererOrganizations/example.com/orderers/orderer.example.com/msp/config.yaml"

fabric-ca-client enroll -u https://orderer:ordererpw@localhost:9054 --caname ca-orderer -M "${PWD}/organizations/ordererOrganizations/example.com/orderers/orderer.example.com/tls" --enrollment.profile tls --csr.hosts orderer.example.com --csr.hosts localhost --tls.certfiles "${PWD}/organizations/fabric-ca/ordererOrg/ca-cert.pem"

cp "${PWD}/organizations/ordererOrganizations/example.com/orderers/orderer.example.com/tls/tlscacerts/"* "${PWD}/organizations/ordererOrganizations/example.com/orderers/orderer.example.com/tls/ca.crt"
cp "${PWD}/organizations/ordererOrganizations/example.com/orderers/orderer.example.com/tls/signcerts/"* "${PWD}/organizations/ordererOrganizations/example.com/orderers/orderer.example.com/tls/server.crt"
cp "${PWD}/organizations/ordererOrganizations/example.com/orderers/orderer.example.com/tls/keystore/"* "${PWD}/organizations/ordererOrganizations/example.com/orderers/orderer.example.com/tls/server.key"
mkdir -p "${PWD}/organizations/ordererOrganizations/example.com/orderers/orderer.example.com/msp/tlscacerts"
cp "${PWD}/organizations/ordererOrganizations/example.com/orderers/orderer.example.com/tls/tlscacerts/"* "${PWD}/organizations/ordererOrganizations/example.com/orderers/orderer.example.com/msp/tlscacerts/tlsca.example.com-cert.pem"

fabric-ca-client enroll -u https://ordererAdmin:ordererAdminpw@localhost:9054 --caname ca-orderer -M "${PWD}/organizations/ordererOrganizations/example.com/users/Admin@example.com/msp" --tls.certfiles "${PWD}/organizations/fabric-ca/ordererOrg/ca-cert.pem"
cp "${PWD}/organizations/ordererOrganizations/example.com/msp/config.yaml" "${PWD}/organizations/ordererOrganizations/example.com/users/Admin@example.com/msp/config.yaml"
  1. 啟動所有容器
docker-compose -f compose/compose-test-net.yaml -f compose/docker/docker-compose-test-net.yaml up -d

以上命令成功後便可使用docker ps命令看到執行的映象:

CONTAINER ID   IMAGE                            COMMAND                  CREATED          STATUS          PORTS                                                                    NAMES
75e842d165ea   hyperledger/fabric-tools:2.4     "/bin/bash"              10 seconds ago   Up 8 seconds                                                                             cli
576b578063c5   hyperledger/fabric-peer:2.4      "peer node start"        16 seconds ago   Up 10 seconds   0.0.0.0:9051->9051/tcp, 7051/tcp, 0.0.0.0:9445->9445/tcp                 peer0.org2.example.com
512d7d98c8c4   hyperledger/fabric-orderer:2.4   "orderer"                16 seconds ago   Up 14 seconds   0.0.0.0:7050->7050/tcp, 0.0.0.0:7053->7053/tcp, 0.0.0.0:9443->9443/tcp   orderer.example.com
276f463cc6a7   hyperledger/fabric-peer:2.4      "peer node start"        16 seconds ago   Up 12 seconds   0.0.0.0:7051->7051/tcp, 0.0.0.0:9444->9444/tcp                           peer0.org1.example.com
8faaaaa7e17a   hyperledger/fabric-ca:1.5        "sh -c 'fabric-ca-se…"   21 seconds ago   Up 20 seconds   0.0.0.0:9054->9054/tcp, 7054/tcp, 0.0.0.0:19054->19054/tcp               ca_orderer
c253d9b790be   hyperledger/fabric-ca:1.5        "sh -c 'fabric-ca-se…"   21 seconds ago   Up 20 seconds   0.0.0.0:7054->7054/tcp, 0.0.0.0:17054->17054/tcp                         ca_org1
0aa90a2686a8   hyperledger/fabric-ca:1.5        "sh -c 'fabric-ca-se…"   21 seconds ago   Up 20 seconds   0.0.0.0:8054->8054/tcp, 7054/tcp, 0.0.0.0:18054->18054/tcp               ca_org2

建立通道

官方呼叫

本小節基於上一節 啟動CA網路,在上節CA網路啟動成功後,可以直接執行以下命令建立通道:

./network.sh createChannel -c mychannel

建立通道

建立通道的前提是建立該通道的創世區塊,在上節步驟中,我們通過無通道、無創世區塊的方式啟動了整個網路,所在本節建立通道包含建立創世區塊的過程。

過程詳解

  1. 檢查依賴,並啟動網路(同上)。
  2. 設定環境變數,用於操作區塊鏈網路
export CORE_PEER_TLS_ENABLED=true
export CHANNEL_NAME=mychannel
export ORDERER_CA=${PWD}/organizations/ordererOrganizations/example.com/tlsca/tlsca.example.com-cert.pem
export PEER0_ORG1_CA=${PWD}/organizations/peerOrganizations/org1.example.com/tlsca/tlsca.org1.example.com-cert.pem
export PEER0_ORG2_CA=${PWD}/organizations/peerOrganizations/org2.example.com/tlsca/tlsca.org2.example.com-cert.pem
export PEER0_ORG3_CA=${PWD}/organizations/peerOrganizations/org3.example.com/tlsca/tlsca.org3.example.com-cert.pem
export ORDERER_ADMIN_TLS_SIGN_CERT=${PWD}/organizations/ordererOrganizations/example.com/orderers/orderer.example.com/tls/server.crt
export ORDERER_ADMIN_TLS_PRIVATE_KEY=${PWD}/organizations/ordererOrganizations/example.com/orderers/orderer.example.com/tls/server.key
  1. 建立通道創世區塊:
# 建立通道資料目錄
mkdir channel-artifacts
# 配置創世區塊環境變數
export FABRIC_CFG_PATH=${PWD}/configtx
configtxgen -profile TwoOrgsApplicationGenesis -outputBlock ./channel-artifacts/${CHANNEL_NAME}.block -channelID ${CHANNEL_NAME}
  1. 建立通道:
# 配置通道環境變數
export FABRIC_CFG_PATH=./config
osnadmin channel join --channelID ${CHANNEL_NAME} --config-block ./channel-artifacts/${CHANNEL_NAME}.block -o localhost:7053 --ca-file "$ORDERER_CA" --client-cert "$ORDERER_ADMIN_TLS_SIGN_CERT" --client-key "$ORDERER_ADMIN_TLS_PRIVATE_KEY"
  1. 使peer節點加入通道:
# 將org1的peer加入通道
export CORE_PEER_LOCALMSPID="Org1MSP"
export CORE_PEER_TLS_ROOTCERT_FILE=$PEER0_ORG1_CA
export CORE_PEER_MSPCONFIGPATH=${PWD}/organizations/peerOrganizations/org1.example.com/users/Admin@org1.example.com/msp
export CORE_PEER_ADDRESS=localhost:7051
peer channel join -b ./channel-artifacts/${CHANNEL_NAME}.block
# 將org2的peer加入通道
export CORE_PEER_LOCALMSPID="Org2MSP"
export CORE_PEER_TLS_ROOTCERT_FILE=$PEER0_ORG2_CA
export CORE_PEER_MSPCONFIGPATH=${PWD}/organizations/peerOrganizations/org2.example.com/users/Admin@org2.example.com/msp
export CORE_PEER_ADDRESS=localhost:9051
peer channel join -b ./channel-artifacts/${CHANNEL_NAME}.block

組織新加入通道後,後面為組織設定錨節點(非必須)。
6. 為通道獲取通道最新配置塊(以下流程為org1環境):

export CORE_PEER_LOCALMSPID="Org1MSP"
export CORE_PEER_TLS_ROOTCERT_FILE=$PEER0_ORG1_CA
export CORE_PEER_MSPCONFIGPATH=${PWD}/organizations/peerOrganizations/org1.example.com/users/Admin@org1.example.com/msp
export CORE_PEER_ADDRESS=localhost:7051
peer channel fetch config config_block.pb -o orderer.example.com:7050 --ordererTLSHostnameOverride orderer.example.com -c ${CHANNEL_NAME} --tls --cafile "$ORDERER_CA"
  1. 將配置塊解碼為JSON並輸出為${CORE_PEER_LOCALMSPID}config.json
configtxlator proto_decode --input config_block.pb --type common.Block --output config_block.json
jq .data.data[0].payload.data.config config_block.json >"${CORE_PEER_LOCALMSPID}config.json"
  1. 追加錨節點配置:
jq '.channel_group.groups.Application.groups.'${CORE_PEER_LOCALMSPID}'.values += {"AnchorPeers":{"mod_policy": "Admins","value":{"anchor_peers": [{"host": "'$HOST'","port": '$PORT'}]},"version": "0"}}' ${CORE_PEER_LOCALMSPID}config.json > ${CORE_PEER_LOCALMSPID}modified_config.json
  1. 根據鏈上配置${CORE_PEER_LOCALMSPID}config.json和追加配置${CORE_PEER_LOCALMSPID}modified_config.json計算更新的配置,並將其作為一個新交易寫入${CORE_PEER_LOCALMSPID}anchors.tx
configtxlator proto_encode --input ${CORE_PEER_LOCALMSPID}config.json --type common.Config --output original_config.pb
configtxlator proto_encode --input ${CORE_PEER_LOCALMSPID}modified_config.json --type common.Config --output modified_config.pb
configtxlator compute_update --channel_id "${CHANNEL_NAME}" --original original_config.pb --updated modified_config.pb --output config_update.pb
configtxlator proto_decode --input config_update.pb --type common.ConfigUpdate --output config_update.json
echo '{"payload":{"header":{"channel_header":{"channel_id":"'$CHANNEL_NAME'", "type":2}},"data":{"config_update":'$(cat config_update.json)'}}}' | jq . >config_update_in_envelope.json
configtxlator proto_encode --input config_update_in_envelope.json --type common.Envelope --output "${CORE_PEER_LOCALMSPID}anchors.tx"
  1. 更新錨節點:
peer channel update -o orderer.example.com:7050 --ordererTLSHostnameOverride orderer.example.com -c $CHANNEL_NAME -f ${CORE_PEER_LOCALMSPID}anchors.tx --tls --cafile "$ORDERER_CA"
  1. org2重複以上流程即建立成功:
echo "update org2 anchor==========="
export CORE_PEER_LOCALMSPID="Org2MSP"
export CORE_PEER_TLS_ROOTCERT_FILE=$PEER0_ORG2_CA
export CORE_PEER_MSPCONFIGPATH=${PWD}/organizations/peerOrganizations/org2.example.com/users/Admin@org2.example.com/msp
export CORE_PEER_ADDRESS=localhost:9051
peer channel fetch config config_block.pb -o localhost:7050 --ordererTLSHostnameOverride orderer.example.com -c ${CHANNEL_NAME} --tls --cafile "$ORDERER_CA"
sleep 3

configtxlator proto_decode --input config_block.pb --type common.Block --output config_block.json
jq .data.data[0].payload.data.config config_block.json >"${CORE_PEER_LOCALMSPID}config.json"

jq '.channel_group.groups.Application.groups.'${CORE_PEER_LOCALMSPID}'.values += {"AnchorPeers":{"mod_policy": "Admins","value":{"anchor_peers": [{"host": "localhost","port": 9051}]},"version": "0"}}' ${CORE_PEER_LOCALMSPID}config.json > ${CORE_PEER_LOCALMSPID}modified_config.json

configtxlator proto_encode --input ${CORE_PEER_LOCALMSPID}config.json --type common.Config --output original_config.pb
configtxlator proto_encode --input ${CORE_PEER_LOCALMSPID}modified_config.json --type common.Config --output original_config.pb
configtxlator compute_update --channel_id "${CHANNEL_NAME}" --original original_config.pb --updated modified_config.pb --output config_update.pb
configtxlator proto_decode --input config_update.pb --type common.ConfigUpdate --output config_update.json
echo '{"payload":{"header":{"channel_header":{"channel_id":"'$CHANNEL_NAME'", "type":2}},"data":{"config_update":'$(cat config_update.json)'}}}' | jq . >config_update_in_envelope.json
configtxlator proto_encode --input config_update_in_envelope.json --type common.Envelope --output "${CORE_PEER_LOCALMSPID}anchors.tx"

peer channel update -o localhost:7050 --ordererTLSHostnameOverride orderer.example.com -c $CHANNEL_NAME -f ${CORE_PEER_LOCALMSPID}anchors.tx --tls --cafile "$ORDERER_CA"
sleep 3

部署鏈碼

官方呼叫

本小節基於上一節 建立通道,在上節通道建立成功後,可以直接執行以下命令部署鏈碼:

./network.sh deployCC -ccn mychaincode -ccp ./asset-transfer-basic-go -ccv 1.0 -ccl go

部署鏈碼

過程詳解

  1. 檢查引數是否正常:
    檢查引數是否正常
  2. 下載asset-transfer-basic-go的包依賴:
pushd asset-transfer-basic-go            # 進入asset-transfer-basic-go目錄
GO111MODULE=on go mod vendor    # 下載go包依賴
popd                            #返回當前目錄
  1. 檢查鏈碼是否需要初始化、設定策略、私有資料集:
    檢查鏈碼
  2. 設定環境變數:
export FABRIC_CFG_PATH=$PWD/config/
export CORE_PEER_TLS_ENABLED=true
export ORDERER_CA=${PWD}/organizations/ordererOrganizations/example.com/tlsca/tlsca.example.com-cert.pem
export PEER0_ORG1_CA=${PWD}/organizations/peerOrganizations/org1.example.com/tlsca/tlsca.org1.example.com-cert.pem
export PEER0_ORG2_CA=${PWD}/organizations/peerOrganizations/org2.example.com/tlsca/tlsca.org2.example.com-cert.pem
export PEER0_ORG3_CA=${PWD}/organizations/peerOrganizations/org3.example.com/tlsca/tlsca.org3.example.com-cert.pem
export ORDERER_ADMIN_TLS_SIGN_CERT=${PWD}/organizations/ordererOrganizations/example.com/orderers/orderer.example.com/tls/server.crt
export ORDERER_ADMIN_TLS_PRIVATE_KEY=${PWD}/organizations/ordererOrganizations/example.com/orderers/orderer.example.com/tls/server.key
  1. 打包鏈碼:
peer lifecycle chaincode package mychaincode.tar.gz --path ./asset-transfer-basic-go --lang golang --label mychaincode_1.0
  1. 安裝鏈碼:
# ORG1安裝鏈碼
export CORE_PEER_LOCALMSPID="Org1MSP"
export CORE_PEER_TLS_ROOTCERT_FILE=$PEER0_ORG1_CA
export CORE_PEER_MSPCONFIGPATH=${PWD}/organizations/peerOrganizations/org1.example.com/users/Admin@org1.example.com/msp
export CORE_PEER_ADDRESS=localhost:7051
peer lifecycle chaincode install mychaincode.tar.gz
# ORG2安裝鏈碼
export CORE_PEER_LOCALMSPID="Org2MSP"
export CORE_PEER_TLS_ROOTCERT_FILE=$PEER0_ORG2_CA
export CORE_PEER_MSPCONFIGPATH=${PWD}/organizations/peerOrganizations/org2.example.com/users/Admin@org2.example.com/msp
export CORE_PEER_ADDRESS=localhost:9051
peer lifecycle chaincode install mychaincode.tar.gz

安裝鏈碼後會返回一個鏈碼 ID 需要記下:
鏈碼 ID
7. 將鏈碼 ID 設為環境變數:

export PACKAGE_ID=mychaincode_1.0:39889cf0623cce2500261b22914a7aa9037a897bc7f6c5b36df7a922f29b05e0
  1. ORG1查詢已安裝鏈碼並批准鏈碼:
export CORE_PEER_LOCALMSPID="Org1MSP"
export CORE_PEER_TLS_ROOTCERT_FILE=$PEER0_ORG1_CA
export CORE_PEER_MSPCONFIGPATH=${PWD}/organizations/peerOrganizations/org1.example.com/users/Admin@org1.example.com/msp
export CORE_PEER_ADDRESS=localhost:7051
# 查詢已安裝鏈碼
peer lifecycle chaincode queryinstalled
# 批准鏈碼
peer lifecycle chaincode approveformyorg -o localhost:7050 --ordererTLSHostnameOverride orderer.example.com --tls --cafile "$ORDERER_CA" --channelID mychannel --name mychaincode --version 1.0 --package-id ${PACKAGE_ID} --sequence 1
  1. ORG2查詢已安裝鏈碼並批准鏈碼:
export CORE_PEER_LOCALMSPID="Org2MSP"
export CORE_PEER_TLS_ROOTCERT_FILE=$PEER0_ORG2_CA
export CORE_PEER_MSPCONFIGPATH=${PWD}/organizations/peerOrganizations/org2.example.com/users/Admin@org2.example.com/msp
export CORE_PEER_ADDRESS=localhost:9051
# 查詢已安裝鏈碼
peer lifecycle chaincode queryinstalled
# 批准鏈碼
peer lifecycle chaincode approveformyorg -o localhost:7050 --ordererTLSHostnameOverride orderer.example.com --tls --cafile "$ORDERER_CA" --channelID mychannel --name mychaincode --version 1.0 --package-id ${PACKAGE_ID} --sequence 1
  1. 檢查鏈碼是否已準備好被提交:
peer lifecycle chaincode checkcommitreadiness --channelID mychannel --name mychaincode --version 1.0 --sequence 1 --output json

檢查鏈碼是否已準備好被提交:
11. 提交鏈碼:

peer lifecycle chaincode commit -o localhost:7050 --ordererTLSHostnameOverride orderer.example.com --tls --cafile "$ORDERER_CA"  --channelID mychannel --name mychaincode --version 1.0 --sequence 1 --peerAddresses localhost:7051 --tlsRootCertFiles $PEER0_ORG1_CA --peerAddresses localhost:9051 --tlsRootCertFiles $PEER0_ORG2_CA
  1. 查詢提交的鏈碼:
peer lifecycle chaincode querycommitted --channelID mychannel --name mychaincode
  1. 呼叫鏈碼:
peer chaincode invoke -o localhost:7050 --ordererTLSHostnameOverride orderer.example.com --tls --cafile "$ORDERER_CA" -C mychannel -n mychaincode --peerAddresses

總結

本文先是說明了fabric-samples過度的封裝不利於我們瞭解掌握其中各個操作的真實過程,然後單獨拿出test-network進行修改定製,最後詳細分析了test-network中啟動預設網路、啟動CA網路、建立通道、部署鏈碼的詳細過程,並且給出了每個過程的程式碼,使我們能夠根據程式碼一步步搭建所述網路,進一步理解Fabric架構。

相關實驗原始碼已上傳:https://github.com/wefantasy/FabricLearn

參考


  1. hyperledger. fabric-samples. Github. ↩︎

相關文章