CBOR: repeated map keys are silently collapsed, where the ledger either rejects them or keeps every pair
维护者通常 1 天内回复
还没有人认领这个 Issue。
评估
- 难度
- 4/5
- 预计耗时
- 3-5 天
- 新手友好度
- 58/100
- Issue 类型
- 缺陷
- 描述清晰度
- 描述清楚
- 活跃度
- 活跃
- 技术栈
- typescript
- 领域
- data
调研方向
Start in packages/evolution/src/CBOR.ts at decodeMapAt and the captured-format map encoder; trace the transaction body, metadata-label, and metadatum paths. Run the regression cases through Transaction.fromCBORHex and compare re-encoded bytes, including controls and the multi-assets, withdrawals, and mint cases. Done means ledger-record and Map duplicates fail with a key-naming error while metadatum pairs round-trip byte-identically.
由索引模型根据 Issue 内容生成。
描述
Summary
The CBOR map decoder stores entries in a JS Map, so a repeated key keeps only its last value, and no error is raised. On re-encode the captured key order replays every key, so the output repeats the last value:
body a4 ... 02 00 02 0a → a4 ... 02 0a 02 0a (fee 0 lost)
label a2 00 01 00 02 → a2 00 02 00 02 ({0: 1} lost)
datum a2 01 01 01 02 → a2 01 02 01 02 ({1: 1} lost)
The ledger treats repeated keys in two different ways, so a single rule at the CBOR layer cannot be right:
| Where | Ledger | SDK today | Should |
|---|---|---|---|
| transaction body, witness set | reject: SparseKeyed decoders fail on a repeated field (Coders.hs L565-569, duplicateKey L634-640; Conway/TxBody.hs L183, Alonzo/TxWits.hs L609) |
accepts, rewrites | reject on decode |
metadata labels and other Map fields |
reject from protocol version 9: decodeMap uses decodeMapLikeEnforceNoDuplicates (Decoder.hs L748-753, L785-789) |
accepts, rewrites | reject on decode |
| metadatum map values | keep every pair: Metadatum Map is a list of pairs (Metadata.hs L161-172) |
drops the earlier pair | keep every pair |
| Plutus data maps | keep every pair: Map [(Data, Data)] (plutus Data.hs L44, L277-283) |
drops the earlier pair | tracked in #397 |
Affected
packages/evolution/src/CBOR.ts
decodeMapAt(L1973-2035):map.set(k, v)overwrites a repeated key; the capturedkeyOrderstill records both- map encode with a captured format (L1496-1525) replays every
keyOrderentry, each with the surviving value
Every schema built on this decoder inherits the behavior. Tested here: the transaction body, metadata labels and metadatum values. Multi-assets, withdrawals and mint go through the same ledger decodeMap, but were not tested, so the fix should add one case for each.
Fix
Decide per schema, following the ledger:
- ledger records and
Mapfields: reject a repeated key when decoding, with an error that names the key - metadatum map values: keep every pair in order, so decode then encode returns the same pairs
The Plutus data side is #397, and it needs the same answer as metadatum values. The devnet accepted {1: 1, 1: 2} as an inline datum and rejected the SDK's rewrite with 3100, so rejecting on decode would refuse valid on-chain datums.
Regression test
Oracle is the node.
- body
a4 00 [inputs] 01 [outputs] 02 00 02 0a: before fix, decodes and re-encodes as02 0a 02 0a; after fix,Transaction.fromCBORHexfails with a duplicate key error - metadata
a2 00 01 00 02(label 0 twice): same, rejected after fix - metadatum
a1 00 a2 01 01 01 02: before fix, written back asa1 00 a2 01 02 01 02; after fix, byte-identical - control: maps without repeated keys are unchanged
Devnet, raw submission through Ogmios:
- body with the fee key twice: node rejects as malformed; the SDK decodes it
- metadata with label 0 twice: node rejects as malformed; the SDK decodes it
- metadatum
{1: 1, 1: 2}under label 0: original accepted; afteraddVKeyWitnessesHex, rejected with 3107 metadata hash mismatch
Must FAIL on main today and PASS after the fix.
Reference
#397 covers the Plutus data side. #531 asks for rejecting repeated keys on decode before the signing fix hashes original bytes.
- 主要语言
- TypeScript
- 星标
- 22
- 派生
- 35
- 平均合并
- 19 小时 56 分钟
- 30 天内合并 PR
- 58
环境准备
- 没有 Dockerfile 或 Docker Compose 文件
- 没有 Pull Request 模板
- 阅读贡献指南
从这里开始
- 先读完整个 Issue,再读项目的贡献指南。
- 在 Issue 下留言说明你要接手 —— 这能避免两个人做同样的事。
- Fork 仓库,在一个分支上完成修改。
- 提交 Pull Request,并在描述里引用这个 Issue 编号。
IntersectMBO/evolution-sdk 的其他 Issue
-
bug
难度 2/5 1-3 小时 新手友好度 79/100
IntersectMBO/evolution-sdk#694 ·
维护者通常 1 天内回复
-
bug
难度 2/5 1-3 小时 新手友好度 84/100
IntersectMBO/evolution-sdk#559 ·
维护者通常 1 天内回复
-
enhancement
难度 2/5 1-3 小时 新手友好度 72/100
IntersectMBO/evolution-sdk#557 ·
维护者通常 1 天内回复
-
dependabot: remove stale @types/bip39 entries可能已有人在做 @Kshot3000 于 5 天前认领。 未关闭dependencies good first issue
难度 1/5 1 小时以内 新手友好度 93/100
IntersectMBO/evolution-sdk#541 ·
维护者通常 1 天内回复
-
txBuilder: committee cert redeemers are never resolved to a certificate index可能已有人在做 @Kshot3000 于 5 天前认领。 未关闭
难度 2/5 1-3 小时 新手友好度 80/100
IntersectMBO/evolution-sdk#518 ·
维护者通常 1 天内回复
查看 IntersectMBO/evolution-sdk 的全部 Issue
相似的 Issue
-
area:editor bug issue-form:bug P0 platform:windows review: low
难度 2/5 1-3 小时 新手友好度 64/100
1lck/Lithe-IDEA#1388 ·
维护者通常 1 天内回复
-
fix(api): isToolAuditEnabled swallows database read errors on auditToolOperations without logging未关闭area: backend bug priority: low
难度 2/5 1-3 小时 新手友好度 82/100
snapotter-hq/SnapOtter#3238 ·
维护者通常 1 天内回复
-
rig up --plan times out after 5 s and reports an UNKNOWN outcome while the daemon completes the plan未关闭
难度 2/5 1-3 小时 新手友好度 82/100
维护者通常 1 天内回复
-
难度 2/5 1-3 小时 新手友好度 72/100
modelcontextprotocol/servers#5216 ·
维护者通常 1 天内回复
-
难度 2/5 1-3 小时 新手友好度 76/100
维护者通常 1 天内回复