Let's say I have a business network v1.0.0 which has a Participant with the following model:
participant Member identified by memberId {
o String memberId
o String firstName
}
After deploying the network I create a Member.
Later I want to add a field to the Member model. E.g.
participant Member identified by memberId {
o String memberId
o String firstName
o String lastName
}
So I create new network and upgrade the previous one:
composer network upgrade -c peeradmin#hlfv1 -n example-netowrk -V 2.0.0
What happens to the member I created before? Is it deleted? How can I keep that in the system and continue to use it and update it's information by only adding lastName?
The evolution of model definitions is described in the documentation here
https://hyperledger.github.io/composer/latest/reference/model-compatibility and should answer your question.
when you change the model, your api will change as well to reflect the changes. Your data won't disappear, it can't as it's on the ledger, but it won't have the new fields you added.
Once your new model is deployed you can then issue a GET request to that asset, this gives you all the existing data, you populate the new field with whatever you need and issue a PUT request on that asset. This will now give you an old asset with the new data.
Of course, I suggest you think carefully how you change existing assets. I am thinking here of a policy which says you should not rename anything, you should not delete anything. all you should do is add new properties. If you start messing around with renaming and deleting, this is bound to cause issue, especially in a production environment.
Related
I need to perform soft deletion using jhipster.
Ex:
If user click on delete button I need to mark is_active flag to false.
Writing custom code will be the only solution or is there any way to do it?
Things I have done so far :
I have followed Jhipster web site and created Monolithic application.
Then I have created new entity called 'Student' using the entity sub-generator . (filed names : id, name age, address and is_active. )
The Sub generator generated files contain all the basic CRUD operations and provided a CRUD front-end for student entity.
The front end contains buttons for create student, view, edit and delete.
When I Click on a delete button the studuent record will be permanatly delete from the database.
But my Requirement is to keep the record in the database and mark only the is_active filed in to false.
Basically I need to keep history data of the student without permanatly deleting them.
you will have to edit it yourself. First of all, I recommend you to extend all classes generated by JHipster (except for Resources, you will have to create another class and use a custom mapping thus changing the service in the frontend)
Extend your StudentRepository and create a method that updates the is_active value (it would be better if it receives the id and the value: true or false)
Extend yout StudentService and create a new method (e.g. call it public void disableAddress(Long id))
In that method the your newly created method in the repository layer
Edit StudentResource and change the code inside the deleteStudent method and call your newly created method in the service layer
If you created a new resource, change the service calling your api.
Previously I developed my application on Hyperledger Composer. Now I'm trying to migrate the application to Hyperledger Fabric 1.4.
I implemented the Commercial-Paper tutorial given the Fabric 1.4 docs,which you can find here. Everything works fine.
Now I want to tailor this to my application and want to define more assets.
They have a file paper.js at commercial-paper/organization/digibank/contract/lib, is this the definition of the "paper" asset?
If I need to define additional assets, do I also create a file myasset.js at the same location and then call in the smart contract?
or is there a better way to define assets?
PS: I am trying to map the assets from Hyperledger composer to Hyperledger fabric 1.4.
Additionally how do you define relationships among assets and participants or other assets? In Composer we used to use --> to define relationships, how do we achieve the same thing fabric-1.4?
Since you already answered the question yourself i would only like to add on the part of the user identification of your own answer.
What's worth mentioning there is the CID Lib. With that and the concept of AttributeBasedAccessControl you can manage the access to queries/invokes perfectly on chain.
Hope that helps and adds a bit more insights to your answer :)
I believe I found the answer to my own question and I hope this would help anyone who is in a similar situation (Moving from Hyperledger Composer to Fabric 1.4)
ctx.stub.putState(key, data);
We simply use the above code to add an asset. A very simplified version is found in fabcar example.
async createCar(ctx, carNumber, make, model, color, owner) {
console.info('============= START : Create Car ===========');
const car = {
color,
docType: 'car',
make,
model,
owner,
};
await ctx.stub.putState(carNumber, Buffer.from(JSON.stringify(car)));
console.info('============= END : Create Car ===========');
}
Here we are adding a car, which is an asset.
In the commercial-paper example, they have done this using an Object-Oriented Approach. With paper.js they just create a 'paper' object (paper class extends state class. State class has the methods to make and split keys, which will be used later), then pass it to 'paperlist' which then uses the methods defined in statelist.js (paperlist class extends statelist class, which has all the methods to write the state onto the ledger) to create this asset using the following code
async addState(state) {
let key = this.ctx.stub.createCompositeKey(this.name, state.getSplitKey());
let data = State.serialize(state);
await this.ctx.stub.putState(key, data);
}
Here you can observe that the key is generated using the methods from the state class, which was inherited by the paper class.
And coming to the last question about relationships, I haven't found a concrete answer yet, but I believe you can achieve this by passing the participant ID or the asset id (Eg: A User is identified by userId, so we just pass the userId) in the data object.
In hindsight, this question looks really dumb, but I hope it helps some people out.
Please feel free to correct my understanding of the Hyperledger Examples. I'm here to learn :)
How can I validate the existence of a a resource when a participant is created
for example:
participant Trader identified by traderId {
o String traderId
o String traderFirstName
o String traderLastName
--> Car owner
}
and there is an asset:
participant Car identified by carId {
o String carId
o string vin
}
When I create a new participant I've to assign a Car to him. When I do that using the CLI or a Restful API or composer-playground there's no validation that this Car exists or not. How can I make sure that it exists so that when I create a participant Trader it should be mapped to an existing instance of the asset Car not to an asset that doesn't exist?
It looks like you are using the "system transactions" AddParticipant and AddAsset from Playground and the REST server.
If you want to do the checking, you will need to write your own Transaction and execute a get on the Car registry (though maybe you should really define the Car as an Asset not a Participant) to check the presence of the owner, and then a put on the Trader registry.
I would suggest looking at the Transactions in the Samples in Playground for examples of writing Transaction scripts. Please also see this reference document.
I have a question about how to update the data model of the assets already stored in the blockchain.
1 - Is it possible to change the data model of an asset? For example by adding new fields or changing the existing ones.
2 - Is it possible to add a new asset to the ledger? By creating a new one which doesn't exist.
3 - These logics could be applied both to HL Composer both to HL Fabric (chaincode written in nodeJS/goLang)?
Thanks.
Adding New fields to a Composer Model:
If you add a new field to an Asset (or participant), you can no longer see the data of existing Asset instances, but if you then remove the field from the model model - you can see the data again! If you add the new field but with 'optional' after the field in the model, you will see the original data.
If you don't want the new field to be optional, you need to start with it as optional, then run code to add a value to the new field for existing Asset instances, then you can remove the optional keyword.
Add a new asset type to the Composer model
You can add a new Asset type to the model file, and then upgrade the model on the Fabric.
There is a method in a factory newResource.
The third parameter of this method is id. Are there any ways or workarounds to generate id?
There was a similar question if you mean to auto-increment the identifier:
Auto Increment field in Composer
It is not recommended by the devs, because different peers may have calculated the IDs at the same time for different new assets/participants and disagree. Disagreements would force all records to roll back.
Source: https://github.com/hyperledger/composer/issues/2931
You control what the id is generated as (deterministically) when you create the new Resource in the Resource registry (whether its an AssetRegistry or ParticipantRegistry etc) and depends on the id field type that identifies the asset/participant.
See sample networks for examples. Eg Perishables network:
https://github.com/hyperledger/composer-sample-networks/blob/v0.16.x/packages/perishable-network/lib/logic.js#L133
Here, Grower is created as a Resource using an email id as the identifier of the Resource.
see model here -> https://github.com/hyperledger/composer-sample-networks/blob/v0.16.x/packages/perishable-network/models/perishable.cto
here - the Participant Grower is extended from a generic Business participant that is identified by an email id (as it inherits that field from the supertype).
This is a real problem and the Hyperledger documentation is not clear about which is the right approach.
When you create a new resource the third parameter id is mandatory and the transaction is rejected if it already exists another asset with the same id. So, how to fill the parameter id of newResource?
factory.newResource(ns, type, id)
A solution could be counting the assets of the same type and generating a pseudo-incremental ID. But this should be used only for assets that are kinda unique on the blockchain. You should use this approach if you don't care of the rejection of the transaction by the peers; or maybe if the rejection is wanted behavior, because a deterministic unique id could work like a unique constraint (like in sql). A big flaw of "counting the assets" is the hyperledger query language doesn't do that, so you you have to use getAll method of the AssetRegistry and then get length of the array, which is not scalable for big arrays:
let bananas_registry = await getAssetRegistry("org.exampleblockchain.Banana");
let all_bananas = await bananas_registry.getAll();
let new_banana_id = String(all_bananas.length + 1);
Another way to get unique ID is concatenate ID of parent assets.
But sometimes I also need something like a real random ID (not incremental). I do not understand why the is not the default for the parameter Id.
Anyway, when I will need a real random ID, I will generate a long random string so the risk of collision with other peers will be low. I will let you know!