跳转至

使用 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 的企业区块链应用中,我们讨论了保险索赔的区块链用例。它包括以下步骤:

  1. 保险公司向经纪人报告索赔
  2. 代理提供所请求的信息

  3. 经纪人向发行人提交索赔

  4. 发行人确认索赔
  5. 发行人处理并批准索赔

在本章中,我们将使用相同的保险索赔用例,但也通过 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,我们开始处理我们的模型文件,如下所示:

  1. sample.cto重命名为insurance-claim.cto
  2. 将名称空间改为com.packt.quickstart.claim并删除剩余的代码
  3. 定义参与者和资产

我们在 第十六章中写了一个名为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
      }
  1. 定义交易和事件。通过使用Init功能,我们在机上投保,如下所示:
      transaction Init {
        o String insureeId
        o String firstName
        o String lastName
        o String ssn
        o String policyNumber
      }
      event InitEvent {
        --> Insuree insuree
      }
  1. Composer 的 JavaScript API 提供 CRUD 来创建资源,包括参与者。对于保险公司和经纪人,我们将使用这种方法。当我们进行测试时,我们将对此进行更详细的解释。
  2. 定义ReportLost:被保险人向经纪人报告索赔——开始索赔,如下所示:
      transaction ReportLost {
        o String claimId
        o String desc
        o String insureeId
        o String brokerId
      }
      event ReportLostEvent {
         --> Claim claim
      }
  1. 定义RequestedInfo:代理提供请求的信息,如下所示:
      transaction RequestedInfo {
        --> Claim claim
      }
      event RequestedInfoEvent {
        --> Claim claim
      }
  1. 定义SubmitClaim:经纪人向发行人提交索赔。
  2. 定义ConfirmClaimSubmission:发行人确认索赔。
  3. 定义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); }

执行SubmitClaimConfirmClaimSubmissionApproveClaim。这些功能类似于RequestedInfo

在操场上测试

我们刚刚实现了上一节中的所有模型和逻辑文件,所以是时候测试我们的 composer 应用程序了:

  1. 单击操场左下方面板上的 Deploy changes 按钮。这将部署编写器代码。
  2. 单击顶部导航栏上的测试链接。它将弹出提交交易页面。从事务类型下拉列表中选择初始化方法。输入 JSON 值,如下截图所示;输入数据与我们在 第十六章探索一个使用 Hyperledger Fabric 的企业区块链应用中测试的数据相同。实例化结构链代码步骤。提交事务处理,如下所示:

如果交易提交成功,我们将能够看到被保险人参与者已经创建,例如:

  1. 现在,让我们登上经纪人和保险公司。在参与者部分单击公司,然后单击创建新参与者。在中输入经纪人数据,与我们在第 16 章 、使用 Hyperledger Fabric 探索企业区块链应用 中的chaincodeInvokeAddBroker步骤相同。单击新建,如下所示:

如果交易提交成功,这将在代理上实现。重复同样的步骤登上保险公司,如下所示:

  1. 提交ReportLost,如下所示:

结果如下:

  1. 测试RequestedInfo,结果如下:

其余步骤(SubmitClaimConfirmClaimSubmissionApproveClaimRequestedInfo非常相似。

部署业务网络

我们已经在操场上测试了 composer 应用程序,所以接下来我们将把它部署到区块链:

  1. 创建一个名为insurance-claim-network的文件夹,并导航到该文件夹。
  2. 生成业务网络项目模板,如下所示:
 yo hyperledger-composer:businessnetwork

会提示几个问题。输入insurance-claim-network作为网络名称,选择空模板网络,如下图所示:

这将生成几个带有默认模板的文件。用我们之前测试过的模型文件替换com.packt.quickstart .claim.cto的内容。

lib文件夹下新建一个名为lib的文件夹,将测试过的logic.js复制到这里。 用测试过的acl文件替换permissions.acl,如下:

  1. 启动 Hyperledger Fabric,如下所示:
 cd ~/fabric-devservers
 export FABRIC_VERSION=hlfv12
 ./startFabric.sh
 ./createPeerAdminCard.sh

这将创建PeerAdminCard,如下面的截图所示:

  1. 生成业务网络档案。从insurance-claim-network目录中,运行以下命令:
 composer archive create -t dir -n 

这将生成insurance-claim-network@0.0.1.bna

  1. 安装业务网络。从insurance-claim-network目录中,运行以下命令:
 composer network install --card PeerAdmin@hlfv1 --archiveFile 
      insurance-claim-network@0.0.1.bna
  1. 启动业务网络。从insurance-claim-network目录中,运行以下命令:
 composer network start --networkName insurance-claim-network --
      networkVersion 0.0.1 --networkAdmin admin --networkAdminEnrollSecret 
      adminpw --card PeerAdmin@hlfv1 --file networkadmin.card
  1. 导入网络管理卡。从目录中的insurance-claim-network运行以下命令。这将把insurance-claim-network导入网络:
 composer card import --file networkadmin.card
  1. 检查业务网络是否已成功部署。从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:3000http:// 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。现在我们已经学完了这一章,我们已经了解了两个最受欢迎的公共和企业区块链。作为一名区块链开发人员,您应该具备编写区块链应用程序所需的基本区块链知识。在下一章,我们将讨论各种真实世界的区块链用例。


我们一直在努力

apachecn/AiLearning

【布客】中文翻译组