CBOR: bignum payloads bypass bounded_bytes chunking above 64 bytes

Open Beginner friendly
#530 0 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

Assessment

Difficulty
2/5
Estimated time
1-3 hours
Newbie friendliness
86/100
Issue type
Bug
Clarity
Clearly specified
Activity status
Active
Tech stack
typescript

Research direction

Start in packages/evolution/src/CBOR.ts at encodeUintSync, encodeNintSync, and the existing BoundedBytes and encodeBoundedBytesSync paths; review the CDDL notes in packages/evolution/src/Data.ts. Run the existing CBOR or datum-hash tests, then add regression coverage for the positive and negative over-64-byte cases. Done means those payloads use chunked strings while the 9-byte case remains definite and the expected hashes match.

Written by the indexing model from the issue text.

Description

bug external-review

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.

Dominant language
TypeScript
Stars
22
Forks
30
Avg merge
13h
Merged PRs (30d)
14

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

More from IntersectMBO/evolution-sdk

All issues in IntersectMBO/evolution-sdk

Similar issues

More TypeScript issues

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.