使用Hyperledger-Fabric和Composer实现区块链应用程序

45次阅读

共计 9856 个字符,预计需要花费 25 分钟才能阅读完成。

目前无法绕过技术领域的是区块链话题。但除了加密货币之外,还有更多有趣的应用程序可以带来许多激动人心的软件生态系统。这也适用于 Hyperledger 项目,该项目提供了一个非常模块化的区块链框架。让我们看看使用 Hyperledger Fabric 和 Composer 实现区块链应用程序是多么容易。

关于项目 Hyperledger

Hyperledger 是一个 umbrella 项目的名称,在该项目下开源区块链方法和工具是协同开发的。它由 Linux 基金会于 2015 年推出,并享有 IBM,英特尔和富士通等软件巨头以及大型社区的热烈参与。Hyperledger 的 GitHub 存储库目前比以往更加活跃。任何人都可以参与开发。

在 Hyperledger 中,不仅开发了单个区块链框架(或平台)。相反,重点是并行采用多种方法,创造协同效应,可重复使用的组件和灵活性。从 Hyperledger 概念的角度来看,区块链网络与比特币或以太网等加密货币的代表无法比较。相反,Hyperledger 网络的节点分布在参与组织中,这使得私有,许可或联盟区块链网络特别有趣。首先,我们可以忘记公共区块链的工作证明,股权证明和其他共识机制。所涉及的组织从应用程序业务价值和所涉及的信任中作为联合体验证彼此的交易和利益。这也很大程度上解决了可扩展性问题(我们从比特币网络中了解到)并且可以实现高交易吞吐量。

项目 Hyperledger 的不同区块链方法是 Fabric,Burrow,Iroha,Indy 和 Sawtooth。私有,许可和联合区块链可以与所有这些区块链一起开发,但每种实现都遵循不同的方法。

我们将在本文中详细介绍 Fabric,因为它拥有最活跃的社区,并且是最灵活的变体。由于其强大的模块化,fabric 是普遍可用的。“你可以将 Hyperledger Fabric 视为类似于 Apache Web Server”,Linux 基金会 Hyperledger 执行董事 Brian Behlendorf 说。其他方法更多用于在有限的环境中实施特殊情况。

Hyperledger Fabric ——灵活的区块链应用平台

使用 Fabric 作为平台,可以开发完全独立的分布式分类帐解决方案。Fabric 包含可以尽可能自由实现的概念。区块链网络的基础是对所需组织结构的建模。每个参与者都有固定的身份,可以通过颁发的证书来识别自己。除了身份验证之外,还包括授权。使用这种基于角色的系统,可以获得许可区块链中隐私和机密性的灵活方面。对于证书和参与者的管理,可以使用结构证书颁发机构(1.0 版之前的成员服务提供者)。

资产的定义(要在区块链上管理的项目)完全取决于区块链应用程序。这些资产,例如来自汽车行业的引擎块由 JSON 和 / 或二进制格式的键值对模型定义。

链代码的概念旨在基于资产及其所有者实现业务逻辑。这可用于实现 Go,Java 或 Node.js 等语言中的规则,这些规则定义读取权限或资产修改。执行链代码功能可以读取和返回资产和 / 或创建和修改资产并将它们存储在本地分类帐数据库中。在节点上的本地持久性更改之后,将更改提交给网络(“认可”)并在其他组织接受后插入到区块链中。在以太坊或其他公共区块链平台的背景下,可以将链码与智能合约进行比较。

通道用于实现隐私领域。在最简单的场景中,整个链代码部署在所有参与者加入的单个通道上。但是,为了创建封装区域并仅允许选定的参与者在其中进行通信,可以配置具有受限参与者组的通道。每个通道可以部署不同的链代码,从而可以实现功能隔离。此外,可以使用 AES 部分或完全加密通道中的通信。

结果,在每个通道中维护一个分布式分类帐,这可以被想象为链接交易的现金簿。每个参与者为他们所属的每个通道保留一份分类帐副本。这为网络中的每个现有信道创建了区块链数据结构。与区块链一样,交易存储在块中,这些块在单个连接列表中成为加密链。

但是,为了向客户端应用程序提供分类帐数据的单独视图,甚至可以执行针对网络的复杂读取请求。由于使用了像 CouchDB 这样的面向文档的数据库,这是可能的。这为连接到 Fabric 网络的客户端提供了灵活的数据访问。

使用 Composer 添加更简单的概念

Hyperledger-Composer 是 Hyperledger 生态系统中的工具之一。你可以将其视为 Fabric 的框架。如果你想开发,构建和管理 Fabric 网络,那么即使不是强制性的,也是实用的。它引入了基于 Fabric 的进一步概念,以提供精美的抽象概念。

除资产外,还可以在 Composer 建模语言中定义网络参与者,交易和事件的方案。每种交易类型的流都通过 JavaScript 代码在简单的 API 上实现。访问控制文件可用于限制参与者对某些资源的访问权限。可以在 Composer Query Language 中定义对分类帐中数据的常用查询,这是一种类似 SQL 的语言。

然后,必须将所有必需文件打包到.bna 文件中的 BND(业务网络定义)。然后,可以将此存档安装在现有 Fabric 网络上。BND 的源代码当然可以在我们首选的编辑器中进行本地开发和测试,因此可以通过 Git 进行版本控制。对于原型设计和演示目的,有 Composer Playground。这提供了一个现代,清晰且直观可用的 Web 界面,可访问 Composer CLI 的本地配置。使用 Playground,你可以轻松创建,安装,测试,编辑,导入和导出 BND。

在 Composer Playground 中,你可以以用户友好的方式安装,修改和测试新的业务网络,而无需先前的样本区块链应用知识(例如车辆生命周期,汽车拍卖或农场动物跟踪)。在设置工具之后,可以在本地完成相同的操作,这样我们就可以在短时间玩游戏后离开托管游乐场。这个游乐场非常适合使用原型验证想法并了解底层的 Composer 和 Fabric 模型。

使用案例:引擎块的供应链跟踪

为了使用 Hyperledger-Fabric 和 Composer 实现私有区块链网络,以汽车行业的发动机组跟踪为例。在这种情况下,有制造商和经销商作为网络参与者。发动机及其安装的车辆显示为资产。制造商和经销商的公司被引入并被识别为网络中的组织。

Fabric 链代码应提供以下功能:

  • 1. 生产具有唯一序列号的发动机缸体。
  • 2. 生产后将发动机缸体传送给经销商。
  • 3. 跟踪车辆的序列号。
  • 4. 将发动机缸体安装到注册车辆中。

下一步是安装所需的工具和设置项目。

开发环境设置和项目创建

首先,需要安装文档中列出的 Fabric 的所有要求。然后我们安装 Composer 和 Composer 及其相关工具本身的要求。

然后,最好让自己熟悉新环境。如果我们完全按照上一个链接的说明操作,则 fabric-tools 现在位于我们的主目录中。通过描述的脚本,我们可以在 Docker-Compose 中启动一个简单的 Fabric 网络,获得对等管理员访问权限并停止并再次删除它。首先,我们下载 1.1 版的 Docker 镜像并启动网络:

export FABRIC_VERSION=hlfv11 && ./downloadFabric.sh && ./startFabric.sh

在网络运行时,composer-playground web-UI 可以通过 composer-playground 启动。它使用 composer-cli 的所有托管配置并访问正在运行的 Fabric 网络。从现在开始,我们将 Fabric 视为可配置的平台 / 基础架构,其状态通过合适的工具进行更改。我们不直接使用 Fabric 概念开发链代码,权限或任何模型,因为 Composer 提供了更多优势。

实施功能

