基于HyperLedger 创建第一个区块链网络

linux系统版本:CentOS Linux release 7.2.1511 (Core)
构建您的第一个网络(BYFN)场景提供了一个由两个组织组成的示例Hyperledger Fabric网络,每个组织都有两个peer节点,以及一个“solo”ordering服务。

(1)先决条件
  • 安装curl
  • 安装docker & docker compose,Docker 版本要求 17.06.2-ce or greater
我本机的docker 版本是Docker version 17.09.0-ce, build afdb6d4
docker-compose version 1.16.1, build 6d1ac219
  • 安装go语言,版本1.9.x or greater
  • 安装node.js和npm
  • python 2.7
  The Fabric Node.js SDK requires an iteration of Python 2.7 in order
for  npm install  operations to complete successfully
  • 下载官网的例子,并且下载特定于平台的二进制文件
cd first - network
curl - sSL https : // goo . gl / Q3YRTi | bash 如果这个命令不能成功执行的话,就先去下载好对应的脚本,然后再执行,执行好后会发现当前目录多了一个bin目录,目录里面有:
cryptogen,
configtxgen,
configtxlator, and
peer
然后把这个bin目录添加到系统的环境变量中去
(2)官网提供了两种方法创建网络:
  1. 懒人方法,一键运行脚本
cd first - network
./ byfn . sh - m generate
./ byfn . sh - m up
./ byfn . sh - m down
  1. 逐步运行命令
  • 证书生成器
cryptogen来为网络中的实体生成加密材料(证书),这些证书是身份的代表,它们允许在我们的实体进行交流和交易时进行签名/验证身份验证。
证书是如何工作的:
cryptogen工具读取包含网络拓扑的 crypto-config.yaml配置文件来生成相关证书,并允许我们为组织和属于这些组织的组件生成一组证书和密钥。每个组织都配置了一个唯一的根证书(ca-cert),它将特定组件(peer node和ordering node)绑定到该组织。通过为每个组织分配唯一的CA证书,我们正在模仿一个典型的网络,参与会员将使用自己的证书授权。 Hyperledger Fabric中的交易和通信由实体的私钥(keystore)签名,然后通过公钥(signcerts)进行验证。
我们运行完  cryptogen  这个工具后, 生成的证书和秘钥会保存在一个名为 crypto-config 的文件夹里面
  • 配置事务生成器
configtxgen tool  用来创建4个配置文件:
  • orderer genesis block,
  • channel channel configuration transaction,
  • and two anchor peer transactions - one for each Peer Org.
order block是用于ordering服务的创世纪块,  channel transaction文件在通道创建时广播给orderer。 anchor peer transactions, 按照名称可能得出的提示, anchor peer transactions在此通道上指定每个组织的锚点peer。

configtxgen   tool是如何工作的?
Configtxgen 工具读取 -  configtx.yaml  - 这个配置文件,这个配置文件包含一个简单网络的定义。有3个会员 - 一个 Orderer Org ( OrdererOrg ) 和2个 Peer Orgs ( Org1  &  Org2 ) ,这两个Org分别管理着两个peer,这个文件也指定了一个 组合-  SampleConsortium  - ,包含了两个Peer Orgs.
注意:sampleConsortium被定义在system-level profile中,接下来被channel-level profile引用。Channels存在在consortium的范围内,所有的consortium都在network的范围内。
你会看到这个文件有两个不同的头部,一个是给-  TwoOrgsOrdererGenesis  - 用,另一个是给通道用-  TwoOrgsChannel .
这两个头部很重要,因为会作为创建上面4个配置文件的参数给传递出去。
这个配置文件还有两个附加的定义是值得我们注意的:
Org(peer0.org1.example.com & peer0.org2.example.com)的anchor节点,另外一个就是指向每个成员的MSP目录的位置,基于此,我们可以将每个Org的根证书存放在orderer Genesis block中,这是一个很重要的概念。现在任意network entity与ordering service通信时就能对其数字签名进行验证。
  • 运行tool:
