使用 1.0 版本
Hyperledger Fabric 1.0 版本整体 重新设计了架构,新的设计可以实现更好的扩展性和安全性。
下载 Compose 模板文件
$ git clone https://github.com/yeasy/docker-compose-files
进入 hyperledger/1.0
目录,查看包括若干模板文件,功能如下。
文件 | 功能 |
---|---|
orderer-base.yaml | orderer 节点的基础服务模板 |
peer-base.yaml | peer 节点的基础服务模板 |
docker-compose-base.yaml | 包含 orderer 和 peers 组织结构的基础服务模板 |
docker-compose-1peer.yaml | 使用自定义的 channel 启动一个最小化的环境,包括 1 个 peer 节点、1 个 orderer 节点、1 个 CA 节点、1 个 cli 节点 |
docker-compose-2orgs-4peers.yaml | 使用自定义的 channel 启动一个环境,包括 4 个 peer 节点、1 个 orderer 节点、1 个 CA 节点、1 个 cli 节点 |
docker-compose-2orgs-4peers-couchdb.yaml | 启动一个带有 couchdb 服务的网络环境 |
docker-compose-2orgs-4peers-event.yaml | 启动一个带有 event 事件服务的网络环境 |
e2e_cli/channel-artifacts | 存放创建 orderer, channel, anchor peer 操作时的配置文件 |
e2e_cli/crypto-config | 存放 orderer 和 peer 相关证书 |
e2e_cli/example | 用来测试的 chaincode |
scripts/setup_Docker.sh | 安装并配置 dokcer 和 docker-compose |
scripts/download_images.sh | 下载依赖镜像 |
scripts/start_fabric.sh | 快速启动一个fabric 网络 |
scripts/initialize.sh | 自动化测试脚本,用来初始化 channel 和 chaincode |
scripts/test_4peers.sh | 自动化测试脚本,用来执行 chaincode 操作 |
scripts/cleanup_env.sh | 容器,镜像自动清除脚本 |
scripts/test_1peer.sh | 测试1个peer网络的自动化脚本 |
kafka/ | 基于kafka 的 ordering 服务 |
安装 Docker 和 docker-compose
docker 及 docker-compose 可以自行手动安装。也可以通过 hyperledger/1.0/scripts 提供的 setup_Docker.sh
脚本自动安装。
$ bash scripts/setup_Docker.sh
获取 Docker 镜像
Docker 镜像可以自行从源码编译(make docker
),或从 DockerHub 仓库下载。
执行脚本获取
直接执行 hyperledger/1.0/scripts 提供的 download_images.sh
脚本获取。
$ bash scripts/download_images.sh
从官方仓库获取
从社区 DockerHub 仓库下载。
# pull fabric images
ARCH=x86_64
BASEIMAGE_RELEASE=0.3.1
BASE_VERSION=1.0.0
PROJECT_VERSION=1.0.0
IMG_TAG=1.0.0
echo "Downloading fabric images from DockerHub...with tag = ${IMG_TAG}... need a while"
# TODO: we may need some checking on pulling result?
docker pull hyperledger/fabric-peer:$ARCH-$IMG_TAG
docker pull hyperledger/fabric-orderer:$ARCH-$IMG_TAG
docker pull hyperledger/fabric-ca:$ARCH-$IMG_TAG
docker pull hyperledger/fabric-tools:$ARCH-$IMG_TAG
docker pull hyperledger/fabric-ccenv:$ARCH-$PROJECT_VERSION
docker pull hyperledger/fabric-baseimage:$ARCH-$BASEIMAGE_RELEASE
docker pull hyperledger/fabric-baseos:$ARCH-$BASEIMAGE_RELEASE
# Only useful for debugging
# docker pull yeasy/hyperledger-fabric
echo "===Re-tagging images to *latest* tag"
docker tag hyperledger/fabric-peer:$ARCH-$IMG_TAG hyperledger/fabric-peer
docker tag hyperledger/fabric-orderer:$ARCH-$IMG_TAG hyperledger/fabric-orderer
docker tag hyperledger/fabric-ca:$ARCH-$IMG_TAG hyperledger/fabric-ca
docker tag hyperledger/fabric-tools:$ARCH-$IMG_TAG hyperledger/fabric-tools
从第三方仓库获取
这里也提供了调整(基于 golang:1.8 基础镜像制作)后的第三方镜像,与社区版本功能是一致的。
通过如下命令拉取相关镜像,并更新镜像别名。
$ ARCH=x86_64
$ BASEIMAGE_RELEASE=0.3.1
$ BASE_VERSION=1.0.0
$ PROJECT_VERSION=1.0.0
$ IMG_TAG=1.0.0
$ docker pull yeasy/hyperledger-fabric-base:$IMG_VERSION
&& docker pull yeasy/hyperledger-fabric-peer:$IMG_VERSION
&& docker pull yeasy/hyperledger-fabric-orderer:$IMG_VERSION
&& docker pull yeasy/hyperledger-fabric-ca:$IMG_VERSION
&& docker pull hyperledger/fabric-couchdb:$ARCH-$IMG_VERSION
&& docker pull hyperledger/fabric-kafka:$ARCH-$IMG_VERSION
&& docker pull hyperledger/fabric-zookeeper:$ARCH-$IMG_VERSION
$ docker tag yeasy/hyperledger-fabric-peer:$IMG_VERSION hyperledger/fabric-peer
&& docker tag yeasy/hyperledger-fabric-orderer:$IMG_VERSION hyperledger/fabric-orderer
&& docker tag yeasy/hyperledger-fabric-ca:$IMG_VERSION hyperledger/fabric-ca
&& docker tag yeasy/hyperledger-fabric-peer:$IMG_VERSION hyperledger/fabric-tools
&& docker tag yeasy/hyperledger-fabric-base:$IMG_VERSION hyperledger/fabric-ccenv:$ARCH-$PROJECT_VERSION
&& docker tag yeasy/hyperledger-fabric-base:$IMG_VERSION hyperledger/fabric-baseos:$ARCH-$BASEIMAGE_RELEASE
&& docker tag yeasy/hyperledger-fabric-base:$IMG_VERSION hyperledger/fabric-baseimage:$ARCH-$BASEIMAGE_RELEASE
&& docker tag hyperledger/fabric-couchdb:$ARCH-$IMG_VERSION hyperledger/fabric-couchdb
&& docker tag hyperledger/fabric-zookeeper:$ARCH-$IMG_VERSION hyperledger/fabric-zookeeper
&& docker tag hyperledger/fabric-kafka:$ARCH-$IMG_VERSION hyperledger/fabric-kafka
启动 fabric 1.0 网络
通过如下命令快速启动。
$ bash scripts/start_fabric.sh
或者
$ docker-compose -f docker-compose-2orgs-4peers.yaml up
注意输出日志中无错误信息。
此时,系统中包括 7 个容器。
$ docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
8683435422ca hyperledger/fabric-peer "bash -c 'while true;" 19 seconds ago Up 18 seconds 7050-7059/tcp fabric-cli
f284c4dd26a0 hyperledger/fabric-peer "peer node start --pe" 22 seconds ago Up 19 seconds 7050/tcp, 0.0.0.0:7051->7051/tcp, 7052/tcp, 7054-7059/tcp, 0.0.0.0:7053->7053/tcp peer0.org1.example.com
95fa3614f82c hyperledger/fabric-ca "fabric-ca-server sta" 22 seconds ago Up 19 seconds 0.0.0.0:7054->7054/tcp fabric-ca
833ca0d8cf41 hyperledger/fabric-orderer "orderer" 22 seconds ago Up 19 seconds 0.0.0.0:7050->7050/tcp orderer.example.com
cd21cfff8298 hyperledger/fabric-peer "peer node start --pe" 22 seconds ago Up 20 seconds 7050/tcp, 7052/tcp, 7054-7059/tcp, 0.0.0.0:9051->7051/tcp, 0.0.0.0:9053->7053/tcp peer0.org2.example.com
372b583b3059 hyperledger/fabric-peer "peer node start --pe" 22 seconds ago Up 20 seconds 7050/tcp, 7052/tcp, 7054-7059/tcp, 0.0.0.0:10051->7051/tcp, 0.0.0.0:10053->7053/tcp peer1.org2.example.com
47ce30077276 hyperledger/fabric-peer "peer node start --pe" 22 seconds ago Up 20 seconds 7050/tcp, 7052/tcp, 7054-7059/tcp, 0.0.0.0:8051->7051/tcp, 0.0.0.0:8053->7053/tcp peer1.org1.example.com
测试网络
启动 fabric 网络后,可以进行 chaincode 操作,验证网络是否启动正常。
进入到 cli 容器里面,执行 initialize.sh
和 test_4peers.sh
脚本。
通过如下命令进入容器 cli 并执行测试脚本。
$ docker exec -it fabric-cli bash
$ bash ./scripts/initialize.sh
注意输出日志无错误提示,最终返回结果应该为:
UTC [main] main -> INFO 00c Exiting.....
===================== Chaincode Instantiation on PEER2 on channel 'businesschannel' is successful =====================
===================== All GOOD, initialization completed =====================
_____ _ _ ____
| ____| | | | | _
| _| | | | | | | |
| |___ | | | | |_| |
|_____| |_| \_| |____/
之后同样是在 cli
容器里执行 test_4peers.sh
脚本
$ bash ./scripts/test_4peers.sh
输出日志无错误提示,最终返回结果应该为:
Query Result: 80
UTC [main] main -> INFO 008 Exiting.....
===================== Query on PEER3 on channel 'businesschannel' is successful =====================
===================== All GOOD, End-2-End execution completed =====================
_____ _ _ ____
| ____| | | | | _
| _| | | | | | | |
| |___ | | | | |_| |
|_____| |_| \_| |____/
至此,整个网络启动并验证成功。
使用 Hyperledger Fabric SDK Node 进行测试
Hyperledger Fabric Client SDK 能够非常简单的使用API和 Hyperledger Fabric Blockchain 网络进行交互。其v1.1
及其以上的版本添加了一个重要的功能Conection-Profile来保存整个network中必要的配置信息,方便client读取和配置。 该Demo基于Connection-Profile
测试了整个网络的如下功能:
- Fabric CA 相关
- Enroll用户
- Register用户
- Channel 相关
- 创建Channel
- 将指定Peer join Channel
- 查询Channel相关信息
- 动态更新Channel配置信息
- Chaincode 相关
- Install Chaincode
- Instantiate Chaincode
- Invoke Chaincode
- Query Chaincode
- 查询Chaincode相关信息
主要依赖
- Node v8.9.0 或更高 (注意目前v9.0+还不支持)
- npm v5.5.1 或更高
- gulp命令。 必须要进行全局安装
npm install -g gulp
- docker运行环境
- docker compose工具
主要fabric环境可参考Fabric 1.0。
下载 Demo 工程
$ git clone https://github.com/Sunnykaby/Hyperledger-fabric-node-sdk-demo
进入 Hyperledger-fabric-node-sdk-demo
目录,查看各文件夹和文件,功能如下。
文件/文件夹 | 功能 |
---|---|
artifacts-local | 本地准备好构建fabric网络的基础材料 |
artifacts-remote | 使用官方fabric-sample动态构建网络 |
extra | 一些拓展性的材料 |
node | 基于Fabric SDK Node的demo核心代码 |
src | 测试用chaincode |
Init.sh | 构建Demo的初始化脚本 |
构建Demo
该项目提供两种Demo构建方式:
- 利用本地已经准备好的相关网络资源,启动fabric network。
- 利用官方fabric-sample项目,动态启动fabric network。
当然,你也可以使用自己已经创建好的fabric network和其相关的connection-profile来测试Demo。
##进入项目根目录
##使用本地资源构建Demo
./Init.sh local
##使用官方资源构建Demo
./Init.sh remote
执行之后,会在根目录中生成一个demo
文件夹,其就是Demo程序的入口。
清理Demo资源,使用./Init.sh clean
启动Fabric网络
首先,我们需要准备一个fabric网络来进行测试。 进入到demo
文件夹。
本地资源构建网络
进入资源目录,利用脚本启动网络即可。
cd artifacts
##启动网络
./net.sh up
##关闭网络
./net.sh down
用该脚本启动网络中包含:1个orderer, 2个organisation, 4个peer(每个组织有2个peer)和两个ca(每个组织一个)。
官方资源构建网络
在demo目录,利用脚本启动网络即可。
##启动网络,并配置本地资源
./net.sh init
##关闭网络并清理资源
./net.sh clean
用该脚本启动网络中包含:1个orderer, 2个organisation, 4个peer(每个组织有2个peer)和两个ca(每个组织一个)。
与本地资源启动不同,该方案主要有以下步骤:
- 将官方fabric-sample项目clone到本地
- 利用
fabric-sample/first-network/bynf.sh up
启动fabric脚本 - 将一些资源文件连接到指定位置,方便node程序使用
- 通过资源文件构建connection-profile(替换密钥等)
- 创建一个新的channel的binary
详细信息可以直接查看net.sh
脚本。
clean
命令会将所有相关的docker 容器和remote的动态资源全部删除。还原到最初的demo文件状态。
资源清单
无论是remote还是local模式,最终资源和网络准备完成之后,核心资源列表如下:
demo/artifacts/
├── channel-artifacts
│ ├── channel2.tx
│ ├── channel.tx
│ ├── genesis.block
│ ├── Org1MSPanchors.tx
│ └── Org2MSPanchors.tx
├── connection-profile
│ ├── network.yaml
│ ├── org1.yaml
│ ├── org2.yaml
├── crypto-config
│ ├── ordererOrganizations
│ │ └── example.com
│ └── peerOrganizations
│ ├── org1.example.com
│ └── org2.example.com
运行Demo
网络和相关资源准备成功之后,进入demo/node
目录。 其主要结构为:
├── app //核心应用接口
│ ├── api-handler.js //接口定义文件
│ ├── *.js //应用实现模块
│ ├── tools //通用工具类
│ │ ├── ca-tools.js
│ │ ├── config-tool.js
│ │ └── helper.js
├── app-test.js //Demo程序启动文件
├── package.json
└── readme.md
使用命令node app-test.js
即可进行一个完整workflow的测试,包括最开始我们提到的所有功能。 同时可以使用node app-test.js -m ca|createChannel|joinChannel|install|instantiate|invoke|query|queryChaincodeInfo|queryChannelInfo
来运行单个功能。
程序使用的均为默认参数,其定义在app-test.js
文件中。可以按照需求修改对应的参数,再运行程序即可。
持续更新
如果在使用途中发现任何问题,或者有任何需求可以在该项目的issue中提出改进方案或者建议。 Github地址:Hyperledger-fabric-node-sdk-demo
Fabric v0.6
Fabric 目前的稳定版本为 v0.6,最新的版本 1.0 还在演进中,即将发布。
v0.6 的架构相对简单,适合作为实验或 PoC 场景使用。
Fabric v0.6 安装部署
如果是初次接触 Hyperledger Fabric 项目,推荐采用如下的步骤,基于 Docker-Compose 的一键部署。
官方文档现在也完善了安装部署的步骤,具体可以参考代码 doc
目录下内容。
动手前,建议适当了解一些 Docker 相关知识。
安装 Docker
Docker 支持 Linux 常见的发行版,如 Redhat/Centos/Ubuntu 等。
$ curl -fsSL https://get.docker.com/ | sh
以 Ubuntu 14.04 为例,安装成功后,修改 Docker 服务配置(/etc/default/docker
文件)。
DOCKER_OPTS="$DOCKER_OPTS -H tcp://0.0.0.0:2375 -H unix:///var/run/docker.sock --api-cors-header='*'"
重启 Docker 服务。
$ sudo service docker restart
Ubuntu 16.04 中默认采用了 systemd 管理启动服务,Docker 配置文件在 /etc/systemd/system/docker.service.d/override.conf
。
修改后,需要通过如下命令重启 Docker 服务。
$ sudo systemctl daemon-reload
$ sudo systemctl restart docker.service
安装 docker-compose
首先,安装 python-pip 软件包。
$ sudo aptitude install python-pip
安装 docker-compose(推荐为 1.7.0 及以上版本)。
$ sudo pip install docker-compose>=1.7.0
下载镜像
目前 1.0 代码还没有正式发布,推荐使用 v0.6 分支代码进行测试。
下载相关镜像,并进行配置。
$ docker pull yeasy/hyperledger-fabric:0.6-dp
&& docker pull yeasy/hyperledger-fabric-peer:0.6-dp
&& docker pull yeasy/hyperledger-fabric-base:0.6-dp
&& docker pull yeasy/blockchain-explorer:latest
&& docker tag yeasy/hyperledger-fabric-peer:0.6-dp hyperledger/fabric-peer
&& docker tag yeasy/hyperledger-fabric-base:0.6-dp hyperledger/fabric-baseimage
&& docker tag yeasy/hyperledger-fabric:0.6-dp hyperledger/fabric-membersrvc
也可以使用 官方仓库 中的镜像。
$ docker pull hyperledger/fabric-peer:x86_64-0.6.1-preview
&& docker pull hyperledger/fabric-membersrvc:x86_64-0.6.1-preview
&& docker pull yeasy/blockchain-explorer:latest
&& docker tag hyperledger/fabric-peer:x86_64-0.6.1-preview hyperledger/fabric-peer
&& docker tag hyperledger/fabric-peer:x86_64-0.6.1-preview hyperledger/fabric-baseimage
&& docker tag hyperledger/fabric-membersrvc:x86_64-0.6.1-preview hyperledger/fabric-membersrvc
之后,用户可以选择采用不同的一致性机制,包括 noops、pbft 两类。
使用 noops 模式
noops 默认没有采用 consensus 机制,1 个节点即可,可以用来进行快速测试。
$ docker run --name=vp0
--restart=unless-stopped
-it
-p 7050:7050
-p 7051:7051
-v /var/run/docker.sock:/var/run/docker.sock
-e CORE_PEER_ID=vp0
-e CORE_PEER_ADDRESSAUTODETECT=true
-e CORE_NOOPS_BLOCK_WAIT=10
hyperledger/fabric-peer:latest peer node start
使用 PBFT 模式
PBFT 是经典的分布式一致性算法,也是 hyperledger 目前最推荐的算法,该算法至少需要 4 个节点。
首先,下载 Compose 模板文件。
$ git clone https://github.com/yeasy/docker-compose-files
进入 hyperledger/0.6/pbft
目录,查看包括若干模板文件,功能如下。
4-peers.yml
: 启动 4 个 PBFT peer 节点。4-peers-with-membersrvc.yml
: 启动 4 个 PBFT peer 节点 + 1 个 CA 节点,并启用 CA 功能。4-peers-with-explorer.yml
: 启动 4 个 PBFT peer 节点 + 1 个 Blockchain-explorer,可以通过 Web 界面监控集群状态。4-peers-with-membersrvc-explorer.yml
: 启动 4 个 PBFT peer 节点 + 1 个 CA 节点 + 1 个 Blockchain-explorer,并启用 CA 功能。
例如,快速启动一个 4 个 PBFT 节点的集群。
$ docker-compose -f 4-peers.yml up
多物理节点部署
上述方案的典型场景是单物理节点上部署多个 Peer 节点。如果要扩展到多物理节点,需要容器云平台的支持,如 Swarm 等。
当然,用户也可以分别在各个物理节点上通过手动启动容器的方案来实现跨主机组网,每个物理节点作为一个 peer 节点。
首先,以 4 节点下的 PBFT 模式为例,配置 4 台互相连通的物理机,分别按照上述步骤配置 Docker,下载镜像。
4 台物理机分别命名为 vp0 ~ vp3。
vp0
vp0 作为初始的探测节点。
$ docker run --name=vp0
--net="host"
--restart=unless-stopped
-it --rm
-v /var/run/docker.sock:/var/run/docker.sock
-e CORE_PEER_ID=vp0
-e CORE_PBFT_GENERAL_N=4
-e CORE_LOGGING_LEVEL=debug
-e CORE_PEER_ADDRESSAUTODETECT=true
-e CORE_PEER_NETWORKID=dev
-e CORE_PEER_VALIDATOR_CONSENSUS_PLUGIN=pbft
-e CORE_PBFT_GENERAL_MODE=batch
-e CORE_PBFT_GENERAL_TIMEOUT_REQUEST=10s
hyperledger/fabric-peer:latest peer node start
vp1 ~ vp3
以 vp1 为例,假如 vp0 的地址为 10.0.0.1。
$ NAME=vp1
$ ROOT_NODE=10.0.0.1
$ docker run --name=${NAME}
--net="host"
--restart=unless-stopped
-it --rm
-v /var/run/docker.sock:/var/run/docker.sock
-e CORE_PEER_ID=${NAME}
-e CORE_PBFT_GENERAL_N=4
-e CORE_LOGGING_LEVEL=debug
-e CORE_PEER_ADDRESSAUTODETECT=true
-e CORE_PEER_NETWORKID=dev
-e CORE_PEER_VALIDATOR_CONSENSUS_PLUGIN=pbft
-e CORE_PBFT_GENERAL_MODE=batch
-e CORE_PBFT_GENERAL_TIMEOUT_REQUEST=10s
-e CORE_PEER_DISCOVERY_ROOTNODE=${ROOT_NODE}:7051
hyperledger/fabric-peer:latest peer node start
服务端口
Hyperledger 默认监听的服务端口包括:
- 7050: REST 服务端口,推荐 NVP 节点开放,0.6 之前版本中为 5000;
- 7051:peer gRPC 服务监听端口,0.6 之前版本中为 30303;
- 7052:peer CLI 端口,0.6 之前版本中为 30304;
- 7053:peer 事件服务端口,0.6 之前版本中为 31315;
- 7054:eCAP
- 7055:eCAA
- 7056:tCAP
- 7057:tCAA
- 7058:tlsCAP
- 7059:tlsCAA
使用 chaincode
下面演示 example02 chaincode,完成两方(如 a 和 b)之间进行价值的转移。
部署 chaincode
集群启动后,进入一个 VP 节点。以 pbft 模式为例,节点名称为 pbft_vp0_1
。
$ docker exec -it pbft_vp0_1 bash
部署 chaincode example02。
$ peer chaincode deploy -p github.com/hyperledger/fabric/examples/chaincode/go/chaincode_example02 -c '{"Function":"init", "Args": ["a","100", "b", "200"]}'
03:08:44.740 [chaincodeCmd] chaincodeDeploy -> INFO 001 Deploy result: type:GOLANG chaincodeID:<path:"github.com/hyperledger/fabric/examples/chaincode/go/chaincode_example02" name:"ee5b24a1f17c356dd5f6e37307922e39ddba12e5d2e203ed93401d7d05eb0dd194fb9070549c5dc31eb63f4e654dbd5a1d86cbb30c48e3ab1812590cd0f78539" > ctorMsg:<args:"init" args:"a" args:"100" args:"b" args:"200" >
Deploy chaincode: ee5b24a1f17c356dd5f6e37307922e39ddba12e5d2e203ed93401d7d05eb0dd194fb9070549c5dc31eb63f4e654dbd5a1d86cbb30c48e3ab1812590cd0f78539
03:08:44.740 [main] main -> INFO 002 Exiting.....
返回 chaincode id 为 ee5b24a1f17c356dd5f6e37307922e39ddba12e5d2e203ed93401d7d05eb0dd194fb9070549c5dc31eb63f4e654dbd5a1d86cbb30c48e3ab1812590cd0f78539
,后面将用这个 id 来标识这次交易。为了方便,把它记录到环境变量 CC_ID 中。
$ CC_ID="ee5b24a1f17c356dd5f6e37307922e39ddba12e5d2e203ed93401d7d05eb0dd194fb9070549c5dc31eb63f4e654dbd5a1d86cbb30c48e3ab1812590cd0f78539"
部署成功后,系统中会自动生成几个 chaincode 容器,例如
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
e86c26bad76f dev-vp1-ee5b24a1f17c356dd5f6e37307922e39ddba12e5d2e203ed93401d7d05eb0dd194fb9070549c5dc31eb63f4e654dbd5a1d86cbb30c48e3ab1812590cd0f78539 "/opt/gopath/bin/ee5b" 2 minutes ago Up 2 minutes dev-vp1-ee5b24a1f17c356dd5f6e37307922e39ddba12e5d2e203ed93401d7d05eb0dd194fb9070549c5dc31eb63f4e654dbd5a1d86cbb30c48e3ab1812590cd0f78539
597ebaf929a0 dev-vp2-ee5b24a1f17c356dd5f6e37307922e39ddba12e5d2e203ed93401d7d05eb0dd194fb9070549c5dc31eb63f4e654dbd5a1d86cbb30c48e3ab1812590cd0f78539 "/opt/gopath/bin/ee5b" 2 minutes ago Up 2 minutes dev-vp2-ee5b24a1f17c356dd5f6e37307922e39ddba12e5d2e203ed93401d7d05eb0dd194fb9070549c5dc31eb63f4e654dbd5a1d86cbb30c48e3ab1812590cd0f78539
8748a3b47312 dev-vp3-ee5b24a1f17c356dd5f6e37307922e39ddba12e5d2e203ed93401d7d05eb0dd194fb9070549c5dc31eb63f4e654dbd5a1d86cbb30c48e3ab1812590cd0f78539 "/opt/gopath/bin/ee5b" 2 minutes ago Up 2 minutes dev-vp3-ee5b24a1f17c356dd5f6e37307922e39ddba12e5d2e203ed93401d7d05eb0dd194fb9070549c5dc31eb63f4e654dbd5a1d86cbb30c48e3ab1812590cd0f78539
cf6e762f6a2e dev-vp0-ee5b24a1f17c356dd5f6e37307922e39ddba12e5d2e203ed93401d7d05eb0dd194fb9070549c5dc31eb63f4e654dbd5a1d86cbb30c48e3ab1812590cd0f78539 "/opt/gopath/bin/ee5b" 2 minutes ago Up 2 minutes dev-vp0-ee5b24a1f17c356dd5f6e37307922e39ddba12e5d2e203ed93401d7d05eb0dd194fb9070549c5dc31eb63f4e654dbd5a1d86cbb30c48e3ab1812590cd0f78539
查询 chaincode
查询 a 手头的价值,为初始值 100。
$ peer chaincode query -n ${CC_ID} -c '{"Function": "query", "Args": ["a"]}'
03:22:31.420 [chaincodeCmd] chaincodeInvokeOrQuery -> INFO 001 Successfully queried transaction: chaincodeSpec:<type:GOLANG chaincodeID:<name:"ee5b24a1f17c356dd5f6e37307922e39ddba12e5d2e203ed93401d7d05eb0dd194fb9070549c5dc31eb63f4e654dbd5a1d86cbb30c48e3ab1812590cd0f78539" > ctorMsg:<args:"query" args:"a" > >
Query Result: 100
03:22:31.420 [main] main -> INFO 002 Exiting.....
调用 chaincode
a 向 b 转账 10 元。
$ peer chaincode invoke -n ${CC_ID} -c '{"Function": "invoke", "Args": ["a", "b", "10"]}'
03:22:57.345 [chaincodeCmd] chaincodeInvokeOrQuery -> INFO 001 Successfully invoked transaction: chaincodeSpec:<type:GOLANG chaincodeID:<name:"ee5b24a1f17c356dd5f6e37307922e39ddba12e5d2e203ed93401d7d05eb0dd194fb9070549c5dc31eb63f4e654dbd5a1d86cbb30c48e3ab1812590cd0f78539" > ctorMsg:<args:"invoke" args:"a" args:"b" args:"10" > > (fc298ffb-c763-4ed0-9da2-072de2ab20b1)
03:22:57.345 [main] main -> INFO 002 Exiting.....
查询 a 手头的价值,为新的值 90。
```sh $ peer chaincode query -n ${CC_ID} -c '{"Function": "query", "Args": ["a"]}' 03:23:33.045 [chaincodeCmd] chaincodeInvokeOrQuery -> INFO 001 Successfully queried transaction: chaincodeSpec:ctorMsg: > Query Result: 90 03:23:33.045 [main] main -> INFO 002 Exiting..... ···
权限管理
权限管理机制是 hyperledger fabric 项目的一大特色。下面给出使用权限管理的一个应用案例。
启动集群
首先下载相关镜像。
$ docker pull yeasy/hyperledger:latest
$ docker tag yeasy/hyperledger:latest hyperledger/fabric-baseimage:latest
$ docker pull yeasy/hyperledger-peer:latest
$ docker pull yeasy/hyperledger-membersrvc:latest
进入 hyperledger 项目,启动带成员管理的 PBFT 集群。
$ git clone https://github.com/yeasy/docker-compose-files
$ cd docker-compose-files/hyperledger/0.6/pbft
$ docker-compose -f 4-peers-with-membersrvc.yml up
用户登陆
当启用了权限管理后,首先需要登录,例如以内置账户 jim 账户登录。
登录 vp0,并执行登录命令。
$ docker exec -it pbft_vp0_1 bash
# peer network login jim
06:57:13.603 [networkCmd] networkLogin -> INFO 001 CLI client login...
06:57:13.603 [networkCmd] networkLogin -> INFO 002 Local data store for client loginToken: /var/hyperledger/production/client/
Enter password for user 'jim': 6avZQLwcUe9b
06:57:25.022 [networkCmd] networkLogin -> INFO 003 Logging in user 'jim' on CLI interface...
06:57:25.576 [networkCmd] networkLogin -> INFO 004 Storing login token for user 'jim'.
06:57:25.576 [networkCmd] networkLogin -> INFO 005 Login successful for user 'jim'.
06:57:25.576 [main] main -> INFO 006 Exiting.....
也可以用 REST 方式:
POST HOST:7050/registrar
Request:
{
"enrollId": "jim",
"enrollSecret": "6avZQLwcUe9b"
}
Response:
{
"OK": "User jim is already logged in."
}
chaincode 部署
登录之后,chaincode 的部署、调用等操作与之前类似,只是需要通过 -u 选项来指定用户名。
在 vp0 上执行命令:
# peer chaincode deploy -u jim -p github.com/hyperledger/fabric/examples/chaincode/go/chaincode_example02 -c '{"Function":"init", "Args": ["a","100", "b", "200"]}'
06:58:20.099 [chaincodeCmd] getChaincodeSpecification -> INFO 001 Local user 'jim' is already logged in. Retrieving login token.
06:58:22.178 [chaincodeCmd] chaincodeDeploy -> INFO 002 Deploy result: type:GOLANG chaincodeID:<path:"github.com/hyperledger/fabric/examples/chaincode/go/chaincode_example02" name:"ee5b24a1f17c356dd5f6e37307922e39ddba12e5d2e203ed93401d7d05eb0dd194fb9070549c5dc31eb63f4e654dbd5a1d86cbb30c48e3ab1812590cd0f78539" > ctorMsg:<args:"init" args:"a" args:"100" args:"b" args:"200" >
Deploy chaincode: ee5b24a1f17c356dd5f6e37307922e39ddba12e5d2e203ed93401d7d05eb0dd194fb9070549c5dc31eb63f4e654dbd5a1d86cbb30c48e3ab1812590cd0f78539
06:58:22.178 [main] main -> INFO 003 Exiting.....
记录下返回的 chaincode ID。
# CC_ID=ee5b24a1f17c356dd5f6e37307922e39ddba12e5d2e203ed93401d7d05eb0dd194fb9070549c5dc31eb63f4e654dbd5a1d86cbb30c48e3ab1812590cd0f78539
此时,查询账户值应当为初始值。
# peer chaincode query -u jim -n ${CC_ID} -c '{"Function": "query", "Args": ["a"]}'
07:28:39.925 [chaincodeCmd] getChaincodeSpecification -> INFO 001 Local user 'jim' is already logged in. Retrieving login token.
07:28:40.281 [chaincodeCmd] chaincodeInvokeOrQuery -> INFO 002 Successfully queried transaction: chaincodeSpec:<type:GOLANG chaincodeID:<name:"ee5b24a1f17c356dd5f6e37307922e39ddba12e5d2e203ed93401d7d05eb0dd194fb9070549c5dc31eb63f4e654dbd5a1d86cbb30c48e3ab1812590cd0f78539" > ctorMsg:<args:"query" args:"a" > secureContext:"jim" >
Query Result: 100
07:28:40.281 [main] main -> INFO 003 Exiting.....
也可以通过 REST 方式进行:
POST HOST:7050/chaincode
Request:
{
"jsonrpc": "2.0",
"method": "deploy",
"params": {
"type": 1,
"chaincodeID":{
"path":"github.com/hyperledger/fabric/examples/chaincode/go/chaincode_example02"
},
"ctorMsg": {
"function":"init",
"args":["a", "1000", "b", "2000"]
},
"secureContext": "jim"
},
"id": 1
}
Response:
{
"jsonrpc": "2.0",
"result": {
"status": "OK",
"message": "ee5b24a1f17c356dd5f6e37307922e39ddba12e5d2e203ed93401d7d05eb0dd194fb9070549c5dc31eb63f4e654dbd5a1d86cbb30c48e3ab1812590cd0f78539"
},
"id": 1
}
chaincode 调用
在账户 a、b 之间进行转账 10 元的操作。
# peer chaincode invoke -u jim -n ${CC_ID} -c '{"Function": "invoke", "Args": ["a", "b", "10"]}'
07:29:25.245 [chaincodeCmd] getChaincodeSpecification -> INFO 001 Local user 'jim' is already logged in. Retrieving login token.
07:29:25.585 [chaincodeCmd] chaincodeInvokeOrQuery -> INFO 002 Successfully invoked transaction: chaincodeSpec:<type:GOLANG chaincodeID:<name:"ee5b24a1f17c356dd5f6e37307922e39ddba12e5d2e203ed93401d7d05eb0dd194fb9070549c5dc31eb63f4e654dbd5a1d86cbb30c48e3ab1812590cd0f78539" > ctorMsg:<args:"invoke" args:"a" args:"b" args:"10" > secureContext:"jim" > (f8347e3b-7230-4561-9017-3946756a0bf4)
07:29:25.585 [main] main -> INFO 003 Exiting.....
也可以通过 REST 方式进行:
POST HOST:7050/chaincode
Request:
{
"jsonrpc": "2.0",
"method": "invoke",
"params": {
"type": 1,
"chaincodeID":{
"name":"980d4bb7f69578592e5775a6da86d81a221887817d7164d3e9d4d4df1c981440abf9a61417eaf8ad6f7fc79893da36de2cf4709131e9af39bca6ebc2e5a1cd9d"
},
"ctorMsg": {
"function":"invoke",
"args":["a", "b", "100"]
},
"secureContext": "jim"
},
"id": 3
}
Response:
{
"jsonrpc": "2.0",
"result": {
"status": "OK",
"message": "66308740-a2c5-4a60-81f1-778dbed49cc3"
},
"id": 3
}
chaincode 查询
查询 a 账户的余额。
# peer chaincode query -u jim -n ${CC_ID} -c '{"Function": "query", "Args": ["a"]}'
07:29:55.844 [chaincodeCmd] getChaincodeSpecification -> INFO 001 Local user 'jim' is already logged in. Retrieving login token.
07:29:56.198 [chaincodeCmd] chaincodeInvokeOrQuery -> INFO 002 Successfully queried transaction: chaincodeSpec:<type:GOLANG chaincodeID:<name:"ee5b24a1f17c356dd5f6e37307922e39ddba12e5d2e203ed93401d7d05eb0dd194fb9070549c5dc31eb63f4e654dbd5a1d86cbb30c48e3ab1812590cd0f78539" > ctorMsg:<args:"query" args:"a" > secureContext:"jim" >
Query Result: 90
07:29:56.198 [main] main -> INFO 003 Exiting.....
也可以通过 REST 方式进行:
POST HOST:7050/chaincode
Request:
{
"jsonrpc": "2.0",
"method": "query",
"params": {
"type": 1,
"chaincodeID":{
"name":"980d4bb7f69578592e5775a6da86d81a221887817d7164d3e9d4d4df1c981440abf9a61417eaf8ad6f7fc79893da36de2cf4709131e9af39bca6ebc2e5a1cd9d"
},
"ctorMsg": {
"function":"query",
"args":["a"]
},
"secureContext": "jim"
},
"id": 5
}
Response:
{
"jsonrpc": "2.0",
"result": {
"status": "OK",
"message": "900"
},
"id": 5
}
区块信息查询
URL:
GET HOST:7050/chain/blocks/2
Response:
{
"transactions": [
{
"type": 2,
"chaincodeID": "EoABMjhiYjJiMjMxNjE3MWE3MDZiYjI4MTBlYzM1ZDA5NWY0MzA4NzdiZjQ0M2YxMDYxZWYwZjYwYmJlNzUzZWQ0NDA3MDBhNTMxMmMxNjM5MGQzYjMwMTk5ZmU5NDY1YzNiNzVkNTk0NDM1OGNhYWUwMWNhODFlZjI4MTI4YTFiZmI=",
"payload": "Cp0BCAESgwESgAEyOGJiMmIyMzE2MTcxYTcwNmJiMjgxMGVjMzVkMDk1ZjQzMDg3N2JmNDQzZjEwNjFlZjBmNjBiYmU3NTNlZDQ0MDcwMGE1MzEyYzE2MzkwZDNiMzAxOTlmZTk0NjVjM2I3NWQ1OTQ0MzU4Y2FhZTAxY2E4MWVmMjgxMjhhMWJmYhoTCgZpbnZva2USAWESAWISAzEwMA==",
"uuid": "2b3b6cf3-9887-4dd5-8f2e-3634ec9c719a",
"timestamp": {
"seconds": 1466577447,
"nanos": 399637431
},
"nonce": "5AeA6S1odhPIDiGjFTFG8ttcihOoNNsh",
"cert": "MIICPzCCAeSgAwIBAgIRAMndnS+Me0G6gs4J9/fb8HcwCgYIKoZIzj0EAwMwMTELMAkGA1UEBhMCVVMxFDASBgNVBAoTC0h5cGVybGVkZ2VyMQwwCgYDVQQDEwN0Y2EwHhcNMTYwNjIyMDYzMzE4WhcNMTYwOTIwMDYzMzE4WjAxMQswCQYDVQQGEwJVUzEUMBIGA1UEChMLSHlwZXJsZWRnZXIxDDAKBgNVBAMTA2ppbTBZMBMGByqGSM49AgEGCCqGSM49AwEHA0IABDLd2W8PxzgB4A85Re2x44BApbOGqP05tnkygbXSctLiqi5HVfwRAACS6znVA9+toni59Yy+XAH3w2offdjFW3mjgdwwgdkwDgYDVR0PAQH/BAQDAgeAMAwGA1UdEwEB/wQCMAAwDQYDVR0OBAYEBAECAwQwDwYDVR0jBAgwBoAEAQIDBDBNBgYqAwQFBgcBAf8EQAfASTE6bZ0P5mrEzTa5r1UyKFv+dKezBiGU0V3l2iWzk9evlGMvaC2pwhEKfKDdKxs7YSMYe/7cLq/oF++GBVowSgYGKgMEBQYIBEBEO3TKXuORl5Geuco8Gnn5TkoIl4+b96aPGDGvKbmDjMXR9vEBuUXTnsbDL53j7kC8/XQs1kZboC1ojLeUSN03MAoGCCqGSM49BAMDA0kAMEYCIQCZqyANMFcu1WiMe2So0pC7eRU95F0+qUXLAKZsPWv/YQIhALmNaglP7CoMOe2qxehucmffDlu0BRLSYDHyV9xcxmkH",
"signature": "MEYCIQDob3NqdrfwlSGhi+zz+Ypl7S9QQ07RIFr8nV92e8KDNgIhANIljz4tRS8vwQk01hTemNQFJX2zMI6DhSUFZivbbtoR"
}
],
"stateHash": "7YUoVvYnMLHbLf47uTixLtkjF6xM9DuvgSWC92MbOUzk09xhcRBBLZqe5FvJElgZemELBOcuIFnubL0LiGH0yw==",
"previousBlockHash": "On4BlpqCYNpugUKluqvOcbvkr3TAQxmlISLdd6qrONtIgmQ4iUDeWxAA9lUCceZfF8tke8A0Wy7m9tksNpKodw==",
"consensusMetadata": "CAI=",
"nonHashData": {
"localLedgerCommitTimestamp": {
"seconds": 1466577447,
"nanos": 653618964
},
"transactionResults": [
{
"uuid": "2b3b6cf3-9887-4dd5-8f2e-3634ec9c719a"
}
]
}
}
Python 客户端
前面应用案例,都是直接通过 HTTP API 来跟 hyperledger 进行交互,操作比较麻烦。
还可以直接通过 hyperledger-py 客户端来进行更方便的操作。
安装
$ pip install hyperledger --upgrade
或直接源码安装
$ git clone https://github.com/yeasy/hyperledger-py.git
$ cd hyperledger-py
$ pip install -r requirements.txt
$ python setup.py install
使用
>>> from hyperledger.client import Client
>>> c = Client(base_url="http://127.0.0.1:7050")
>>> c.peer_list()
{u'peers': [{u'type': 1, u'ID': {u'name': u'vp1'}, u'address': u'172.17.0.2:30303'}, {u'type': 1, u'ID': {u'name': u'vp2'}, u'address': u'172.17.0.3:30303'}]}
更多使用方法,可以参考 API 文档。
其它客户端
目前,HyperLedger Fabric 已经成立了 SDK 工作组。
目前在实现的客户端 SDK 包括: