Skip to content

Commit 2516bc0

Browse files
committed
O.C.Peras.Weight: add haddocks
using cabal-docspec (not yet nixified)
1 parent 4defc5d commit 2516bc0

File tree

1 file changed

+163
-4
lines changed
  • ouroboros-consensus/src/ouroboros-consensus/Ouroboros/Consensus/Peras

1 file changed

+163
-4
lines changed

ouroboros-consensus/src/ouroboros-consensus/Ouroboros/Consensus/Peras/Weight.hs

Lines changed: 163 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5,14 +5,25 @@
55
{-# LANGUAGE ScopedTypeVariables #-}
66
{-# LANGUAGE TypeOperators #-}
77

8+
-- | Data structure for tracking the weight of blocks due to Peras boosts.
89
module Ouroboros.Consensus.Peras.Weight
9-
( -- * 'PerasWeightSnapshot'
10+
( -- * 'PerasWeightSnapshot' type
1011
PerasWeightSnapshot
12+
13+
-- * Construction
1114
, emptyPerasWeightSnapshot
1215
, mkPerasWeightSnapshot
16+
17+
-- * Conversion
1318
, perasWeightSnapshotToList
19+
20+
-- * Insertion
1421
, addToPerasWeightSnapshot
22+
23+
-- * Pruning
1524
, prunePerasWeightSnapshot
25+
26+
-- * Query
1627
, weightBoostOfPoint
1728
, weightBoostOfFragment
1829
) where
@@ -26,16 +37,37 @@ import Ouroboros.Consensus.Block
2637
import Ouroboros.Network.AnchoredFragment (AnchoredFragment)
2738
import qualified Ouroboros.Network.AnchoredFragment as AF
2839

40+
-- | Data structure for tracking the weight of blocks due to Peras boosts.
2941
newtype PerasWeightSnapshot blk = PerasWeightSnapshot
3042
{ getPerasWeightSnapshot :: Map (Point blk) PerasWeight
3143
}
32-
deriving stock (Show, Eq)
44+
deriving stock Eq
3345
deriving Generic
3446
deriving newtype NoThunks
3547

48+
instance StandardHash blk => Show (PerasWeightSnapshot blk) where
49+
show = show . perasWeightSnapshotToList
50+
51+
-- | An empty 'PerasWeightSnapshot' not containing any boosted blocks.
3652
emptyPerasWeightSnapshot :: PerasWeightSnapshot blk
3753
emptyPerasWeightSnapshot = PerasWeightSnapshot Map.empty
3854

55+
-- | Create a weight snapshot from a list of boosted points with an associated
56+
-- weight. In case of duplicate points, their weights are combined.
57+
--
58+
-- >>> :{
59+
-- weights :: [(Point Blk, PerasWeight)]
60+
-- weights =
61+
-- [ (BlockPoint 2 "foo", PerasWeight 2)
62+
-- , (GenesisPoint, PerasWeight 3)
63+
-- , (BlockPoint 3 "bar", PerasWeight 2)
64+
-- , (BlockPoint 2 "foo", PerasWeight 2)
65+
-- ]
66+
-- :}
67+
--
68+
-- >>> snap = mkPerasWeightSnapshot weights
69+
-- >>> snap
70+
-- [(Origin,PerasWeight 3),(At (Block {blockPointSlot = SlotNo 2, blockPointHash = "foo"}),PerasWeight 4),(At (Block {blockPointSlot = SlotNo 3, blockPointHash = "bar"}),PerasWeight 2)]
3971
mkPerasWeightSnapshot ::
4072
StandardHash blk =>
4173
[(Point blk, PerasWeight)] ->
@@ -45,9 +77,47 @@ mkPerasWeightSnapshot =
4577
(\s (pt, weight) -> addToPerasWeightSnapshot pt weight s)
4678
emptyPerasWeightSnapshot
4779

80+
-- | Return the list of boosted points with their associated weight, sorted
81+
-- based on their point. Does not contain duplicate points.
82+
--
83+
-- >>> :{
84+
-- weights :: [(Point Blk, PerasWeight)]
85+
-- weights =
86+
-- [ (BlockPoint 2 "foo", PerasWeight 2)
87+
-- , (GenesisPoint, PerasWeight 3)
88+
-- , (BlockPoint 3 "bar", PerasWeight 2)
89+
-- , (BlockPoint 2 "foo", PerasWeight 2)
90+
-- ]
91+
-- :}
92+
--
93+
-- >>> snap = mkPerasWeightSnapshot weights
94+
-- >>> perasWeightSnapshotToList snap
95+
-- [(Origin,PerasWeight 3),(At (Block {blockPointSlot = SlotNo 2, blockPointHash = "foo"}),PerasWeight 4),(At (Block {blockPointSlot = SlotNo 3, blockPointHash = "bar"}),PerasWeight 2)]
4896
perasWeightSnapshotToList :: PerasWeightSnapshot blk -> [(Point blk, PerasWeight)]
49-
perasWeightSnapshotToList = Map.toList . getPerasWeightSnapshot
97+
perasWeightSnapshotToList = Map.toAscList . getPerasWeightSnapshot
5098

99+
-- | Add weight for the given point to the 'PerasWeightSnapshot'. If the point
100+
-- already has some weight, it is added on top.
101+
--
102+
-- >>> :{
103+
-- weights :: [(Point Blk, PerasWeight)]
104+
-- weights =
105+
-- [ (BlockPoint 2 "foo", PerasWeight 2)
106+
-- , (GenesisPoint, PerasWeight 3)
107+
-- ]
108+
-- :}
109+
--
110+
-- >>> snap0 = mkPerasWeightSnapshot weights
111+
-- >>> snap0
112+
-- [(Origin,PerasWeight 3),(At (Block {blockPointSlot = SlotNo 2, blockPointHash = "foo"}),PerasWeight 2)]
113+
--
114+
-- >>> snap1 = addToPerasWeightSnapshot (BlockPoint 3 "bar") (PerasWeight 2) snap0
115+
-- >>> snap1
116+
-- [(Origin,PerasWeight 3),(At (Block {blockPointSlot = SlotNo 2, blockPointHash = "foo"}),PerasWeight 2),(At (Block {blockPointSlot = SlotNo 3, blockPointHash = "bar"}),PerasWeight 2)]
117+
--
118+
-- >>> snap2 = addToPerasWeightSnapshot (BlockPoint 2 "foo") (PerasWeight 2) snap1
119+
-- >>> snap2
120+
-- [(Origin,PerasWeight 3),(At (Block {blockPointSlot = SlotNo 2, blockPointHash = "foo"}),PerasWeight 4),(At (Block {blockPointSlot = SlotNo 3, blockPointHash = "bar"}),PerasWeight 2)]
51121
addToPerasWeightSnapshot ::
52122
StandardHash blk =>
53123
Point blk ->
@@ -57,6 +127,29 @@ addToPerasWeightSnapshot ::
57127
addToPerasWeightSnapshot pt weight =
58128
PerasWeightSnapshot . Map.insertWith (<>) pt weight . getPerasWeightSnapshot
59129

130+
-- | Prune the given 'PerasWeightSnapshot' by removing the weight of all blocks
131+
-- strictly older than the given slot.
132+
--
133+
-- This function is used to get garbage-collect boosted blocks blocks which are
134+
-- older than our immutable tip as we will never adopt a chain containing them.
135+
--
136+
-- >>> :{
137+
-- weights :: [(Point Blk, PerasWeight)]
138+
-- weights =
139+
-- [ (BlockPoint 2 "foo", PerasWeight 2)
140+
-- , (GenesisPoint, PerasWeight 3)
141+
-- , (BlockPoint 3 "bar", PerasWeight 2)
142+
-- , (BlockPoint 2 "foo", PerasWeight 2)
143+
-- ]
144+
-- :}
145+
--
146+
-- >>> snap = mkPerasWeightSnapshot weights
147+
--
148+
-- >>> prunePerasWeightSnapshot (SlotNo 2) snap
149+
-- [(At (Block {blockPointSlot = SlotNo 2, blockPointHash = "foo"}),PerasWeight 4),(At (Block {blockPointSlot = SlotNo 3, blockPointHash = "bar"}),PerasWeight 2)]
150+
--
151+
-- >>> prunePerasWeightSnapshot (SlotNo 3) snap
152+
-- [(At (Block {blockPointSlot = SlotNo 3, blockPointHash = "bar"}),PerasWeight 2)]
60153
prunePerasWeightSnapshot ::
61154
SlotNo ->
62155
PerasWeightSnapshot blk ->
@@ -67,16 +160,73 @@ prunePerasWeightSnapshot slot =
67160
isTooOld :: Point blk -> Bool
68161
isTooOld pt = pointSlot pt < NotOrigin slot
69162

163+
-- | Get the weight boost for a point, or @'mempty' :: 'PerasWeight'@ otherwise.
164+
--
165+
-- >>> :{
166+
-- weights :: [(Point Blk, PerasWeight)]
167+
-- weights =
168+
-- [ (BlockPoint 2 "foo", PerasWeight 2)
169+
-- , (GenesisPoint, PerasWeight 3)
170+
-- , (BlockPoint 3 "bar", PerasWeight 2)
171+
-- , (BlockPoint 2 "foo", PerasWeight 2)
172+
-- ]
173+
-- :}
174+
--
175+
-- >>> snap = mkPerasWeightSnapshot weights
176+
--
177+
-- >>> weightBoostOfPoint snap (BlockPoint 2 "foo")
178+
-- PerasWeight 4
179+
--
180+
-- >>> weightBoostOfPoint snap (BlockPoint 2 "baz")
181+
-- PerasWeight 0
70182
weightBoostOfPoint ::
71183
forall blk.
72184
StandardHash blk =>
73185
PerasWeightSnapshot blk -> Point blk -> PerasWeight
74186
weightBoostOfPoint (PerasWeightSnapshot weightByPoint) pt =
75187
Map.findWithDefault mempty pt weightByPoint
76188

189+
-- | Get the weight boost for a fragment, ie the sum of all
190+
-- 'weightBoostOfPoint' for all points on the fragment (excluding the anchor).
191+
--
192+
-- Note that this quantity is relative to the anchor of the fragment, so it
193+
-- should only be compared against other fragments with the same anchor.
194+
--
195+
-- >>> :{
196+
-- weights :: [(Point Blk, PerasWeight)]
197+
-- weights =
198+
-- [ (BlockPoint 2 "foo", PerasWeight 2)
199+
-- , (GenesisPoint, PerasWeight 3)
200+
-- , (BlockPoint 3 "bar", PerasWeight 2)
201+
-- , (BlockPoint 2 "foo", PerasWeight 2)
202+
-- ]
203+
-- :}
204+
--
205+
-- >>> :{
206+
-- snap = mkPerasWeightSnapshot weights
207+
-- foo = HeaderFields (SlotNo 2) (BlockNo 1) "foo"
208+
-- bar = HeaderFields (SlotNo 3) (BlockNo 2) "bar"
209+
-- frag0 :: AnchoredFragment (HeaderFields Blk)
210+
-- frag0 = Empty AnchorGenesis :> foo :> bar
211+
-- :}
212+
--
213+
-- >>> weightBoostOfFragment snap frag0
214+
-- PerasWeight 6
215+
--
216+
-- Only keeping the last block from @frag0@:
217+
--
218+
-- >>> frag1 = AF.anchorNewest 1 frag0
219+
-- >>> weightBoostOfFragment snap frag1
220+
-- PerasWeight 2
221+
--
222+
-- Dropping the head from @frag0@, and instead adding an unboosted point:
223+
--
224+
-- >>> frag2 = AF.dropNewest 1 frag0 :> HeaderFields (SlotNo 4) (BlockNo 2) "baz"
225+
-- >>> weightBoostOfFragment snap frag2
226+
-- PerasWeight 4
77227
weightBoostOfFragment ::
78228
forall blk h.
79-
(HasHeader blk, HasHeader h, HeaderHash blk ~ HeaderHash h) =>
229+
(StandardHash blk, HasHeader h, HeaderHash blk ~ HeaderHash h) =>
80230
PerasWeightSnapshot blk ->
81231
AnchoredFragment h ->
82232
PerasWeight
@@ -85,3 +235,12 @@ weightBoostOfFragment weightSnap frag =
85235
foldMap
86236
(weightBoostOfPoint weightSnap . castPoint . blockPoint)
87237
(AF.toOldestFirst frag)
238+
239+
-- $setup
240+
-- >>> import Ouroboros.Consensus.Block
241+
-- >>> import Ouroboros.Network.AnchoredFragment (AnchoredFragment, AnchoredSeq(..), Anchor(..))
242+
-- >>> import qualified Ouroboros.Network.AnchoredFragment as AF
243+
-- >>> :set -XTypeFamilies
244+
-- >>> data Blk = Blk
245+
-- >>> type instance HeaderHash Blk = String
246+
-- >>> instance StandardHash Blk

0 commit comments

Comments
 (0)