Hyperledger Fabric 官方最新翻译---使用指南(二)(Building Your First Network)

点此查看最新,fabric官方文档中文翻译目录

  构建你第一个由两个组织组成的Hyperledger fabric 网络(BYFN),每个都包含两个peer节点,和一个”solo”的order 节点

1:安装先决条件

  在我们开始前,保证所有的Prerequisites都安装到你用于开发chaincode applications和操作fabric的环境。
  你还需要安装示例、二进制文件和Docker镜像( Install Samples, Binaries and Docker Images),你会发现在 fabric-samples仓库有很多示例,我们将使用first-network 为样例,让我们进入到子目录

cd fabric-samples/first-network

  注意:本篇文档涉及到指令都需要在fabric-samples/first-network文件夹下运行,如果你在别的文件夹运行脚本,脚本有可能会提示找不到二进制文件。
  我们提供了一个全注释脚本byfn.sh,来快速启动一个4个节点代表2个组织以及1个order节点组成的fabric网络。它同样会启动一个容器,容器中运行一个脚本增加peer节点到channel,部署和实例化链码,以及基于已部署的链码推动交易(transactions)执行。
  下面是byfn.sh的帮助文本

Usage:
  byfn.sh <mode> [-c <channel name>] [-t <timeout>] [-d <delay>] [-f <docker-compose-file>] [-s <dbtype>] [-l <language>] [-i <imagetag>] [-v]
    <mode> - one of 'up', 'down', 'restart', 'generate' or 'upgrade'
      - 'up' - bring up the network with docker-compose up
      - 'down' - clear the network with docker-compose down
      - 'restart' - restart the network
      - 'generate' - generate required certificates and genesis block
      - 'upgrade'  - upgrade the network from v1.0.x to v1.1
    -c <channel name> - channel name to use (defaults to "mychannel")
    -t <timeout> - CLI timeout duration in seconds (defaults to 10)
    -d <delay> - delay duration in seconds (defaults to 3)
    -f <docker-compose-file> - specify which docker-compose file use (defaults to docker-compose-cli.yaml)
    -s <dbtype> - the database backend to use: goleveldb (default) or couchdb
    -l <language> - the chaincode language: golang (default) or node
    -i <imagetag> - the tag to be used to launch the network (defaults to "latest")
    -v - verbose mode
  byfn.sh -h (print this message)

Typically, one would first generate the required certificates and
genesis block, then bring up the network. e.g.:

        byfn.sh generate -c mychannel
        byfn.sh up -c mychannel -s couchdb
        byfn.sh up -c mychannel -s couchdb -i 1.1.0-alpha
        byfn.sh up -l node
        byfn.sh down -c mychannel
        byfn.sh upgrade -c mychannel

Taking all defaults:
        byfn.sh generate
        byfn.sh up
        byfn.sh down

  如果你选择不提供channel名称,那么脚本会使用一个默认名称mychannel。CLI超时参数是一个可选参数(-t),如果你选择不设置它,那么CLI会放弃超过默认设置10秒的查询请求。

2 想让它运行起来

2.1 生成网络基础文件

执行下面的命令
./byfn.sh generate
  你会看到后续要发生什么的简短描述,伴随着yes/no的命令提示行。
按下y或者敲回车会执行描述的动作。
截图略过。。。。。
  第一步首先创建各类网络组件所需要的证书和私钥,引导ordering服务的创世区块(genesis block),配置一个channel所需要的配置事务(transactions)集合。

2.2 启动网络

现在你可以启动网络使用下列指令

./byfn.sh up

  上面的命令会编译Golang链码镜像并且启动相关的容器。Go是默认是支持语言,同时也支持Node。如果你想运行node链码,可以改为一下命令

./byfn.sh up –l node

注意:查看Hyperledger Fabric Shim 文档了解更多关于node.js chaincode shim API
再一次会提示你希望继续还是终端。按下y按钮或者敲回车

Starting with channel 'mychannel' and CLI timeout of '10'
Continue? [Y/n]
proceeding ...
Creating network "net_byfn" with the default driver
Creating peer0.org1.example.com
Creating peer1.org1.example.com
Creating peer0.org2.example.com
Creating orderer.example.com
Creating peer1.org2.example.com
Creating cli


 ____    _____      _      ____    _____
/ ___|  |_   _|    / \    |  _ \  |_   _|
\___ \    | |     / _ \   | |_) |   | |
 ___) |   | |    / ___ \  |  _ <    | |
|____/    |_|   /_/   \_\ |_| \_\   |_|

Channel name : mychannel
Creating channel...

  这将会启动所有的容器,并创建一个端对端的应用场景。成功完成后,你的终端会显示

Query Result: 90
2017-05-16 17:08:15.158 UTC [main] main -> INFO 008 Exiting.....
===================== Query successful on peer1.org2 on channel 'mychannel' =====================

===================== All GOOD, BYFN execution completed =====================


 _____   _   _   ____
| ____| | \ | | |  _ \
|  _|   |  \| | | | | |
| |___  | |\  | | |_| |
|_____| |_| \_| |____/

  你可以滚动这些日志查看各种交易。如果你没有得到这个结果,可以跳到下面Troubleshooting章节,让我们看看是否能帮助你发现错误

2.3关闭网络

  最后,让我把它们都一次关闭掉让我们可以探索网络设置。以下命令会杀掉容器,删除加密素材和四个网络基础文件,从你的docker仓库中删除链码镜像

./byfn.sh down

再一次,会提示你继续还是终端,按下Y或者回车

Stopping with channel 'mychannel' and CLI timeout of '10'
Continue? [Y/n] y
proceeding ...
WARNING: The CHANNEL_NAME variable is not set. Defaulting to a blank string.
WARNING: The TIMEOUT variable is not set. Defaulting to a blank string.
Removing network net_byfn
468aaa6201ed
...
Untagged: dev-peer1.org2.example.com-mycc-1.0:latest
Deleted: sha256:ed3230614e64e1c83e510c0c282e982d2b06d148b1c498bbdcc429e2b2531e91
...

  如果你想了解更多关于潜在的工具和启动机制,继续往下读。在下面的章节,我们将介绍构建功能齐全的fabric网络的各个步骤和要求
。
  注意:下面的步骤假定将cli容器中的CORE_LOGGING_LEVEL参数设置为DEBUG
。你可以通过修改first-network文件夹下的docker-compose-cli.yaml配置文件来完成这样的修改。

cli:
  container_name: cli
  image: hyperledger/fabric-tools:$IMAGE_TAG
  tty: true
  stdin_open: true
  environment:
    - GOPATH=/opt/gopath
    - CORE_VM_ENDPOINT=unix:///host/var/run/docker.sock
    - CORE_LOGGING_LEVEL=DEBUG
    #- CORE_LOGGING_LEVEL=INFO

3 加密发生器

  我们将使用cryptogen工具来生成我们各种网络组件的加密材料(X509证书以及签名秘钥),这些证书是身份的代表,他们准许在我们实体通讯和交易的过程中签名和验证身份验证。

3.1 它是怎样工作的

  Cryptogen使用包含网络拓扑的文件crypto-config.yaml,并准许我们为组织以及属于这些组织的组件,生成一组证书和密钥。每个组织配备了一个根证书(ca-cert)将特定的组件(peer和order节点)绑定到该组织。通过分配每个组织一个唯一的根证书,我们模拟一个经典的网络,其中一个成员将使用自己的证书颁发机构,fabric中的交易和通信将会被一个实体的私钥(keystore)签名,公钥验证 (signcerts).
  你将会注意到这个文件中的count变量,我们用它指定每个组织中有多少peer节点,在我们这个例子里面一个组织有两个peer节点。我们现在不会深入到x.509 certificates and public key infrastructure 细节。如果你感兴趣,你可以在空闲时间细读这些主题。
  在运行这些工具前,让我们快速浏览一下 crypto-config.yaml的一个片段。注意OrdererOrgs节点下的“Name”, “Domain” and “Specs” parameters参数
  

