Hyperledger Composer架构
欢迎参加“选择私人区块链技术”系列的第二部分(第1部分在这里)。在每篇文章中,我们都会实现一个简单的用例来概述现有技术的作用以及它如何在企业中发挥作用。
最初,这篇文章本来将是关于Hyperledger Fabric,但是在了解了Hyperledger Composer之后,很显然,首先写出这些内容是有好处的。这将使我们能够更高层次地了解可以在Hyperledger Fabric区块链上构建哪种类型的业务应用程序,并更轻松地理解Fabric本身的用途。
让我们先从part1中定义的在金融行业的人工简单用例开始。以下是这个用例中的各部分:
让我们看看我们能够如何使用Hyperledger Composer来明确这个用例中的所有参与者,并使他们能够共享适当的信息。
Hyperledger Composer是一个更高级别的工具集和框架,用于在Hyperledger Fabric区块链之上快速构建和运行应用程序。如果Fabric是网络级别,那么Composer是应用程序级别的。我们可以使用它给那些能在Fabric通道内部署和执行的应用程序定义数据模型、业务逻辑和访问控制列表。此类应用程序的用户不必运行本地节点,并如果需要的话可通过RPC或HTTP REST与远程节点交互。
Composer配备了一个出色的网络环境,它允许用户在浏览器中创建应用程序原型而无需设置本地网络。我们将使用这个环境来实施和测试我们的用例。在未来的文章中,我们将导出“商业网络定义”并将其部署到真正的Hyperledger Fabric区块链。
解决方案的完整代码可以在这里找到。我们将了解到如何使用Composer Playground逐步配置每一部分。
选择“部署新的商业网络”并填写所需的信息。在我的情况下,网络的名称是'对冲基金网络',管理卡名称是admin @ hedge-fund-network。选择'空商业网络'模板并点击部署。这将创建一个空的商业网络和一个完全控制它的管理员身份。在创建商业网络后,我们可以通过按'立即连接'连接到它。
Composer有自己的对象建模语言,非常简单易用。有四种类型的资源可以定义:
现在,让我们创建一个名为'org.acme.mynetwork.cto'的模型文件并添加以下代码。该文件定义了3种参与者类型(交易者,客户,托管人),批次资产,交易交易和NewTrade事件。
/ ** *我的商品交易网络 * / namespace org.acme.mynetwork
asset Lot identified by lotId { o String lotId o String securityName o Double quantity o Double price --> Client owner }
participant Client identified by clientId { o String clientId o String description }
participant Custodian identified by custodianId { o String custodianId o String description }
participant Trader identified by traderId { o String traderId o String name }
transaction Trade { --> Trader trader --> Client client --> Lot lot }
event NewTradeEvent { --> Lot lot }
接下来,我们将实现每次发送交易事务时执行的自定义逻辑。使用下面的代码创建一个名为script.js的新脚本文件。Composer知道基于注释中的@param注释为每个交易交易执行此代码。这段代码做了两件事:更改一个Lot的所有者,并在成功时发出一个NewTrade事件。
/ ** *跟踪交易 * @param { org.acme.mynetwork.Trade}交易 - 将被处理的交易 * @交易 * / function tradeCommodity(trade) { var factory = getFactory(); trade.lot.owner = trade.client; var result = getAssetRegistry(‘org.acme.mynetwork.Lot’) .then(function (assetRegistry) { return assetRegistry.update(trade.lot); }); if (result) { var newTradeEvent = factory.newEvent(‘org.acme.mynetwork’, ‘NewTradeEvent’); newTradeEvent.lot = trade.lot; emit(newTradeEvent); } return result; }
最后,我们需要定义一个访问控制列表来管理每个参与者类型可以执行和查看的内容。我们在这里指定交易者可以执行交易,客户可以查看他们自己的交易,而保管人可以查看所有交易。
/ *管理员* /
rule NetworkAdminUser { description: "Grant business network administrators full access to user resources" participant: "org.hyperledger.composer.system.NetworkAdmin" operation: ALL resource: "**" action: ALLOW }
rule NetworkAdminSystem { description: "Grant business network administrators full access to system resources" participant: "org.hyperledger.composer.system.NetworkAdmin" operation: ALL resource: "org.hyperledger.composer.system.**" action: ALLOW }
/* Common */ rule CommonReadTransactionRegistry { description: "Allow all participants to read transaction registry" participant: "org.hyperledger.composer.system.Participant" operation: READ resource: "org.hyperledger.composer.system.TransactionRegistry" action: ALLOW }
rule CommonReadParticipantRegistry { description: "Allow all participants to read participant registry" participant: "org.hyperledger.composer.system.Participant" operation: READ resource: "org.hyperledger.composer.system.ParticipantRegistry" action: ALLOW }
rule CommonReadAssetRegistry { description: "Allow all participants to read asset registry" participant: "org.hyperledger.composer.system.Participant" operation: READ resource: "org.hyperledger.composer.system.AssetRegistry" action: ALLOW }
rule CommonReadNetwork { description: "Allow all participants to read network" participant: "org.hyperledger.composer.system.Participant" operation: READ resource: "org.hyperledger.composer.system.Network" action: ALLOW }
/* 交易人 */
rule TraderManageClient { description: "Allow traders to read all clients" participant: "org.acme.mynetwork.Trader" operation: ALL resource: "org.acme.mynetwork.Client" action: ALLOW
rule TraderManageOwnTrades { description: "Allow traders to manage their trades" participant(t): "org.acme.mynetwork.Trader" operation: ALL resource(tt): "org.acme.mynetwork.Trade" condition: (tt.trader.getIdentifier() == t.getIdentifier()) action: ALLOW }
rule TraderManageLots { description: "Allow traders to read and create lots" participant: "org.acme.mynetwork.Trader" operation: READ, CREATE resource: "org.acme.mynetwork.Lot" action: ALLOW }
rule TraderUpdateLots { description: "Allow traders to update lots via Trade transaction" participant: "org.acme.mynetwork.Trader" operation: UPDATE resource: "org.acme.mynetwork.Lot" transaction: "org.acme.mynetwork.Trade" action: ALLOW }
rule TraderReadOwnTrader { description: "Allow traders to read their own info" participant(t): "org.acme.mynetwork.Trader" operation: READ resource(tt): "org.acme.mynetwork.Trader" condition: (tt.getIdentifier() == t.getIdentifier()) action: ALLOW }
rule TraderAddAsset { description: "Allow traders to add assets to registry" participant: "org.acme.mynetwork.Trader" operation: CREATE resource: "org.hyperledger.composer.system.AddAsset" action: ALLOW }
rule TraderCreateHistorianRecord { description: "Allow traders to create historian record" participant: "org.acme.mynetwork.Trader" operation: CREATE resource: "org.hyperledger.composer.system.HistorianRecord" action: ALLOW }
rule TraderReadOwnHistorianRecord { description: "Allow traders to read their own historian record" participant(t): "org.acme.mynetwork.Trader" operation: READ resource(hr): "org.hyperledger.composer.system.HistorianRecord" condition: (hr.transactionType == "org.acme.mynetwork.Trade" && hr.participantInvoking.getIdentifier() == t.getIdentifier()) action: ALLOW }
/ *客户端* /
rule ClientReadOwnTrades { description: "Allow clients to view their trades" participant(c): "org.acme.mynetwork.Client" operation: READ resource(t): "org.acme.mynetwork.Trade" condition: (t.client.getIdentifier() == c.getIdentifier()) action: ALLOW }
rule ClientReadOwnEvents { description: "Allow clients to subscribe to NewTrade events" participant(c): "org.acme.mynetwork.Client" operation: READ resource(e): "org.acme.mynetwork.NewTradeEvent" condition: (e.lot.owner.getIdentifier() == c.getIdentifier()) action: ALLOW }
rule ClientReadOwnLots { description: "Allow clients to view lots they own" participant(c): "org.acme.mynetwork.Client" operation: READ resource(s): "org.acme.mynetwork.Lot" condition: (s.owner.getIdentifier() == c.getIdentifier()) action: ALLOW }
rule ClientReadOwnClient { description: "Allow clients to view their info" participant(c): "org.acme.mynetwork.Client" operation: READ resource(cc): "org.acme.mynetwork.Client" condition: (cc.getIdentifier() == c.getIdentifier()) action: ALLOW }
rule ClientReadTraders { description: "Allow clients to view traders" participant: "org.acme.mynetwork.Client" operation: READ resource: "org.acme.mynetwork.Trader" action: ALLOW }
rule ClientReadHistorianRecord { description: "Allow clients to view their historian records" participant(c): "org.acme.mynetwork.Client" operation: READ resource(hr): "org.hyperledger.composer.system.HistorianRecord" condition: (hr.transactionType == "org.acme.mynetwork.Trade" && hr.transactionInvoked.client.getIdentifier() == c.getIdentifier()) action: ALLOW }
/ *保管人* /
rule CustodianReadAllTrades { description: "Allow custodian to view all trades" participant: "org.acme.mynetwork.Custodian" operation: READ resource: "org.acme.mynetwork.Trade" action: ALLOW }
rule CustodianReadAllLots { description: "Allow custodian to view all lots" participant: "org.acme.mynetwork.Custodian" operation: READ resource: "org.acme.mynetwork.Lot" action: ALLOW }
rule CustodianReadAllClients { description: "Allow custodian to view all clients" participant: "org.acme.mynetwork.Custodian" operation: READ resource: "org.acme.mynetwork.Client" action: ALLOW }
rule CustodianReadAllEvents { description: "Allow custodian to subscribe to NewTrade events" participant: "org.acme.mynetwork.Custodian" operation: READ resource: "org.acme.mynetwork.NewTradeEvent" action: ALLOW }
rule CustodianReadAllTraders { description: "Allow custodian to view all traders" participant: "org.acme.mynetwork.Custodian" operation: READ resource: "org.acme.mynetwork.Trader" action: ALLOW }
rule CustodianReadOwnCustodian { description: "Allow custodian to view their info" participant(c): "org.acme.mynetwork.Custodian" operation: READ resource(cc): "org.acme.mynetwork.Custodian" condition: (cc.getIdentifier() == c.getIdentifier()) action: ALLOW }
rule CustodianReadHistorianRecord { description: "Allow custodian to view all trade historian records" participant(t): "org.acme.mynetwork.Custodian" operation: READ resource(hr): "org.hyperledger.composer.system.HistorianRecord" condition: (hr.transactionType == "org.acme.mynetwork.Trade") action: ALLOW }
完成所有步骤后,我们可以通过单击左侧的更新来部署应用程序。
既然我们有完整的应用程序定义,我们可以使用Composer Playground Test模块进行测试(点击顶部的测试)。
首先,让我们用一些参与者创建我们的应用程序。我们可以创建2个客户:托管人和交易人。
为了能够与商业网络进行交互,参与者需要一个关联的身份。身份可以在ID注册表中创建(打开右上角的用户下拉列表)。我们将通过指定其名称并指向上一步中创建的参与者实例来为每个参与者创建一个身份。至少,我们需要4个身份:2个客户,1个交易员和1个托管人。
我们现在可以通过点击列表中每个标识旁边的“立即使用”使用新创建的标识进行登录。首先,我们以交易者身份登录并创建一个不属于任何客户的新Lot(客户ID为空)。
然后,我们通过交易将Lot的所有权分配给客户1。
现在,我们再创建一个Lot,并通过另一个交易将其分配给客户2。
然后,我们将以客户端和客户2的身份登录,以检查我们是否可以看到我们的Lot。
客户1Lot
客户2Lot
正如你所看到的,每个客户只能看到他们拥有所有权的lot,他们不知道其他客户的交易。
我们先以托管人身份登陆,再检查我们是否可以查看所有交易。事实上,这两种交易都是可见的,如下所示:
托管人也可以查看所有交易的历史记录:
请记住,当交易广播到Hyperledger Fabric网络时,每个配置的对等方都独立执行自定义事务处理逻辑,以确保区块链更新的正确性。这是一个主要的体系结构差异,在许多情况下,这与传统的集中式客户端服务器方法相比具有优势。在传统的方法中,单个组织将负责管理数据并将数据暴露给其他参与者,迫使他人信任数据并使其成为潜在的单点故障。
在区块链方法中,每个对等方负责管理和协调他们自己的数据副本。这使整个网络更加灵活和分散。但是,配置并不是很简单。还有其他隐私问题需要考虑,因为这些数据现在托管在许多地方,从而形成潜在的更大威胁。
希望这可以让你更好地理解Hyperledger Composer是什么以及它如何在多个参与者之间共享信息和跟踪资产和其他概念方面起到作用。随意导出网络的.bna文件,并按照此处的教程将应用程序部署到本地Hyperledger Fabric网络。我们很乐意听取您对Hyperledger Composer的想法。请在下面留下任何问题或意见。
原文发布时间为:2018-03-12
本文作者:Mr.Crypto
本文来源:腾讯云 云+社区,如需转载请联系原作者。
文章浏览阅读308次。B. 通过"$r(‘app.type.name’)"的形式引用应用资源,app代表是应用内resources目录中定义的资源,type代表资源类型(或资源的存放位置)。11.在Column和Row容器组件中,justifyContent用于设置子组件在主轴方向上的对齐格式,alignItems用于设置子组件在交叉轴方向上的对齐格式。E. 属性方法:用于组件属性的配置,统一通过属性方法进行设置,如fontSize()、width()、height()、color() 等。_下面哪一个事件方法可以获取到list滑动的偏移量
文章浏览阅读1.5k次。近日,欧洲计算机视觉国际会议 ECCV 2022(European Conference on Computer Vision)发布了论文录用结果。本届 ECCV 2022论文有效投稿数5803篇,其中1650篇论文中选,录取率仅为28%。ECCV是国际顶尖的计算机视觉会议之一,每两年举行一次。今年将在10月23日-27日于以色列特拉维夫(Tel-Aviv)举行,并采取线..._kd-mvs: knowledge distillation based self-supervised learning for multi-view
文章浏览阅读8.7k次,点赞3次,收藏2次。感谢
文章浏览阅读1k次。本文主要介绍hadoop配置当中的一些零碎点总结,Windows与virtual box虚拟机之间实现文本复制的设置,配置完对应Linux的hadoop软件包之后的path环境说明,使用mkdir与mkdir -p 的不同之处,gedit与vim的区别_hadoop!w保存
文章浏览阅读3.2k次,点赞3次,收藏13次。方法:1、web界面导出 2、命令行 dis cu敲命令后,可以查看设备的所有配置,将配置可以粘贴出来(适用于配置较少情况) 3、FTP导出FTP导出具体步骤:1、在ROUTER\SWITCH上<XA-WAN-ROUTER-01>sys[XA-WAN-ROUTER-01]ftp server enable[XA-WAN-ROUTER-01]aaa local-user ftp password irreversible-ciph..._华为交换机web导出配置
文章浏览阅读2.8k次。作者 |RicardoMJiang来源 |https://juejin.cn/post/6997396071055900680我估计用到这么高版本的同学非常少,大家可以简单了解下,做个..._alias(libs.plugins.springboot)
文章浏览阅读3.4w次,点赞51次,收藏195次。【1】inRange()函数OpenCV中的inRange()函数可实现二值化功能(这点类似threshold()函数),更关键的是可以同时针对多通道进行操作,使用起来非常方便!主要是将在两个阈值内的像素值设置为白色(255),而不在阈值区间内的像素值设置为黑色(0),该功能类似于之间所讲的双阈值化操作。函数原型(C++): void inRange(InputArr..._opencv inrange
文章浏览阅读72次。1.封装在面向对象程式设计方法中,封装(英语:Encapsulation)是指,一种将抽象性函式接口的实作细节部份包装、隐藏起来的方法。封装可以被认为是一个保护屏障,防止该类的代码和数据被外部类定义的代码随机访问。要访问该类的代码和数据,必须通过严格的接口控制。封装最主要的功能在于我们能修改自己的实现代码,而不用修改那些调用我们代码的程序片段。适当的封装可以让程式码更容易理解与维护,也加强了程式码..._一般情况下,需要通过____和____方法访问封装的私有成员变量。
文章浏览阅读9.6k次。es拼音插件https://github.com/medcl/elasticsearch-analysis-pinyin/tree/v1.6.0,具体用法此处不介绍,看readme现在要实现一个搜场馆的功能,需要按场馆名称首字母缩写也能搜索出场馆,还必须要高亮显示首拼对应的汉字部分。analysis可定义如下: "analysis": { "tokenizer_es使用pinyin搜索,对应中文没有高亮显示
文章浏览阅读509次,点赞3次,收藏2次。前言C语言里自定义类型有3种,分别是结构体,枚举,联合结构体结构是一些值的集合,这些值称为成员变量。结构的每个成员可以是不同类型的变量。结构体的声明结构体的声明形式如下struct tag//tag是标签名{ member-list;//大括号里面是结构体成员}variable-list;//大括号后面分号前是变量列表,可以在这里定义变量。注意最后的分号不能少示例struct Book{ char name[30]; double price; char author_语言
文章浏览阅读1k次。点击上方“CVer”,选择加"星标"置顶重磅干货,第一时间送达本文转载自:科研大匠近日,塔里木大学发布了《2021年塔里木大学面向社会公开招聘教师公告》,有编制,送大大房子..._有两篇sci可以硕士直接当老师吗
文章浏览阅读1w次,点赞15次,收藏27次。以下所有都是基于Flink 1.12.0版本Flink JDBCSink的使用flink提供了JDBCSink方便我们写入数据库,以下是使用案例:pom依赖需要引入flink-connector-jdbc的依赖。另外,我这里是写入mysql,所以还引入了mysql的驱动包<dependency> <groupId>org.apache.flink</groupId> <artifactId>flink-connector-jdbc_2_flink jdbcsink