55{-# LANGUAGE FlexibleContexts #-}
66{-# LANGUAGE FlexibleInstances #-}
77{-# LANGUAGE FunctionalDependencies #-}
8- {-# LANGUAGE NamedFieldPuns #-}
98{-# LANGUAGE ScopedTypeVariables #-}
10- {-# LANGUAGE TypeApplications #-}
9+ {-# LANGUAGE StandaloneDeriving #-}
1110{-# LANGUAGE TypeFamilies #-}
1211{-# LANGUAGE UndecidableInstances #-}
1312
1413module Ouroboros.Consensus.Block.SupportsPeras
1514 ( BlockSupportsPeras (.. )
16- , PerasCert (.. )
17- , PerasVote (.. )
18- , IsPerasVote (.. )
19- , getPerasVoteId
20- , getPerasVoteTarget
21- , IsPerasCert (.. )
15+ , PerasValidationErr (.. )
16+ , PerasForgeErr (.. )
2217 , ValidatedPerasCert (.. )
2318 , ValidatedPerasVote (.. )
2419 , ValidatedPerasVotesWithQuorum
@@ -27,14 +22,14 @@ module Ouroboros.Consensus.Block.SupportsPeras
2722 , vpvqPerasParams
2823 )
2924 , votesReachQuorum
25+ , IsPerasVote (.. )
26+ , getPerasVoteId
27+ , getPerasVoteTarget
28+ , IsPerasCert (.. )
3029 ) where
3130
32- import Cardano.Binary (FromCBOR (.. ), ToCBOR (.. ))
33- import Codec.Serialise (Serialise (.. ))
34- import Codec.Serialise.Decoding (decodeListLenOf )
35- import Codec.Serialise.Encoding (encodeListLen )
3631import Data.List.NonEmpty (NonEmpty (.. ))
37- import Data.Proxy ( Proxy ( .. ) )
32+ import Data.Typeable ( Typeable )
3833import GHC.Generics (Generic )
3934import NoThunks.Class
4035import Ouroboros.Consensus.Block.Abstract
@@ -47,38 +42,45 @@ import Ouroboros.Consensus.Peras.Types
4742 , PerasVoteStakeDistr (.. )
4843 , PerasVoteTarget (.. )
4944 , PerasVoterId (.. )
50- , lookupPerasVoteStake
5145 , stakeAboveThreshold
5246 )
53- import Ouroboros.Consensus.Util (ShowProxy (.. ))
5447
5548-- * BlockSupportsPeras class
5649
5750class
58- ( IsPerasVote (PerasVote blk ) blk
51+ ( StandardHash blk
52+ , Typeable blk
53+ , IsPerasVote (PerasVote blk ) blk
5954 , IsPerasCert (PerasCert blk ) blk
55+ , Show (PerasVote blk )
56+ , Show (PerasCert blk )
57+ , Show (PerasValidationErr blk )
58+ , Show (PerasForgeErr blk )
59+ , Eq (PerasVote blk )
60+ , Eq (PerasCert blk )
61+ , Eq (PerasValidationErr blk )
62+ , Eq (PerasForgeErr blk )
63+ , NoThunks (PerasVote blk )
64+ , NoThunks (PerasCert blk )
65+ , NoThunks (PerasValidationErr blk )
66+ , NoThunks (PerasForgeErr blk )
6067 ) =>
6168 BlockSupportsPeras blk
6269 where
63- data PerasCert blk
64-
6570 data PerasVote blk
66-
67- data PerasValidationErr blk
68-
69- data PerasForgeErr blk
70-
71- validatePerasCert ::
72- PerasParams ->
73- PerasCert blk ->
74- Either (PerasValidationErr blk ) (ValidatedPerasCert blk )
71+ data PerasCert blk
7572
7673 validatePerasVote ::
7774 PerasParams ->
7875 PerasVoteStakeDistr ->
7976 PerasVote blk ->
8077 Either (PerasValidationErr blk ) (ValidatedPerasVote blk )
8178
79+ validatePerasCert ::
80+ PerasParams ->
81+ PerasCert blk ->
82+ Either (PerasValidationErr blk ) (ValidatedPerasCert blk )
83+
8284 forgePerasCert ::
8385 PerasParams ->
8486 ValidatedPerasVotesWithQuorum blk ->
@@ -92,106 +94,21 @@ class
9294 blk ->
9395 Maybe (PerasCert blk )
9496
95- -- TODO: degenerate instance for all blks to get things to compile
96- -- see https://github.com/tweag/cardano-peras/issues/73
97- instance BlockSupportsPeras blk where
98- data PerasCert blk = PerasCert
99- { pcCertRound :: PerasRoundNo
100- , pcCertBlock :: Point blk
101- }
102- deriving stock (Generic , Eq , Ord , Show )
103- deriving anyclass NoThunks
104-
105- data PerasVote blk = PerasVote
106- { pvVoteRound :: PerasRoundNo
107- , pvVoteBlock :: Point blk
108- , pvVoteVoterId :: PerasVoterId
109- }
110- deriving stock (Generic , Eq , Ord , Show )
111- deriving anyclass NoThunks
112-
113- -- TODO: enrich with actual error types
114- -- see https://github.com/tweag/cardano-peras/issues/120
115- data PerasValidationErr blk
116- = PerasValidationErr
117- deriving stock (Show , Eq )
118-
119- -- TODO: enrich with actual error types
120- -- see https://github.com/tweag/cardano-peras/issues/120
121- data PerasForgeErr blk
122- = PerasForgeErr
123- deriving stock (Show , Eq )
97+ -- * Error types
12498
125- -- TODO: perform actual validation against all
126- -- possible 'PerasValidationErr' variants
127- -- see https://github.com/tweag/cardano-peras/issues/120
128- validatePerasCert params cert =
129- Right
130- ValidatedPerasCert
131- { vpcCert = cert
132- , vpcCertBoost = perasWeight params
133- }
134-
135- -- TODO: perform actual validation against all
136- -- possible 'PerasValidationErr' variants
137- -- see https://github.com/tweag/cardano-peras/issues/120
138- validatePerasVote _params stakeDistr vote
139- | Just stake <- lookupPerasVoteStake (getPerasVoteVoterId vote) stakeDistr =
140- Right
141- ValidatedPerasVote
142- { vpvVote = vote
143- , vpvVoteStake = stake
144- }
145- | otherwise =
146- Left PerasValidationErr
147-
148- -- TODO: perform actual validation against all
149- -- possible 'PerasForgeErr' variants
150- -- see https://github.com/tweag/cardano-peras/issues/120
151- forgePerasCert params votes =
152- return $
153- ValidatedPerasCert
154- { vpcCert =
155- PerasCert
156- { pcCertRound = pvtRoundNo (vpvqTarget votes)
157- , pcCertBlock = pvtBlock (vpvqTarget votes)
158- }
159- , vpcCertBoost = perasWeight params
160- }
161-
162- -- TODO: extract actual Peras certificates from blocks when the HFC plumbing
163- -- is in place.
164- getPerasCertInBlock _ = Nothing
165-
166- instance ShowProxy blk => ShowProxy (PerasCert blk ) where
167- showProxy _ = " PerasCert " <> showProxy (Proxy @ blk )
168-
169- instance ShowProxy blk => ShowProxy (PerasVote blk ) where
170- showProxy _ = " PerasVote " <> showProxy (Proxy @ blk )
171-
172- instance Serialise (HeaderHash blk ) => Serialise (PerasCert blk ) where
173- encode PerasCert {pcCertRound, pcCertBlock} =
174- encodeListLen 2
175- <> encode pcCertRound
176- <> encode pcCertBlock
177- decode = do
178- decodeListLenOf 2
179- pcCertRound <- decode
180- pcCertBlock <- decode
181- pure $ PerasCert {pcCertRound, pcCertBlock}
99+ -- TODO: enrich with actual error types
100+ -- see https://github.com/tweag/cardano-peras/issues/120
101+ data PerasValidationErr blk
102+ = PerasValidationErr
103+ deriving stock (Show , Eq , Generic )
104+ deriving anyclass NoThunks
182105
183- instance Serialise (HeaderHash blk ) => Serialise (PerasVote blk ) where
184- encode PerasVote {pvVoteRound, pvVoteBlock, pvVoteVoterId} =
185- encodeListLen 3
186- <> encode pvVoteRound
187- <> encode pvVoteBlock
188- <> toCBOR (unPerasVoterId pvVoteVoterId)
189- decode = do
190- decodeListLenOf 3
191- pvVoteRound <- decode
192- pvVoteBlock <- decode
193- pvVoteVoterId <- PerasVoterId <$> fromCBOR
194- pure $ PerasVote {pvVoteRound, pvVoteBlock, pvVoteVoterId}
106+ -- TODO: enrich with actual error types
107+ -- see https://github.com/tweag/cardano-peras/issues/120
108+ data PerasForgeErr blk
109+ = PerasForgeErr
110+ deriving stock (Show , Eq , Generic )
111+ deriving anyclass NoThunks
195112
196113-- * Validated types
197114
@@ -200,16 +117,24 @@ data ValidatedPerasVote blk
200117 { vpvVote :: ! (PerasVote blk )
201118 , vpvVoteStake :: ! PerasVoteStake
202119 }
203- deriving stock (Show , Eq , Ord , Generic )
204- deriving anyclass NoThunks
120+
121+ deriving instance Show (PerasVote blk ) => Show (ValidatedPerasVote blk )
122+ deriving instance Eq (PerasVote blk ) => Eq (ValidatedPerasVote blk )
123+ deriving instance Ord (PerasVote blk ) => Ord (ValidatedPerasVote blk )
124+ deriving instance NoThunks (PerasVote blk ) => NoThunks (ValidatedPerasVote blk )
125+ deriving instance Generic (ValidatedPerasVote blk )
205126
206127data ValidatedPerasCert blk
207128 = ValidatedPerasCert
208129 { vpcCert :: ! (PerasCert blk )
209130 , vpcCertBoost :: ! PerasWeight
210131 }
211- deriving stock (Show , Eq , Ord , Generic )
212- deriving anyclass NoThunks
132+
133+ deriving instance Show (PerasCert blk ) => Show (ValidatedPerasCert blk )
134+ deriving instance Eq (PerasCert blk ) => Eq (ValidatedPerasCert blk )
135+ deriving instance Ord (PerasCert blk ) => Ord (ValidatedPerasCert blk )
136+ deriving instance NoThunks (PerasCert blk ) => NoThunks (ValidatedPerasCert blk )
137+ deriving instance Generic (ValidatedPerasCert blk )
213138
214139-- | A collection of validated Peras votes that:
215140-- 1. are all for the same target, and
@@ -223,16 +148,34 @@ data ValidatedPerasVotesWithQuorum blk
223148 , vpvqPerasParams :: ! PerasParams
224149 -- ^ The Peras parameters used to validate that the votes reach quorum
225150 }
226- deriving stock (Show , Eq , Generic )
227- deriving anyclass NoThunks
151+
152+ deriving instance
153+ ( StandardHash blk
154+ , Show (PerasVote blk )
155+ ) =>
156+ Show (ValidatedPerasVotesWithQuorum blk )
157+ deriving instance
158+ ( StandardHash blk
159+ , Eq (PerasVote blk )
160+ ) =>
161+ Eq (ValidatedPerasVotesWithQuorum blk )
162+ deriving instance
163+ ( StandardHash blk
164+ , NoThunks (PerasVote blk )
165+ ) =>
166+ NoThunks (ValidatedPerasVotesWithQuorum blk )
167+ deriving instance
168+ Generic (ValidatedPerasVotesWithQuorum blk )
228169
229170-- | Smart constructor for 'ValidatedPerasVotesReachingQuorum'.
230171--
231172-- This function checks that all votes are for the same target, and that their
232173-- total stake is above the quorum threshold defined in the given 'PerasCfg'.
233174-- It returns 'Nothing' if either of these conditions is not met.
234175votesReachQuorum ::
235- StandardHash blk =>
176+ ( StandardHash blk
177+ , IsPerasVote (PerasVote blk ) blk
178+ ) =>
236179 PerasParams ->
237180 [ValidatedPerasVote blk ] ->
238181 Maybe (ValidatedPerasVotesWithQuorum blk )
@@ -287,17 +230,18 @@ getPerasVoteTarget vote =
287230 , pvtBlock = getPerasVoteBlock vote
288231 }
289232
290- instance IsPerasVote (PerasVote blk ) blk where
291- getPerasVoteRound = pvVoteRound
292- getPerasVoteBlock = pvVoteBlock
293- getPerasVoteVoterId = pvVoteVoterId
294-
295- instance IsPerasVote (ValidatedPerasVote blk ) blk where
233+ instance
234+ IsPerasVote (PerasVote blk ) blk =>
235+ IsPerasVote (ValidatedPerasVote blk ) blk
236+ where
296237 getPerasVoteRound = getPerasVoteRound . vpvVote
297238 getPerasVoteBlock = getPerasVoteBlock . vpvVote
298239 getPerasVoteVoterId = getPerasVoteVoterId . vpvVote
299240
300- instance IsPerasVote vote blk => IsPerasVote (WithArrivalTime vote ) blk where
241+ instance
242+ IsPerasVote vote blk =>
243+ IsPerasVote (WithArrivalTime vote ) blk
244+ where
301245 getPerasVoteRound = getPerasVoteRound . forgetArrivalTime
302246 getPerasVoteBlock = getPerasVoteBlock . forgetArrivalTime
303247 getPerasVoteVoterId = getPerasVoteVoterId . forgetArrivalTime
@@ -307,11 +251,10 @@ class IsPerasCert cert blk | cert -> blk where
307251 getPerasCertRound :: cert -> PerasRoundNo
308252 getPerasCertBlock :: cert -> Point blk
309253
310- instance IsPerasCert (PerasCert blk ) blk where
311- getPerasCertRound = pcCertRound
312- getPerasCertBlock = pcCertBlock
313-
314- instance IsPerasCert (ValidatedPerasCert blk ) blk where
254+ instance
255+ IsPerasCert (PerasCert blk ) blk =>
256+ IsPerasCert (ValidatedPerasCert blk ) blk
257+ where
315258 getPerasCertRound = getPerasCertRound . vpcCert
316259 getPerasCertBlock = getPerasCertBlock . vpcCert
317260
0 commit comments