Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Test that consensus emits valid CBOR #323

Conversation

dnadales
Copy link
Member

@dnadales dnadales commented Aug 25, 2023

  • Check that the encoders used in the serialization roundtrip are valid.
  • Add a unit test to check that the encoders used to encode the Cardano examples are valid.

Needs: well-typed/cborg#324.

Closes IntersectMBO/ouroboros-network#3099.

@dnadales dnadales requested a review from a team as a code owner August 25, 2023 07:51
@dnadales dnadales self-assigned this Aug 25, 2023
bs = toLazyByteString enc_a

validFlatTerm (toFlatTerm enc_a) ?! "Encoded flat term is not valid: " <> show enc_a
(bsRem, a' ) <- deserialiseFromBytes dec bs `onError` showByteString bs
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Would it make sense to use fromFlatTerm instead of going through bytestrings? Or maybe do both to be extra sure we are catching all bugs?

Comment on lines 96 to 100
encodersProduceValidCBOR ::
forall blk . (SerialiseDiskConstraints blk)
=> CodecConfig blk
-> Examples blk
-> TestTree
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe this function could go into the consensus testlib

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, then it could also be re-used in Test.Consensus.{Byron,Shelley}.Serialisation 👍

import Test.Util.Serialisation.Roundtrip


Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Redundant newline

-> TestTree
encodersProduceValidCBOR codecConfig examples =
testGroup "Encoders produce valid CBOR" $
[ test exampleBlock "Block" (encodeDisk codecConfig)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I wonder if something like testProperty "Block" $ roundtrip (encodeDisk codecConfig) (decodeDisk codecConfig) exampleBlock could also work, since it removes a bit of duplication

@@ -78,31 +81,53 @@ roundtrip enc dec = roundtrip' enc (const <$> dec)

-- | Roundtrip property for values annotated with their serialized form
--
-- In addition, we check that the encoded CBOR is valid using [validFlatTerm](https://hackage.haskell.org/package/cborg-0.2.9.0/docs/Codec-CBOR-FlatTerm.html#v:validFlatTerm).
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Using Haddock markup:

Suggested change
-- In addition, we check that the encoded CBOR is valid using [validFlatTerm](https://hackage.haskell.org/package/cborg-0.2.9.0/docs/Codec-CBOR-FlatTerm.html#v:validFlatTerm).
-- In addition, we check that the encoded CBOR is valid using 'validFlatTerm'.

@dnadales dnadales force-pushed the dnadales/ouroboros-network/3099-test-that-consensus-emits-valid-CBOR branch from d600ae3 to d1048b0 Compare September 4, 2023 17:06
Copy link
Contributor

@jorisdral jorisdral left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good! I only have some minor comments

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just to be sure: nothing changed when moving these definitions from the Golden module to this module?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nope, I just extracted the relevant bits and pieces.

@@ -28,6 +28,7 @@ import Test.ThreadNet.Util.SimpleBlock
import Test.Util.HardFork.Future (singleEraFuture)
import Test.Util.Orphans.Arbitrary ()
import Test.Util.Serialisation.Roundtrip
import Test.Util.Serialisation.SomeResult ()
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm slightly surprised this is necessary, since the SomeResult module contains no orphan instances. What happens if you remove it?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good catch!

@@ -28,30 +28,38 @@ module Test.Util.Serialisation.Roundtrip (
, roundtrip_SerialiseNodeToNode
, roundtrip_all
, roundtrip_envelopes
-- * Unit tests
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
-- * Unit tests
-- * Roundtrip tests for examples

Comment on lines 634 to 672
examplesRoundtrip ::
forall blk . (SerialiseDiskConstraints blk, Eq blk, Show blk, LedgerSupportsProtocol blk)
=> CodecConfig blk
-> Examples blk
-> [TestTree]
examplesRoundtrip codecConfig examples =
[ testRoundtripFor "Block" (encodeDisk codecConfig) (decodeDisk codecConfig) exampleBlock
, testRoundtripFor "Header hash" encode (const <$> decode) exampleHeaderHash
, testRoundtripFor "Ledger state" (encodeDisk codecConfig) (const <$> decodeDisk codecConfig) exampleLedgerState
, testRoundtripFor "Annotated tip" (encodeDisk codecConfig) (const <$> decodeDisk codecConfig) exampleAnnTip
, testRoundtripFor "Chain dependent state" (encodeDisk codecConfig) (const <$> decodeDisk codecConfig) exampleChainDepState
, testRoundtripFor "Extended ledger state" encodeExt (const <$> decodeExt) exampleExtLedgerState
]
where
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The body before the where should probably have an additional two-space indentation

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Missed that. Thanks!

Comment on lines 634 to 672
examplesRoundtrip ::
forall blk . (SerialiseDiskConstraints blk, Eq blk, Show blk, LedgerSupportsProtocol blk)
=> CodecConfig blk
-> Examples blk
-> [TestTree]
examplesRoundtrip codecConfig examples =
[ testRoundtripFor "Block" (encodeDisk codecConfig) (decodeDisk codecConfig) exampleBlock
, testRoundtripFor "Header hash" encode (const <$> decode) exampleHeaderHash
, testRoundtripFor "Ledger state" (encodeDisk codecConfig) (const <$> decodeDisk codecConfig) exampleLedgerState
, testRoundtripFor "Annotated tip" (encodeDisk codecConfig) (const <$> decodeDisk codecConfig) exampleAnnTip
, testRoundtripFor "Chain dependent state" (encodeDisk codecConfig) (const <$> decodeDisk codecConfig) exampleChainDepState
, testRoundtripFor "Extended ledger state" encodeExt (const <$> decodeExt) exampleExtLedgerState
]
where
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I wonder if we can trade in some horizontal real estate for vertical real estate

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I tried putting the type in one line but I think it's too long. However, I corrected the indentation in testRoundtripFor.

validFlatTerm (toFlatTerm enc_a) ?! "Encoded flat term is not valid: " <> show enc_a
(bsRem, a' ) <- deserialiseFromBytes dec bs `onError` showByteString bs
validFlatTerm flatTerm_a ?! "Encoded flat term is not valid: " <> show enc_a
-- TODO: requires https://github.com/well-typed/cborg/pull/325
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should this be reflected in an issue, such that we don't forget about completing this TODO once a new version of cborg is released?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I added a s-r-p that contains the cborg fix. I can remove this comment.

Comment on lines 33 to 38
[ testGroup "Shelley examples roundtrip" $ examplesRoundtrip ShelleyCodecConfig Shelley.Examples.examplesShelley
, testGroup "Mary examples roundtrip" $ examplesRoundtrip ShelleyCodecConfig Shelley.Examples.examplesMary
, testGroup "Allegra examples roundtrip" $ examplesRoundtrip ShelleyCodecConfig Shelley.Examples.examplesAllegra
, testGroup "Alonzo examples roundtrip" $ examplesRoundtrip ShelleyCodecConfig Shelley.Examples.examplesAlonzo
, testGroup "Babbage examples roundtrip" $ examplesRoundtrip ShelleyCodecConfig Shelley.Examples.examplesBabbage
, testGroup "Conway examples roundtrip" $ examplesRoundtrip ShelleyCodecConfig Shelley.Examples.examplesConway
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Random idea I had: maybe we should store Shelley-based era examples in an NP Examples ShelleyEras and map the roundtrip test function over it. That way, we won't forget about adding a roundtrip test when we add a new shelley-based era

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That's an excellent idea! Thanks. Let me try and see what I can do.

This required to factor out 'SomeResult' as well.
@dnadales dnadales force-pushed the dnadales/ouroboros-network/3099-test-that-consensus-emits-valid-CBOR branch 2 times, most recently from 2fcfa97 to 7923927 Compare September 19, 2023 15:41
Copy link
Contributor

@jorisdral jorisdral left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM!

@@ -124,16 +127,20 @@ roundtrip' enc dec a = checkRoundtripResult $ do
flatTerm_a = toFlatTerm enc_a

validFlatTerm flatTerm_a ?! "Encoded flat term is not valid: " <> show enc_a
a' <- fromFlatTerm dec flatTerm_a
a == a' bs ?! show a <> " /= " <> show (a' bs)
-- TODO: the decode test via FlatTerm will currently fail because https://github.com/input-output-hk/cardano-ledger/issues/3741
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Does the issue link back to this part of the code, such that we don't forget re-enabling it?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good point, I'll have to add a permalink after merging this one

Function `Test.Util.Serialisation.Roundtrip.roundtrip'` has been
adapted to check that the resulting encoding is valid according to
[validFlatTerm](https://hackage.haskell.org/package/cborg-0.2.9.0/docs/Codec-CBOR-FlatTerm.html#v:validFlatTerm).

We also test that the CBOR encoders for Cardano examples are valid by
testing them with the `roundtrip'` function.
@dnadales dnadales force-pushed the dnadales/ouroboros-network/3099-test-that-consensus-emits-valid-CBOR branch from 7923927 to f8426b2 Compare September 20, 2023 11:41
@dnadales dnadales added this pull request to the merge queue Sep 20, 2023
Merged via the queue into main with commit f743b8f Sep 20, 2023
9 of 11 checks passed
@dnadales dnadales deleted the dnadales/ouroboros-network/3099-test-that-consensus-emits-valid-CBOR branch September 20, 2023 11:47
github-merge-queue bot pushed a commit that referenced this pull request Sep 28, 2023
Also inlcudes changelog entries for #366 and the first commit in #323
(second commit was reverted in #362).
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Test that Consensus emits valid CBOR
3 participants