hyperledger composer 实战
背景介绍
hyperledger composer是 hyperledger 组织下的新星项目,封装了Node SDK与区块链交互的复杂细节,对使用者提供了一套简洁直观的语法来定义业务模型,可以让区块链开发人员快速上手,缩短开发时间,是一套非常好的工具。
业务模型概念讲解
定义业务模型的过程在composer中称之为定义’Business Network’, 业务模型有以下几个关键要素:
- Asset, 资产,可用于交易的价值物,比如房产买卖中的房子
- Participant, 参与者,参与交易的人,比如房产买卖中房主、购房者、中介
- Transaction, 交易,由某一参与者发起,对资产状态带来改变的操作,如房主挂牌销售、购房者出价,成交等
- ACL, 权限控制, 限制参与者能够发起的交易(操作)
同样,在上图可以看到,在composer定义一个业务模型需要下面 3 类文件:
- Model files, 模型文件,其中包含资产、参与者的定义,以及交易需要的参数
- Javascript Files, 定义交易的具体实现逻辑
- Access Control File, 定义 ACL 规则
最终,将业务模型的所有文件打包成以.bna 结尾’Business Network’文件
安装
1
npm install -g composer-cli generator-hyperledger-composer composer-rest-server yo
- composer-cli 包含了开发’Business Network’的命令行工具,如打包,部署等
- generator-hyperledger-composer Yo 脚手架插件,专用于快速生成’Business Newtork’
- yo 脚手架开发框架
- composer-rest-server 基于loopback的 API 生成工具,可以快速将’Business Network’转换成可以访问的 API,大大减少了开发时间
Composer 实战
清理 Docker 容器,获得干净的测试环境
1
2
3docker kill $(docker ps -q)
docker rm $(docker ps -aq)
docker rmi $(docker images dev-* -q)启动 Fabric 网络
1
2
3
4
5
6
7mkdir ~/work/fabric-tools && cd ~/work/fabric-tools
curl -O https://raw.githubusercontent.com/hyperledger/composer-tools/master/packages/fabric-dev-servers/fabric-dev-servers.tar.gz
tar xvzf fabric-dev-servers.tar.gz
./downloadFabric.sh //下载fabric相关docker镜像
./startFabric.sh //使用Docker-compose启动Fabric网络
./createComposerProfile.sh //创建连接文件在 createComposerProfile.sh 脚本中, 将会生成~/.composer-connection-profiles/hlfv1/connection.json 连接文件,这个文件明确了 composer 如何连接 Fabric 区块链网络,如果你对 Fabric 网络比较熟悉的话,也可以不用执行前 2 个脚本,直接生成连接文件,然后按实际情况修正即可。注意:composer 推荐使用 Fabric1.0 网络。
停止 Fabric 网络
1
2
3cd ~/work/fabric-tools
./stopFabric.sh
./teardownFabric.sh克隆 composer 例子代码
1
2
3cd ~/work
git clone https://github.com/hyperledger/composer-sample-networks.git
cp -r ./composer-sample-networks/packages/basic-sample-network/ ./my-network使用编辑器(官方推荐VSCode)打开 my-network 目录, 从目录结构中可以看到几个重要的目录和文件
- permissions.acl ACL 定义文件
- models 目录,用于存储 Model Files(.cto),每个.cto 使用独立的命名空间
- lib 目录,用于存储 Javascript Files
修改 my-network 项目
修改 package.json 文件
- 修改 name 为’my-network’
- 修改 description 为’My Commodity Trading network’
- 修改 prepublish 脚本中修改生成的 Business network 打包名为’my-network.bna’
使用如下内容替换 models/sample.cto
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20/**
* My commodity trading network
*/
namespace org.acme.mynetwork
asset Commodity identified by tradingSymbol {
o String tradingSymbol
o String description
o String mainExchange
o Double quantity
--> Trader owner
}
participant Trader identified by tradeId {
o String tradeId
o String firstName
o String lastName
}
transaction Trade {
--> Commodity commodity
--> Trader newOwner
}在 sample.cto 文件中,定义了 Asset(货物)、Participant(商人)和 Transaction(贸易),在贸易当中,货物会被易主
使用如下内容替换 lib/sample.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27/*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/**
* Track the trade of a commodity from one trader to another
* @param {org.acme.mynetwork.Trade} trade - the trade to be processed
* @transaction
*/
function tradeCommodity(trade) {
trade.commodity.owner = trade.newOwner;
return getAssetRegistry("org.acme.mynetwork.Commodity").then(function (
assetRegistry
) {
return assetRegistry.update(trade.commodity);
});
}如果一个 js 文件中的一个函数被@trasnaction 注释,则注释中@param 指定的交易类型(本例中为‘org.acme.mynetwork.Trade’)被提交时,该函数会被自动执行。sample.js 文件完成了’货物易主’的逻辑:在一个 Trade(贸易)操作中,货物的属主被更新为 trade.newOwner,且被永久地更新到区块链上。
修改权限控制文件 permissions.acl 为如下内容
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18/**
* Access control rules for mynetwork
*/
rule Default {
description: "Allow all participants access to all resources"
participant: "ANY"
operation: ALL
resource: "org.acme.mynetwork.*"
action: ALLOW
}
rule SystemACL {
description: "System ACL to permit all access"
participant: "org.hyperledger.composer.system.Participant"
operation: ALL
resource: "org.hyperledger.composer.system.**"
action: ALLOW
}
生成 Business Network Archive
1
2cd ~/work/my-network
npm install你将看到如下输出:
1
2
3$ mkdirp ./dist && composer archive create --sourceType dir --sourceName . -a ./dist/my-network.bna
Creating Business Network Archive
Looking for package.json of Business Network Definition
Input directory: /Users/jiaxi/work/fabric-composer/my-network
Found:
Description: My Commodity Trading network
Name: my-network
Identifier: my-network@0.1.8
Written Business Network Definition Archive file to
Output file: ./dist/my-network.bna
Command succeeded
Done in 158.57s.
1 |
|
同样要回答一系列问题
1 | Welcome to the Hyperledger Composer project generator |
进入项目目录,运行应用程序
1 | cd my-app //根据骨架自动生成 |
根据 README.md 和 pacakge.json 文件可以看出,该项目使用angular-cli和 composer-rest-server,其中 composer-rest-server 提供访问 Business Network 的 API,angular-cli 提供 WEB 访问界面。以下内容出自 package.json 文件
1 | "name": "my-app", |
如果启动过程中没有出现错误信息,则访问http://0.0.0.0:4200/即可进入WEB应用界面。
FAQ
- 建议使用 npm 来安装相关的模块。笔者一开始是使用 yarn 来全局安装模块,结果后面某些步骤就无法进行下去了,这里还没有弄明白原因,但考虑为了节约读者的时间,还是先用 npm 吧。
- docker 镜像最好使用 1.0.0 版。笔者在尝试部署 Business Network 的时候总是失败,最后试下来发现用的 docker 镜像是 1.0.1 版(最新版),无奈之下,只好使用fabric-samples中的 fabcar 来启动 fabric 区块链网络。
- 读者已经发现笔者总是使用 PeerAdmin 这个用户名来访问区块链,这是怎么做到的呢,请读者参考Composer Identity Import
总结
本是只是笔者个人对于 hyperledger composer 工具集一些个人理解,并整合官方的hyperledger composer 开发者指南,这里笔者仅描述了使用 hyperledger composer 的开发基于 Fabric 区块链应用的一个大概流程,还有很多具体的细节没有涉及,希望读者能通过阅读官方文档的方式来进一步学习。
参考资料
hyperledger composer
Node 模块包依赖管理工具——Yarn
loopback: rest API server
yeoman
angular-cli
hyperledger composer 开发者指南