使用 Hyperledger Composer 实施业务网络
Hyperledger Composer 是一个高级工具集和框架,用于在 Hyperledger Fabric 区块链上快速构建和运行应用程序。
我们在上一章中学习了 Hyperledger Fabric,因此您已经知道开发基于 Fabric 的应用程序是非常复杂的,因为它需要在网络级别处理许多配置。
在本章中,我们将讨论以下主题:
- Hyperledger Composer 快速概览
- 设置 Hyperledger Composer 环境
- 分析业务场景
- 商业网络档案
- 实现业务交易功能
hyperledger Composer–快速概述
Hyperledger Composer 是一套基于 JavaScript 的高级工具集和框架,可简化并快速构建和运行基于 Hyperledger 结构区块链的应用程序。企业所有者和开发人员可以通过 composer 工具快速创建智能合同和应用程序。composer 工具生成一个 RESTful 端点来与 fabric 通道交互。Composer 没有使用 Golang 编写链码,而是使用模型语言为区块链网络生成一个业务网络档案(.BNA
)文件。
以下是 Hyperledger Composer 解决方案架构的示例:
Hyperledger Composer 包含以下部分列出的组件。
约曼发电机
Yeoman 中的 npm 模块生成器-hyperledger-composer 用于为 Hyperledger Composer 制作模板。它支持并生成三种不同类型的模板:
- CLI 应用程序
- 角度 2 应用
- 骨干商业网络
您可以使用 Yeoman 生成的角度骨架连接到 Hyperledger Composer REST 服务器。
作曲家休息服务器
Composer 的 REST 服务器利用一个独立的 Node.js 进程,并从已部署的 composer 业务网络公开一组 RESTful API 端点。这些生成的 API 可以与结构链代码交互。然后,端代码可以为资产、参与者和事务触发创建、读取、更新、删除 ( CRUD )。
环回连接器
LoopBack 连接器利用 Node.js LoopBack 框架来公开业务网络中定义的资产、参与者和事务的 GET/POST/PUT/DELETE 操作。
就可以了
JavaScript SDK API 用于与部署的业务网络进行交互。它由客户端和管理 API 组成。
客户端 API 提供查询、创建、更新和删除资源(资产和参与者),并从客户端应用程序提交事务。
管理 API 用于部署业务网络。
作曲家游乐场
Hyperledger Composer playground 是一个基于浏览器的界面,用于创建和测试业务网络。你可以利用操场来建立和测试你的商业网络。
Composer-cli
Composer-cli 是一个命令行工具,允许您部署和管理业务网络。
以下是一些命令的列表:
| 命令 | 描述 |
| composer archive create
| 创建业务网络档案文件的命令(nba
)。 |
| composer archive list
| 验证企业网络档案的内容。 |
| composer card create
| 从单个组件创建业务网卡。 |
| composer card delete
| 从单个组件中删除业务网卡。 |
| composer card list
| 列出存储在本地钱包中的所有业务网卡。 |
| composer network deploy
| 将业务网络存档从本地磁盘部署到 Hyperledger 结构网络。 |
| composer network list
| 列出业务网卡的详细信息。 |
| composer network ping
| 测试与已部署的业务网络的连接。 |
设置 Hyperledger Composer 环境
我们刚刚回顾了 Hyperledger Composer 解决方案架构。在本节中,我们将设置 Hyperledger 开发环境。
安装先决条件
在我们安装 composer 工具之前,请按照 Hyperledger Fabric environment 的设置-安装必备组件部分,确保您具备所需的必备组件。
安装开发环境
以下是用于开发环境的安装命令:
- 安装 CLI 工具:
npm install -g composer-cli@0.20
- 安装
composer-rest-server
:
npm install -g composer-rest-server@0.20
- 正在安装 Hyperledger Composer 生成器:
npm install -g generator-hyperledger-composer@0.20
- 安装约曼:
npm install -g yo
- 安装游乐场:
npm install -g composer-playground
- 安装结构运行时:
按如下方式下载并安装 composer 的 fabric runtime:
mkdir ~/fabric-devserver && cd ~/fabric-devserver
curl -O https://raw.githubusercontent.com/hyperledger/composer- tools/master/packages/fabric-dev-servers/fabric-dev-servers.zip
unzip fabric-dev-servers.zip
export FABRIC_VERSION=hlfv12
./downloadFabric.sh
在这一步,您已经安装了典型 composer 开发环境所需的一切。
分析业务场景
在 第 16 章 、探索使用 Hyperledger Fabric 的企业区块链应用中,我们讨论了保险索赔的区块链用例。它包括以下步骤:
- 保险公司向经纪人报告索赔
-
代理提供所请求的信息
-
经纪人向发行人提交索赔
- 发行人确认索赔
- 发行人处理并批准索赔
在本章中,我们将使用相同的保险索赔用例,但也通过 Hyperledger Composer 构建端到端应用程序。
商业网络档案
Composer business 由四种不同类型的文件组成:模型文件(.cto
)、脚本文件(.js
)、访问控制列表(ACL)文件(.acl
)和查询文件(.qry
)。
网络模型文件(。首席技术官)
CTO 文件由以下元素组成:
| 元素 | 描述 |
| 单一名称空间 | 定义合成器模型命名空间;每个.cto
模型文件都需要一个名称空间。 |
| 资源-资产 | 任何可以在双方之间交换的有价值的东西。 |
| 资源-参与者 | 商业网络成员。 |
| 资源-枚举 | 由一组命名值组成的数据类型。 |
| 资源-概念 | 不是其他类型的任何要建模的对象。 |
| 资源-交易 | 定义区块链业务逻辑。 |
| 资源-事件 | 区块链交易通知。 |
| 导入 | 从其他命名空间导入资源。 |
与其他编程语言一样,composer 模型语言的数据类型包括 String、Double、Integer 等。
让我们看一些资产、参与者、交易和事件的例子。
IBM Bluemix 提供浏览器版本游乐场,无需安装;我们可以用这个工具做一个快速原型。下面是链接:https://composer-playground.mybluemix.net/。
连接到基本样本网络。Playground 将为您生成一些默认的样本资产、参与者、交易和事件,例如:
sample.cto
/**
* Sample business network definition.
*/
namespace org.example.basic
asset SampleAsset identified by assetId {
o String assetId
--> SampleParticipant owner
o String value
}
participant SampleParticipant identified by participantId {
o String participantId
o String firstName
o String lastName
}
transaction SampleTransaction {
--> SampleAsset asset
o String newValue
}
event SampleEvent {
--> SampleAsset asset
o String oldValue
o String newValue
}
在sample.cto.SampleAsset
中定义了一个namespace org.example.basic
,它是一个Asset
类的例子。它定义了一个资产,该资产的名称后面跟有一个标识field.o
String assetId
:即SampleAsset
的一个字段。--> SampleParticipant owner
:字段指向SampleParticipant
instance.SampleParticipant
是一个Participant
类的例子,语法类似于SampleAsset.SampleTransaction
是一个事务的例子class.SampleEvent
是一个事件类的例子。
脚本文件(。js)
我们在模型文件中定义事务和事件,模型文件是实现这些事务功能的脚本文件。注释中的装饰符用于用事务处理所需的元数据来注释函数,例如:
/**
* Sample transaction processor function.
* @param {org.example.basic.SampleTransaction} tx The sample transaction instance.
* @transaction
*/
async function sampleTransaction(tx) { // eslint-disable-line no-unused-vars
..
emit(event);
}
在sampleTransaction
函数中,@param
标记后面是触发事务处理器函数的事务的资源名。@transaction
将此函数标记为事务处理器函数。
访问控制列表(ACL)文件(acl)
ACL 文件定义了业务网络中参与者的权限,例如:
rule OwnerHasFullAccessToTheirAssets {
description: "Allow all participants full access to their assets"
participant(p): "org.example.basic.SampleParticipant"
operation: ALL
resource(r): "org.example.basic.SampleAsset"
condition: (r.owner.getIdentifier() === p.getIdentifier())
action: ALLOW
}
在前面的 ACL 示例中,它指定参与者是SampleParticipant
。任何注册为SampleParticipant
的实例都可以对org.example.SampleAsset
的所有实例执行ALL
操作。当SampleAsset
所有人与提交交易的参与者相同时,该交易被触发。
查询文件(。qry)
查询文件定义了用于返回有关区块链世界国家数据的查询。查询语法与 SQL 语言非常相似,例如:
query queryName {
description: "Select SampleAsset by assetId "
statement:
SELECT org.example.basic.SampleAsset
WHERE (_$assetId = assetId)
}
设计商业模式
现在,我们已经学习了基本的 composer 模型语言和结构,是时候使用 Hyperledger Composer 实现保险索赔了。
为了简单起见,在本例中,我们将允许参与者拥有对所有资源的读写权限。删除与 ACL 相关的示例资源,并更新规则,如下所示:
rule EverybodyCanReadEverything {
description: "Allow all participants read access to all resources"
participant: "**"
operation: READ
resource: "com.packt.quickstart.claim.*"
action: ALLOW
}
rule EverybodyCanSubmitTransactions {
description: "Allow all participants to submit transactions"
participant: "**"
operation: CREATE
resource: "**"
action: ALLOW
}
使用简化的 ACL,我们开始处理我们的模型文件,如下所示:
- 将
sample.cto
重命名为insurance-claim.cto
- 将名称空间改为
com.packt.quickstart.claim
并删除剩余的代码 - 定义参与者和资产
我们在 第十六章 ,中写了一个名为claimcontract.go
的链码,探索一个使用 Hyperledger Fabric 的企业区块链应用,它为被保险人、经纪保险人和索赔定义了一个结构。我们可以定义类似于这个结构的参与者和资产。这很简单,如下所示:
namespace com.packt.quickstart.claim
participant Insuree identified by id {
o String id
o String firstName
o String lastName
o String ssn
o String policyNumber
}
participant Company identified by id {
o String id
o String type
o String name
}
asset Claim identified by id {
o String id
o String desc
o Integer status
o String insureeId
o String brokerId
o String insurerId
o String comment
o String processAt
}
- 定义交易和事件。通过使用
Init
功能,我们在机上投保,如下所示:
transaction Init {
o String insureeId
o String firstName
o String lastName
o String ssn
o String policyNumber
}
event InitEvent {
--> Insuree insuree
}
- Composer 的 JavaScript API 提供 CRUD 来创建资源,包括参与者。对于保险公司和经纪人,我们将使用这种方法。当我们进行测试时,我们将对此进行更详细的解释。
- 定义
ReportLost
:被保险人向经纪人报告索赔——开始索赔,如下所示:
transaction ReportLost {
o String claimId
o String desc
o String insureeId
o String brokerId
}
event ReportLostEvent {
--> Claim claim
}
- 定义
RequestedInfo
:代理提供请求的信息,如下所示:
transaction RequestedInfo {
--> Claim claim
}
event RequestedInfoEvent {
--> Claim claim
}
- 定义
SubmitClaim
:经纪人向发行人提交索赔。 - 定义
ConfirmClaimSubmission
:发行人确认索赔。 - 定义
ApproveClaim
:发行人处理并批准索赔。
步骤 8、9 和 10 是事务函数,与步骤 7 非常相似。
我们已经在模型文件中定义了所有的事务、参与者和资产。下一步,我们将实现我们在模型文件中定义的事务。
实现业务交易功能
通过回顾SampleTransaction
,我们在上一节中学习了如何实现事务函数。按照类似的方法,我们将实现一个保险索赔事务功能。将sample.js
改名为logic.js
。
执行Init
功能,如下所示:
Init() function is used to register insuree person information.
/**
* Create the insuree
* @param {com.packt.quickstart.claim.Init} initalAppliation - the InitialApplication transaction
* @transaction
*/
async function Init(application) { // eslint-disable-line no-unused-vars
const factory = getFactory();
const namespace = 'com.packt.quickstart.claim';
const insuree = factory.newResource(namespace, 'Insuree', application.insureeId);
insuree.firstName = application.firstName;; insuree.lastName = application.lastName
insuree.ssn = application.ssn;;
insuree.policyNumber = application.policyNumber;;
const participantRegistry = await
getParticipantRegistry(insuree.getFullyQualifiedType());
await participantRegistry.add(insuree);
// emit event
const initEventEvent = factory.newEvent(namespace, 'InitEvent');
initEventEvent.insuree = insuree;
emit(initEventEvent);
}
执行ReportLost
并建立和创建索赔,如下所示:
/**
* insuree report lost item
* @param {com.packt.quickstart.claim.ReportLost} ReportLost - the ReportLost transaction
* @transaction
*/
async function ReportLost(request) {
const factory = getFactory();
const namespace = 'com.packt.quickstart.claim';
let claimId = request.claimId;
let desc = request.desc;
let insureeId = request.insureeId;
let brokerId = request.brokerId;
const claim = factory.newResource(namespace, 'Claim', claimId);
claim.desc = desc;
claim.status = "ReportLost";
claim.insureeId = insureeId;
claim.brokerId = brokerId;
claim.insurerId = "";
claim.comment = "";
claim.processAt = (new Date()).toString();
const claimRegistry = await getAssetRegistry(claim.getFullyQualifiedType());
await claimRegistry.add(claim);
// emit event
const reportLostEvent = factory.newEvent(namespace, 'ReportLostEvent');
reportLostEvent.claim = claim;
emit(reportLostEvent); }
执行RequestedInfo
以验证和更新索赔状态,如下所示:
/**
* broker send Requested Info to insuree
* @param {com.packt.quickstart.claim.RequestedInfo} RequestedInfo - the RequestedInfo transaction
* @transaction
*/
async function RequestedInfo(request) { // eslint-disable-line no-unused-vars
const factory = getFactory();
const namespace = 'com.packt.quickstart.claim';
let claim = request.claim;
if (claim.status !== 'ReportLost') {
throw new Error ('This claim should be in ReportLost status');
}
claim.status = 'RequestedInfo';
claim.processAt = (new Date()).toString();
const assetRegistry = await getAssetRegistry(request.claim.getFullyQualifiedType());
await assetRegistry.update(claim);
// emit event
const requestedInfoEventEvent = factory.newEvent(namespace, 'RequestedInfoEvent');
requestedInfoEventEvent.claim = claim;
emit(requestedInfoEventEvent); }
执行SubmitClaim
、ConfirmClaimSubmission
、ApproveClaim
。这些功能类似于RequestedInfo
。
在操场上测试
我们刚刚实现了上一节中的所有模型和逻辑文件,所以是时候测试我们的 composer 应用程序了:
- 单击操场左下方面板上的 Deploy changes 按钮。这将部署编写器代码。
- 单击顶部导航栏上的测试链接。它将弹出提交交易页面。从事务类型下拉列表中选择初始化方法。输入 JSON 值,如下截图所示;输入数据与我们在 第十六章 ,探索一个使用 Hyperledger Fabric 的企业区块链应用中测试的数据相同。实例化结构链代码步骤。提交事务处理,如下所示:
如果交易提交成功,我们将能够看到被保险人参与者已经创建,例如:
- 现在,让我们登上经纪人和保险公司。在参与者部分单击公司,然后单击创建新参与者。在中输入经纪人数据,与我们在第 16 章 、使用 Hyperledger Fabric 探索企业区块链应用 中的
chaincodeInvokeAddBroker
步骤相同。单击新建,如下所示:
如果交易提交成功,这将在代理上实现。重复同样的步骤登上保险公司,如下所示:
- 提交
ReportLost
,如下所示:
结果如下:
- 测试
RequestedInfo
,结果如下:
其余步骤(SubmitClaim
、ConfirmClaimSubmission
和ApproveClaim
与RequestedInfo
非常相似。
部署业务网络
我们已经在操场上测试了 composer 应用程序,所以接下来我们将把它部署到区块链:
- 创建一个名为
insurance-claim-network
的文件夹,并导航到该文件夹。 - 生成业务网络项目模板,如下所示:
yo hyperledger-composer:businessnetwork
会提示几个问题。输入insurance-claim-network
作为网络名称,选择空模板网络,如下图所示:
这将生成几个带有默认模板的文件。用我们之前测试过的模型文件替换com.packt.quickstart
.claim.cto
的内容。
在lib
文件夹下新建一个名为lib
的文件夹,将测试过的logic.js
复制到这里。
用测试过的acl
文件替换permissions.acl
,如下:
- 启动 Hyperledger Fabric,如下所示:
cd ~/fabric-devservers
export FABRIC_VERSION=hlfv12
./startFabric.sh
./createPeerAdminCard.sh
这将创建PeerAdminCard
,如下面的截图所示:
- 生成业务网络档案。从
insurance-claim-network
目录中,运行以下命令:
composer archive create -t dir -n
这将生成insurance-claim-network@0.0.1.bna
。
- 安装业务网络。从
insurance-claim-network
目录中,运行以下命令:
composer network install --card PeerAdmin@hlfv1 --archiveFile
insurance-claim-network@0.0.1.bna
- 启动业务网络。从
insurance-claim-network
目录中,运行以下命令:
composer network start --networkName insurance-claim-network --
networkVersion 0.0.1 --networkAdmin admin --networkAdminEnrollSecret
adminpw --card PeerAdmin@hlfv1 --file networkadmin.card
- 导入网络管理卡。从目录中的
insurance-claim-network
运行以下命令。这将把insurance-claim-network
导入网络:
composer card import --file networkadmin.card
- 检查业务网络是否已成功部署。从
insurance-claim-network
目录中,运行以下命令:
composer network ping --card admin@insurance-claim-network
结果应该如下所示:
检查业务网络是否部署成功
与 REST 服务器集成
我们刚刚在光纤网络中部署了insurance-claim-network
。下一步是构建一个保险索赔客户端 API,以便与网络中的智能合同功能进行交互。Hyperledger Composer REST 服务器可用于生成 REST API。REST 客户端可以调用这些端点函数,并从结构区块链与业务网络链代码进行交互。
生成 Hyperledger Composer REST API
运行以下命令生成 composer 服务器 API:
composer-rest-server
从业务网卡输入admin@insurance-claim-network
,如下截图所示:
输入业务网卡
这将生成 REST API,并将其公开为http://serverIP:3000
和http:// serverIP:3000/explorer
。
打开浏览 URL。您将看到生成的 REST 端点,如下所示:
让我们尝试多种方法来演示这些端点如何与结构网络交互。
从端点选择init Post
方法,提供 post JSON 数据,然后点击试用!按钮。JSON 数据的示例如下所示:
{
"$class": "com.packt.quickstart.claim.Init",
"insureeId": "user-001",
"firstName": "John",
"lastName": "Smith",
"ssn": "9999",
"policyNumber": "string"
}
这里有一个截图,显示了点击后的结果!按钮:
JSON 数据的示例
API 将调用光纤网络中的Init
chaincode,并将响应返回给浏览器。
使用过帐方法选择一家公司来创建被保险人。按如下方式输入这个 JSON 请求:
{
"$class": "com.packt.quickstart.claim.Init",
"insureeId": "user-001",
"firstName": "John",
"lastName": "Smith",
"ssn": "9999",
"policyNumber": "string"
}
您应该会看到一个成功的响应,类似于下面的屏幕截图:
选择一家使用过帐方法创建被保险人的公司,输入以下 JSON 请求
从端点选择ReportLost Post
方法,提供 post JSON 数据,点击 T 试一试! :
{
"$class": "com.packt.quickstart.claim.ReportLost",
"claimId": "claim_001",
"desc": "I was in Destiny shopping center and lost my IPhone 8",
"insureeId": "user_001",
"brokerId": "broker_001"
}
您应该会看到来自区块链的成功响应。
要验证索赔是否已在网络中成功创建,您可以选择索赔获取方法,然后单击试用!您应该能够获得索赔结果,如下所示:
验证索赔是否在网络中成功创建
其他保险索赔端点 API 将与我们探索的非常相似。
摘要
我们已经到了这一章的结尾。在本章中,我们概述了 Hyperledger Composer 并安装了相关工具。我们使用 composer 模型语言开发了与第十六章中相同的保险索赔用例,并将其部署到结构网络中。最后,我们将应用程序与 composer REST 服务器集成在一起,生成一个客户端 API,并从 web 上与这些 API 进行交互。
此时,您应该能够轻松使用 Hyperledger Composer。现在我们已经学完了这一章,我们已经了解了两个最受欢迎的公共和企业区块链。作为一名区块链开发人员,您应该具备编写区块链应用程序所需的基本区块链知识。在下一章,我们将讨论各种真实世界的区块链用例。