现在我们在我们选择的目录中创建我们的 BND 项目。对于 Yeoman(使用模板设置项目的代码生成器,如 Maven Archtypes),有一个模板(hyperledger-composer:businessnetwork。但是,我已经准备了一个存储库,我们现在也可以使用 JavaScript ES6 和一些很好的工具。我们应该从开始分支“初始”开始。master分支具有最终版本和工作版本。我们首先克隆存储库的初始分支。

git clone -b initial git@github.com:jverhoelen/fabric-composer-engine-supplychain.git

现在我们在我们选择的编辑器中打开文件夹。Visual Studio Code 非常适合 Composer,因为它具有可安装的语法高亮扩展。稍作修改后你会发现它是一个 NPM 项目,所以我们从 npm install 开始安装所有依赖项。使用 npm test 我们可以运行单元测试,使用 npm run lint 我们可以测试代码样式,并且使用 npm run createArchive 我们可以创建 the.bna 文件,我们以打包格式完成业务网络定义。让我们马上试试看是否一切正常。

然后我们熟悉项目结构。lib文件夹包含实现交易处理器功能的 JS 文件。当然,我们想测试这个业务逻辑并将我们的单元测试存储在 test/ 文件夹中。模型定义(参与者,资产,交易等)在 models/ 中。

我们想首先为所需的区块链网络建模。为此,我们删除模型文件的内容,并在第一行为其指定一个新的命名空间:

namespace org.acme.enginesupplychain

我们为参与者制造商和经销商建模,并使用 Composer 建模语言的继承。我们还希望每个参与者除了姓名外还有一个可选地址。我们将这些属性放入一个概念中:

participant Member identified by memberId {
    o String memberId
    o String name
    o Address address optional
}
 
participant Manufacturer extends Member {
}
 
participant Merchant extends Member {
}
 
concept Address {
    o String country
    o String city
    o String street
    o String streetNo
}

然后我们介绍我们网络的资产:引擎块和稍后安装引擎的汽车。在这里,我们了解资产和参与者可以互相参考。引用始终指向任何类型的现有资源。我们以小“o”开头的属性总是存在于资源本身中。

asset Engine identified by engineId {
    o String engineId
    o EngineProperties data
 
    --> Manufacturer manufacturer
    --> Car currentCar optional
    --> Merchant merchant optional
}
 
asset Car identified by carId {
    o String carId
    o String legalDocumentId
}
 
concept EngineProperties {
    o String brand
    o String model
    o Double horsePower
    o Double cubicCapacity
    o Integer cylindersAmount
}

在对系统建模之后,我们定义了可以在现有资产和参与者之上执行的所有可用操作。这些是交易资源。之后,我们为以下每个交易模型测试并实现基础交易逻辑。

transaction EngineMerchantTransfer {
    --> Engine engine
    --> Merchant merchant
}
 
transaction EngineCarInstallation {
    --> Engine engine
    --> Car car
}
 
transaction EngineCreation {
    --> Manufacturer manufacturer
    o EngineProperties data
}
 
transaction CarCreation {o String legalIdDocument}

现在我们已经定义了可能发生的事情,我们可以在提交交易时开始实现它如何影响分类帐状态。首先,我们致力于创建引擎资产。引擎应该以 UUID 格式获得随机生成的 ID,并且应该从一开始就始终属于制造商。所以我们清空 logic.js 文件并从头开始。我们定义常量 modelsNamespace 和函数 uuid,因为我们将更频繁地需要它们。接下来是createEngineAsset 函数。函数上方的文档块非常重要,以便 Composer 可以识别打包代码时实现的交易类型。

/* global getAssetRegistry getFactory */
 
const modelsNamespace = 'org.acme.enginesupplychain'
function uuid() {const s4 = () => Math.floor((1 + Math.random()) * 0x10000).toString(16).substring(1)
    return `${s4()}${s4()}-${s4()}-${s4()}-${s4()}-${s4()}${s4()}${s4()}`
}
 
/**
* Creation of a Engine asset triggered by physical production.
* @param {org.acme.enginesupplychain.EngineCreation} tx - the transaction to create an engine
* @transaction
*/
async function createEngineAsset(tx) { // eslint-disable-line no-unused-vars
    const engineRegistry = await getAssetRegistry(modelsNamespace + '.Engine')
    const engine = getFactory().newResource(modelsNamespace, 'Engine', uuid())
    const engineData = getFactory().newConcept(modelsNamespace, 'EngineProperties')
 
    engine.data = Object.assign(engineData, tx.data)
    engine.manufacturer = tx.manufacturer
 
    await engineRegistry.add(engine)
}

通过这种方式,我们还实现了其他交易类型 EngineMerchantTransferEngineCarInstallationCarCreation

/**
* An engine is transfered to a merchant.
* @param {org.acme.enginesupplychain.EngineMerchantTransfer} tx - the engine transfer transaction
* @transaction
*/
async function transferEngineToMerchant(tx) { // eslint-disable-line no-unused-vars
    const engineRegistry = await getAssetRegistry(modelsNamespace + '.Engine')
    tx.engine.merchant = tx.merchant
 
    await engineRegistry.update(tx.engine)
}
 
/**
* An engine is installed in a car.
* @param {org.acme.enginesupplychain.EngineCarInstallation} tx - the engine into car installation transaction
* @transaction
*/
async function installEngineToCar(tx) { // eslint-disable-line no-unused-vars
    const engineRegistry = await getAssetRegistry(modelsNamespace + '.Engine')
    if (tx.car) {
        tx.engine.currentCar = tx.car
        await engineRegistry.update(tx.engine)
    } else {return Promise.reject('No target car was set on the transaction!')
    }
}
 
/**
* A car is created.
* @param {org.acme.enginesupplychain.CarCreation} tx - transaction to create a new car
* @transaction
*/
async function createCar(tx) { // eslint-disable-line no-unused-vars
    const carRegistry = await getAssetRegistry(modelsNamespace + '.Car')
    const factory = getFactory()
    const carId = uuid()
    const car = factory.newResource(modelsNamespace, 'Car', carId)
    car.legalDocumentId = tx.legalIdDocument
 
    await carRegistry.add(car)
}

功能本身的单元测试相对简单,如果我们有经验,我们不需要了解更多。只有对此所需的对象的 boostrapping 仍然有点超载样板代码。测试首先启动内存中的 Fabric 网络,在其上安装业务网络,然后以默认管理员身份对其进行身份验证。因为这个 Composer 提供了库 composer-admincomposer-clientcomposer-commoncomposer-connector-embedded。在测试设置之后,我们现在可以针对嵌入式网络编写测试用例。由于其长度,设置代码未包含在列表中,但可以在 test/EngineSupplychainSpec.js 中的主分支上查看和测试。

用于测试交易类型的单元测试用例通常具有类似的模式。他们使用其属性和关系重新创建交易,针对网络执行交易,然后检查所涉及的资产和参与者的数据状态。我们来看看 createEngineAsset 的现有测试用例。

describe(‘EngineSupplychainSpec’, () => {
 
   // setup is done in the before and beforeEach hook
   // results are the bnc (BusinessNetworkConnection), target namespace
   // as well as test assets, participants and required registries
   describe('createEngineAsset', () => {it('should create an Engine by submitting a valid EngineCreation transaction', async () => {const factory = bnc.getBusinessNetwork().getFactory()
 
           const engineCreationTrans = factory.newTransaction(namespace, 'EngineCreation')
           engineCreationTrans.data = factory.newConcept(namespace, 'EngineProperties')
           engineCreationTrans.data.brand = 'Audi'
           engineCreationTrans.data.model = 'Fancy engine model'
           engineCreationTrans.data.horsePower = 400
           engineCreationTrans.data.cubicCapacity = 4000
           engineCreationTrans.data.cylindersAmount = 10
 
           const manufacturerRegistry = await bnc.getParticipantRegistry(namespace + '.Manufacturer')
           await manufacturerRegistry.addAll([])
           engineCreationTrans.manufacturer = factory.newRelationship(namespace, 'Manufacturer', testManufacturer.$identifier)
 
           await bnc.submitTransaction(engineCreationTrans)
 
           const allEngines = await engineRegistry.getAll()
           allEngines.length.should.equal(2)
       })
   })
})

在 Hyperledger Composer 中实现业务网络定义的方法应该通过这些见解变得清晰。此外,BND 可以为我们定义更多的东西。在 permissions.acl 中,你可以使用访问控制语言为给定简单条件的参与者定义访问限制。对于许多应用程序,事件和查询功能也非常有用和有趣。

最后,我们来看看主分支上的解决方案。所有这些要求都已在其中实施和测试。我们现在用 npm run createArchive 生成完成的 .bna 文件,然后在 dist/ 文件夹中。我们现在可以将它导入到我们在控制台中启动的 Composer Playground 中,以便在我们的本地 Fabric 网络上进行尝试。通过 Web UI 的方式应该是不言自明的,但它也是正式记录的。

总结和展望

我们已经了解了 Hyperledger 项目的重要部分。具体来说,我们现在知道 Fabric 作为具有基本概念的区块链平台。Composer 添加了许多重要概念,使开发人员可以非常方便地实施和管理区块链网络。通过实施的关于发动机缸体生产和跟踪的区块链应用案例,我们了解了一个简单但功能强大的私人 / 联盟区块链用例。

最终的区块链网络最初只在本地执行。我们还没有扩展同行组织和订购服务的配置。但我们可以轻松添加更多组织并通过多个主机分发对等节点。对于由真正的组织联盟跨越的区块链网络,我们仍然有一些问题需要解决:

我们如何管理组织和对等节点?组织如何自动将新的对等节点添加到网络中?我们如何获得一个可以抵御失败的公平和同质的网络?客户如何与网络通信?

这个仍然年轻的平台已经提供了很多功能和舒适性。但是,仍有许多任务需要完成。从开发人员的角度来看,单元测试代码看起来仍然非常臃肿。很快就会出现库,通过它可以更容易地实现通常的测试模式。我们迫切希望看到 Hyperledger 等项目将如何继续推动业务中分布式账本技术的适应性。

故障排除

确保所有工具都与 Fabric 1.1 兼容。这意味着必须下载此版本的所有 docker 镜像。应安装最新版本的 Composer 和 Composer Playground。目前是 v0.19.1。本文中 Fabric 和 Composer 文档的所有链接都是故意修复到 Fabric 1.1 和最新的 Composer 版本。

分享一些 Hyperledger fabric 区块链相关的交互式在线编程实战教程:

  • Hyperledger Fabric 区块链开发详解,本课程面向初学者,内容即包含 Hyperledger Fabric 的身份证书与 MSP 服务、权限策略、信道配置与启动、链码通信接口等核心概念,也包含 Fabric 网络设计、nodejs 链码与应用开发的操作实践,是 Nodejs 工程师学习 Fabric 区块链开发的最佳选择。
  • Hyperledger Fabric java 区块链开发详解,课程面向初学者,内容即包含 Hyperledger Fabric 的身份证书与 MSP 服务、权限策略、信道配置与启动、链码通信接口等核心概念,也包含 Fabric 网络设计、java 链码与应用开发的操作实践,是 java 工程师学习 Fabric 区块链开发的最佳选择。

汇智网原创翻译,转载请标明出处。这里是原文使用 Hyperledger Fabric 和 Composer 实现区块链应用程序

正文完
 0