通过RESTful API提交事务(如何处理transactionid和timestamp)

时间:2017-07-21 14:28:07

标签: hyperledger hyperledger-fabric hyperledger-composer

问题: 我无法通过composer-rest-server生成的RESTful API发布事务。我收到statusCode 422;事务实例无效。但是,相同的示例适用于Playground。

情境: 我在我的.cto文件中设置了一个名为Offer的交易,该交易发布了买房的提议:

// Offer - Specifies an offer that a bidder places on a house listing with an associated price

transaction Offer {
  o Double bidPrice
  --> HouseListing listing
  --> Person bidder
}

composer-rest-server生成了一个带有以下JSON字符串的API,用于发布Offer类型的事务:

{
  "$class": "org.acme.purchasing.Offer",
  "bidPrice": 0,
  "listing": "string",
  "bidder": "string",
  "transactionId": "string",
  "timestamp": "2017-07-21T13:37:09.460Z"
}

我已经使用以上示例派生的以下JSON代码将其替换为示例事务:

{
  "$class": "org.acme.purchasing.Offer",
  "bidPrice": 1000,
  "listing": "001",
  "bidder": "RJOHNSON",
  "transactionId": "1b9aa63c-dfad-4aad-a610-dfc80f2796b2",
  "timestamp": "2017-07-21T13:37:09.460Z"
}

返回的响应是错误代码422:

{
  "error": {
    "statusCode": 422,
    "name": "ValidationError",
    "message": "The `Offer` instance is not valid. Details: `transactionId` can't be set (value: \"1b9aa63c-dfad-4aad-a610-d...6b2\").",
    "details": {
      "context": "Offer",
      "codes": {
        "transactionId": [
          "absence"
        ]
      },
      "messages": {
        "transactionId": [
          "can't be set"
        ]
      }
    },
    "stack": "ValidationError: The `Offer` instance is not valid. Details: `transactionId` can't be set (value: \"1b9aa63c-dfad-4aad-a610-d...6b2\").\n    at /usr/lib/node_modules/composer-rest-server/node_modules/loopback-datasource-juggler/lib/dao.js:355:12\n    at ModelConstructor.<anonymous> (/usr/lib/node_modules/composer-rest-server/node_modules/loopback-datasource-juggler/lib/validations.js:566:11)\n    at ModelConstructor.next (/usr/lib/node_modules/composer-rest-server/node_modules/loopback-datasource-juggler/lib/hooks.js:93:12)\n    at ModelConstructor.<anonymous> (/usr/lib/node_modules/composer-rest-server/node_modules/loopback-datasource-juggler/lib/validations.js:563:23)\n    at ModelConstructor.trigger (/usr/lib/node_modules/composer-rest-server/node_modules/loopback-datasource-juggler/lib/hooks.js:83:12)\n    at ModelConstructor.Validatable.isValid (/usr/lib/node_modules/composer-rest-server/node_modules/loopback-datasource-juggler/lib/validations.js:529:8)\n    at /usr/lib/node_modules/composer-rest-server/node_modules/loopback-datasource-juggler/lib/dao.js:351:9\n    at doNotify (/usr/lib/node_modules/composer-rest-server/node_modules/loopback-datasource-juggler/lib/observer.js:155:49)\n    at doNotify (/usr/lib/node_modules/composer-rest-server/node_modules/loopback-datasource-juggler/lib/observer.js:155:49)\n    at doNotify (/usr/lib/node_modules/composer-rest-server/node_modules/loopback-datasource-juggler/lib/observer.js:155:49)\n    at doNotify (/usr/lib/node_modules/composer-rest-server/node_modules/loopback-datasource-juggler/lib/observer.js:155:49)\n    at Function.ObserverMixin._notifyBaseObservers (/usr/lib/node_modules/composer-rest-server/node_modules/loopback-datasource-juggler/lib/observer.js:178:5)\n    at Function.ObserverMixin.notifyObserversOf (/usr/lib/node_modules/composer-rest-server/node_modules/loopback-datasource-juggler/lib/observer.js:153:8)\n    at Function.ObserverMixin._notifyBaseObservers (/usr/lib/node_modules/composer-rest-server/node_modules/loopback-datasource-juggler/lib/observer.js:176:15)\n    at Function.ObserverMixin.notifyObserversOf (/usr/lib/node_modules/composer-rest-server/node_modules/loopback-datasource-juggler/lib/observer.js:153:8)\n    at Function.ObserverMixin._notifyBaseObservers (/usr/lib/node_modules/composer-rest-server/node_modules/loopback-datasource-juggler/lib/observer.js:176:15)"
  }
}

现在奇怪的是,我已经将相同的BNA部署到Hyperledger Composer Playground上,并且能够成功执行Offer类型的交易。

