Skip to content
This repository was archived by the owner on Apr 13, 2022. It is now read-only.

Commit 9e3401d

Browse files
airvinnwaywood
andcommitted
Added implementation of getStateByRange
Co-authored-by: Nick Waywood <n.waywood@gmail.com> Signed-off-by: Allison Irvin <allison.irvin@au1.ibm.com>
1 parent b86e650 commit 9e3401d

File tree

5 files changed

+60
-26
lines changed

5 files changed

+60
-26
lines changed

examples/Marbles.hs

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,11 @@
33

44
-- Example invocations:
55
-- peer chaincode invoke -n mycc -c '{"Args":["initMarble","marble1","red","large","Al"]}' -C myc
6+
-- peer chaincode invoke -n mycc -c '{"Args":["initMarble","marble2","blue","large","Nick"]}' -C myc
67
-- peer chaincode invoke -n mycc -c '{"Args":["readMarble","marble1"]}' -C myc
78
-- peer chaincode invoke -n mycc -c '{"Args":["deleteMarble","marble1"]}' -C myc
89
-- peer chaincode invoke -n mycc -c '{"Args":["transferMarble","marble1", "Nick"]}' -C myc
10+
-- peer chaincode invoke -n mycc -c '{"Args":["getMarblesByRange","marble1", "marble3"]}' -C myc
911

1012
module Marbles where
1113

@@ -78,8 +80,7 @@ invokeFunc s =
7880
-- Right ("queryMarbles", parameters) -> queryMarbles s parameters
7981
-- Right ("getHistoryForMarble", parameters) ->
8082
-- getHistoryForMarble s parameters
81-
-- Right ("getMarblesByRange", parameters) ->
82-
-- getMarblesByRange s parameters
83+
Right ("getMarblesByRange", parameters) -> getMarblesByRange s parameters
8384
-- Right ("getMarblesByRangeWithPagination", parameters) ->
8485
-- getMarblesByRangeWithPagination s parameters
8586
-- Right ("queryMarblesWithPagination", parameters) ->
@@ -159,6 +160,16 @@ readMarble s params = if Prelude.length params == 1
159160
else pure $ errorPayload
160161
"Incorrect arguments. Need a marble name, color, size and owner"
161162

163+
getMarblesByRange :: DefaultChaincodeStub -> [Text] -> IO Pb.Response
164+
getMarblesByRange s params = if Prelude.length params == 2
165+
then do
166+
e <- getStateByRange s (params !! 0) (params !! 1)
167+
case e of
168+
Left _ -> pure $ errorPayload "Failed to get marbles"
169+
Right a -> trace (show a) (pure $ successPayload Nothing)
170+
else pure $ errorPayload
171+
"Incorrect arguments. Need a start key and an end key"
172+
162173
parseMarble :: [Text] -> Marble
163174
parseMarble params = Marble { objectType = "marble"
164175
, name = params !! 0

src/Interfaces.hs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
module Interfaces
22
( ChaincodeStubInterface(..)
3-
, StateQueryIterator(..)
3+
, StateQueryIteratorInterface(..)
44
)
55
where
66

@@ -36,7 +36,7 @@ class ChaincodeStubInterface ccs where
3636

3737
-- setStateValidationParameter :: ccs -> String -> [ByteString] -> Maybe Error
3838
-- getStateValiationParameter :: ccs -> String -> Either Error [ByteString]
39-
getStateByRange :: ccs -> Text -> Text -> Either Error StateQueryIterator
39+
getStateByRange :: ccs -> Text -> Text -> IO (Either Error StateQueryIterator)
4040
-- getStateByRangeWithPagination :: ccs -> String -> String -> Int32 -> String -> Either Error (StateQueryIterator, Pb.QueryResponseMetadata)
4141
-- getStateByPartialCompositeKey :: ccs -> String -> [String] -> Either Error StateQueryIterator
4242
-- getStateByPartialCompositeKeyWithPagination :: ccs -> String -> [String] -> Int32 -> String -> Either Error (StateQueryIterator, Pb.QueryResponseMetadata)

src/Messages.hs

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
module Messages where
44

5+
import qualified Data.ByteString.UTF8 as BSU
56
import qualified Data.ByteString.Lazy as LBS
67
import Data.ByteString as BS
78
import Data.Text
@@ -65,6 +66,14 @@ delStatePayload :: Text -> Pb.DelState
6566
delStatePayload key =
6667
Pb.DelState {delStateKey = fromStrict key, delStateCollection = ""}
6768

69+
getStateByRangePayload :: Text -> Text -> Pb.GetStateByRange
70+
getStateByRangePayload startKey endKey = Pb.GetStateByRange {
71+
getStateByRangeStartKey = fromStrict startKey
72+
, getStateByRangeEndKey = fromStrict endKey
73+
, getStateByRangeCollection = ""
74+
, getStateByRangeMetadata = BSU.fromString ""
75+
}
76+
6877
-- buildChaincodeMessage
6978
-- :: Enumerated Pb.ChaincodeMessage_Type
7079
-- -> a

src/Stub.hs

Lines changed: 28 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
module Stub where
44

55

6+
import Data.Bifunctor
67
import Data.ByteString as BS
78
import Data.Text
89
import Data.Text.Encoding
@@ -13,19 +14,20 @@ import Data.Vector as Vector
1314
, foldr
1415
, empty
1516
)
17+
import qualified Data.ByteString.Lazy as LBS
1618