OrdererOrgs:
#---------------------------------------------------------
# Orderer
# --------------------------------------------------------
- Name: Orderer
  Domain: example.com
  CA:
      Country: US
      Province: California
      Locality: San Francisco
  #   OrganizationalUnit: Hyperledger Fabric
  #   StreetAddress: address for org # default nil
  #   PostalCode: postalCode for org # default nil
  # ------------------------------------------------------
  # "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
  EnableNodeOUs: true

  网络实体的命名规则如下: “{{.Hostname}}.{{.Domain}}”,所以用我们的排序节点作为参考点,我们留下了一个排序节点名称:orderer.example.com。该节点绑定到了Orderer的MSP ID。这个文件包含大量的定义和语法文档。你还可以参阅 Membership Service Providers (MSP) 文档,深入学习更多关于MSP的内容。
  在我们运行完 cryptogen工具,产生的证书和私钥将会被保存到文件夹crypto-config。
  

4 配置交易生成器

  configtxgen工具被用来创建四个配置基础文件:

  • 排序创世块
  • channel配置交易
  • 两个锚节点交易,每个机构各一个

      可以查看configtxgen关于这个工具功能性的完整描述,
    排序区块是排序服务的创世区块,并且在channel创建时 channel
    配置交易文件就被广播到了order节点。锚节点交易,顾名思义,指明这个channel上每个组织的锚节点。

4.1 它是怎样工作的

  Configtxgen使用一个文件- configtx.yaml里面包含了样例网络的定义。有三个成员:一个排序组织和两个分别管理着两个peer节点的peer组织。这个文件同时还指定了一个联合体- SampleConsortium-由两个peer组织构成,注意文件头部的 “Profiles” 部分。你会注意到有两个独特的标题。
  一个用于order创世区块- TwoOrgsOrdererGenesis,另一个用于channel- TwoOrgsChannel。
  这些头文件很重要,因为我们将在创建基础文件时将它们作为参数传入。
  注意:SampleConsortium是在系统级配置定义,然后在channel级配置中引入。Channel存在于联合体范围之内,所有的联合体必须在网络范围内定义。
  这个文件同样包含两个附加的规范值得注意。
  第一,我们定义了每个peer组织的锚节点(peer0.org1.example.com & peer0.org2.example.com)。

5 运行工具

  你可以使用configtxgen 和 cryptogen命令创建证书/私钥和各种各样的配置基础文件。或者你可以试着修改byfn.sh文件来实现你自己的小目标。
  

5.1 手动生成基础文件

  你可以参考byfn.sh中的 generateCerts函数获取必要的命令用于创建证书,这些证书用于crypto-config.yaml文件中定义的网络配置,但是为了方便起见,我们这里也提供了参考。
  首先让我们运行cryptogen工具,我们的二进制文件位于bin目录,所以我们需要提供工具所在的相对路径。
  

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

你可以在终端看到以下内容

org1.example.com
org2.example.com

  证书和私钥文件将会被输出到first-network目录下的crypto-config目录。
  下一步我们需要告诉configtxgen 工具哪里去寻找他需要摄取的configtx.yaml文件。我们需要告诉它在我们当前的工作目录中找寻
export FABRIC_CFG_PATH=$PWD,然后我们将要调用configtxgen工具去创建排序创世区块。

../bin/configtxgen -profile TwoOrgsOrdererGenesis -outputBlock ./channel-artifacts/genesis.block

你将会在终端看到下面的类似输出

2017-10-26 19:21:56.301 EDT [common/tools/configtxgen] main -> INFO 001 Loading configuration
2017-10-26 19:21:56.309 EDT [common/tools/configtxgen] doOutputBlock -> INFO 002 Generating genesis block
2017-10-26 19:21:56.309 EDT [common/tools/configtxgen] doOutputBlock -> INFO 003 Writing genesis block

注意:排序创世节点和后续的基础文件我们都将输出到根目录的channel-artifacts文件夹。

5.2 创建一个渠道配置交易

  下一步我们需要创建一个channel事务基础文件。确认替换了$CHANNEL_NAME
  参数或者设置了环境变量CHANNEL_NAME,它将贯穿这些文档被使用
  

生成channel.tx

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

你的控制台会有如下的类似输出

