構(gòu)建第一個 Hyperledger Fabric 網(wǎng)絡(luò)

構(gòu)建第一個 Hyperledger Fabric 網(wǎng)絡(luò)

Hyperledger Fabric 最新的文檔基于版本是 v2.0 Alpha release。由于示例中相關(guān)的 docker 鏡像的版本是 v1.4.3,因為相關(guān)文檔需要參考的版本為 v1.4.3。這些文檔鏈接在本文的 Reference 部分都有涉及。

1. 本文目的

參考文檔 Building Your First Network 搭建第一個 Hyperledger Fabric 網(wǎng)絡(luò)。本示例 fabric-samples 需要的 hyperledger fabric 相關(guān)的二進制程序安裝參考文檔 Install Samples, Binaries and Docker Images。而安裝 hyperledger fabric 相關(guān)的二進制程序所需要的一些前置軟件需求,請參考文檔 Prerequisites

2. 構(gòu)建 Hyperledger Fabric 網(wǎng)絡(luò)

根據(jù) fabric-samples/first-network 示例搭建第一個 Hyperledger Fabric 網(wǎng)絡(luò)。這里,主要是基于提供的腳本 byfn.sh 來快速搭建。腳本 byfn.sh 提供了許多可配置的參數(shù),如果不提供則使用默認值。這里為了簡化,先使用默認值。

需要注意的是,下面的命令需要在 first-network 目錄下運行,但是調(diào)用的 hyperledger fabric 相關(guān)的二進制程序卻是在 fabric-samples/bin 目錄。

2.1 腳本 byfn.sh 的詳細說明

