Skip to content

CBOR: bignum payloads bypass bounded_bytes chunking above 64 bytes #530

Description

@solidsnakedev

Summary

Plutus Data integers whose magnitude exceeds 64 bytes (|value| >= 2^512) are encoded as a single
definite-length byte string under CBOR tag 2 or 3. The Conway CDDL, quoted in this repo at
Data.ts L165-167, defines a bignum payload as bounded_bytes = bytes .size (0..64), so a magnitude
of 65 bytes or more must be an indefinite-length byte string split into chunks of at most 64 bytes.
The SDK already applies that rule to Data byte-string leaves, so the same file chunks a 65-byte
bytearray and does not chunk a 65-byte bignum. The result is Plutus data that violates the grammar,
and a datum hash that differs from the one computed over the chunked form.

Affected

packages/evolution/src/CBOR.ts

  • encodeUintSync (L985-991): passes bigintToBytes(value) straight to encodeTagSync(2, ...) (L989-990)
  • encodeNintSync (L1028-1035): same for tag 3 (L1033-1034)
  • contrast: the BoundedBytes node (L1231-1239) routes through encodeBoundedBytesSync (L1109),
    which chunks at 64 bytes and is applied unconditionally

packages/evolution/src/Data.ts

  • CDDL for big_uint / big_nint / bounded_bytes documented at L165-167

Fix

Wrap the bignum magnitude in the existing BoundedBytes node so the chunking rule applies, mirroring
the fix PR #160 made for byte-string leaves:

return encodeTagSync(2, BoundedBytes.make(bigintToBytes(value)), options, fmt)

and the tag 3 analogue in encodeNintSync. Alternatively have encodeTagSync treat tag 2 and 3
payloads as bounded bytes. Note #395 edits the same two lines of encodeNintSync for the negative
bignum boundary, so the two changes will conflict.

Regression test

  • given: Data.int(2n ** 512n)
  • before fix: encodes to c25841... (single 65-byte definite string); toDatumHash is 9b2838f7...
  • after fix: encodes to c25f5840...4100ff; toDatumHash is
    939bb1f51ea88f86a070fefb5c1185d10b4d10a13e3b7db24aac02220c18adab
  • negative analogue: Data.int(-(2n ** 520n)) chunks under tag 3 rather than emitting c35841...
  • unchanged: a 9-byte bignum such as 2n ** 64n stays definite, so only the over-64-byte case moves

Must FAIL on main today and PASS after the fix.

Reference

Same defect class as #158, which covered Data byte-string leaves and was fixed in PR #160. The
integer path was never routed through BoundedBytes.

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

    bugSomething isn't workingexternal-reviewFrom external review batch

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions