本文适用于linux环境。

先放文档地址:

官方文档:http://hyperledger-fabric.readthedocs.io/en/latest/

中文文档:https://hyperledgercn.github.io/hyperledgerDocs/

一、准备条件

需要安装的软件:git、cURL、docker和docker-compose、go语言、nodejs和npm、python,网上有好多教程,自行安装。

下面来下载Fabric需要的镜像(在gopath/src/github.com/hyperledger/目录下):

(注:如果已经下载了fabric的镜像,但是没有fabric-samples这个文件夹,可以单独下载,放在本地任意目录都行,地址https://github.com/hyperledger/fabric-samples  本文使用的fabric1.1版本,下载这个样例时版本一定要和你使用的镜像的版本一致,要不。。。都是泪)

curl -sSL https://goo.gl/6wtTN5 | bash

这条命令是从这个地址上下载一个脚本,然后执行脚本的命令进行下载(地址可能会变,可以参考官方文档

这是会有个fabric-simples文件夹,进入。

设置环境变量:

sudo gedit ~/.bashrc

然后在最后一行加入:

export PATH=$PATH:/home/zhj/project/gopath/src/github.com/hyperledger/test/fabric-samples/bin

将里面的路径换成你自己的安装路径。

现在需下载的环境已经准备好,下面以first-network这个文件夹进行搭建第一个Fabric网络。

二、部署网络

本部分利用已下载的自带脚本自动执行所有操作,包括搭建起一个Fabric网络,其中包括一个order和四个分别属于两个组织的peer;加入channel;部署执行chaincode。

1、生成所有秘钥和证书

cd first-network/
./byfn.sh -m generate

第一步生成我们各种网络实体的所有证书和密钥,genesis block用于引导排序服务,以及配置Channel所需要的一组交易配置集合 。

2、启动网络

./byfn.sh -m up

来看一下输出日志的主要事件(省略中间大部分输出):

===================== Channel "mychannel" is created successfully ===================== 
===================== peer0.org1 joined on the channel "mychannel" ===================== 
===================== peer1.org1 joined on the channel "mychannel" ===================== 
===================== peer0.org2 joined on the channel "mychannel" ===================== 
===================== peer1.org2 joined on the channel "mychannel" ===================== 
===================== Anchor peers for org "Org1MSP" on "mychannel" is updated successfully ===================== 
===================== Anchor peers for org "Org2MSP" on "mychannel" is updated successfully ===================== 
===================== Chaincode is installed on peer0.org1 ===================== 
===================== Chaincode is installed on peer0.org2 ===================== 
===================== Chaincode Instantiation on peer0.org2 on channel 'mychannel' is successful ===================== 
===================== Query on peer0.org1 on channel 'mychannel' is successful ===================== 
===================== Invoke transaction on peer0.org1 on channel 'mychannel' is successful ===================== 
===================== Chaincode is installed on peer1.org2 ===================== 
===================== Query on peer1.org2 on channel 'mychannel' is successful =====================

可以看到,先创建了一个channel,然后将四个peer节点分别加入channel中,再设置两个组织的锚节点。

(下面进行chaincode操作,chaincode的要实现的是:初始化两个账户a和b,分别拥有100和200的余额,可以执行查询、转账操作)

在两个锚节点上分别安装chaincode,在channel上实例化chaincode,然后开始对chaincode进行操作:在组织1的锚节点上执行查询操作,调用转账操作;在组织2的peer1上安装chaincode并执行查询操作。可以看到peer0.org1对chaincode执行修改操作后,在peer1.org2节点可以看到修改后的结果。

3、关闭网络

./byfn.sh -m down

包括关闭容器,移除加密材料和4个配置信息,并且从Docker仓库删除chaincode镜像。

以上是通过example自带的脚本来自动执行所有的操作,仔细研究每一步的话,可以查看脚本中的内容。下面通过手动配置的方法来实现以上的各功能。

三、手动配置网络

1、手动生成配置文件

(1)生成证书、秘钥

cryptogen generate --config=./crypto-config.yaml

使用cryptogen工具根据crypto-config.yaml配置文件生成各种网络实体的加密材料(x509证书)。这些证书是身份的代表,它们允许在我们的网络实体进行交流和交易时进行签名/验证身份验证。执行tree crypto-config操作,可以看到生成了ordererOrganizations 和peerOrganizations两个组织,其中peerOrganizations中包含org1.example.com和org2.example.com两个组织。

每个组织都配置了唯一的根证书(ca-cert),它将特定组件(peers和orders)绑定到该组织。通过为每一个组织分配唯一的CA证书,我们正在模仿一个经典的网络,这个网络中的成员将使用自己的证书颁发机构。Hyperledger Fabric中的交易和通信是通过存储在keystore中的实体的私钥签名,然后通过公钥手段进行验证(signcerts)。

(2)配置交易生成器

configtxgen tool用于创建4个配置工作: order的genesis block, channel的channel configuration transaction, * 以及两个anchor peer transactions一个对应一个Peer组织。order block是一个ordering service的创世区块,channel transaction文件在Channel创建的时侯广播给order。anchor peer transactions,正如名称所示,指定了每个组织在此channel上的Anchor peer。

Configtxgen使用一个包含示例网络的configtx.yaml文件。有3个成员:一个排序服务组织OrdererOrg以及两个节点组织(Org1&Org2),每个组织管理和持有2个peer节点。该文件还指定了一个SampleConsortium的联盟,由上述2个节点组织构成。下面进行配置

生成order的genesis block:

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

创建channel transaction的配置:

export CHANNEL_NAME=mychannel
configtxgen -profile TwoOrgsChannel -outputCreateChannelTx ./channel-artifacts/channel.tx -channelID $CHANNEL_NAME

在通道上定义org1和org2的锚节点:

configtxgen -profile TwoOrgsChannel -outputAnchorPeersUpdate ./channel-artifacts/Org1MSPanchors.tx -channelID $CHANNEL_NAME -asOrg Org1MSP
configtxgen -profile TwoOrgsChannel -outputAnchorPeersUpdate ./channel-artifacts/Org2MSPanchors.tx -channelID $CHANNEL_NAME -asOrg Org2MSP

以上生成的配置都放在了channel-artifacts/这个文件夹中,查看一下现在包含的文件:tree channel-artifacts/

channel-artifacts/
├── channel.tx
├── genesis.block
├── Org1MSPanchors.tx

└── Org2MSPanchors.tx

查看排序创世区块和通道创世区块的命令分别是:

configtxgen -profile TwoOrgsOrdererGenesis -inspectBlock ./channel-artifacts/genesis.block
configtxgen -profile TwoOrgsOrdererGenesis -inspectChannelCreateTx ./channel-artifacts/channel.tx

会以json格式解析给出区块的内容.

2、启动网络

使用docker-compose根据配置文件来启动网络(配置文件不只是docker-compose-cli.yaml,还包括order节点和peer节点的配置,详见这篇文章):

CHANNEL_NAME=$CHANNEL_NAME TIMEOUT=10 docker-compose -f docker-compose-cli.yaml up -d

其中cli充当客户端的作用,cli和peer连接,将指令发送给peer节点上执行。默认是peer0.org1节点。

3、创建并加入channel

加入cli容器:

docker exec -it cli bash

如果显示下面这样,说明成功:

root@0d83760ad1aa:/opt/gopath/src/github.com/hyperledger/fabric/peer#

将节点切换到peer0.org1:

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

下面进行创建channel,应该与前面创建的channel配置保持一样的channel名字

export CHANNEL_NAME=mychannel
ORDERER_CA=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/ordererOrganizations/example.com/orderers/orderer.example.com/msp/tlscacerts/tlsca.example.com-cert.pem
peer channel create -o orderer.example.com:7050 -c $CHANNEL_NAME -f ./channel-artifacts/channel.tx --tls $CORE_PEER_TLS_ENABLED --cafile $ORDERER_CA

使用-c标志指定channel的名字,-f标志指定配置交易,在这个例子中它是channel.tx。

这时可以看到目录中多了一个创世区块mychannel.block,它包含了channel.tx的配置信息,我们使用它加入channel。

下面加入peer0.org1的通道,进行链码的相关配置:

peer channel join -b mychannel.block

现在已经加入peer0.org1的通道,下面将其他三个节点也加入通道中:

 

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 
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=peer1.org1.example.com:7051

peer channel join -b mychannel.block
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 
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:7051

peer channel join -b mychannel.block

 

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 
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:7051

peer channel join -b mychannel.block

更新锚节点:

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 
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

peer channel update -o orderer.example.com:7050 -c mychannel -f ./channel-artifacts/Org1MSPanchors.tx --tls true --cafile $ORDERER_CA
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 
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:7051

peer channel update -o orderer.example.com:7050 -c mychannel -f ./channel-artifacts/Org2MSPanchors.tx --tls true --cafile $ORDERER_CA

4、安装和实例化链码

下面安装和实例化链码都是在节点peer0.org1上操作的,应先切换到该节点,切换方法上面有。

在每个会执行并背书交易的节点上安装chaincode,并在通道上实例化。注意:每个相关节点都需要安装一遍,在通道上实例化只需要一次即可。

这里安装一个已经下载好的链码,在我cli的容器中位置是:/opt/gopath/src/github.com/chaincode/chaincode_example02/go,可能不太一样,自己找一下。

peer chaincode install -n mycc -v 1.0 -p github.com/chaincode/chaincode_example02/go

下面在通道上实例化链码,需要指定背书策略:

peer chaincode instantiate -o orderer.example.com:7050 --tls $CORE_PEER_TLS_ENABLED --cafile $ORDERER_CA -C $CHANNEL_NAME -n mycc -v 1.0 -c '{"Args":["init","a", "100", "b","200"]}' -P "OR ('Org1MSP.member','Org2MSP.member')"

其中-c '{"Args":["init","a", "100", "b","200"]}'是初始化链码,-P "OR ('Org1MSP.member','Org2MSP.member')"是指定背书策略,即两个组织中任何一个节点背书即可

5、执行链码

先执行查询操作,我们在上一步初始化的时候,将a的值设为100,b的值设为200,现在查询一下a的值:

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

返回结果为:

2018-06-15 03:21:12.859 UTC [chaincodeCmd] checkChaincodeCmdParams -> INFO 001 Using default escc
2018-06-15 03:21:12.859 UTC [chaincodeCmd] checkChaincodeCmdParams -> INFO 002 Using default vscc
Query Result: 100
2018-06-15 03:21:12.863 UTC [main] main -> INFO 003 Exiting.....

可以看到查询结果为100.下面进行修改操作,从a给b转账10:

peer chaincode invoke -o orderer.example.com:7050  --tls $CORE_PEER_TLS_ENABLED --cafile $ORDERER_CA -C $CHANNEL_NAME -n mycc -c '{"Args":["invoke","a","b","10"]}'

然后在执行查询操作可以看到a的值变为90,b的值变为210

现在切换到peer1.org2节点上执行查询操作:

安装chaincode并执行查询操作:

 

peer chaincode install -n mycc -v 1.0 -p github.com/chaincode/chaincode_example02/go/
peer chaincode query -C $CHANNEL_NAME -n mycc -c '{"Args":["query","a"]}'
peer chaincode query -C $CHANNEL_NAME -n mycc -c '{"Args":["query","b"]}'

可以看到查询结果a是90,b是210.

6、查看日志,清除操作

所有操作已执行完,执行exit退出cli通道,使用docker logs [name]命令可以查看相关通道的日志,如

docker logs dev-peer0.org1.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

下面清理操作:

./byfn.sh -m down

所有的通道和链码镜像等都被清除。