Skip to content

CBOR: tags with 4- and 8-byte headers fail to decode, and two smaller preservation gaps #580

Description

@solidsnakedev

Three small gaps found while testing format preservation, in order of impact.

1. Tags with a 4- or 8-byte header fail to decode

decodeTagAt accepts tag headers only up to 2 bytes, so a transaction that writes tag 258 as da00000102 fails with CBORError: Unsupported tag encoding: 26. The node accepts that transaction, and CML round-trips it byte for byte. The spec says tag header width is preserved (.specs/cbor-encoding-preservation.md L180-183) and lists "non-minimal tag width" as supported (L329), which holds only for 1- and 2-byte headers.

Affected: packages/evolution/src/CBOR.ts decodeTagAt (L2044-2054), which has no branch for additional info 26 or 27.

Fix: decode 4- and 8-byte tag headers and record the width, as integer headers already do.

Devnet, raw submission through Ogmios: inputs written as 00 da00000102 81 [input], signed over their own body, were accepted. Transaction.fromCBORHex on the same bytes throws.

2. An empty indefinite witness set is written back as a0

An unsigned transaction with witness set bfff comes back from fromCBORHex then toCBORHex with a0. The body and the transaction id are unchanged, because the id is taken over the body only (cardano-ledger Core.hs L651), so no signature is affected. addVKeyWitnessesHex keeps the indefinite map. CML round-trips it byte for byte.

Affected: the empty map fast path in encodeMapSync (L1371), the same one #576 fixes for Plutus data. The fix for #576 covers this too; this entry only adds a regression case.

3. The CBOR guide says re-encoding is canonical by default

docs/content/docs/encoding/cbor.mdx L37 comments "Re-encode to hex (canonical by default)". The default, CML_DEFAULT_OPTIONS, keeps map insertion order (sortMapKeys: false), and the same page says so at L135. The comment should say the default keeps the original order.

Regression test

  • Transaction.fromCBORHex accepts tag 258 written with a 4-byte header, and toCBORHex returns the same bytes
  • 84 [body] bfff f5 f6 round-trips byte for byte

Must FAIL on main today and PASS after the fix.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions