来自:腾讯云,作者:Mr.Su
链接:https://cloud.tencent.com/developer/article/1057817
Hyperledger Composer架构
最初,这篇文章本来将是关于Hyperledger Fabric,但是在了解了Hyperledger Composer之后,很显然,首先写出这些内容是有好处的。这将使我们能够更高层次地了解可以在Hyperledger Fabric区块链上构建哪种类型的业务应用程序,并更轻松地理解Fabric本身的用途。
商业用例
让我们先从在金融行业的人工简单用例开始。以下是这个用例中的各部分:
让我们看看我们能够如何使用Hyperledger Composer来明确这个用例中的所有参与者,并使他们能够共享适当的信息。
什么是Hyperledger Composer?
Hyperledger Composer是一个更高级别的工具集和框架,用于在Hyperledger Fabric区块链之上快速构建和运行应用程序。如果Fabric是网络级别,那么Composer是应用程序级别的。我们可以使用它给那些能在Fabric通道内部署和执行的应用程序定义数据模型、业务逻辑和访问控制列表。此类应用程序的用户不必运行本地节点,并如果需要的话可通过RPC或HTTP REST与远程节点交互。
Composer配备了一个出色的网络环境,它允许用户在浏览器中创建应用程序原型而无需设置本地网络。我们将使用这个环境来实施和测试我们的用例。在未来的文章中,我们将导出“商业网络定义”并将其部署到真正的Hyperledger Fabric区块链。
解决方案
解决方案的完整代码可以在GitHub找到。我们将了解到如何使用Composer Playground逐步配置每一部分。
(
GitHub地址:https://github.com/andrei-anisimov/hyperledger-composer-example?spm=a2c4e.11153940.blogcont582465.11.25ab2222E5w1ab
)
1.创建网络
选择“部署新的商业网络”并填写所需的信息。在我的情况下,网络的名称是'对冲基金网络',管理卡名称是admin @ hedge-fund-network。选择'空商业网络'模板并点击部署。这将创建一个空的商业网络和一个完全控制它的管理员身份。在创建商业网络后,我们可以通过按'立即连接'连接到它。
2.配置对象模型
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
}
3.配置交易逻辑
接下来,我们将实现每次发送交易事务时执行的自定义逻辑。使用下面的代码创建一个名为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;
}
4.访问控制列表(ACL)
最后,我们需要定义一个访问控制列表来管理每个参与者类型可以执行和查看的内容。我们在这里指定交易者可以执行交易,客户可以查看他们自己的交易,而保管人可以查看所有交易。
/ *管理员* /
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
}
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
}