How to fetch asset modification history in hyperledger fabric

后端 未结 4 837
独厮守ぢ
独厮守ぢ 2021-01-07 13:33

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

相关标签:
4条回答
  • 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

    0 讨论(0)
  • 2021-01-07 14:04

    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.

    0 讨论(0)
  • 2021-01-07 14:29

    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"
    )
    
    0 讨论(0)
  • 2021-01-07 14:29

    From the Fabric FAQ, A. The chaincode API GetHistoryForKey() will return history of values for a key.

    0 讨论(0)
提交回复
热议问题