Skip to content

Commit

Permalink
[FAB-2980] Protobuf for ledger QueryResult
Browse files Browse the repository at this point in the history
https://gerrit.hyperledger.org/r/#/c/7221/ added QueryResult
structures to chaincode shim.

This CR changes golang QueryResult structs such as KV (holds a result
of a range/execute query) and KeyModification (holds a result of a
history query) to protobuf messages. This makes the QueryResult
agnostic of language. As a result, both golang and java chaincode
shim can easily cast the QueryResult to appropriate struct depending
on the query type.

Further, TxID used in KeyModification struct is renamed to TxId to
to maintain consistency with ChannelHeader as both are exposed outside
fabric via Chaincode/Smart-Contract and Block, respectively.

Change-Id: I68a58d10a073ec8f83ed2523fc5ba0b82c61242e
Signed-off-by: senthil <cendhu@gmail.com>
Signed-off-by: Luis Sanchez <sanchezl@us.ibm.com>
  • Loading branch information
cendhu authored and Luis Sanchez committed Apr 20, 2017
1 parent fed2efa commit 7e401a1
Show file tree
Hide file tree
Showing 13 changed files with 180 additions and 56 deletions.
22 changes: 14 additions & 8 deletions core/chaincode/shim/chaincode.go
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ import (
"github.com/hyperledger/fabric/common/flogging"
commonledger "github.com/hyperledger/fabric/common/ledger"
"github.com/hyperledger/fabric/core/comm"
"github.com/hyperledger/fabric/core/ledger"
"github.com/hyperledger/fabric/protos/ledger/queryresult"
pb "github.com/hyperledger/fabric/protos/peer"
"github.com/hyperledger/fabric/protos/utils"
"github.com/op/go-logging"
Expand Down Expand Up @@ -489,14 +489,14 @@ func getStateByPartialCompositeKey(stub ChaincodeStubInterface, objectType strin
return keysIter, nil
}

func (iter *StateQueryIterator) Next() (*ledger.KV, error) {
func (iter *StateQueryIterator) Next() (*queryresult.KV, error) {
result, err := next(iter.CommonIterator, STATE_QUERY_RESULT)
return result.(*ledger.KV), err
return result.(*queryresult.KV), err
}

func (iter *HistoryQueryIterator) Next() (*ledger.KeyModification, error) {
func (iter *HistoryQueryIterator) Next() (*queryresult.KeyModification, error) {
result, err := next(iter.CommonIterator, HISTORY_QUERY_RESULT)
return result.(*ledger.KeyModification), err
return result.(*queryresult.KeyModification), err
}

// HasNext returns true if the range query iterator contains additional keys
Expand All @@ -508,21 +508,25 @@ func (iter *CommonIterator) HasNext() bool {
return false
}

// getResultsFromBytes deserializes QueryResult and return either a KV struct
// or KeyModification depending on the result type (i.e., state (range/execute)
// query, history query). Note that commonledger.QueryResult is an empty golang
// interface that can hold values of any type.
func getResultFromBytes(queryResultBytes *pb.QueryResultBytes, iter *CommonIterator,
rType resultType) (commonledger.QueryResult, error) {

decoder := gob.NewDecoder(bytes.NewBuffer(queryResultBytes.ResultBytes))

if rType == STATE_QUERY_RESULT {
var stateQueryResult ledger.KV
var stateQueryResult queryresult.KV
if err := decoder.Decode(&stateQueryResult); err != nil {
return nil, err
}
iter.currentLoc++
return &stateQueryResult, nil

} else if rType == HISTORY_QUERY_RESULT {
var historyQueryResult ledger.KeyModification
var historyQueryResult queryresult.KeyModification
if err := decoder.Decode(&historyQueryResult); err != nil {
return nil, err
}
Expand All @@ -545,7 +549,9 @@ func fetchRemainingQueryResult(iter *CommonIterator) error {
return nil
}

// Next returns the next key and value in the state or history query iterator.
// next returns the next QueryResult (i.e., either a KV struct or KeyModificationin)
// from the state or history query iterator. Note that commonledger.QueryResult is an
// empty golang interface that can hold values of any type.
func next(iter *CommonIterator, rType resultType) (commonledger.QueryResult, error) {

if iter.currentLoc < len(iter.response.Results) {
Expand Down
6 changes: 3 additions & 3 deletions core/chaincode/shim/interfaces.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ package shim
import (
"github.com/golang/protobuf/ptypes/timestamp"

"github.com/hyperledger/fabric/core/ledger"
"github.com/hyperledger/fabric/protos/ledger/queryresult"
pb "github.com/hyperledger/fabric/protos/peer"
)

Expand Down Expand Up @@ -150,7 +150,7 @@ type StateQueryIteratorInterface interface {
CommonIteratorInterface

// Next returns the next key and value in the range and execute query iterator.
Next() (*ledger.KV, error)
Next() (*queryresult.KV, error)
}

// HistoryQueryIteratorInterface allows a chaincode to iterate over a set of
Expand All @@ -160,7 +160,7 @@ type HistoryQueryIteratorInterface interface {
CommonIteratorInterface

// Next returns the next key and value in the history query iterator.
Next() (*ledger.KeyModification, error)
Next() (*queryresult.KeyModification, error)
}

// MockQueryIteratorInterface allows a chaincode to iterate over a set of
Expand Down
6 changes: 3 additions & 3 deletions core/chaincode/shim/mockstub.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ import (

"github.com/golang/protobuf/ptypes/timestamp"
"github.com/hyperledger/fabric/common/util"
"github.com/hyperledger/fabric/core/ledger"
"github.com/hyperledger/fabric/protos/ledger/queryresult"
pb "github.com/hyperledger/fabric/protos/peer"
"github.com/op/go-logging"
)
Expand Down Expand Up @@ -381,7 +381,7 @@ func (iter *MockStateRangeQueryIterator) HasNext() bool {
}

// Next returns the next key and value in the range query iterator.
func (iter *MockStateRangeQueryIterator) Next() (*ledger.KV, error) {
func (iter *MockStateRangeQueryIterator) Next() (*queryresult.KV, error) {
if iter.Closed == true {
mockLogger.Error("MockStateRangeQueryIterator.Next() called after Close()")
return nil, errors.New("MockStateRangeQueryIterator.Next() called after Close()")
Expand All @@ -401,7 +401,7 @@ func (iter *MockStateRangeQueryIterator) Next() (*ledger.KV, error) {
key := iter.Current.Value.(string)
value, err := iter.Stub.GetState(key)
iter.Current = iter.Current.Next()
return &ledger.KV{Key: key, Value: value}, err
return &queryresult.KV{Key: key, Value: value}, err
}
iter.Current = iter.Current.Next()
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,11 +22,11 @@ import (
commonledger "github.com/hyperledger/fabric/common/ledger"
"github.com/hyperledger/fabric/common/ledger/blkstorage"
"github.com/hyperledger/fabric/common/ledger/util"
"github.com/hyperledger/fabric/core/ledger"
"github.com/hyperledger/fabric/core/ledger/kvledger/history/historydb"
"github.com/hyperledger/fabric/core/ledger/kvledger/txmgmt/rwsetutil"
"github.com/hyperledger/fabric/core/ledger/ledgerconfig"
"github.com/hyperledger/fabric/protos/common"
"github.com/hyperledger/fabric/protos/ledger/queryresult"
putils "github.com/hyperledger/fabric/protos/utils"
"github.com/syndtr/goleveldb/leveldb/iterator"
)
Expand Down Expand Up @@ -93,7 +93,7 @@ func (scanner *historyScanner) Next() (commonledger.QueryResult, error) {
return nil, err
}
logger.Debugf("Found historic key value for namespace:%s key:%s from transaction %s\n",
scanner.namespace, scanner.key, queryResult.(*ledger.KeyModification).TxID)
scanner.namespace, scanner.key, queryResult.(*queryresult.KeyModification).TxId)
return queryResult, nil
}

Expand Down Expand Up @@ -143,7 +143,7 @@ func getKeyModificationFromTran(tranEnvelope *common.Envelope, namespace string,
// got the correct namespace, now find the key write
for _, kvWrite := range nsRWSet.KvRwSet.Writes {
if kvWrite.Key == key {
return &ledger.KeyModification{TxID: txID, Value: kvWrite.Value,
return &queryresult.KeyModification{TxId: txID, Value: kvWrite.Value,
Timestamp: timestamp, IsDelete: kvWrite.IsDelete}, nil
}
} // end keys loop
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,9 +23,9 @@ import (

configtxtest "github.com/hyperledger/fabric/common/configtx/test"
"github.com/hyperledger/fabric/common/ledger/testutil"
"github.com/hyperledger/fabric/core/ledger"
"github.com/hyperledger/fabric/core/ledger/util"
"github.com/hyperledger/fabric/protos/common"
"github.com/hyperledger/fabric/protos/ledger/queryresult"
"github.com/hyperledger/fabric/protos/peer"
"github.com/spf13/viper"
)
Expand Down Expand Up @@ -129,10 +129,10 @@ func TestHistory(t *testing.T) {
if kmod == nil {
break
}
txid := kmod.(*ledger.KeyModification).TxID
retrievedValue := kmod.(*ledger.KeyModification).Value
retrievedTimestamp := kmod.(*ledger.KeyModification).Timestamp
retrievedIsDelete := kmod.(*ledger.KeyModification).IsDelete
txid := kmod.(*queryresult.KeyModification).TxId
retrievedValue := kmod.(*queryresult.KeyModification).Value
retrievedTimestamp := kmod.(*queryresult.KeyModification).Timestamp
retrievedIsDelete := kmod.(*queryresult.KeyModification).IsDelete
t.Logf("Retrieved history record for key=key7 at TxId=%s with value %v and timestamp %v",
txid, retrievedValue, retrievedTimestamp)
count++
Expand Down
14 changes: 7 additions & 7 deletions core/ledger/kvledger/kv_ledger_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,10 +22,10 @@ import (
"testing"

"github.com/hyperledger/fabric/common/ledger/testutil"
ledgerpackage "github.com/hyperledger/fabric/core/ledger"
"github.com/hyperledger/fabric/core/ledger/ledgerconfig"
ledgertestutil "github.com/hyperledger/fabric/core/ledger/testutil"
"github.com/hyperledger/fabric/protos/common"
"github.com/hyperledger/fabric/protos/ledger/queryresult"
putils "github.com/hyperledger/fabric/protos/utils"
"github.com/stretchr/testify/assert"
)
Expand Down Expand Up @@ -183,7 +183,7 @@ func TestKVLedgerDBRecovery(t *testing.T) {
if kmod == nil {
break
}
retrievedValue := kmod.(*ledgerpackage.KeyModification).Value
retrievedValue := kmod.(*queryresult.KeyModification).Value
count++
expectedValue := []byte("value1." + strconv.Itoa(count))
testutil.AssertEquals(t, retrievedValue, expectedValue)
Expand Down Expand Up @@ -228,7 +228,7 @@ func TestKVLedgerDBRecovery(t *testing.T) {
if kmod == nil {
break
}
retrievedValue := kmod.(*ledgerpackage.KeyModification).Value
retrievedValue := kmod.(*queryresult.KeyModification).Value
count++
expectedValue := []byte("value1." + strconv.Itoa(count))
testutil.AssertEquals(t, retrievedValue, expectedValue)
Expand Down Expand Up @@ -295,7 +295,7 @@ func TestKVLedgerDBRecovery(t *testing.T) {
if kmod == nil {
break
}
retrievedValue := kmod.(*ledgerpackage.KeyModification).Value
retrievedValue := kmod.(*queryresult.KeyModification).Value
count++
expectedValue := []byte("value1." + strconv.Itoa(count))
testutil.AssertEquals(t, retrievedValue, expectedValue)
Expand Down Expand Up @@ -328,7 +328,7 @@ func TestKVLedgerDBRecovery(t *testing.T) {
if kmod == nil {
break
}
retrievedValue := kmod.(*ledgerpackage.KeyModification).Value
retrievedValue := kmod.(*queryresult.KeyModification).Value
count++
expectedValue := []byte("value1." + strconv.Itoa(count))
testutil.AssertEquals(t, retrievedValue, expectedValue)
Expand Down Expand Up @@ -395,7 +395,7 @@ func TestKVLedgerDBRecovery(t *testing.T) {
if kmod == nil {
break
}
retrievedValue := kmod.(*ledgerpackage.KeyModification).Value
retrievedValue := kmod.(*queryresult.KeyModification).Value
count++
expectedValue := []byte("value1." + strconv.Itoa(count))
testutil.AssertEquals(t, retrievedValue, expectedValue)
Expand Down Expand Up @@ -520,7 +520,7 @@ func TestLedgerWithCouchDbEnabledWithBinaryAndJSONData(t *testing.T) {
if kmod == nil {
break
}
retrievedValue = kmod.(*ledgerpackage.KeyModification).Value
retrievedValue = kmod.(*queryresult.KeyModification).Value
count++
}
testutil.AssertEquals(t, count, 3)
Expand Down
12 changes: 6 additions & 6 deletions core/ledger/kvledger/txmgmt/txmgr/commontests/txmgr_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,9 +24,9 @@ import (
"os"

"github.com/hyperledger/fabric/common/ledger/testutil"
"github.com/hyperledger/fabric/core/ledger"
"github.com/hyperledger/fabric/core/ledger/kvledger/txmgmt/version"
ledgertestutil "github.com/hyperledger/fabric/core/ledger/testutil"
"github.com/hyperledger/fabric/protos/ledger/queryresult"
)

func TestMain(m *testing.M) {
Expand Down Expand Up @@ -350,8 +350,8 @@ func testIterator(t *testing.T, env testEnv, numKeys int, startKeyNum int, endKe
break
}
keyNum := begin + count
k := kv.(*ledger.KV).Key
v := kv.(*ledger.KV).Value
k := kv.(*queryresult.KV).Key
v := kv.(*queryresult.KV).Value
t.Logf("Retrieved k=%s, v=%s at count=%d start=%s end=%s", k, v, count, startKey, endKey)
testutil.AssertEquals(t, k, createTestKey(keyNum))
testutil.AssertEquals(t, v, createTestValue(keyNum))
Expand Down Expand Up @@ -397,9 +397,9 @@ func testIteratorWithDeletes(t *testing.T, env testEnv) {
itr, _ := queryExecuter.GetStateRangeScanIterator(cID, createTestKey(3), createTestKey(6))
defer itr.Close()
kv, _ := itr.Next()
testutil.AssertEquals(t, kv.(*ledger.KV).Key, createTestKey(3))
testutil.AssertEquals(t, kv.(*queryresult.KV).Key, createTestKey(3))
kv, _ = itr.Next()
testutil.AssertEquals(t, kv.(*ledger.KV).Key, createTestKey(5))
testutil.AssertEquals(t, kv.(*queryresult.KV).Key, createTestKey(5))
}

func TestTxValidationWithItr(t *testing.T) {
Expand Down Expand Up @@ -594,7 +594,7 @@ func testExecuteQuery(t *testing.T, env testEnv) {

//Unmarshal the document to Asset structure
assetResp := &Asset{}
json.Unmarshal(queryRecord.(*ledger.KV).Value, &assetResp)
json.Unmarshal(queryRecord.(*queryresult.KV).Value, &assetResp)

//Verify the owner retrieved matches
testutil.AssertEquals(t, assetResp.Owner, "bob")
Expand Down
6 changes: 3 additions & 3 deletions core/ledger/kvledger/txmgmt/txmgr/lockbasedtxmgr/helper.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,11 +18,11 @@ package lockbasedtxmgr

import (
commonledger "github.com/hyperledger/fabric/common/ledger"
"github.com/hyperledger/fabric/core/ledger"
"github.com/hyperledger/fabric/core/ledger/kvledger/txmgmt/rwsetutil"
"github.com/hyperledger/fabric/core/ledger/kvledger/txmgmt/statedb"
"github.com/hyperledger/fabric/core/ledger/kvledger/txmgmt/version"
"github.com/hyperledger/fabric/core/ledger/ledgerconfig"
"github.com/hyperledger/fabric/protos/ledger/queryresult"
"github.com/hyperledger/fabric/protos/ledger/rwset/kvrwset"
)

Expand Down Expand Up @@ -169,7 +169,7 @@ func (itr *resultsItr) Next() (commonledger.QueryResult, error) {
return nil, nil
}
versionedKV := queryResult.(*statedb.VersionedKV)
return &ledger.KV{Key: versionedKV.Key, Value: versionedKV.Value}, nil
return &queryresult.KV{Key: versionedKV.Key, Value: versionedKV.Value}, nil
}

// updateRangeQueryInfo updates two attributes of the rangeQueryInfo
Expand Down Expand Up @@ -222,7 +222,7 @@ func (itr *queryResultsItr) Next() (commonledger.QueryResult, error) {
if itr.RWSetBuilder != nil {
itr.RWSetBuilder.AddToReadSet(versionedQueryRecord.Namespace, versionedQueryRecord.Key, versionedQueryRecord.Version)
}
return &ledger.KV{Key: versionedQueryRecord.Key, Value: versionedQueryRecord.Value}, nil
return &queryresult.KV{Key: versionedQueryRecord.Key, Value: versionedQueryRecord.Value}, nil
}

// Close implements method in interface ledger.ResultsIterator
Expand Down
19 changes: 3 additions & 16 deletions core/ledger/ledger_interface.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,6 @@ limitations under the License.
package ledger

import (
google_protobuf "github.com/golang/protobuf/ptypes/timestamp"
commonledger "github.com/hyperledger/fabric/common/ledger"
"github.com/hyperledger/fabric/protos/common"
"github.com/hyperledger/fabric/protos/peer"
Expand Down Expand Up @@ -90,11 +89,12 @@ type QueryExecutor interface {
// startKey is included in the results and endKey is excluded. An empty startKey refers to the first available key
// and an empty endKey refers to the last available key. For scanning all the keys, both the startKey and the endKey
// can be supplied as empty strings. However, a full scan shuold be used judiciously for performance reasons.
// The returned ResultsIterator contains results of type *KV
// The returned ResultsIterator contains results of type *KV which is defined in protos/ledger/queryresult.
GetStateRangeScanIterator(namespace string, startKey string, endKey string) (commonledger.ResultsIterator, error)
// ExecuteQuery executes the given query and returns an iterator that contains results of type specific to the underlying data store.
// Only used for state databases that support query
// For a chaincode, the namespace corresponds to the chaincodeId
// The returned ResultsIterator contains results of type *KV which is defined in protos/ledger/queryresult.
ExecuteQuery(namespace, query string) (commonledger.ResultsIterator, error)
// Done releases resources occupied by the QueryExecutor
Done()
Expand All @@ -103,6 +103,7 @@ type QueryExecutor interface {
// HistoryQueryExecutor executes the history queries
type HistoryQueryExecutor interface {
// GetHistoryForKey retrieves the history of values for a key.
// The returned ResultsIterator contains results of type *KeyModification which is defined in protos/ledger/queryresult.
GetHistoryForKey(namespace string, key string) (commonledger.ResultsIterator, error)
}

Expand All @@ -128,17 +129,3 @@ type TxSimulator interface {
// TODO detailed illustration of a couple of representations.
GetTxSimulationResults() ([]byte, error)
}

// KV - QueryResult for KV-based datamodel. Holds a key and corresponding value. A nil value indicates a non-existent key.
type KV struct {
Key string
Value []byte
}

// KeyModification - QueryResult for History.
type KeyModification struct {
TxID string
Value []byte
Timestamp *google_protobuf.Timestamp
IsDelete bool
}
2 changes: 1 addition & 1 deletion examples/chaincode/go/map/map.go
Original file line number Diff line number Diff line change
Expand Up @@ -154,7 +154,7 @@ func (t *SimpleChaincode) Invoke(stub shim.ChaincodeStubInterface) pb.Response {
if iterErr != nil {
return shim.Error(fmt.Sprintf("query operation failed. Error accessing state: %s", err))
}
keys = append(keys, response.TxID)
keys = append(keys, response.TxId)
}

for key, txID := range keys {
Expand Down
2 changes: 1 addition & 1 deletion examples/chaincode/go/marbles02/marbles_chaincode.go
Original file line number Diff line number Diff line change
Expand Up @@ -593,7 +593,7 @@ func (t *SimpleChaincode) getHistoryForMarble(stub shim.ChaincodeStubInterface,
}
buffer.WriteString("{\"TxId\":")
buffer.WriteString("\"")
buffer.WriteString(response.TxID)
buffer.WriteString(response.TxId)
buffer.WriteString("\"")

buffer.WriteString(", \"Value\":")
Expand Down
Loading

0 comments on commit 7e401a1

Please sign in to comment.