Skip to content

Implement SerialiseAsCBOR and Eq for AnyScript era#1122

Open
Jimbo4350 wants to merge 4 commits intomasterfrom
jordan/1088-serialise-as-cbor-any-simple-script
Open

Implement SerialiseAsCBOR and Eq for AnyScript era#1122
Jimbo4350 wants to merge 4 commits intomasterfrom
jordan/1088-serialise-as-cbor-any-simple-script

Conversation

@Jimbo4350
Copy link
Contributor

@Jimbo4350 Jimbo4350 commented Mar 9, 2026

Changelog

- description: |
    Add `SerialiseAsCBOR (AnyScript era)` and `Eq (AnyScript era)` instances,
    and generators and property tests for CBOR roundtripping.
  type:
  - feature
  projects:
  - cardano-api

Context

Closes #1088

How to trust this PR

  • AnyScript CBOR serialisation uses the ledger's tagged AlonzoScript format (tag 0 = native script, tags 1–4 = PlutusV1–V4), so round-tripping is unambiguous.
  • Eq (AnyScript era) uses eqT to resolve the existential lang in AnyPlutusScript, delegating to the underlying Eq instances.
  • Property tests cover: CBOR roundtrip via H.tripping, and garbage bytes always returning Left.

Checklist

  • Commit sequence broadly makes sense and commits have useful messages
  • New tests are added if needed and existing tests are updated. See Running tests for more details
  • Self-reviewed the diff

@Jimbo4350 Jimbo4350 force-pushed the jordan/1088-serialise-as-cbor-any-simple-script branch 3 times, most recently from f2fbb2e to da77b52 Compare March 10, 2026 13:06
@Jimbo4350 Jimbo4350 marked this pull request as ready for review March 10, 2026 13:13
Copilot AI review requested due to automatic review settings March 10, 2026 13:13
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Adds CBOR serialisation and equality support for AnyScript in the experimental API, plus generators and property tests to validate CBOR roundtripping for the Conway-era AnyScript wrapper.

Changes:

  • Implement Eq (AnyScript era) by resolving the existential Plutus language via eqT.
  • Implement SerialiseAsCBOR (AnyScript era) using the ledger Script encoding (native vs Plutus tagged form).
  • Add a Conway AnyScript generator and Hedgehog properties for CBOR roundtrip and failure cases.

Reviewed changes

Copilot reviewed 3 out of 3 changed files in this pull request and generated 3 comments.

File Description
cardano-api/src/Cardano/Api/Experimental/AnyScript.hs Adds Eq and SerialiseAsCBOR instances for AnyScript and the AsAnyScript type proxy.
cardano-api/gen/Test/Gen/Cardano/Api/Experimental.hs Adds generators for SimpleScript in Conway and AnyScript values used by tests.
cardano-api/test/cardano-api-test/Test/Cardano/Api/Experimental.hs Adds a new test group with CBOR roundtrip and “garbage bytes” deserialisation properties for AnyScript.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines 23 to 27
import Cardano.Api.Ledger.Internal.Reexport qualified as L
import Cardano.Api.Serialise.Cbor

import Cardano.Binary qualified as CBOR
import Cardano.Ledger.Binary qualified as CBOR
import Cardano.Ledger.Core qualified as L
Copy link

Copilot AI Mar 10, 2026

Choose a reason for hiding this comment

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

The module imports two different modules qualified as L (Cardano.Api.Ledger.Internal.Reexport and Cardano.Ledger.Core), which will not compile due to the duplicate qualifier. Use distinct qualifiers (e.g. Ledger vs LedgerCore) or drop one import if it’s redundant, and update the references accordingly.

Copilot uses AI. Check for mistakes.
Comment on lines +122 to +125
prop_roundtrip_cbor_any_script :: Property
prop_roundtrip_cbor_any_script = H.property $ do
script <- H.forAll genAnyScript
H.tripping script Exp.serialiseToCBOR (Exp.deserialiseFromCBOR Exp.AsAnyScript)
Copy link

