一朵小奇葩✿ۣ

导航

Hyperledger Fabric V2.0(五)手动搭建Fabric网络(基于first-network案例)

如果还不具备Hyperledger Fabric V2.0的完整环境,请参考:Hyperledger Fabric(一)V2.0基础环境搭建。在具备基础环境后,便可进行Fabric网络的部署工作。可以参照官网文档关于first-network案例的部分,使用提供的脚本文件快速启动区块链网络。但为了搭建自定义的Fabric网络,需要掌握脚本所执行的具体操作。

脚本部署Fabric网络的方式如下(启用CAs,使用couchdb):

Ⅰ cd fabric-samples/first-network   #进入fabric-samples/first-network目录

Ⅱ ./byfn.sh down   #若已经进行过部署,则销毁已有网络;若第一次部署,则忽略该步骤

Ⅲ ./byfn.sh up -a -n -s couchdb   #参数-a启动证书颁发机构,-n不部署abstore链码(脚本默认部署该链码),-s使用couchdb数据库而不是goleveldb ,关于该脚本的详细使用帮助可通过./byfn.sh -h查看

等效的手动部署Fabric网络的方式如下(启用CAs,使用couchdb):

Ⅰ 为网络中的实体生成证书及密钥,生成联盟通道配置组件,启动Fabric网络

cd fabric-samples/first-network   #进入fabric-samples/first-network目录

① 使用cryptogen工具生成证书及密钥,放置于crypto-config目录下

cryptogen generate --config=./crypto-config.yaml   #byfn.sh脚本中的generateCerts()函数调用cryptogen工具后,还调用了同一目录下的ccp-generate.sh脚本为Org1和Org2生成CCP文件(供后期SDK使用),在此先忽略

② 使用configtxgen工具生成4个配置组件(genesis.block,channel.tx,Org1MSPanchors.tx,Org2MSPanchors.tx),放置于 channel-artifacts目录下

export FABRIC_CFG_PATH=$PWD   #告诉configtxgen从哪里寻找configtx.yaml文件

configtxgen -profile SampleMultiNodeEtcdRaft -channelID byfn-sys-channel -outputBlock ./channel-artifacts/genesis.block   #生成系统通道创世区块genesis.block

export CHANNEL_NAME=mychannel   #通过环境变量指定通道名称

configtxgen -profile TwoOrgsChannel -outputCreateChannelTx ./channel-artifacts/channel.tx -channelID $CHANNEL_NAME   #创建 通道配置 事务channel.tx

configtxgen -profile TwoOrgsChannel -outputAnchorPeersUpdate ./channel-artifacts/Org1MSPanchors.tx -channelID $CHANNEL_NAME -asOrg Org1MSP   #创建 更新组织Org1在该通道上的锚节点 的事务Org1MSPanchors.tx

configtxgen -profile TwoOrgsChannel -outputAnchorPeersUpdate ./channel-artifacts/Org2MSPanchors.tx -channelID $CHANNEL_NAME -asOrg Org2MSP   #创建 更新组织Org2在该通道上的锚节点 的事务Org2MSPanchors.tx

结果如下:

③ 使用docker compose基于yaml配置文件启动容器,建立Fabric网络(使用CAs与couchdb)

export BYFN_CA1_PRIVATE_KEY=$(cd crypto-config/peerOrganizations/org1.example.com/ca && ls *_sk)   #以环境变量的形式指定每个组织的CA的私钥,CA节点的yaml配置文件中会使用该变量

export BYFN_CA2_PRIVATE_KEY=$(cd crypto-config/peerOrganizations/org2.example.com/ca && ls *_sk)

docker-compose -f docker-compose-cli.yaml -f docker-compose-etcdraft2.yaml -f docker-compose-ca.yaml -f docker-compose-couch.yaml up -d   #参数-d用于不显示实时日志,若想查看日志流,后续命令则需要打开另一个终端来执行

docker ps   #查看已启动容器的基本信息,包括一个cli,四个peer,四个couchdb,五个order,两个ca

docker network inspect net_byfn   #可查看网络信息

Ⅱ 创建通道,将peer节点加入通道,并更新组织的锚节点

docker exec -it cli bash   #进入CLI(命令行)容器

配置环境变量,以使CLI容器作为peer0.org1.example.com节点执行命令,后续很多操作需要不断地切换这组环境变量,以作为不同的peer节点执行相关操作,节点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

为了便于查看,在此也先给出节点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

① 将通道配置事务发送给order节点以创建通道

export CHANNEL_NAME=mychannel   #以环境变量形式指定通道名称,必须全部小写

peer channel create -o orderer.example.com:7050 -c $CHANNEL_NAME -f ./channel-artifacts/channel.tx --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   #若通道创建成功,将接收到来自order节点的通道的创世区块,以通道名称命名

② 切换peer节点的环境变量,多次执行以下命令,将节点加入通道

peer channel join -b $CHANNEL_NAME.block   #命令中的$CHANNEL_NAME.block,根据通道名称而变化

