From d5467f3716075991ac0c685ebbc97a8e427cdb00 Mon Sep 17 00:00:00 2001 From: senthil Date: Tue, 24 Jan 2017 20:18:40 +0530 Subject: [PATCH] [FAB-204] Expose ledger rich query API to chaincode Adding a new chaincode API called ExecuteQuery() that executes a given rich query on the state DB (if it is supported). For example, if CouchDB is the state DB, chaincode can utilize ExecuteQuery() API to execute declarative JSON query to find documents which satisfy given criteria. http://docs.couchdb.org/en/2.0.0/api/database/find.html Change-Id: I296d261c247badc679a7d5bfa25172a9e19ccf34 Signed-off-by: senthil --- core/chaincode/chaincode_support.go | 2 +- core/chaincode/exectransaction_test.go | 58 +++- core/chaincode/handler.go | 219 ++++++++++---- core/chaincode/shim/chaincode.go | 33 ++- core/chaincode/shim/handler.go | 84 ++++-- core/chaincode/shim/interfaces.go | 10 +- .../hyperledger/java/shim/ChaincodeStub.java | 2 +- .../org/hyperledger/java/shim/Handler.java | 6 +- core/chaincode/shim/mockstub.go | 8 +- examples/chaincode/go/map/map.go | 31 +- protos/peer/chaincode.pb.go | 280 +++++++++--------- protos/peer/chaincode.proto | 23 +- 12 files changed, 514 insertions(+), 242 deletions(-) diff --git a/core/chaincode/chaincode_support.go b/core/chaincode/chaincode_support.go index 039f9b6c595..e173c7fb66e 100644 --- a/core/chaincode/chaincode_support.go +++ b/core/chaincode/chaincode_support.go @@ -298,7 +298,7 @@ func (chaincodeSupport *ChaincodeSupport) deregisterHandler(chaincodehandler *Ha // clean up rangeQueryIteratorMap for _, context := range chaincodehandler.txCtxs { - for _, v := range context.rangeQueryIteratorMap { + for _, v := range context.queryIteratorMap { v.Close() } } diff --git a/core/chaincode/exectransaction_test.go b/core/chaincode/exectransaction_test.go index 2a24433ea94..6711dc8265e 100644 --- a/core/chaincode/exectransaction_test.go +++ b/core/chaincode/exectransaction_test.go @@ -37,6 +37,7 @@ import ( putils "github.com/hyperledger/fabric/protos/utils" "github.com/golang/protobuf/proto" + "github.com/hyperledger/fabric/core/ledger/ledgerconfig" "github.com/hyperledger/fabric/core/ledger/ledgermgmt" "github.com/hyperledger/fabric/msp" mspmgmt "github.com/hyperledger/fabric/msp/mgmt" @@ -855,9 +856,7 @@ func TestChaincodeInvokeChaincodeErrorCase(t *testing.T) { } // Test the invocation of a transaction. -func TestRangeQuery(t *testing.T) { - //TODO enable after ledger enables RangeQuery - t.Skip() +func TestQueries(t *testing.T) { chainID := util.GetTestChainID() @@ -891,8 +890,44 @@ func TestRangeQuery(t *testing.T) { } // Invoke second chaincode, which will inturn invoke the first chaincode + f = "put" + args = util.ToChaincodeArgs(f, "key1", "{\"shipmentID\":\"161003PKC7300\",\"customsInvoice\":{\"methodOfTransport\":\"GROUND\",\"invoiceNumber\":\"00091622\"},\"weightUnitOfMeasure\":\"KGM\",\"volumeUnitOfMeasure\": \"CO\",\"dimensionUnitOfMeasure\":\"CM\",\"currency\":\"USD\"}") + spec = &pb.ChaincodeSpec{Type: 1, ChaincodeID: cID, Input: &pb.ChaincodeInput{Args: args}} + _, _, _, err = invoke(ctxt, chainID, spec) + + if err != nil { + t.Fail() + t.Logf("Error invoking <%s>: %s", chaincodeID, err) + theChaincodeSupport.Stop(ctxt, cccid, &pb.ChaincodeDeploymentSpec{ChaincodeSpec: spec}) + return + } + + f = "put" + args = util.ToChaincodeArgs(f, "key2", "{\"shipmentID\":\"161003PKC7300\",\"customsInvoice\":{\"methodOfTransport\":\"GROUND\",\"invoiceNumber\":\"00091622\"},\"weightUnitOfMeasure\":\"KGM\",\"volumeUnitOfMeasure\": \"CO\",\"dimensionUnitOfMeasure\":\"CM\",\"currency\":\"USD\"}") + spec = &pb.ChaincodeSpec{Type: 1, ChaincodeID: cID, Input: &pb.ChaincodeInput{Args: args}} + _, _, _, err = invoke(ctxt, chainID, spec) + + if err != nil { + t.Fail() + t.Logf("Error invoking <%s>: %s", chaincodeID, err) + theChaincodeSupport.Stop(ctxt, cccid, &pb.ChaincodeDeploymentSpec{ChaincodeSpec: spec}) + return + } + + f = "put" + args = util.ToChaincodeArgs(f, "key3", "{\"shipmentID\":\"161003PKC7300\",\"customsInvoice\":{\"methodOfTransport\":\"GROUND\",\"invoiceNumber\":\"00091622\"},\"weightUnitOfMeasure\":\"KGM\",\"volumeUnitOfMeasure\": \"CO\",\"dimensionUnitOfMeasure\":\"CM\",\"currency\":\"USD\"}") + spec = &pb.ChaincodeSpec{Type: 1, ChaincodeID: cID, Input: &pb.ChaincodeInput{Args: args}} + _, _, _, err = invoke(ctxt, chainID, spec) + + if err != nil { + t.Fail() + t.Logf("Error invoking <%s>: %s", chaincodeID, err) + theChaincodeSupport.Stop(ctxt, cccid, &pb.ChaincodeDeploymentSpec{ChaincodeSpec: spec}) + return + } + f = "keys" - args = util.ToChaincodeArgs(f) + args = util.ToChaincodeArgs(f, "key0", "key3") spec = &pb.ChaincodeSpec{Type: 1, ChaincodeID: cID, Input: &pb.ChaincodeInput{Args: args}} _, _, _, err = invoke(ctxt, chainID, spec) @@ -903,6 +938,21 @@ func TestRangeQuery(t *testing.T) { theChaincodeSupport.Stop(ctxt, cccid, &pb.ChaincodeDeploymentSpec{ChaincodeSpec: spec}) return } + + if ledgerconfig.IsCouchDBEnabled() == true { + f = "query" + args = util.ToChaincodeArgs(f, "{\"selector\":{\"currency\":\"USD\"}}") + + spec = &pb.ChaincodeSpec{Type: 1, ChaincodeID: cID, Input: &pb.ChaincodeInput{Args: args}} + _, _, _, err = invoke(ctxt, chainID, spec) + + if err != nil { + t.Fail() + t.Logf("Error invoking <%s>: %s", chaincodeID, err) + theChaincodeSupport.Stop(ctxt, cccid, &pb.ChaincodeDeploymentSpec{ChaincodeSpec: spec}) + return + } + } theChaincodeSupport.Stop(ctxt, cccid, &pb.ChaincodeDeploymentSpec{ChaincodeSpec: spec}) } diff --git a/core/chaincode/handler.go b/core/chaincode/handler.go index 513b45e288d..3d74fff07d7 100644 --- a/core/chaincode/handler.go +++ b/core/chaincode/handler.go @@ -57,7 +57,7 @@ type transactionContext struct { responseNotifier chan *pb.ChaincodeMessage // tracks open iterators used for range queries - rangeQueryIteratorMap map[string]ledger.ResultsIterator + queryIteratorMap map[string]ledger.ResultsIterator txsimulator ledger.TxSimulator } @@ -180,7 +180,7 @@ func (handler *Handler) createTxContext(ctxt context.Context, chainID string, tx return nil, fmt.Errorf("txid:%s exists", txid) } txctx := &transactionContext{chainID: chainID, proposal: prop, responseNotifier: make(chan *pb.ChaincodeMessage, 1), - rangeQueryIteratorMap: make(map[string]ledger.ResultsIterator)} + queryIteratorMap: make(map[string]ledger.ResultsIterator)} handler.txCtxs[txid] = txctx txctx.txsimulator = getTxSimulator(ctxt) @@ -201,23 +201,23 @@ func (handler *Handler) deleteTxContext(txid string) { } } -func (handler *Handler) putRangeQueryIterator(txContext *transactionContext, txid string, - rangeScanIterator ledger.ResultsIterator) { +func (handler *Handler) putQueryIterator(txContext *transactionContext, txid string, + queryIterator ledger.ResultsIterator) { handler.Lock() defer handler.Unlock() - txContext.rangeQueryIteratorMap[txid] = rangeScanIterator + txContext.queryIteratorMap[txid] = queryIterator } -func (handler *Handler) getRangeQueryIterator(txContext *transactionContext, txid string) ledger.ResultsIterator { +func (handler *Handler) getQueryIterator(txContext *transactionContext, txid string) ledger.ResultsIterator { handler.Lock() defer handler.Unlock() - return txContext.rangeQueryIteratorMap[txid] + return txContext.queryIteratorMap[txid] } -func (handler *Handler) deleteRangeQueryIterator(txContext *transactionContext, txid string) { +func (handler *Handler) deleteQueryIterator(txContext *transactionContext, txid string) { handler.Lock() defer handler.Unlock() - delete(txContext.rangeQueryIteratorMap, txid) + delete(txContext.queryIteratorMap, txid) } //THIS CAN BE REMOVED ONCE WE FULL SUPPORT (Invoke) CONFIDENTIALITY WITH CC-CALLING-CC @@ -385,10 +385,12 @@ func newChaincodeSupportHandler(chaincodeSupport *ChaincodeSupport, peerChatStre {Name: pb.ChaincodeMessage_GET_STATE.String(), Src: []string{initstate}, Dst: initstate}, {Name: pb.ChaincodeMessage_RANGE_QUERY_STATE.String(), Src: []string{readystate}, Dst: readystate}, {Name: pb.ChaincodeMessage_RANGE_QUERY_STATE.String(), Src: []string{initstate}, Dst: initstate}, - {Name: pb.ChaincodeMessage_RANGE_QUERY_STATE_NEXT.String(), Src: []string{readystate}, Dst: readystate}, - {Name: pb.ChaincodeMessage_RANGE_QUERY_STATE_NEXT.String(), Src: []string{initstate}, Dst: initstate}, - {Name: pb.ChaincodeMessage_RANGE_QUERY_STATE_CLOSE.String(), Src: []string{readystate}, Dst: readystate}, - {Name: pb.ChaincodeMessage_RANGE_QUERY_STATE_CLOSE.String(), Src: []string{initstate}, Dst: initstate}, + {Name: pb.ChaincodeMessage_EXECUTE_QUERY_STATE.String(), Src: []string{readystate}, Dst: readystate}, + {Name: pb.ChaincodeMessage_EXECUTE_QUERY_STATE.String(), Src: []string{initstate}, Dst: initstate}, + {Name: pb.ChaincodeMessage_QUERY_STATE_NEXT.String(), Src: []string{readystate}, Dst: readystate}, + {Name: pb.ChaincodeMessage_QUERY_STATE_NEXT.String(), Src: []string{initstate}, Dst: initstate}, + {Name: pb.ChaincodeMessage_QUERY_STATE_CLOSE.String(), Src: []string{readystate}, Dst: readystate}, + {Name: pb.ChaincodeMessage_QUERY_STATE_CLOSE.String(), Src: []string{initstate}, Dst: initstate}, {Name: pb.ChaincodeMessage_ERROR.String(), Src: []string{initstate}, Dst: endstate}, {Name: pb.ChaincodeMessage_ERROR.String(), Src: []string{readystate}, Dst: readystate}, {Name: pb.ChaincodeMessage_RESPONSE.String(), Src: []string{initstate}, Dst: initstate}, @@ -396,20 +398,21 @@ func newChaincodeSupportHandler(chaincodeSupport *ChaincodeSupport, peerChatStre {Name: pb.ChaincodeMessage_TRANSACTION.String(), Src: []string{readystate}, Dst: readystate}, }, fsm.Callbacks{ - "before_" + pb.ChaincodeMessage_REGISTER.String(): func(e *fsm.Event) { v.beforeRegisterEvent(e, v.FSM.Current()) }, - "before_" + pb.ChaincodeMessage_COMPLETED.String(): func(e *fsm.Event) { v.beforeCompletedEvent(e, v.FSM.Current()) }, - "before_" + pb.ChaincodeMessage_INIT.String(): func(e *fsm.Event) { v.beforeInitState(e, v.FSM.Current()) }, - "after_" + pb.ChaincodeMessage_GET_STATE.String(): func(e *fsm.Event) { v.afterGetState(e, v.FSM.Current()) }, - "after_" + pb.ChaincodeMessage_RANGE_QUERY_STATE.String(): func(e *fsm.Event) { v.afterRangeQueryState(e, v.FSM.Current()) }, - "after_" + pb.ChaincodeMessage_RANGE_QUERY_STATE_NEXT.String(): func(e *fsm.Event) { v.afterRangeQueryStateNext(e, v.FSM.Current()) }, - "after_" + pb.ChaincodeMessage_RANGE_QUERY_STATE_CLOSE.String(): func(e *fsm.Event) { v.afterRangeQueryStateClose(e, v.FSM.Current()) }, - "after_" + pb.ChaincodeMessage_PUT_STATE.String(): func(e *fsm.Event) { v.enterBusyState(e, v.FSM.Current()) }, - "after_" + pb.ChaincodeMessage_DEL_STATE.String(): func(e *fsm.Event) { v.enterBusyState(e, v.FSM.Current()) }, - "after_" + pb.ChaincodeMessage_INVOKE_CHAINCODE.String(): func(e *fsm.Event) { v.enterBusyState(e, v.FSM.Current()) }, - "enter_" + establishedstate: func(e *fsm.Event) { v.enterEstablishedState(e, v.FSM.Current()) }, - "enter_" + initstate: func(e *fsm.Event) { v.enterInitState(e, v.FSM.Current()) }, - "enter_" + readystate: func(e *fsm.Event) { v.enterReadyState(e, v.FSM.Current()) }, - "enter_" + endstate: func(e *fsm.Event) { v.enterEndState(e, v.FSM.Current()) }, + "before_" + pb.ChaincodeMessage_REGISTER.String(): func(e *fsm.Event) { v.beforeRegisterEvent(e, v.FSM.Current()) }, + "before_" + pb.ChaincodeMessage_COMPLETED.String(): func(e *fsm.Event) { v.beforeCompletedEvent(e, v.FSM.Current()) }, + "before_" + pb.ChaincodeMessage_INIT.String(): func(e *fsm.Event) { v.beforeInitState(e, v.FSM.Current()) }, + "after_" + pb.ChaincodeMessage_GET_STATE.String(): func(e *fsm.Event) { v.afterGetState(e, v.FSM.Current()) }, + "after_" + pb.ChaincodeMessage_RANGE_QUERY_STATE.String(): func(e *fsm.Event) { v.afterRangeQueryState(e, v.FSM.Current()) }, + "after_" + pb.ChaincodeMessage_EXECUTE_QUERY_STATE.String(): func(e *fsm.Event) { v.afterExecuteQueryState(e, v.FSM.Current()) }, + "after_" + pb.ChaincodeMessage_QUERY_STATE_NEXT.String(): func(e *fsm.Event) { v.afterQueryStateNext(e, v.FSM.Current()) }, + "after_" + pb.ChaincodeMessage_QUERY_STATE_CLOSE.String(): func(e *fsm.Event) { v.afterQueryStateClose(e, v.FSM.Current()) }, + "after_" + pb.ChaincodeMessage_PUT_STATE.String(): func(e *fsm.Event) { v.enterBusyState(e, v.FSM.Current()) }, + "after_" + pb.ChaincodeMessage_DEL_STATE.String(): func(e *fsm.Event) { v.enterBusyState(e, v.FSM.Current()) }, + "after_" + pb.ChaincodeMessage_INVOKE_CHAINCODE.String(): func(e *fsm.Event) { v.enterBusyState(e, v.FSM.Current()) }, + "enter_" + establishedstate: func(e *fsm.Event) { v.enterEstablishedState(e, v.FSM.Current()) }, + "enter_" + initstate: func(e *fsm.Event) { v.enterInitState(e, v.FSM.Current()) }, + "enter_" + readystate: func(e *fsm.Event) { v.enterReadyState(e, v.FSM.Current()) }, + "enter_" + endstate: func(e *fsm.Event) { v.enterEndState(e, v.FSM.Current()) }, }, ) @@ -495,8 +498,8 @@ func (handler *Handler) notify(msg *pb.ChaincodeMessage) { chaincodeLogger.Debugf("notifying Txid:%s", msg.Txid) tctx.responseNotifier <- msg - // clean up rangeQueryIteratorMap - for _, v := range tctx.rangeQueryIteratorMap { + // clean up queryIteratorMap + for _, v := range tctx.queryIteratorMap { v.Close() } } @@ -667,9 +670,9 @@ func (handler *Handler) handleRangeQueryState(msg *pb.ChaincodeMessage) { return } - handler.putRangeQueryIterator(txContext, iterID, rangeIter) + handler.putQueryIterator(txContext, iterID, rangeIter) - var keysAndValues []*pb.RangeQueryStateKeyValue + var keysAndValues []*pb.QueryStateKeyValue var i = uint32(0) var qresult ledger.QueryResult for ; i < maxRangeQueryStateLimit; i++ { @@ -682,20 +685,20 @@ func (handler *Handler) handleRangeQueryState(msg *pb.ChaincodeMessage) { break } kv := qresult.(*ledger.KV) - keyAndValue := pb.RangeQueryStateKeyValue{Key: kv.Key, Value: kv.Value} + keyAndValue := pb.QueryStateKeyValue{Key: kv.Key, Value: kv.Value} keysAndValues = append(keysAndValues, &keyAndValue) } if qresult != nil { rangeIter.Close() - handler.deleteRangeQueryIterator(txContext, iterID) + handler.deleteQueryIterator(txContext, iterID) } - payload := &pb.RangeQueryStateResponse{KeysAndValues: keysAndValues, HasMore: qresult != nil, ID: iterID} + payload := &pb.QueryStateResponse{KeysAndValues: keysAndValues, HasMore: qresult != nil, ID: iterID} payloadBytes, err := proto.Marshal(payload) if err != nil { rangeIter.Close() - handler.deleteRangeQueryIterator(txContext, iterID) + handler.deleteQueryIterator(txContext, iterID) // Send error msg back to chaincode. GetState will not trigger event payload := []byte(err.Error()) @@ -711,7 +714,7 @@ func (handler *Handler) handleRangeQueryState(msg *pb.ChaincodeMessage) { } // afterRangeQueryState handles a RANGE_QUERY_STATE_NEXT request from the chaincode. -func (handler *Handler) afterRangeQueryStateNext(e *fsm.Event, state string) { +func (handler *Handler) afterQueryStateNext(e *fsm.Event, state string) { msg, ok := e.Args[0].(*pb.ChaincodeMessage) if !ok { e.Cancel(fmt.Errorf("Received unexpected message type")) @@ -720,12 +723,12 @@ func (handler *Handler) afterRangeQueryStateNext(e *fsm.Event, state string) { chaincodeLogger.Debugf("Received %s, invoking get state from ledger", pb.ChaincodeMessage_RANGE_QUERY_STATE) // Query ledger for state - handler.handleRangeQueryStateNext(msg) + handler.handleQueryStateNext(msg) chaincodeLogger.Debug("Exiting RANGE_QUERY_STATE_NEXT") } // Handles query to ledger to rage query state next -func (handler *Handler) handleRangeQueryStateNext(msg *pb.ChaincodeMessage) { +func (handler *Handler) handleQueryStateNext(msg *pb.ChaincodeMessage) { // The defer followed by triggering a go routine dance is needed to ensure that the previous state transition // is completed before the next one is triggered. The previous state transition is deemed complete only when // the afterRangeQueryState function is exited. Interesting bug fix!! @@ -746,8 +749,8 @@ func (handler *Handler) handleRangeQueryStateNext(msg *pb.ChaincodeMessage) { handler.serialSendAsync(serialSendMsg, nil) }() - rangeQueryStateNext := &pb.RangeQueryStateNext{} - unmarshalErr := proto.Unmarshal(msg.Payload, rangeQueryStateNext) + queryStateNext := &pb.QueryStateNext{} + unmarshalErr := proto.Unmarshal(msg.Payload, queryStateNext) if unmarshalErr != nil { payload := []byte(unmarshalErr.Error()) chaincodeLogger.Errorf("Failed to unmarshall state range next query request. Sending %s", pb.ChaincodeMessage_ERROR) @@ -756,7 +759,7 @@ func (handler *Handler) handleRangeQueryStateNext(msg *pb.ChaincodeMessage) { } txContext := handler.getTxContext(msg.Txid) - rangeIter := handler.getRangeQueryIterator(txContext, rangeQueryStateNext.ID) + rangeIter := handler.getQueryIterator(txContext, queryStateNext.ID) if rangeIter == nil { payload := []byte("Range query iterator not found") @@ -765,7 +768,7 @@ func (handler *Handler) handleRangeQueryStateNext(msg *pb.ChaincodeMessage) { return } - var keysAndValues []*pb.RangeQueryStateKeyValue + var keysAndValues []*pb.QueryStateKeyValue var i = uint32(0) var qresult ledger.QueryResult @@ -780,20 +783,20 @@ func (handler *Handler) handleRangeQueryStateNext(msg *pb.ChaincodeMessage) { break } kv := qresult.(*ledger.KV) - keyAndValue := pb.RangeQueryStateKeyValue{Key: kv.Key, Value: kv.Value} + keyAndValue := pb.QueryStateKeyValue{Key: kv.Key, Value: kv.Value} keysAndValues = append(keysAndValues, &keyAndValue) } if qresult != nil { rangeIter.Close() - handler.deleteRangeQueryIterator(txContext, rangeQueryStateNext.ID) + handler.deleteQueryIterator(txContext, queryStateNext.ID) } - payload := &pb.RangeQueryStateResponse{KeysAndValues: keysAndValues, HasMore: qresult != nil, ID: rangeQueryStateNext.ID} + payload := &pb.QueryStateResponse{KeysAndValues: keysAndValues, HasMore: qresult != nil, ID: queryStateNext.ID} payloadBytes, err := proto.Marshal(payload) if err != nil { rangeIter.Close() - handler.deleteRangeQueryIterator(txContext, rangeQueryStateNext.ID) + handler.deleteQueryIterator(txContext, queryStateNext.ID) // Send error msg back to chaincode. GetState will not trigger event payload := []byte(err.Error()) @@ -809,7 +812,7 @@ func (handler *Handler) handleRangeQueryStateNext(msg *pb.ChaincodeMessage) { } // afterRangeQueryState handles a RANGE_QUERY_STATE_CLOSE request from the chaincode. -func (handler *Handler) afterRangeQueryStateClose(e *fsm.Event, state string) { +func (handler *Handler) afterQueryStateClose(e *fsm.Event, state string) { msg, ok := e.Args[0].(*pb.ChaincodeMessage) if !ok { e.Cancel(fmt.Errorf("Received unexpected message type")) @@ -818,12 +821,12 @@ func (handler *Handler) afterRangeQueryStateClose(e *fsm.Event, state string) { chaincodeLogger.Debugf("Received %s, invoking get state from ledger", pb.ChaincodeMessage_RANGE_QUERY_STATE) // Query ledger for state - handler.handleRangeQueryStateClose(msg) + handler.handleQueryStateClose(msg) chaincodeLogger.Debug("Exiting RANGE_QUERY_STATE_CLOSE") } // Handles the closing of a state iterator -func (handler *Handler) handleRangeQueryStateClose(msg *pb.ChaincodeMessage) { +func (handler *Handler) handleQueryStateClose(msg *pb.ChaincodeMessage) { // The defer followed by triggering a go routine dance is needed to ensure that the previous state transition // is completed before the next one is triggered. The previous state transition is deemed complete only when // the afterRangeQueryState function is exited. Interesting bug fix!! @@ -844,8 +847,8 @@ func (handler *Handler) handleRangeQueryStateClose(msg *pb.ChaincodeMessage) { handler.serialSendAsync(serialSendMsg, nil) }() - rangeQueryStateClose := &pb.RangeQueryStateClose{} - unmarshalErr := proto.Unmarshal(msg.Payload, rangeQueryStateClose) + queryStateClose := &pb.QueryStateClose{} + unmarshalErr := proto.Unmarshal(msg.Payload, queryStateClose) if unmarshalErr != nil { payload := []byte(unmarshalErr.Error()) chaincodeLogger.Errorf("Failed to unmarshall state range query close request. Sending %s", pb.ChaincodeMessage_ERROR) @@ -854,13 +857,13 @@ func (handler *Handler) handleRangeQueryStateClose(msg *pb.ChaincodeMessage) { } txContext := handler.getTxContext(msg.Txid) - iter := handler.getRangeQueryIterator(txContext, rangeQueryStateClose.ID) + iter := handler.getQueryIterator(txContext, queryStateClose.ID) if iter != nil { iter.Close() - handler.deleteRangeQueryIterator(txContext, rangeQueryStateClose.ID) + handler.deleteQueryIterator(txContext, queryStateClose.ID) } - payload := &pb.RangeQueryStateResponse{HasMore: false, ID: rangeQueryStateClose.ID} + payload := &pb.QueryStateResponse{HasMore: false, ID: queryStateClose.ID} payloadBytes, err := proto.Marshal(payload) if err != nil { @@ -877,6 +880,114 @@ func (handler *Handler) handleRangeQueryStateClose(msg *pb.ChaincodeMessage) { }() } +const maxExecuteQueryStateLimit = 100 + +// afterExecuteQueryState handles a EXECUTE_QUERY_STATE request from the chaincode. +func (handler *Handler) afterExecuteQueryState(e *fsm.Event, state string) { + msg, ok := e.Args[0].(*pb.ChaincodeMessage) + if !ok { + e.Cancel(fmt.Errorf("Received unexpected message type")) + return + } + chaincodeLogger.Debugf("Received %s, invoking get state from ledger", pb.ChaincodeMessage_EXECUTE_QUERY_STATE) + + // Query ledger for state + handler.handleExecuteQueryState(msg) + chaincodeLogger.Debug("Exiting EXECUTE_QUERY_STATE") +} + +// Handles query to ledger to execute query state +func (handler *Handler) handleExecuteQueryState(msg *pb.ChaincodeMessage) { + // The defer followed by triggering a go routine dance is needed to ensure that the previous state transition + // is completed before the next one is triggered. The previous state transition is deemed complete only when + // the afterQueryState function is exited. Interesting bug fix!! + go func() { + // Check if this is the unique state request from this chaincode txid + uniqueReq := handler.createTXIDEntry(msg.Txid) + if !uniqueReq { + // Drop this request + chaincodeLogger.Error("Another state request pending for this Txid. Cannot process.") + return + } + + var serialSendMsg *pb.ChaincodeMessage + + defer func() { + handler.deleteTXIDEntry(msg.Txid) + chaincodeLogger.Debugf("[%s]handleExecuteQueryState serial send %s", shorttxid(serialSendMsg.Txid), serialSendMsg.Type) + handler.serialSendAsync(serialSendMsg, nil) + }() + + executeQueryState := &pb.ExecuteQueryState{} + unmarshalErr := proto.Unmarshal(msg.Payload, executeQueryState) + if unmarshalErr != nil { + payload := []byte(unmarshalErr.Error()) + chaincodeLogger.Errorf("Failed to unmarshall range query request. Sending %s", pb.ChaincodeMessage_ERROR) + serialSendMsg = &pb.ChaincodeMessage{Type: pb.ChaincodeMessage_ERROR, Payload: payload, Txid: msg.Txid} + return + } + + iterID := util.GenerateUUID() + + var txContext *transactionContext + + txContext, serialSendMsg = handler.isValidTxSim(msg.Txid, "[%s]No ledger context for ExecuteQueryState. Sending %s", shorttxid(msg.Txid), pb.ChaincodeMessage_ERROR) + if txContext == nil { + return + } + fmt.Println("==CENDHU==" + executeQueryState.Query) + executeIter, err := txContext.txsimulator.ExecuteQuery(executeQueryState.Query) + if err != nil { + // Send error msg back to chaincode. GetState will not trigger event + payload := []byte(err.Error()) + chaincodeLogger.Errorf("Failed to get ledger scan iterator. Sending %s", pb.ChaincodeMessage_ERROR) + serialSendMsg = &pb.ChaincodeMessage{Type: pb.ChaincodeMessage_ERROR, Payload: payload, Txid: msg.Txid} + return + } + + handler.putQueryIterator(txContext, iterID, executeIter) + + var keysAndValues []*pb.QueryStateKeyValue + var i = uint32(0) + var qresult ledger.QueryResult + for ; i < maxExecuteQueryStateLimit; i++ { + qresult, err := executeIter.Next() + if err != nil { + chaincodeLogger.Errorf("Failed to get query result from iterator. Sending %s", pb.ChaincodeMessage_ERROR) + return + } + if qresult == nil { + break + } + kv := qresult.(*ledger.KV) + keyAndValue := pb.QueryStateKeyValue{Key: kv.Key, Value: kv.Value} + keysAndValues = append(keysAndValues, &keyAndValue) + } + + if qresult != nil { + executeIter.Close() + handler.deleteQueryIterator(txContext, iterID) + } + + payload := &pb.QueryStateResponse{KeysAndValues: keysAndValues, HasMore: qresult != nil, ID: iterID} + payloadBytes, err := proto.Marshal(payload) + if err != nil { + executeIter.Close() + handler.deleteQueryIterator(txContext, iterID) + + // Send error msg back to chaincode. GetState will not trigger event + payload := []byte(err.Error()) + chaincodeLogger.Errorf("Failed marshall resopnse. Sending %s", pb.ChaincodeMessage_ERROR) + serialSendMsg = &pb.ChaincodeMessage{Type: pb.ChaincodeMessage_ERROR, Payload: payload, Txid: msg.Txid} + return + } + + chaincodeLogger.Debugf("Got keys and values. Sending %s", pb.ChaincodeMessage_RESPONSE) + serialSendMsg = &pb.ChaincodeMessage{Type: pb.ChaincodeMessage_RESPONSE, Payload: payloadBytes, Txid: msg.Txid} + + }() +} + // afterPutState handles a PUT_STATE request from the chaincode. func (handler *Handler) afterPutState(e *fsm.Event, state string) { _, ok := e.Args[0].(*pb.ChaincodeMessage) diff --git a/core/chaincode/shim/chaincode.go b/core/chaincode/shim/chaincode.go index 2345adef63a..ed8176f53e6 100644 --- a/core/chaincode/shim/chaincode.go +++ b/core/chaincode/shim/chaincode.go @@ -315,12 +315,12 @@ func (stub *ChaincodeStub) DelState(key string) error { return stub.handler.handleDelState(key, stub.TxID) } -// StateRangeQueryIterator allows a chaincode to iterate over a range of +// StateQueryIterator allows a chaincode to iterate over a set of // key/value pairs in the state. -type StateRangeQueryIterator struct { +type StateQueryIterator struct { handler *Handler uuid string - response *pb.RangeQueryStateResponse + response *pb.QueryStateResponse currentLoc int } @@ -329,12 +329,21 @@ type StateRangeQueryIterator struct { // an iterator will be returned that can be used to iterate over all keys // between the startKey and endKey, inclusive. The order in which keys are // returned by the iterator is random. -func (stub *ChaincodeStub) RangeQueryState(startKey, endKey string) (StateRangeQueryIteratorInterface, error) { +func (stub *ChaincodeStub) RangeQueryState(startKey, endKey string) (StateQueryIteratorInterface, error) { response, err := stub.handler.handleRangeQueryState(startKey, endKey, stub.TxID) if err != nil { return nil, err } - return &StateRangeQueryIterator{stub.handler, stub.TxID, response, 0}, nil + return &StateQueryIterator{stub.handler, stub.TxID, response, 0}, nil +} + +func (stub *ChaincodeStub) ExecuteQuery(query string) (StateQueryIteratorInterface, error) { + response, err := stub.handler.handleExecuteQueryState(query, stub.TxID) + if err != nil { + return nil, err + } + return &StateQueryIterator{stub.handler, stub.TxID, response, 0}, nil + } //Given a list of attributes, createCompositeKey function combines these attributes @@ -359,11 +368,11 @@ func createCompositeKey(stub ChaincodeStubInterface, objectType string, attribut //matches the given partial composite key. This function should be used only for //a partial composite key. For a full composite key, an iter with empty response //would be returned. -func (stub *ChaincodeStub) PartialCompositeKeyQuery(objectType string, attributes []string) (StateRangeQueryIteratorInterface, error) { +func (stub *ChaincodeStub) PartialCompositeKeyQuery(objectType string, attributes []string) (StateQueryIteratorInterface, error) { return partialCompositeKeyQuery(stub, objectType, attributes) } -func partialCompositeKeyQuery(stub ChaincodeStubInterface, objectType string, attributes []string) (StateRangeQueryIteratorInterface, error) { +func partialCompositeKeyQuery(stub ChaincodeStubInterface, objectType string, attributes []string) (StateQueryIteratorInterface, error) { partialCompositeKey, _ := stub.CreateCompositeKey(objectType, attributes) keysIter, err := stub.RangeQueryState(partialCompositeKey+"1", partialCompositeKey+":") if err != nil { @@ -374,7 +383,7 @@ func partialCompositeKeyQuery(stub ChaincodeStubInterface, objectType string, at // HasNext returns true if the range query iterator contains additional keys // and values. -func (iter *StateRangeQueryIterator) HasNext() bool { +func (iter *StateQueryIterator) HasNext() bool { if iter.currentLoc < len(iter.response.KeysAndValues) || iter.response.HasMore { return true } @@ -382,7 +391,7 @@ func (iter *StateRangeQueryIterator) HasNext() bool { } // Next returns the next key and value in the range query iterator. -func (iter *StateRangeQueryIterator) Next() (string, []byte, error) { +func (iter *StateQueryIterator) Next() (string, []byte, error) { if iter.currentLoc < len(iter.response.KeysAndValues) { keyValue := iter.response.KeysAndValues[iter.currentLoc] iter.currentLoc++ @@ -390,7 +399,7 @@ func (iter *StateRangeQueryIterator) Next() (string, []byte, error) { } else if !iter.response.HasMore { return "", nil, errors.New("No such key") } else { - response, err := iter.handler.handleRangeQueryStateNext(iter.response.ID, iter.uuid) + response, err := iter.handler.handleQueryStateNext(iter.response.ID, iter.uuid) if err != nil { return "", nil, err @@ -407,8 +416,8 @@ func (iter *StateRangeQueryIterator) Next() (string, []byte, error) { // Close closes the range query iterator. This should be called when done // reading from the iterator to free up resources. -func (iter *StateRangeQueryIterator) Close() error { - _, err := iter.handler.handleRangeQueryStateClose(iter.response.ID, iter.uuid) +func (iter *StateQueryIterator) Close() error { + _, err := iter.handler.handleQueryStateClose(iter.response.ID, iter.uuid) return err } diff --git a/core/chaincode/shim/handler.go b/core/chaincode/shim/handler.go index 0bd9f330a44..0292ddf3a6e 100644 --- a/core/chaincode/shim/handler.go +++ b/core/chaincode/shim/handler.go @@ -494,7 +494,7 @@ func (handler *Handler) handleDelState(key string, txid string) error { return errors.New("Incorrect chaincode message received") } -func (handler *Handler) handleRangeQueryState(startKey, endKey string, txid string) (*pb.RangeQueryStateResponse, error) { +func (handler *Handler) handleRangeQueryState(startKey, endKey string, txid string) (*pb.QueryStateResponse, error) { // Create the channel on which to communicate the response from validating peer respChan, uniqueReqErr := handler.createChannel(txid) if uniqueReqErr != nil { @@ -522,7 +522,7 @@ func (handler *Handler) handleRangeQueryState(startKey, endKey string, txid stri // Success response chaincodeLogger.Debugf("[%s]Received %s. Successfully got range", shorttxid(responseMsg.Txid), pb.ChaincodeMessage_RESPONSE) - rangeQueryResponse := &pb.RangeQueryStateResponse{} + rangeQueryResponse := &pb.QueryStateResponse{} unmarshalErr := proto.Unmarshal(responseMsg.Payload, rangeQueryResponse) if unmarshalErr != nil { chaincodeLogger.Errorf("[%s]unmarshall error", shorttxid(responseMsg.Txid)) @@ -542,7 +542,7 @@ func (handler *Handler) handleRangeQueryState(startKey, endKey string, txid stri return nil, errors.New("Incorrect chaincode message received") } -func (handler *Handler) handleRangeQueryStateNext(id, txid string) (*pb.RangeQueryStateResponse, error) { +func (handler *Handler) handleQueryStateNext(id, txid string) (*pb.QueryStateResponse, error) { // Create the channel on which to communicate the response from validating peer respChan, uniqueReqErr := handler.createChannel(txid) if uniqueReqErr != nil { @@ -553,16 +553,16 @@ func (handler *Handler) handleRangeQueryStateNext(id, txid string) (*pb.RangeQue defer handler.deleteChannel(txid) // Send RANGE_QUERY_STATE_NEXT message to validator chaincode support - payload := &pb.RangeQueryStateNext{ID: id} + payload := &pb.QueryStateNext{ID: id} payloadBytes, err := proto.Marshal(payload) if err != nil { return nil, errors.New("Failed to process range query state next request") } - msg := &pb.ChaincodeMessage{Type: pb.ChaincodeMessage_RANGE_QUERY_STATE_NEXT, Payload: payloadBytes, Txid: txid} - chaincodeLogger.Debugf("[%s]Sending %s", shorttxid(msg.Txid), pb.ChaincodeMessage_RANGE_QUERY_STATE_NEXT) + msg := &pb.ChaincodeMessage{Type: pb.ChaincodeMessage_QUERY_STATE_NEXT, Payload: payloadBytes, Txid: txid} + chaincodeLogger.Debugf("[%s]Sending %s", shorttxid(msg.Txid), pb.ChaincodeMessage_QUERY_STATE_NEXT) responseMsg, err := handler.sendReceive(msg, respChan) if err != nil { - chaincodeLogger.Errorf("[%s]error sending %s", shorttxid(msg.Txid), pb.ChaincodeMessage_RANGE_QUERY_STATE_NEXT) + chaincodeLogger.Errorf("[%s]error sending %s", shorttxid(msg.Txid), pb.ChaincodeMessage_QUERY_STATE_NEXT) return nil, errors.New("could not send msg") } @@ -570,14 +570,14 @@ func (handler *Handler) handleRangeQueryStateNext(id, txid string) (*pb.RangeQue // Success response chaincodeLogger.Debugf("[%s]Received %s. Successfully got range", shorttxid(responseMsg.Txid), pb.ChaincodeMessage_RESPONSE) - rangeQueryResponse := &pb.RangeQueryStateResponse{} - unmarshalErr := proto.Unmarshal(responseMsg.Payload, rangeQueryResponse) + queryResponse := &pb.QueryStateResponse{} + unmarshalErr := proto.Unmarshal(responseMsg.Payload, queryResponse) if unmarshalErr != nil { chaincodeLogger.Errorf("[%s]unmarshall error", shorttxid(responseMsg.Txid)) return nil, errors.New("Error unmarshalling RangeQueryStateResponse.") } - return rangeQueryResponse, nil + return queryResponse, nil } if responseMsg.Type.String() == pb.ChaincodeMessage_ERROR.String() { // Error response @@ -590,7 +590,7 @@ func (handler *Handler) handleRangeQueryStateNext(id, txid string) (*pb.RangeQue return nil, errors.New("Incorrect chaincode message received") } -func (handler *Handler) handleRangeQueryStateClose(id, txid string) (*pb.RangeQueryStateResponse, error) { +func (handler *Handler) handleQueryStateClose(id, txid string) (*pb.QueryStateResponse, error) { // Create the channel on which to communicate the response from validating peer respChan, uniqueReqErr := handler.createChannel(txid) if uniqueReqErr != nil { @@ -601,16 +601,16 @@ func (handler *Handler) handleRangeQueryStateClose(id, txid string) (*pb.RangeQu defer handler.deleteChannel(txid) // Send RANGE_QUERY_STATE_CLOSE message to validator chaincode support - payload := &pb.RangeQueryStateClose{ID: id} + payload := &pb.QueryStateClose{ID: id} payloadBytes, err := proto.Marshal(payload) if err != nil { return nil, errors.New("Failed to process range query state close request") } - msg := &pb.ChaincodeMessage{Type: pb.ChaincodeMessage_RANGE_QUERY_STATE_CLOSE, Payload: payloadBytes, Txid: txid} - chaincodeLogger.Debugf("[%s]Sending %s", shorttxid(msg.Txid), pb.ChaincodeMessage_RANGE_QUERY_STATE_CLOSE) + msg := &pb.ChaincodeMessage{Type: pb.ChaincodeMessage_QUERY_STATE_CLOSE, Payload: payloadBytes, Txid: txid} + chaincodeLogger.Debugf("[%s]Sending %s", shorttxid(msg.Txid), pb.ChaincodeMessage_QUERY_STATE_CLOSE) responseMsg, err := handler.sendReceive(msg, respChan) if err != nil { - chaincodeLogger.Errorf("[%s]error sending %s", shorttxid(msg.Txid), pb.ChaincodeMessage_RANGE_QUERY_STATE_CLOSE) + chaincodeLogger.Errorf("[%s]error sending %s", shorttxid(msg.Txid), pb.ChaincodeMessage_QUERY_STATE_CLOSE) return nil, errors.New("could not send msg") } @@ -618,14 +618,62 @@ func (handler *Handler) handleRangeQueryStateClose(id, txid string) (*pb.RangeQu // Success response chaincodeLogger.Debugf("[%s]Received %s. Successfully got range", shorttxid(responseMsg.Txid), pb.ChaincodeMessage_RESPONSE) - rangeQueryResponse := &pb.RangeQueryStateResponse{} - unmarshalErr := proto.Unmarshal(responseMsg.Payload, rangeQueryResponse) + queryResponse := &pb.QueryStateResponse{} + unmarshalErr := proto.Unmarshal(responseMsg.Payload, queryResponse) if unmarshalErr != nil { chaincodeLogger.Errorf("[%s]unmarshall error", shorttxid(responseMsg.Txid)) return nil, errors.New("Error unmarshalling RangeQueryStateResponse.") } - return rangeQueryResponse, nil + return queryResponse, nil + } + if responseMsg.Type.String() == pb.ChaincodeMessage_ERROR.String() { + // Error response + chaincodeLogger.Errorf("[%s]Received %s", shorttxid(responseMsg.Txid), pb.ChaincodeMessage_ERROR) + return nil, errors.New(string(responseMsg.Payload[:])) + } + + // Incorrect chaincode message received + chaincodeLogger.Errorf("Incorrect chaincode message %s recieved. Expecting %s or %s", responseMsg.Type, pb.ChaincodeMessage_RESPONSE, pb.ChaincodeMessage_ERROR) + return nil, errors.New("Incorrect chaincode message received") +} + +func (handler *Handler) handleExecuteQueryState(query string, txid string) (*pb.QueryStateResponse, error) { + // Create the channel on which to communicate the response from validating peer + respChan, uniqueReqErr := handler.createChannel(txid) + if uniqueReqErr != nil { + chaincodeLogger.Debugf("[%s]Another state request pending for this Txid. Cannot process.", shorttxid(txid)) + return nil, uniqueReqErr + } + + defer handler.deleteChannel(txid) + + // Send EXECUTE_QUERY_STATE message to validator chaincode support + payload := &pb.ExecuteQueryState{Query: query} + payloadBytes, err := proto.Marshal(payload) + if err != nil { + return nil, errors.New("Failed to process range query state request") + } + msg := &pb.ChaincodeMessage{Type: pb.ChaincodeMessage_EXECUTE_QUERY_STATE, Payload: payloadBytes, Txid: txid} + chaincodeLogger.Debugf("[%s]Sending %s", shorttxid(msg.Txid), pb.ChaincodeMessage_EXECUTE_QUERY_STATE) + responseMsg, err := handler.sendReceive(msg, respChan) + if err != nil { + chaincodeLogger.Errorf("[%s]error sending %s", shorttxid(msg.Txid), pb.ChaincodeMessage_EXECUTE_QUERY_STATE) + return nil, errors.New("could not send msg") + } + + if responseMsg.Type.String() == pb.ChaincodeMessage_RESPONSE.String() { + // Success response + chaincodeLogger.Debugf("[%s]Received %s. Successfully got range", shorttxid(responseMsg.Txid), pb.ChaincodeMessage_RESPONSE) + + executeQueryResponse := &pb.QueryStateResponse{} + unmarshalErr := proto.Unmarshal(responseMsg.Payload, executeQueryResponse) + if unmarshalErr != nil { + chaincodeLogger.Errorf("[%s]unmarshall error", shorttxid(responseMsg.Txid)) + return nil, errors.New("Error unmarshalling QueryStateResponse.") + } + + return executeQueryResponse, nil } if responseMsg.Type.String() == pb.ChaincodeMessage_ERROR.String() { // Error response diff --git a/core/chaincode/shim/interfaces.go b/core/chaincode/shim/interfaces.go index 34639520f01..0c43ce01a09 100644 --- a/core/chaincode/shim/interfaces.go +++ b/core/chaincode/shim/interfaces.go @@ -68,7 +68,7 @@ type ChaincodeStubInterface interface { // an iterator will be returned that can be used to iterate over all keys // between the startKey and endKey, inclusive. The order in which keys are // returned by the iterator is random. - RangeQueryState(startKey, endKey string) (StateRangeQueryIteratorInterface, error) + RangeQueryState(startKey, endKey string) (StateQueryIteratorInterface, error) //PartialCompositeKeyQuery function can be invoked by a chaincode to query the //state based on a given partial composite key. This function returns an @@ -76,12 +76,14 @@ type ChaincodeStubInterface interface { //matches the given partial composite key. This function should be used only for //a partial composite key. For a full composite key, an iter with empty response //would be returned. - PartialCompositeKeyQuery(objectType string, keys []string) (StateRangeQueryIteratorInterface, error) + PartialCompositeKeyQuery(objectType string, keys []string) (StateQueryIteratorInterface, error) //Given a list of attributes, createCompundKey function combines these attributes //to form a composite key. CreateCompositeKey(objectType string, attributes []string) (string, error) + ExecuteQuery(query string) (StateQueryIteratorInterface, error) + // GetCallerCertificate returns caller certificate GetCallerCertificate() ([]byte, error) @@ -104,9 +106,9 @@ type ChaincodeStubInterface interface { SetEvent(name string, payload []byte) error } -// StateRangeQueryIteratorInterface allows a chaincode to iterate over a range of +// StateQueryIteratorInterface allows a chaincode to iterate over a set of // key/value pairs in the state. -type StateRangeQueryIteratorInterface interface { +type StateQueryIteratorInterface interface { // HasNext returns true if the range query iterator contains additional keys // and values. diff --git a/core/chaincode/shim/java/src/main/java/org/hyperledger/java/shim/ChaincodeStub.java b/core/chaincode/shim/java/src/main/java/org/hyperledger/java/shim/ChaincodeStub.java index f5bb20becb2..d842b231967 100644 --- a/core/chaincode/shim/java/src/main/java/org/hyperledger/java/shim/ChaincodeStub.java +++ b/core/chaincode/shim/java/src/main/java/org/hyperledger/java/shim/ChaincodeStub.java @@ -102,7 +102,7 @@ public Map rangeQueryState(String startKey, String endKey) { */ public Map rangeQueryRawState(String startKey, String endKey) { Map map = new HashMap<>(); - for (Chaincode.RangeQueryStateKeyValue mapping : handler.handleRangeQueryState( + for (Chaincode.QueryStateKeyValue mapping : handler.handleRangeQueryState( startKey, endKey, uuid).getKeysAndValuesList()) { map.put(mapping.getKey(), mapping.getValue()); } diff --git a/core/chaincode/shim/java/src/main/java/org/hyperledger/java/shim/Handler.java b/core/chaincode/shim/java/src/main/java/org/hyperledger/java/shim/Handler.java index 37a17ae3918..6d8b0f5cd85 100644 --- a/core/chaincode/shim/java/src/main/java/org/hyperledger/java/shim/Handler.java +++ b/core/chaincode/shim/java/src/main/java/org/hyperledger/java/shim/Handler.java @@ -599,7 +599,7 @@ public void handleDeleteState(String key, String uuid) { } } - public RangeQueryStateResponse handleRangeQueryState(String startKey, String endKey, String uuid) { + public QueryStateResponse handleRangeQueryState(String startKey, String endKey, String uuid) { // Create the channel on which to communicate the response from validating peer Channel responseChannel; try { @@ -646,9 +646,9 @@ public RangeQueryStateResponse handleRangeQueryState(String startKey, String end logger.debug(String.format("[%s]Received %s. Successfully got range", shortID(response.getTxid()), RESPONSE)); - RangeQueryStateResponse rangeQueryResponse; + QueryStateResponse rangeQueryResponse; try { - rangeQueryResponse = RangeQueryStateResponse.parseFrom(response.getPayload()); + rangeQueryResponse = QueryStateResponse.parseFrom(response.getPayload()); } catch (Exception e) { logger.error(String.format("[%s]unmarshall error", shortID(response.getTxid()))); throw new RuntimeException("Error unmarshalling RangeQueryStateResponse."); diff --git a/core/chaincode/shim/mockstub.go b/core/chaincode/shim/mockstub.go index bf209d4adea..8b9e4fa4285 100644 --- a/core/chaincode/shim/mockstub.go +++ b/core/chaincode/shim/mockstub.go @@ -188,17 +188,21 @@ func (stub *MockStub) DelState(key string) error { return nil } -func (stub *MockStub) RangeQueryState(startKey, endKey string) (StateRangeQueryIteratorInterface, error) { +func (stub *MockStub) RangeQueryState(startKey, endKey string) (StateQueryIteratorInterface, error) { return NewMockStateRangeQueryIterator(stub, startKey, endKey), nil } +func (stub *MockStub) ExecuteQuery(query string) (StateQueryIteratorInterface, error) { + return nil, errors.New("Not Implemented") +} + //PartialCompositeKeyQuery function can be invoked by a chaincode to query the //state based on a given partial composite key. This function returns an //iterator which can be used to iterate over all composite keys whose prefix //matches the given partial composite key. This function should be used only for //a partial composite key. For a full composite key, an iter with empty response //would be returned. -func (stub *MockStub) PartialCompositeKeyQuery(objectType string, attributes []string) (StateRangeQueryIteratorInterface, error) { +func (stub *MockStub) PartialCompositeKeyQuery(objectType string, attributes []string) (StateQueryIteratorInterface, error) { return partialCompositeKeyQuery(stub, objectType, attributes) } diff --git a/examples/chaincode/go/map/map.go b/examples/chaincode/go/map/map.go index 568cb8238fb..593e4f4631f 100644 --- a/examples/chaincode/go/map/map.go +++ b/examples/chaincode/go/map/map.go @@ -86,7 +86,13 @@ func (t *SimpleChaincode) Invoke(stub shim.ChaincodeStubInterface) pb.Response { return shim.Success(value) case "keys": - keysIter, err := stub.RangeQueryState("", "") + if len(args) < 2 { + return shim.Error("put operation must include two arguments, a key and value") + } + startKey := args[0] + endKey := args[1] + + keysIter, err := stub.RangeQueryState(startKey, endKey) if err != nil { return shim.Error(fmt.Sprintf("keys operation failed. Error accessing state: %s", err)) } @@ -106,6 +112,29 @@ func (t *SimpleChaincode) Invoke(stub shim.ChaincodeStubInterface) pb.Response { return shim.Error(fmt.Sprintf("keys operation failed. Error marshaling JSON: %s", err)) } + return shim.Success(jsonKeys) + case "query": + query := args[0] + keysIter, err := stub.ExecuteQuery(query) + if err != nil { + return shim.Error(fmt.Sprintf("query operation failed. Error accessing state: %s", err)) + } + defer keysIter.Close() + + var keys []string + for keysIter.HasNext() { + key, _, iterErr := keysIter.Next() + if iterErr != nil { + return shim.Error(fmt.Sprintf("query operation failed. Error accessing state: %s", err)) + } + keys = append(keys, key) + } + + jsonKeys, err := json.Marshal(keys) + if err != nil { + return shim.Error(fmt.Sprintf("query operation failed. Error marshaling JSON: %s", err)) + } + return shim.Success(jsonKeys) default: diff --git a/protos/peer/chaincode.pb.go b/protos/peer/chaincode.pb.go index 5030e7f7f64..9ba60698a74 100644 --- a/protos/peer/chaincode.pb.go +++ b/protos/peer/chaincode.pb.go @@ -97,23 +97,24 @@ func (ChaincodeDeploymentSpec_ExecutionEnvironment) EnumDescriptor() ([]byte, [] type ChaincodeMessage_Type int32 const ( - ChaincodeMessage_UNDEFINED ChaincodeMessage_Type = 0 - ChaincodeMessage_REGISTER ChaincodeMessage_Type = 1 - ChaincodeMessage_REGISTERED ChaincodeMessage_Type = 2 - ChaincodeMessage_INIT ChaincodeMessage_Type = 3 - ChaincodeMessage_READY ChaincodeMessage_Type = 4 - ChaincodeMessage_TRANSACTION ChaincodeMessage_Type = 5 - ChaincodeMessage_COMPLETED ChaincodeMessage_Type = 6 - ChaincodeMessage_ERROR ChaincodeMessage_Type = 7 - ChaincodeMessage_GET_STATE ChaincodeMessage_Type = 8 - ChaincodeMessage_PUT_STATE ChaincodeMessage_Type = 9 - ChaincodeMessage_DEL_STATE ChaincodeMessage_Type = 10 - ChaincodeMessage_INVOKE_CHAINCODE ChaincodeMessage_Type = 11 - ChaincodeMessage_RESPONSE ChaincodeMessage_Type = 13 - ChaincodeMessage_RANGE_QUERY_STATE ChaincodeMessage_Type = 14 - ChaincodeMessage_RANGE_QUERY_STATE_NEXT ChaincodeMessage_Type = 15 - ChaincodeMessage_RANGE_QUERY_STATE_CLOSE ChaincodeMessage_Type = 16 - ChaincodeMessage_KEEPALIVE ChaincodeMessage_Type = 17 + ChaincodeMessage_UNDEFINED ChaincodeMessage_Type = 0 + ChaincodeMessage_REGISTER ChaincodeMessage_Type = 1 + ChaincodeMessage_REGISTERED ChaincodeMessage_Type = 2 + ChaincodeMessage_INIT ChaincodeMessage_Type = 3 + ChaincodeMessage_READY ChaincodeMessage_Type = 4 + ChaincodeMessage_TRANSACTION ChaincodeMessage_Type = 5 + ChaincodeMessage_COMPLETED ChaincodeMessage_Type = 6 + ChaincodeMessage_ERROR ChaincodeMessage_Type = 7 + ChaincodeMessage_GET_STATE ChaincodeMessage_Type = 8 + ChaincodeMessage_PUT_STATE ChaincodeMessage_Type = 9 + ChaincodeMessage_DEL_STATE ChaincodeMessage_Type = 10 + ChaincodeMessage_INVOKE_CHAINCODE ChaincodeMessage_Type = 11 + ChaincodeMessage_RESPONSE ChaincodeMessage_Type = 13 + ChaincodeMessage_RANGE_QUERY_STATE ChaincodeMessage_Type = 14 + ChaincodeMessage_EXECUTE_QUERY_STATE ChaincodeMessage_Type = 15 + ChaincodeMessage_QUERY_STATE_NEXT ChaincodeMessage_Type = 16 + ChaincodeMessage_QUERY_STATE_CLOSE ChaincodeMessage_Type = 17 + ChaincodeMessage_KEEPALIVE ChaincodeMessage_Type = 18 ) var ChaincodeMessage_Type_name = map[int32]string{ @@ -131,28 +132,30 @@ var ChaincodeMessage_Type_name = map[int32]string{ 11: "INVOKE_CHAINCODE", 13: "RESPONSE", 14: "RANGE_QUERY_STATE", - 15: "RANGE_QUERY_STATE_NEXT", - 16: "RANGE_QUERY_STATE_CLOSE", - 17: "KEEPALIVE", + 15: "EXECUTE_QUERY_STATE", + 16: "QUERY_STATE_NEXT", + 17: "QUERY_STATE_CLOSE", + 18: "KEEPALIVE", } var ChaincodeMessage_Type_value = map[string]int32{ - "UNDEFINED": 0, - "REGISTER": 1, - "REGISTERED": 2, - "INIT": 3, - "READY": 4, - "TRANSACTION": 5, - "COMPLETED": 6, - "ERROR": 7, - "GET_STATE": 8, - "PUT_STATE": 9, - "DEL_STATE": 10, - "INVOKE_CHAINCODE": 11, - "RESPONSE": 13, - "RANGE_QUERY_STATE": 14, - "RANGE_QUERY_STATE_NEXT": 15, - "RANGE_QUERY_STATE_CLOSE": 16, - "KEEPALIVE": 17, + "UNDEFINED": 0, + "REGISTER": 1, + "REGISTERED": 2, + "INIT": 3, + "READY": 4, + "TRANSACTION": 5, + "COMPLETED": 6, + "ERROR": 7, + "GET_STATE": 8, + "PUT_STATE": 9, + "DEL_STATE": 10, + "INVOKE_CHAINCODE": 11, + "RESPONSE": 13, + "RANGE_QUERY_STATE": 14, + "EXECUTE_QUERY_STATE": 15, + "QUERY_STATE_NEXT": 16, + "QUERY_STATE_CLOSE": 17, + "KEEPALIVE": 18, } func (x ChaincodeMessage_Type) String() string { @@ -350,46 +353,55 @@ func (m *RangeQueryState) String() string { return proto.CompactTextS func (*RangeQueryState) ProtoMessage() {} func (*RangeQueryState) Descriptor() ([]byte, []int) { return fileDescriptor1, []int{8} } -type RangeQueryStateNext struct { +type ExecuteQueryState struct { + Query string `protobuf:"bytes,1,opt,name=query" json:"query,omitempty"` +} + +func (m *ExecuteQueryState) Reset() { *m = ExecuteQueryState{} } +func (m *ExecuteQueryState) String() string { return proto.CompactTextString(m) } +func (*ExecuteQueryState) ProtoMessage() {} +func (*ExecuteQueryState) Descriptor() ([]byte, []int) { return fileDescriptor1, []int{9} } + +type QueryStateNext struct { ID string `protobuf:"bytes,1,opt,name=ID" json:"ID,omitempty"` } -func (m *RangeQueryStateNext) Reset() { *m = RangeQueryStateNext{} } -func (m *RangeQueryStateNext) String() string { return proto.CompactTextString(m) } -func (*RangeQueryStateNext) ProtoMessage() {} -func (*RangeQueryStateNext) Descriptor() ([]byte, []int) { return fileDescriptor1, []int{9} } +func (m *QueryStateNext) Reset() { *m = QueryStateNext{} } +func (m *QueryStateNext) String() string { return proto.CompactTextString(m) } +func (*QueryStateNext) ProtoMessage() {} +func (*QueryStateNext) Descriptor() ([]byte, []int) { return fileDescriptor1, []int{10} } -type RangeQueryStateClose struct { +type QueryStateClose struct { ID string `protobuf:"bytes,1,opt,name=ID" json:"ID,omitempty"` } -func (m *RangeQueryStateClose) Reset() { *m = RangeQueryStateClose{} } -func (m *RangeQueryStateClose) String() string { return proto.CompactTextString(m) } -func (*RangeQueryStateClose) ProtoMessage() {} -func (*RangeQueryStateClose) Descriptor() ([]byte, []int) { return fileDescriptor1, []int{10} } +func (m *QueryStateClose) Reset() { *m = QueryStateClose{} } +func (m *QueryStateClose) String() string { return proto.CompactTextString(m) } +func (*QueryStateClose) ProtoMessage() {} +func (*QueryStateClose) Descriptor() ([]byte, []int) { return fileDescriptor1, []int{11} } -type RangeQueryStateKeyValue struct { +type QueryStateKeyValue struct { Key string `protobuf:"bytes,1,opt,name=key" json:"key,omitempty"` Value []byte `protobuf:"bytes,2,opt,name=value,proto3" json:"value,omitempty"` } -func (m *RangeQueryStateKeyValue) Reset() { *m = RangeQueryStateKeyValue{} } -func (m *RangeQueryStateKeyValue) String() string { return proto.CompactTextString(m) } -func (*RangeQueryStateKeyValue) ProtoMessage() {} -func (*RangeQueryStateKeyValue) Descriptor() ([]byte, []int) { return fileDescriptor1, []int{11} } +func (m *QueryStateKeyValue) Reset() { *m = QueryStateKeyValue{} } +func (m *QueryStateKeyValue) String() string { return proto.CompactTextString(m) } +func (*QueryStateKeyValue) ProtoMessage() {} +func (*QueryStateKeyValue) Descriptor() ([]byte, []int) { return fileDescriptor1, []int{12} } -type RangeQueryStateResponse struct { - KeysAndValues []*RangeQueryStateKeyValue `protobuf:"bytes,1,rep,name=keysAndValues" json:"keysAndValues,omitempty"` - HasMore bool `protobuf:"varint,2,opt,name=hasMore" json:"hasMore,omitempty"` - ID string `protobuf:"bytes,3,opt,name=ID" json:"ID,omitempty"` +type QueryStateResponse struct { + KeysAndValues []*QueryStateKeyValue `protobuf:"bytes,1,rep,name=keysAndValues" json:"keysAndValues,omitempty"` + HasMore bool `protobuf:"varint,2,opt,name=hasMore" json:"hasMore,omitempty"` + ID string `protobuf:"bytes,3,opt,name=ID" json:"ID,omitempty"` } -func (m *RangeQueryStateResponse) Reset() { *m = RangeQueryStateResponse{} } -func (m *RangeQueryStateResponse) String() string { return proto.CompactTextString(m) } -func (*RangeQueryStateResponse) ProtoMessage() {} -func (*RangeQueryStateResponse) Descriptor() ([]byte, []int) { return fileDescriptor1, []int{12} } +func (m *QueryStateResponse) Reset() { *m = QueryStateResponse{} } +func (m *QueryStateResponse) String() string { return proto.CompactTextString(m) } +func (*QueryStateResponse) ProtoMessage() {} +func (*QueryStateResponse) Descriptor() ([]byte, []int) { return fileDescriptor1, []int{13} } -func (m *RangeQueryStateResponse) GetKeysAndValues() []*RangeQueryStateKeyValue { +func (m *QueryStateResponse) GetKeysAndValues() []*QueryStateKeyValue { if m != nil { return m.KeysAndValues } @@ -406,10 +418,11 @@ func init() { proto.RegisterType((*ChaincodeMessage)(nil), "protos.ChaincodeMessage") proto.RegisterType((*PutStateInfo)(nil), "protos.PutStateInfo") proto.RegisterType((*RangeQueryState)(nil), "protos.RangeQueryState") - proto.RegisterType((*RangeQueryStateNext)(nil), "protos.RangeQueryStateNext") - proto.RegisterType((*RangeQueryStateClose)(nil), "protos.RangeQueryStateClose") - proto.RegisterType((*RangeQueryStateKeyValue)(nil), "protos.RangeQueryStateKeyValue") - proto.RegisterType((*RangeQueryStateResponse)(nil), "protos.RangeQueryStateResponse") + proto.RegisterType((*ExecuteQueryState)(nil), "protos.ExecuteQueryState") + proto.RegisterType((*QueryStateNext)(nil), "protos.QueryStateNext") + proto.RegisterType((*QueryStateClose)(nil), "protos.QueryStateClose") + proto.RegisterType((*QueryStateKeyValue)(nil), "protos.QueryStateKeyValue") + proto.RegisterType((*QueryStateResponse)(nil), "protos.QueryStateResponse") proto.RegisterEnum("protos.ConfidentialityLevel", ConfidentialityLevel_name, ConfidentialityLevel_value) proto.RegisterEnum("protos.ChaincodeSpec_Type", ChaincodeSpec_Type_name, ChaincodeSpec_Type_value) proto.RegisterEnum("protos.ChaincodeDeploymentSpec_ExecutionEnvironment", ChaincodeDeploymentSpec_ExecutionEnvironment_name, ChaincodeDeploymentSpec_ExecutionEnvironment_value) @@ -523,72 +536,73 @@ var _ChaincodeSupport_serviceDesc = grpc.ServiceDesc{ func init() { proto.RegisterFile("peer/chaincode.proto", fileDescriptor1) } var fileDescriptor1 = []byte{ - // 1060 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x09, 0x6e, 0x88, 0x02, 0xff, 0xa4, 0x56, 0xdb, 0x6e, 0xdb, 0x46, - 0x13, 0x0e, 0x75, 0xb0, 0xa5, 0xd1, 0xc1, 0x9b, 0x8d, 0xe2, 0xe8, 0xd7, 0xdf, 0x22, 0x06, 0xd1, - 0x16, 0x6e, 0x51, 0x48, 0xad, 0x9a, 0x14, 0x05, 0x0a, 0x04, 0x65, 0xc8, 0x8d, 0xca, 0x58, 0xa6, - 0x94, 0x15, 0x6d, 0xc4, 0xbd, 0x31, 0x68, 0x6a, 0x25, 0x13, 0x96, 0xb9, 0x04, 0xb9, 0x12, 0xac, - 0xbb, 0x5e, 0xf7, 0x35, 0xfa, 0x16, 0x7d, 0x99, 0xbe, 0x49, 0x51, 0x2c, 0x0f, 0xb2, 0x0e, 0x36, - 0x10, 0xa0, 0x57, 0xda, 0xd9, 0xf9, 0xbe, 0xd9, 0x99, 0x6f, 0x76, 0x56, 0x84, 0x46, 0xc0, 0x58, - 0xd8, 0x71, 0xaf, 0x1d, 0xcf, 0x77, 0xf9, 0x98, 0xb5, 0x83, 0x90, 0x0b, 0x8e, 0xf7, 0xe2, 0x9f, - 0xa8, 0xf5, 0xbf, 0x4d, 0x2f, 0x5b, 0x30, 0x5f, 0x24, 0x90, 0xd6, 0xcb, 0x29, 0xe7, 0xd3, 0x19, - 0xeb, 0xc4, 0xd6, 0xd5, 0x7c, 0xd2, 0x11, 0xde, 0x2d, 0x8b, 0x84, 0x73, 0x1b, 0x24, 0x00, 0xf5, - 0x35, 0x54, 0xf4, 0x8c, 0x68, 0x1a, 0x18, 0x43, 0x21, 0x70, 0xc4, 0x75, 0x53, 0x39, 0x52, 0x8e, - 0xcb, 0x34, 0x5e, 0xcb, 0x3d, 0xdf, 0xb9, 0x65, 0xcd, 0x5c, 0xb2, 0x27, 0xd7, 0xea, 0x17, 0x50, - 0xbf, 0xa7, 0xf9, 0xc1, 0x5c, 0x48, 0x94, 0x13, 0x4e, 0xa3, 0xa6, 0x72, 0x94, 0x3f, 0xae, 0xd2, - 0x78, 0xad, 0xfe, 0xa3, 0x40, 0x6d, 0x05, 0x1b, 0x05, 0xcc, 0xc5, 0x6d, 0x28, 0x88, 0x65, 0xc0, - 0xe2, 0xf8, 0xf5, 0x6e, 0x2b, 0x49, 0x22, 0x6a, 0x6f, 0x80, 0xda, 0xf6, 0x32, 0x60, 0x34, 0xc6, - 0xe1, 0xd7, 0x50, 0x71, 0xef, 0xd3, 0x8b, 0x53, 0xa8, 0x74, 0x9f, 0xed, 0xd0, 0x4c, 0x83, 0xae, - 0xe3, 0xf0, 0xb7, 0x50, 0xf4, 0x64, 0x56, 0xcd, 0x7c, 0x4c, 0x38, 0xdc, 0x25, 0x48, 0x2f, 0x4d, - 0x40, 0xb8, 0x09, 0xfb, 0x52, 0x16, 0x3e, 0x17, 0xcd, 0xc2, 0x91, 0x72, 0x5c, 0xa4, 0x99, 0xa9, - 0xbe, 0x81, 0x82, 0x4c, 0x06, 0xd7, 0xa0, 0x7c, 0x66, 0x19, 0xe4, 0x9d, 0x69, 0x11, 0x03, 0x3d, - 0xc1, 0x00, 0x7b, 0xbd, 0x41, 0x5f, 0xb3, 0x7a, 0x48, 0xc1, 0x25, 0x28, 0x58, 0x03, 0x83, 0xa0, - 0x1c, 0xde, 0x87, 0xbc, 0xae, 0x51, 0x94, 0x97, 0x5b, 0xef, 0xb5, 0x73, 0x0d, 0x15, 0xd4, 0xbf, - 0x72, 0xf0, 0x62, 0x75, 0xa6, 0xc1, 0x82, 0x19, 0x5f, 0xde, 0x32, 0x5f, 0xc4, 0x52, 0xfc, 0x0c, - 0x35, 0x77, 0xbd, 0xec, 0x58, 0x93, 0x4a, 0xf7, 0xf9, 0x83, 0x9a, 0xd0, 0x4d, 0x2c, 0xfe, 0x05, - 0x6a, 0x6c, 0x32, 0x61, 0xae, 0xf0, 0x16, 0xcc, 0x70, 0x04, 0x4b, 0x95, 0x69, 0xb5, 0x93, 0x7e, - 0xb7, 0xb3, 0x7e, 0xb7, 0xed, 0xac, 0xdf, 0x74, 0x93, 0x80, 0x8f, 0xa0, 0x22, 0xa3, 0x0d, 0x1d, - 0xf7, 0xc6, 0x99, 0xb2, 0x58, 0xa8, 0x2a, 0x5d, 0xdf, 0xc2, 0x16, 0xec, 0xb3, 0x3b, 0xe6, 0x12, - 0x7f, 0x11, 0xcb, 0x52, 0xef, 0xbe, 0xda, 0x49, 0x6d, 0xb3, 0xa4, 0x36, 0xb9, 0x63, 0xee, 0x5c, - 0x78, 0xdc, 0x27, 0xfe, 0xc2, 0x0b, 0xb9, 0x2f, 0x1d, 0x34, 0x0b, 0xa2, 0xb6, 0xa1, 0xf1, 0x10, - 0x40, 0xaa, 0x69, 0x0c, 0xf4, 0x13, 0x42, 0x13, 0x65, 0x47, 0x17, 0x23, 0x9b, 0x9c, 0x22, 0x45, - 0xfd, 0x5d, 0x59, 0x13, 0xcf, 0xf4, 0x17, 0xdc, 0x75, 0x24, 0xf5, 0xbf, 0x8b, 0x77, 0x0c, 0x07, - 0xde, 0xb8, 0xc7, 0x7c, 0x16, 0xc6, 0x01, 0xb5, 0xd9, 0x34, 0xbd, 0xdb, 0xdb, 0xdb, 0x2a, 0x85, - 0xe6, 0x2a, 0xd2, 0x30, 0xe4, 0x01, 0x8f, 0x9c, 0x99, 0xce, 0x7d, 0xc1, 0xee, 0xe2, 0x5b, 0xe3, - 0x86, 0xcc, 0x11, 0x3c, 0x8c, 0x0f, 0xaf, 0xd2, 0xcc, 0xc4, 0x9f, 0x41, 0x59, 0x84, 0x8e, 0x1f, - 0x79, 0xcc, 0x17, 0x71, 0xe4, 0x2a, 0xbd, 0xdf, 0x50, 0xff, 0x2e, 0x00, 0x5a, 0x05, 0x3d, 0x65, - 0x51, 0x24, 0xb5, 0xfe, 0x7e, 0x63, 0x2e, 0x3e, 0xdf, 0x29, 0x23, 0xc5, 0xad, 0x8f, 0xc6, 0x4f, - 0x50, 0x5e, 0x0d, 0xf3, 0x27, 0xb4, 0xff, 0x1e, 0x2c, 0x33, 0x0f, 0x9c, 0xe5, 0x8c, 0x3b, 0xe3, - 0xb4, 0xed, 0x99, 0x29, 0x87, 0x58, 0xdc, 0x79, 0xe3, 0xb8, 0xdf, 0x65, 0x1a, 0xaf, 0xf1, 0x7b, - 0x38, 0x08, 0x36, 0x4b, 0x6f, 0x16, 0xe3, 0xd3, 0x8e, 0x76, 0xb2, 0xdc, 0x92, 0x88, 0x6e, 0x13, - 0xf1, 0x1b, 0xa8, 0xaf, 0x5a, 0x41, 0xe4, 0x33, 0xd5, 0xdc, 0x7b, 0x64, 0x40, 0x63, 0x2f, 0xdd, - 0x42, 0xab, 0x7f, 0xe6, 0x1e, 0x1e, 0xc8, 0x2a, 0x94, 0x28, 0xe9, 0x99, 0x23, 0x9b, 0x50, 0xa4, - 0xe0, 0x3a, 0x40, 0x66, 0x11, 0x03, 0xe5, 0xe4, 0x3c, 0x9a, 0x96, 0x69, 0xa3, 0x3c, 0x2e, 0x43, - 0x91, 0x12, 0xcd, 0xb8, 0x40, 0x05, 0x7c, 0x00, 0x15, 0x9b, 0x6a, 0xd6, 0x48, 0xd3, 0x6d, 0x73, - 0x60, 0xa1, 0xa2, 0x0c, 0xa9, 0x0f, 0x4e, 0x87, 0x7d, 0x62, 0x13, 0x03, 0xed, 0x49, 0x28, 0xa1, - 0x74, 0x40, 0xd1, 0xbe, 0xf4, 0xf4, 0x88, 0x7d, 0x39, 0xb2, 0x35, 0x9b, 0xa0, 0x92, 0x34, 0x87, - 0x67, 0x99, 0x59, 0x96, 0xa6, 0x41, 0xfa, 0xa9, 0x09, 0xb8, 0x01, 0xc8, 0xb4, 0xce, 0x07, 0x27, - 0xe4, 0x52, 0xff, 0x55, 0x33, 0x2d, 0x5d, 0xbe, 0x0d, 0x95, 0x24, 0xc1, 0xd1, 0x70, 0x60, 0x8d, - 0x08, 0xaa, 0xe1, 0xe7, 0xf0, 0x94, 0x6a, 0x56, 0x8f, 0x5c, 0x7e, 0x38, 0x23, 0xf4, 0x22, 0xa5, - 0xd6, 0x71, 0x0b, 0x0e, 0x77, 0xb6, 0x2f, 0x2d, 0xf2, 0xd1, 0x46, 0x07, 0xf8, 0xff, 0xf0, 0x62, - 0xd7, 0xa7, 0xf7, 0x07, 0x23, 0x82, 0x90, 0x4c, 0xe1, 0x84, 0x90, 0xa1, 0xd6, 0x37, 0xcf, 0x09, - 0x7a, 0xaa, 0xfe, 0x08, 0xd5, 0xe1, 0x5c, 0x8c, 0x84, 0x23, 0x98, 0xe9, 0x4f, 0x38, 0x46, 0x90, - 0xbf, 0x61, 0xcb, 0xf4, 0x4d, 0x97, 0x4b, 0xdc, 0x80, 0xe2, 0xc2, 0x99, 0xcd, 0x59, 0x7a, 0x3b, - 0x13, 0x43, 0x25, 0x70, 0x40, 0x1d, 0x7f, 0xca, 0x3e, 0xcc, 0x59, 0xb8, 0x8c, 0xe9, 0xb8, 0x05, - 0xa5, 0x48, 0x38, 0xa1, 0x38, 0x59, 0xf1, 0x57, 0x36, 0x3e, 0x84, 0x3d, 0xe6, 0x8f, 0xa5, 0x27, - 0x99, 0x9e, 0xd4, 0x52, 0xbf, 0x84, 0x67, 0x5b, 0x61, 0x2c, 0xd9, 0xfb, 0x3a, 0xe4, 0x4c, 0x23, - 0x0d, 0x92, 0x33, 0x0d, 0xf5, 0x2b, 0x68, 0x6c, 0xc1, 0xf4, 0x19, 0x8f, 0xd8, 0x0e, 0x4e, 0x83, - 0x17, 0x5b, 0xb8, 0x13, 0xb6, 0x3c, 0x97, 0x09, 0x7f, 0x72, 0x61, 0x7f, 0x28, 0x3b, 0x31, 0x28, - 0x8b, 0x02, 0xee, 0x47, 0x0c, 0x13, 0xa8, 0xdd, 0xb0, 0x65, 0xa4, 0xf9, 0xe3, 0x38, 0x66, 0xf2, - 0x07, 0x56, 0xe9, 0xbe, 0xcc, 0x6e, 0xe4, 0x23, 0x67, 0xd3, 0x4d, 0x96, 0x9c, 0xa9, 0x6b, 0x27, - 0x3a, 0xe5, 0x61, 0x72, 0x74, 0x89, 0x66, 0x66, 0x5a, 0x4f, 0x3e, 0xab, 0xe7, 0x9b, 0x57, 0xd0, - 0xd0, 0xb9, 0x3f, 0xf1, 0xc6, 0xcc, 0x17, 0x9e, 0x33, 0xf3, 0xc4, 0xb2, 0xcf, 0x16, 0x6c, 0x26, - 0x9f, 0xbe, 0xe1, 0xd9, 0xdb, 0xbe, 0xa9, 0xa3, 0x27, 0x18, 0x41, 0x55, 0x1f, 0x58, 0xef, 0x4c, - 0x83, 0x58, 0xb6, 0xa9, 0xf5, 0x91, 0xd2, 0xfd, 0xb8, 0xf6, 0x68, 0x8c, 0xe6, 0x41, 0xc0, 0x43, - 0x81, 0x0d, 0x28, 0x51, 0x36, 0xf5, 0x22, 0xc1, 0x42, 0xdc, 0x7c, 0xec, 0xc9, 0x68, 0x3d, 0xea, - 0x51, 0x9f, 0x1c, 0x2b, 0xdf, 0x29, 0x6f, 0x75, 0x38, 0xe4, 0xe1, 0xb4, 0x7d, 0xbd, 0x0c, 0x58, - 0x38, 0x63, 0xe3, 0x29, 0x0b, 0x53, 0xc2, 0x6f, 0x5f, 0x4f, 0x3d, 0x71, 0x3d, 0xbf, 0x6a, 0xbb, - 0xfc, 0xb6, 0xb3, 0xe6, 0xee, 0x4c, 0x9c, 0xab, 0xd0, 0x73, 0x93, 0x6f, 0x8a, 0xa8, 0x23, 0x3f, - 0x3e, 0xae, 0x92, 0x4f, 0x91, 0x1f, 0xfe, 0x0d, 0x00, 0x00, 0xff, 0xff, 0xad, 0x76, 0x5b, 0xa4, - 0xa9, 0x08, 0x00, 0x00, + // 1077 bytes of a gzipped FileDescriptorProto + 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x09, 0x6e, 0x88, 0x02, 0xff, 0xa4, 0x56, 0x5f, 0x6f, 0xe2, 0x46, + 0x10, 0x8f, 0xf9, 0x93, 0xc0, 0x40, 0x60, 0xb3, 0xc7, 0xe5, 0x28, 0x6a, 0x55, 0x6a, 0xf5, 0x21, + 0x57, 0x55, 0xd0, 0xa6, 0x77, 0x55, 0xa5, 0x56, 0xa7, 0xfa, 0xec, 0x3d, 0xea, 0x0b, 0x31, 0xdc, + 0xe2, 0x44, 0x49, 0x5f, 0x22, 0xc7, 0x2c, 0xc4, 0x0a, 0xf1, 0xba, 0xf6, 0x82, 0xc2, 0xdb, 0x7d, + 0xa4, 0x3e, 0xf7, 0x33, 0xf5, 0x33, 0x54, 0xd5, 0xda, 0xe6, 0x5f, 0x48, 0xa4, 0x93, 0xee, 0x89, + 0xfd, 0xcd, 0xfc, 0x7e, 0xb3, 0x33, 0xb3, 0x3b, 0x8b, 0xa1, 0x16, 0x30, 0x16, 0xb6, 0xdd, 0x1b, + 0xc7, 0xf3, 0x5d, 0x3e, 0x64, 0xad, 0x20, 0xe4, 0x82, 0xe3, 0xdd, 0xf8, 0x27, 0x6a, 0x7c, 0xb1, + 0xe9, 0x65, 0x33, 0xe6, 0x8b, 0x84, 0xd2, 0xf8, 0x7a, 0xcc, 0xf9, 0x78, 0xc2, 0xda, 0x31, 0xba, + 0x9e, 0x8e, 0xda, 0xc2, 0xbb, 0x63, 0x91, 0x70, 0xee, 0x82, 0x84, 0xa0, 0xbe, 0x86, 0x92, 0xbe, + 0x10, 0x9a, 0x06, 0xc6, 0x90, 0x0b, 0x1c, 0x71, 0x53, 0x57, 0x9a, 0xca, 0x51, 0x91, 0xc6, 0x6b, + 0x69, 0xf3, 0x9d, 0x3b, 0x56, 0xcf, 0x24, 0x36, 0xb9, 0x56, 0xbf, 0x85, 0xca, 0x4a, 0xe6, 0x07, + 0x53, 0x21, 0x59, 0x4e, 0x38, 0x8e, 0xea, 0x4a, 0x33, 0x7b, 0x54, 0xa6, 0xf1, 0x5a, 0xfd, 0x4f, + 0x81, 0xfd, 0x25, 0x6d, 0x10, 0x30, 0x17, 0xb7, 0x20, 0x27, 0xe6, 0x01, 0x8b, 0xe3, 0x57, 0x8e, + 0x1b, 0x49, 0x12, 0x51, 0x6b, 0x83, 0xd4, 0xb2, 0xe7, 0x01, 0xa3, 0x31, 0x0f, 0xbf, 0x86, 0x92, + 0xbb, 0x4a, 0x2f, 0x4e, 0xa1, 0x74, 0xfc, 0x6c, 0x4b, 0x66, 0x1a, 0x74, 0x9d, 0x87, 0xbf, 0x87, + 0xbc, 0x27, 0xb3, 0xaa, 0x67, 0x63, 0xc1, 0xe1, 0xb6, 0x40, 0x7a, 0x69, 0x42, 0xc2, 0x75, 0xd8, + 0x93, 0x6d, 0xe1, 0x53, 0x51, 0xcf, 0x35, 0x95, 0xa3, 0x3c, 0x5d, 0x40, 0xf5, 0x0d, 0xe4, 0x64, + 0x32, 0x78, 0x1f, 0x8a, 0x67, 0x96, 0x41, 0xde, 0x99, 0x16, 0x31, 0xd0, 0x0e, 0x06, 0xd8, 0xed, + 0xf4, 0xba, 0x9a, 0xd5, 0x41, 0x0a, 0x2e, 0x40, 0xce, 0xea, 0x19, 0x04, 0x65, 0xf0, 0x1e, 0x64, + 0x75, 0x8d, 0xa2, 0xac, 0x34, 0xbd, 0xd7, 0xce, 0x35, 0x94, 0x53, 0xff, 0xc9, 0xc0, 0x8b, 0xe5, + 0x9e, 0x06, 0x0b, 0x26, 0x7c, 0x7e, 0xc7, 0x7c, 0x11, 0xb7, 0xe2, 0x57, 0xd8, 0x77, 0xd7, 0xcb, + 0x8e, 0x7b, 0x52, 0x3a, 0x7e, 0xfe, 0x68, 0x4f, 0xe8, 0x26, 0x17, 0xff, 0x0e, 0xfb, 0x6c, 0x34, + 0x62, 0xae, 0xf0, 0x66, 0xcc, 0x70, 0x04, 0x4b, 0x3b, 0xd3, 0x68, 0x25, 0xe7, 0xdd, 0x5a, 0x9c, + 0x77, 0xcb, 0x5e, 0x9c, 0x37, 0xdd, 0x14, 0xe0, 0x26, 0x94, 0x64, 0xb4, 0xbe, 0xe3, 0xde, 0x3a, + 0x63, 0x16, 0x37, 0xaa, 0x4c, 0xd7, 0x4d, 0xd8, 0x82, 0x3d, 0x76, 0xcf, 0x5c, 0xe2, 0xcf, 0xe2, + 0xb6, 0x54, 0x8e, 0x5f, 0x6d, 0xa5, 0xb6, 0x59, 0x52, 0x8b, 0xdc, 0x33, 0x77, 0x2a, 0x3c, 0xee, + 0x13, 0x7f, 0xe6, 0x85, 0xdc, 0x97, 0x0e, 0xba, 0x08, 0xa2, 0xb6, 0xa0, 0xf6, 0x18, 0x41, 0x76, + 0xd3, 0xe8, 0xe9, 0x27, 0x84, 0x26, 0x9d, 0x1d, 0x5c, 0x0e, 0x6c, 0x72, 0x8a, 0x14, 0xf5, 0xa3, + 0xb2, 0xd6, 0x3c, 0xd3, 0x9f, 0x71, 0xd7, 0x91, 0xd2, 0xcf, 0x6f, 0xde, 0x11, 0x54, 0xbd, 0x61, + 0x87, 0xf9, 0x2c, 0x8c, 0x03, 0x6a, 0x93, 0x71, 0x7a, 0xb7, 0x1f, 0x9a, 0x55, 0x0a, 0xf5, 0x65, + 0xa4, 0x7e, 0xc8, 0x03, 0x1e, 0x39, 0x13, 0x9d, 0xfb, 0x82, 0xdd, 0xc7, 0xb7, 0xc6, 0x0d, 0x99, + 0x23, 0x78, 0x18, 0x6f, 0x5e, 0xa6, 0x0b, 0x88, 0xbf, 0x84, 0xa2, 0x08, 0x1d, 0x3f, 0xf2, 0x98, + 0x2f, 0xe2, 0xc8, 0x65, 0xba, 0x32, 0xa8, 0xff, 0xe6, 0x00, 0x2d, 0x83, 0x9e, 0xb2, 0x28, 0x92, + 0xbd, 0xfe, 0x71, 0x63, 0x2e, 0xbe, 0xda, 0x2a, 0x23, 0xe5, 0xad, 0x8f, 0xc6, 0x2f, 0x50, 0x5c, + 0x0e, 0xf3, 0x27, 0x1c, 0xff, 0x8a, 0x2c, 0x33, 0x0f, 0x9c, 0xf9, 0x84, 0x3b, 0xc3, 0xf4, 0xd8, + 0x17, 0x50, 0x0e, 0xb1, 0xb8, 0xf7, 0x86, 0xf1, 0x79, 0x17, 0x69, 0xbc, 0xc6, 0xef, 0xa1, 0x1a, + 0x6c, 0x96, 0x5e, 0xcf, 0xc7, 0xbb, 0x35, 0xb7, 0xb2, 0x7c, 0xd0, 0x22, 0xfa, 0x50, 0x88, 0xdf, + 0x40, 0x65, 0x79, 0x14, 0x44, 0x3e, 0x53, 0xf5, 0xdd, 0x27, 0x06, 0x34, 0xf6, 0xd2, 0x07, 0x6c, + 0xf5, 0xef, 0xcc, 0xe3, 0x03, 0x59, 0x86, 0x02, 0x25, 0x1d, 0x73, 0x60, 0x13, 0x8a, 0x14, 0x5c, + 0x01, 0x58, 0x20, 0x62, 0xa0, 0x8c, 0x9c, 0x47, 0xd3, 0x32, 0x6d, 0x94, 0xc5, 0x45, 0xc8, 0x53, + 0xa2, 0x19, 0x97, 0x28, 0x87, 0xab, 0x50, 0xb2, 0xa9, 0x66, 0x0d, 0x34, 0xdd, 0x36, 0x7b, 0x16, + 0xca, 0xcb, 0x90, 0x7a, 0xef, 0xb4, 0xdf, 0x25, 0x36, 0x31, 0xd0, 0xae, 0xa4, 0x12, 0x4a, 0x7b, + 0x14, 0xed, 0x49, 0x4f, 0x87, 0xd8, 0x57, 0x03, 0x5b, 0xb3, 0x09, 0x2a, 0x48, 0xd8, 0x3f, 0x5b, + 0xc0, 0xa2, 0x84, 0x06, 0xe9, 0xa6, 0x10, 0x70, 0x0d, 0x90, 0x69, 0x9d, 0xf7, 0x4e, 0xc8, 0x95, + 0xfe, 0x87, 0x66, 0x5a, 0xba, 0x7c, 0x1b, 0x4a, 0x49, 0x82, 0x83, 0x7e, 0xcf, 0x1a, 0x10, 0xb4, + 0x8f, 0x9f, 0xc3, 0x01, 0xd5, 0xac, 0x0e, 0xb9, 0xfa, 0x70, 0x46, 0xe8, 0x65, 0x2a, 0xad, 0xe0, + 0x17, 0xf0, 0x8c, 0x5c, 0x10, 0xfd, 0xcc, 0xde, 0x74, 0x54, 0x65, 0xcc, 0x35, 0xc3, 0x95, 0x45, + 0x2e, 0x6c, 0x84, 0x64, 0x94, 0x75, 0xab, 0xde, 0xed, 0x0d, 0x08, 0x3a, 0x90, 0xf9, 0x9c, 0x10, + 0xd2, 0xd7, 0xba, 0xe6, 0x39, 0x41, 0x58, 0xfd, 0x19, 0xca, 0xfd, 0xa9, 0x18, 0x08, 0x47, 0x30, + 0xd3, 0x1f, 0x71, 0x8c, 0x20, 0x7b, 0xcb, 0xe6, 0xe9, 0x03, 0x2f, 0x97, 0xb8, 0x06, 0xf9, 0x99, + 0x33, 0x99, 0xb2, 0xf4, 0xaa, 0x26, 0x40, 0x25, 0x50, 0xa5, 0x8e, 0x3f, 0x66, 0x1f, 0xa6, 0x2c, + 0x9c, 0xc7, 0x72, 0xdc, 0x80, 0x42, 0x24, 0x9c, 0x50, 0x9c, 0x2c, 0xf5, 0x4b, 0x8c, 0x0f, 0x61, + 0x97, 0xf9, 0x43, 0xe9, 0x49, 0x46, 0x29, 0x45, 0xea, 0x4b, 0x38, 0x48, 0x86, 0x7e, 0x3d, 0x50, + 0x0d, 0xf2, 0x7f, 0x49, 0x94, 0x46, 0x49, 0x80, 0xda, 0x84, 0xca, 0x8a, 0x63, 0xc9, 0xeb, 0x52, + 0x81, 0x8c, 0x69, 0xa4, 0xa4, 0x8c, 0x69, 0xa8, 0xdf, 0x40, 0x75, 0xc5, 0xd0, 0x27, 0x3c, 0x62, + 0x5b, 0x94, 0xdf, 0x00, 0xaf, 0x28, 0x27, 0x6c, 0x7e, 0x2e, 0x8b, 0xf9, 0xe4, 0xa2, 0x3f, 0x2a, + 0xeb, 0x72, 0xca, 0xa2, 0x80, 0xfb, 0x11, 0x93, 0xaf, 0xed, 0x2d, 0x9b, 0x47, 0x9a, 0x3f, 0x8c, + 0xc3, 0x25, 0x7f, 0x72, 0xa5, 0xd5, 0xdf, 0xd7, 0xf6, 0x8e, 0x74, 0x53, 0x20, 0x47, 0xee, 0xc6, + 0x89, 0x4e, 0x79, 0x98, 0x6c, 0x58, 0xa0, 0x0b, 0x98, 0x16, 0x90, 0x5d, 0x14, 0xf0, 0xdd, 0x2b, + 0xa8, 0xe9, 0xdc, 0x1f, 0x79, 0x43, 0xe6, 0x0b, 0xcf, 0x99, 0x78, 0x62, 0xde, 0x65, 0x33, 0x36, + 0x91, 0x2f, 0x63, 0xff, 0xec, 0x6d, 0xd7, 0xd4, 0xd1, 0x0e, 0x46, 0x50, 0xd6, 0x7b, 0xd6, 0x3b, + 0xd3, 0x20, 0x96, 0x6d, 0x6a, 0x5d, 0xa4, 0x1c, 0x5f, 0xac, 0xbd, 0x29, 0x83, 0x69, 0x10, 0xf0, + 0x50, 0x60, 0x03, 0x0a, 0x94, 0x8d, 0xbd, 0x48, 0xb0, 0x10, 0xd7, 0x9f, 0x7a, 0x51, 0x1a, 0x4f, + 0x7a, 0xd4, 0x9d, 0x23, 0xe5, 0x07, 0xe5, 0xad, 0x0e, 0x87, 0x3c, 0x1c, 0xb7, 0x6e, 0xe6, 0x01, + 0x0b, 0x27, 0x6c, 0x38, 0x66, 0x61, 0x2a, 0xf8, 0xf3, 0xe5, 0xd8, 0x13, 0x37, 0xd3, 0xeb, 0x96, + 0xcb, 0xef, 0xda, 0x6b, 0xee, 0xf6, 0xc8, 0xb9, 0x0e, 0x3d, 0x37, 0xf9, 0xe4, 0x88, 0xda, 0xf2, + 0xdb, 0xe4, 0x3a, 0xf9, 0x52, 0xf9, 0xe9, 0xff, 0x00, 0x00, 0x00, 0xff, 0xff, 0x0f, 0xe1, 0x88, + 0xa2, 0xc8, 0x08, 0x00, 0x00, } diff --git a/protos/peer/chaincode.proto b/protos/peer/chaincode.proto index 23371cc328f..f4b5d82a835 100644 --- a/protos/peer/chaincode.proto +++ b/protos/peer/chaincode.proto @@ -134,9 +134,10 @@ message ChaincodeMessage { INVOKE_CHAINCODE = 11; RESPONSE = 13; RANGE_QUERY_STATE = 14; - RANGE_QUERY_STATE_NEXT = 15; - RANGE_QUERY_STATE_CLOSE = 16; - KEEPALIVE = 17; + EXECUTE_QUERY_STATE = 15; + QUERY_STATE_NEXT = 16; + QUERY_STATE_CLOSE = 17; + KEEPALIVE = 18; } Type type = 1; @@ -162,21 +163,25 @@ message RangeQueryState { string endKey = 2; } -message RangeQueryStateNext { +message ExecuteQueryState { + string query = 1; +} + +message QueryStateNext { string ID = 1; } -message RangeQueryStateClose { - string ID = 1; +message QueryStateClose { + string ID = 1; } -message RangeQueryStateKeyValue { +message QueryStateKeyValue { string key = 1; bytes value = 2; } -message RangeQueryStateResponse { - repeated RangeQueryStateKeyValue keysAndValues = 1; +message QueryStateResponse { + repeated QueryStateKeyValue keysAndValues = 1; bool hasMore = 2; string ID = 3; }