请注意,在Playground中,&#34; transactionId&#34;和&#34;时间戳&#34;未指定,因为Playground似乎处理这些值。例如,这就是Playground最初向我提出的建议:

{
  "$class": "org.acme.purchasing.Offer",
  "bidPrice": 0,
  "listing": "resource:org.acme.purchasing.HouseListing#id:7965",
  "bidder": "resource:org.acme.purchasing.Person#id:4441"
}

有人可以建议为什么它说Offer实例无效?我的第一个想法是,它不喜欢我放置在&#34; transactionId&#34;但是另一个Stack Overflow帖子指出transactionId只是我已经生成的任意UUIDv4字符串。

更新#1:默认演示失败

为了确保BNA没有错误,我已将默认的carauction-demo(与我的示例紧密相似)部署到我的本地Hyperledger Fabric实例上并部署了composer-rest-server。我还将相同的BNA部署到了游乐场。所有资产和参与者在Explorer(本地实例)和Playground中都创建了相同的内容。在提交要约交易时:

{
  "$class": "org.acme.vehicle.auction.Offer",
  "bidPrice": 800,
  "listing": "resource:org.acme.vehicle.auction.VehicleListing#L001",
  "member": "resource:org.acme.vehicle.auction.Member#member3@acme.org"
}

这个JSON由Playground生成并在那里成功。复制/粘贴/执行到资源管理器会产生状态500错误。

{
  "error": {
    "statusCode": 500,
    "name": "Error",
    "message": "error trying invoke chaincode. Error: chaincode error (status: 500, message: Error: Object with ID 'string' in collection with ID 'Asset:org.acme.vehicle.auction.VehicleListing' does not exist)",
    "stack": "Error: error trying invoke chaincode. Error: chaincode error (status: 500, message: Error: Object with ID 'string' in collection with ID 'Asset:org.acme.vehicle.auction.VehicleListing' does not exist)\n    at _initializeChannel.then.then.then.then.catch (/usr/lib/node_modules/composer-rest-server/node_modules/composer-connector-hlfv1/lib/hlfconnection.js:806:34)"
  }
}

我仍然迷失在这里的错误。

3 个答案:

答案 0 :(得分:1)

经过多次实验和一些搜索,我得出结论,问题是NPM是使用sudo(作为root)安装的。我将安装重新编译为非root用户,问题现在已经解决了。一切都按预期工作。

答案 1 :(得分:0)

Composer将transactionId本身更新为生成的,您不能在JSON中执行此操作,因此会出现错误原因。这是一个Loopback - &gt; Swagger转换问题,因为它不应出现在/ POST REST操作中 - 在此处捕获https://github.com/hyperledger/composer/issues/663

答案 2 :(得分:0)

所以我已经成功执行了Offer事务(/ POST)。我认为&#39; 500&#39;错误是因为通过REST在您的商品交易中存在缺少字段(&#39;字符串&#39;类型)或关系。

使用汽车拍卖网络https://github.com/hyperledger/composer-sample-networks/blob/master/packages/carauction-network/models/auction.cto

的示例

使用/ POST的这些商品交易中的任何一个在资源管理器中都是成功的:

{
  "$class": "org.acme.vehicle.auction.Offer",
  "bidPrice": 20,
  "listing": "org.acme.vehicle.auction.VehicleListing#100",
  "member": "org.acme.vehicle.auction.Member#a@b.com"
 }

OR

{
  "$class": "org.acme.vehicle.auction.Offer",
  "bidPrice": 20,
  "listing": "org.acme.vehicle.auction.VehicleListing#100",
  "member": "org.acme.vehicle.auction.Member#a@b.com",
  "timestamp": "2017-07-28T14:07:02.558Z"
}

在资源管理器中以200(SUCCESS)和transactionId响应:

{
  "$class": "org.acme.vehicle.auction.Offer",
  "bidPrice": 20,
  "listing": "org.acme.vehicle.auction.VehicleListing#100",
  "member": "org.acme.vehicle.auction.Member#a@b.com",
  "transactionId": "e75b9934-1f08-4daf-90db-702bbe4b8fa1"
}

这是上面#100的我的VehicleListing资产JSON

{
  "$class": "org.acme.vehicle.auction.VehicleListing",
  "listingId": "100",
  "reservePrice": 50,
  "description": "string",
  "state": "FOR_SALE",
  "offers": [
    {
      "$class": "org.acme.vehicle.auction.Offer",
      "bidPrice": 50,
      "listing": "100",
      "member": "resource:org.acme.vehicle.auction.Member#a@b.com",
      "transactionId": "string123",
      "timestamp": "2017-07-28T14:07:02.825Z"
    }
  ],
  "vehicle": "resource:org.acme.vehicle.auction.Vehicle#123"
}

我为Vehicle 123以及会员a@b.com创建了资产