2017-10-26 19:24:05.324 EDT [common/tools/configtxgen] main -> INFO 001 Loading configuration
2017-10-26 19:24:05.329 EDT [common/tools/configtxgen] doOutputChannelCreateTx -> INFO 002 Generating new channel configtx
2017-10-26 19:24:05.329 EDT [common/tools/configtxgen] doOutputChannelCreateTx -> INFO 003 Writing new channel tx

  下一步我们要在我们构建的channel中为org1定义锚节点,再次提醒替换$CHANNEL_NAME参数或者设置环境变量。终端输出将会类似channel交易基础文件。

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

  现在,我们定义channel上另一个org2的锚节点
  

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

6 启动网络

6.1 环境变量

  为了一下针对peer0.org1.example.com的CLI命令能运行,我们需要设置如下四个环境变量。这些针对peer0.org1.example.com的变量已经预植到CLI容器,因此我们可以直接操作命令不需要传入他们。但是如果你要调用其他peer或者order,你需要相应的提供这些值。检查docker-compose-base.yaml这些特殊路径
  

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

6.2 创建和加入channel

  回想一下,我们使用上面“创建一个渠道配置交易“部分中的configtxgen工具创建了通道配置事务。你可以重复这个步骤创建额外的channel配置交易,使用相同或者不同configtx.yaml 中的配置传递给configtxgen工具。然后你可以重复本节中的步骤去给你的网络创建其他channel。
  我们将使用如下命令进入CLI容器

docker exec -it cli bash

  如果成功你会看到如下信息
 

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

  接下来,我们要传入创建的渠道配置交易文件,即“创建一个渠道配置交易”中创建的channel.tx文件,作为创建channel请求的一部分传给order。
  我们指定我们的-c指定我们的channel名称以及-f指定我们的渠道交易配置基础文件。在这个例子中,它是channel.tx,但是你也可以挂在你自己的交易配置文件用不同的名字,一旦你在CLI容器中设置了CHANNEL_NAME环境变量,那么你就不用显示传入-c参数。

export CHANNEL_NAME=mychannel
#我们还传入了order的ca证书,为了TLS 握手
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

注意:我们命令中传递的—cafile,它是order的根证书本地路径,准许我们来验证TLS握手。
  这个指令返回一个创世区块channel-ID.block,我们用来加入channel。
  它包含channel.tx中的配置信息,如果你没有对默认的channel名字做任何修改,那么这个命令会返回你一个原标题mychannel.block.
  现在,我们将peer0.org1.example.com加入到channel
peer channel join -b mychannel.block。你可以修改“环境变量”那一节提到的四个环境变量来让其他节点也加入到channel。
  我们可以简单将锚节点peer0.org2.example.com 加入到channel而不是将每个节点都加入。当我们重写CLI容器中的默认环境变量配置。完整的命令如下:
  

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 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 join -b mychannel.block

  或者你可以单独选择设置这些环境变量而不是传入整个字符串。一旦设置好,你只需要再执行channel join 命令,CLI容器将进行peer0.org2.example.com相关操作。
  

6.3 更新锚节点

  以下命令是channel更新,他们将要传播channel的定义。本质来说,我们将要在channel的创世节点上添加额外的配置信息。注意我们没有修改创世区块,而是简单地将增量添加到定义锚节点的链中。
将org1的锚节点修改为peer0.org1.example.com

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

  现在修改channel定义将org2锚节点设置为peer0.org2.example.com,与peer channel join命令对等,我们也需要在执行命令前预设环境变量
  

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

6.4 安装&实例化码链

  注意:我们将利用一个简单的码链做演示。想学习怎样编写自己的码链,请查看“ Chaincode for Developers”指南。

  应用程序通过链码与超级账本交互。因此,我们需要在每个执行和背书我们交易的节点上安装链码,然后在channel上初始化链码。
首先,安装样例Go或者Node链码到四个Peer节点中的一个。如下指令安装特定的源代码到我们的peer节点文件系统上去。
注意:每个链码,每个版本,你只能安装一个版本的源码。

# 安装go链码
peer chaincode install -n mycc -v 1.0 -p  github.com/chaincode/chaincode_example02/go/
# 安装Node.js链码,-l 用来指定语言
peer chaincode install -n mycc -v 1.0 -l node -p /opt/gopath/src/github.com/chaincode/chaincode_example02/node/

  下一步,在channel上实例化链码。Channel上实例化链码、设置链码的背书策略、为目标peer启动一个链码容器。注意-p参数,这是指定该链码的交易被验证时的背书策略水平。
  下面的命令中,你会注意到我们设置的策略是
-P “OR (‘Org1MSP.peer’,’Org2MSP.peer’)”,意思是需要Org1或者Org2一个背书即可。如果我们把语法改成AND,那我们需要两个组织都进行了背书。

Golang
# 注意-C 后面的系统参数
# 如果你没有安装mycc名称的链码,那么注意同步修改
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')"

注意:实例化node.js链码将会需要大约一分钟,不是这个命令被挂起了,相反,它正在编译docker镜像安装fabric-shim层。

# 注意-l指定语言
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 
-l node 
-v 1.0 
-c '{"Args":["init","a", "100", "b","200"]}' 
-P "OR ('Org1MSP.peer','Org2MSP.peer')"

  查看“endorsement policies”文档,了解更多策略实施的细节。

  如果你想要更多的peer节点与账本交互。你可以将他们加入channel,然后安装相同名称、版本、语言的链码源码到适当的peer节点文件系统上。当指定的链码与每个peer节点交互时都会启动一个链码容器,当然,node编写的链码镜像都会编译慢一些。

  一旦链码被初始化,我们就不需要 –l参数了。我们只需要传入channel的标识符和链码的名称。

6.5 查询

  让我们查询值a来确定链码已经被恰当的实例化以及状态DB被填充(the state DB was populated)。查询语法如下:

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

6.6 调用

  现在让我们把10从a移动到b,这个交易将会创建一个新的block,更新DB状态。调用语法如下:

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"]}'

6.7 查询结果

  确认一下上一步查询结果,初始化a为100,上一步调用移动了10,那么应该在查询a应该显示90。查询语句如下:

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

  查询结果为

Query Result: 90

6.8 后台发生了什么?

  注意:这些步骤描述script.sh由’./byfn.sh up’运行的场景。 使用./byfn.sh清理网络并确保该命令处于活动状态。 然后使用相同的docker-compose重新启动您的网络

  • A Scrip-Script.sh是在CLI容器内部执行的脚本,这个配置文件使用提供的channel名称及channel.tx中的channel配置来执行createChannel指令。
  • createChannel的输出是创世区块– .block。它将会存储在peer节点的文件系统中,包含从channel.tx获取到的channel配置。
  • joinChannel命令用上一步创建的创世区块作为输入对四个peer节点执行,这个命令将peer节点加入your_channel_name同时创建.block开始的链。
  • 现在我们拥有一个channel包含四个peer节点以及两个组织,这就是我们的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)的锚节点被修改了,我们将Org1MSPanchors.tx和Org2MSPanchors.tx基础文件以及channel名字一起传递给ordering 服务
  • 一个链码chaincode_example02被安装在了peer0.org1.example.com和peer0.org2.example.com
  • 链码在peer0.org2.example.com上实例化了,实例化是将链码增加到channel上,开始目标peer节点的容器,初始化分配给链码的键值对。这个例子的初始化值是[“a”,”100” “b”,”200”].初始化的结果是一个名为dev-peer0.org2.example.com-mycc-1.0的容器被创建。
  • 实例化指令同时传入了背书策略,例如策略被定义为-P “AND (‘Org1MSP.peer’,’Org2MSP.peer’)”,意味着一个交易必须同时被org1和org2的peer节点背书。
  • 一个关于a的值查询发送给了peer0.org1.example.com,链码之前已经被安装在了peer0.org1.example.com,所以这会启动一个org1 peer0的容器dev-peer0.org1.example.com-mycc-1.0,查询的结果也会同时返回,因为没有写的d工作发生,所以返回a的值100.
  • 一个调用被发送给peer0.org1.example.com将10从a移到b
  • 链码之后被安装到了peer1.org2.example.com
  • 一个查询被发送到peer1.org2.example.com查询a的值,这会2启动第三个链码容器dev-peer1.org2.example.com-mycc-1.0。A的值90会被返回,说明之前a的值被修改了10的交易生效了。
  • -

6.9 这说明了什么

  链码必须被安装到一个peer节点上,以保证他能成功对账本进行读/写操作。此外,只有在一个链码init或者对它进行传统读/写交易操作才会启动一个链码容器。

