fix(deps): pin @kynesyslabs/demosdk via overrides to collapse nested 2.12.2 install#869
Conversation
…2.12.2 install
Repro: the SDK 4.0.0 published with a self-dep on
`@kynesyslabs/demosdk@^2.8.22`, which made bun install a second copy
of the SDK under
`node_modules/@kynesyslabs/demosdk/node_modules/@kynesyslabs/demosdk@2.12.2`
alongside the top-level 4.0.0. Any module that resolved through the
nested copy saw the old API surface — the 2.12.2 post-fork serializer
doesn't walk `gcr_edits[].amount`, which produced a different
canonical hash than the SDK that signed the tx, surfacing on the node
as `GCREdit mismatch` on every post-fork transfer.
Override pins `@kynesyslabs/demosdk: 4.0.0` across the whole tree so
the nested copy collapses to a single installation:
before:
node_modules/@kynesyslabs/demosdk/ ← 4.0.0
node_modules/@kynesyslabs/demosdk/node_modules/
@kynesyslabs/demosdk/ ← 2.12.2
after:
node_modules/@kynesyslabs/demosdk/ ← 4.0.0
(nothing nested)
Verified by `rm -rf node_modules/@kynesyslabs && bun install`: a single
`@kynesyslabs/demosdk/package.json` at the expected version with no
nested copy.
Companion sdks PR (#88, fix/remove-self-dep) drops the self-dep and
bumps to 4.0.1, after which this override can bump too — until then
4.0.0 + override is the safe combination.
Qodo reviews are paused for this user.Troubleshooting steps vary by plan Learn more → On a Teams plan? Using GitHub Enterprise Server, GitLab Self-Managed, or Bitbucket Data Center? |
|
Warning Review limit reached
More reviews will be available in 44 minutes and 54 seconds. Learn how PR review limits work. Your organization has run out of usage credits. Purchase more in the billing tab. ⌛ How to resolve this issue?After more reviews become available, a review can be triggered using the We recommend that you space out your commits to avoid hitting the rate limit. 🚦 How do rate limits work?CodeRabbit enforces hourly rate limits for each developer per organization. Our paid plans include higher PR review limits than trial, open-source, and free plans. In all cases, reviews become available again over time. During sustained high-volume PR review activity, CodeRabbit may temporarily slow when the next review becomes available. Please see our Fair Usage Limits Policy for further information. ✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
Greptile SummaryThis PR pins
Confidence Score: 4/5The override correctly collapses the duplicate SDK install and is consistent with the direct dependency for now, but the exact-version pin in overrides will silently override any future dependencies bump from upgrade_sdk, making it easy to deploy with the wrong SDK version without noticing. The overrides exact-version entry will win over any dependencies bump made by bun run upgrade_sdk, silently keeping the resolved version at 4.0.0 even after a developer believes they've upgraded. This is a real footgun on a codepath (the upgrade_sdk script) that exists specifically to keep the SDK current. package.json — the interaction between overrides["@kynesyslabs/demosdk"] and the upgrade_sdk script needs attention before this is merged. Important Files Changed
Flowchart%%{init: {'theme': 'neutral'}}%%
flowchart TD
A[bun install] --> B{overrides entry present?}
B -- Yes --> C[Resolve ALL instances of @kynesyslabs/demosdk to 4.0.0]
B -- No --> D[Resolve direct dep to 4.0.0 / Resolve SDK self-dep ^2.8.22 to 2.12.2]
D --> E[nested 2.12.2 copy installed]
E --> F[GCREdit mismatch on node]
C --> G[Single copy at 4.0.0]
G --> H[Canonical hash matches signed tx]
I[bun run upgrade_sdk] --> J[dependencies bumped to 4.0.1]
J --> K{overrides still 4.0.0?}
K -- Yes --> L[bun resolves to 4.0.0 on disk — silent downgrade]
K -- Also bumped --> M[Consistent single copy at 4.0.1]
Reviews (1): Last reviewed commit: "fix(deps): pin @kynesyslabs/demosdk via ..." | Re-trigger Greptile |
| "fast-xml-parser": ">=5.3.4", | ||
| "validator": ">=13.15.20" | ||
| "validator": ">=13.15.20", | ||
| "@kynesyslabs/demosdk": "4.0.0" |
There was a problem hiding this comment.
upgrade_sdk script will silently downgrade after an SDK bump
In bun, an overrides entry with an exact version applies to all instances of the package — including the direct dependency. When a developer runs bun run upgrade_sdk (line 24), bun bumps the dependencies["@kynesyslabs/demosdk"] entry to the latest version, but leaves overrides["@kynesyslabs/demosdk"] at "4.0.0". The override wins at install time, so the resolved version on disk stays at 4.0.0 even though dependencies now reads a higher version. The node silently runs the old SDK, re-introducing the very hash mismatch this PR is fixing, with no error at install time to indicate what happened. A comment pointing to the companion PR and a reminder to bump the override in lockstep would prevent this.
…ion canary (#870) Two diagnostic-only log lines so the dev.node2 mystery ("source has fix #867+#869, container reports the right SHA, mismatch still happens") becomes traceable from the log stream alone: 1) SYMMETRIC-NORMALISE-V2 canary — distinctive marker proves the running binary actually executed the post-PR-#867 branch. Grep for the literal string on the host; missing = runtime is using stale bytes despite the SHA. 2) Mismatch dump — when the hash compare fails, emit three JSON blobs back-to-back: - normalisedTxEdits (what tx-side hash sees) - normalisedRegen (what regen-side hash sees) - tx.content.gcr_edits raw (pre-normalisation) so we can eyeball-diff the exact field that diverges instead of guessing from the truncated hashes. Pure logging — no consensus / validation behaviour change. Strip after the root cause is found. Co-authored-by: tcsenpai <tcsenpai@discus.sh>
…ion so applyGasFeeSeparation prepends don't break the hash compare (#871) Root cause of the dev.node2 GCREdit mismatch that survived PRs #861/#867/#869: confirmTransaction runs `applyGasFeeSeparation` when the gasFeeSeparation fork is active, which PREPENDS node-computed fee edits onto `tx.content.gcr_edits` in place. The hash comparison ran AFTER that mutation, so: tx.content.gcr_edits (mutated): [fee_a, fee_b, ..., subtract, add, gas, nonce] GCRGeneration.generate(tx): [subtract, add, gas, nonce] The compare was diverging by exactly the prepended fee edits — a structural mismatch the SDK has no way to predict because the fee distribution is the validator's computation, not the signer's. dev.node2 reproduced and the local devnet did NOT because the local devnet boots with `gasFeeSeparation.activationHeight: null` → `applyGasFeeSeparation` is gated off → no prepend → the (already shipped) #861/#867 normalisation was sufficient. Fix: snapshot `tx.content.gcr_edits` via structured clone BEFORE calling `confirmTransaction`, then run the hash compare against the snapshot instead of the mutated array. The invariant we want to verify is "did the SDK ship the same edits GCRGeneration would regenerate?" — that's what the snapshot captures. Fee edits live downstream of this check and become part of the signed validity data via the existing `signValidityData` flow. Verified by tracing call sites: - applyGasFeeSeparation.ts:187 mutates tx.content.gcr_edits in place - validateTransaction.ts:133 calls it inside confirmTransaction - endpointValidation.ts:35 calls confirmTransaction, line ~42 was then reading the already-mutated tx.content.gcr_edits Manual repro from earlier in the session: BROADCAST=1 bun transfer_10pct.mjs against dev.node2 returned `valid: false` / "GCREdit mismatch" on every attempt despite the source on disk being correct (post-#867). Tracing showed regen produced a constant `16f9495100b98…` hash (the SDK-shipped 4-edit set) while tx-side hash varied per run — and the varying part was the SHA-256 of the prepended fee edits, whose contents depend on per-block fee state. Co-authored-by: tcsenpai <tcsenpai@discus.sh>
Repro
SDK 4.0.0 ships with a self-dep on
@kynesyslabs/demosdk@^2.8.22. bun obediently installs a SECOND copy nested:Any module resolution that lands on the nested copy sees the OLD API surface. The 2.12.2 post-fork serializer does NOT walk
gcr_edits[].amount, which produces a different canonical hash than the SDK that signed the tx — surfaces on the node asGCREdit mismatchon every post-fork transfer.Fix
overrides["@kynesyslabs/demosdk"]: "4.0.0"forces single-version install across the whole tree. Nested copy collapses.Verified by
rm -rf node_modules/@kynesyslabs && bun install: a single@kynesyslabs/demosdk/package.jsonat 4.0.0, no nested copy.Companion
sdks PR kynesyslabs/sdks#88 drops the self-dep and bumps SDK to 4.0.1. Once that's published, this override can bump to
4.0.1too. Until then, 4.0.0 + override is the safe combination.Test plan
bun installfrom clean tree: single SDK installedbun transfer_10pct.mjs: expectvalid: trueconfirm