前言
在基於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
目錄拷貝到本地執行):
- 修改
compose-test-net.yaml
、compose-ca.yaml
、docker/docker-compose-test-net.yaml
、docker/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
- 將基於Debian搭建Hyperledger Fabric 2.4開發環境及執行簡單案例中的
/usr/local/fabric/config
目錄複製到test-network
根目錄下。如無特殊說明,環境變數FABRIC_CFG_PATH
總是預設指向test-network/config
目錄。 - 修改
docker-compose-test-net.yaml
,將${DOCKER_SOCK}
改成/var/run/docker.sock
。 - 修改
createChannel.sh
、deployCC.sh
,將FABRIC_CFG_PATH=$PWD/../config/
改成FABRIC_CFG_PATH=$PWD/config/
- 如無特殊說明,本文所有命令皆執行在
test-network
根目錄下。
啟動預設網路
官方呼叫
在test-network
中,包含一個預設最簡網路,該網路只包含兩個peer
節點、一個orderer
節點和一個cli
節點,其中各節點的證書使用cryptogen
工具靜態生成。可以直接執行以下命令啟動預設最簡網路:
./network.sh up
過程詳解
- 檢查依賴:
- 檢查
peer
版本 - 檢查
./config
配置目錄是否存在 - 檢查
peer
版本與docker image
版本是否匹配 - 檢查
fabric-ca
環境是否正常,預設使用cryptogen
- 建立組織證書:
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"
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
過程詳解
- 檢查軟體、版本依賴:
- 啟動fabric-ca容器:
docker-compose -f compose/compose-ca.yaml -f compose/docker/docker-compose-ca.yaml up -d
- 建立org1證書目錄:
# 建立組織證書根目錄
mkdir -p organizations/peerOrganizations/org1.example.com/
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"
- 建立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"
- 構造
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"
- 構造
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"
- 構造
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"
- 為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"
- 構造
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"
- 構造其它使用者身份證書目錄:
# 構造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"
- 構造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"
- 構造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"
- 啟動所有容器
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
建立通道的前提是建立該通道的創世區塊,在上節步驟中,我們通過無通道、無創世區塊的方式啟動了整個網路,所在本節建立通道包含建立創世區塊的過程。
過程詳解
- 檢查依賴,並啟動網路(同上)。
- 設定環境變數,用於操作區塊鏈網路
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
- 建立通道創世區塊:
# 建立通道資料目錄
mkdir channel-artifacts
# 配置創世區塊環境變數
export FABRIC_CFG_PATH=${PWD}/configtx
configtxgen -profile TwoOrgsApplicationGenesis -outputBlock ./channel-artifacts/${CHANNEL_NAME}.block -channelID ${CHANNEL_NAME}
- 建立通道:
# 配置通道環境變數
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"
- 使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"
- 將配置塊解碼為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"
- 追加錨節點配置:
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
- 根據鏈上配置
${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"
- 更新錨節點:
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"
- 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
過程詳解
- 檢查引數是否正常:
- 下載asset-transfer-basic-go的包依賴:
pushd asset-transfer-basic-go # 進入asset-transfer-basic-go目錄
GO111MODULE=on go mod vendor # 下載go包依賴
popd #返回當前目錄
- 檢查鏈碼是否需要初始化、設定策略、私有資料集:
- 設定環境變數:
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
- 打包鏈碼:
peer lifecycle chaincode package mychaincode.tar.gz --path ./asset-transfer-basic-go --lang golang --label mychaincode_1.0
- 安裝鏈碼:
# 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 需要記下:
7. 將鏈碼 ID 設為環境變數:
export PACKAGE_ID=mychaincode_1.0:39889cf0623cce2500261b22914a7aa9037a897bc7f6c5b36df7a922f29b05e0
- 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
- 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
- 檢查鏈碼是否已準備好被提交:
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
- 查詢提交的鏈碼:
peer lifecycle chaincode querycommitted --channelID mychannel --name mychaincode
- 呼叫鏈碼:
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
參考
hyperledger. fabric-samples. Github. ↩︎