Skip to content

Commit be396a3

Browse files
committed
Fix typed-protocols-doc
1 parent 097476e commit be396a3

File tree

6 files changed

+122
-149
lines changed

6 files changed

+122
-149
lines changed

cabal.project

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,6 @@ packages: ./typed-protocols
1919
./typed-protocols-stateful
2020
./typed-protocols-stateful-cborg
2121
./typed-protocols-examples
22-
-- ./typed-protocols-doc
22+
./typed-protocols-doc
2323

2424
test-show-details: direct

typed-protocols-doc/src/Network/TypedProtocol/Documentation/TH.hs

Lines changed: 20 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ import Control.Monad
1515
-- This import is only needed when 'getDoc' is available.
1616
import Data.Maybe (maybeToList)
1717
#endif
18+
import Data.Maybe (mapMaybe)
1819
import Data.Proxy
1920
import Language.Haskell.TH
2021
import Language.Haskell.TH.Datatype
@@ -34,45 +35,29 @@ describeProtocol protoTyCon protoTyArgs codecTyCon codecTyArgs = do
3435
protoDescription <- getDescription protoTyCon
3536
let pname = nameBase (datatypeName info)
3637

37-
let extractMessageStateNames :: InstanceDec -> [Name]
38-
extractMessageStateNames (DataInstD _ _ _ _ tys _) =
39-
[ case ty of
40-
ForallC _ _ (GadtC _ _ ty') -> go ty'
41-
GadtC _ _ ty' -> go ty'
42-
_ -> error $ "Not a GADT: " ++ show ty
43-
| ty <- tys
44-
]
45-
where
46-
go (PromotedT tyName) = tyName
47-
go (SigT ty' _) = go ty'
48-
go (AppT _ ty') = go ty'
49-
go ty' = error $ "Cannot detect message name from type: " ++ show ty'
50-
extractMessageStateNames i = error $ "Not a DataInstD: " ++ show i
38+
let extractAgency :: InstanceDec -> Maybe Name
39+
extractAgency (TySynInstD (TySynEqn _ _ (PromotedT agency))) = Just agency
40+
extractAgency dec = error $ "Unexpected InstanceDec: " ++ show dec
41+
42+
let extractAgencies :: [InstanceDec] -> [Name]
43+
extractAgencies = mapMaybe extractAgency
44+
45+
let extractTheAgency :: [InstanceDec] -> Name
46+
extractTheAgency inst = case extractAgencies inst of
47+
[agency] -> agency
48+
xs -> error $ "Incorrect number of agencies: " ++ show xs
5149

5250
pstates <- forM (datatypeCons info) $ \conInfo -> do
5351
let conName = constructorName conInfo
5452
stateDescription <- getDescription conName
5553

56-
serverAgencies <- reifyInstances ''ServerHasAgency [ConT conName]
57-
let serverAgencies' =
58-
[ nameBase tyName
59-
| inst <- serverAgencies
60-
, tyName <- extractMessageStateNames inst
61-
, nameBase tyName == nameBase conName
62-
]
63-
clientAgencies <- reifyInstances ''ClientHasAgency [ConT conName]
64-
let clientAgencies' =
65-
[ nameBase tyName
66-
| inst <- clientAgencies
67-
, tyName <- extractMessageStateNames inst
68-
, nameBase tyName == nameBase conName
69-
]
70-
71-
let agencyID = case (serverAgencies', clientAgencies') of
72-
([], []) -> NobodyAgencyID
73-
(_, []) -> ServerAgencyID
74-
([], _) -> ClientAgencyID
75-
_ -> error $ show (nameBase conName, serverAgencies', clientAgencies')
54+
stateAgencies <- reifyInstances ''StateAgency [ConT conName]
55+
let agencyName = extractTheAgency stateAgencies
56+
agencyID = case nameBase agencyName of
57+
"ServerAgency" -> 'ServerAgencyID
58+
"ClientAgency" -> 'ClientAgencyID
59+
"NobodyAgency" -> 'NobodyAgencyID
60+
x -> error $ "Unknown agency type " ++ x ++ " in state " ++ nameBase conName
7661

7762
return (conName, stateDescription, agencyID)
7863

@@ -87,7 +72,7 @@ describeProtocol protoTyCon protoTyArgs codecTyCon codecTyArgs = do
8772
protoDescription
8873
""
8974
$(listE
90-
[ [| ( $(makeState $ ConT conName), stateDescription, agencyID) |]
75+
[ [| ( $(makeState $ ConT conName), stateDescription, $(conE agencyID)) |]
9176
| (conName, stateDescription, agencyID) <- pstates
9277
]
9378
)

typed-protocols-doc/test/Network/TypedProtocol/Tests/ControlProtocol.hs

Lines changed: 54 additions & 65 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
{-# OPTIONS_GHC -Wno-redundant-constraints #-}
2+
13
{-# LANGUAGE DataKinds #-}
24
{-# LANGUAGE DerivingVia #-}
35
{-# LANGUAGE EmptyCase #-}
@@ -30,10 +32,10 @@ import Data.Typeable
3032
import Data.Word
3133
import Network.TypedProtocol.Core
3234

33-
data AgentInfo c =
35+
data AgentInfo =
3436
AgentInfo
35-
{ agentInfoCurrentBundle :: !(Maybe (BundleInfo c))
36-
, agentInfoStagedKey :: !(Maybe (KeyInfo c))
37+
{ agentInfoCurrentBundle :: !(Maybe BundleInfo)
38+
, agentInfoStagedKey :: !(Maybe KeyInfo)
3739
, agentInfoBootstrapConnections :: ![BootstrapInfo]
3840
}
3941
deriving (Show, Eq)
@@ -50,7 +52,6 @@ deriving via (ViaEnum Command)
5052
instance
5153
( Codec codec
5254
, HasInfo codec (DefEnumEncoding codec)
53-
, Integral (DefEnumEncoding codec)
5455
) => HasInfo codec Command
5556

5657
instance
@@ -63,16 +64,16 @@ instance
6364
encode codec = encodeEnum codec (Proxy @(DefEnumEncoding codec))
6465
decode codec = decodeEnum codec (Proxy @(DefEnumEncoding codec))
6566

66-
newtype FakeKey k = FakeKey { fakeKeyData :: ByteString }
67+
newtype FakeKey = FakeKey { fakeKeyData :: ByteString }
6768
deriving (Show, Eq, Ord)
6869

6970
newtype VersionIdentifier = VersionIdentifier { versionIdentifierData :: ByteString }
7071
deriving (Show, Eq, Ord)
7172

72-
instance HasInfo (TestCodec ()) VersionIdentifier where
73+
instance HasInfo TestCodec VersionIdentifier where
7374
info _ _ = basicField "Bytes" (FixedSize 32)
7475

75-
instance HasInfo (TestCodec ()) (FakeKey k) where
76+
instance HasInfo TestCodec FakeKey where
7677
info _ _ = basicField "Bytes" (FixedSize 128)
7778

7879
data BootstrapInfo =
@@ -92,25 +93,25 @@ deriving via (ViaEnum ConnectionStatus)
9293
instance (Codec codec, HasInfo codec (DefEnumEncoding codec))
9394
=> HasInfo codec ConnectionStatus
9495

95-
data BundleInfo c =
96+
data BundleInfo =
9697
BundleInfo
9798
{ bundleInfoEvolution :: !Word32
9899
, bundleInfoOCertN :: !Word64
99-
, bundleInfoVK :: !(FakeKey c)
100+
, bundleInfoVK :: !FakeKey
100101
}
101102
deriving (Show, Eq)
102103

103-
newtype KeyInfo c =
104+
newtype KeyInfo =
104105
KeyInfo
105-
{ keyInfoVK :: FakeKey c
106+
{ keyInfoVK :: FakeKey
106107
}
107108
deriving (Show, Eq)
108109

109110
deriving newtype
110111
instance
111-
( HasInfo codec (FakeKey c)
112+
( HasInfo codec FakeKey
112113
, Codec codec
113-
) => HasInfo codec (KeyInfo c)
114+
) => HasInfo codec KeyInfo
114115

115116
$(deriveSerDoc ''TestCodec [] ''BundleInfo)
116117
$(deriveSerDoc ''TestCodec [] ''BootstrapInfo)
@@ -129,27 +130,27 @@ $(deriveSerDoc ''TestCodec [] ''AgentInfo)
129130
-- through. This allows the control client to report success to the user, but it
130131
-- also helps make things more predictable in testing, because it means that
131132
-- sending keys is now synchronous.
132-
data ControlProtocol (m :: Type -> Type) (k :: Type) where
133+
data ControlProtocol (m :: Type -> Type) (c :: Type) where
133134
-- | Default state after connecting, but before the protocol version has been
134135
-- negotiated.
135-
InitialState :: ControlProtocol m k
136+
InitialState :: ControlProtocol m c
136137

137138
-- | System is idling, waiting for the server to push the next key.
138-
IdleState :: ControlProtocol m k
139+
IdleState :: ControlProtocol m c
139140

140141
-- | Client has requested a new KES key to be generated in the staging area.
141-
WaitForPublicKeyState :: ControlProtocol m k
142+
WaitForPublicKeyState :: ControlProtocol m c
142143

143144
-- | Client has requested agent information
144-
WaitForInfoState :: ControlProtocol m k
145+
WaitForInfoState :: ControlProtocol m c
145146

146147
-- | An OpCert has been pushed, client must now confirm that it has been
147148
-- received, and that it matches the staged KES key.
148-
WaitForConfirmationState :: ControlProtocol m k
149+
WaitForConfirmationState :: ControlProtocol m c
149150

150151
-- | The server has closed the connection, thus signalling the end of the
151152
-- session.
152-
EndState :: ControlProtocol m k
153+
EndState :: ControlProtocol m c
153154

154155
{-# ANN VersionMessage (Description ["Announce the protocol version."]) #-}
155156
{-# ANN GenStagedKeyMessage
@@ -217,61 +218,49 @@ instance Protocol (ControlProtocol m c) where
217218

218219
DropStagedKeyMessage :: Message (ControlProtocol m c) IdleState WaitForPublicKeyState
219220

220-
PublicKeyMessage :: Maybe (FakeKey c)
221+
PublicKeyMessage :: Maybe FakeKey
221222
-> Message (ControlProtocol m c) WaitForPublicKeyState IdleState
222223

223-
InstallKeyMessage :: FakeKey c
224+
InstallKeyMessage :: FakeKey
224225
-> Message (ControlProtocol m c) IdleState WaitForConfirmationState
225226

226227
InstallResultMessage :: Word32
227228
-> Message (ControlProtocol m c) WaitForConfirmationState IdleState
228229

229230
RequestInfoMessage :: Message (ControlProtocol m c) IdleState WaitForInfoState
230231

231-
InfoMessage :: AgentInfo c
232+
InfoMessage :: AgentInfo
232233
-> Message (ControlProtocol m c) WaitForInfoState IdleState
233234

234235
AbortMessage :: Message (ControlProtocol m c) InitialState EndState
235236
EndMessage :: Message (ControlProtocol m c) IdleState EndState
236237
ProtocolErrorMessage :: Message (ControlProtocol m c) a EndState
237238

238239
-- | Server always has agency, except between sending a key and confirming it
239-
data ServerHasAgency st where
240-
TokInitial :: ServerHasAgency InitialState
241-
TokIdle :: ServerHasAgency IdleState
242-
243-
-- | Client only has agency between sending a key and confirming it
244-
data ClientHasAgency st where
245-
TokWaitForConfirmation :: ClientHasAgency WaitForConfirmationState
246-
TokWaitForPublicKey :: ClientHasAgency WaitForPublicKeyState
247-
TokWaitForInfo :: ClientHasAgency WaitForInfoState
248-
249-
-- | Someone, i.e., the server, always has agency
250-
data NobodyHasAgency st where
251-
TokEnd :: NobodyHasAgency EndState
252-
253-
exclusionLemma_ClientAndServerHaveAgency tok1 tok2 =
254-
case tok1 of
255-
TokWaitForConfirmation ->
256-
case tok2 of {}
257-
TokWaitForPublicKey ->
258-
case tok2 of {}
259-
TokWaitForInfo ->
260-
case tok2 of {}
261-
exclusionLemma_NobodyAndClientHaveAgency tok1 tok2 =
262-
case tok1 of
263-
TokEnd -> case tok2 of {}
264-
exclusionLemma_NobodyAndServerHaveAgency tok1 tok2 =
265-
case tok1 of
266-
TokEnd -> case tok2 of {}
267-
268-
instance HasInfo (TestCodec ()) (Message (ControlProtocol m c) InitialState IdleState) where
240+
type StateAgency InitialState = ServerAgency
241+
type StateAgency IdleState = ServerAgency
242+
type StateAgency WaitForConfirmationState = ClientAgency
243+
type StateAgency WaitForPublicKeyState = ClientAgency
244+
type StateAgency WaitForInfoState = ClientAgency
245+
type StateAgency EndState = NobodyAgency
246+
247+
type StateToken = SControlProtocol
248+
249+
data SControlProtocol (st :: ControlProtocol m c) where
250+
SInitialState :: SControlProtocol InitialState
251+
SIdleState :: SControlProtocol IdleState
252+
SWaitForConfirmationState :: SControlProtocol WaitForConfirmationState
253+
SWaitForPublicKeyState :: SControlProtocol WaitForPublicKeyState
254+
SWaitForInfoState :: SControlProtocol WaitForInfoState
255+
SEndState :: SControlProtocol EndState
256+
257+
instance HasInfo TestCodec (Message (ControlProtocol m c) InitialState IdleState) where
269258
info codec _ = aliasField
270259
("Message<" ++
271260
"InitialState,IdleState" ++
272261
">")
273262
(info codec (Proxy @VersionIdentifier))
274-
instance HasInfo (TestCodec ()) (Message (ControlProtocol m c) IdleState WaitForPublicKeyState) where
263+
instance HasInfo TestCodec (Message (ControlProtocol m c) IdleState WaitForPublicKeyState) where
275264
info codec _ = aliasField
276265
("Message<" ++
277266
"IdleState,WaitForPublicKeyState" ++
@@ -283,39 +272,39 @@ instance HasInfo (TestCodec ()) (Message (ControlProtocol m c) IdleState WaitFor
283272
-- QueryStagedKeyMessage -> infoOf QueryStagedKeyCmd
284273
-- DropStagedKeyMessage -> infoOf DropStagedKeyCmd
285274

286-
instance (HasInfo (TestCodec ()) (FakeKey c)) => HasInfo (TestCodec ()) (Message (ControlProtocol m c) WaitForPublicKeyState IdleState) where
275+
instance (HasInfo TestCodec FakeKey) => HasInfo TestCodec (Message (ControlProtocol m c) WaitForPublicKeyState IdleState) where
287276
info codec _ = aliasField
288277
("Message<" ++
289278
"WaitForPublicKeyState,IdleState" ++
290279
">")
291-
(info codec (Proxy @(Maybe (FakeKey c))))
292-
instance (HasInfo (TestCodec ()) (FakeKey c)) => HasInfo (TestCodec ()) (Message (ControlProtocol m c) IdleState WaitForConfirmationState) where
280+
(info codec (Proxy @(Maybe FakeKey)))
281+
instance (HasInfo TestCodec FakeKey) => HasInfo TestCodec (Message (ControlProtocol m c) IdleState WaitForConfirmationState) where
293282
info codec _ = aliasField
294283
("Message<" ++
295284
"IdleState,WaitForConfirmationState" ++
296285
">")
297-
(info codec (Proxy @(FakeKey c)))
298-
instance HasInfo (TestCodec ()) (Message (ControlProtocol m c) WaitForConfirmationState IdleState) where
286+
(info codec (Proxy @FakeKey))
287+
instance HasInfo TestCodec (Message (ControlProtocol m c) WaitForConfirmationState IdleState) where
299288
info codec _ = aliasField
300289
("Message<" ++
301290
"WaitForConfirmationState,IdleState" ++
302291
">")
303292
(info codec (Proxy @Word32))
304-
instance HasInfo (TestCodec ()) (Message (ControlProtocol m c) IdleState WaitForInfoState) where
293+
instance HasInfo TestCodec (Message (ControlProtocol m c) IdleState WaitForInfoState) where
305294
info codec _ = aliasField
306295
("Message<" ++
307296
"IdleState,WaitForInfoState" ++
308297
">")
309298
(info codec (Proxy @()))
310-
instance ( HasInfo (TestCodec ()) (FakeKey c)
311-
, HasInfo (TestCodec ()) (AgentInfo c)
312-
) => HasInfo (TestCodec ()) (Message (ControlProtocol m c) WaitForInfoState IdleState) where
299+
instance ( HasInfo TestCodec FakeKey
300+
, HasInfo TestCodec AgentInfo
301+
) => HasInfo TestCodec (Message (ControlProtocol m c) WaitForInfoState IdleState) where
313302
info codec _ = aliasField
314303
("Message<" ++
315304
"WaitForInfoState,IdleState" ++
316305
">")
317-
(info codec (Proxy @(AgentInfo c)))
318-
instance HasInfo (TestCodec ()) (Message (ControlProtocol m c) _st EndState) where
306+
(info codec (Proxy @AgentInfo))
307+
instance HasInfo TestCodec (Message (ControlProtocol m c) _st EndState) where
319308
info codec _ = aliasField
320309
("Message<" ++
321310
"st,EndState" ++

typed-protocols-doc/test/Network/TypedProtocol/Tests/Documentation.hs

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -24,10 +24,10 @@ tests = testGroup "Documentation"
2424
, testProperty "state transitions" (p_correctStateTransitions testProtocolDescription)
2525
]
2626

27-
testProtocolDescription :: ProtocolDescription (TestCodec ())
28-
testProtocolDescription = $(describeProtocol ''ControlProtocol [''IO, ''()] ''TestCodec [''()])
27+
testProtocolDescription :: ProtocolDescription TestCodec
28+
testProtocolDescription = $(describeProtocol ''ControlProtocol [''IO, ''()] ''TestCodec [])
2929

30-
p_correctAgencies :: ProtocolDescription (TestCodec ()) -> Property
30+
p_correctAgencies :: ProtocolDescription TestCodec -> Property
3131
p_correctAgencies d =
3232
counterexample (show stateAgencyMap) .
3333
once $
@@ -45,7 +45,7 @@ p_correctAgencies d =
4545
where
4646
stateAgencyMap = [(state, agency) | (state, _, agency) <- protocolStates d]
4747

48-
p_correctStateTransitions :: ProtocolDescription (TestCodec ()) -> Property
48+
p_correctStateTransitions :: ProtocolDescription TestCodec -> Property
4949
p_correctStateTransitions d =
5050
once $
5151
checkMessage "VersionMessage" (State "InitialState") (State "IdleState")
@@ -83,6 +83,6 @@ p_correctStateTransitions d =
8383
counterexample "toState"
8484
(messageToState msg === toState)
8585

86-
findMessage :: String -> Maybe (MessageDescription (TestCodec ()))
86+
findMessage :: String -> Maybe (MessageDescription TestCodec)
8787
findMessage msgName =
8888
listToMaybe [ msg | msg <- protocolMessages d, messageName msg == msgName ]

0 commit comments

Comments
 (0)