Collecting the History of Assets

The key-value pairs in the world state can be created, updated, and deleted. It is all reflected in the blockchain, and we can receive the full history of any asset in the chaincode.

To do that, we can use the getHistoryForKey function from ChaincodeStub.

getHistoryForKey(key: string): Promise<HistoryQueryIterator>

The function returns an iterator pointing to the history of a specified key - HistoryQueryIterator. HistoryQueryIterator implements the same behavior as StateQueryIterator does, the only difference is the underlying data. A historical value, an associated transaction ID, client proposal timestamp, and deletion flag are returned for each historical key update as elements of an object that conforms to the KeyModification data type.

interface KeyModification {
    isDelete:      boolean;
    value:         Uint8Array;
    timestamp:     Timestamp;
    txId:          string;
}

getHistoryForKey is not re-executed during the validation phase. This means that other committed transactions may update the key concurrently, impacting the result set, which will not be detected at the validation or commit time. Therefore, applications susceptible to this should not use getHistoryForKey as part of transactions that update the ledger, while limiting the use to read-only chaincode operations.

Considering all of the above, we can implement getHistory(objType, key), a new function in SimpleContract.

async getHistory(ctx, objType, key) {
   const compositeKey = this._createCompositeKey(ctx, objType, key); 

   const iteratorPromise = ctx.stub.getHistoryForKey(compositeKey); 

   let history = [];
   for await (const res of iteratorPromise) {
       history.push({
           txId: res.txId,
           value: res.value.toString(),
           isDelete: res.isDelete
       });
   } 

   return JSON.stringify({
       objectType: objType,
       key:        key,
       values:     history
   });
}

getHistory is a read-only function that returns a list of modifications for the specified asset key. Since this function uses composite keys to compute the input value for getHistoryForKey, the asset type is provided as an argument to the getHistory function.

Last updated

Was this helpful?