如何在超级分层结构中获取资产修改历史记录

时间:2017-08-08 14:04:10

标签: ibm-cloud blockchain hyperledger hyperledger-fabric

我正在使用IBM bluemix blockchain service为我的资产共享演示试用一些智能合约逻辑。

无论如何在超级分层结构网络中查询资产修改历史。

我已经检查过Fabric 0.6和1.0版本的文档,但我只能找到 stub.pushState(key,value_json) stub.getState(key) 以交换分类帐的宽度。
但是使用 stub.getState(key) ,我只能获取密钥的最新条目,但是如何获取并显示为同一密钥编写的一系列更改/修改。 我使用{peeraddress}/Block/getBlock/{Block}遍历了块,但是我只获得加密的事务有效负载,因为它的安全性已经开启。我没有想到显示相同密钥的资产修改历史。


请建议我这样做的正确方法。

提前致谢

4 个答案:

答案 0 :(得分:6)

您可以使用GetHistoryForKey() API,如下所示:

    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到API说明界面:

// 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)

如果您想检查不在链代码上下文中的更改历史记录,可以使用QSCC(查询系统链接代码),它提供以下功能:

// These are function names from Invoke first parameter
const (
    GetChainInfo       string = "GetChainInfo"
    GetBlockByNumber   string = "GetBlockByNumber"
    GetBlockByHash     string = "GetBlockByHash"
    GetTransactionByID string = "GetTransactionByID"
    GetBlockByTxID     string = "GetBlockByTxID"
)

答案 1 :(得分:2)

来自Fabric FAQ,A。链代码API GetHistoryForKey()将返回密钥值的历史记录。

答案 2 :(得分:1)

如果需要。 Java SDk和go chaincode组合。这是示例

  

Java代码

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;
}

然后您进行chancode实现,如下所示

  

执行代码

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())

}

你去了。玩得开心。

答案 3 :(得分:0)

对于NodeJS SDK:

您可以使用“ GetHistoryForKey”。 它返回跨时间键值的历史记录。对于每次历史键更新,都将返回历史值以及关联的交易ID和时间戳。

您可以在这里找到它(文档链接):

https://fabric-shim.github.io/release-1.3/fabric-shim.ChaincodeStub.html#getHistoryForKey__anchor