Copilot AI Mar 10, 2026

Choose a reason for hiding this comment

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

serialiseToCBOR, deserialiseFromCBOR, and AsAnyScript are not exported from Cardano.Api.Experimental, so Exp.serialiseToCBOR / Exp.deserialiseFromCBOR Exp.AsAnyScript won’t typecheck from this import. Either import Cardano.Api.Serialise.Cbor (for the methods) and Cardano.Api.Experimental.AnyScript (for AsAnyScript), or switch to using Api.serialiseToCBOR / Api.deserialiseFromCBOR with AsAnyScript brought into scope.

Copilot uses AI. Check for mistakes.
Comment on lines +129 to +133
prop_deserialise_garbage_bytes_returns_left = H.property $ do
garbage <- H.forAll $ Gen.bytes (Range.linear 0 128)
case Exp.deserialiseFromCBOR Exp.AsAnyScript garbage of
Left _ -> H.success
Right _ -> H.annotate "Expected deserialisation failure but got Right" >> H.failure
Copy link

Copilot AI Mar 10, 2026

Choose a reason for hiding this comment

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

This property is not guaranteed: arbitrary bytes can occasionally form a valid CBOR encoding of a script, so the test can be flaky (sometimes Right). Consider generating bytes that are guaranteed invalid for this decoder (e.g. take a valid serialiseToCBOR output and append extra trailing bytes, or otherwise ensure the bytes cannot match the tagged AlonzoScript encoding).

Copilot uses AI. Check for mistakes.
@Jimbo4350 Jimbo4350 force-pushed the jordan/1088-serialise-as-cbor-any-simple-script branch 3 times, most recently from 51d7d8c to 830c361 Compare March 11, 2026 13:11
Add HasTypeProxy and SerialiseAsCBOR instances for AnyScript era,
enabling CBOR serialisation/deserialisation of both simple and plutus
scripts using the ledger's native Script era encoding format.

Closes #1088
Uses eqT to handle the existential lang in AnyPlutusScript, delegating
to the underlying Eq instances on SimpleScript and PlutusScriptInEra.
Also adds Typeable lang constraint to the AnyPlutusScript constructor.
Adds genAnyScript and genSimpleScriptInEra generators, along with
roundtrip and garbage-input property tests for SerialiseAsCBOR AnyScript.
@Jimbo4350 Jimbo4350 force-pushed the jordan/1088-serialise-as-cbor-any-simple-script branch from 830c361 to 13deb19 Compare March 11, 2026 13:37
CBOR.DecoderErrorCustom
( mconcat
[ "AnyScript PlutusScript ("
, Text.pack (show (Plutus.plutusLanguage plutus))
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
, Text.pack (show (Plutus.plutusLanguage plutus))
, Text.show (Plutus.plutusLanguage plutus)

, ")"
]
)
(Text.pack . show $ pretty e)
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
(Text.pack . show $ pretty e)
(Text.show $ pretty e)

script <- decodeScript
case L.getNativeScript script of
Just ns -> Right $ AnySimpleScript (SimpleScript ns)
Nothing ->
Copy link
Contributor

Choose a reason for hiding this comment

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

@copilot Rewrite deserialiseFromCBOR using asum over a list, utilising Alternative Maybe to short-circuit on the first successful parse.

Copy link
Contributor

Choose a reason for hiding this comment

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

@Jimbo4350 thoughts on #1130 ?

Copy link

Copilot AI commented Mar 12, 2026

@carbolymer I've opened a new pull request, #1130, to work on those changes. Once the pull request is ready, I'll request review from you.


-- | Deserialising random garbage bytes should always return 'Left'.
prop_deserialise_garbage_bytes_returns_left :: Property
prop_deserialise_garbage_bytes_returns_left = H.property $ do
Copy link
Contributor

Choose a reason for hiding this comment

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

This negative case test is pointless - it does not give us any guarantees and just adds a maintenance burden.

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.

Implement SerialiseAsCBOR for AnySimpleScript

4 participants