Hyperledger Composer 链代码与 IBM ODM 规则引擎不在同一个流程中运行,所以两个流程通过 REST 调用进行通信。
Hyperledger Composer 提供了一个 API,可使用它在链代码外执行 POST REST 调用,传递当前交易,以及所需的任何其他资产或参与者数据。Hyperledger Composer 将资源作为 REST 调用的参数传递到 JSON 文档中。
IBM ODM 将决策服务公开为 REST API,该 API 可接受描述请求有效负载的 JSON 有效负载。
例如,下面的 Hyperledger Composer 交易处理器使用一个决策服务来确定给定交易是否存在欺诈,如以下代码所示:
- /**
- * Transfer a vehicle to another private owner
- * @param {org.vda.PrivateVehicleTransfer} privateVehicleTransfer - the PrivateVehicleTransfer transaction
- * @transaction
- */
- function privateVehicleTransfer(privateVehicleTransfer) {
- ...
- }
这段 JavaScript 代码知道哪个决策服务实现了它需要执行的决策。作为对等节点执行环境的一部分,Rule Execution Server 正在运行,并准备通过 REST API 接收请求。
在回调中使用以下代码来调用决策服务:
- var
- rulesetPath
- =
- ruleappName
- +
- "/"
- +
- currentRuleappVersion
- +
- "/"
- +
- rulesetName
- +
- "/"
- +
- currentRulesetVersion
- ;
- // this is where we're calling out to a Decision Service to determine of the transaction is suspicious or not
- // The Decision Service returns a 'status' and a 'message'.'status' could be ACCEPTED, REJECTED, SUSPICION.
- // If REJECTED, the transaction should abort with the 'message' indicating why.If SUSPICION, the 'message'
- // should be assigned to the Vehicle.suspiciousMessage field
- // The Decision Service receives all the data about the current transaction: buyer, seller and the vehicle
- var url = 'http://odmruntime_odm-runtime_1:9060/DecisionService/rest/' + rulesetPath;
- var dsCallObject = factory.newResource(NS_DECISION, 'IsSuspiciousTransferDecisionService', "isSuspiciousTransfer");
- dsCallObject.transaction = privateVehicleTransfer;
- print("Calling ODM Decision Service: " + url);
- return post( url, dsCallObject, {permitResourcesForRelationships: true, deduplicateResources: true});
可以在 vda.js 中查看本示例的代码。
这个回调所处理的交易包装在一个专用对象中,并传递给该调用。这里引入了包装器对象,是为了让 Hyperledger Composer 发送的 JSON 有效负载与决策服务期望的请求有效负载相匹配,期望有效负载取决于 IBM ODM 中指定的决策服务签名。例如,一个决策服务签名可能有多个输入参数,所有参数都必须是请求有效负载中的条目。
下面的有效负载中的
条目与 IBM ODM 的决策操作中指定的
- transaction
输入参数相匹配。
- transaction
由于
交易指明了买家、卖家和车辆,所以整个对象图序可序列化为一个 JSON 文档。在调用 Hyperledger Composer
- PrivateVehicleTransfer
API 时,会将该文档发送给决策服务。对于此交易,生成了以下 JSON 代码:
- post()
- {
- "$class": "org.acme.vehicle.lifecycle.decision.IsSuspiciousTransferDecisionService",
- "$id": "resource:org.acme.vehicle.lifecycle.decision.IsSuspiciousTransferDecisionService#isSuspiciousTransfer",
- "dsId": "isSuspiciousTransfer",
- "transaction": {
- "$class": "org.vda.PrivateVehicleTransfer",
- "$id": "resource:org.vda.PrivateVehicleTransfer#4302c409-96f1-4660-9772-400875e5e2e2",
- "seller": {
- "$class": "composer.base.Person",
- "$id": "resource:composer.base.Person#dan",
- "ssn": "dan",
- "firstName": "Dan",
- "lastName": "Selman",
- "gender": "MALE",
- "nationalities": ["French", "UK"],
- "contactDetails": {
- "$class": "composer.base.ContactDetails",
- "email": "dan@acme.org",
- "address": {
- "$class": "composer.base.Address",
- "city": "Winchester",
- "country": "UK",
- "region": "England"
- }
- }
- },
- "buyer": {
- "$class": "composer.base.Person",
- "$id": "resource:composer.base.Person#anthony",
- "ssn": "anthony",
- "firstName": "Anthony",
- "lastName": "Smith",
- "gender": "MALE",
- "nationalities": ["French"],
- "contactDetails": {
- "$class": "composer.base.ContactDetails",
- "email": "anthony@acme.org",
- "address": {
- "$class": "composer.base.Address",
- "city": "Paris",
- "country": "France",
- "region": "IDF"
- }
- }
- },
- "specialNotes": "Dan selling a car to Anthony Smith",
- "vehicle": {
- "$class": "org.vda.Vehicle",
- "$id": "resource:org.vda.Vehicle#156478954",
- "vin": "156478954",
- "vehicleDetails": {
- "$class": "org.vda.VehicleDetails",
- "make": "Arium",
- "modelType": "Nova",
- "colour": "white",
- "vin": "156478954",
- "taxationClass": "PETROL_CAR"
- },
- "vehicleStatus": "ACTIVE",
- "owner": "resource:composer.base.Person#dan",
- "logEntries": [{
- "$class": "org.vda.VehicleTransferLogEntry",
- "vehicle": "resource:org.vda.Vehicle#156478954",
- "buyer": "resource:composer.base.Person#dan",
- "timestamp": "2017-07-30T13:57:13.652Z"
- }]
- },
- "transactionId": "4302c409-96f1-4660-9772-400875e5e2e2",
- "timestamp": "2017-07-30T13:57:23.121Z"
- }
- }
决策服务的 XOM 应支持此有效负载。Hyperledger Composer 首先序列化对象,然后通过 ID 引用已序列化的对象。XOM 中的具体 JSON 注释可用于处理对象图去序列化。参见
项目的代码。
- vehicle
- -
- lifecycle
- -
- xom
确保调用了决策服务的正确版本,因为决策逻辑的演化可能独立于智能合约中的代码。区块链网络中的所有节点都必须使用决策逻辑的同一个版本。生命周期示意图中描述了一种管理决策逻辑版本的方式。
决策服务返回一个描述决策操作的 JSON 文档。如果输入 JSON 文档的格式取决于 Hyperledger Composer 和区块链应用程序数据模型的格式,那么答案的格式是自由的,并受 IBM ODM 决策服务的控制。在本文中的示例中,如果有可疑的交易,决策服务会返回一个类似以下代码的 JSON 有效负载:
- {
- "status": "SUSPICION",
- "message": "Cross Border Suspicious Transfer: please double check buyer regulation"
- }
根据决策服务所制定的业务决策,交易处理器使用此响应来处理交易。在下面的示例中,决策的结果写入到了
资产中。
- Vehicle
- .
- then
- (
- function
- (
- response
- )
- {
- if (response.body.result['status'] != null) {
- if (response.body.result.status === "REJECTED") {
- vehicle.suspiciousMessage = "REJECTED: " + response.body.result.message;
- } else if (response.body.result.status === "SUSPICION") {
- vehicle.suspiciousMessage = response.body.result.message;
- }
- }
- }
决策逻辑是作为常规 IBM ODM 决策服务来实现的。 可以为一个决策服务定义多个入口点,以适应需要在智能合约中委托给 IBM ODM 的不同业务决策。一个入口点(对应于 IBM ODM 中的一个决策操作)是一个专门的规则集,它拥有一个签名并包含表示为业务规则的决策逻辑。
决策的输入参数通常是一个来自 Hyperledger Composer 的交易,引用了完成决策所需的资产、参与者或历史交易。如果要传递更多数据,则需要在 Hyperledger Composer 中建模一个专门的资源对象(一个资产或概念),并将它填充到 Transaction Processor 中,然后再调用决策服务。
输出参数是一个对象,它包含需要返回给智能合约的决策和任何数据。
在本文的样本中,决策操作按照下图中所示的方式来定义入口点:
点击查看大图
在调用
API 时,通过这个决策操作创建的 REST API 支持由 Hyperledger Composer 序列化的 JSON 输入。
- post
输出参数是一个包含
和
- status
的数据结构,由业务规则填充,并以 JSON 文档形式返回给调用方。
- message
样本中的决策逻辑很简单:一个规则流(包含一条业务规则)和一个决策表,如下面的 3 个屏幕截图所示。
IBM ODM Rule Designer 中的规则流:
点击查看大图
IBM ODM Rule Designer 中的业务规则:
点击查看大图
IBM ODM Rule Designer 中的决策表:
点击查看大图
IBM ODM 支持您需要的任何复杂程度的决策逻辑。由数千乃至数万条规则组成的决策逻辑很常见,而且很容易受到 IBM ODM 支持。本文中的样本主要使用 Rule Designer 来创造决策逻辑,但也可以使用 Decision Center 定义并管理业务逻辑。未来有望看到介绍利用 Decision Composer 实现决策逻辑和协作管理业务规则生命周期的内容。
请注意,完全可以在 IBM ODM BOM 编辑器中指定规则中使用的业务词汇表。例如,在此样本中,Hyperledger Composer 提供的数据模型非常冗长,包含多级嵌套。BOM 已进行了调节,能实现简洁的短语来隐藏这种复杂性。在样本中,
概念有一个额外的
- Person
方法,它隐藏了查找国家信息的底层复杂性,如下面的屏幕截图所示:
- getCountry()
点击查看大图
区块链是一个运行时环境,根据设计,在该环境中,通过智能合约处理的交易是由机制进行分配并控制的,以此确保账本一致性和安全性。
将交易提交到 Hyperledger Fabric 后,会将它们分派到区块链网络的所有节点,并应用智能合约的多个实例来处理交易。这些智能合约的所有实例都必须返回它们控制的资产的一组相同更新,而且它们必须采取关于交易的有效性的相同决策。所以这里的要点是,所有节点都将决策逻辑的同一个版本委托给 IBM ODM。此外,就像无法在区块链内篡改智能合约代码一样,无人能篡改业务规则也很重要。
出于这两个原因,无法采用 IBM ODM 中通常使用的典型部署流程来部署决策逻辑的新版本。因为所有节点都有自己的隐藏且私有的 Rule Execution Server 实例,所以从 Rule Execution Server Console、Rule Designer 或 Decision Center(或通过 IBM ODM API 中的任何其他集中管理的 API)执行部署不适合区块链用例。
样本包含一种专用的部署机制,该机制使用区块链的特性来确保所有节点都有相同的逻辑版本。
- vehicle - lifecycle
将特定的资产和交易添加到应用程序,以便存储和管理这些规则集。可以在
项目的
- vehicle - lifecycle
和
- odm.cto
中看到它们的实现。
- odm.js
决策逻辑的更新是作为区块链交易进行处理的。当决策逻辑发生更改时,IBM ODM 会生成规则集归档的新版本。此归档的二进制文件(以及它的版本号)通过一个交易提交到区块链,如以下代码所示:
- transaction
- RuleAppUpdated
- identified
- by
- transactionId
- {
- o String transactionId
- o String resDeployerURL
- // ruleapp name should be of the form <ruleapp>/<ruleset>
- o String ruleAppName
- o String ruleapp_version
- o String ruleset_version
- o String archive
- o String managedXomURI
- }
一个专用的交易处理器在每个区块链节点上处理交易。它执行以下 3 个操作:
- asset
- RuleApp
- identified
- by
- ruleAppId
- {
- o String ruleAppId
- // ruleapp name should be of the form <ruleapp>/<ruleset>
- o String ruleAppName
- o String ruleapp_version
- o String ruleset_version
- o String archive
- }
) 中:
- RuleAppCurrentVersion
- asset
- RuleAppCurrentVersion
- identified
- by
- ruleAppName
- {
- // ruleapp name should be of the form <ruleapp>/<ruleset>
- o String ruleAppName
- o String ruleapp_version
- o String ruleset_version
- }
facade 将 RuleApp 或规则集部署到节点的 Rule Execution Server,并传入
- Deployer
二进制文件及版本信息。
- Archive
为了知道使用了规则集的哪个版本,交易处理器利用这个特定资产来查找此信息,并在调用决策服务时使用它对 REST API 进行参数化。
如果某处出错且
交易需要回滚,也会回滚
- RuleAppUpdated
资产,并仍然使用决策服务的上一个版本。然后,将规则集的最新版本部署到 Rule Execution Server,但从不使用它。
- Current Version
可以调整此机制,避免将大型 RuleApps 二进制文件直接存储在账本中。账本可以存储 Ruleapp 的引用和一个哈希代码签名,智能合约可以使用该签名来检查是否修改了二进制文件。
请注意,决策逻辑高度依赖于支持业务规则的 XOM。样本中演示了一种将 XOM 部署到区块链中运行的各种 Rule Execution Server 的类似机制。
对智能合约使用 IBM ODM 的一个关键优势是,业务干系人可使用广泛的工具来管理和制约智能合约的决策逻辑。根据每周或者甚至每日的市场变化或其他因素,决策逻辑的演化速度通常比应用程序的剩余部分更快。
重要的是各参与方的代表能控制智能合约中的逻辑。如果智能合约实现了一个规定各方如何交换资产和价值的具体合约,各方必须在规则和生命周期上达成一致。
例如,各方可能决定一起评审规则,协商内容,并协商应部署这些规则的时间。此协议可能需要一个明确定义的制约流程,并由每方开展多级评审和批准。
IBM ODM 通过 Decision Center 及其业务控制台在此领域取得了突出成绩,如下图所示:
点击查看大图
尽管对于区块链平台,必须分布式地执行规则,但可以将管理环境集中在一起,使每方的业务干系人能够更容易地协作定义和管理其区块链应用程序的决策逻辑。
IBM ODM 的核心原则之一是将业务干系人(包括策略经理、分析师、律师、会计、审计员)集合在一起,为他们提供工具,以便按他们习惯的方式表达和制约应用程序的决策逻辑。
很快将有一篇文章重点介绍如何使用 Decision Center(和一个特定的 DevOps 流程)来管理并部署用 IBM ODM 实现的智能合约逻辑,敬请期待。
IBM ODM 非常适合表达和制约智能合约中的规则。定义智能合约时,业务干系人必须参与其中,而且通过将智能合约的规则与应用程序代码分离,来自双方的业务干系人都能使用 Decision Center 等工具协作定义和制约各种规则。他们也可以快速响应变化,避免耗时的代码库更新流程。
Vehicle Lifecycle 样本演示了如何结合使用 IBM ODM 和 Hyperledger Fabric “连锁”执行智能合约决策逻辑,并利用 IBM ODM 的企业级规则引擎。
在下一个区块链项目中,可以考虑对您的智能合约使用 IBM ODM。它天生就适合 Hyperledger Composer 和区块链环境。随着让业务干系人参与该流程,并寻找快速响应变化的方式,IBM ODM 的优势将变得特别重要。
我们渴望听到您的集成 IBM ODM 和区块链的体验,以及任何其他需求。
非常感谢 Hyperledger Composer 团队成员为这次集成提供极大的帮助和热情支持。尤其要感谢 IBM 区块链团队的 Simon Stone 的持续支持。
还要感谢 Laurent Grateau、Philippe Bonnard 和 Jeremy Pichon 贡献本文的样本,感谢 Peter Gilliver 和 Nicolas Sauterey 对本文的细心评审。
来源: http://www.ibm.com/developerworks/cn/java/java-language-polymorphism/index.html