构建你第一个由两个组织组成的Hyperledger fabric 网络(BYFN),每个都包含两个peer节点,和一个”solo”的order 节点
在我们开始前,保证所有的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 [-c ] [-t ] [-d ] [-f file>] [-s ] [-l ] [-i ] [-v]
- 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 to use (defaults to "mychannel")
-t - CLI timeout duration in seconds (defaults to 10)
-d - delay duration in seconds (defaults to 3)
-f file> - specify which docker-compose file use (defaults to docker-compose-cli.yaml)
-s - the database backend to use: goleveldb (default) or couchdb
-l - the chaincode language: golang (default) or node
-i - 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秒的查询请求。
执行下面的命令
./byfn.sh generate
你会看到后续要发生什么的简短描述,伴随着yes/no的命令提示行。
按下y或者敲回车会执行描述的动作。
截图略过。。。。。
第一步首先创建各类网络组件所需要的证书和私钥,引导ordering服务的创世区块(genesis block),配置一个channel所需要的配置事务(transactions)集合。
现在你可以启动网络使用下列指令
./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章节,让我们看看是否能帮助你发现错误
最后,让我把它们都一次关闭掉让我们可以探索网络设置。以下命令会杀掉容器,删除加密素材和四个网络基础文件,从你的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
我们将使用cryptogen工具来生成我们各种网络组件的加密材料(X509证书以及签名秘钥),这些证书是身份的代表,他们准许在我们实体通讯和交易的过程中签名和验证身份验证。
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。
configtxgen工具被用来创建四个配置基础文件:
两个锚节点交易,每个机构各一个
可以查看configtxgen关于这个工具功能性的完整描述,
排序区块是排序服务的创世区块,并且在channel创建时 channel
配置交易文件就被广播到了order节点。锚节点交易,顾名思义,指明这个channel上每个组织的锚节点。
Configtxgen使用一个文件- configtx.yaml里面包含了样例网络的定义。有三个成员:一个排序组织和两个分别管理着两个peer节点的peer组织。这个文件同时还指定了一个联合体- SampleConsortium-由两个peer组织构成,注意文件头部的 “Profiles” 部分。你会注意到有两个独特的标题。
一个用于order创世区块- TwoOrgsOrdererGenesis,另一个用于channel- TwoOrgsChannel。
这些头文件很重要,因为我们将在创建基础文件时将它们作为参数传入。
注意:SampleConsortium是在系统级配置定义,然后在channel级配置中引入。Channel存在于联合体范围之内,所有的联合体必须在网络范围内定义。
这个文件同样包含两个附加的规范值得注意。
第一,我们定义了每个peer组织的锚节点(peer0.org1.example.com & peer0.org2.example.com)。
你可以使用configtxgen 和 cryptogen命令创建证书/私钥和各种各样的配置基础文件。或者你可以试着修改byfn.sh文件来实现你自己的小目标。
你可以参考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文件夹。
下一步我们需要创建一个channel事务基础文件。确认替换了$CHANNEL_NAME
参数或者设置了环境变量CHANNEL_NAME,它将贯穿这些文档被使用
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
为了一下针对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
回想一下,我们使用上面“创建一个渠道配置交易“部分中的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相关操作。
以下命令是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
注意:我们将利用一个简单的码链做演示。想学习怎样编写自己的码链,请查看“ 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的标识符和链码的名称。
让我们查询值a来确定链码已经被恰当的实例化以及状态DB被填充(the state DB was populated)。查询语法如下:
peer chaincode query -C $CHANNEL_NAME -n mycc -c '{"Args":["query","a"]}'
现在让我们把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"]}'
确认一下上一步查询结果,初始化a为100,上一步调用移动了10,那么应该在查询a应该显示90。查询语句如下:
peer chaincode query -C $CHANNEL_NAME -n mycc -c '{"Args":["query","a"]}'
查询结果为
Query Result: 90
注意:这些步骤描述script.sh由’./byfn.sh up’运行的场景。 使用./byfn.sh清理网络并确保该命令处于活动状态。 然后使用相同的docker-compose重新启动您的网络
链码必须被安装到一个peer节点上,以保证他能成功对账本进行读/写操作。此外,只有在一个链码init或者对它进行传统读/写交易操作才会启动一个链码容器。
检查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 =====================
_____ _ _ ____
| ____| | \ | | | _ \
| _| | \| | | | | |
| |___ | |\ | | |_| |
|_____| |_| \_| |____/
你可以滚动这些日志查看各类交易日期
检查个别链码容器,查看每个容器交易的分别执行情况。这是每个容器的合并输出
$ 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"}
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容器提供两次相同的私钥。
状态数据库能从默认的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链码交互。
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"]}'
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}}]
CouchDB是一种NoSQL解决方案。它是一种面向文档的数据库,文档字段被存储为键值映射。字段可以是简单的键值对、列表或者映射。除了LevelDB支持的键查询/复合键/键范围查询,CouchDB还具备完整的数据富查询能力,例如对整个区块链数据的无键查询,当他的数据使用json方式存储的就可以被完整查询。所以CouchDB可以满足很多LevelDB不支持的链表、审计、报告需求。
CouchDB同样也增加了区块链的合规性和数据保护的安全性。因为它能够通过过滤和屏蔽事务中的单个属性来实现字段级别的安全,如果需要能值允许读权限。
另外,CouchDB属于CAP定义中的AP类型(可用性和分区容错性)。他使用最终以直线的主-主复制模型。更多的信息可以查看 Eventual Consistency page of the CouchDB documentation,但是在每个fabric节点中,已经没有了数据复制,写到数据已经被保证了一致性和持久性(不同于最终一致性)。
CouchDB是Fabric第一个外部可插拔的状态数据库,并且可能也应该会有其他额外的数据库想法。例如,IBM允许他们的区块链支持关系型数据库,同时CP-TYPE(一致性和分区容错性)数据库可能也会需要。从而没有在应用程序的级别保证数据库一致性。
如果peer容器或者CouchDB容器的数据需要被持久化。一个想法是挂载docker宿主机的目录到容器的关联目录。例如,你增加以下两行到docker-compose-base.yaml的peer容器配置中去。
volumes:
- /var/hyperledger/peer0:/var/hyperledger/production
针对CouchDB容器,你可以增加下面一行到CouchDB容器配置
volumes:
- /var/hyperledger/couchdb0:/opt/couchdb/data
./byfn.sh down
注意:如果不移除旧的容器和镜像,你会看到错误
docker rm -f $(docker ps -aq)
docker rmi -f $(docker images -q)
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 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