Skip to content

Commit 7e401a1

Browse files
cendhuLuis Sanchez
authored and
Luis Sanchez
committed
[FAB-2980] Protobuf for ledger QueryResult
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 <[email protected]> Signed-off-by: Luis Sanchez <[email protected]>
1 parent fed2efa commit 7e401a1

File tree

13 files changed

+180
-56
lines changed

13 files changed

+180
-56
lines changed

core/chaincode/shim/chaincode.go

+14-8
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ import (
3535
"github.com/hyperledger/fabric/common/flogging"
3636
commonledger "github.com/hyperledger/fabric/common/ledger"
3737
"github.com/hyperledger/fabric/core/comm"
38-
"github.com/hyperledger/fabric/core/ledger"
38+
"github.com/hyperledger/fabric/protos/ledger/queryresult"
3939
pb "github.com/hyperledger/fabric/protos/peer"
4040
"github.com/hyperledger/fabric/protos/utils"
4141
"github.com/op/go-logging"
@@ -489,14 +489,14 @@ func getStateByPartialCompositeKey(stub ChaincodeStubInterface, objectType strin
489489
return keysIter, nil
490490
}
491491

492-
func (iter *StateQueryIterator) Next() (*ledger.KV, error) {
492+
func (iter *StateQueryIterator) Next() (*queryresult.KV, error) {
493493
result, err := next(iter.CommonIterator, STATE_QUERY_RESULT)
494-
return result.(*ledger.KV), err
494+
return result.(*queryresult.KV), err
495495
}
496496

497-
func (iter *HistoryQueryIterator) Next() (*ledger.KeyModification, error) {
497+
func (iter *HistoryQueryIterator) Next() (*queryresult.KeyModification, error) {
498498
result, err := next(iter.CommonIterator, HISTORY_QUERY_RESULT)
499-
return result.(*ledger.KeyModification), err
499+
return result.(*queryresult.KeyModification), err
500500
}
501501

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

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

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

516520
if rType == STATE_QUERY_RESULT {
517-
var stateQueryResult ledger.KV
521+
var stateQueryResult queryresult.KV
518522
if err := decoder.Decode(&stateQueryResult); err != nil {
519523
return nil, err
520524
}
521525
iter.currentLoc++
522526
return &stateQueryResult, nil
523527

524528
} else if rType == HISTORY_QUERY_RESULT {
525-
var historyQueryResult ledger.KeyModification
529+
var historyQueryResult queryresult.KeyModification
526530
if err := decoder.Decode(&historyQueryResult); err != nil {
527531
return nil, err
528532
}
@@ -545,7 +549,9 @@ func fetchRemainingQueryResult(iter *CommonIterator) error {
545549
return nil
546550
}
547551

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

551557
if iter.currentLoc < len(iter.response.Results) {

core/chaincode/shim/interfaces.go

+3-3
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ package shim
1919
import (
2020
"github.com/golang/protobuf/ptypes/timestamp"
2121

22-
"github.com/hyperledger/fabric/core/ledger"
22+
"github.com/hyperledger/fabric/protos/ledger/queryresult"
2323
pb "github.com/hyperledger/fabric/protos/peer"
2424
)
2525

@@ -150,7 +150,7 @@ type StateQueryIteratorInterface interface {
150150
CommonIteratorInterface
151151

152152
// Next returns the next key and value in the range and execute query iterator.
153-
Next() (*ledger.KV, error)
153+
Next() (*queryresult.KV, error)
154154
}
155155

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

162162
// Next returns the next key and value in the history query iterator.
163-
Next() (*ledger.KeyModification, error)
163+
Next() (*queryresult.KeyModification, error)
164164
}
165165

166166
// MockQueryIteratorInterface allows a chaincode to iterate over a set of

core/chaincode/shim/mockstub.go

+3-3
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ import (
2626

2727
"github.com/golang/protobuf/ptypes/timestamp"
2828
"github.com/hyperledger/fabric/common/util"
29-
"github.com/hyperledger/fabric/core/ledger"
29+
"github.com/hyperledger/fabric/protos/ledger/queryresult"
3030
pb "github.com/hyperledger/fabric/protos/peer"
3131
"github.com/op/go-logging"
3232
)
@@ -381,7 +381,7 @@ func (iter *MockStateRangeQueryIterator) HasNext() bool {
381381
}
382382

383383
// Next returns the next key and value in the range query iterator.
384-
func (iter *MockStateRangeQueryIterator) Next() (*ledger.KV, error) {
384+
func (iter *MockStateRangeQueryIterator) Next() (*queryresult.KV, error) {
385385
if iter.Closed == true {
386386
mockLogger.Error("MockStateRangeQueryIterator.Next() called after Close()")
387387
return nil, errors.New("MockStateRangeQueryIterator.Next() called after Close()")
@@ -401,7 +401,7 @@ func (iter *MockStateRangeQueryIterator) Next() (*ledger.KV, error) {
401401
key := iter.Current.Value.(string)
402402
value, err := iter.Stub.GetState(key)
403403
iter.Current = iter.Current.Next()
404-
return &ledger.KV{Key: key, Value: value}, err
404+
return &queryresult.KV{Key: key, Value: value}, err
405405
}
406406
iter.Current = iter.Current.Next()
407407
}

core/ledger/kvledger/history/historydb/historyleveldb/historyleveldb_query_executer.go

+3-3
Original file line numberDiff line numberDiff line change
@@ -22,11 +22,11 @@ import (
2222
commonledger "github.com/hyperledger/fabric/common/ledger"
2323
"github.com/hyperledger/fabric/common/ledger/blkstorage"
2424
"github.com/hyperledger/fabric/common/ledger/util"
25-
"github.com/hyperledger/fabric/core/ledger"
2625
"github.com/hyperledger/fabric/core/ledger/kvledger/history/historydb"
2726
"github.com/hyperledger/fabric/core/ledger/kvledger/txmgmt/rwsetutil"
2827
"github.com/hyperledger/fabric/core/ledger/ledgerconfig"
2928
"github.com/hyperledger/fabric/protos/common"
29+
"github.com/hyperledger/fabric/protos/ledger/queryresult"
3030
putils "github.com/hyperledger/fabric/protos/utils"
3131
"github.com/syndtr/goleveldb/leveldb/iterator"
3232
)
@@ -93,7 +93,7 @@ func (scanner *historyScanner) Next() (commonledger.QueryResult, error) {
9393
return nil, err
9494
}
9595
logger.Debugf("Found historic key value for namespace:%s key:%s from transaction %s\n",
96-
scanner.namespace, scanner.key, queryResult.(*ledger.KeyModification).TxID)
96+
scanner.namespace, scanner.key, queryResult.(*queryresult.KeyModification).TxId)
9797
return queryResult, nil
9898
}
9999

@@ -143,7 +143,7 @@ func getKeyModificationFromTran(tranEnvelope *common.Envelope, namespace string,
143143
// got the correct namespace, now find the key write
144144
for _, kvWrite := range nsRWSet.KvRwSet.Writes {
145145
if kvWrite.Key == key {
146-
return &ledger.KeyModification{TxID: txID, Value: kvWrite.Value,
146+
return &queryresult.KeyModification{TxId: txID, Value: kvWrite.Value,
147147
Timestamp: timestamp, IsDelete: kvWrite.IsDelete}, nil
148148
}
149149
} // end keys loop

core/ledger/kvledger/history/historydb/historyleveldb/historyleveldb_test.go

+5-5
Original file line numberDiff line numberDiff line change
@@ -23,9 +23,9 @@ import (
2323

2424
configtxtest "github.com/hyperledger/fabric/common/configtx/test"
2525
"github.com/hyperledger/fabric/common/ledger/testutil"
26-
"github.com/hyperledger/fabric/core/ledger"
2726
"github.com/hyperledger/fabric/core/ledger/util"
2827
"github.com/hyperledger/fabric/protos/common"
28+
"github.com/hyperledger/fabric/protos/ledger/queryresult"
2929
"github.com/hyperledger/fabric/protos/peer"
3030
"github.com/spf13/viper"
3131
)
@@ -129,10 +129,10 @@ func TestHistory(t *testing.T) {
129129
if kmod == nil {
130130
break
131131
}
132-
txid := kmod.(*ledger.KeyModification).TxID
133-
retrievedValue := kmod.(*ledger.KeyModification).Value
134-
retrievedTimestamp := kmod.(*ledger.KeyModification).Timestamp
135-
retrievedIsDelete := kmod.(*ledger.KeyModification).IsDelete
132+
txid := kmod.(*queryresult.KeyModification).TxId
133+
retrievedValue := kmod.(*queryresult.KeyModification).Value
134+
retrievedTimestamp := kmod.(*queryresult.KeyModification).Timestamp
135+
retrievedIsDelete := kmod.(*queryresult.KeyModification).IsDelete
136136
t.Logf("Retrieved history record for key=key7 at TxId=%s with value %v and timestamp %v",
137137
txid, retrievedValue, retrievedTimestamp)
138138
count++

core/ledger/kvledger/kv_ledger_test.go

+7-7
Original file line numberDiff line numberDiff line change
@@ -22,10 +22,10 @@ import (
2222
"testing"
2323

2424
"github.com/hyperledger/fabric/common/ledger/testutil"
25-
ledgerpackage "github.com/hyperledger/fabric/core/ledger"
2625
"github.com/hyperledger/fabric/core/ledger/ledgerconfig"
2726
ledgertestutil "github.com/hyperledger/fabric/core/ledger/testutil"
2827
"github.com/hyperledger/fabric/protos/common"
28+
"github.com/hyperledger/fabric/protos/ledger/queryresult"
2929
putils "github.com/hyperledger/fabric/protos/utils"
3030
"github.com/stretchr/testify/assert"
3131
)
@@ -183,7 +183,7 @@ func TestKVLedgerDBRecovery(t *testing.T) {
183183
if kmod == nil {
184184
break
185185
}
186-
retrievedValue := kmod.(*ledgerpackage.KeyModification).Value
186+
retrievedValue := kmod.(*queryresult.KeyModification).Value
187187
count++
188188
expectedValue := []byte("value1." + strconv.Itoa(count))
189189
testutil.AssertEquals(t, retrievedValue, expectedValue)
@@ -228,7 +228,7 @@ func TestKVLedgerDBRecovery(t *testing.T) {
228228
if kmod == nil {
229229
break
230230
}
231-
retrievedValue := kmod.(*ledgerpackage.KeyModification).Value
231+
retrievedValue := kmod.(*queryresult.KeyModification).Value
232232
count++
233233
expectedValue := []byte("value1." + strconv.Itoa(count))
234234
testutil.AssertEquals(t, retrievedValue, expectedValue)
@@ -295,7 +295,7 @@ func TestKVLedgerDBRecovery(t *testing.T) {
295295
if kmod == nil {
296296
break
297297
}
298-
retrievedValue := kmod.(*ledgerpackage.KeyModification).Value
298+
retrievedValue := kmod.(*queryresult.KeyModification).Value
299299
count++
300300
expectedValue := []byte("value1." + strconv.Itoa(count))
301301
testutil.AssertEquals(t, retrievedValue, expectedValue)
@@ -328,7 +328,7 @@ func TestKVLedgerDBRecovery(t *testing.T) {
328328
if kmod == nil {
329329
break
330330
}
331-
retrievedValue := kmod.(*ledgerpackage.KeyModification).Value
331+
retrievedValue := kmod.(*queryresult.KeyModification).Value
332332
count++
333333
expectedValue := []byte("value1." + strconv.Itoa(count))
334334
testutil.AssertEquals(t, retrievedValue, expectedValue)
@@ -395,7 +395,7 @@ func TestKVLedgerDBRecovery(t *testing.T) {
395395
if kmod == nil {
396396
break
397397
}
398-
retrievedValue := kmod.(*ledgerpackage.KeyModification).Value
398+
retrievedValue := kmod.(*queryresult.KeyModification).Value
399399
count++
400400
expectedValue := []byte("value1." + strconv.Itoa(count))
401401
testutil.AssertEquals(t, retrievedValue, expectedValue)
@@ -520,7 +520,7 @@ func TestLedgerWithCouchDbEnabledWithBinaryAndJSONData(t *testing.T) {
520520
if kmod == nil {
521521
break
522522
}
523-
retrievedValue = kmod.(*ledgerpackage.KeyModification).Value
523+
retrievedValue = kmod.(*queryresult.KeyModification).Value
524524
count++
525525
}
526526
testutil.AssertEquals(t, count, 3)

core/ledger/kvledger/txmgmt/txmgr/commontests/txmgr_test.go

+6-6
Original file line numberDiff line numberDiff line change
@@ -24,9 +24,9 @@ import (
2424
"os"
2525

2626
"github.com/hyperledger/fabric/common/ledger/testutil"
27-
"github.com/hyperledger/fabric/core/ledger"
2827
"github.com/hyperledger/fabric/core/ledger/kvledger/txmgmt/version"
2928
ledgertestutil "github.com/hyperledger/fabric/core/ledger/testutil"
29+
"github.com/hyperledger/fabric/protos/ledger/queryresult"
3030
)
3131

3232
func TestMain(m *testing.M) {
@@ -350,8 +350,8 @@ func testIterator(t *testing.T, env testEnv, numKeys int, startKeyNum int, endKe
350350
break
351351
}
352352
keyNum := begin + count
353-
k := kv.(*ledger.KV).Key
354-
v := kv.(*ledger.KV).Value
353+
k := kv.(*queryresult.KV).Key
354+
v := kv.(*queryresult.KV).Value
355355
t.Logf("Retrieved k=%s, v=%s at count=%d start=%s end=%s", k, v, count, startKey, endKey)
356356
testutil.AssertEquals(t, k, createTestKey(keyNum))
357357
testutil.AssertEquals(t, v, createTestValue(keyNum))
@@ -397,9 +397,9 @@ func testIteratorWithDeletes(t *testing.T, env testEnv) {
397397
itr, _ := queryExecuter.GetStateRangeScanIterator(cID, createTestKey(3), createTestKey(6))
398398
defer itr.Close()
399399
kv, _ := itr.Next()
400-
testutil.AssertEquals(t, kv.(*ledger.KV).Key, createTestKey(3))
400+
testutil.AssertEquals(t, kv.(*queryresult.KV).Key, createTestKey(3))
401401
kv, _ = itr.Next()
402-
testutil.AssertEquals(t, kv.(*ledger.KV).Key, createTestKey(5))
402+
testutil.AssertEquals(t, kv.(*queryresult.KV).Key, createTestKey(5))
403403
}
404404

405405
func TestTxValidationWithItr(t *testing.T) {
@@ -594,7 +594,7 @@ func testExecuteQuery(t *testing.T, env testEnv) {
594594

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

599599
//Verify the owner retrieved matches
600600
testutil.AssertEquals(t, assetResp.Owner, "bob")

core/ledger/kvledger/txmgmt/txmgr/lockbasedtxmgr/helper.go

+3-3
Original file line numberDiff line numberDiff line change
@@ -18,11 +18,11 @@ package lockbasedtxmgr
1818

1919
import (
2020
commonledger "github.com/hyperledger/fabric/common/ledger"
21-
"github.com/hyperledger/fabric/core/ledger"
2221
"github.com/hyperledger/fabric/core/ledger/kvledger/txmgmt/rwsetutil"
2322
"github.com/hyperledger/fabric/core/ledger/kvledger/txmgmt/statedb"
2423
"github.com/hyperledger/fabric/core/ledger/kvledger/txmgmt/version"
2524
"github.com/hyperledger/fabric/core/ledger/ledgerconfig"
25+
"github.com/hyperledger/fabric/protos/ledger/queryresult"
2626
"github.com/hyperledger/fabric/protos/ledger/rwset/kvrwset"
2727
)
2828

@@ -169,7 +169,7 @@ func (itr *resultsItr) Next() (commonledger.QueryResult, error) {
169169
return nil, nil
170170
}
171171
versionedKV := queryResult.(*statedb.VersionedKV)
172-
return &ledger.KV{Key: versionedKV.Key, Value: versionedKV.Value}, nil
172+
return &queryresult.KV{Key: versionedKV.Key, Value: versionedKV.Value}, nil
173173
}
174174

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

228228
// Close implements method in interface ledger.ResultsIterator

core/ledger/ledger_interface.go

+3-16
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,6 @@ limitations under the License.
1717
package ledger
1818

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

@@ -128,17 +129,3 @@ type TxSimulator interface {
128129
// TODO detailed illustration of a couple of representations.
129130
GetTxSimulationResults() ([]byte, error)
130131
}
131-
132-
// KV - QueryResult for KV-based datamodel. Holds a key and corresponding value. A nil value indicates a non-existent key.
133-
type KV struct {
134-
Key string
135-
Value []byte
136-
}
137-
138-
// KeyModification - QueryResult for History.
139-
type KeyModification struct {
140-
TxID string
141-
Value []byte
142-
Timestamp *google_protobuf.Timestamp
143-
IsDelete bool
144-
}

examples/chaincode/go/map/map.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -154,7 +154,7 @@ func (t *SimpleChaincode) Invoke(stub shim.ChaincodeStubInterface) pb.Response {
154154
if iterErr != nil {
155155
return shim.Error(fmt.Sprintf("query operation failed. Error accessing state: %s", err))
156156
}
157-
keys = append(keys, response.TxID)
157+
keys = append(keys, response.TxId)
158158
}
159159

160160
for key, txID := range keys {

examples/chaincode/go/marbles02/marbles_chaincode.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -593,7 +593,7 @@ func (t *SimpleChaincode) getHistoryForMarble(stub shim.ChaincodeStubInterface,
593593
}
594594
buffer.WriteString("{\"TxId\":")
595595
buffer.WriteString("\"")
596-
buffer.WriteString(response.TxID)
596+
buffer.WriteString(response.TxId)
597597
buffer.WriteString("\"")
598598

599599
buffer.WriteString(", \"Value\":")

0 commit comments

Comments
 (0)