Отправка транзакции через RESTful API (как обрабатывать идентификатор транзакции и временную метку)

Проблема: я не могу выполнить POST транзакцию через RESTful API, созданный composer-rest-server. Я получаю statusCode 422; экземпляр транзакции недействителен. Однако тот же пример работает в Playground.

Сценарий. Я настроил транзакцию под названием Offer в моем файле .cto, которая публикует предложение о покупке дома:

// 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 сгенерировал API со следующей строкой JSON для публикации транзакции типа 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 «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"
}

Может ли кто-нибудь посоветовать, почему он говорит, что экземпляр предложения недействителен? Моя первая мысль заключалась в том, что мне не нравится строка, которую я помещаю в "transactionId", но в другом сообщении о переполнении стека указывается, что transactionId - это просто произвольная строка UUIDv4, которую я уже сгенерировал.

Обновление №1: сбой даже при демонстрации по умолчанию

Чтобы гарантировать, что BNA не содержит ошибок, я развернул демо-версию carauction-demo по умолчанию (очень похожую на мой пример) на моем локальном экземпляре Hyperledger Fabric и развернул composer-rest-server. Я также развернул тот же самый BNA в Playground. Все активы и участники были созданы одинаково как из проводника (локальный экземпляр), так и из игровой площадки. Когда приходит время отправлять транзакцию с предложением:

{
  "$class": "org.acme.vehicle.auction.Offer",
  "bidPrice": 800,
  "listing": "resource:org.acme.vehicle.auction.VehicleListing#L001",
  "member": "resource:org.acme.vehicle.auction.Member#[email protected]"
}

Этот JSON был сгенерирован игровой площадкой и преуспел там. Копирование / вставка / выполнение в проводнике дает ошибку статуса 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)"
  }
}

Я все еще не понимаю, что здесь не так.


person Community    schedule 21.07.2017    source источник


Ответы (3)


После долгих экспериментов и поисков я пришел к выводу, что проблема в том, что NPM был установлен с использованием sudo (от имени пользователя root). Я переделал установку как некорневой, и теперь проблема решена. Все работает как положено.

person Community    schedule 24.07.2017
comment
вы переустанавливали только npm, или вам пришлось переустанавливать всю структуру Hyperledger? - person deltu100; 21.05.2019

Composer обновляет сам transactionId как сгенерированный, вы не можете сделать это в своем JSON и, следовательно, почему вы получаете ошибку. Это проблема преобразования Loopback -> Swagger, поскольку она не должна появляться в операции / POST REST - зафиксировано здесь https://github.com/hyperledger/composer/issues/663

person Paul O'Mahony    schedule 21.07.2017
comment
Спасибо и ценим помощь. После удаления строки transactionId я получаю сообщение об ошибке statusCode 500, ошибка при попытке вызвать цепной код. Ошибка: ошибка цепного кода (статус: 500, сообщение: Ошибка: объект с идентификатором 'string' в коллекции с идентификатором 'Asset: org.acme.purchasing.HouseListing' не существует). Похоже, он все еще ожидает строковый объект. - person ; 21.07.2017
comment
Похоже, это попытка обновить актив, который либо не был указан должным образом, например, полностью квалифицирован, либо идентификатор для которого не существует? Я вижу, что этот листинг (в транзакции) имеет отношение к Asset HouseListing, определенному (но не размещенному здесь) ранее ... и, предположительно, у вас все еще есть экземпляры. - person Paul O'Mahony; 24.07.2017
comment
Да, экземпляр для этого актива все еще существует. В качестве теста я развернул стандартную сеть BNA carauction-network в моем экземпляре Hyperledger и выполнил composer-rest-server. Опять же, развернув этот BNA на Playground, я смог успешно создавать активы, участников и выполнять транзакции с предложениями. Когда я пытаюсь сделать то же самое с помощью RESTful API Explorer, я могу создавать активы и участников, но не могу выполнить транзакции с предложениями (статус ошибки 500). Выполнял ли кто-нибудь транзакцию с предложением в carauction-network через проводник или это ошибка? - person ; 24.07.2017

Итак, я успешно выполнил транзакции с предложениями (/ POST). Я думаю, что ошибка «500» связана с отсутствием поля (типа «строка») или отношения в вашей транзакции предложения через REST.

На примере сети автомобильных аукционов https://github.com/hyperledger/composer-sample-networks/blob/master/packages/carauction-network/models/auction.cto

Любая из этих транзакций предложения с использованием / POST была успешной в Explorer:

{
  "$class": "org.acme.vehicle.auction.Offer",
  "bidPrice": 20,
  "listing": "org.acme.vehicle.auction.VehicleListing#100",
  "member": "org.acme.vehicle.auction.Member#[email protected]"
 }

OR

{
  "$class": "org.acme.vehicle.auction.Offer",
  "bidPrice": 20,
  "listing": "org.acme.vehicle.auction.VehicleListing#100",
  "member": "org.acme.vehicle.auction.Member#[email protected]",
  "timestamp": "2017-07-28T14:07:02.558Z"
}

ответил 200 (УСПЕХ) и transactionId в проводнике:

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

Это мой актив JSON для списка транспортных средств для № 100 выше.

{
  "$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#[email protected]",
      "transactionId": "string123",
      "timestamp": "2017-07-28T14:07:02.825Z"
    }
  ],
  "vehicle": "resource:org.acme.vehicle.auction.Vehicle#123"
}

И я создал актив для Vehicle 123, а также для члена [email protected]

person Paul O'Mahony    schedule 28.07.2017
comment
Еще раз спасибо за вашу помощь в этом, и я тоже смог успешно выполнить транзакции сейчас. Оказалось, что npm устанавливается с рутом. Как только я установил npm под своим именем пользователя, все было в порядке. Должно быть, возникла проблема с доступом, но теперь моя проблема решена! - person ; 30.07.2017