存证溯源案例5.0概览
本文分享如何使用 Go
语言和Fabric 2.0链码
开发fabric智能合约实战案例-存证溯源案例,本篇主要介绍链码中溯源使用方法及案例应用。如下图所示:
链码提供以下接口来用于溯源操作:
GetHistoryForKey(key string) (HistoryQueryIteratorInterface, error)
1、溯源接口介绍
GetHistoryForKey(key string) (HistoryQueryIteratorInterface, error)
我们通常基于指定Key,来查询相对应记录的键值对,通过该方法查询某记录(键值对)的历史信息,包含创建、修改、删除的所有状态信息。
HistoryQueryIteratorInterface接为一个迭代器,描述为:
type HistoryQueryIteratorInterface interface {
// Inherit HasNext() and Close()
CommonIteratorInterface
// Next returns the next key and value in the history query iterator.
Next() (*queryresult.KeyModification, error)
}
Next()方法返回一个具体的记录结果*queryresult.KeyModification
type KeyModification struct {
TxId string `protobuf:"bytes,1,opt,name=tx_id,json=txId,proto3" json:"tx_id,omitempty"`
Value []byte `protobuf:"bytes,2,opt,name=value,proto3" json:"value,omitempty"`
Timestamp *timestamppb.Timestamp `protobuf:"bytes,3,opt,name=timestamp,proto3" json:"timestamp,omitempty"`
IsDelete bool `protobuf:"varint,4,opt,name=is_delete,json=isDelete,proto3" json:"is_delete,omitempty"`
XXX_NoUnkeyedLiteral struct{} `json:"-"`
XXX_unrecognized []byte `json:"-"`
XXX_sizecache int32 `json:"-"`
}
我们通过调用Value
方法获取相应值内容,其中TxID则为该记录的交易ID,timestamp为执行该交易的具体时间,isDelete则表示该记录是否是删除操作。
下文为具体使用方法。
2、存证溯源案例实际应用
func (s *SmartContract) GetAssetHistory(ctx contractapi.TransactionContextInterface, assetID, pageSize, pageIndex int) ([]HistoryQueryResult, error) {
log.Printf("GetAssetHistory: ID %v", assetID)
resultsIterator, err := ctx.GetStub().GetHistoryForKey(transIDToStr(assetID))
if err != nil {
return nil, err
}
defer resultsIterator.Close()
var records []HistoryQueryResult
var index int = 0
var startIndex int = (pageIndex - 1) * pageSize
var endIndex int = startIndex + pageIndex
for resultsIterator.HasNext() {
if index < startIndex {
_, err := resultsIterator.Next()
if err != nil {
return nil, err
}
index++
continue
}
if index >= endIndex {
break
}
response, err := resultsIterator.Next()
if err != nil {
return nil, err
}
var asset Asset
if len(response.Value) > 0 {
err = json.Unmarshal(response.Value, &asset)
if err != nil {
return nil, err
}
} else {
asset = Asset{
ID: transIDToStr(assetID),
}
}
timestamp := response.Timestamp.AsTime()
if err != nil {
return nil, err
}
record := HistoryQueryResult{
TxId: response.TxId,
Timestamp: timestamp,
Record: &asset,
IsDelete: response.IsDelete,
}
records = append(records, record)
index++
}
return records, nil
}