Skip to content

Commit

Permalink
LocalStateQuery: let the client acquire the immutable tip
Browse files Browse the repository at this point in the history
We will use this to make it easier for the CLI to only output answers that are
not subject to rollback.

This change to LocalStateQuery is gated by NodeToClient_Version16, since that
is still mutable (it enables Conway et al).
  • Loading branch information
nfrisby committed Jan 5, 2024
1 parent 9028b8d commit bf971a2
Show file tree
Hide file tree
Showing 10 changed files with 172 additions and 130 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -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)

Expand Down
5 changes: 5 additions & 0 deletions ouroboros-network-protocols/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down Expand Up @@ -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

Expand Down Expand Up @@ -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

Expand Down Expand Up @@ -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)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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
Expand All @@ -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
Expand All @@ -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)
Expand All @@ -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)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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)
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,8 @@
{-# LANGUAGE DataKinds #-}
{-# LANGUAGE DeriveFoldable #-}
{-# LANGUAGE DeriveFunctor #-}
{-# LANGUAGE DeriveGeneric #-}
{-# LANGUAGE DeriveTraversable #-}
{-# LANGUAGE EmptyCase #-}
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE GADTs #-}
Expand All @@ -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

Expand Down Expand Up @@ -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.
Expand All @@ -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.
Expand Down Expand Up @@ -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.
Expand Down
1 change: 1 addition & 0 deletions ouroboros-network-protocols/test-cddl/Main.hs
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,13 +22,14 @@ query = any
result = any

msgAcquire = [0, point]
/ [8]
/ [8]
/ [10]
msgAcquired = [1]
msgFailure = [2, failure]
msgQuery = [3, query]
msgResult = [4, result]
msgRelease = [5]
msgReAcquire = [6, point]
/ [9]
/ [11]
lsqMsgDone = [7]

Original file line number Diff line number Diff line change
Expand Up @@ -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)


--
Expand All @@ -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'
Expand All @@ -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 =
Expand All @@ -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

Expand Down
Loading

0 comments on commit bf971a2

Please sign in to comment.