1719
import Peer.ChaincodeShim
1820

1921
import Network.GRPC.HighLevel
2022
import Google.Protobuf.Timestamp as Pb
2123
import Peer.Proposal as Pb
2224
import Proto3.Suite
25+
import Proto3.Wire.Decode
2326

2427
import Interfaces
2528
import Messages
2629
import Types
2730

28-
2931
-- NOTE: When support for concurrency transaction is added, this function will no longer be required
3032
-- as the stub function will block and listen for responses over a channel when the code is concurrent
3133
listenForResponse :: StreamRecv ChaincodeMessage -> IO (Either Error ByteString)
@@ -66,7 +68,7 @@ instance ChaincodeStubInterface DefaultChaincodeStub where
6668
-- invokeChaincode :: ccs -> String -> [ByteString] -> String -> Pb.Response
6769
-- invokeChaincode ccs cc params = Pb.Response{ responseStatus = 500, responseMessage = message(notImplemented), responsePayload = Nothing }
6870
--
69-
getState :: ccs -> Text -> IO (Either Error ByteString)
71+
-- getState :: ccs -> Text -> IO (Either Error ByteString)
7072
getState ccs key =
7173
let payload = getStatePayload key
7274
message =
@@ -78,7 +80,7 @@ instance ChaincodeStubInterface DefaultChaincodeStub where
7880
Right _ -> pure ()
7981
listenForResponse (recvStream ccs)
8082

81-
-- -- putState :: ccs -> Text -> ByteString -> Maybe Error
83+
-- putState :: ccs -> Text -> ByteString -> Maybe Error
8284
putState ccs key value =
8385
let payload = putStatePayload key value
8486
message =
@@ -108,16 +110,27 @@ instance ChaincodeStubInterface DefaultChaincodeStub where
108110
-- -- getStateValiationParameter :: ccs -> String -> Either Error [ByteString]
109111
-- getStateValiationParameter ccs key = Left notImplemented
110112
--
111-
-- getStateByRange :: ccs -> Text -> Text -> Either Error StateQueryIterator
112-
getStateByRange ccs startKey endKey =
113-
let payload = getStateByRangePayload startKey endKey
114-
message = buildChaincodeMessage GET_STATE_BY_RANGE payload (txId ccs) (channelId ccs)
115-
in do
116-
e <- (sendStream ccs) message
117-
case e of
118-
Left err -> error ("Error while streaming: " ++ show err)
119-
Right _ -> pure ()
120-
listenForResponse (recvStream ccs)
113+
-- getStateByRange :: ccs -> Text -> Text -> IO (Either Error StateQueryIterator)
114+
getStateByRange ccs startKey endKey =
115+
let payload = getStateByRangePayload startKey endKey
116+
message = buildChaincodeMessage GET_STATE_BY_RANGE payload (txId ccs) (channelId ccs)
117+
bsToSqi :: ByteString -> Either Error StateQueryIterator
118+
bsToSqi bs = let eeaQueryResponse = parse (decodeMessage (FieldNumber 1)) bs :: Either ParseError QueryResponse in
119+
case eeaQueryResponse of
120+
Left _ -> Left ParseError
121+
Right queryResponse -> Right StateQueryIterator {
122+
sqiChannelId = getChannelId ccs
123+
, sqiTxId = getTxId ccs
124+
, sqiResponse = queryResponse
125+
, sqiCurrentLoc = 0
126+
}
127+
in do
128+
e <- (sendStream ccs) message
129+
case e of
130+
Left err -> error ("Error while streaming: " ++ show err)
131+
Right _ -> pure ()
132+
(bsToSqi =<<) <$> listenForResponse (recvStream ccs)
133+
121134
--
122135
-- -- getStateByRangeWithPagination :: ccs -> String -> String -> Int32 -> String -> Either Error (StateQueryIterator, Pb.QueryResponseMetadata)
123136
-- getStateByRangeWithPagination ccs startKey endKey pageSize bookmark = Left notImplemented
@@ -191,10 +204,10 @@ instance ChaincodeStubInterface DefaultChaincodeStub where
191204
-- -- setEvent :: ccs -> String -> ByteArray -> Maybe Error
192205
-- setEvent ccs = Right notImplemented
193206

194-
instance StateQueryIteratorInterface DefaultStateQueryIterator where
207+
instance StateQueryIteratorInterface StateQueryIterator where
195208
-- hasNext :: sqi -> Bool
196209
hasNext sqi = True
197210
-- close :: sqi -> Maybe Error
198211
close _ = Nothing
199212
-- next :: sqi -> Either Error Pb.KV
200-
next _ = Left _
213+
next _ = Left $ Error "not implemented"

src/Types.hs

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -9,14 +9,15 @@ import Network.GRPC.HighLevel.Generated
99
import Proto3.Suite
1010
import Network.GRPC.HighLevel
1111

12-
import Peer.ChaincodeShim
12+
import Peer.ChaincodeShim as Pb
1313
import Google.Protobuf.Timestamp as Pb
1414
import Peer.Proposal as Pb
1515
import Peer.ProposalResponse as Pb
1616

1717
data Error = GRPCError GRPCIOError
1818
| InvalidArgs
1919
| Error String
20+
| ParseError
2021
deriving (Eq, Show)
2122

2223
data ChaincodeStub = ChaincodeStub {
@@ -54,12 +55,12 @@ data DefaultChaincodeStub = DefaultChaincodeStub {
5455
sendStream :: StreamSend ChaincodeMessage
5556
}
5657

57-
data DefaultStateQueryIterator = DefaultStateQueryIterator {
58-
channelId :: Text
59-
txId :: Text
60-
response :: Pb.QueryResponse
61-
currentLoc :: Int
62-
}
58+
data StateQueryIterator = StateQueryIterator {
59+
sqiChannelId :: Text,
60+
sqiTxId :: Text,
61+
sqiResponse :: Pb.QueryResponse,
62+
sqiCurrentLoc :: Int
63+
} deriving (Show)
6364

6465
-- MapStringBytes is a synonym for the Map type whose keys are String and values
6566
type MapStringBytes = Map String ByteString

0 commit comments

Comments
 (0)