Skip to content

fix(deps): pin @kynesyslabs/demosdk via overrides to collapse nested 2.12.2 install#869

Merged
tcsenpai merged 1 commit into
stabilisationfrom
fix/sdk-override-pin
May 26, 2026
Merged

fix(deps): pin @kynesyslabs/demosdk via overrides to collapse nested 2.12.2 install#869
tcsenpai merged 1 commit into
stabilisationfrom
fix/sdk-override-pin

Conversation

@tcsenpai
Copy link
Copy Markdown
Contributor

Repro

SDK 4.0.0 ships with a self-dep on @kynesyslabs/demosdk@^2.8.22. bun obediently installs a SECOND copy nested:

node_modules/@kynesyslabs/demosdk/                              ← 4.0.0
node_modules/@kynesyslabs/demosdk/node_modules/
                                  @kynesyslabs/demosdk/         ← 2.12.2

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 as GCREdit mismatch on 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.json at 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.1 too. Until then, 4.0.0 + override is the safe combination.

Test plan

  • bun install from clean tree: single SDK installed
  • Rebuild dev.node2 with this PR + retry bun transfer_10pct.mjs: expect valid: true confirm

…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-code-review
Copy link
Copy Markdown
Contributor

Qodo reviews are paused for this user.

Troubleshooting steps vary by plan Learn more →

On a Teams plan?
Reviews resume once this user has a paid seat and their Git account is linked in Qodo.
Link Git account →

Using GitHub Enterprise Server, GitLab Self-Managed, or Bitbucket Data Center?
These require an Enterprise plan - Contact us
Contact us →

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented May 26, 2026

Warning

Review limit reached

@tcsenpai, we couldn't start this review because you've reached your PR review rate limit.

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 @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

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.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 2def5426-891c-407e-8ba8-b165c239db58

📥 Commits

Reviewing files that changed from the base of the PR and between 335c87c and 06064d7.

📒 Files selected for processing (1)
  • package.json
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch fix/sdk-override-pin

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.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@tcsenpai tcsenpai merged commit f1a53d5 into stabilisation May 26, 2026
3 checks passed
@tcsenpai tcsenpai deleted the fix/sdk-override-pin branch May 26, 2026 15:40
@greptile-apps
Copy link
Copy Markdown

greptile-apps Bot commented May 26, 2026

Greptile Summary

This PR pins @kynesyslabs/demosdk to 4.0.0 in the overrides section of package.json to prevent bun from installing a nested 2.12.2 copy (due to SDK 4.0.0's self-dep on ^2.8.22), which caused GCREdit mismatch errors on post-fork transfers because the nested copy uses an older serializer.

  • Adds \"@kynesyslabs/demosdk\": \"4.0.0\" to overrides, collapsing duplicate SDK instances to a single copy at the version already pinned in dependencies.
  • The fix is explicitly scoped as a temporary measure until companion sdks PR Push HTTP as main and deprecate WS #88 (dropping the self-dep, bumping to 4.0.1) is published, at which point both dependencies and overrides should be bumped together.

Confidence Score: 4/5

The 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

Filename Overview
package.json Adds @kynesyslabs/demosdk: "4.0.0" to overrides to collapse the nested 2.12.2 install caused by SDK 4.0.0's self-dep; the exact-version pin will silently downgrade the direct dep if upgrade_sdk is run without updating the override.

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]
Loading

Reviews (1): Last reviewed commit: "fix(deps): pin @kynesyslabs/demosdk via ..." | Re-trigger Greptile

Comment thread package.json
"fast-xml-parser": ">=5.3.4",
"validator": ">=13.15.20"
"validator": ">=13.15.20",
"@kynesyslabs/demosdk": "4.0.0"
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 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.

tcsenpai added a commit that referenced this pull request May 26, 2026
…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>
tcsenpai added a commit that referenced this pull request May 26, 2026
…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>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant