Skip to content

Commit

Permalink
Simplify the en/decoder for PBFtChainState
Browse files Browse the repository at this point in the history
Fixes #1609.

Since we're breaking backwards compatibility of the `ExtLedgerState`
serialisation format, we can get rid of the code dealing with
backwards compatibility in `PBFtChainState`.

Nevertheless, start using `Versioned` for `PBFtChainState` so that it will be
easier in the future to handle changes to the format.
  • Loading branch information
mrBliss committed Feb 11, 2020
1 parent cf018e1 commit 1b06eb1
Show file tree
Hide file tree
Showing 5 changed files with 29 additions and 80 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
{-# LANGUAGE GeneralizedNewtypeDeriving #-}
{-# LANGUAGE LambdaCase #-}
{-# LANGUAGE MultiWayIf #-}
{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE RecordWildCards #-}
{-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE StandaloneDeriving #-}
Expand Down Expand Up @@ -40,7 +41,6 @@ module Ouroboros.Consensus.Protocol.PBFT.ChainState (

import Codec.Serialise (Serialise (..))
import Codec.Serialise.Decoding (Decoder)
import qualified Codec.Serialise.Decoding as Serialise
import Codec.Serialise.Encoding (Encoding)
import qualified Codec.Serialise.Encoding as Serialise
import qualified Control.Exception as Exn
Expand All @@ -54,6 +54,7 @@ import Data.Word
import GHC.Generics (Generic)
import GHC.Stack

import Cardano.Binary (enforceSize)
import Cardano.Prelude (NoUnexpectedThunks)

import Ouroboros.Network.Block (SlotNo (..))
Expand All @@ -64,6 +65,7 @@ import Ouroboros.Consensus.Protocol.Abstract
import Ouroboros.Consensus.Protocol.PBFT.ChainState.HeaderHashBytes
import Ouroboros.Consensus.Protocol.PBFT.Crypto
import Ouroboros.Consensus.Util (repeatedly)
import Ouroboros.Consensus.Util.Versioned

{-------------------------------------------------------------------------------
Types
Expand Down Expand Up @@ -565,58 +567,35 @@ fromList k n (anchor, signers, ebbs) =
Serialization
-------------------------------------------------------------------------------}

serializationFormatVersion1 :: Word8
serializationFormatVersion1 = 1

serializationFormatVersion2 :: Word8
serializationFormatVersion2 = 2
-- CHANGELOG
--
-- Version 0 is 2 fields, the anchor and the window. Note that it does not
-- have the version marker.
--
-- Version 1 has 4 fields, the version marker, anchor, window, and @~(Map
-- SlotNo (WithOrigin SlotNo))@.
--
-- Version 2 has 4 fields, the version marker, anchor, window, and @~(Maybe EbbInfo)@.

encodePBftChainState :: (PBftCrypto c, Serialise (PBftVerKeyHash c))
=> PBftChainState c -> Encoding
encodePBftChainState st@PBftChainState{..} = mconcat [
Serialise.encodeListLen 4
, encode serializationFormatVersion2
, encode (withOriginToMaybe anchor)
, encode signers
, encode ebbs'
]
serializationFormatVersion0 :: VersionNumber
serializationFormatVersion0 = 0

encodePBftChainState
:: (PBftCrypto c, Serialise (PBftVerKeyHash c))
=> PBftChainState c -> Encoding
encodePBftChainState st@PBftChainState{..} =
encodeVersion serializationFormatVersion0 $ mconcat [
Serialise.encodeListLen 3
, encode (withOriginToMaybe anchor)
, encode signers
, encode ebbs'
]
where
(anchor, signers, ebbs') = toList st

decodePBftChainState :: (PBftCrypto c, Serialise (PBftVerKeyHash c), HasCallStack)
=> SecurityParam
-> WindowSize
-> Decoder s (PBftChainState c)
decodePBftChainState k n = Serialise.decodeListLen >>= \case
2 -> do -- Version is 0
decodePBftChainState k n = decodeVersion
[(serializationFormatVersion0, Decode decodePBftChainState0)]
where
decodePBftChainState0 = do
enforceSize "PBftChainState" 3
anchor <- withOriginFromMaybe <$> decode
signers <- decode
return $ fromList k n (anchor, signers, ebbsEmpty)
4 -> decode >>= \v -> if
| v == serializationFormatVersion1 -> do
anchor <- withOriginFromMaybe <$> decode
signers <- decode
ebbs' <- decode
let _ = ebbs' :: Map SlotNo (WithOrigin SlotNo)
-- NB we discard ebbs'
return $ fromList k n (anchor, signers, ebbsEmpty)
| v == serializationFormatVersion2 -> do
anchor <- withOriginFromMaybe <$> decode
signers <- decode
ebbs' <- decode
return $ fromList k n (anchor, signers, ebbs')
| otherwise ->
error $ "unexpected serialisation format version: " <> show v
o -> error $ "unexpected list length: " <> show o
ebbs' <- decode
return $ fromList k n (anchor, signers, ebbs')

instance Serialise (PBftVerKeyHash c) => Serialise (PBftSigner c) where
encode = encode . toPair
Expand Down
37 changes: 6 additions & 31 deletions ouroboros-consensus/test-consensus/Test/Consensus/Ledger/Byron.hs
Original file line number Diff line number Diff line change
Expand Up @@ -98,9 +98,6 @@ tests = testGroup "Byron"
-- Note that for most Byron types, we simply wrap the en/decoders from
-- cardano-ledger, which already has golden tests for them.
[ test_golden_ChainState
, test_golden_ChainState_backwardsCompat_version0
, test_golden_ChainState_backwardsCompat_version1
, test_golden_ChainState_backwardsCompat_version2
, test_golden_LedgerState
, test_golden_GenTxId
, test_golden_UPIState
Expand Down Expand Up @@ -257,9 +254,8 @@ secParam = SecurityParam 2
windowSize :: CS.WindowSize
windowSize = CS.WindowSize 2

exampleChainStateWithoutEBB, exampleChainStateWithEBB :: ChainState (BlockProtocol ByronBlock)
(exampleChainStateWithoutEBB, exampleChainStateWithEBB) =
(withoutEBB, withEBB)
exampleChainState :: ChainState (BlockProtocol ByronBlock)
exampleChainState = withEBB
where
signers = map (`CS.PBftSigner` CC.exampleKeyHash) [1..4]

Expand All @@ -283,29 +279,8 @@ test_golden_ChainState :: TestTree
test_golden_ChainState = goldenTestCBOR
"ChainState"
encodeByronChainState
exampleChainStateWithEBB
"test-consensus/golden/cbor/byron/ChainState2"

test_golden_ChainState_backwardsCompat_version0 :: TestTree
test_golden_ChainState_backwardsCompat_version0 =
testCase "ChainState version 0" $ goldenTestCBORBackwardsCompat
(decodeByronChainState secParam)
exampleChainStateWithoutEBB
"test-consensus/golden/cbor/byron/ChainState0"

test_golden_ChainState_backwardsCompat_version1 :: TestTree
test_golden_ChainState_backwardsCompat_version1 =
testCase "ChainState version 1" $ goldenTestCBORBackwardsCompat
(decodeByronChainState secParam)
exampleChainStateWithoutEBB
"test-consensus/golden/cbor/byron/ChainState1"

test_golden_ChainState_backwardsCompat_version2 :: TestTree
test_golden_ChainState_backwardsCompat_version2 =
testCase "ChainState version 2" $ goldenTestCBORBackwardsCompat
(decodeByronChainState secParam)
exampleChainStateWithEBB
"test-consensus/golden/cbor/byron/ChainState2"
exampleChainState
"test-consensus/golden/cbor/byron/ChainState0"

test_golden_LedgerState :: TestTree
test_golden_LedgerState = goldenTestCBOR
Expand Down Expand Up @@ -350,13 +325,13 @@ goldenTestCBOR name enc a path =

-- | Check whether we can successfully decode the contents of the given file.
-- This file will typically contain an older serialisation format.
goldenTestCBORBackwardsCompat
_goldenTestCBORBackwardsCompat
:: (Eq a, Show a)
=> (forall s. Decoder s a)
-> a
-> FilePath
-> Assertion
goldenTestCBORBackwardsCompat dec a path = do
_goldenTestCBORBackwardsCompat dec a path = do
bytes <- Lazy.readFile path
case deserialiseFromBytes dec bytes of
Left failure
Expand Down
Binary file modified ouroboros-consensus/test-consensus/golden/cbor/byron/ChainState0
Binary file not shown.

This file was deleted.

Binary file not shown.

0 comments on commit 1b06eb1

Please sign in to comment.