{-# LANGUAGE GADTs #-}
{-# LANGUAGE NamedFieldPuns #-}
{-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE TypeApplications #-}
module Test.Consensus.Shelley.Serialisation (tests) where
import qualified Cardano.Ledger.MemoBytes.Internal as SL
import qualified Cardano.Ledger.Shelley.Tx as SL
import qualified Cardano.Ledger.Shelley.TxWits as SL
import qualified Codec.CBOR.Write as CBOR
import qualified Data.ByteString.Lazy as Lazy
import Data.Constraint
import Data.Proxy (Proxy (..))
import Data.Word (Word64)
import Ouroboros.Consensus.Protocol.TPraos (TPraos)
import Ouroboros.Consensus.Shelley.HFEras ()
import Ouroboros.Consensus.Shelley.Ledger
import Ouroboros.Consensus.Shelley.Ledger.SupportsProtocol ()
import Ouroboros.Consensus.Shelley.Node ()
import Ouroboros.Consensus.Shelley.Node.Serialisation ()
import Ouroboros.Consensus.Shelley.Protocol.TPraos ()
import Ouroboros.Consensus.Storage.Common (BinaryBlockInfo (..))
import Test.Consensus.Cardano.Generators ()
import Test.Consensus.Shelley.Generators ()
import Test.Consensus.Shelley.MockCrypto
import Test.Tasty
import Test.Tasty.QuickCheck
import Test.Util.Corruption
import Test.Util.Orphans.Arbitrary ()
import Test.Util.Serialisation.Roundtrip
import Test.Util.Serialisation.TxWireSize
getTxBytes :: GenTx Block -> Maybe String
getTxBytes :: GenTx (ShelleyBlock (TPraos MockCrypto) ShelleyEra) -> Maybe String
getTxBytes (ShelleyTx TxId
_txId (SL.MkShelleyTx (SL.ShelleyTx TxBody TopTx ShelleyEra
_ (SL.MkShelleyTxWits MemoBytes (ShelleyTxWitsRaw ShelleyEra)
memoBytes) StrictMaybe (TxAuxData ShelleyEra)
_))) =
String -> Maybe String
forall a. a -> Maybe a
Just (String -> Maybe String) -> String -> Maybe String
forall a b. (a -> b) -> a -> b
$ ShortByteString -> String
forall a. Show a => a -> String
show (MemoBytes (ShelleyTxWitsRaw ShelleyEra) -> ShortByteString
forall t. MemoBytes t -> ShortByteString
SL.mbBytes MemoBytes (ShelleyTxWitsRaw ShelleyEra)
memoBytes)
tests :: TestTree
tests :: TestTree
tests =
String -> [TestTree] -> TestTree
testGroup
String
"Shelley"
[ CodecConfig (ShelleyBlock (TPraos MockCrypto) ShelleyEra)
-> (forall a.
NestedCtxt_ (ShelleyBlock (TPraos MockCrypto) ShelleyEra) Header a
-> Dict (Eq a, Show a))
-> Maybe CDDLsForNodeToNode
-> TestTree
forall blk.
(SerialiseDiskConstraints blk, SerialiseNodeToNodeConstraints blk,
SerialiseNodeToClientConstraints blk,
Show (BlockNodeToNodeVersion blk), StandardHash blk, GetHeader blk,
Arbitrary' blk, Arbitrary' (Header blk),
Arbitrary' (HeaderHash blk), Arbitrary' (LedgerState blk EmptyMK),
Arbitrary' (AnnTip blk),
Arbitrary' (ChainDepState (BlockProtocol blk)),
ArbitraryWithVersion (BlockNodeToNodeVersion blk) (Coherent blk),
ArbitraryWithVersion (BlockNodeToNodeVersion blk) (Header blk),
ArbitraryWithVersion (BlockNodeToNodeVersion blk) (GenTx blk),
ArbitraryWithVersion (BlockNodeToNodeVersion blk) (GenTxId blk),
ArbitraryWithVersion
(BlockNodeToNodeVersion blk) (SomeSecond (NestedCtxt Header) blk),
ArbitraryWithVersion (BlockNodeToClientVersion blk) blk,
ArbitraryWithVersion (BlockNodeToClientVersion blk) (GenTx blk),
ArbitraryWithVersion
(BlockNodeToClientVersion blk) (ApplyTxErr blk),
ArbitraryWithVersion
(BlockNodeToClientVersion blk) (SomeBlockQuery (BlockQuery blk)),
ArbitraryWithVersion
(BlockNodeToClientVersion blk) (SomeResult blk),
Arbitrary
(WithVersion (BlockNodeToClientVersion blk) (LedgerConfig blk)),
ArbitraryWithVersion
(QueryVersion, BlockNodeToClientVersion blk)
(SomeSecond Query blk),
Show (BlockNodeToClientVersion blk),
BlockSupportsLedgerQuery blk) =>
CodecConfig blk
-> (forall a. NestedCtxt_ blk Header a -> Dict (Eq a, Show a))
-> Maybe CDDLsForNodeToNode
-> TestTree
roundtrip_all CodecConfig (ShelleyBlock (TPraos MockCrypto) ShelleyEra)
testCodecCfg NestedCtxt_ (ShelleyBlock (TPraos MockCrypto) ShelleyEra) Header a
-> Dict (Eq a, Show a)
forall a.
NestedCtxt_ (ShelleyBlock (TPraos MockCrypto) ShelleyEra) Header a
-> Dict (Eq a, Show a)
forall a era proto.
ShelleyCompatible proto era =>
NestedCtxt_ (ShelleyBlock proto era) Header a
-> Dict (Eq a, Show a)
dictNestedHdr Maybe CDDLsForNodeToNode
forall a. Maybe a
Nothing
, String -> [TestTree] -> TestTree
testGroup
String
"GenTx.txWireSize"
[ String
-> (WithVersion
ShelleyNodeToNodeVersion
(GenTx (ShelleyBlock (TPraos MockCrypto) ShelleyEra))
-> Property)
-> TestTree
forall a. Testable a => String -> a -> TestTree
testProperty String
"txSubmission" ((WithVersion
ShelleyNodeToNodeVersion
(GenTx (ShelleyBlock (TPraos MockCrypto) ShelleyEra))
-> Property)
-> TestTree)
-> (WithVersion
ShelleyNodeToNodeVersion
(GenTx (ShelleyBlock (TPraos MockCrypto) ShelleyEra))
-> Property)
-> TestTree
forall a b. (a -> b) -> a -> b
$ CodecConfig (ShelleyBlock (TPraos MockCrypto) ShelleyEra)
-> WithVersion
(BlockNodeToNodeVersion
(ShelleyBlock (TPraos MockCrypto) ShelleyEra))
(GenTx (ShelleyBlock (TPraos MockCrypto) ShelleyEra))
-> Property
forall blk.
(SerialiseNodeToNode blk (GenTx blk), TxLimits blk) =>
CodecConfig blk
-> WithVersion (BlockNodeToNodeVersion blk) (GenTx blk) -> Property
prop_txWireSize_txSubmission CodecConfig (ShelleyBlock (TPraos MockCrypto) ShelleyEra)
testCodecCfg
, String
-> (WithVersion
ShelleyNodeToNodeVersion
(GenTx (ShelleyBlock (TPraos MockCrypto) ShelleyEra))
-> Property)
-> TestTree
forall a. Testable a => String -> a -> TestTree
testProperty String
"tight" ((WithVersion
ShelleyNodeToNodeVersion
(GenTx (ShelleyBlock (TPraos MockCrypto) ShelleyEra))
-> Property)
-> TestTree)
-> (WithVersion
ShelleyNodeToNodeVersion
(GenTx (ShelleyBlock (TPraos MockCrypto) ShelleyEra))
-> Property)
-> TestTree
forall a b. (a -> b) -> a -> b
$ (GenTx (ShelleyBlock (TPraos MockCrypto) ShelleyEra)
-> Maybe String)
-> CodecConfig (ShelleyBlock (TPraos MockCrypto) ShelleyEra)
-> WithVersion
(BlockNodeToNodeVersion
(ShelleyBlock (TPraos MockCrypto) ShelleyEra))
(GenTx (ShelleyBlock (TPraos MockCrypto) ShelleyEra))
-> Property
forall blk.
(SerialiseNodeToNode blk (GenTx blk), TxLimits blk) =>
(GenTx blk -> Maybe String)
-> CodecConfig blk
-> WithVersion (BlockNodeToNodeVersion blk) (GenTx blk)
-> Property
prop_txWireSize GenTx (ShelleyBlock (TPraos MockCrypto) ShelleyEra) -> Maybe String
getTxBytes CodecConfig (ShelleyBlock (TPraos MockCrypto) ShelleyEra)
testCodecCfg
]
,
String -> (ShelleyHash -> Property) -> TestTree
forall a. Testable a => String -> a -> TestTree
testProperty String
"hashSize real crypto" ((ShelleyHash -> Property) -> TestTree)
-> (ShelleyHash -> Property) -> TestTree
forall a b. (a -> b) -> a -> b
$ Proxy (ShelleyBlock (TPraos MockCrypto) ShelleyEra)
-> HeaderHash (ShelleyBlock (TPraos MockCrypto) ShelleyEra)
-> Property
forall blk.
ConvertRawHash blk =>
Proxy blk -> HeaderHash blk -> Property
prop_hashSize Proxy (ShelleyBlock (TPraos MockCrypto) ShelleyEra)
pReal
, String -> (ShelleyHash -> Property) -> TestTree
forall a. Testable a => String -> a -> TestTree
testProperty String
"ConvertRawHash real crypto" ((ShelleyHash -> Property) -> TestTree)
-> (ShelleyHash -> Property) -> TestTree
forall a b. (a -> b) -> a -> b
$ Proxy (ShelleyBlock (TPraos MockCrypto) ShelleyEra)
-> HeaderHash (ShelleyBlock (TPraos MockCrypto) ShelleyEra)
-> Property
forall blk.
(StandardHash blk, ConvertRawHash blk) =>
Proxy blk -> HeaderHash blk -> Property
roundtrip_ConvertRawHash Proxy (ShelleyBlock (TPraos MockCrypto) ShelleyEra)
pReal
, String
-> (ShelleyBlock (TPraos MockCrypto) ShelleyEra -> Property)
-> TestTree
forall a. Testable a => String -> a -> TestTree
testProperty String
"BinaryBlockInfo sanity check" ShelleyBlock (TPraos MockCrypto) ShelleyEra -> Property
prop_shelleyBinaryBlockInfo
, String -> [TestTree] -> TestTree
testGroup
String
"Integrity"
[ String
-> (Coherent (ShelleyBlock (TPraos MockCrypto) ShelleyEra) -> Bool)
-> TestTree
forall a. Testable a => String -> a -> TestTree
testProperty String
"generate non-corrupt blocks" Coherent (ShelleyBlock (TPraos MockCrypto) ShelleyEra) -> Bool
prop_blockIntegrity
, String
-> (Header (ShelleyBlock (TPraos MockCrypto) ShelleyEra) -> Bool)
-> TestTree
forall a. Testable a => String -> a -> TestTree
testProperty String
"generate non-corrupt headers" Header (ShelleyBlock (TPraos MockCrypto) ShelleyEra) -> Bool
prop_headerIntegrity
, String
-> (Coherent (ShelleyBlock (TPraos MockCrypto) ShelleyEra)
-> Corruption -> Property)
-> TestTree
forall a. Testable a => String -> a -> TestTree
testProperty String
"detect corruption in blocks" Coherent (ShelleyBlock (TPraos MockCrypto) ShelleyEra)
-> Corruption -> Property
prop_detectCorruption_Block
, String
-> (Header (ShelleyBlock (TPraos MockCrypto) ShelleyEra)
-> Corruption -> Property)
-> TestTree
forall a. Testable a => String -> a -> TestTree
testProperty String
"detect corruption in headers" Header (ShelleyBlock (TPraos MockCrypto) ShelleyEra)
-> Corruption -> Property
prop_detectCorruption_Header
]
]
where
pReal :: Proxy Block
pReal :: Proxy (ShelleyBlock (TPraos MockCrypto) ShelleyEra)
pReal = Proxy (ShelleyBlock (TPraos MockCrypto) ShelleyEra)
forall {k} (t :: k). Proxy t
Proxy
testCodecCfg :: CodecConfig Block
testCodecCfg :: CodecConfig (ShelleyBlock (TPraos MockCrypto) ShelleyEra)
testCodecCfg = CodecConfig (ShelleyBlock (TPraos MockCrypto) ShelleyEra)
forall proto era. CodecConfig (ShelleyBlock proto era)
ShelleyCodecConfig
dictNestedHdr ::
forall a era proto.
ShelleyCompatible proto era =>
NestedCtxt_ (ShelleyBlock proto era) Header a -> Dict (Eq a, Show a)
dictNestedHdr :: forall a era proto.
ShelleyCompatible proto era =>
NestedCtxt_ (ShelleyBlock proto era) Header a
-> Dict (Eq a, Show a)
dictNestedHdr NestedCtxt_ (ShelleyBlock proto era) Header a
R:NestedCtxt_ShelleyBlockfa proto era Header a
CtxtShelley = Dict (Eq a, Show a)
forall (a :: Constraint). a => Dict a
Dict
prop_shelleyBinaryBlockInfo :: Block -> Property
prop_shelleyBinaryBlockInfo :: ShelleyBlock (TPraos MockCrypto) ShelleyEra -> Property
prop_shelleyBinaryBlockInfo ShelleyBlock (TPraos MockCrypto) ShelleyEra
blk =
ByteString
encodedHeader ByteString -> ByteString -> Property
forall a. (Eq a, Show a) => a -> a -> Property
=== ByteString
extractedHeader
where
BinaryBlockInfo{Word16
headerOffset :: Word16
headerOffset :: BinaryBlockInfo -> Word16
headerOffset, Word16
headerSize :: Word16
headerSize :: BinaryBlockInfo -> Word16
headerSize} =
ShelleyBlock (TPraos MockCrypto) ShelleyEra -> BinaryBlockInfo
forall proto era.
ShelleyCompatible proto era =>
ShelleyBlock proto era -> BinaryBlockInfo
shelleyBinaryBlockInfo ShelleyBlock (TPraos MockCrypto) ShelleyEra
blk
extractedHeader :: Lazy.ByteString
extractedHeader :: ByteString
extractedHeader =
Int64 -> ByteString -> ByteString
Lazy.take (Word16 -> Int64
forall a b. (Integral a, Num b) => a -> b
fromIntegral Word16
headerSize) (ByteString -> ByteString) -> ByteString -> ByteString
forall a b. (a -> b) -> a -> b
$
Int64 -> ByteString -> ByteString
Lazy.drop (Word16 -> Int64
forall a b. (Integral a, Num b) => a -> b
fromIntegral Word16
headerOffset) (ByteString -> ByteString) -> ByteString -> ByteString
forall a b. (a -> b) -> a -> b
$
Encoding -> ByteString
CBOR.toLazyByteString (ShelleyBlock (TPraos MockCrypto) ShelleyEra -> Encoding
forall proto era.
ShelleyCompatible proto era =>
ShelleyBlock proto era -> Encoding
encodeShelleyBlock ShelleyBlock (TPraos MockCrypto) ShelleyEra
blk)
encodedHeader :: Lazy.ByteString
encodedHeader :: ByteString
encodedHeader = Encoding -> ByteString
CBOR.toLazyByteString (Encoding -> ByteString) -> Encoding -> ByteString
forall a b. (a -> b) -> a -> b
$ Header (ShelleyBlock (TPraos MockCrypto) ShelleyEra) -> Encoding
forall proto era.
ShelleyCompatible proto era =>
Header (ShelleyBlock proto era) -> Encoding
encodeShelleyHeader (ShelleyBlock (TPraos MockCrypto) ShelleyEra
-> Header (ShelleyBlock (TPraos MockCrypto) ShelleyEra)
forall blk. GetHeader blk => blk -> Header blk
getHeader ShelleyBlock (TPraos MockCrypto) ShelleyEra
blk)
testTPraosSlotsPerKESPeriod :: Word64
testTPraosSlotsPerKESPeriod :: Word64
testTPraosSlotsPerKESPeriod = Word64
forall a. Bounded a => a
maxBound
prop_blockIntegrity :: Coherent Block -> Bool
prop_blockIntegrity :: Coherent (ShelleyBlock (TPraos MockCrypto) ShelleyEra) -> Bool
prop_blockIntegrity =
Word64 -> ShelleyBlock (TPraos MockCrypto) ShelleyEra -> Bool
forall proto era.
ShelleyCompatible proto era =>
Word64 -> ShelleyBlock proto era -> Bool
verifyBlockIntegrity Word64
testTPraosSlotsPerKESPeriod (ShelleyBlock (TPraos MockCrypto) ShelleyEra -> Bool)
-> (Coherent (ShelleyBlock (TPraos MockCrypto) ShelleyEra)
-> ShelleyBlock (TPraos MockCrypto) ShelleyEra)
-> Coherent (ShelleyBlock (TPraos MockCrypto) ShelleyEra)
-> Bool
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Coherent (ShelleyBlock (TPraos MockCrypto) ShelleyEra)
-> ShelleyBlock (TPraos MockCrypto) ShelleyEra
forall a. Coherent a -> a
getCoherent
prop_headerIntegrity :: Header Block -> Bool
=
forall proto.
ProtocolHeaderSupportsKES proto =>
Word64 -> ShelleyProtocolHeader proto -> Bool
verifyHeaderIntegrity @(TPraos MockCrypto) Word64
testTPraosSlotsPerKESPeriod
(BHeader MockCrypto -> Bool)
-> (Header (ShelleyBlock (TPraos MockCrypto) ShelleyEra)
-> BHeader MockCrypto)
-> Header (ShelleyBlock (TPraos MockCrypto) ShelleyEra)
-> Bool
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Header (ShelleyBlock (TPraos MockCrypto) ShelleyEra)
-> BHeader MockCrypto
Header (ShelleyBlock (TPraos MockCrypto) ShelleyEra)
-> ShelleyProtocolHeader (TPraos MockCrypto)
forall proto era.
Header (ShelleyBlock proto era) -> ShelleyProtocolHeader proto
shelleyHeaderRaw
prop_detectCorruption_Block :: Coherent Block -> Corruption -> Property
prop_detectCorruption_Block :: Coherent (ShelleyBlock (TPraos MockCrypto) ShelleyEra)
-> Corruption -> Property
prop_detectCorruption_Block (Coherent ShelleyBlock (TPraos MockCrypto) ShelleyEra
blk) =
(ShelleyBlock (TPraos MockCrypto) ShelleyEra -> Encoding)
-> (forall s.
Decoder
s
(ByteString
-> Either
DecoderError (ShelleyBlock (TPraos MockCrypto) ShelleyEra)))
-> (ShelleyBlock (TPraos MockCrypto) ShelleyEra -> Bool)
-> ShelleyBlock (TPraos MockCrypto) ShelleyEra
-> Corruption
-> Property
forall a.
Show a =>
(a -> Encoding)
-> (forall s. Decoder s (ByteString -> Either DecoderError a))
-> (a -> Bool)
-> a
-> Corruption
-> Property
detectCorruption
ShelleyBlock (TPraos MockCrypto) ShelleyEra -> Encoding
forall proto era.
ShelleyCompatible proto era =>
ShelleyBlock proto era -> Encoding
encodeShelleyBlock
Decoder
s
(ByteString
-> Either
DecoderError (ShelleyBlock (TPraos MockCrypto) ShelleyEra))
forall s.
Decoder
s
(ByteString
-> Either
DecoderError (ShelleyBlock (TPraos MockCrypto) ShelleyEra))
forall proto era s.
ShelleyCompatible proto era =>
Decoder
s (ByteString -> Either DecoderError (ShelleyBlock proto era))
decodeShelleyBlock
(Word64 -> ShelleyBlock (TPraos MockCrypto) ShelleyEra -> Bool
forall proto era.
ShelleyCompatible proto era =>
Word64 -> ShelleyBlock proto era -> Bool
verifyBlockIntegrity Word64
testTPraosSlotsPerKESPeriod)
ShelleyBlock (TPraos MockCrypto) ShelleyEra
blk
prop_detectCorruption_Header :: Header Block -> Corruption -> Property
=
(Header (ShelleyBlock (TPraos MockCrypto) ShelleyEra) -> Encoding)
-> (forall s.
Decoder
s
(ByteString
-> Either
DecoderError
(Header (ShelleyBlock (TPraos MockCrypto) ShelleyEra))))
-> (Header (ShelleyBlock (TPraos MockCrypto) ShelleyEra) -> Bool)
-> Header (ShelleyBlock (TPraos MockCrypto) ShelleyEra)
-> Corruption
-> Property
forall a.
Show a =>
(a -> Encoding)
-> (forall s. Decoder s (ByteString -> Either DecoderError a))
-> (a -> Bool)
-> a
-> Corruption
-> Property
detectCorruption
Header (ShelleyBlock (TPraos MockCrypto) ShelleyEra) -> Encoding
forall proto era.
ShelleyCompatible proto era =>
Header (ShelleyBlock proto era) -> Encoding
encodeShelleyHeader
((Header (ShelleyBlock (TPraos MockCrypto) ShelleyEra)
-> Either
DecoderError (Header (ShelleyBlock (TPraos MockCrypto) ShelleyEra))
forall a b. b -> Either a b
Right (Header (ShelleyBlock (TPraos MockCrypto) ShelleyEra)
-> Either
DecoderError
(Header (ShelleyBlock (TPraos MockCrypto) ShelleyEra)))
-> (ByteString
-> Header (ShelleyBlock (TPraos MockCrypto) ShelleyEra))
-> ByteString
-> Either
DecoderError (Header (ShelleyBlock (TPraos MockCrypto) ShelleyEra))
forall b c a. (b -> c) -> (a -> b) -> a -> c
.) ((ByteString
-> Header (ShelleyBlock (TPraos MockCrypto) ShelleyEra))
-> ByteString
-> Either
DecoderError
(Header (ShelleyBlock (TPraos MockCrypto) ShelleyEra)))
-> Decoder
s
(ByteString
-> Header (ShelleyBlock (TPraos MockCrypto) ShelleyEra))
-> Decoder
s
(ByteString
-> Either
DecoderError
(Header (ShelleyBlock (TPraos MockCrypto) ShelleyEra)))
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Decoder
s
(ByteString
-> Header (ShelleyBlock (TPraos MockCrypto) ShelleyEra))
forall s.
Decoder
s
(ByteString
-> Header (ShelleyBlock (TPraos MockCrypto) ShelleyEra))
forall proto era s.
ShelleyCompatible proto era =>
Decoder s (ByteString -> Header (ShelleyBlock proto era))
decodeShelleyHeader)
( forall proto.
ProtocolHeaderSupportsKES proto =>
Word64 -> ShelleyProtocolHeader proto -> Bool
verifyHeaderIntegrity @(TPraos MockCrypto) Word64
testTPraosSlotsPerKESPeriod
(BHeader MockCrypto -> Bool)
-> (Header (ShelleyBlock (TPraos MockCrypto) ShelleyEra)
-> BHeader MockCrypto)
-> Header (ShelleyBlock (TPraos MockCrypto) ShelleyEra)
-> Bool
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Header (ShelleyBlock (TPraos MockCrypto) ShelleyEra)
-> BHeader MockCrypto
Header (ShelleyBlock (TPraos MockCrypto) ShelleyEra)
-> ShelleyProtocolHeader (TPraos MockCrypto)
forall proto era.
Header (ShelleyBlock proto era) -> ShelleyProtocolHeader proto
shelleyHeaderRaw
)