diff --git a/ouroboros-network-api/src/Ouroboros/Network/NodeToClient/Version.hs b/ouroboros-network-api/src/Ouroboros/Network/NodeToClient/Version.hs index 955a94a1e17..c50800a2872 100644 --- a/ouroboros-network-api/src/Ouroboros/Network/NodeToClient/Version.hs +++ b/ouroboros-network-api/src/Ouroboros/Network/NodeToClient/Version.hs @@ -38,7 +38,8 @@ data NodeToClientVersion | NodeToClientV_15 -- ^ added `query` to NodeToClientVersionData | NodeToClientV_16 - -- ^ enabled @CardanoNodeToClientVersion11@, i.e., Conway and + -- ^ add @ImmutableTip@ to @LocalStateQuery@, enabled + -- @CardanoNodeToClientVersion11@, i.e., Conway and -- @GetStakeDelegDeposits@. deriving (Eq, Ord, Enum, Bounded, Show, Typeable) diff --git a/ouroboros-network-protocols/CHANGELOG.md b/ouroboros-network-protocols/CHANGELOG.md index 9f2c3808977..fc0379bce70 100644 --- a/ouroboros-network-protocols/CHANGELOG.md +++ b/ouroboros-network-protocols/CHANGELOG.md @@ -4,6 +4,11 @@ ### Breaking changes +* In LocalStateQuery, changed the argument of `MsgAcquire` and `MsgReAcquire` + from `Maybe point` to a new ADT `Target point`. It still allows the client to + acquire either the volatile tip or a specific point, but now also allows them + to instead acquire the immutable tip. + ### Non-breaking changes ## 0.6.1.0 -- 2023-12-14 diff --git a/ouroboros-network-protocols/src/Ouroboros/Network/Protocol/LocalStateQuery/Client.hs b/ouroboros-network-protocols/src/Ouroboros/Network/Protocol/LocalStateQuery/Client.hs index 73c436f4498..2e3ceecc8c2 100644 --- a/ouroboros-network-protocols/src/Ouroboros/Network/Protocol/LocalStateQuery/Client.hs +++ b/ouroboros-network-protocols/src/Ouroboros/Network/Protocol/LocalStateQuery/Client.hs @@ -49,7 +49,7 @@ localStateQueryClientNull = -- * a termination messge -- data ClientStIdle block point query (m :: Type -> Type) a where - SendMsgAcquire :: Maybe point + SendMsgAcquire :: Target point -> ClientStAcquiring block point query m a -> ClientStIdle block point query m a @@ -82,7 +82,7 @@ data ClientStAcquired block point query m a where -> ClientStQuerying block point query m a result -> ClientStAcquired block point query m a - SendMsgReAcquire :: Maybe point + SendMsgReAcquire :: Target point -> ClientStAcquiring block point query m a -> ClientStAcquired block point query m a @@ -119,8 +119,8 @@ mapLocalStateQueryClient fpoint fquery fresult = where goIdle :: ClientStIdle block point query m a -> ClientStIdle block' point' query' m a - goIdle (SendMsgAcquire pt k) = - SendMsgAcquire (fpoint <$> pt) (goAcquiring k) + goIdle (SendMsgAcquire tgt k) = + SendMsgAcquire (fpoint <$> tgt) (goAcquiring k) goIdle (SendMsgDone a) = SendMsgDone a @@ -168,9 +168,9 @@ localStateQueryClientPeer (LocalStateQueryClient handler) = :: ClientStIdle block point query m a -> Peer (LocalStateQuery block point query) AsClient StIdle m a handleStIdle req = case req of - SendMsgAcquire pt stAcquiring -> + SendMsgAcquire tgt stAcquiring -> Yield (ClientAgency TokIdle) - (MsgAcquire pt) + (MsgAcquire tgt) (handleStAcquiring stAcquiring) SendMsgDone a -> Yield (ClientAgency TokIdle) diff --git a/ouroboros-network-protocols/src/Ouroboros/Network/Protocol/LocalStateQuery/Codec.hs b/ouroboros-network-protocols/src/Ouroboros/Network/Protocol/LocalStateQuery/Codec.hs index ebc371efe91..b272dd3e12e 100644 --- a/ouroboros-network-protocols/src/Ouroboros/Network/Protocol/LocalStateQuery/Codec.hs +++ b/ouroboros-network-protocols/src/Ouroboros/Network/Protocol/LocalStateQuery/Codec.hs @@ -35,14 +35,16 @@ codecLocalStateQuery ( MonadST m , ShowQuery query ) - => (point -> CBOR.Encoding) + => Bool -- ^ allow 'ImmutableTip' in @'MsgAcquire' + -> (point -> CBOR.Encoding) -> (forall s . CBOR.Decoder s point) -> (forall result . query result -> CBOR.Encoding) -> (forall s . CBOR.Decoder s (Some query)) -> (forall result . query result -> result -> CBOR.Encoding) -> (forall result . query result -> forall s . CBOR.Decoder s result) -> Codec (LocalStateQuery block point query) CBOR.DeserialiseFailure m ByteString -codecLocalStateQuery encodePoint decodePoint +codecLocalStateQuery canAcquireImmutable + encodePoint decodePoint encodeQuery decodeQuery encodeResult decodeResult = mkCodecCborLazyBS encode decode @@ -65,15 +67,24 @@ codecLocalStateQuery encodePoint decodePoint PeerHasAgency pr st -> Message (LocalStateQuery block point query) st st' -> CBOR.Encoding - encode (ClientAgency TokIdle) (MsgAcquire (Just pt)) = + encode (ClientAgency TokIdle) (MsgAcquire (SpecificPoint pt)) = CBOR.encodeListLen 2 <> CBOR.encodeWord 0 <> encodePoint pt - encode (ClientAgency TokIdle) (MsgAcquire Nothing) = + encode (ClientAgency TokIdle) (MsgAcquire VolatileTip) = CBOR.encodeListLen 1 <> CBOR.encodeWord 8 + encode (ClientAgency TokIdle) (MsgAcquire ImmutableTip) + | canAcquireImmutable = + CBOR.encodeListLen 1 + <> CBOR.encodeWord 10 + | otherwise = + error $ "encodeFailure: local state query: acquiring the immutable tip " + ++ "must be conditional on negotiating v16 of the node-to-client " + ++ "protocol" + encode (ServerAgency TokAcquiring) MsgAcquired = CBOR.encodeListLen 1 <> CBOR.encodeWord 1 @@ -97,15 +108,24 @@ codecLocalStateQuery encodePoint decodePoint CBOR.encodeListLen 1 <> CBOR.encodeWord 5 - encode (ClientAgency TokAcquired) (MsgReAcquire (Just pt)) = + encode (ClientAgency TokAcquired) (MsgReAcquire (SpecificPoint pt)) = CBOR.encodeListLen 2 <> CBOR.encodeWord 6 <> encodePoint pt - encode (ClientAgency TokAcquired) (MsgReAcquire Nothing) = + encode (ClientAgency TokAcquired) (MsgReAcquire VolatileTip) = CBOR.encodeListLen 1 <> CBOR.encodeWord 9 + encode (ClientAgency TokAcquired) (MsgReAcquire ImmutableTip) + | canAcquireImmutable = + CBOR.encodeListLen 1 + <> CBOR.encodeWord 11 + | otherwise = + error $ "encodeFailure: local state query: re-acquiring the immutable " + ++ "tip must be conditional on negotiating v16 of the " + ++ "node-to-client protocol" + encode (ClientAgency TokIdle) MsgDone = CBOR.encodeListLen 1 <> CBOR.encodeWord 7 @@ -119,10 +139,13 @@ codecLocalStateQuery encodePoint decodePoint case (stok, len, key) of (ClientAgency TokIdle, 2, 0) -> do pt <- decodePoint - return (SomeMessage (MsgAcquire (Just pt))) + return (SomeMessage (MsgAcquire (SpecificPoint pt))) (ClientAgency TokIdle, 1, 8) -> do - return (SomeMessage (MsgAcquire Nothing)) + return (SomeMessage (MsgAcquire VolatileTip)) + + (ClientAgency TokIdle, 1, 10) -> do + return (SomeMessage (MsgAcquire ImmutableTip)) (ServerAgency TokAcquiring, 1, 1) -> return (SomeMessage MsgAcquired) @@ -144,10 +167,13 @@ codecLocalStateQuery encodePoint decodePoint (ClientAgency TokAcquired, 2, 6) -> do pt <- decodePoint - return (SomeMessage (MsgReAcquire (Just pt))) + return (SomeMessage (MsgReAcquire (SpecificPoint pt))) (ClientAgency TokAcquired, 1, 9) -> do - return (SomeMessage (MsgReAcquire Nothing)) + return (SomeMessage (MsgReAcquire VolatileTip)) + + (ClientAgency TokAcquired, 1, 11) -> do + return (SomeMessage (MsgReAcquire ImmutableTip)) (ClientAgency TokIdle, 1, 7) -> return (SomeMessage MsgDone) diff --git a/ouroboros-network-protocols/src/Ouroboros/Network/Protocol/LocalStateQuery/Server.hs b/ouroboros-network-protocols/src/Ouroboros/Network/Protocol/LocalStateQuery/Server.hs index ef2183047a5..cde87b395c4 100644 --- a/ouroboros-network-protocols/src/Ouroboros/Network/Protocol/LocalStateQuery/Server.hs +++ b/ouroboros-network-protocols/src/Ouroboros/Network/Protocol/LocalStateQuery/Server.hs @@ -35,7 +35,7 @@ newtype LocalStateQueryServer block point (query :: Type -> Type) m a = LocalSta -- It must be prepared to handle either. -- data ServerStIdle block point query m a = ServerStIdle { - recvMsgAcquire :: Maybe point + recvMsgAcquire :: Target point -> m (ServerStAcquiring block point query m a), recvMsgDone :: m a @@ -69,7 +69,7 @@ data ServerStAcquired block point query m a = ServerStAcquired { query result -> m (ServerStQuerying block point query m a result), - recvMsgReAcquire :: Maybe point + recvMsgReAcquire :: Target point -> m (ServerStAcquiring block point query m a), recvMsgRelease :: m (ServerStIdle block point query m a) diff --git a/ouroboros-network-protocols/src/Ouroboros/Network/Protocol/LocalStateQuery/Type.hs b/ouroboros-network-protocols/src/Ouroboros/Network/Protocol/LocalStateQuery/Type.hs index c37916754c9..67d37d338e2 100644 --- a/ouroboros-network-protocols/src/Ouroboros/Network/Protocol/LocalStateQuery/Type.hs +++ b/ouroboros-network-protocols/src/Ouroboros/Network/Protocol/LocalStateQuery/Type.hs @@ -1,4 +1,8 @@ {-# LANGUAGE DataKinds #-} +{-# LANGUAGE DeriveFoldable #-} +{-# LANGUAGE DeriveFunctor #-} +{-# LANGUAGE DeriveGeneric #-} +{-# LANGUAGE DeriveTraversable #-} {-# LANGUAGE EmptyCase #-} {-# LANGUAGE FlexibleInstances #-} {-# LANGUAGE GADTs #-} @@ -18,6 +22,7 @@ module Ouroboros.Network.Protocol.LocalStateQuery.Type where import Data.Kind (Type) import Data.Proxy (Proxy (..)) +import GHC.Generics (Generic) import Network.TypedProtocol.Core @@ -68,6 +73,23 @@ instance ( ShowProxy block , showProxy (Proxy :: Proxy query) ] +data Target point = -- | The tip of the volatile chain + -- + -- Cannot fail to be acquired. + VolatileTip + | -- | A specified point + -- + -- Fails to be acquired if the point is not between + -- 'VolatileTip' and 'ImmutableTip' (inclusive). + SpecificPoint point + -- | The tip of the immutable chain + -- + -- Cannot fail to be acquired. + -- + -- Requires at least 'NodeToClientV_16'. + | ImmutableTip + deriving (Eq, Foldable, Functor, Generic, Ord, Show, Traversable) + instance Protocol (LocalStateQuery block point query) where -- | The messages in the state query protocol. @@ -76,16 +98,11 @@ instance Protocol (LocalStateQuery block point query) where -- data Message (LocalStateQuery block point query) from to where - -- | The client requests that the state as of a particular recent point on - -- the server's chain (within K of the tip) be made available to query, - -- and waits for confirmation or failure. - -- - -- From 'NodeToClient_V8' onwards if the point is not specified, current tip - -- will be acquired. For previous versions of the protocol 'point' must be - -- given. + -- | The client requests that the 'Target' ledger state on the server's + -- chain be made available to query, and waits for confirmation or failure. -- MsgAcquire - :: Maybe point + :: Target point -> Message (LocalStateQuery block point query) StIdle StAcquiring -- | The server can confirm that it has the state at the requested point. @@ -122,19 +139,15 @@ instance Protocol (LocalStateQuery block point query) where :: Message (LocalStateQuery block point query) StAcquired StIdle -- | This is like 'MsgAcquire' but for when the client already has a - -- state. By moveing to another state directly without a 'MsgRelease' it + -- state. By moving to another state directly without a 'MsgRelease' it -- enables optimisations on the server side (e.g. moving to the state for -- the immediate next block). -- -- Note that failure to re-acquire is equivalent to 'MsgRelease', -- rather than keeping the exiting acquired state. -- - -- From 'NodeToClient_V8' onwards if the point is not specified, current tip - -- will be acquired. For previous versions of the protocol 'point' must be - -- given. - -- MsgReAcquire - :: Maybe point + :: Target point -> Message (LocalStateQuery block point query) StAcquired StAcquiring -- | The client can terminate the protocol. diff --git a/ouroboros-network-protocols/test-cddl/Main.hs b/ouroboros-network-protocols/test-cddl/Main.hs index 3c29360d23f..f54ff394e02 100644 --- a/ouroboros-network-protocols/test-cddl/Main.hs +++ b/ouroboros-network-protocols/test-cddl/Main.hs @@ -429,6 +429,7 @@ localStateQueryCodec :: Codec (LocalStateQuery Block BlockPoint Query) CBOR.DeserialiseFailure IO BL.ByteString localStateQueryCodec = codecLocalStateQuery + True Serialise.encode Serialise.decode encodeQuery decodeQuery (\Query{} -> Serialise.encode) (\Query{} -> Serialise.decode) diff --git a/ouroboros-network-protocols/test-cddl/specs/local-state-query.cddl b/ouroboros-network-protocols/test-cddl/specs/local-state-query.cddl index cf788832a45..991ee9c1ac1 100644 --- a/ouroboros-network-protocols/test-cddl/specs/local-state-query.cddl +++ b/ouroboros-network-protocols/test-cddl/specs/local-state-query.cddl @@ -22,7 +22,8 @@ query = any result = any msgAcquire = [0, point] - / [8] + / [8] + / [10] msgAcquired = [1] msgFailure = [2, failure] msgQuery = [3, query] @@ -30,5 +31,5 @@ msgResult = [4, result] msgRelease = [5] msgReAcquire = [6, point] / [9] + / [11] lsqMsgDone = [7] - diff --git a/ouroboros-network-protocols/testlib/Ouroboros/Network/Protocol/LocalStateQuery/Examples.hs b/ouroboros-network-protocols/testlib/Ouroboros/Network/Protocol/LocalStateQuery/Examples.hs index 01d356816c3..466a3348c50 100644 --- a/ouroboros-network-protocols/testlib/Ouroboros/Network/Protocol/LocalStateQuery/Examples.hs +++ b/ouroboros-network-protocols/testlib/Ouroboros/Network/Protocol/LocalStateQuery/Examples.hs @@ -5,7 +5,7 @@ module Ouroboros.Network.Protocol.LocalStateQuery.Examples where import Ouroboros.Network.Protocol.LocalStateQuery.Client import Ouroboros.Network.Protocol.LocalStateQuery.Server import Ouroboros.Network.Protocol.LocalStateQuery.Type - (AcquireFailure (..)) + (AcquireFailure (..), Target) -- @@ -20,36 +20,36 @@ import Ouroboros.Network.Protocol.LocalStateQuery.Type localStateQueryClient :: forall block point query result m. Applicative m - => [(Maybe point, query result)] + => [(Target point, query result)] -> LocalStateQueryClient block point query m - [(Maybe point, Either AcquireFailure result)] + [(Target point, Either AcquireFailure result)] localStateQueryClient = LocalStateQueryClient . pure . goIdle [] where goIdle - :: [(Maybe point, Either AcquireFailure result)] -- ^ Accumulator - -> [(Maybe point, query result)] -- ^ Remainder + :: [(Target point, Either AcquireFailure result)] -- ^ Accumulator + -> [(Target point, query result)] -- ^ Remainder -> ClientStIdle block point query m - [(Maybe point, Either AcquireFailure result)] + [(Target point, Either AcquireFailure result)] goIdle acc [] = SendMsgDone $ reverse acc goIdle acc ((pt, q):ptqs') = SendMsgAcquire pt $ goAcquiring acc pt q ptqs' goAcquiring - :: [(Maybe point, Either AcquireFailure result)] -- ^ Accumulator - -> Maybe point + :: [(Target point, Either AcquireFailure result)] -- ^ Accumulator + -> Target point -> query result - -> [(Maybe point, query result)] -- ^ Remainder + -> [(Target point, query result)] -- ^ Remainder -> ClientStAcquiring block point query m - [(Maybe point, Either AcquireFailure result)] + [(Target point, Either AcquireFailure result)] goAcquiring acc pt q ptqss' = ClientStAcquiring { recvMsgAcquired = pure $ goQuery q $ \r -> goAcquired ((pt, Right r):acc) ptqss' , recvMsgFailure = \failure -> pure $ goIdle ((pt, Left failure):acc) ptqss' } goAcquired - :: [(Maybe point, Either AcquireFailure result)] - -> [(Maybe point, query result)] -- ^ Remainder + :: [(Target point, Either AcquireFailure result)] + -> [(Target point, query result)] -- ^ Remainder -> ClientStAcquired block point query m - [(Maybe point, Either AcquireFailure result)] + [(Target point, Either AcquireFailure result)] goAcquired acc [] = SendMsgRelease $ pure $ SendMsgDone $ reverse acc goAcquired acc ((pt, qs):ptqss') = SendMsgReAcquire pt $ goAcquiring acc pt qs ptqss' @@ -71,7 +71,7 @@ localStateQueryClient = LocalStateQueryClient . pure . goIdle [] -- localStateQueryServer :: forall block point query m state. Applicative m - => (Maybe point -> Either AcquireFailure state) + => (Target point -> Either AcquireFailure state) -> (forall result. state -> query result -> result) -> LocalStateQueryServer block point query m () localStateQueryServer acquire answer = @@ -83,8 +83,8 @@ localStateQueryServer acquire answer = , recvMsgDone = pure () } - goAcquiring :: Maybe point -> m (ServerStAcquiring block point query m ()) - goAcquiring pt = pure $ case acquire pt of + goAcquiring :: Target point -> m (ServerStAcquiring block point query m ()) + goAcquiring tgt = pure $ case acquire tgt of Left failure -> SendMsgFailure failure goIdle Right state -> SendMsgAcquired $ goAcquired state diff --git a/ouroboros-network-protocols/testlib/Ouroboros/Network/Protocol/LocalStateQuery/Test.hs b/ouroboros-network-protocols/testlib/Ouroboros/Network/Protocol/LocalStateQuery/Test.hs index 258be6630d4..4793fb7f260 100644 --- a/ouroboros-network-protocols/testlib/Ouroboros/Network/Protocol/LocalStateQuery/Test.hs +++ b/ouroboros-network-protocols/testlib/Ouroboros/Network/Protocol/LocalStateQuery/Test.hs @@ -1,11 +1,12 @@ -{-# LANGUAGE FlexibleContexts #-} -{-# LANGUAGE FlexibleInstances #-} -{-# LANGUAGE GADTs #-} -{-# LANGUAGE NamedFieldPuns #-} -{-# LANGUAGE RankNTypes #-} -{-# LANGUAGE ScopedTypeVariables #-} -{-# LANGUAGE StandaloneDeriving #-} -{-# LANGUAGE TypeApplications #-} +{-# LANGUAGE FlexibleContexts #-} +{-# LANGUAGE FlexibleInstances #-} +{-# LANGUAGE GADTs #-} +{-# LANGUAGE GeneralizedNewtypeDeriving #-} +{-# LANGUAGE NamedFieldPuns #-} +{-# LANGUAGE RankNTypes #-} +{-# LANGUAGE ScopedTypeVariables #-} +{-# LANGUAGE StandaloneDeriving #-} +{-# LANGUAGE TypeApplications #-} {-# OPTIONS_GHC -Wno-orphans #-} module Ouroboros.Network.Protocol.LocalStateQuery.Test @@ -29,6 +30,7 @@ import Control.Tracer (nullTracer) import Codec.Serialise (DeserialiseFailure) import qualified Codec.Serialise as Serialise (decode, encode) +import qualified Codec.Serialise.Class as SerialiseClass import Network.TypedProtocol.Codec hiding (prop_codec) import Network.TypedProtocol.Proofs @@ -97,51 +99,58 @@ instance ( Arbitrary (query result) arbitrary = QueryWithResult <$> arbitrary <*> arbitrary data Query result where - QueryPoint :: Query (Maybe (Point Block)) + -- | An arbitrary query that happens to be trivial to implement in this test + GetTheLedgerState :: Query MockLedgerState deriving instance Show (Query result) instance ShowProxy Query where +newtype MockLedgerState = MockLedgerState (Target (Point Block)) + deriving (Arbitrary, Eq, Show, SerialiseClass.Serialise) + -- | Information to test an example server and client. data Setup = Setup - { clientInput :: [(Maybe (Point Block), Query (Maybe (Point Block)))] + { clientInput :: [(Target (Point Block), Query MockLedgerState)] -- ^ Input for 'localStateQueryClient' - , serverAcquire :: Maybe (Point Block) -> Either AcquireFailure (Maybe (Point Block)) + , serverAcquire :: Target (Point Block) -> Either AcquireFailure MockLedgerState -- ^ First input parameter for 'localStateQueryServer' - , serverAnswer :: forall result. Maybe (Point Block) -> Query result -> result + , serverAnswer :: forall result. MockLedgerState -> Query result -> result -- ^ Second input parameter for 'localStateQueryServer' - , expected :: [(Maybe (Point Block), Either AcquireFailure (Maybe (Point Block)))] + , expected :: [(Target (Point Block), Either AcquireFailure MockLedgerState)] -- ^ Expected result for the 'localStateQueryClient'. } -mkSetup - :: Map (Maybe (Point Block)) (Maybe AcquireFailure, Query (Maybe (Point Block))) - -- ^ For each point, the given state queries will be executed. In case of - -- the second field is an 'AcquireFailure', the server will fail with - -- that failure. - -- - -- This is the randomly generated input for the 'Setup'. - -> Setup +-- | This map determines the input to the server and client defined in +-- "Ouroboros.Network.Protocol.LocalStateQuery.Examples" +-- +-- For each entry, in order, the client will attempt to acquire the key, the +-- server will respond either with the given @'Just' 'AcquireFailure'@ or else +-- in the affirmative, in which case the client will issue the given query. +-- +-- This is the randomly generated input for the 'Setup'. +type SetupData = Map (Target (Point Block)) (Maybe AcquireFailure, Query MockLedgerState) + +mkSetup :: SetupData -> Setup mkSetup input = Setup { clientInput = [(pt, q) | (pt, (_, q)) <- Map.toList input] - , serverAcquire = \pt -> case Map.lookup pt input of - Just (Just failure, _qs) -> Left failure - Just (Nothing, _qs) -> Right pt - Nothing -> error $ - "a point not in the input was tried to be acquired: " <> show pt + , serverAcquire = \tgt -> case Map.lookup tgt input of + Just (Just failure, _q) -> Left failure + Just (Nothing, _q) -> Right (MockLedgerState tgt) + Nothing -> error $ + "a point not in the input was tried to be acquired: " <> show tgt , serverAnswer = answer , expected = - [ (pt, res) - | (pt, (mbFailure, q)) <- Map.toList input + [ (tgt, res) + | (tgt, (mbFailure, q)) <- Map.toList input , let res = case mbFailure of - Nothing -> Right $ answer pt q + Nothing -> Right $ answer (MockLedgerState tgt) q Just failure -> Left failure ] } where - answer :: Maybe (Point Block) -> Query result -> result - answer pt q = case q of - QueryPoint -> pt + answer :: MockLedgerState -> Query result -> result + answer st q = case q of + GetTheLedgerState -> st -- @@ -151,7 +160,7 @@ mkSetup input = Setup { -- | Run a simple local state query client and server, directly on the wrappers, -- without going via the 'Peer'. -- -prop_direct :: Map (Maybe (Point Block)) (Maybe AcquireFailure, Query (Maybe (Point Block))) +prop_direct :: SetupData -> Property prop_direct input = runSimOrThrow @@ -171,7 +180,7 @@ prop_direct input = -- | Run a simple local state query client and server, going via the 'Peer' -- representation, but without going via a channel. -- -prop_connect :: Map (Maybe (Point Block)) (Maybe AcquireFailure, Query (Maybe (Point Block))) +prop_connect :: SetupData -> Property prop_connect input = case runSimOrThrow @@ -197,7 +206,7 @@ prop_channel :: ( MonadAsync m , MonadST m ) => m (Channel m ByteString, Channel m ByteString) - -> Map (Maybe (Point Block)) (Maybe AcquireFailure, Query (Maybe (Point Block))) + -> SetupData -> m Property prop_channel createChannels input = @@ -216,7 +225,7 @@ prop_channel createChannels input = -- | Run 'prop_channel' in the simulation monad. -- -prop_channel_ST :: Map (Maybe (Point Block)) (Maybe AcquireFailure, Query (Maybe (Point Block))) +prop_channel_ST :: SetupData -> Property prop_channel_ST input = runSimOrThrow @@ -224,14 +233,14 @@ prop_channel_ST input = -- | Run 'prop_channel' in the IO monad. -- -prop_channel_IO :: Map (Maybe (Point Block)) (Maybe AcquireFailure, Query (Maybe (Point Block))) +prop_channel_IO :: SetupData -> Property prop_channel_IO input = ioProperty (prop_channel createConnectedChannels input) -- | Run 'prop_channel' in the IO monad using local pipes. -- -prop_pipe_IO :: Map (Maybe (Point Block)) (Maybe AcquireFailure, Query (Maybe (Point Block))) +prop_pipe_IO :: SetupData -> Property prop_pipe_IO input = ioProperty (prop_channel createPipeConnectedChannels input) @@ -241,14 +250,23 @@ prop_pipe_IO input = -- Codec properties -- +instance Arbitrary point => Arbitrary (Target point) where + arbitrary = oneof + [ pure ImmutableTip + , SpecificPoint <$> arbitrary + , pure VolatileTip + ] + +instance SerialiseClass.Serialise point => SerialiseClass.Serialise (Target point) + instance Arbitrary AcquireFailure where arbitrary = elements [ AcquireFailurePointTooOld , AcquireFailurePointNotOnChain ] -instance Arbitrary (Query (Maybe (Point Block))) where - arbitrary = pure QueryPoint +instance Arbitrary (Query MockLedgerState) where + arbitrary = pure GetTheLedgerState -- | A newtype wrapper which captures type of response generated for all -- queries. @@ -266,32 +284,9 @@ instance ( Arbitrary point , Arbitrary result ) => Arbitrary (AnyMessageAndAgencyWithResult block point query result) where - arbitrary = oneof - [ AnyMessageAndAgencyWithResult . getAnyMessageAndAgencyV7 <$> (arbitrary :: Gen (AnyMessageAndAgencyV7 block point query result)) - - , pure $ AnyMessageAndAgencyWithResult $ AnyMessageAndAgency (ClientAgency TokIdle) - (MsgAcquire Nothing) - - , pure $ AnyMessageAndAgencyWithResult $ AnyMessageAndAgency (ClientAgency TokAcquired) - (MsgReAcquire Nothing) - ] - --- Newtype wrapper which generates only valid data for 'NodeToClientV7' protocol. --- -newtype AnyMessageAndAgencyV7 block point query result = AnyMessageAndAgencyV7 { - getAnyMessageAndAgencyV7 - :: AnyMessageAndAgency (LocalStateQuery block point query) - } - deriving Show - -instance ( Arbitrary point - , Arbitrary (query result) - , Arbitrary result - ) - => Arbitrary (AnyMessageAndAgencyV7 block point query result) where - arbitrary = AnyMessageAndAgencyV7 <$> oneof + arbitrary = AnyMessageAndAgencyWithResult <$> oneof [ AnyMessageAndAgency (ClientAgency TokIdle) <$> - (MsgAcquire . Just <$> arbitrary) + (MsgAcquire <$> arbitrary) , AnyMessageAndAgency (ServerAgency TokAcquiring) <$> pure MsgAcquired @@ -311,15 +306,14 @@ instance ( Arbitrary point pure MsgRelease , AnyMessageAndAgency (ClientAgency TokAcquired) <$> - (MsgReAcquire . Just <$> arbitrary) + (MsgReAcquire <$> arbitrary) , AnyMessageAndAgency (ClientAgency TokIdle) <$> pure MsgDone ] - instance ShowQuery Query where - showResult QueryPoint = show + showResult GetTheLedgerState = show instance Eq (AnyMessage (LocalStateQuery Block (Point Block) Query)) where @@ -335,12 +329,12 @@ instance Eq (AnyMessage (LocalStateQuery Block (Point Block) Query)) where (==) (AnyMessage (MsgQuery query)) (AnyMessage (MsgQuery query')) = case (query, query') of - (QueryPoint, QueryPoint) -> True + (GetTheLedgerState, GetTheLedgerState) -> True (==) (AnyMessage (MsgResult query result)) (AnyMessage (MsgResult query' result')) = case (query, query') of - (QueryPoint, QueryPoint) -> result == result' + (GetTheLedgerState, GetTheLedgerState) -> result == result' (==) (AnyMessage MsgRelease) (AnyMessage MsgRelease) = True @@ -360,28 +354,29 @@ codec :: MonadST m m ByteString codec = codecLocalStateQuery + True Serialise.encode Serialise.decode encodeQuery decodeQuery encodeResult decodeResult where encodeQuery :: Query result -> CBOR.Encoding - encodeQuery QueryPoint = Serialise.encode () + encodeQuery GetTheLedgerState = Serialise.encode () decodeQuery :: forall s . CBOR.Decoder s (Some Query) decodeQuery = do () <- Serialise.decode - return $ Some QueryPoint + return $ Some GetTheLedgerState encodeResult :: Query result -> result -> CBOR.Encoding - encodeResult QueryPoint = Serialise.encode + encodeResult GetTheLedgerState = Serialise.encode decodeResult :: Query result -> forall s. CBOR.Decoder s result - decodeResult QueryPoint = Serialise.decode + decodeResult GetTheLedgerState = Serialise.decode -- | Check the codec round trip property. -- prop_codec - :: AnyMessageAndAgencyWithResult Block (Point Block) Query (Maybe (Point Block)) + :: AnyMessageAndAgencyWithResult Block (Point Block) Query MockLedgerState -> Bool prop_codec (AnyMessageAndAgencyWithResult msg) = runST (prop_codecM codec msg) @@ -389,7 +384,7 @@ prop_codec (AnyMessageAndAgencyWithResult msg) = -- | Check for data chunk boundary problems in the codec using 2 chunks. -- prop_codec_splits2 - :: AnyMessageAndAgencyWithResult Block (Point Block) Query (Maybe (Point Block)) + :: AnyMessageAndAgencyWithResult Block (Point Block) Query MockLedgerState -> Bool prop_codec_splits2 (AnyMessageAndAgencyWithResult msg) = runST (prop_codec_splitsM splits2 codec msg) @@ -397,13 +392,13 @@ prop_codec_splits2 (AnyMessageAndAgencyWithResult msg) = -- | Check for data chunk boundary problems in the codec using 3 chunks. -- prop_codec_splits3 - :: AnyMessageAndAgencyWithResult Block (Point Block) Query (Maybe (Point Block)) + :: AnyMessageAndAgencyWithResult Block (Point Block) Query MockLedgerState -> Bool prop_codec_splits3 (AnyMessageAndAgencyWithResult msg) = runST (prop_codec_splitsM splits3 codec msg) prop_codec_cbor - :: AnyMessageAndAgencyWithResult Block (Point Block) Query (Maybe (Point Block)) + :: AnyMessageAndAgencyWithResult Block (Point Block) Query MockLedgerState -> Bool prop_codec_cbor (AnyMessageAndAgencyWithResult msg) = runST (prop_codec_cborM codec msg) @@ -411,6 +406,6 @@ prop_codec_cbor (AnyMessageAndAgencyWithResult msg) = -- | Check that the encoder produces a valid CBOR. -- prop_codec_valid_cbor - :: AnyMessageAndAgencyWithResult Block (Point Block) Query (Maybe (Point Block)) + :: AnyMessageAndAgencyWithResult Block (Point Block) Query MockLedgerState -> Property prop_codec_valid_cbor (AnyMessageAndAgencyWithResult msg) = prop_codec_valid_cbor_encoding codec msg