Skip to content

Commit 6dd15ad

Browse files
authored
Redefine Header with MemoBytes (#1687)
Since we removed the `era` type parameter in `MemoBytes` (in `cardano-ledger-core`), we can use `MemoBytes` to define more types that need to be memoized - `Header` among them. This simplifies the definition of `Header` and also brings some instances for free. Closes IntersectMBO/cardano-ledger#4850
2 parents ef682d1 + d5619df commit 6dd15ad

File tree

2 files changed

+30
-49
lines changed

2 files changed

+30
-49
lines changed
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
### Non-Breaking
2+
3+
- Added `SafeToHash` instance for `BHeader`

ouroboros-consensus-protocol/src/ouroboros-consensus-protocol/Ouroboros/Consensus/Protocol/Praos/Header.hs

Lines changed: 27 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,12 @@
22
{-# LANGUAGE DeriveGeneric #-}
33
{-# LANGUAGE DerivingVia #-}
44
{-# LANGUAGE FlexibleInstances #-}
5+
{-# LANGUAGE GeneralizedNewtypeDeriving #-}
56
{-# LANGUAGE NamedFieldPuns #-}
67
{-# LANGUAGE PatternSynonyms #-}
78
{-# LANGUAGE StandaloneDeriving #-}
9+
{-# LANGUAGE TypeFamilies #-}
10+
{-# LANGUAGE ViewPatterns #-}
811

912
-- | Block header associated with Praos.
1013
--
@@ -39,10 +42,8 @@ import Cardano.Ledger.Binary
3942
, DecCBOR (decCBOR)
4043
, EncCBOR (..)
4144
, ToCBOR (..)
42-
, encodedSigKESSizeExpr
4345
, serialize'
4446
, unCBORGroup
45-
, withSlice
4647
)
4748
import Cardano.Ledger.Binary.Coders
4849
import Cardano.Ledger.Binary.Crypto
@@ -56,18 +57,25 @@ import Cardano.Ledger.Hashes
5657
( EraIndependentBlockBody
5758
, EraIndependentBlockHeader
5859
, HASH
60+
, SafeToHash
61+
, originalBytesSize
5962
)
6063
import Cardano.Ledger.Keys (KeyRole (BlockIssuer), VKey)
64+
import Cardano.Ledger.MemoBytes
65+
( Mem
66+
, MemoBytes
67+
, Memoized (..)
68+
, getMemoRawType
69+
, mkMemoized
70+
)
6171
import Cardano.Protocol.Crypto (Crypto, KES, VRF)
6272
import Cardano.Protocol.TPraos.BHeader (PrevHash)
6373
import Cardano.Protocol.TPraos.OCert (OCert)
6474
import Cardano.Slotting.Block (BlockNo)
6575
import Cardano.Slotting.Slot (SlotNo)
66-
import qualified Data.ByteString as BS
67-
import qualified Data.ByteString.Lazy as BSL
6876
import Data.Word (Word32)
6977
import GHC.Generics (Generic)
70-
import NoThunks.Class (AllowThunksIn (..), NoThunks (..))
78+
import NoThunks.Class (NoThunks (..))
7179
import Ouroboros.Consensus.Protocol.Praos.VRF (InputVRF)
7280

7381
-- | The body of the header is the part which gets hashed to form the hash
@@ -121,54 +129,31 @@ instance Crypto c => Eq (HeaderRaw c) where
121129
headerRawSig h1 == headerRawSig h2
122130
&& headerRawBody h1 == headerRawBody h2
123131

124-
-- | Checks the binary representation first.
125-
instance Crypto c => Eq (Header c) where
126-
h1 == h2 =
127-
headerBytes h1 == headerBytes h2
128-
&& headerRaw h1 == headerRaw h2
129-
130132
instance
131133
Crypto crypto =>
132134
NoThunks (HeaderRaw crypto)
133135

134136
-- | Full header type, carrying its own memoised bytes.
135-
data Header crypto = HeaderConstr
136-
{ headerRaw :: !(HeaderRaw crypto)
137-
, headerBytes :: BS.ByteString -- lazy on purpose, constructed on demand
138-
}
139-
deriving (Show, Generic)
140-
deriving NoThunks via AllowThunksIn '["headerBytes"] (Header crypto)
137+
newtype Header crypto = HeaderConstr (MemoBytes (HeaderRaw crypto))
138+
deriving Generic
139+
deriving newtype (Eq, Show, NoThunks, Plain.ToCBOR, SafeToHash)
140+
141+
instance Memoized (Header crypto) where
142+
type RawType (Header crypto) = HeaderRaw crypto
141143

142144
pattern Header ::
143145
Crypto crypto =>
144146
HeaderBody crypto ->
145147
KES.SignedKES (KES crypto) (HeaderBody crypto) ->
146148
Header crypto
147-
pattern Header{headerBody, headerSig} <-
148-
HeaderConstr
149-
{ headerRaw =
150-
HeaderRaw
151-
{ headerRawBody = headerBody
152-
, headerRawSig = headerSig
153-
}
154-
}
149+
pattern Header{headerBody, headerSig} <- (getMemoRawType -> HeaderRaw headerBody headerSig)
155150
where
156-
Header body sig =
157-
let header =
158-
HeaderRaw
159-
{ headerRawBody = body
160-
, headerRawSig = sig
161-
}
162-
in HeaderConstr
163-
{ headerRaw = header
164-
, headerBytes = serialize' (pvMajor (hbProtVer body)) header
165-
}
166-
151+
Header body sig = mkMemoized (pvMajor (hbProtVer body)) $ HeaderRaw body sig
167152
{-# COMPLETE Header #-}
168153

169154
-- | Compute the size of the header
170155
headerSize :: Header crypto -> Int
171-
headerSize (HeaderConstr _ bytes) = BS.length bytes
156+
headerSize = originalBytesSize
172157

173158
-- | Hash a header
174159
headerHash ::
@@ -239,16 +224,9 @@ instance Crypto crypto => DecCBOR (HeaderRaw crypto) where
239224
instance Crypto crypto => DecCBOR (Annotator (HeaderRaw crypto)) where
240225
decCBOR = pure <$> decCBOR
241226

242-
instance Crypto c => Plain.ToCBOR (Header c) where
243-
toCBOR (HeaderConstr _ bytes) = Plain.encodePreEncoded bytes
244-
245-
instance Crypto c => EncCBOR (Header c) where
246-
encodedSizeExpr size proxy =
247-
1
248-
+ encodedSizeExpr size (headerRawBody . headerRaw <$> proxy)
249-
+ encodedSigKESSizeExpr (KES.getSig . headerRawSig . headerRaw <$> proxy)
227+
instance Crypto c => EncCBOR (Header c)
250228

251-
instance Crypto c => DecCBOR (Annotator (Header c)) where
252-
decCBOR = do
253-
(Annotator getT, Annotator getBytes) <- withSlice decCBOR
254-
pure (Annotator (\fullbytes -> HeaderConstr (getT fullbytes) (BSL.toStrict (getBytes fullbytes))))
229+
deriving via
230+
Mem (HeaderRaw crypto)
231+
instance
232+
Crypto crypto => DecCBOR (Annotator (Header crypto))

0 commit comments

Comments
 (0)