Hyperledger getParticipants - node.js

function Exchange(exchange){
// We do the actual exchange here:
// We first need to get both actual nodes:
var nodeIdFrom=exchange.nodeIdFrom;
var quantity =exchange.quantity;
var price = exchange.price;
var nodeIdTo =exchange.nodeIdTo;
return getParticipantRegistry('org.acme.mynetwork.Node')
.then(function(ParticipantRegistry){
ParticipantRegistry.get(nodeIdFrom)
.then(function(Participant){
Participant.Need=Participant.Need+quantity;
Participant.Balance_account=Participant.Balance_account+quantity*price;
return ParticipantRegistry.update(Participant);
});
});
I'm trying to execute a transaction defined as:
transaction Exchange{
o String nodeIdFrom
o String nodeIdTo
o Double quantity
o Double Price
}
To execute a transaction (we take money somewhere and put it somewhere else). With only the ids of the nodes as a parameter.
But right now that function does not work, you can execute it on the playground but my node is not modified.
Is it possible to apply a transaction without giving node as Node (node is a Participant).

it should work - here's an example (Using a fictitious sample 'Trader' Network and like you, I have defined 'qty' as a 'Double' in the Transaction model definition itself) of updating an Asset by a specific identifier (you're doing something similar - Participant by ID) and then - updating the asset's quantity using the Promises chain below. Suggest to use console.log() for outputs too when debugging.
So - given Transaction model:
transaction TraderById {
o String tradeId
o String tradingSymbol
o Double qty
}
and an Asset modeled as:
asset Commodity identified by tradingSymbol {
o String tradingSymbol
o String description
o String mainExchange
o Double quantity
--> Trader owner
}
you can update the Asset quantity ('quantity') as follows:
/**
*
* #param {org.acme.trading.TraderById} tradeById - the trade to be processed
* #transaction
*/
function TradeById(tradeById){
var commodityRegistry;
return getAssetRegistry('org.acme.trading.Commodity')
.then(function(registry){
commodityRegistry=registry;
return commodityRegistry.get(tradeById.tradingSymbol);
})
.then(function(result){
result.quantity-=tradeById.qty;
return commodityRegistry.update(result);
});
}

Related

Hyperledger Composer - can't find transaction error

I am making a blockchain application using hyperledger composer and have written my cto, with on transaction, and the script file with no visible errors. However, when i try submit a transaction it returns this error: Error: Could not find any transactions to execute for org.evidence.net.evidenceDeposit.
Here is my CTO file:
namespace org.evidence.net
enum type {
o storage
o device
o physical
}
enum status {
o collected
o stored
o withdrawn
}
asset EvidenceItem identified by evidenceItemId {
o String evidenceItemId
o String caseNo
o type Type
o status Status
o String optionalHash optional
--> person Holder
}
abstract participant person identified by id {
o String id
o String firstName
o String lastName
}
participant Investigator extends person {
}
participant EvidenceManager extends person {
}
participant FRT extends person {
}
transaction evidenceDeposit {
--> EvidenceItem EvidenceItem
--> EvidenceManager EvidenceManager
}
event FirstDeposit {
o String evidenceItemId
o String id
}
And here is my script file:
/*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/**
* Transfer evidence from FRT to Evidence Manager
* #param (org.evidence.net.evidenceDeposit} tx - the evidenceDeposit transaction
* #transaction
*/
const NS = 'org.evidence.net';
async function evidenceDeposit(tx) {
// get asset registry for evidenceItem
const evidenceItemRegistry = await getAssetRegistry(NS + '.evidenceItem');
//Get participant registry for Evidence Manager
const EvidenceManagerRegistry = await getParticipantRegistry(NS + '.EvidenceManager');
const evidenceItem = await evidenceItemRegistry.get(tx.evidenceItem.getIdentifier());
//Make sure that the evidenceItem exists
if (!evidenceItem) {
throw new Error(' Evidence with id ${tx.evidenceItem.getIdentifier()} does not exist');
exit();
}
if (evidenceItem.status !== 'collected') {
throw new Error('Evidence with id ${tx.evidenceItem.getIdentifier()} is not in collected status');
}
// Get Evidence Manager ID
const EvidenceManagerID = tx.EvidenceManager.getIdentifier();
//Make sure Evidence Manager exists
const EvidenceManager = await EvidenceManagerRegistry.get(EvidenceManagerID);
if(!EvidenceManager) {
throw new Error('Evidence Manager with id ${EvidenceManagerID} does not exist');
}
//Update evidenceItem with new owner
tx.evidenceItem.holder = tx.EvidenceManager;
tx.evidenceItem.status = 'stored';
//Update the asset in the asset registry
await evidenceItemRegistry.update(tx.evidenceItem);
//Create deposit event
let FirstDepositEvent = getFactory().newEvent(NS, 'FirstDeposit');
FirstDepositEvent.evidenceItemId = tx.evidenceItem.evidenceItemId;
FirstDepositEvent.id = tx.EvidenceManager.id;
// Emit the Event
emit(FirstDepositEvent);
}
I have looked around and can't seem to find the problem. Any help is appreciated.
Please see the readme below as Hyperledger Composer has been deprecated for over a year.
https://github.com/hyperledger/composer/blob/master/README.md

Error when submitting transaction

I have a little bit unusual problem. Following code works in online playground, but id doesn't work when i'm using generated API on rest server deployed locally. When trying to post transaction i get an error.
cto file:
namespace org.dps.track
asset Item identified by itemId{
o String itemId
o String name
o String idgId
o String serialNumber
o String comment
--> BU owner
--> Item [] items optional
}
participant BU identified by buId{
o String buId
o String name
o String country
o String city
}
participant Assembler extends BU{
}
participant Manufacturer extends BU{
}
transaction Trade{
--> Item item
--> BU newOwner
}
enum status{
o IN_TRANSIT
o DEPARTURED
o DELIVERED
}
chaincode:
/**
* Sample transaction processor function.
* #param {org.dps.track.Trade } trade - the sample transaction instance.
* #transaction
*/
async function tradeCommodity(trade) {
const factory = getFactory();
trade.item.owner = trade.newOwner;
var list = [];
if (trade.item.items && trade.item.items.length > 0) {
trade.item.items.forEach((asset) => {
list.push(asset);
});
}
const assetRegistry = await getAssetRegistry('org.dps.track.Item');
// persist the state of the current ITEM
await assetRegistry.update(trade.item);
for (var i = 0; i < list.length; ++i) {
let res = await assetRegistry.get(list[i].getIdentifier());
res.owner = factory.newRelationship('org.dps.track', 'Assembler', trade.newOwner.getIdentifier());
// persist the state of the ITEM with new owner as a relationship
await assetRegistry.update(res);
}
}
When trying to post transaction via Rest API i get error:
{
"error": {
"statusCode": 500,
"name": "Error",
"message": "Error trying invoke business network. Error: No valid responses from any peers.\nResponse from attempted peer comms was an error: Error: transaction returned with failure: Error: Could not find any functions to execute for transaction org.dps.track.Trade#e4764be8e037c7186774512860c0cde6d7eaed5c301ddf36c4c1ab560577861a",
"stack": "Error: Error trying invoke business network. Error: No valid responses from any peers.\nResponse from attempted peer comms was an error: Error: transaction returned with failure: Error: Could not find any functions to execute for transaction org.dps.track.Trade#e4764be8e037c7186774512860c0cde6d7eaed5c301ddf36c4c1ab560577861a\n at HLFConnection.invokeChainCode (/home/bryczek/.nvm/versions/node/v8.11.3/lib/node_modules/composer-rest-server/node_modules/composer-connector-hlfv1/lib/hlfconnection.js:1002:30)\n at <anonymous>"
}
}
Has anyone an idea what is wrong? I would be really thankful for help.
Your problem is your model file, not the transaction code. You need Assembler not BU in the relationship field for Item and for Trade
Your asset should be:
asset Item identified by itemId{
o String itemId
o String name
o String idgId
o String serialNumber
o String comment
--> Assembler owner
--> Item [] items optional
}
as Assembler is the resource class (not BU, which is an extended class - there is no registry for this).
Your transaction Trade should also reflect the same resource ie (not BU) :
transaction Trade{
--> Item item
--> Assembler newOwner
}
Other than that, it should work fine with your existing code (have tested it against a Fabric network, using the following example Trade transaction in my REST API, where previous owner was Assembler#1 and it changes related Items from the items array for Item #1)
{
"$class": "org.dps.track.Trade",
"item":"resource:org.dps.track.Item#1",
"newOwner":"resource:org.dps.track.Assembler#2"
}
I modified model file and now whe n trying to generate rest API i only get System(General business network methods), no Item, BU and Trade API, why is this happening?
cto:
/**
* New model file
*/
namespace org.dps.track
//asset section
asset Item identified by itemId{
o String itemId
o String name
o String idgId
o String serialNumber
o String comment
--> BU owner
--> Item [] items optional
}
//participant section
participant BU identified by buId{
o String buId
o String name
o String country
o String city
o participantType type
}
//tranasaction section
transaction Trade{
-->Item item
-->BU newOwner
}
enum status {
o IN_TRANSIT
o DEPARTURED
o DELIVERED
}
enum participantType{
o Manufacturer
o Assembler
}
cc:
/**
* Sample transaction processor function.
* #param {org.dps.track.Trade } trade - the sample transaction instance.
* #transaction
*/
async function tradeCommodity(trade) {
const factory = getFactory();
trade.item.owner = trade.newOwner;
var list = [];
if (trade.item.items && trade.item.items.length > 0) {
trade.item.items.forEach((asset) => {
list.push(asset);
});
}
const assetRegistry = await getAssetRegistry('org.dps.track.Item');
// persist the state of the current ITEM
await assetRegistry.update(trade.item);
for (var i = 0; i < list.length; ++i) {
let res = await assetRegistry.get(list[i].getIdentifier());
res.owner = factory.newRelationship('org.dps.track', 'BU', trade.newOwner.getIdentifier());
// persist the state of the ITEM with new owner as a relationship
await assetRegistry.update(res);
}
}

How to update values from an asset in hyperledger

model
asset Route identified by route_id {
o String route_id
o String rider_id
o String parcel_id
}
transaction assignParcelToRider {
o String rider_id
o String parcel_id
}
logic.js
var assetRegistry;
var id = assignValue.rider_id;
return getAssetRegistry('org.rytle.Route').then(function(ar) {
assetRegistry = ar;
return assetRegistry.get(id);
}).then(function(asset) {
asset.parcel_id = assignValue.parcel_id;
return assetRegistry.update(asset);
});
Here I want to find the rider_id and update parcel_id there. But here its not finding the rider_id.
The main thing is you need to get the asset, by the asset identifier when using .get() and rider_id is not that, in your model.
Also - may need more info - but it all rests on id getting a value from assignValue.rider_id and I can't tell how that was defined / asserted and whether it is within scope. I can see that id however, should be in scope for your function below - but using the correct identifier for an asset, this should work (as an example):
return getAssetRegistry('org.rytle.Route').then(function(ar) {
return ar.get(route_id) // or whatever you've assigned it to or txnobject.route.getIdentifier()); // ie you must get the asset by identifier
}).then(function(asset) {
asset.parcel_id = id;
return ar.update(asset);
});
and so on;
ps you can check out sample-networks for some examples (eg under 'test' directory) - note these now use async / await functions (instead of 'promises' shown above) which came in with Node 8 (and is far easier to write than using promises FYI)

One to many relationship between two assets hyperledger composer

I am trying a test a use case where I have taken two assets: a car and parts. I want to link the car with different instances of parts using a transaction. My model and js files are below :
namespace org.sample.test
asset Part identified by partId {
o String partId
o String partName
o String partManufacturer
}
asset Car identified by Vin {
o String Vin
--> Part part optional
o String modelNumber
}
transaction MakeCar{
o String carid
o String carmodel
o String[] PartId
}
/**
* Sample transaction processor function.
* #param {org.sample.test.MakeCar} tx The sample transaction instance.
* #transaction
*/
async function makecar(tx) { // eslint-disable-line no-unused-vars
var factory = getFactory();
var vehicle = factory.newResource('org.sample.test','Car',tx.carid);
vehicle.modelNumber = tx.carmodel;
var part = factory.newRelationship('org.sample.test','Part',tx.PartId);
vehicle.part = part;
const assetRegistry = await getAssetRegistry('org.sample.test.Car');
await assetRegistry.add(vehicle);
// Update the asset in the asset registry.
}
I also tried first creating the asset using the getfactory then creating relations by traversing partIds one by one using array but then as my Car asset is not created yet its throwing error.
I updated my transaction fucntion :
async function makecar(tx) { // eslint-disable-line no-unused-vars
var factory = getFactory();
var part;
var vehicle = factory.newResource('org.sample.test','Car',tx.carid);
vehicle.modelNumber = tx.carmodel;
var i=0;
while (i<tx.PartId.length)
{
part = factory.newRelationship('org.sample.test','Part',tx.PartId[i]);
vehicle.part = part;
i++;
}
assetRegistry = await getAssetRegistry('org.sample.test.Car');
await assetRegistry.add(vehicle);
}
Now its giving error : t: Instance org.sample.test.Car#OOOO has property part with type org.sample.test.Part that is not derived from org.sample.test.Part[]
the problem is this line:
var part = factory.newRelationship('org.sample.test','Part',tx.PartId);
it should be [something like]:
var part = factory.newRelationship('org.example.trading','Part',tx.PartId[0]); // 1st element of an array
its because you've defined tx.PartId as an array of relationships in your transaction definition, so you need to access the relevant element.
At this point, I'm not sure how you want to move forward, but your Car (vehicle) asset has an optional one to one relationship with Part (part Id) which is the optional field in your model. Perhaps it needs to be an array of relationships ? -> Part[] part optional But replacing the line above, will at least have it working, in its present form. An example of using an array of relationships is shown in the answer in this SO: -> Creating new participant and adding array of assets by reference to it (in particular :shares array in the model there)

Hyperledger Composer - ACL Rule with function in condition

I'm trying to write a little complexer logic in the condition of an ACL Rule as always the p.getIdentifier() == r.getIdentifier(), because in my fault it isn't possible.
These are my models:
participant Customer identified by customerID {
o String customerID
o String name
...
}
asset A identified by aID {
o String aID
--> Customer customer
}
asset B identified by bID {
o String bID
--> A a
}
Now I want to give the Customer access to see all B assets, but only where the relationship to A references to an asset, which have a relatinship to the actual participant of Customer, who is "logged in".
Summarized logic: From asset B to A, and then from A to Customer.
So in this case I can't compare the identifiers of Customer and B directly and have to go over A. Therefore I wanted to evaulate the access with a function which is called in the script.js file:
rule CustomerAccessCustomer {
description: "The customer should see all B assets, but only when he have a relationship in asset A "
participant(p): "org.xxx.test.participant.Customer"
operation: READ
resource(r): "org.xxx.test.asset.B"
condition: (evaluateAccess(p,r))
action: ALLOW
}
Here is the function of the script.js:
async function evaluateAccess(p,r) {
try {
const bRegistry = await getAssetRegistry('org.xxx.test.asset.B');
const b = await bRegistry.get(r.getIdentifier());
const aRegistry = await getAssetRegistry('org.xxx.test.asset.A');
const a = await aRegistry.get(b.a.getIdentifier());
if (p.getIdentifier() === a.customer.getIdentifier()) {
return true;
}
} catch (error) {
console.log(error);
}
}
But I get an error Error: The runtime API is not available.
Do I think the wrong way, isn't it possible to evaluate access with a function?
How did you handle access rule if you can't just compare the identifiers?
you should just be able to do:
rule CustomerAccessCustomer {
description: "The customer should see all B assets, but only when he have a relationship in asset A "
participant(p): "org.xxx.test.participant.Customer"
operation: READ
resource(r): "org.xxx.test.asset.B"
condition: ( (p.getIdentifier() === r.a.customer.getIdentifier())
action: ALLOW
}
but p would also need READ access already to be able to 'read' Asset resource 'A' (to check the identifier etc) in the first place :-)
The customer should be participant not asset:
participant Customer identified by customerID {
o String customerID
o String name
}

Resources