作者:ethanlu([email protected])
创建于:2018/7/18
最后修改:2018/7/18
1、安装预置环境
检查一下在开发区块链应用程序或者Hyperledger Fabric的平台上是否已经安装了预置环境。
1、下载并安装Hyperledger的Fabric-samples
。fabric-samples
文件夹中包含了许多示例:
需要git branch 切换到v1.0.2(git checkout v.1.0.2)否则报错。
git clone https://github.com/hyperledger/fabric-samples.git
2、我们将使用first-network
这个例子。现在让我们打开这个子目录。
cd first-network
注意:本文档中提供的命令必须运行在fabric-sample
的子目录first-network
中。如果你选择从其他位置运行命令,提供的一些列脚本将无法找到对应的二进制工具。
3、我们提供一个完全注释的脚本byfn.sh,利用这些Docker镜像可以快速引导一个由4个代表2个不同组织的peer节点以及一个排序服务节点的Hyperledger fabric
网络。它还将启动一个容器来运行一个将peer节点加入channel、部署实例化链码服务以及驱动已经部署的链码执行交易的脚本。
./byfn.sh -h
以下是该byfn.sh
脚本的帮助文档:
如果你选择不提供channel名称,则脚本将使用默认名称mychannel
。CLI超时参数(用-t标志指定)是一个可选值;如果你选择不设置它,那么CLI容器将会在脚本执行完之后退出。
4、执行该脚本:
./byfn.sh -m generate
接下来,可以使用以下命令来启动整个网络。再试提示是否继续。回答y:
生成工具后会出现如下界面:
第一步生成我们各种网络实体的所有证书和密钥,genesis block
用于引导排序服务,以及配置Channel
所需要的一组交易配置集合。
5、接下来,使用以下命令来启动整个网络:
./byfn.sh -m up
日志将继续。然后启动所有容器,驱动一个端到端的应用场景。成功以后,在终端窗口中会报告以下内容:
跑通之后会出现如下界面:
6、最后,让我们把它全部停下来,这样我们可以一步一步地探索网络设置。以下操作将关闭你的容器,移除加密材料和4个配置信息,并且从Docker仓库删除chaincode镜像。你将再一次被提示是否继续,回答y:
./byfn.sh -m down
测试用例说明:
1、加密生成器
Cryptogen
消费一个包含网络拓扑的crypto-config.yaml
,并允许我们为组织和属于这些组织的组件生成一组证书和密钥。每个组织都配置了唯一的根证书(ca-cert
),它将特定组件(peers和orders)绑定到该组织。通过为每一个组织分配唯一的CA证书,我们正在模仿一个经典的网络,这个网络中的成员将使用自己的证书颁发机构。Hyperledger Fabric中的交易和通信是通过存储在keystore
中的实体的私钥签名,然后通过公钥手段进行验证(signcerts
)。
你将注意到在这个文件里有一个count
变量。我们将使用它来指定每个组织中peer
的数量;在我们的例子中,每个组织有两个peer。我们现在不会深入研究x.509证书和公钥基础设施的细节。如果你有兴趣,你可以在自己的时间细读这些主题。
在运行该工具之前,让我们快速浏览一下这段代码crypto-config.yaml
。特别注意在OrdererOrgs
头下的Name
,Domain
和Specs
参数:
OrdererOrgs:
#---------------------------------------------------------
# Orderer
# --------------------------------------------------------
- Name: Orderer
Domain: example.com
# ------------------------------------------------------
# "Specs" - See PeerOrgs below for complete description
# -----------------------------------------------------
Specs:
- Hostname: orderer
# -------------------------------------------------------
# "PeerOrgs" - Definition of organizations managing peer nodes
# ------------------------------------------------------
PeerOrgs:
# -----------------------------------------------------
# Org1
# ----------------------------------------------------
- Name: Org1
Domain: org1.example.com
网络实体的命名约定如下:”{{.Hostname}}.{{.Domain}}”。所以使用我们的排序节点作为参考点,它与Order
的MSP ID相关联。该文件包含了有关定义和语法的大量文档。
我们运行cryptogen
工具,生成的证书和密钥将被保存到名为crypto-config
的文件夹中。
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个节点组织构成。 请特别注意此文件顶部的”Profiles”部分。你会注意到我们有两个独特的标题。一个是orderer的创世区块-TwoOrgsOrdererGenesis
-另一个是针对管道的TwoOrgsChannel
。
此文件还包含两个值得注意的附加规格。首先,我们为每个组织指定了锚点节点(peer0.org1.example.com
和peer0.org2.example.com
)。其次,我们为每个成员指定MSP文件夹,用来存储每个组织在orderer genesis block
中指定的根证书。这是一个关键的概念。现在任意和ordering service通信的网络实体都可以对其数字签名进行验证。
3、运行工具
你可以用configtxgen
和cryptogen
命令来手动生成证书/密钥和各种配置文件。或者,你可以尝试使用byfn.sh
脚本来完成你的目标。
必要的话,你可以参考byfn.sh脚本中的generateCerts
函数去生成相关定义在crypto-config.yaml
文件中用于你的网络配置的相关证书。然而,为了方便起见,我们也将在此提供参考。
首先,我们来运行cryptogen
这个工具。我们的二进制文件在bin
目录中,所以我们需要提供工具所在的相对路径。
../bin/cryptogen generate --config=./crypto-config.yaml
接下来,我们需要告诉configtxgen
工具需要提取的configtx.yaml
所在的位置。我们会告诉它在我们当前所在工作目录:
首先,我们需要设置一个环境变量来告诉configtxgen
哪里去寻找configtx.yaml。然后,我们将调用configtxgen
工具去创建orderer genesis block
:
export FABRIC_CFG_PATH=$PWD
../bin/configtxgen -profile TwoOrgsOrdererGenesis -outputBlock ./channel-artifacts/genesis.block
你可以忽略有关中间证书,证书撤销列表(crls)和MSP配置的日志警告。我们没有在示例网络中使用其中的任何一个。
接下来,我们需要创建channel transaction
配置。请确保替换$CHANNEL_NAME
或者将CHANNEL_NAME
设置为整个说明中可以使用的环境变量:
export CHANNEL_NAME=mychannel
# this file contains the definitions for our sample channel
../bin/configtxgen -profile TwoOrgsChannel -outputCreateChannelTx ./channel-artifacts/channel.tx -channelID $CHANNEL_NAME
接下来,我们将在正在构建的通道上定义Org1
的anchor peer
。请再次确认$CHANNEL_NAME已被替换或者为以下命令设置了环境变量:
../bin/configtxgen -profile TwoOrgsChannel -outputAnchorPeersUpdate ./channel-artifacts/Org1MSPanchors.tx -channelID $CHANNEL_NAME -asOrg Org1MSP
现在,我们将在同一个通道定义Org2
的anchor peer
:
../bin/configtxgen -profile TwoOrgsChannel -outputAnchorPeersUpdate ./channel-artifacts/Org2MSPanchors.tx -channelID $CHANNEL_NAME -asOrg Org2MSP
4、启动网络
利用docker-compose
脚本来启动我们的区块链网络。docker-compose
文件利用我们之前下载的镜像,并用以前生成的genesis.block
来引导orderer
。
working_dir: /opt/gopath/src/github.com/hyperledger/fabric/peer
# command: /bin/bash -c './scripts/script.sh ${CHANNEL_NAME}; sleep $TIMEOUT'
volumes
启动网络,channel__name默认为mychannel:
CHANNEL_NAME=$CHANNEL_NAME TIMEOUT=<pick_a_value> docker-compose -f docker-compose-cli.yaml up -d
5、 环境变量设置
为了使针对peer0.org1.example.com
的CLI命令起作用,我们需要使用下面给出四个环境变量来介绍我们的命令。为peer0.org1.example.com
涉及的这些变量将被拷贝到CLI容器中,因此我们不需要复制它们。然而,如果你发送调用到其他的peer节点或者orderer,则需要相应地提供这些值。检查docker-compose-base.yaml
中的具体路径:
# Environment variables for PEER0
CORE_PEER_MSPCONFIGPATH=/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org1.example.com/users/[email protected]/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
6、创建/加入channel
使用docker exec
命令进入CLI容器:
docker exec -it cli bash
如果成功将看到下列信息:
root@0d78bb69300d:/opt/gopath/src/github.com/hyperledger/fabric/peer#
使用configtxgen工具生成信道配置-channel.tx
。将这个配置作为请求的一部分传递给order。
使用-c
标志指定channel的名字,-f
标志指定配置交易。在这个例子中它是channel.tx
,当然也可以使用不同的名称,挂载自己的交易配置。
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 replace the $CHANNEL_NAME variable appropriately
peer channel create -o orderer.example.com:7050 -c $CHANNEL_NAME -f ./channel-artifacts/channel.tx --tls $CORE_PEER_TLS_ENABLED --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-ID.block>
-我们将使用它加入信道。它包含了channel.tx
中的配置信息。
加入peer0.org1.example.com信道。
# By default, this joins ``peer0.org1.example.com`` only
# the <channel-ID>.block was returned by the previous command
peer channel join -b <channel-ID.block>
7、安装和实例化链码:
首先,在将示例代码安装到4个peer节点中的其中一个。这个命令将源代码放到peer节点的文件系统中。
peer chaincode install -n mycc -v 1.0 -p github.com/hyperledger/fabric/examples/chaincode/go/chaincode_example02
接下来,在信道上实例化chaincode。这将初始化信道上的链码,设置链码的背书策略,为目标peer节点启动一个chaincode容器注意-P
参数。这是我们需要指定的当这个chaincode的交易需要被验证的时侯的背书策略。
在下面的命令中,你会注意到我们指定-P "OR ('Org0MSP.member','Org1MSP.member')"
作为背书策略。这意味着我们需要Org1或者Org2组织中的其中一个的节点的背书即可(即只有一个背书)。如果我们改变语法为AND
那么我们就需要2个背书者。
# be sure to replace the $CHANNEL_NAME environment variable
# if you did not install your chaincode with a name of mycc, then modify that argument as well
peer chaincode instantiate -o orderer.example.com:7050 --tls $CORE_PEER_TLS_ENABLED --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.member','Org2MSP.member')"
8、操作:
查询:查询一下a
的值,以确保链码被正确实例化,state DB
被填充。查询的语法如下:
# be sure to set the -C and -n flags appropriately
peer chaincode query -C $CHANNEL_NAME -n mycc -c '{"Args":["query","a"]}'
转账:现在让我们从a
账户转10
到b
账户。这个交易将创建一个新的区块并更新state DB
。调用语法如下:
# be sure to set the -C and -n flags appropriately
peer chaincode invoke -o orderer.example.com:7050 --tls $CORE_PEER_TLS_ENABLED --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
的值为100
,在上一次调用的时侯转移了10
给b
。因此,查询a
应该展示90
。查询的语法如下:
# 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
后台分析:
-
script.sh
脚本被拷贝到CLI容器中。这个脚本驱动了使用提供的channel name以及信道配置的channel.tx文件的createChannel
命令。 -
createChannel
命令的产出是一个创世区块-<your_channel_name>.block
-这个创世区块被存储在peer节点的文件系统中同时包含了在channel.tx的信道配置。 -
joinChannel
命令被4个peer节点执行,作为之前产生的genesis block的输入。这个命令介绍了peer节点加入<your_channel_name>
以及利用<your_channel_name>.block
去创建一条链。 -
现在我们有了由4个peer节点以及2个组织构成的信道。这是我们的
TwoOrgsChannel
配置文件。 -
peer0.org1.example.com
和peer1.org1.example.com
属于Org1;peer0.org2.example.com
和peer1.org2.example.com
属于Org2 -
这些关系是通过crypto-config.yaml定义的,MSP路径在docker-compose文件中被指定。
-
Org1MSP(
peer0.org1.example.com
)和Org2MSP(peer0.org2.example.com
)的anchor peers将在后续被更新。我们通过携带channel的名字传递Org1MSPanchors.tx
和Org2MSPanchors.tx
配置到排序服务来实现anchor peer的更新。 -
一个链码-
chaincode_example02
被安装在peer0.org1.example.com
和peer0.org2.example.com
-
这个链码在
peer0.org2.example.com
被实例化。实例化过程将链码添加到信道上,并启动peer节点对应的容器,并且初始化和链码服务有关的键值对。示例的初始化的值是[”a“,”100“,”b“,”200“]
。实例化的结果是一个名为dev-peer0.org2.example.com-mycc-1.0
的容器启动了。 -
实例化过程同样为背书策略传递相关参数。策略被定义为
-P "OR ('Org1MSP.member','Org2MSP.member')"
,意思是任何交易必须被Org1或者Org2背书。 -
一个针对
a
的查询发往peer0.org1.example.com
。链码服务已经被安装在了peer0.org1.example.com
,因此这次查询将启动一个名为dev-peer0.org1.example.com-mycc-1.0
的容器。查询的结果也将被返回。没有写操作出现,因此查询的结果的值将为100
。 -
一次
invoke
被发往peer0.org1.example.com
,从a
转移10
到b
。 -
然后链码服务被安装到
peer1.org2.example.com
-
一个
query
请求被发往peer1.org2.example.com
用于查询a
的值。这将启动第三个链码服务名为dev-peer1.org2.example.com-mycc-1.0
。返回a
的值为90,正确地反映了之前的交易,a
的值被转移了10。
遇到的问题:
1、cryptogen tool not found. exiting
ethanlu@ubuntu:~/go/src/github.com/hyperledger/fabric-samples/first-network$ ./byfn.sh -m generate
Generating certs and genesis block for with channel 'mychannel' and CLI timeout of '10000'
Continue (y/n)? t
invalid response
Continue (y/n)? y
proceeding ...
cryptogen tool not found. exiting
解决方法:
1、下载二进制工具:
curl -sSL https://goo.gl/Gci9ZX | bash
会出现新的问题:
curl: (7) Failed to connect to goo.gl port 443: Connection timed out
这个问题google了也未必能解决,网上的说法一大堆,有的说是ipv6导致,有的说是防火墙导致
2、在浏览器中打开命令curl -sSL https://goo.gl/Gci9ZX | bash
中的这个链接https://goo.gl/Gci9ZX
(需要翻墙),然后你可以看到这其实就是一个shell脚本,脚本也就主要做了两件事:下载平台相关可执行文件和下载fabric docker镜像。内容如下:
#!/bin/bash
#
# Copyright IBM Corp. All Rights Reserved.
#
# SPDX-License-Identifier: Apache-2.0
#
export VERSION=1.0.2
export ARCH=$(echo "$(uname -s|tr '[:upper:]' '[:lower:]'|sed 's/mingw64_nt.*/windows/')-$(uname -m | sed 's/x86_64/amd64/g')" | awk '{print tolower($0)}')
#Set MARCH variable i.e ppc64le,s390x,x86_64,i386
MARCH=`uname -m`
dockerFabricPull() {
local FABRIC_TAG=$1
for IMAGES in peer orderer couchdb ccenv javaenv kafka zookeeper tools; do
echo "==> FABRIC IMAGE: $IMAGES"
echo
docker pull hyperledger/fabric-$IMAGES:$FABRIC_TAG
docker tag hyperledger/fabric-$IMAGES:$FABRIC_TAG hyperledger/fabric-$IMAGES
done
}
dockerCaPull() {
local CA_TAG=$1
echo "==> FABRIC CA IMAGE"
echo
docker pull hyperledger/fabric-ca:$CA_TAG
docker tag hyperledger/fabric-ca:$CA_TAG hyperledger/fabric-ca
}
: ${CA_TAG:="$MARCH-$VERSION"}
: ${FABRIC_TAG:="$MARCH-$VERSION"}
echo "===> Downloading platform binaries"
curl https://nexus.hyperledger.org/content/repositories/releases/org/hyperledger/fabric/hyperledger-fabric/${ARCH}-${VERSION}/hyperledger-fabric-${ARCH}-${VERSION}.tar.gz | tar xz
echo "===> Pulling fabric Images"
dockerFabricPull ${FABRIC_TAG}
echo "===> Pulling fabric ca Image"
dockerCaPull ${CA_TAG}
echo
echo "===> List out hyperledger docker images"
docker images | grep hyperledger*
3、在你的fabric-sample下新建download.sh
,将以上内容复制到文件里,然后保存退出执行以下命令:
chmod a+x download.sh
4、进入目录,然后执行命令:
./download.sh
这个时候bin文件夹下就会出现一堆二进制工具。