Skip to content

Commit 35de907

Browse files
committed
Basic Peras types: PerasCert, PerasWeightSnapshot
1 parent c094b2a commit 35de907

File tree

6 files changed

+498
-0
lines changed

6 files changed

+498
-0
lines changed

docs/website/contents/references/glossary.md

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -472,6 +472,19 @@ These kinds are maintained by the Networking layer:
472472
- [Public root peers](#public-root-peers).
473473
- [Shared peers](#shared-peers).
474474

475+
## ;Peras ;weight ;boost
476+
477+
Peras is an extension of Praos enabling faster settlement under optimistic conditions.
478+
To this end, Peras can result in a block `B` receiving a *boost*, which means that any chain containing `B` gets additional weight when being compared to other chains.
479+
480+
Consider a chain fragment `F`:
481+
482+
- Its ;*weight boost* is the sum of all boosts received by points on this fragment (excluding the anchor). Note that the same point can be boosted multiple times.
483+
484+
- Its ;*total weight* is its tip block number plus its weight boost.
485+
486+
Note that these notions are always relative to a particular anchor, so different chain fragments must have the same anchor when their total weight is to be compared.
487+
475488
## ;Phases
476489

477490
Byron, Shelley, Goguen (current one as of August 2023), Basho, Voltaire.

ouroboros-consensus/ouroboros-consensus.cabal

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,7 @@ library
8383
Ouroboros.Consensus.Block.RealPoint
8484
Ouroboros.Consensus.Block.SupportsDiffusionPipelining
8585
Ouroboros.Consensus.Block.SupportsMetrics
86+
Ouroboros.Consensus.Block.SupportsPeras
8687
Ouroboros.Consensus.Block.SupportsProtocol
8788
Ouroboros.Consensus.Block.SupportsSanityCheck
8889
Ouroboros.Consensus.BlockchainTime
@@ -197,6 +198,7 @@ library
197198
Ouroboros.Consensus.Node.Run
198199
Ouroboros.Consensus.Node.Serialisation
199200
Ouroboros.Consensus.NodeId
201+
Ouroboros.Consensus.Peras.Weight
200202
Ouroboros.Consensus.Protocol.Abstract
201203
Ouroboros.Consensus.Protocol.BFT
202204
Ouroboros.Consensus.Protocol.LeaderSchedule

ouroboros-consensus/src/ouroboros-consensus/Ouroboros/Consensus/Block.hs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,5 +8,6 @@ import Ouroboros.Consensus.Block.NestedContent as X
88
import Ouroboros.Consensus.Block.RealPoint as X
99
import Ouroboros.Consensus.Block.SupportsDiffusionPipelining as X
1010
import Ouroboros.Consensus.Block.SupportsMetrics as X
11+
import Ouroboros.Consensus.Block.SupportsPeras as X
1112
import Ouroboros.Consensus.Block.SupportsProtocol as X
1213
import Ouroboros.Consensus.Block.SupportsSanityCheck as X
Lines changed: 176 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,176 @@
1+
{-# LANGUAGE DeriveAnyClass #-}
2+
{-# LANGUAGE DeriveGeneric #-}
3+
{-# LANGUAGE DerivingVia #-}
4+
{-# LANGUAGE FlexibleContexts #-}
5+
{-# LANGUAGE FlexibleInstances #-}
6+
{-# LANGUAGE GeneralizedNewtypeDeriving #-}
7+
{-# LANGUAGE MultiParamTypeClasses #-}
8+
{-# LANGUAGE NamedFieldPuns #-}
9+
{-# LANGUAGE ScopedTypeVariables #-}
10+
{-# LANGUAGE TypeApplications #-}
11+
{-# LANGUAGE TypeFamilies #-}
12+
{-# LANGUAGE UndecidableInstances #-}
13+
14+
module Ouroboros.Consensus.Block.SupportsPeras
15+
( PerasRoundNo (..)
16+
, PerasWeight (..)
17+
, boostPerCert
18+
, BlockSupportsPeras (..)
19+
, PerasCert (..)
20+
, ValidatedPerasCert (..)
21+
, makePerasCfg
22+
, HasPerasCert (..)
23+
, getPerasCertRound
24+
, getPerasCertBoostedBlock
25+
, getPerasCertBoost
26+
27+
-- * Ouroboros Peras round length
28+
, PerasRoundLength (..)
29+
, defaultPerasRoundLength
30+
) where
31+
32+
import Codec.Serialise (Serialise (..))
33+
import Codec.Serialise.Decoding (decodeListLenOf)
34+
import Codec.Serialise.Encoding (encodeListLen)
35+
import Data.Monoid (Sum (..))
36+
import Data.Proxy (Proxy (..))
37+
import Data.Word (Word64)
38+
import GHC.Generics (Generic)
39+
import NoThunks.Class
40+
import Ouroboros.Consensus.Block.Abstract
41+
import Ouroboros.Consensus.Util
42+
import Ouroboros.Consensus.Util.Condense
43+
import Quiet (Quiet (..))
44+
45+
newtype PerasRoundNo = PerasRoundNo {unPerasRoundNo :: Word64}
46+
deriving Show via Quiet PerasRoundNo
47+
deriving stock Generic
48+
deriving newtype (Enum, Eq, Ord, NoThunks, Serialise)
49+
50+
instance Condense PerasRoundNo where
51+
condense = show . unPerasRoundNo
52+
53+
instance ShowProxy PerasRoundNo where
54+
showProxy _ = "PerasRoundNo"
55+
56+
newtype PerasWeight = PerasWeight {unPerasWeight :: Word64}
57+
deriving Show via Quiet PerasWeight
58+
deriving stock Generic
59+
deriving newtype (Eq, Ord, NoThunks)
60+
deriving (Semigroup, Monoid) via Sum Word64
61+
62+
instance Condense PerasWeight where
63+
condense = show . unPerasWeight
64+
65+
-- | TODO this will become a Ledger protocol parameter
66+
boostPerCert :: PerasWeight
67+
boostPerCert = PerasWeight 15
68+
69+
-- TODO using 'Validated' for extra safety? Or some @.Unsafe@ module?
70+
data ValidatedPerasCert blk = ValidatedPerasCert
71+
{ vpcCert :: !(PerasCert blk)
72+
, vpcCertBoost :: !PerasWeight
73+
}
74+
deriving stock (Show, Eq, Ord, Generic)
75+
deriving anyclass NoThunks
76+
77+
{-------------------------------------------------------------------------------
78+
Ouroboros Peras round length
79+
-------------------------------------------------------------------------------}
80+
81+
newtype PerasRoundLength = PerasRoundLength {unPerasRoundLength :: Word64}
82+
deriving stock (Show, Eq, Ord)
83+
deriving newtype (NoThunks, Num)
84+
85+
-- | See the Protocol parameters section of the Peras design report:
86+
-- https://tweag.github.io/cardano-peras/peras-design.pdf#section.2.1
87+
-- TODO this will become a Ledger protocol parameter
88+
defaultPerasRoundLength :: PerasRoundLength
89+
defaultPerasRoundLength = 90
90+
91+
class
92+
( Show (PerasCfg blk)
93+
, NoThunks (PerasCert blk)
94+
) =>
95+
BlockSupportsPeras blk
96+
where
97+
data PerasCfg blk
98+
99+
data PerasCert blk
100+
101+
data PerasValidationErr blk
102+
103+
validatePerasCert ::
104+
PerasCfg blk ->
105+
PerasCert blk ->
106+
Either (PerasValidationErr blk) (ValidatedPerasCert blk)
107+
108+
-- TODO degenerate instance for all blks to get things to compile
109+
instance StandardHash blk => BlockSupportsPeras blk where
110+
newtype PerasCfg blk = PerasCfg
111+
{ -- TODO eventually, this will come from the
112+
-- protocol parameters from the ledger state
113+
perasCfgWeightBoost :: PerasWeight
114+
}
115+
deriving stock (Show, Eq)
116+
117+
data PerasCert blk = PerasCert
118+
{ pcCertRound :: PerasRoundNo
119+
, pcCertBoostedBlock :: Point blk
120+
}
121+
deriving stock (Generic, Eq, Ord, Show)
122+
deriving anyclass NoThunks
123+
124+
-- TODO enrich with actual error types
125+
data PerasValidationErr blk
126+
= PerasValidationErr
127+
deriving stock (Show, Eq)
128+
129+
-- TODO perform actual validation against all
130+
-- possible 'PerasValidationErr' variants
131+
validatePerasCert cfg cert =
132+
Right
133+
ValidatedPerasCert
134+
{ vpcCert = cert
135+
, vpcCertBoost = perasCfgWeightBoost cfg
136+
}
137+
138+
instance ShowProxy blk => ShowProxy (PerasCert blk) where
139+
showProxy _ = "PerasCert " <> showProxy (Proxy @blk)
140+
141+
instance Serialise (HeaderHash blk) => Serialise (PerasCert blk) where
142+
encode PerasCert{pcCertRound, pcCertBoostedBlock} =
143+
encodeListLen 2
144+
<> encode pcCertRound
145+
<> encode pcCertBoostedBlock
146+
decode = do
147+
decodeListLenOf 2
148+
pcCertRound <- decode
149+
pcCertBoostedBlock <- decode
150+
pure $ PerasCert{pcCertRound, pcCertBoostedBlock}
151+
152+
-- | Derive a 'PerasCfg' from a 'BlockConfig'
153+
-- TODO this currently doesn't depend on 'BlockConfig' at all, but likely will
154+
makePerasCfg :: Maybe (BlockConfig blk) -> PerasCfg blk
155+
makePerasCfg _ =
156+
PerasCfg
157+
{ perasCfgWeightBoost = boostPerCert
158+
}
159+
160+
class StandardHash blk => HasPerasCert cert blk where
161+
getPerasCert :: cert blk -> PerasCert blk
162+
163+
instance StandardHash blk => HasPerasCert PerasCert blk where
164+
getPerasCert = id
165+
166+
instance StandardHash blk => HasPerasCert ValidatedPerasCert blk where
167+
getPerasCert = vpcCert
168+
169+
getPerasCertRound :: HasPerasCert cert blk => cert blk -> PerasRoundNo
170+
getPerasCertRound = pcCertRound . getPerasCert
171+
172+
getPerasCertBoostedBlock :: HasPerasCert cert blk => cert blk -> Point blk
173+
getPerasCertBoostedBlock = pcCertBoostedBlock . getPerasCert
174+
175+
getPerasCertBoost :: ValidatedPerasCert blk -> PerasWeight
176+
getPerasCertBoost = vpcCertBoost

0 commit comments

Comments
 (0)