6.10 我怎样查看这些交易

检查CLI 的Docker容器

docker logs -f cli

你会看到如下输出

2017-05-16 17:08:01.366 UTC [msp] GetLocalMSP -> DEBU 004 Returning existing local MSP
2017-05-16 17:08:01.366 UTC [msp] GetDefaultSigningIdentity -> DEBU 005 Obtaining default signing identity
2017-05-16 17:08:01.366 UTC [msp/identity] Sign -> DEBU 006 Sign: plaintext: 0AB1070A6708031A0C08F1E3ECC80510...6D7963631A0A0A0571756572790A0161
2017-05-16 17:08:01.367 UTC [msp/identity] Sign -> DEBU 007 Sign: digest: E61DB37F4E8B0D32C9FE10E3936BA9B8CD278FAA1F3320B08712164248285C54
Query Result: 90
2017-05-16 17:08:15.158 UTC [main] main -> INFO 008 Exiting.....
===================== Query successful on peer1.org2 on channel 'mychannel' =====================

===================== All GOOD, BYFN execution completed =====================


 _____   _   _   ____
| ____| | \ | | |  _ \
|  _|   |  \| | | | | |
| |___  | |\  | | |_| |
|_____| |_| \_| |____/

  你可以滚动这些日志查看各类交易日期

6.11 我怎样查看链码日志

  检查个别链码容器,查看每个容器交易的分别执行情况。这是每个容器的合并输出

$ docker logs dev-peer0.org2.example.com-mycc-1.0
04:30:45.947 [BCCSP_FACTORY] DEBU : Initialize BCCSP [SW]
ex02 Init
Aval = 100, Bval = 200

$ docker logs dev-peer0.org1.example.com-mycc-1.0
04:31:10.569 [BCCSP_FACTORY] DEBU : Initialize BCCSP [SW]
ex02 Invoke
Query Response:{"Name":"a","Amount":"100"}
ex02 Invoke
Aval = 90, Bval = 210

$ docker logs dev-peer1.org2.example.com-mycc-1.0
04:31:30.420 [BCCSP_FACTORY] DEBU : Initialize BCCSP [SW]
ex02 Invoke
Query Response:{"Name":"a","Amount":"90"}

7 了解Docker Compose的拓扑结构

  BYFN示例为我们提供了两种Docker Compose文件,每个都是docker-compose-base.yaml的扩展(位于base文件夹)。
  第一个docker-compose-cli.yaml提供给我们一个CLI容器,一个order节点,4个peer节点。我们用这个文件来查看此页面的所有说明。
注意:本章的剩余部分涉及到了为SDK设计的docker compose文件。有关这个测试的详细情况,可以查看 Node SDK
  第二个,docker-compose-e2e.yaml被用来运行使用node.js SDK来运行端对端的测试。除了SDK的功能,它主要的不同是涉及到了fabric-ca服务容器。结果是,我们可以发送REST请求到CAs组织来完成用户的登记和注册。
  如果你想在不运行byfn.sh文件情况下使用docker-compose-e2e.yaml,我们需要做四个请问的修改。我们需要将私钥指向我们的CA组织。你可以在crypto-config文件夹找到这个值。例如org1路径是crypto-config/peerOrganizations/org1.example.com/ca/.私钥是一个很长的hash值以_sk结尾。Org2的路径是crypto-config/peerOrganizations/org2.example.com/ca/。
  在docker-compose-e2e.yaml中更新ca0和ca1的FABRIC_CA_SERVER_TLS_KEYFILE 变量。你还需要修改命令中的路径去启动ca服务器。你为每个CA容器提供两次相同的私钥。

8 使用CouchDB

  状态数据库能从默认的goleveldb切换为CouchDB。CouchDB
可以使用相同的链码函数,但是它增加能力对状态数据库进行执行丰富和复杂查询,当链码数据被建模为JSON格式时。
  当使用CouchDB数据库替换默认数据库时,遵循上面列出生成基础文件相同的步骤,除了启动网络时传入docker-compose-couch.yaml。如下:

docker-compose -f docker-compose-cli.yaml -f docker-compose-couch.yaml up –d

