Repository navigation
Conversation
PlutusDataCborDecoder accepted CBOR that plutus's decodeData rejects (plutus 1.65.0.0 Data.hs:209-307, cborg 0.2.8.0): byte strings and bignum payloads over 64 bytes, nested or tagged chunks, d802 bignum tags, nested and unknown tags (read as I 0), tagged tag-102 index/fields, extra elements in an indefinite tag-102 array, simple values dropped by filterBreaks, indefinite integers and tags, and 64-bit lengths read as signed. A script with such a Data constant is MalformedScriptWitnesses in the ledger but decoded in julc. - MapPreservingCborDecoder bounds byte strings (indefinite only as definite chunks of at most 64 bytes, bignum payloads included), rejects indefinite integers and tags and arrays longer than the input, and allows a tag only around bytes (c2/c3) or an array. - PlutusDataCborDecoder.fromDataItem rejects unknown and nested tags and a tagged tag-102 index or fields, and drops only the closing break. Trailing bytes follow the ledger context: - decode() is strict: one item, no leftover (inline datums: makeBinaryData -> decodeFull', ledger-core Plutus/Data.hs:154-173; datums and redeemers are exact item slices). - decodeFirst() ignores the remainder, as FLAT data constants do (FlatViaSerialise -> deserialiseOrFail, serialise Codec/Serialise.hs: 134-143). Used only by UplcFlatDecoder.readData. Tests: PlutusDataDecoderParityTest (accept/reject/trailing vectors and FLAT end-to-end cases), every verdict confirmed against plutus decodeData on cborg 0.2.8.0; a 90k-vector differential fuzz shows no difference for either mode. One MapDecodingFidelityTest vector (tag 1000 on a map) is removed: plutus rejects it. Fixes #237 Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_012MQvHGqr1BvpfjkzfbHWfW
satran004
left a comment
There was a problem hiding this comment.
Correctness-focused review of 8297793: no blocking correctness finding identified in this diff.
Checked the decoder against plutus-core 1.65.0.0 decodeData and inspected cbor-java 0.9's delegated array/tag parsing. Reviewed bounded chunks/bignums, general-constructor Word64 and arity checks, nested/unknown tags, misplaced breaks, unsigned lengths, duplicate map associations, and the strict decode versus FLAT-only decodeFirst call path.
Independently ran core (799 tests), Java VM (2,469 discovered; 262 explicitly inapplicable PV10 cases skipped), and cardano-client-lib tests: no failures. Also ran core with #236 and #238 combined successfully. Did not rerun the author's Haskell differential fuzz campaign, Yano, or an external DevKit.
Documentation follow-up: ADR-037 explicitly preserves the old top-level sequence handling, unknown-tag behavior, and non-map permissiveness. Please record that this change supersedes those constraints, and add release guidance for the public decode() behavior change. The stricter behavior is intentional and appropriate; the governing documentation should say so.
Recommendation: no correctness blocker found within the reviewed change.
Fixes #237. This is related to #229 / #236, the encoder.
Summary
PlutusDataCborDecoderaccepted CBOR that plutus'sdecodeDatarejects (plutus 1.65.0.0Data.hs:209-307, cborg 0.2.8.0). It backs FLATdataconstants, so a script the ledger rejects asMalformedScriptWitnessesdecoded fine in julc. That gives Yano'sjava-julcphase-1 well-formedness check a false accept.What it wrongly accepted:
d802bignum tags;I 0;filterBreaks(81f5decoded asList []);Trailing bytes now follow the ledger context:
decode()makeBinaryData→decodeFull'(ledger-corePlutus/Data.hs:154-173); datums and redeemers are exact item slicesdecodeFirst()dataconstants:FlatViaSerialise→deserialiseOrFail(serialiseCodec/Serialise.hs:134-143)UplcFlatDecoder.readDataOn
main, julc's hybrid matched neither context. It also falsely rejected a FLAT constant followed by some trailing items, which turned a valid script intoMalformedScriptWitnesses.Tests
PlutusDataDecoderParityTest: accept, reject and trailing-byte vectors, plus FLAT end-to-end cases. Every verdict is confirmed against plutusdecodeDatarunning on cborg 0.2.8.0.main, about 8.2k of every 30k were false accepts.MapDecodingFidelityTestvector (tag 1000 on a map) is removed, because plutus rejects it../gradlew cleanTest testledger-conformance133/0, anchor 15/15,appchain-anchor-onchain120/120script-evaluatorsIndependently reviewed (the reviewer ran its own 72 vectors through the oracle): approve. The trailing-byte design follows that review.
Note: Yano's own ledger-rules decoding of script constants has the same trailing-byte false reject, independent of julc. It's fixed separately in Yano.
🤖 Generated with Claude Code