本教程将讲述如何一步一步通过配置文件搭建hyperledger fabric区块链网络,教程涉及以下步骤,分别是
#1.生成注册证书材料和各个organization的证明材料(CA证书)
#2.生成orderer创世纪区块提供ordering服务,以及生成channel相关信息的配置文件
#3.创建channel以及把peer节点加入到channel中
#4.安装chaincode并初始化进行测试验收
以下是每个步骤的详解:
第一步:生成注册材料包括order organization和peer organization的root certificate(ca-cert)以及属于这些organization的成分的身份注册与证明材料;其中每个单独的organization拥有其ca证书,属于该organization中的成分的身份注册与证明材料(密钥)由该organization的ca颁发,最终通过私钥-公钥对完成对单独个体的数字签名身份认证。以上步骤涉及到的organization和属于该organization的成分在文件-crypto-config.yaml-中声明,并且通过工具cryptogen生成证书和密钥,该文件的具体内容如下:
OrdererOrgs:
- Name: Orderer
Domain: example.com
Specs:
- Hostname: orderer
PeerOrgs:
- Name: Org1
Domain: org1.example.com
EnableNodeOUs: true
Users:
Count: 1
- Name: Org2
Domain: org2.example.com
EnableNodeOUs: true
Template:
Count: 2
Users:
Count: 1
该文件涉及到三个organization,分别是一个OrdererOrgs与两个PeerOrgs。
这一步操作通过以下语句完成:
../bin/cryptogen generate --config=./crypto-config.yaml
由此生成的证书和密钥保存在文件夹-crypto-config-下。
第二步:在注册材料生成了以后,就需要定义一系列属于区块链系统的定义,包括一个orderer创世纪块(orderer genesis block),用以提供ordering服务(这一步理解为创建一个order organization以及该organization下的orderer节点);一个通道配置交易文件,用以在channel创建时广播到orderer,定义该channel的配置信息,包括属于该channel的organization等;以及多个anchor peer transaction(例子中是2个)文件,每个anchor peer transaction对应一个organization,用以指定该channel下每个organization的anchor peer(理解为organization的第一个peer)。
以上步骤涉及到的配置都在文件-configtx.yaml-中声明,并且通过工具configtxgen生成相关成分,-configtx.yaml-的内容如下:
Organizations:
- &OrdererOrg
Name: OrdererOrg
ID: OrdererMSP
MSPDir: crypto-config/ordererOrganizations/example.com/msp
- &Org1
Name: Org1MSP
ID: Org1MSP
MSPDir: crypto-config/peerOrganizations/org1.example.com/msp
AnchorPeers:
- Host: peer0.org1.example.com
Port: 7051
- &Org2
Name: Org2MSP
ID: Org2MSP
MSPDir: crypto-config/peerOrganizations/org2.example.com/msp
AnchorPeers:
- Host: peer0.org2.example.com
Port: 7051
Capabilities:
Global: &ChannelCapabilities
V1_1: true
Orderer: &OrdererCapabilities
V1_1: true
Application: &ApplicationCapabilities
V1_2: true
Application: &ApplicationDefaults
Organizations:
Orderer: &OrdererDefaults
OrdererType: solo
Addresses:
- orderer.example.com:7050
BatchTimeout: 2s
BatchSize:
MaxMessageCount: 10
AbsoluteMaxBytes: 99 MB
PreferredMaxBytes: 512 KB
Kafka:
Brokers:
- 127.0.0.1:9092
Organizations:
Profiles:
TwoOrgsOrdererGenesis:
Capabilities:
<<: *ChannelCapabilities
Orderer:
<<: *OrdererDefaults
Organizations:
- *OrdererOrg
Capabilities:
<<: *OrdererCapabilities
Consortiums:
SampleConsortium:
Organizations:
- *Org1
- *Org2
TwoOrgsChannel:
Consortium: SampleConsortium
Application:
<<: *ApplicationDefaults
Organizations:
- *Org1
- *Org2
Capabilities:
<<: *ApplicationCapabilities
在以上文件中,有几点需要注意的,分别是Organizations下的MSPDir,某个organization下的MSPDir为该organization的注册证明材料的文件系统路径(在上一步中已生成的材料);还有profiles下的两个可选参数,分别是TwoOrgsOrdererGenesis和TwoOrgsChannel,前者是生成orderer创世纪块,后者是生成与channel相关的配置信息。
以上操作分别通过以下命令执行:
#首先简单介绍configtxgen工具的参数
#Usage of ../bin/configtxgen:
# -asOrg string
# Performs the config generation as a particular organization (by name), only including values in the write set that org (likely) has privilege to set
# -channelID string
# The channel ID to use in the configtx
# -configPath string
# The path containing the configuration to use (if set)
# -inspectBlock string
# Prints the configuration contained in the block at the specified path
# -inspectChannelCreateTx string
# Prints the configuration contained in the transaction at the specified path
# -outputAnchorPeersUpdate string
# Creates an config update to update an anchor peer (works only with the default channel creation, and only for the first update)
# -outputBlock string
# The path to write the genesis block to (if set)
# -outputCreateChannelTx string
# The path to write a channel creation configtx to (if set)
# -printOrg string
# Prints the definition of an organization as JSON. (useful for adding an org to a channel manually)
# -profile string
# The profile from configtx.yaml to use for generation. (default "SampleInsecureSolo")
# -version
# Show version information
#configtxgen工具需要指定-configtx.yaml-的路径,因此进入-configtx.yaml-的目录路径并用以下语句声明
export FABRIC_CFG_PATH=$PWD
#生成orderer创世纪块
../bin/configtxgen -profile TwoOrgsOrdererGenesis -outputBlock ./channel-artifacts/genesis.block
#生成channel的相关信息文件,保存到channel.tx中
export CHANNEL_NAME=mychannel && ../bin/configtxgen -profile TwoOrgsChannel -outputCreateChannelTx ./channel-artifacts/channel.tx -channelID $CHANNEL_NAME
#指定channel下每个organization的anchor peer
../bin/configtxgen -profile TwoOrgsChannel -outputAnchorPeersUpdate ./channel-artifacts/Org1MSPanchors.tx -channelID $CHANNEL_NAME -asOrg Org1MSP
../bin/configtxgen -profile TwoOrgsChannel -outputAnchorPeersUpdate ./channel-artifacts/Org2MSPanchors.tx -channelID $CHANNEL_NAME -asOrg Org2MSP
第三步:以上步骤声明了很多区块链系统涉及到的成分的注册材料(包括organization的证书和密钥)、以及区块链网络的架构(比如说通过文件定义了channel以及channel下的成分),接下来我们就需要在区块链系统中创建架构中涉及的成分。以下步骤都是在docker的cli容器中进行的,可以通过以下语句启动cli容器并进入:
docker exec -it cli bash
首先是基于上一步的通道配置文件channel.tx创建一个新通道,并且指定与该channel相关的提供ordering服务的orderer节点。同时会生成一个创世纪块,并加入到该channel中(我的理解是:channel是一种虚的东西,需要通过一个实的创世纪块来代表,并且区块链需要从创世纪块开始不断往后添加新的区块),创世纪块的名字为-channel-ID.block-。这一步可以通过以下命令执行:
#-o 能为该channel提供ordering 服务的节点,该节点在orderer创世纪块被创建的时候就以及生成
#-f 通道的相关配置信息的文件系统路径,上一步已经生成
#-c 通道的名字
# --tls --cafile(+ local path) 与处于local path的orderer root cert进行握手,验证通道是否能与orderer节点进行连接,以确保能提供服务
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
接着需要把每个organization的peer节点加入到channel中,容器中默认的环境变量是属于Org1的,因此执行以下命令的时候会默认把Org1的peer0加入到channel:
peer channel join -b mychannel.block
接着需要把Org2的peer0加入到channel中,因此需要首先修改环境变量才能加入,完整的命令如下:
#前三个就为需要修改的环境变量,与Org(x)相关
CORE_PEER_MSPCONFIGPATH=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org2.example.com/users/[email protected]/msp CORE_PEER_ADDRESS=peer0.org2.example.com:7051 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
请注意前面一步只是把Org1和Org2的peer0加入到了channel中,接着还需要根据anchor peer的配置信息文件定义每个Org的anchor peer从而更新整个channel(相当于执行一个定义文件-Org(x)MSPanchors.tx-)。
更新Org1的anchor peer:
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的anchor peer:
CORE_PEER_MSPCONFIGPATH=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org2.example.com/users/[email protected]/msp CORE_PEER_ADDRESS=peer0.org2.example.com:7051 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
第四步:此时,整个区块链网络的所有成分已经搭建完成,包括虚的定义关系的文件和实的区块链成分实体,接下来是往区块链网络安装chaincode并进行测试的过程,由于应用程序通过连接peer调用chaincode与区块链系统进行交互,因此chaincode是安装到所有peer上的。
首先是安装chaincode,可以通过以下命令执行
#-n chaincode的名字
#-v chaincode的版本
#-p chaincode的安装路径,为一个go文件夹下
peer chaincode install -n mycc -v 1.0 -p github.com/chaincode/chaincode_example02/go/
接下来进行初始化(或升级)chaincode到某个channel上,可以通过以下命令执行
#-C 通道的名字,必须对应某个已存在的通道
#-n chaincode的名字
#-v chaincode的版本,当chaincode需要升级为新版本时,可以定义为不同的版本并进行upgrade(peer chaincode upgrade)
#-c 初始化的内容,参数必须对应于chaincode的go代码的Init函数的参数列表
#-P endorsement policy,在这个例子中只需要任意一个organization的peer认可proposal就能通过
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 "OR ('Org1MSP.peer','Org2MSP.peer')"
以下是测试阶段
#查询a账户的余额
peer chaincode query -C $CHANNEL_NAME -n mycc -c '{"Args":["query","a"]}'
#转账
peer chaincode invoke -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 -c '{"Args":["invoke","a","b","10"]}'
#再次查询转账后a账户的余额
peer chaincode query -C $CHANNEL_NAME -n mycc -c '{"Args":["query","a"]}'