Usage:
byfn.sh <mode> [-c <channel name>] [-t <timeout>] [-d <delay>] [-f <docker-compose-file>] [-s <dbtype>] [-l <language>] [-o <consensus-type>] [-i <imagetag>] [-v]"
  <mode> - one of 'up', 'down', 'restart', 'generate' or 'upgrade'"
    - 'up' - bring up the network with docker-compose up"
    - 'down' - clear the network with docker-compose down"
    - 'restart' - restart the network"
    - 'generate' - generate required certificates and genesis block"
    - 'upgrade'  - upgrade the network from version 1.3.x to 1.4.0"
  -c <channel name> - channel name to use (defaults to \"mychannel\")"
  -t <timeout> - CLI timeout duration in seconds (defaults to 10)"
  -d <delay> - delay duration in seconds (defaults to 3)"
  -f <docker-compose-file> - specify which docker-compose file use (defaults to docker-compose-cli.yaml)"
  -s <dbtype> - the database backend to use: goleveldb (default) or couchdb"
  -l <language> - the chaincode language: golang (default), node, or java"
  -o <consensus-type> - the consensus-type of the ordering service: solo (default), kafka, or etcdraft"
  -i <imagetag> - the tag to be used to launch the network (defaults to \"latest\")"
  -v - verbose mode"
byfn.sh -h (print this message)"

Typically, one would first generate the required certificates and
genesis block, then bring up the network. e.g.:"

  byfn.sh generate -c mychannel"
  byfn.sh up -c mychannel -s couchdb"
  byfn.sh up -c mychannel -s couchdb -i 1.4.0"
  byfn.sh up -l node"
  byfn.sh down -c mychannel"
  byfn.sh upgrade -c mychannel"

Taking all defaults:"
      byfn.sh generate"
      byfn.sh up"
      byfn.sh down"

2.2 使用腳本 byfn.sh 構(gòu)建 Fabric 網(wǎng)絡(luò)的詳細步驟

Step 1. Generate Network Artifacts

$ ./byfn.sh generate

Step 2. Bring Up the Network

$ sudo ./byfn.sh up

Step 3. Bring Down the Network

$ sudo ./byfn.sh down

3. 拓展

在這一部分,將把上述通過腳本 byfn.sh 構(gòu)建的過程每一個關(guān)鍵步驟進行詳細解構(gòu),并通過手動執(zhí)行命令的方式來構(gòu)建 hyperledger fabric 網(wǎng)絡(luò)。

3.0 前置操作

下面的操作需要將容器 cli 的 FABRIC_LOGGING_SPEC 日志級別從 INFO 調(diào)整為 DEBUG。

first-network/docker-compose-cli.yaml

cli:
  container_name: cli
  image: hyperledger/fabric-tools:$IMAGE_TAG
  tty: true
  stdin_open: true
  environment:
    - GOPATH=/opt/gopath
    - CORE_VM_ENDPOINT=unix:///host/var/run/docker.sock
    - FABRIC_LOGGING_SPEC=DEBUG
    #- FABRIC_LOGGING_SPEC=INFO

3.1 Crypto Generator

  • cryptogen
    • 生成密碼組件的工具
    • 文件位置為 fabric-samples/bin/cryptogen
  • crypto-config.yaml
    • 配置文件,用于說明示例 first-network 需要生成的密碼組件
    • 文件位置為 first-network/crypto-config.yaml
  • crypto-config
    • 示例 first-network 生成的密碼組件
    • 文件位置為 first-network/crypto-config

3.2 Configuration Transaction Generator

  • configtxgen
    • 生成構(gòu)件,如
      • orderer genesis block,
      • channel configuration transaction,
      • and two anchor peer transactions - one for each Peer Org.
    • 文件位置為 fabric-samples/bin/configtxgen
  • configtx.yaml.yaml
    • 配置文件,用于說明示例 first-network 需要的構(gòu)件,一個 Orderer Org (OrdererOrg),和兩個 Peer Orgs (Org1 & Org2)。
    • 文件位置為 first-network/configtx.yaml
  • channel-artifacts
    • 示例 first-network 生成構(gòu)件
      • channel.tx
      • genesis.block
      • Org1MSPanchors.tx
      • Org2MSPanchors.tx
    • 文件位置為 first-network/channel-artifacts

3.3 通過工具獨立運行上述命令

下面,我們通過命令 cryptogen 和 configtxgen 手動生成上述的密碼組件和示例構(gòu)件。

3.3.1 手動生成密碼組件

參考腳本 byfn.sh 中的函數(shù) generateCerts().

$ ../bin/cryptogen generate --config=./crypto-config.yaml
org1.example.com
org2.example.com

最終的密碼組件會生成到目錄 first-network/crypto-config 中。

3.3.2 手動生成示例構(gòu)件

參考腳本 byfn.sh 中的函數(shù) generateChannelArtifacts().

$ export FABRIC_CFG_PATH=$PWD
$ ../bin/configtxgen -profile TwoOrgsOrdererGenesis -channelID byfn-sys-channel -outputBlock ./channel-artifacts/genesis.block

最終的示例構(gòu)件會生成到目錄 first-network/channel-artifacts 中,如 first-network/channel-artifacts/genesis.block。

3.3.3 Create a Channel Configuration Transaction

注意,需要設(shè)置環(huán)境變量 CHANNEL_NAME。

創(chuàng)建 first-network/channel-artifacts/channel.tx
# The channel.tx artifact contains the definitions for our sample channel

$ export CHANNEL_NAME=mychannel  && ../bin/configtxgen -profile TwoOrgsChannel -outputCreateChannelTx ./channel-artifacts/channel.tx -channelID $CHANNEL_NAME
創(chuàng)建 first-network/channel-artifacts/Org1MSPanchors.tx
$ ../bin/configtxgen -profile TwoOrgsChannel -outputAnchorPeersUpdate ./channel-artifacts/Org1MSPanchors.tx -channelID $CHANNEL_NAME -asOrg Org1MSP
創(chuàng)建 first-network/channel-artifacts/Org2MSPanchors.tx
$ ../bin/configtxgen -profile TwoOrgsChannel -outputAnchorPeersUpdate ./channel-artifacts/Org2MSPanchors.tx -channelID $CHANNEL_NAME -asOrg Org2MSP

3.4 Start the network

如果之前利用腳本 byfn.sh 啟動了測試網(wǎng)絡(luò),需要先關(guān)閉,如執(zhí)行下列命令

$ sudo ./byfn.sh down

3.4.1 Start the network

$ sudo docker-compose -f docker-compose-cli.yaml up -d

或通過下面的命令啟動,能夠立刻顯示日志,但需要另啟一個窗口運行下面的 cli 容器。

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

3.4.2 Create & Join Channel

$ sudo docker exec -it cli bash
root@33ab5acc5622:/opt/gopath/src/github.com/hyperledger/fabric/peer#

在容器 cli 中需要設(shè)置的環(huán)境變量。

# Environment variables for PEER0

$ 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
$ export CHANNEL_NAME=mychannel

# the channel.tx file is mounted in the channel-artifacts directory within your CLI container
# as a result, we pass the full path for the file
# we also pass the path for the orderer ca-cert in order to verify the TLS handshake
# be sure to export or replace the $CHANNEL_NAME variable appropriately

$ 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

上述命令將會生成文件 <CHANNEL_NAME.block>,這里是 mychannel.block

將 peer0.org1.example.com 加入到 channel
# By default, this joins ``peer0.org1.example.com`` only
# the <CHANNEL_NAME.block> was returned by the previous command
# if you have not modified the channel name, you will join with mychannel.block
# if you have created a different channel name, then pass in the appropriately named block

$ peer channel join -b mychannel.block
將 peer0.org2.example.com 加入到 channel
$ 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 channel join -b mychannel.block

3.4.3 Update the anchor peers

將 Org1 定義為 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
$ 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
將 Org2 定義為 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
$ 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

3.4.4 Install & Instantiate Chaincode

Chaincode 代碼支持 golang, node, java 語言,默認為 golang,本示例中全部使用默認值。

Install peer0 in Org1

首先設(shè)置 Org1 相關(guān)的環(huán)境變量。

$ 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
# this installs the Go chaincode. For go chaincode -p takes the relative path from $GOPATH/src
$ peer chaincode install -n mycc -v 1.0 -p github.com/chaincode/chaincode_example02/go/
Install peer0 in Org2

首先設(shè)置 Org2 相關(guān)的環(huán)境變量。

# Environment variables for PEER0 in Org2

$ 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
# this installs the Go chaincode. For go chaincode -p takes the relative path from $GOPATH/src
$ peer chaincode install -n mycc -v 1.0 -p github.com/chaincode/chaincode_example02/go/
Instantiate the chaincode on the channel
# be sure to replace the $CHANNEL_NAME environment variable if you have not exported it
# if you did not install your chaincode with a name of mycc, then modify that argument as well
$ export CHANNEL_NAME=mychannel
$ peer chaincode instantiate -o orderer.example.com:7050 --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 -C $CHANNEL_NAME -n mycc -v 1.0 -c '{"Args":["init","a", "100", "b","200"]}' -P "AND ('Org1MSP.peer','Org2MSP.peer')"

注意,-P "AND ('Org1MSP.peer','Org2MSP.peer')" 中的 AND 可以改為 OR,這意味著只需要 Org1 或 Org2 其中一個組織背書就可以了。

3.4.5 Query

# be sure to set the -C and -n flags appropriately

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

3.4.6 Invoke

# be sure to set the -C and -n flags appropriately

$ 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"]}'

3.4.7 Query

# be sure to set the -C and -n flags appropriately

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

返回結(jié)果

Query Result: 90

3.4.8 Install peer1 in Org2

首先設(shè)置好環(huán)境變量。

# Environment variables for PEER1 in Org2

$ 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=peer1.org2.example.com:10051
$ CORE_PEER_LOCALMSPID="Org2MSP"
$ CORE_PEER_TLS_ROOTCERT_FILE=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org2.example.com/peers/peer1.org2.example.com/tls/ca.crt
# this installs the Go chaincode. For go chaincode -p takes the relative path from $GOPATH/src
$ peer chaincode install -n mycc -v 1.0 -p github.com/chaincode/chaincode_example02/go/

3.4.9 Query by peer1 in Org2

首先需要將 peer1 in Org2 加入到 channel,之后才能響應(yīng)查詢。

$ 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=peer1.org2.example.com:10051
$ CORE_PEER_LOCALMSPID="Org2MSP"
$ CORE_PEER_TLS_ROOTCERT_FILE=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org2.example.com/peers/peer1.org2.example.com/tls/ca.crt
$ peer channel join -b mychannel.block
# be sure to set the -C and -n flags appropriately

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

返回結(jié)果

Query Result: 90

3.4.10 How do I see these transactions?

$ sudo docker logs -f cli

3.4.11 How can I see the chaincode logs?

$ sudo docker logs dev-peer0.org2.example.com-mycc-1.0
ex02 Init
Aval = 100, Bval = 200
ex02 Invoke
Query Response:{"Name":"a","Amount":"100"}
ex02 Invoke
Aval = 90, Bval = 210
ex02 Invoke
Query Response:{"Name":"a","Amount":"90"}

$ sudo docker logs dev-peer0.org1.example.com-mycc-1.0
ex02 Invoke
Aval = 90, Bval = 210

$ sudo docker logs dev-peer1.org2.example.com-mycc-1.0
ex02 Invoke
Query Response:{"Name":"a","Amount":"90"}

3.5 Using CouchDB

$ sudo docker-compose -f docker-compose-cli.yaml -f docker-compose-couch.yaml up -d

Reference

項目源代碼

項目源代碼會逐步上傳到 Github,地址為 https://github.com/windstamp

Contributor

  1. Windstamp, https://github.com/windstamp
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

推薦閱讀更多精彩內(nèi)容