[toc]
运行一个简单的Fabric网络
设定一个简单的Fabric的网络场景,包括2个organization,每个有2个peer,并使用”solo” ordering服务;网络实体所需的加密材料(x509证书)已预先生成并放到相应目录和配置文件里了。无需修改这些配置; example/e2e_cli文件夹里包含了docker-compose文件和要用来创建和测试的网络的脚本文件;
另外如何使用配置生成工具configtxgen生成网络配置;
前提
完成以下安装Fabric源码和编译configtxgen工具:
- 完成环境,并设置正确的$GOPATH环境变量;
在/etc/profile/go.sh 中加入以下内容
export PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/srv/jdk1.8.0_66/bin:/root/bin:/usr/local/go/bin
export GOPATH=/opt/gopath
chmod +x /etc/profile/go.sh && source /etc/profile/go.sh
- 接取Fabric源码;
# git clone https://github.com/hyperledger/fabric.git
如果运行在linux,在Fabric目录下执行以下命令:
# cd $GOPATH/src/github.com/hyperledger/fabric
# make configtxgen
# 输出
build/bin/configtxgen
CGO_CFLAGS=" " GOBIN=/opt/gopath/src/github.com/hyperledger/fabric/build/bin go install -tags "nopkcs11" -ldflags "-X github.com/hyperledger/fabric/common/configtx/tool/configtxgen/metadata.Version=1.0.7-snapshot-84a7e5c" github.com/hyperledger/fabric/common/configtx/tool/configtxgen
Binary available as build/bin/configtxgen
如果运行在OSX,先安装Xcode 8.0或者以上版本,然后在Fabric目录下执行以下命令:
# 安装 Homebrew,若mac上有brew的可以跳过此步骤
/usr/bin/ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)"
#添加 gnu-tar
# brew install gnu-tar --with-default-name
#添加 libtool
# brew install libtool
# 编译 configtxgen
# make confgitxgen
build/bin/configtxgen
CGO_CFLAGS=" " GOBIN=/Users/johndoe/work/src/github.com/hyperledger/fabric/build/bin go install -ldflags "-X github.com/hyperledger/fabric/common/metadata.Version=1.0.0-snapshot-8d3275f -X github.com/hyperledger/fabric/common /metadata.BaseVersion=0.3.0 -X github.com/hyperledger/fabric/common/metadata.BaseDockerLabel=org.hyperledger.fabric" github.com/hyperledger/fabric/common/configtx/tool/configtxgen
Binary available as build/bin/configtxgen``
编译后扫行文件放在Fabric目录下的 build/bin/configtxgen中
执行完整脚本
为了加快部署过程,Fabric提供了一个脚本 来执行所有任务。执行该脚本 会生成配置结果、本地网络、Chaincode测试;
进入 examples/e2e_cli
目录,首先从Dcoker Hub摘取镜像:
# 执行脚本
# bash ./download-dockerimages.sh
这个执行过程耗时会比较长,脚本执行后输出:
===> List out hyperledger docker images
hyperledger/fabric-ca latest 35311d8617b4 7 days ago 240 MB
hyperledger/fabric-ca x86_64-1.0.0-alpha 35311d8617b4 7 days ago 240 MB
hyperledger/fabric-couchdb latest f3ce31e25872 7 days ago 1.51 GB
hyperledger/fabric-couchdb x86_64-1.0.0-alpha f3ce31e25872 7 days ago 1.51 GB
hyperledger/fabric-kafka latest 589dad0b93fc 7 days ago 1.3 GB
hyperledger/fabric-kafka x86_64-1.0.0-alpha 589dad0b93fc 7 days ago 1.3 GB
hyperledger/fabric-zookeeper latest 9a51f5be29c1 7 days ago 1.31 GB
hyperledger/fabric-zookeeper x86_64-1.0.0-alpha 9a51f5be29c1 7 days ago 1.31 GB
hyperledger/fabric-orderer latest 5685fd77ab7c 7 days ago 182 MB
hyperledger/fabric-orderer x86_64-1.0.0-alpha 5685fd77ab7c 7 days ago 182 MB
hyperledger/fabric-peer latest 784c5d41ac1d 7 days ago 184 MB
hyperledger/fabric-peer x86_64-1.0.0-alpha 784c5d41ac1d 7 days ago 184 MB
hyperledger/fabric-javaenv latest a08f85d8f0a9 7 days ago 1.42 GB
hyperledger/fabric-javaenv x86_64-1.0.0-alpha a08f85d8f0a9 7 days ago 1.42 GB
hyperledger/fabric-ccenv latest 91792014b61f 7 days ago 1.29 GB
hyperledger/fabric-ccenv x86_64-1.0.0-alpha 91792014b61f 7 days ago 1.29 GB
现在运行完整脚本:
现在运行完整脚本:
bash network_setup.sh up mychannel
如果没有设置 channel-ID
参数,channel名默认是mychannel
。脚本执行成功后输出:
===================== Query on PEER3 on channel 'mychannel' is successful =====================
===================== All GOOD, End-2-End execution completed =====================
此时,网络启动运行并测试成功
清理
停止网络:
# 在e2e_cli目录下
# docker rm -f $(docker ps -aq)
然后执行 docker images
命令查看Chaincode镜像,类似输出如下:
REPOSITORY TAG IMAGE ID CREATED SIZE
dev-peer3-mycc-1.0 latest 13f6c8b042c6 5 minutes ago 176 MB
dev-peer0-mycc-1.0 latest e27456b2bd92 5 minutes ago 176 MB
dev-peer2-mycc-1.0 latest 111098a7c98c 5 minutes ago 176 MB
删除镜像:
docker rmi <IMAGE ID> <IMAGE ID> <IMAGE ID>
例如:
# docker rmi -f 13e e122 333
最后删除配置结果, 在crypto/orderer
目录删除 orderer.block
和channel.tx;
configtxgen
configtxgen 工具生成两个内容: Orderer的bootstrap block和Fabric的channel configuration transaction;
roderer block是ordering服务的创世区块; channel transaction文件在create channel时会被广播给orderer;
configtx.yaml
包含网络的定义,并给出了网络组件的拓扑结构-2个成员(Org0和Org1)分别管理维护2个peer。 还指出每个网络实体的加密材料的存储位置。crypto
目录包含每个实体的admin证书、ca证书、签名证书和私钥;
为了方便使用,官方提供了一个脚本 generateCfgTrx.sh
,该脚本整合了configtxgen
的执行过程,执行后会生成两个配置结果:orderer.block
和channel.tx
。如果运行过上边network_setup.sh
则这两个配置结果已生成,要先到crypto/orderere
目录将之删除;
执行generateCfgTrx.sh
脚本
在e2e_cli
目录下:
# cd $GOPATH/src/github.com/hyperledger/fabric/examples/e2e_cli
generateCfgTrx.sh
脚本有个可选能数channel-ID,如果不设此参数,则默认为mychannel;
# <channel-ID>参数是要可选的
# bash generateCfgTrx.sh <channel-ID>
执行成功后输出:
2017/02/28 17:01:52 Generating new channel configtx
2017/02/28 17:01:52 Creating no-op MSP instance
2017/02/28 17:01:52 Obtaining default signing identity
2017/02/28 17:01:52 Creating no-op signing identity instance
2017/02/28 17:01:52 Serializing identity
2017/02/28 17:01:52 signing message
2017/02/28 17:01:52 signing message
2017/02/28 17:01:52 Writing new channel tx
生成的orderer.block
和channel.tx
两个文件存放在corypto/orderer
目录;
orderer.block
是ordering服务的创世区块,channel.tx
包含新channel的配置信息。如前所述,这俩文件 都来自configtx.yaml及其所包含的加密材料和网络信息的数据;
注: 也可以手动执行脚本generateCfgTrx.sh
里的命令。如果傅这种方式,则必需先用e2e_cli
目录下的configtx.yaml
替换Fabric sampleconfgi目录下默认的configtx.yaml
,然后返回fabric目录执行这些命令,前提是删除之前的generateCfgTrx.sh
生成的两个文件;
启动网络
使用docker-compose启动网络,如果还没有摘取 Fabric镜像,则返回之前的操作去拉取镜像;
脚本scrpit.sh
嵌入到docker-compose文件里,该脚本将peer加入到channel并向peer发送read/write请求,如此便可自动执行交易流程。如果还不想使用这个脚本自动执行交易,可以跳到下面”手动执行交易”一节;
在e2e_cli
目录下使用docker-compose生成网络实体并执行嵌入的脚本:
CHANNEL_NAME=<channel-id> docker-compose up -d
如果之前创建了个channel名,就必须将其作为参数,否则使用默认的mychannel。例如:
CHANNEL_NAME=mychannel dcoker -comopse up -d
等待一会儿,因为背后有交易会发送到peer。执行docker ps
查看运行状态的container,可以看到以下内容:
vagrant@hyperledger-devenv:v0.3.0-4eec836:/opt/gopath/src/github.com/hyperledger/fabric/examples/e2e_cli$ docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
45e3e114f7a2 dev-peer3-mycc-1.0 "chaincode -peer.a..." 4 seconds ago Up 4 seconds dev-peer3-mycc-1.0
5970f740ad2b dev-peer0-mycc-1.0 "chaincode -peer.a..." 24 seconds ago Up 23 seconds dev-peer0-mycc-1.0
b84808d66e99 dev-peer2-mycc-1.0 "chaincode -peer.a..." 48 seconds ago Up 47 seconds dev-peer2-mycc-1.0
16d7d94c8773 hyperledger/fabric-peer "peer node start -..." About a minute ago Up About a minute 0.0.0.0:10051->7051/tcp, 0.0.0.0:10053->7053/tcp peer3
3561a99e35e6 hyperledger/fabric-peer "peer node start -..." About a minute ago Up About a minute 0.0.0.0:9051->7051/tcp, 0.0.0.0:9053->7053/tcp peer2
0baad3047d92 hyperledger/fabric-peer "peer node start -..." About a minute ago Up About a minute 0.0.0.0:8051->7051/tcp, 0.0.0.0:8053->7053/tcp peer1
1216896b7b4f hyperledger/fabric-peer "peer node start -..." About a minute ago Up About a minute 0.0.0.0:7051->7051/tcp, 0.0.0.0:7053->7053/tcp peer0
155ff8747b4d hyperledger/fabric-orderer "orderer" About a minute ago Up About a minute 0.0.0.0:7050->7050/tcp orderer
背后发生了什么?
在CLI容器中执行了脚本
script.sh
。该脚本用默认的mychannel
执行createChannel
命令,这个命令用到了之前configtxgen
工具生成的channel.tx
。createChannel
执行后会生成一个创世区块mychannel.block
并保存到当前目录 ;对4个peer分别执行
joinChannel
命令,通过初始区块mychannel.block
加入channel。 至此有一个channel包含4个peer和2个organzation;PER0
和PEER1
属于Org0,PEER2
和PEER3
属于Org1。这些关系的定义都在confiigtx.yaml
中Chaincode
chaincode_example02
被 install到PEER0
和PEER2
然后Chaincode在
PEER2
上instantiate。实例化是指启动容器和初始化与Chaincode相关的键值对,本例中的初始值 是["a","100" "b","200"]
。实例化的结果是一个名为dev-peer2-mycc-1.0
的容器启动,注意,这个容器仅是针对PEER2
;实例化时还会带有背书策略参数,本例中背书策略为”-P” OR(‘OrgOMSP.memeber”,Org1MSP.member’)”,意思是任何交易必须由绑定到Org0或者Org1的peer背书;
对于”a”的query请求发慈禧太后到
PEER0
。在之前Chaincode被install到PEER0
了,所以就可以启动一个名为dev-peer0-mycc-1.0
的新容器,然后返回查询结果。由于没有write操作发生,所以”a”的值依然是”100”。从”a”转移”10”给”b”的invoke请求发送到
PEER0
Chaincode install 到
PEER3
对”a”的query 请求发关到
PEER3
。 这启动了第三个名为dev-peer3-mycc-1.0
的容器,并返回查询结果90,正确的反应了之前的交易;
Chaincode必须被 install到一个peer上才能成功的对这个peer的ledger执行read/write操作。此外,只有当在peer上针对chaincode执行read/writer操作时,这个peer上才会启该chaincode容器(比如,查询”a”的值)交易到容器启动。channel中的所有peer(包括那结没有install chaincode的peer,就像上例中的PEER3
)都会维护一个准确的ledger,ledger包含存储了不可变的、有序的交易记录的block,还有维护current state的statedb。在peer上install chaincode之后就可以直接使用该peer上的chaincode了(就像上例中的PEER3
),因为之前已经instantiated过了;
查看交易
查看CLI容器的log:
# docker logs -f cli
输出:
2017-02-28 04:31:20.841 UTC [logging] InitFromViper -> DEBU 001 Setting default logging level to DEBUG for command 'chaincode'
2017-02-28 04:31:20.842 UTC [msp] GetLocalMSP -> DEBU 002 Returning existing local MSP
2017-02-28 04:31:20.842 UTC [msp] GetDefaultSigningIdentity -> DEBU 003 Obtaining default signing identity
2017-02-28 04:31:20.843 UTC [msp] Sign -> DEBU 004 Sign: plaintext: 0A8F050A59080322096D796368616E6E...6D7963631A0A0A0571756572790A0161
2017-02-28 04:31:20.843 UTC [msp] Sign -> DEBU 005 Sign: digest: 52F1A41B7B0B08CF3FC94D9D7E916AC4C01C54399E71BC81D551B97F5619AB54
Query Result: 90
2017-02-28 04:31:30.425 UTC [main] main -> INFO 006 Exiting.....
===================== Query on chaincode on PEER3 on channel 'mychannel' is successful =====================
===================== All GOOD, End-2-End execution completed =====================
实时查看日志时,需要打开两个终端;
首先,停止运行着的docker容器:
# docker rm -f $(docker ps -aq)
在第一个终端启动docker-compose脚本:
CHANNEL_NAME=<channel-id> docker-compose up -d
在第二个终端查看log:
# docker logs -f cli
这将实时输出通过script.sh
执行的交易信息;
查看chaincode日志
对每个chaincode容器单独查看log,输出:
$ docker logs dev-peer2-mycc-1.0
04:30:45.947 [BCCSP_FACTORY] DEBU : Initialize BCCSP [SW]
ex02 Init
Aval = 100, Bval = 200
$ docker logs dev-peer0-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-peer3-mycc-1.0
04:31:30.420 [BCCSP_FACTORY] DEBU : Initialize BCCSP [SW]
ex02 Invoke
Query Response:{"Name":"a","Amount":"90"}
手动执行交易
停止所有容器:
# docker rm -f $(docker ps -aq)
然后,执行docker iamge
命令查看chaincode镜像,会有类似以下内容:
REPOSITORY TAG IMAGE ID CREATED SIZE
dev-peer3-mycc-1.0 latest 13f6c8b042c6 5 minutes ago 176 MB
dev-peer0-mycc-1.0 latest e27456b2bd92 5 minutes ago 176 MB
dev-peer2-mycc-1.0 latest 111098a7c98c 5 minutes ago 176 MB
删除这些镜像:
docker rmi <IMAGE ID> <IMAGE ID> <IMAGE ID>
比如:
# docker rmi -f 12f e27 111
确保之前生成的配置内容还在,如果删除了就再执行脚本:
./generatecCfgTrx.sh<channel-ID>
或者使用脚本中的命令手动生成;
修改docker-compose文件
打开docker-compose文件注释掉执行script.sh
脚本的命令,如下:
working_dir: /opt/gopath/src/github.com/hyperledger/fabric/peer
# command: /bin/bash -c './scripts/script.sh ${CHANNEL_NAME}'
保存文件 ,重启网络:
# 在e2e_cli目录下执行,设置正确的CHANNEL_NAME
CHANNEL_NAME=<channel-id> docker-compose up -d
命令语法
参照 script.sh
脚本中的creaete和join命令。下面的命令只是针对PEER0
的,当对orderer和peer执行命令,需要修改下面给出的四个环境变量的值;
# 对PEER0所用的环境变量
CORE_PEER_MSPCONFIGPATH=$GOPATH/src/github.com/hyperledger/fabric/peer/crypto/peer/peer0/localMspConfig
CORE_PEER_ADDRESS=peer0:7051
CORE_PEER_LOCALMSPID="Org0MSP"
CORE_PEER_TLS_ROOTCERT_FILE=$GOPATH/src/github.com/hyperledger/fabric/peer/crypto/peer/ peer0/localMspConfig/cacerts/peerOrg0.pem
第个peer的环境变的值都在docker-compose文件中
Create channel
进去cli容器:
# docker exec -it cli bash
执行成功输出:
root@0d78bb69300d:/opt/gopath/src/github.com/hyperledger/fabric/peer#
用-c
指定channel name, -f
指定channel configruation transaction(此例中是channel.tx
)当然也可以使用不同的名称安装configuration transaction;
# channel.tx 和 orderer.block 在 cli 容器的 crypto/orderer 目录下
peer channel create -o orderer0:7050 -c mychannel -f crypto/orderer/channel.tx --tls $CORE_PEER_TLS_ENABLED --cafile $GOPATH/src/github.com/hyperledger/fabric/peer/crypto/orderer/localMspConfig/cacerts/ordererOrg0.pem
由于此例的peer channel create
命令是针对orderer的,所以需要修改之前的环境变量,因此上边的命令应该是:
CORE_PEER_MSPCONFIGPATH=$GOPATH/src/github.com/hyperledger/fabric/peer/crypto/orderer/localMspConfig CORE_PEER_LOCALMSPID="OrdererMSP" peer channel create -o orderer0:7050 -c mychannel -f crypto/orderer/channel.tx --tls $CORE_PEER_TLS_ENABLED --cafile $GOPATH/src/github.com/hyperledger/fabric/peer/crypto/orderer/localMspConfig/cacerts/ordererOrg0.pem
注意:下面的其他命令依然在CLI容中执行,而且要记住命令里每个peer对应的环境变量;
将指定的peer加入到channel:
#默认只将 PEER0 加入
peer channel join -b mychannel.block
完整的命令应该是:
CORE_PEER_MSPCONFIGPATH=$GOPATH/src/github.com/hyperledger/fabric/peer/crypto/peer/peer0/localMspConfig CORE_PEER_ADDRESS=peer0:7051 CORE_PEER_LOCALMSPID="Org0MSP" CORE_PEER_TLS_ROOTCERT_FILE=$GOPATH/src/github.com/hyperledger/fabric/peer/crypto/peer/peer0/localMspConfig/cacerts/peerOrg0.pem peer channel join -b mychannel.block
修改这四个环境变量将其他的peer加入到channel中
将示例chaincode代码安装到四个对等节点中的一个:
Install chaincode
# 在命令前面要加上peer对应的四个环境变量
peer chaincode install -n mycc -v 1.0 -p github.com/hyperledger/fabric/examples/chaincode/go/chaincode_example02
在一个peer上实例化chaincode,这将对该peer启动一个chaincode容器,并为该chaincode设置背书策略。此例中定义的策略是有org0
或org1
中的一个peer背书即可;
# 在命令前面要加上peer对应的四个环境变量
# 用 -C 参数设置正确的channel名,默认是 mychannel
peer chaincode instantiate -o orderer0:7050 --tls $CORE_PEER_TLS_ENABLED --cafile $GOPATH/src/github.com/hyperledger/fabric/peer/crypto/orderer/localMspConfig/cacerts/ordererOrg0.pem -C mychannel -n mycc -v 1.0 -p github.com/hyperledger/fabric/examples/chaincode/go/chaincode_example02 -c '{"Args":["init","a", "100", "b","200"]}' -P "OR ('Org0MSP.member','Org1MSP.member')"
Invoke chaincode
# 在命令前面要加上peer对应的四个环境变量
peer chaincode invoke -o orderer0:7050 --tls $CORE_PEER_TLS_ENABLED --cafile $GOPATH/src/github.com/hyperledger/fabric/peer/crypto/orderer/localMspConfig/cacerts/ordererOrg0.pem -C mychannel -n mycc -c '{"Args":["invoke","a","b","10"]}'
Query chaincode
# 在命令前面要加上peer对应的四个环境变量
peer chaincode query -C mychannel -n mycc -c '{"Args":["query","a"]}'
执行结果:
Query Result: 90
手动构建镜像
构建peer和orderer镜像:
# 在farbic目录下执行,如果不能顺利生成镜像,则使用vagrant环境
# make peer-docker orderer-docker
执行docker images
命令输出
vagrant@hyperledger-devenv:v0.3.0-4eec836:/opt/gopath/src/github.com/hyperledger/fabric$ docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
hyperledger/fabric-orderer latest 264e45897bfb 10 minutes ago 180 MB
hyperledger/fabric-orderer x86_64-0.7.0-snapshot-a0d032b 264e45897bfb 10 minutes ago 180 MB
hyperledger/fabric-peer latest b3d44cff07c6 10 minutes ago 184 MB
hyperledger/fabric-peer x86_64-0.7.0-snapshot-a0d032b b3d44cff07c6 10 minutes ago 184 MB
hyperledger/fabric-javaenv latest 6e2a2adb998a 10 minutes ago 1.42 GB
hyperledger/fabric-javaenv x86_64-0.7.0-snapshot-a0d032b 6e2a2adb998a 10 minutes ago 1.42 GB
hyperledger/fabric-ccenv latest 0ce0e7dc043f 12 minutes ago 1.29 GB
hyperledger/fabric-ccenv x86_64-0.7.0-snapshot-a0d032b 0ce0e7dc043f 12 minutes ago 1.29 GB
hyperledger/fabric-baseimage x86_64-0.3.0 f4751a503f02 4 weeks ago 1.27 GB
hyperledger/fabric-baseos x86_64-0.3.0 c3a4cf3b3350 4 weeks ago 161 MB
使用本地二进制文件
进支vagrant环境
cd $GOPATH/src/github.com/hyperledger/fabric/devenv
# 第一次启动VM用 vagrant up
vagrant ssh
在fabric目录编译peer和orderer:
make clean
make native
生成ccenv
镜像
make peer-docker
然后打开两个终端都进入vagrant,至此有三个终端都在vagrant里;
首先清空ledger文件/var/hyperledger/
(每次运行后,为避免错误或重复,都要清空):
rm -rf /var/hyperledger/*
使用configtxgen
工具创建orderer创世区块:
configtxgen -profile SampleMSPSolo -outputBlock orderer.block
用刚生成的创世区块启动orderer:
ORDERER_GENERAL_GENESISMETHOD=file ORDERER_GENERAL_GENESISFILE=./orderer.block orderer
创建 channel configuration transaction:
configtxgen -profile SampleSingleMSPSolo -outputCreateChannelTx channel.tx -channelID <channel-ID>
执行成功会在当前目录生成channel.tx
以chanless
模块启动peer:
peer node start --peer-defaultchain-false
以channel.tx
为参数创建channel:
peer channel create -o 127.0.0.1:7050 -c mychannel -f channel.tx
执行后在当前目录生成一个channel的创世区块mychannel.block
Join channel
通过channel的创世区块mychannel.block
加入channel:
peer channel join -b mychannel.block
Install chaincode
在peer上安装chaincode:
peer chaincode install -o 127.0.0.1:7050 -n mycc -v 1.0 -p github.com/hyperledger/fabric/examples/chaincode/go/chaincode_example02
执行成功后查看文件可以看到mycc.1.0:
ls /var/hyperledger/production/chaincodes
Instantiate chaincode
实例化chaincode:
peer chaincode instantiate -o 127.0.0.1:7050 -C mychannel -n mycc -v 1.0 -p github.com/hyperledger/fabric/examples/chaincode/go/chaincode_example02 -c '{"Args":["init","a", "100", "b","200"]}'
docker ps
查看运行中的容器,如果chaincode启动成功,则显示:
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
bd9c6bda7560 dev-jdoe-mycc-1.0 "chaincode -peer.a..." 5 seconds ago Up 5 seconds dev-jdoe-mycc-1.0
Invoke chaincode
调用chaincode从”a”转移”10”给”b”:
peer chaincode invoke -o 127.0.0.1:7050 -C mychannel -n mycc -c '{"Args":["invoke","a","b","10"]}'
Query chaincode
查询”a”的值:
# 返回值应是 90
peer chaincode query -o 127.0.0.1:7050 -C mychannel -n mycc -c '{"Args":["query","a"]}'
运行完成后不要忘记清空ledger文件夹/var/hyperledger
:
rm -rf /var/hyperledger/*
使用CouchDB
可以将stateDB默认的goleveldb替换成CouchDB。对于CouchDB, chainocde各功能依然可用,但将chaincode数据以JSON方式存储的话就可以使用CouchDB的复杂查询的功能;
为了使用CouchDB,除了最前面的”前提”一节的操作外,还需要下边两步启动CouchDB容器并将之与peer容器关联;
- 构建 CouchDB镜像
# make sure you are in the fabric directory
make couchdb
- 编辑
fabric/example/e2e_cli/docker-compose.yaml
和docker-compose.yam
将所有与CouchDB有关的内容取消注释。这样chaincode_xample02
就可以CouchDB下运行了;
注意:如果将CouchDB容器的端口映射的主机,请一定要注意安全,在开发环境 中将端映射出来可以通过CouchDB的web界面可视化操作数据。生产环境中一般不会做端口映射,以限制CouchDB的外部访问;
可以用chaincode_example02
在CouldDB下执行上边的chaincode操作,但是为了使用CouchDB的复杂查询功能,chaincode数据一定要以JSON格式存储(例如 fabric/examples/chaincode/go/merbles02);
使用手动执行交易
这一节中的步骤install、instantiate、invoke和querymarbles02
,执行完成join channel
这步后使用下边的命令操作marbles02
:
- 在
PEER0
上安装实例化chaincode
peer chaincode install -o orderer0:7050 -n marbles -v 1.0 -p github.com/hyperledger/fabric/examples/chaincode/go/marbles02
peer chaincode instantiate -o orderer0:7050 --tls $CORE_PEER_TLS_ENABLED --cafile /opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/orderer/localMspConfig/cacerts/ordererOrg0.pem -C mychannel -n marbles -v 1.0 -p github.com/hyperledger/fabric/examples/chaincode/go/marbles02 -c '{"Args":["init"]}' -P "OR ('Org0MSP.member','Org1MSP.member')"
- 创建一些marble并移动它们
peer chaincode invoke -o orderer0:7050 --tls $CORE_PEER_TLS_ENABLED --cafile /opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/orderer/localMspConfig/cacerts/ordererOrg0.pem -C mychannel -n marbles -c '{"Args":["initMarble","marble1","blue","35","tom"]}'
peer chaincode invoke -o orderer0:7050 --tls $CORE_PEER_TLS_ENABLED --cafile /opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/orderer/localMspConfig/cacerts/ordererOrg0.pem -C mychannel -n marbles -c '{"Args":["initMarble","marble2","red","50","tom"]}'
peer chaincode invoke -o orderer0:7050 --tls $CORE_PEER_TLS_ENABLED --cafile /opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/orderer/localMspConfig/cacerts/ordererOrg0.pem -C mychannel -n marbles -c '{"Args":["initMarble","marble3","blue","70","tom"]}'
peer chaincode invoke -o orderer0:7050 --tls $CORE_PEER_TLS_ENABLED --cafile /opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/orderer/localMspConfig/cacerts/ordererOrg0.pem -C mychannel -n marbles -c '{"Args":["transferMarble","marble2","jerry"]}'
peer chaincode invoke -o orderer0:7050 --tls $CORE_PEER_TLS_ENABLED --cafile /opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/orderer/localMspConfig/cacerts/ordererOrg0.pem -C mychannel -n marbles -c '{"Args":["transferMarblesBasedOnColor","blue","jerry"]}'
peer chaincode invoke -o orderer0:7050 --tls $CORE_PEER_TLS_ENABLED --cafile /opt/gopath/src/github.com/hyperledger/fabric/peer/crypto/orderer/localMspConfig/cacerts/ordererOrg0.pem -C mychannel -n marbles -c '{"Args":["delete","marble1"]}'
如果做了CouchDB容器的端口映射,可以通过web界面查看数据,可以看到名为
mychannel
的数据库及其文档如果使用的是vagrant环境
http://localhost:15984/_utils
* 如果不是vagrant环境,使用CouchDB容器指定的端口
http://localhost:5984/_utils
- 有可规律的查询chaincode(例如,读取marble2)
peer chaincode query-C mychannel -n marbles -c {“Args”:[“readMarble”,”marble2”]}’
可以看到mable2
的详细信息:
Query Result: {"color":"red","docType":"marble","name":"marble2","owner":"jerry","size":50}
获取 marble1
的历史
peer chaincode query -C mychannel -n marbles -c '{"Args":["getHistoryForMarble","marble1"]}'
可以看到操作过marbel1
的交易:
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
所拥有的marble:
peer chaincode query -C mychannel -n marbles -c '{"Args":["queryMarblesByOwner","jerry"]}'
查询结果为jerry
所拥有的2个marble的信息:
peer chaincode query -C mychannel -n marbles -c '{"Args":["queryMarblesByOwner","jerry"]}'
查询结果为jerry
所拥有的2个marble的信息:
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}}]
通过owner
字段等于jerry
查询:
peer chaincode query -C mychannel -n marbles -c '{"Args":["queryMarbles","{\"selector\":{\"owner\":\"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}}]
数据持久化
如果需要对peer或CouchDB容器的数据持久化,一种是选择是将容器的相关目录挂载到docker主机;
例如,将下面两内容器入到docker-compose.yaml
文件中的对应peer处:
volumes:
- /var/hyperledger/peer0:/var/hyperledger/production
volumes:
- /var/hyperledger/couchdb0:/opt/couchdb/data
故障排除
- 每次运行后要清理文件
- 如果出现docker错误,则删除镜像,从头再操作一遍;
make clean
make peer-docker orderer-docker
- 如果出现下面的错误
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)
chaincode镜像(如dev-peer0-mycc-1.0
或dev-peer1-mycc-1.0
)可能是以前运行过的,删除它们然后重试;
docker rmi -f $(docker images | grep peer[0-9]-peer[0-9] | awk '{print $3}')
- 使用
down
选项清理网络
./network_setup.sh down
Next Previous