Repository navigation
Conversation
…tMBO#576) Empty arrays and maps returned 80/a0 before the captured format was read, so an empty indefinite list or map and a wider length header were lost; the BoundedBytes branch dropped the captured format entirely, so a datum's byte-string header width and chunk layout were lost. The ledger hashes the original datum and redeemer bytes, so each change broke the script data hash or the transaction id. The empty fast paths now honour a captured indefinite length or header width, and encodeBoundedBytesSync receives the format: it keeps the header width and replays a chunk layout only when the chunk sizes add up to the value's length and no chunk is over 64 bytes, falling back to the default bounded encoding otherwise. Also adds the regression case for IntersectMBO#580 part 2 (empty indefinite witness set) and corrects the CBOR guide's 'canonical by default' comment (IntersectMBO#580 part 3). Tests: 1709 passed / 75 skipped / 0 failed (main baseline 1678 + 31 new).
This branch has not been deployed
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Fixes #576: six encodings of Plutus data that the ledger accepts came back from
Transaction.fromCBORHex→Transaction.toCBORHexin different bytes, with nothing changed. Because the ledger hashes the original bytes of every datum and redeemer, a changed witness datum failed withPPViewHashesDontMatchand a changed inline datum changed the body and the transaction id.This also adds the regression case for #580 part 2 (an empty indefinite witness set written back as
a0) and fixes #580 part 3 (the CBOR guide's "canonical by default" comment). Part 1 of #580 shipped separately.The bug, reproduced first
New regression tests failed on main for five of the six encodings, in both positions the issue names — as a witness datum (
a1 04 d90102 81 [datum]) and as an inline datum in a map-form output:d8799fff(constructor 0, empty indefinite list) →d87980bfff(empty indefinite map) →a0d8799800(empty list, 2-byte length header) →d879805803cccccc(3 bytes, 2-byte length header) →43cccccc5f4201024103ff(bytes in chunks) →43010203bfff→a0(CBOR: tags with 4- and 8-byte headers fail to decode, and two smaller preservation gaps #580 part 2)The sixth encoding,
c24101(1 as a bignum), already round-trips on main — the captured-tag path inencodeUintSynchandles it — so it is included in the tests as a guard rather than claimed as part of this fix. The controld8799f01ffround-tripped before and still does.Fix
CBOR.ts—encodeArraySync/encodeMapEntriesSync: the captured format is read before the empty fast paths. An empty array or map keeps a captured indefinite length (9f ff/bf ff) or a captured definite header width instead of always returning80/a0.CBOR.ts—BoundedBytes: the branch ininternalEncodeSyncnow passes the captured format toencodeBoundedBytesSync. A definite header keeps its width, and an indefinite chunk layout is replayed only when it still fits the value — the chunk sizes add up to the value's length and no chunk is over 64 bytes. A stale layout falls through to the default bounded encoding, so the corruption CBOR: preservation-aware encode reuses stale chunk sizes, writing different content #575 fixed for plain byte strings is not carried into datums (the guard CBOR: Plutus data encodings change on re-encode, breaking the script data hash and the transaction id #576 asked for before this format was passed in).docs/content/docs/encoding/cbor.mdx: the re-encode comment now says the default keeps the original map order, matching what the same page documents forCML_DEFAULT_OPTIONS(CBOR: tags with 4- and 8-byte headers fail to decode, and two smaller preservation gaps #580 part 3).Tests
Transaction-with-format.test.ts: each encoding round-trips byte for byte as a witness datum and as an inline datum (plain decode/encode path), the body hash of a chunked-inline-datum transaction is unchanged (verified via CML), and the empty indefinite witness set round-trips.CBOR-with-format.test.ts: the four generic encodings join the round-trip vectors; hand-crafted formats pin the empty array/map behaviour;BoundedBytestests pin the kept header width, the kept chunk layout, and both stale-layout refusals (sizes that do not add up, a chunk over 64 bytes).tsc --noEmitand eslint are clean; a patch changeset is included.I'm an independent builder working on Cardano tooling — not affiliated with the Cardano Foundation, IOG or Intersect.
Support my work: ADA addr1q8hnl6vl5a6k3rw3n5g3jtte696zcl76kfatzv7gpswa9r0dj7fma6klq55y4ffm7tf0em09udnyhuk4ah92pl5x9jpqjae44v · X: @kshot9000 · GitHub: Kshot3000
cc @cardano-foundation @IntersectMBO