Search code examples
hyperledgerhyperledger-composer

How to do multiple updates for the same asset in a transaction


Here I want to do the multiple update commands for the same asset in a single transaction based on conditions.

This is my sample CTO File:

asset SampleAsset identified by id{
  o String id
  o Integer value 
  o Integer value2 
  o Integer value3 
}

transaction SampleTransaction {
  o Integer value
}

This is my sample JS file:

async function sampleTransaction(tx) {  
var value = tx.value;
await updateValue(value);

if(value < MAX){ //MAX=10000
    const assetRegistry1 = await getAssetRegistry('org.example.basic.SampleAsset');
    var data1 = await assetRegistry.get("1");
    data1.value2 = max;
    await assetRegistry1.update(data1); //updateNo2
}
else{
    const assetRegistry1 = await getAssetRegistry('org.example.basic.SampleAsset');
    var data1 = await assetRegistry.get("1");
    data1.value3 = value;
    await assetRegistry1.update(data1); //UpdateNo2
 }
}

async function updateValue(value){
  const assetRegistry = await getAssetRegistry('org.example.basic.SampleAsset');
  var data = await assetRegistry.get("1");
  data.value = value;
  await assetRegistry.update(data); //UpdateNo1
}

With the above code, only latest update (UpdateNo2) command is making changes to the asset. what about the first update?


Solution

  • In Hyperledger fabric during proposal simulation any writes made to keys cannot be read back. Hyperledger composer is subject to that same limitation both when it is used with a real fabric implementation as well as when it's used in a simulation mode (for example when using the web connection in composer-playground). This is the problem you are seeing in your TP function. Every time you perform

    let data = await assetRegistry.get("1");
    

    in the same transaction, you are getting the original asset, you don't get a version of the asset that has been updated earlier in the transaction. So what is finally put into the world state when the transaction is committed will be only the last change you made which is why only UpdateNo2 is being seen. Try something like this (Note I've not tested it)

    async function sampleTransaction(tx) {
        const assetRegistry = await getAssetRegistry('org.example.basic.SampleAsset');
        const data = await assetRegistry1.get("1");
        const value = tx.value;
        updateValue(data, value);
    
        if(value < MAX){ //MAX=10000
            data.value2 = MAX;
        }
        else{
            data.value3 = value;
        }
        await assetRegistry1.update(data);
    }
    
    function updateValue(data, value){
        data.value = value;
    }
    

    (Note I have left the function structure in just to show the equivalent but updateValue can easily be removed)