③ 切换peer节点的环境变量,多次执行以下命令,为每个组织指定其在当前通道中的锚节点,每个组织至少有一个锚节点

peer channel update -o orderer.example.com:7050 -c $CHANNEL_NAME -f ./channel-artifacts/${CORE_PEER_LOCALMSPID}anchors.tx --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   #为组织指定锚节点

 至此./byfn.sh up -a -n -s couchdb所执行的所有工作均通过手动操作实现,若去掉参数-n,该脚本将会继续执行abstore链码的部署与测试工作,同样可以纯手动完成任何链码的部署与测试。

Ⅲ 链码的打包、安装、定义、提交与调用测试等部署过程如下(在此以abstore为例,也可使用自己编写的链码):

① 打包链码(以java语言为例,node可通过--lang node指定,go语言稍有不同,请参考官网文档)。脚本中命令格式为peer lifecycle chaincode package mycc.tar.gz --path ${CC_SRC_PATH} --lang ${CC_RUNTIME_LANGUAGE} --label mycc_${VERSION}),mycc为链码名称(可自定义),参数--lang指定链码使用的编程语言,--label指定链码标签(通常采用 名称_版本 的格式),--path指定链码的存储路径,docker-compose-cli.yaml文件中有卷的映射关系./../chaincode/:/opt/gopath/src/github.com/hyperledger/fabric-samples/chaincode,因此主机的fabric-samples/chaincode目录对应着peer容器的/opt/gopath/src/github.com/hyperledger/fabric-samples/chaincode目录

peer lifecycle chaincode package mycc.tar.gz --path /opt/gopath/src/github.com/hyperledger/fabric-samples/chaincode/abstore/java/ --lang java --label mycc_1   #一定要根据自己链码的实际存储位置,修改 --path的值,目录对应关系见上述

② 切换peer节点的环境变量,多次执行以下命令,在不同节点安装链码

peer lifecycle chaincode install mycc.tar.gz   #注意链码包名称mycc.tar.gz与前一条命令保持一致,该命令执行期间很容易报错Error: failed to endorse chaincode install: rpc error: code = Unavailable desc = transport is closing,原因未知。解决方案:稍等两分钟,再次执行命令(高频率重复执行命令将引起其它错误),一般第二次就会成功

③ 查询节点上已安装的链码,将链码ID设置为环境变量(后续命令会用到)

peer lifecycle chaincode queryinstalled   #可看到已安装链码包的ID以及标签

CC_PACKAGE_ID=mycc_1:3a8c52d70c36313cfebbaf09d8616e7a6318ababa01c7cbe40603c373bcfe173   #这个ID是动态的,不要直接复制此命令

④ 切换peer节点的环境变量,多次执行以下命令,所有组织就链码定义达成一致(只需要每个组织的某个peer执行一次)

peer lifecycle chaincode approveformyorg --channelID $CHANNEL_NAME --name mycc --version 1.0 --init-required --package-id $CC_PACKAGE_ID --sequence 1 --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   #官方脚本中--version和--sequence的值一致,不太清楚两个值的差别

⑤  检查组织是否就链码定义已经达成一致

peer lifecycle chaincode checkcommitreadiness --channelID $CHANNEL_NAME --name mycc --version 1.0 --init-required --sequence 1 --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 --output json   #查看各组织对链码定义的批准状况

⑥  将链码定义提交到通道(任何组织的某个节点执行一次即可)

peer lifecycle chaincode commit -o orderer.example.com:7050 --channelID $CHANNEL_NAME --name mycc --version 1.0 --sequence 1 --init-required --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 --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   

⑦ 查询链码定义

peer lifecycle chaincode querycommitted --channelID $CHANNEL_NAME --name mycc

⑧ 调用链码的初始化函数

peer chaincode invoke -o orderer.example.com:7050 --isInit --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":["Init","a","100","b","100"]}' --waitForEvent   #-c指定调用链码函数的参数,请根据自己的链码进行修改(第一个参数为函数名)

⑨ 调用链码的查询(query)函数

peer chaincode query -C $CHANNEL_NAME -n mycc -c '{"Args":["query","a"]}'   #-c指定调用链码函数的参数,请根据自己的链码进行修改(第一个参数为函数名)

⑩ 调用链码的invoke函数,a向b转账十元,该事务提交后,再次查询a的值将为90

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"]}' --waitForEvent   #-c指定调用链码函数的参数,请根据自己的链码进行修改(第一个参数为函数名)

 至此,Fabric网络已经通过手动方式完成部署,可通过执行./byfn.sh down来销毁该网络。若想根据具体实际需求自定义网络的成员组织或组织中节点的数量,则需要修改crypto-config.yaml、configtx.yaml以及启动docker容器的yaml配置文件。关于first-network案例使用到的配置文件的简介,请参照Hyperledger Fabric(四)first-network案例中的主要配置文件及主要脚本

posted on 2020-03-05 00:57  always-kaixuan  阅读(4263)  评论(10编辑  收藏  举报