I am using IBM bluemix blockchain service to tryout some smart contract logic for my asset sharing demo.
Is there anyway to query the asset modified history in hyp
For NodeJS SDK:
You can use 'GetHistoryForKey'. It returns a history of key values across time. For each historic key update, the historic value and associated transaction id and timestamp are returned.
You can find it here (doc. link):
https://fabric-shim.github.io/release-1.3/fabric-shim.ChaincodeStub.html#getHistoryForKey__anchor
IF you need. Java SDk and go chaincode combination. Here is the example
Java code
public List<HistoryDao> getUFOHistory(String key) throws Exception {
String[] args = { key };
Logger.getLogger(QueryChaincode.class.getName()).log(Level.INFO, "UFO communication history - " + args[0]);
Collection<ProposalResponse> responses1Query = ucc.getChannelClient().queryByChainCode("skynetchaincode", "getHistoryForUFO", args);
String stringResponse = null;
ArrayList<HistoryDao> newArrayList = new ArrayList<>();
for (ProposalResponse pres : responses1Query) {
stringResponse = new String(pres.getChaincodeActionResponsePayload());
Logger.getLogger(QueryChaincode.class.getName()).log(Level.INFO, stringResponse);
newArrayList = gson.fromJson(stringResponse, new TypeToken<ArrayList<HistoryDao>>() {
}.getType());
}
if (null == stringResponse)
stringResponse = "Not able to find any ufo communication history";
return newArrayList;
}
and you go chancode implemetation is as follows
Go code
func (t *SmartContract) getHistoryForUFO(APIstub shim.ChaincodeStubInterface, args []string) sc.Response {
if len(args) < 1 {
return shim.Error("Incorrect number of arguments. Expecting 1")
}
ufoId := args[0]
resultsIterator, err := APIstub.GetHistoryForKey(ufoId)
if err != nil {
return shim.Error(err.Error())
}
defer resultsIterator.Close()
var buffer bytes.Buffer
buffer.WriteString("[")
bArrayMemberAlreadyWritten := false
for resultsIterator.HasNext() {
response, err := resultsIterator.Next()
if err != nil {
return shim.Error(err.Error())
}
// Add a comma before array members, suppress it for the first array member
if bArrayMemberAlreadyWritten == true {
buffer.WriteString(",")
}
buffer.WriteString("{\"TxId\":")
buffer.WriteString("\"")
buffer.WriteString(response.TxId)
buffer.WriteString("\"")
buffer.WriteString(", \"Value\":")
// if it was a delete operation on given key, then we need to set the
//corresponding value null. Else, we will write the response.Value
//as-is (as the Value itself a JSON)
if response.IsDelete {
buffer.WriteString("null")
} else {
buffer.WriteString(string(response.Value))
}
buffer.WriteString(", \"Timestamp\":")
buffer.WriteString("\"")
buffer.WriteString(time.Unix(response.Timestamp.Seconds, int64(response.Timestamp.Nanos)).String())
buffer.WriteString("\"")
buffer.WriteString(", \"IsDelete\":")
buffer.WriteString("\"")
buffer.WriteString(strconv.FormatBool(response.IsDelete))
buffer.WriteString("\"")
buffer.WriteString("}")
bArrayMemberAlreadyWritten = true
}
buffer.WriteString("]")
fmt.Printf("- History returning:\n%s\n", buffer.String())
return shim.Success(buffer.Bytes())
}
There you go. Have fun.
You can use GetHistoryForKey()
API as following:
historyIter, err := stub.GetHistoryForKey(key)
if err != nil {
errMsg := fmt.Sprintf("[ERROR] cannot retrieve history for key <%s>, due to %s", key, err)
fmt.Println(errMsg)
return shim.Error(errMsg)
}
for historyIter.HasNext() {
modification, err := historyIer.Next()
if err != nil {
errMsg := fmt.Sprintf("[ERROR] cannot read record modification for key %s, id <%s>, due to %s", key, err)
fmt.Println(errMsg)
return shim.Error(errMsg)
}
fmt.Println("Returning information about", string(modification.Value))
}
Here is the link to the interface with API description:
// GetHistoryForKey returns a history of key values across time.
// For each historic key update, the historic value and associated
// transaction id and timestamp are returned. The timestamp is the
// timestamp provided by the client in the proposal header.
// GetHistoryForKey requires peer configuration
// core.ledger.history.enableHistoryDatabase to be true.
// The query is NOT re-executed during validation phase, phantom reads are
// not detected. That is, other committed transactions may have updated
// the key concurrently, impacting the result set, and this would not be
// detected at validation/commit time. Applications susceptible to this
// should therefore not use GetHistoryForKey as part of transactions that
// update ledger, and should limit use to read-only chaincode operations.
GetHistoryForKey(key string) (HistoryQueryIteratorInterface, error)
In case you'd like to inspect history of changes not in context of chaincode you can use QSCC (Query System Chaincode), which provide following capabilities:
// These are function names from Invoke first parameter
const (
GetChainInfo string = "GetChainInfo"
GetBlockByNumber string = "GetBlockByNumber"
GetBlockByHash string = "GetBlockByHash"
GetTransactionByID string = "GetTransactionByID"
GetBlockByTxID string = "GetBlockByTxID"
)
From the Fabric FAQ, A. The chaincode API GetHistoryForKey() will return history of values for a key.