【问题标题】:Submitting a transaction via RESTful API (how to handle transactionid and timestamp)通过 RESTful API 提交交易(如何处理 transactionid 和时间戳)
【发布时间】:2018-08-18 01:05:25
【问题描述】:

问题: 我无法通过 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)"
  }
}

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

请注意,在 Playground 中,未指定“transactionId”和“timestamp”,因为 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 实例无效?我的第一个想法是它不喜欢我放在“transactionId”中的字符串,但另一个 Stack Overflow 帖子指出 transactionId 只是我已经生成的任意 UUIDv4 字符串。

更新 #1:即使使用默认演示也失败

为了确保 BNA 没有错误,我已将默认 carauction-demo(与我的示例非常相似)部署到我的本地 Hyperledger Fabric 实例上,并部署了 composer-rest-server。我还在 Playground 中部署了相同的 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)"
  }
}

我仍然不知道这里出了什么问题。

【问题讨论】:

    标签: hyperledger hyperledger-fabric hyperledger-composer


    【解决方案1】:

    经过大量实验和搜索,我得出的结论是,问题在于 NPM 是使用 sudo(以 root 身份)安装的。我以非root身份重新安装,现在问题已经解决。一切都按预期进行。

    【讨论】:

    • 您是只重新安装了 npm 还是必须重新安装整个超级账本结构?
    【解决方案2】:

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

    【讨论】:

    • 感谢并感谢您的帮助。删除 transactionId 字符串后,我会收到错误状态代码 500,“尝试调用链代码时出错。错误:链代码错误(状态:500,消息:错误:ID 为“字符串”的对象在 ID 为“资产:org”的集合中。 acme.purchasing.HouseListing' 不存在)”。似乎它仍在期待一个字符串对象。
    • 听起来像是在尝试更新尚未正确指定的资产,例如完全合格或不存在的 id?我看到列表(在交易中)与之前定义(但未在此处发布)的 Asset HouseListing 有关系......并且您可能仍然有实例。
    • 是的,该资产的实例当前仍然存在。作为测试,我已将默认 carauction-network BNA 部署到我的超级账本实例并执行 composer-rest-server。同样,将这个 BNA 部署到 Playground,我能够成功地创建资产、参与者并执行 Offer 交易。当我尝试通过 RESTful API Explorer 执行相同操作时,我可以创建资产和参与者,但在尝试执行 Offer 事务时失败(错误状态 500)。是否有人通过 Explorer 在 carauction-network 上执行了 Offer 交易,或者这是一个错误?
    【解决方案3】:

    所以我已经成功执行了 Offer 交易 (/POST)。我认为“500”错误是因为缺少字段(“字符串”类型),或者您的报价交易中通过 REST 的关系。

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

    这些使用 /POST 的 Offer 交易在 Explorer 中都是成功的:

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

    {
      "$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"
    }
    

    在 Explorer 中以 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 创建了资产

    【讨论】:

    • 再次感谢您的帮助,我现在也能够成功执行交易。原来是用root安装npm。一旦我用自己的用户名安装了 npm,一切都很好。肯定有访问问题,但我的问题现在已经解决了!
    猜你喜欢
    • 2020-07-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多