chaincode_example02现在可以使用CouchDB了

注意:如果你选择将fabric-couchdb容器端口映射到宿主机端口,请确认你了解安全隐患。在开发环境映射CouchDB REST API接口是可实现的,同时允许通过CouchDB的web界面(Fauxton)对数据库进行了可视化。生产环境不建议进行端口映射,为了限制对CouchDB的外部访问。

  你可以基于上面列出的步骤,在CouchDB的状态数据库上
使用chaincode_example02的链码,但是为了应用CouchDB查询能力你需要将chaincode的数据模式设置为JSON(例如marbles02)。你可以查找到marbles02链码在fabric/examples/chaincode/go文件夹中。
  我们将遵守上面列出的“创建和加入channel”章节来创建和加入channel。一旦你把peer节点加入到channel,使用下面的步骤与marbles02链码交互。

  • 在peer0.org1.example.com上安装和实例化链码
peer chaincode install -n marbles -v 1.0 -p github.com/chaincode/marbles02/go
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 marbles -v 1.0 -c '{"Args":["init"]}' -P "OR ('Org0MSP.peer','Org1MSP.peer')"
  • 创建一些弹珠然后移动它们
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 marbles -c '{"Args":["initMarble","marble1","blue","35","tom"]}'
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 marbles -c '{"Args":["initMarble","marble2","red","50","tom"]}'
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 marbles -c '{"Args":["initMarble","marble3","blue","70","tom"]}'
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 marbles -c '{"Args":["transferMarble","marble2","jerry"]}'
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 marbles -c '{"Args":["transferMarblesBasedOnColor","blue","jerry"]}'
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 marbles -c '{"Args":["delete","marble1"]}'
  • 如果你选择在 docker-compose中映射CouchDB端口,你可以打开浏览器输入如下地址,查看CouchDB的web接口(Fauxton)
http://localhost:5984/_utils

  你可以看到一个名为mychannel的数据库(或者你自定义的channl名称)以及它里面的文件

  你在CLI中运行常规查询(例如读取弹珠)

 peer chaincode query -C $CHANNEL_NAME -n marbles -c '{"Args":["readMarble","marble2"]}'

  marble2的输出是

Query Result: {"color":"red","docType":"marble","name":"marble2","owner":"jerry","size":50}

  你可以检测特定弹珠的交易历史-例如marble1

peer chaincode query -C $CHANNEL_NAME -n marbles -c '{"Args":["getHistoryForMarble","marble1"]}'

marble1的输出是
Query Result: [{"TxId":"1c3d3caf124c89f91a4c0f353723ac736c58155325f02890adebaa15e16e6464", "Value":{"docType":"marble","name":"marble1","color":"blue","size":35,"owner":"tom"}},{"TxId":"755d55c281889eaeebf405586f9e25d71d36eb3d35420af833a20a2f53a3eefd", "Value":{"docType":"marble","name":"marble1","color":"blue","size":35,"owner":"jerry"}},{"TxId":"819451032d813dde6247f85e56a89262555e04f14788ee33e28b232eef36d98f", "Value":}]

你也可以对数据内容进行富查询,例如所有者jerry的所有弹珠
peer chaincode query -C $CHANNEL_NAME -n marbles -c '{"Args":["queryMarblesByOwner","jerry"]}'
输出将返回jerry的两个弹珠
Query Result: [{"Key":"marble2", "Record":{"color":"red","docType":"marble","name":"marble2","owner":"jerry","size":50}},{"Key":"marble3", "Record":{"color":"blue","docType":"marble","name":"marble3","owner":"jerry","size":70}}]

