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