可以通过configtxgen and cryptogen手动生成证书/密钥以及各项配置文件。同样,可以参考byfn.sh脚本实现。
可以参考byfn.sh脚本中的generateCerts函数用来生成证书(这些证书被定义在crypto-config.yaml中的网络配置所使用)所需要的命令。为了方便起见,我们提供一个参考如下。
首先,先跑起来cryptogen工具,我们的二进制文件都在bin目录下,因此我们需要cd到tool所在的目录下.
../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

接着,我们创建channel transaction artifact(channel.tx)。然后,确保替换$CHANNEL_NAME
export CHANNEL_NAME= mychannel
.. /bin/configtxgen -profile TwoOrgsChannel -outputCreateChannelTx ./channel-artifacts/channel.tx -channelID $CHANNEL_NAME

接着,我们在我们正在创建的channel上定义Org1的anchor节点。然后,确保替换$CHANNEL_NAME
../bin/configtxgen -profile TwoOrgsChannel -outputAnchorPeersUpdate ./channel-artifacts/Org1MSPanchors.tx -channelID $CHANNEL_NAME -asOrg Org1MSP

然后,我们在相同的channel上定义Org2的anchor节点。
../bin/configtxgen -profile TwoOrgsChannel -outputAnchorPeersUpdate ./channel-artifacts/Org2MSPanchors.tx -channelID $CHANNEL_NAME -asOrg Org2MSP

  • 启动network
我们利用docker-compose脚本来启动我们的network。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 ---------docker-compose-cli.yaml
如果没有注释掉上面的命令的话,在network启动的时候,其将执行所有的CLI命令,然后就会导致文章末尾中的错误。
启动network,注意$CHANNEL_NAME,<pick_a_value>自己设定
CHANNEL_NAME=$CHANNEL_NAME TIMEOUT=<pick_a_value> docker-compose -f docker-compose-cli.yaml up -d
  • 9.环境变量
对于以下针对peer0.org1.example.com的CLI命令,我们需要使用以下给出的四个环境变量来介绍我们的命令。这些peer0.org1.example.com变量都被包含在CLI容器里,因此我们可以不用传递的操作它们。然而!,如果你想发送calls到其他peers或者orderer,你需要根据情况提供这些变量。打开docker-compose-base.yaml并查看具体的路径信息
# Environment variables for PEER0CORE_PEER_MSPCONFIGPATH =/opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/peerOrganizations/org1.example.com/users/[email protected]/ mspCORE_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
  • 10.创建并进入Channel
docker exec -it cli bash

请回忆下我们使用configtxgen工具生成channel配置artifact-channel.tx。我们将把artifact作为创建channel的请求的一部分发送给orderer。
注意到在接下来的命令中我们发送了-- cafile作为命令的一部分。这个是orderer证书的本地路径,使得我们可以验证TLS握手。
我们使用-c flag 标注出我们的channel名称,用-f flag标注出我们的channel 配置transaction。在本例中是channel.tx,然而你可以使用不同的名称用于挂载配置transaction。使用下面创建channel的语句的时候注意channel-name。
export CHANNEL_NAME= mychannel
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
上述命令返回了一个genesis block- <channel-ID.block> -我们可以通过这个id进入到channel。它包含channel.tx中指定的配置信息,创建成功后有如下输出:

接下来的操作都需要在CLI容器中进行,在操作peer0.org1.example.com之外的peer时,需要记得相关环境变量的命令。
接下来我们把peer0.org1.example.com加入到channel中去,channel-ID.block是之前生成的,这里我的是mychannel.block。
peer channel join -b <channel-ID.block>

你可把其他的peer加入到该channel上,但是需要设置上述的四个环境变量。
  • 安装并实例化chaincode
我们这里只是使用已经存在的chaincode。
application通过chaincode与blockchain ledger进行交互。我们把chaincode安装到execute与endorse我们transaction的peer上,接下来在channel上初始化chaincode。
首先,安装sample go代码到4个peer之一的peer上。以下命令把chaincode的源代码放到了peer节点的文件系统上。
peer chaincode install - n mycc - v 1.0 - p github . com / hyperledger / fabric / examples / chaincode / go / chaincode_example02