9 为什么使用CouchDB

  CouchDB是一种NoSQL解决方案。它是一种面向文档的数据库,文档字段被存储为键值映射。字段可以是简单的键值对、列表或者映射。除了LevelDB支持的键查询/复合键/键范围查询,CouchDB还具备完整的数据富查询能力,例如对整个区块链数据的无键查询,当他的数据使用json方式存储的就可以被完整查询。所以CouchDB可以满足很多LevelDB不支持的链表、审计、报告需求。
  CouchDB同样也增加了区块链的合规性和数据保护的安全性。因为它能够通过过滤和屏蔽事务中的单个属性来实现字段级别的安全,如果需要能值允许读权限。
  
  另外,CouchDB属于CAP定义中的AP类型(可用性和分区容错性)。他使用最终以直线的主-主复制模型。更多的信息可以查看 Eventual Consistency page of the CouchDB documentation,但是在每个fabric节点中,已经没有了数据复制,写到数据已经被保证了一致性和持久性(不同于最终一致性)。

  CouchDB是Fabric第一个外部可插拔的状态数据库,并且可能也应该会有其他额外的数据库想法。例如,IBM允许他们的区块链支持关系型数据库,同时CP-TYPE(一致性和分区容错性)数据库可能也会需要。从而没有在应用程序的级别保证数据库一致性。
  

10 一个数据持久化的注意点

  如果peer容器或者CouchDB容器的数据需要被持久化。一个想法是挂载docker宿主机的目录到容器的关联目录。例如,你增加以下两行到docker-compose-base.yaml的peer容器配置中去。

volumes:
 - /var/hyperledger/peer0:/var/hyperledger/production

  针对CouchDB容器,你可以增加下面一行到CouchDB容器配置

volumes:
 - /var/hyperledger/couchdb0:/opt/couchdb/data

11 问题处理

  • 总是启动你的网络,使用下面的命令去迁移基础文件,加密,容器和链码镜像
    ./byfn.sh down

注意:如果不移除旧的容器和镜像,你会看到错误

  • 如果你看到Docker错误,首先检查你的docker版本,然后试着重启你的docker进程。Docker的错误经常不能立刻识别。例如,你可能看到因为不能访问容器中安装的加密材料而导致的错误。
    如果你坚持移除你的镜像然后重新开始
docker rm -f $(docker ps -aq)
docker rmi -f $(docker images -q)
  • 如果你看到你创建,实例化,调用或者查询命令的错误,请确认你已经正确的修改了channel名称和链码名称。在提供的样例代码里有一些是占位符。
  • 如果你看到如下的错误
    Error: Error endorsing chaincode: rpc error: code = 2 desc = Error installing chaincode code mycc:1.0(chaincode /var/hyperledger/production/chaincodes/mycc.1.0 exits)

  你可能已经在之前的运行中已经有了链码镜像(例如dev-peer1.org2.example.com-mycc-1.0 ordev-peer0.org1.example.com-mycc-1.0
),移除他们然后再尝试一次

docker rmi -f $(docker images | grep peer[0-9]-peer[0-9] | awk '{print $3}')
  • 如果你看到类似如下的信息
Error connecting: rpc error: code = 14 desc = grpc: RPC failed fast due to transport failure
Error: rpc error: code = 14 desc = grpc: RPC failed fast due to transport failure

  请确认你是在最新的1.0.0镜像下运行的
- 如果你看到如下错误

[configtx/tool/localconfig] Load -> CRIT 002 Error reading configuration: Unsupported Config Type "" panic: Error reading configuration: Unsupported Config Type ""

  那是因为你没有正确设置FABRIC_CFG_PATH 环境变量。configtxgen
工具需要这个变量来寻找configtx.yaml。回头去执行export FABRIC_CFG_PATH=$PWD,然后重新创建你的channel基础文件。
- 清理网络,使用down指令

./byfn.sh down
  • 如果你看到一个错误状态是你仍然有活动端点,修剪你的Docker网络。这将会消除你之前的网络环境,给你开始一个新的环境。
docker network prune

  你将会看到如下信息

WARNING! This will remove all networks not used by at least one container.
Are you sure you want to continue? [y/N]

选择y
- 如果你看到如下的类似错误信息

/bin/bash: ./scripts/script.sh: /bin/bash^M: bad interpreter: No such file or directory

  确保使用到的文件是用Unix编码。着很多时候是因为没有设置git配置中的core.autocrlf为false。有一些方法修复这个。假设你有权限访问vim编辑器,打开文件

     vim ./fabric-samples/first-network/scripts/script.sh

然后修改它的编码通过执行下面的vim命令

     :set ff=unix

此篇文章是fabric官网指南的完整原创翻译。
原地址 http://hyperledger-fabric.readthedocs.io/en/latest/build_network.html

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值