构建第一个 Hyperledger Fabric 网络
构建第一个 Hyperledger Fabric 网络
Hyperledger Fabric 最新的文档基于版本是 v2.0 Alpha release。由于示例中相关的 docker 镜像的版本是 v1.4.3,因为相关文档需要参考的版本为 v1.4.3。这些文档链接在本文的 Reference 部分都有涉及。
1. 本文目的
参考文档 Building Your First Network 搭建第一个 Hyperledger Fabric 网络。本示例 fabric-samples 需要的 hyperledger fabric 相关的二进制程序安装参考文档 Install Samples, Binaries and Docker Images。而安装 hyperledger fabric 相关的二进制程序所需要的一些前置软件需求,请参考文档 Prerequisites。
2. 构建 Hyperledger Fabric 网络
根据 fabric-samples/first-network 示例搭建第一个 Hyperledger Fabric 网络。这里,主要是基于提供的脚本 byfn.sh 来快速搭建。脚本 byfn.sh 提供了许多可配置的参数,如果不提供则使用默认值。这里为了简化,先使用默认值。
需要注意的是,下面的命令需要在 first-network 目录下运行,但是调用的 hyperledger fabric 相关的二进制程序却是在 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 构建 Fabric 网络的详细步骤
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 构建的过程每一个关键步骤进行详细解构,并通过手动执行命令的方式来构建 hyperledger fabric 网络。
3.0 前置操作
下面的操作需要将容器 cli 的 FABRIC_LOGGING_SPEC 日志级别从 INFO 调整为 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
- 生成构件,如
- orderer
genesis block
, - channel
configuration transaction
, - and two
anchor peer transactions
- one for each Peer Org.
- orderer
- 文件位置为 fabric-samples/bin/configtxgen
- 生成构件,如
- configtx.yaml.yaml
- 配置文件,用于说明示例 first-network 需要的构件,一个 Orderer Org (
OrdererOrg
),和两个 Peer Orgs (Org1
&Org2
)。 - 文件位置为 first-network/configtx.yaml
- 配置文件,用于说明示例 first-network 需要的构件,一个 Orderer Org (
- channel-artifacts
- 示例 first-network 生成构件
- channel.tx
- genesis.block
- Org1MSPanchors.tx
- Org2MSPanchors.tx
- 文件位置为 first-network/channel-artifacts
- 示例 first-network 生成构件
3.3 通过工具独立运行上述命令
下面,我们通过命令 cryptogen 和 configtxgen 手动生成上述的密码组件和示例构件。
3.3.1 手动生成密码组件
参考脚本 byfn.sh 中的函数 generateCerts().
$ ../bin/cryptogen generate --config=./crypto-config.yaml
org1.example.com
org2.example.com
最终的密码组件会生成到目录 first-network/crypto-config 中。
3.3.2 手动生成示例构件
参考脚本 byfn.sh 中的函数 generateChannelArtifacts().
$ export FABRIC_CFG_PATH=$PWD
$ ../bin/configtxgen -profile TwoOrgsOrdererGenesis -channelID byfn-sys-channel -outputBlock ./channel-artifacts/genesis.block
最终的示例构件会生成到目录 first-network/channel-artifacts 中,如 first-network/channel-artifacts/genesis.block。
3.3.3 Create a Channel Configuration Transaction
注意,需要设置环境变量 CHANNEL_NAME。
创建 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
创建 first-network/channel-artifacts/Org1MSPanchors.tx
$ ../bin/configtxgen -profile TwoOrgsChannel -outputAnchorPeersUpdate ./channel-artifacts/Org1MSPanchors.tx -channelID $CHANNEL_NAME -asOrg Org1MSP
创建 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 启动了测试网络,需要先关闭,如执行下列命令
$ 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 中需要设置的环境变量。
# 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
首先设置 Org1 相关的环境变量。
$ 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
首先设置 Org2 相关的环境变量。
# 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"]}'
返回结果
Query Result: 90
3.4.8 Install peer1 in Org2
首先设置好环境变量。
# 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,之后才能响应查询。
$ 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"]}'
返回结果
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
- Building Your First Network, https://hyperledger-fabric.readthedocs.io/en/latest/build_network.html
- Building Your First Network - v1.4, https://hyperledger-fabric.readthedocs.io/en/release-1.4/build_network.html
- Prerequisites, https://hyperledger-fabric.readthedocs.io/en/latest/prereqs.html
- Install Samples, Binaries and Docker Images, https://hyperledger-fabric.readthedocs.io/en/latest/install.html
- fabric-samples, https://github.com/hyperledger/fabric-samples
- x.509 certificates and public key infrastructure, https://en.wikipedia.org/wiki/Public_key_infrastructure
- cryptogen, https://hyperledger-fabric.readthedocs.io/en/latest/commands/cryptogen.html
- configtxgen, https://hyperledger-fabric.readthedocs.io/en/latest/commands/configtxgen.html
项目源代码
项目源代码会逐步上传到 Github,地址为 https://github.com/windstamp。
Contributor
- Windstamp, https://github.com/windstamp