接下来,在channel上实例化chaincode。这将在channel上初始化chaincode,同时设置chaincode的endorsement的策略,然后在目标peer上启动chaincode容器。请注意-P参数,我们通过设置这个参数,来指定transaction的endorsement的需求level,用于验证chaincode。
在下面的命令,我们定义了endorsement策略为-P "OR (‘Org0MSP.member‘,‘Org1MSP.member‘)"。这表示我们需要隶属于Org1或者Org2的peer进行“endorsement”(也就是说,只有一个endorsement)。如果把or改为and则说明我们需要两个endorsement
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')"

  • 查询
首先查询a的值,确保chaincode已经正常的实例化,同时确保state DB已经被填充
peer chaincode query -C $CHANNEL_NAME -n mycc -c '{"Args":["query","a"]}'

  • 调用
让我们从a账户转移10个到b账户,这个命令将会创建新的block同时更新state DB。
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"]}'

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

  • 上述调用过程解析
  1. script.sh脚本在CLI容器内部执行,该脚本执行了createChannel命令,提供了channel名称,同时使用channel.tx进行channel配置
  2. createChannel的输出是一个genesis block,使用channel名称命名的block,例如mychannel.block,该block在peers的文件系统上存储,该block包括channel.tx指定的channel配置信息。
  3. 加入channel的命令对所有4个peer进行执行,把之前生成的genesis block作为输入。这个join命令使得peers加入mychannel里面,同时创建了一个以mychannel.block作为开始的chain。
  4. 接着,我们拥有了由4个peer,两个organization组成的channel。这都在我们TwoOrgsChannel profile.里面。
  5. peer0.org1.example.com 与 peer1.org1.example.com 隶属于 Org1; peer0.org2.example.com 以及 peer1.org2.example.com 隶属于 Org2。这些关系在crypto-config.yaml中定义,同时在我们的docker compose中指定了MSP的路径。
  6. Org1MSP (peer0.org1.example.com) 以及 Org2MSP (peer0.org2.example.com)的anchor节点接下来被更新了。我们基于建立的channel把Org1MSPanchors.tx 与 Org2MSPanchors.tx 的artifacts,发送给orderering service,以实现上述的更新。
  7. chaincode_example02被安装在了peer0.org1.example.com 与 peer0.org2.example.com
  8. 接着chaincode在peer0.org2.example.com被实例化。实例化把chaincode加到channel上,并启动目标peer的容器,接着初始化chaincode有关的键-值对( [“a”,”100” “b”,”200”])。实例化的过程导致了dev-peer0.org2.example.com-zeychaincode-1.0的启动。
  9. 实例化需要有endorsement策略的参数,这里设置为-P "OR    (‘Org1MSP.member‘,‘Org2MSP.member‘)",表示任意transaction必须被Org1 或者 Org2的一个peer进行endorsed。
  10. 接下来把对“a”的查询发送给peer0.org1.example.com,即在peer0.org1.example.com查询a的值。chaincode之前已经安装在了peer0.org1.example.com上,因此这个查询将会针对Org1 peer0 启动一个容器(dev-peer0.org1.example.com-zeychaincode-1.0),然后查询结果得到返回,没有任何写的操作发生,因此返回值是100
  11. 接着调用请求发送给peer0.org1.example.com,把10个从a转移到b。
  12. 然后chaincode在peer1.org2.example.com进行安装。
  13. 然后一个查询a的余额的请求发送到peer1.org2.example.com。这个启动了第三个chaincode容器(dev-peer1.org2.example.com-mycc-1.0),90被返回。正确的反应了上述transaction,a的值被改为了10。
Error: Got unexpected status: BAD_REQUEST
原因是存在同名的channel

猜你喜欢

转载自blog.csdn.net/u011011025/article/details/78292278