66{-# LANGUAGE GADTs #-}
77{-# LANGUAGE GeneralizedNewtypeDeriving #-}
88{-# LANGUAGE MultiParamTypeClasses #-}
9+ {-# LANGUAGE OverloadedStrings #-}
910{-# LANGUAGE ScopedTypeVariables #-}
1011{-# LANGUAGE StandaloneDeriving #-}
1112{-# LANGUAGE TypeApplications #-}
@@ -29,6 +30,7 @@ module Ouroboros.Consensus.Shelley.Ledger.Block
2930 , fromShelleyBlock
3031 , toShelleyBlock
3132 , mkShelleyBlock
33+ , mkShelleyBlockWithPerasCert
3234 , mkShelleyHeader
3335
3436 -- * Serialisation
@@ -48,7 +50,12 @@ import Cardano.Ledger.Binary
4850 ( Annotator (.. )
4951 , DecCBOR (.. )
5052 , EncCBOR (.. )
53+ , EncCBORGroup (.. )
5154 , FullByteString (.. )
55+ , cborError
56+ , decodeListLen
57+ , encodeListLen
58+ , fromPlainDecoder
5259 , serialize
5360 )
5461import qualified Cardano.Ledger.Binary.Plain as Plain
@@ -63,9 +70,11 @@ import Cardano.Ledger.Hashes (HASH)
6370import qualified Cardano.Ledger.Shelley.API as SL
6471import Cardano.Protocol.Crypto (Crypto )
6572import qualified Cardano.Protocol.TPraos.BHeader as SL
73+ import Codec.Serialise (Serialise (.. ))
6674import Control.Arrow (Arrow (.. ))
6775import qualified Data.ByteString.Lazy as Lazy
6876import Data.Coerce (coerce )
77+ import Data.Maybe.Strict (StrictMaybe (.. ))
6978import Data.Typeable (Typeable )
7079import GHC.Generics (Generic )
7180import NoThunks.Class (NoThunks (.. ))
@@ -151,6 +160,7 @@ instance ShelleyCompatible proto era => ConvertRawHash (ShelleyBlock proto era)
151160data ShelleyBlock proto era = ShelleyBlock
152161 { shelleyBlockHeader :: ! (ShelleyProtocolHeader proto )
153162 , shelleyBlockBody :: ! (SL. BlockBody era )
163+ , shelleyBlockPerasCert :: ! (StrictMaybe (PerasCert (ShelleyBlock proto era )))
154164 , shelleyBlockHeaderHash :: ! ShelleyHash
155165 }
156166
@@ -181,10 +191,27 @@ mkShelleyBlock ::
181191 ShelleyProtocolHeader proto ->
182192 SL. BlockBody era ->
183193 ShelleyBlock proto era
184- mkShelleyBlock header body =
194+ mkShelleyBlock = mkShelleyBlockGeneric SNothing
195+
196+ mkShelleyBlockWithPerasCert ::
197+ ShelleyCompatible proto era =>
198+ PerasCert (ShelleyBlock proto era ) ->
199+ ShelleyProtocolHeader proto ->
200+ SL. BlockBody era ->
201+ ShelleyBlock proto era
202+ mkShelleyBlockWithPerasCert = mkShelleyBlockGeneric . SJust
203+
204+ mkShelleyBlockGeneric ::
205+ ShelleyCompatible proto era =>
206+ StrictMaybe (PerasCert (ShelleyBlock proto era )) ->
207+ ShelleyProtocolHeader proto ->
208+ BlockBody era ->
209+ ShelleyBlock proto era
210+ mkShelleyBlockGeneric cert header body =
185211 ShelleyBlock
186212 { shelleyBlockHeader = header
187213 , shelleyBlockBody = body
214+ , shelleyBlockPerasCert = cert
188215 , shelleyBlockHeaderHash = pHeaderHash header
189216 }
190217
@@ -308,10 +335,35 @@ instance HasNestedContent f (ShelleyBlock proto era)
308335
309336instance ShelleyCompatible proto era => EncCBOR (ShelleyBlock proto era ) where
310337 -- Don't encode the header hash, we recompute it during deserialisation
311- encCBOR = encCBOR . fromShelleyBlock
338+ encCBOR block = do
339+ let header = shelleyBlockHeader block
340+ let body = shelleyBlockBody block
341+ let bodyLen = listLen body
342+ case shelleyBlockPerasCert block of
343+ SNothing ->
344+ encodeListLen (1 + bodyLen)
345+ <> encCBOR header
346+ <> encCBORGroup body
347+ SJust cert ->
348+ encodeListLen (1 + bodyLen + 1 )
349+ <> encCBOR header
350+ <> encCBORGroup body
351+ <> encCBOR (encode cert)
312352
313353instance ShelleyCompatible proto era => DecCBOR (Annotator (ShelleyBlock proto era )) where
314- decCBOR = fmap toShelleyBlock <$> decCBOR
354+ decCBOR = do
355+ len <- decodeListLen
356+ header <- decCBOR
357+ body <- decCBOR
358+ cert <- decMaybeCertOrFail len
359+ pure $ mkShelleyBlockGeneric <$> cert <*> header <*> body
360+ where
361+ bodyLen = fromIntegral (numSegComponents @ era )
362+
363+ decMaybeCertOrFail len
364+ | len == 1 + bodyLen = pure <$> pure SNothing
365+ | len == 1 + bodyLen + 1 = pure <$> (SJust <$> fromPlainDecoder decode)
366+ | otherwise = cborError $ Plain. DecoderErrorCustom " ShelleyBlock" " invalid number of elements"
315367
316368instance ShelleyCompatible proto era => EncCBOR (Header (ShelleyBlock proto era )) where
317369 -- Don't encode the header hash, we recompute it during deserialisation
@@ -362,7 +414,7 @@ decodeShelleyHeader = eraDecoder @era $ (. Full) . runAnnotator <$> decCBOR
362414-------------------------------------------------------------------------------}
363415
364416instance ShelleyCompatible proto era => Condense (ShelleyBlock proto era ) where
365- condense = show . (shelleyBlockHeader &&& shelleyBlockBody)
417+ condense = show . (( shelleyBlockHeader &&& shelleyBlockBody) &&& shelleyBlockPerasCert )
366418
367419instance ShelleyCompatible proto era => Condense (Header (ShelleyBlock proto era )) where
368420 condense = show . shelleyHeaderRaw
0 commit comments