Skip to content

fix: rename mainnet-fork override flag and apply leftover 0.4.9 review fixes#466

Merged
RetricSu merged 4 commits into
developfrom
agent/claude-bear/397fdf70
Jul 23, 2026
Merged

fix: rename mainnet-fork override flag and apply leftover 0.4.9 review fixes#466
RetricSu merged 4 commits into
developfrom
agent/claude-bear/397fdf70

Conversation

@humble-little-bear

Copy link
Copy Markdown
Collaborator

Closes #460
Closes #462

What

#460 — parameter naming: --allow-mainnet-replay-risk is renamed to --allow-external-key-on-mainnet-fork (CLI flag, option types, error messages, README, tests).

#462 — leftover review items from #461 (0.4.9): the PR was merged before the CodeRabbit review comments were addressed; this applies the still-valid ones:

  • Replay-safety enforcement (was warn-only): transfer-all, udt issue, udt destroy, and deploy now go through validateMainnetForkSigning and thread the returned fork boundary into the SDK, which rejects inputs created at or before the boundary via assertInputsCreatedAfter — mirroring transfer/deposit. The renamed --allow-external-key-on-mainnet-fork flag is now available on all four commands.
  • debug --tx-hash path traversal: the hash is validated as a 0x-prefixed 32-byte hex string before it is interpolated into cache paths.
  • Fork boundary race: the first-run flow only reads get_tip_block_number once the spawned CKB process is the RPC listener (the fork keeps the source chain's genesis hash, so genesis equality alone doesn't identify our node). Falls back to the genesis check where the listener can't be determined (Windows / no lsof).
  • Fork copy symlink escape: copySourceData rejects symlinked entries (top-level and nested) instead of silently copying data from outside the source directory.
  • xUDT type args: xUDT now accepts ≥ 32-byte args (owner lock hash + optional flags/extension); SUDT stays exactly 32 bytes; odd-length hex is rejected for both.
  • UDT scan budget: SUDT and xUDT scans each get their own maxCells budget so a large SUDT set can't silently drop xUDT balances.
  • Smaller items: readSettings fallbacks return deep clones of the defaults; config set try/catch narrowed so I/O errors aren't mislabeled as validation failures (and no doubled prefix); devnet config rethrows the original InitializationError; process command-line lookup uses execFile with arg arrays; ckb-tui download timeout constants aligned and cross-device (EXDEV) installs handled; README TOC gains the missing step-7 fork entry; unused test binding removed.

New/updated tests cover the flag rename, boundary threading for transfer-all/udt issue/udt destroy, tx-hash rejection, symlink rejection, and extended xUDT args. pnpm typecheck, pnpm lint, pnpm test (25 suites) and pnpm build all pass.

Changeset included (patch).

…w fixes

- Rename --allow-mainnet-replay-risk to --allow-external-key-on-mainnet-fork (#460)
- Enforce the Mainnet-fork replay guard in transfer-all, udt issue/destroy,
  and deploy, threading the fork boundary into input selection (#462)
- Validate --tx-hash before it is used in debug cache paths
- Only read the fork boundary after the spawned process binds the RPC port
- Reject symlinked entries when copying fork source chain data
- Accept extended xUDT type args (owner hash + flags/extension)
- Per-kind UDT scan budgets, deep-cloned settings fallbacks, accurate
  config-set errors, preserved devnet-config error, execFile process lookup,
  aligned ckb-tui download timeouts, EXDEV-safe install, README TOC entry

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@coderabbitai

coderabbitai Bot commented Jul 23, 2026

Copy link
Copy Markdown

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 76baa5e8-8ea4-41b3-b03d-670ced107289

📥 Commits

Reviewing files that changed from the base of the PR and between cc3928b and 2038996.

📒 Files selected for processing (1)
  • tests/node-listener.test.ts
🚧 Files skipped from review as they are similar to previous changes (1)
  • tests/node-listener.test.ts

📝 Walkthrough

Summary by CodeRabbit

  • New Features
    • Added --allow-external-key-on-mainnet-fork across deploy, transfer/sweep, and UDT commands; --allow-mainnet-replay-risk is now a hidden deprecated alias.
    • Added README step: “Fork Mainnet/Testnet Into Your Devnet.”
    • xUDT type arguments can include more extension data (beyond the prior limit).
  • Bug Fixes
    • Mainnet-fork replay guard now fails closed as a hard rejection with a computed boundary applied to transaction building/execution.
    • Debug tx-hash validation now rejects non-0x 32-byte hex early.
    • Fork data copying now blocks symlinked entries.
  • Other Improvements
    • Safer settings default handling and improved error preservation; more robust daemon probing and installer behavior.

Walkthrough

The PR renames the external-key mainnet-fork override, enforces replay guards across transaction and deployment flows, validates transaction and UDT inputs, hardens fork-data copying and devnet startup, preserves configuration errors, and improves ckb-tui installation behavior.

Changes

Mainnet fork safety and validation

Layer / File(s) Summary
Fork guard propagation
src/cli.ts, src/cmd/*, src/deploy/..., src/sdk/ckb.ts, src/util/fork-safety.ts, tests/*
The new external-key flag is wired through deploy, transfer, transfer-all, and UDT commands; validated fork boundaries reach SDK transaction builders before submission.
Input and fork-data validation
src/util/validator.ts, src/cmd/debug.ts, src/devnet/fork.ts, src/cfg/setting.ts, tests/*
Transaction hashes and UDT type arguments receive stricter validation, symlinks are rejected during fork-data copying, settings defaults are cloned, and balance scan budgets are isolated per UDT kind.

Runtime reliability

Layer / File(s) Summary
Devnet startup and process inspection
src/cmd/node.ts, tests/node-command.test.ts, tests/node-listener.test.ts
Fork initialization verifies the spawned process owns the RPC port before reading fork state, and process lookups use execFile.
Configuration errors and installation fallback
src/cmd/config.ts, src/cmd/devnet-config.ts, src/tools/ckb-tui.ts
Configuration errors retain their original context, while ckb-tui uses the configured download timeout and handles cross-device moves.

Estimated code review effort: 4 (Complex) | ~45 minutes

Sequence Diagram(s)

sequenceDiagram
  participant CLI
  participant Command
  participant ForkSafety
  participant SDK
  participant CKB
  CLI->>Command: invoke fork-sensitive operation
  Command->>ForkSafety: validate signing key and fork state
  ForkSafety-->>Command: return input rejection boundary
  Command->>SDK: pass rejection boundary
  SDK->>CKB: assert input origins and submit transaction
Loading

Possibly related PRs

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 14.29% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly summarizes the flag rename and remaining 0.4.9 review fixes.
Description check ✅ Passed The description is directly related to the implemented flag rename and review-fix work.
Linked Issues check ✅ Passed The flag rename and the remaining 0.4.9 review fixes in #460 and #462 are implemented across CLI, SDK, docs, and tests.
Out of Scope Changes check ✅ Passed The changes stay within the requested flag rename and review-fix cleanup, with tests and docs supporting those updates.

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

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 4

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In @.changeset/tidy-mugs-repair.md:
- Around line 2-5: Update the CLI option rename described in the changeset so
--allow-mainnet-replay-risk remains supported as a deprecated alias for
--allow-external-key-on-mainnet-fork, or classify the removal as a breaking
release instead of a patch. Ensure existing scripts continue to function while
the new flag is adopted.

In `@src/cmd/node.ts`:
- Around line 193-207: Update isProcessListeningOnPort so lsof probe failures
other than a missing executable return null, representing an indeterminate
ownership check rather than false. Preserve true for a successful
listening-process match and ensure callers can fall back to weaker signals
whenever the inspection cannot reliably run.

In `@src/devnet/fork.ts`:
- Around line 272-282: Validate the sourceData root with assertNoSymlink before
readdirSync enumerates its contents, then retain the existing per-entry and
recursive filter checks around fs.cpSync. This ensures a symlinked data
directory is rejected before traversal.

In `@src/tools/ckb-tui.ts`:
- Around line 187-199: Update the EXDEV fallback in the installation flow around
the renameSync call to copy extractedBinary to a unique staging file inside
binDir, then atomically rename that staged file to this.binaryPath and remove
the original temporary binary. Ensure cleanup handles the staging file
appropriately while preserving the existing direct rename path for
same-filesystem moves.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: ca894959-bcbe-482d-8c63-1a91f10372e8

📥 Commits

Reviewing files that changed from the base of the PR and between b4816d4 and e6d9a7c.

📒 Files selected for processing (25)
  • .changeset/tidy-mugs-repair.md
  • README.md
  • src/cfg/setting.ts
  • src/cli.ts
  • src/cmd/config.ts
  • src/cmd/debug.ts
  • src/cmd/deploy.ts
  • src/cmd/devnet-config.ts
  • src/cmd/node.ts
  • src/cmd/transfer-all.ts
  • src/cmd/transfer.ts
  • src/cmd/udt.ts
  • src/deploy/index.ts
  • src/devnet/fork.ts
  • src/sdk/ckb.ts
  • src/tools/ckb-tui.ts
  • src/util/fork-safety.ts
  • src/util/validator.ts
  • tests/debug-tx-file.test.ts
  • tests/devnet-fork.test.ts
  • tests/fork-safety.test.ts
  • tests/node-command.test.ts
  • tests/transfer-all.test.ts
  • tests/udt.test.ts
  • tests/validator.test.ts

Comment thread .changeset/tidy-mugs-repair.md Outdated
Comment thread src/cmd/node.ts
Comment thread src/devnet/fork.ts
Comment thread src/tools/ckb-tui.ts
- Keep --allow-mainnet-replay-risk as a hidden deprecated alias folded into
  --allow-external-key-on-mainnet-fork (with a deprecation warning) so 0.4.9
  scripts keep working under a patch release
- Treat lsof probe failures with stderr output as indeterminate (null)
  instead of "not listening"; only an empty-stderr exit is a genuine
  no-match, so permission errors fall back to the weaker genesis signal
- Reject a symlinked data root before enumerating source chain data
- Stage cross-device ckb-tui installs inside binDir and publish with an
  atomic rename, so concurrent installs never see a truncated binary

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🧹 Nitpick comments (1)
tests/node-listener.test.ts (1)

48-50: 🎯 Functional Correctness | 🔵 Trivial | ⚡ Quick win

Assert the exact lsof invocation.

These tests verify outcome mapping but never verify the PID/port filters and LISTEN selector required by src/cmd/node.ts:198-211. A wrong command could still leave the suite green and allow readiness checks to inspect the wrong process.

Proposed test assertion
    expect(isProcessListeningOnPort(1234, 8114)).toBe(true);
+   expect(mockExecFileSync).toHaveBeenCalledWith(
+     'lsof',
+     ['-a', '-p', '1234', '-iTCP:8114', '-sTCP:LISTEN'],
+     { stdio: ['ignore', 'pipe', 'pipe'] },
+   );
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@tests/node-listener.test.ts` around lines 48 - 50, Update the
isProcessListeningOnPort test cases to assert mockExecFileSync receives the
exact lsof executable, PID/port filters, and LISTEN selector used by the
implementation. Cover the successful invocation assertion alongside the existing
true outcome, and apply the same command verification consistently to relevant
result-mapping tests.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@src/cmd/node.ts`:
- Around line 201-209: Update the synchronous lsof probe in
clearForkFirstRunWhenNodeUp to pass a short timeout option to execFileSync. In
its catch handling, detect timeout failures and return null so the existing
fallback path proceeds, while preserving the current ENOENT and stderr-based
behavior for other failures.

---

Nitpick comments:
In `@tests/node-listener.test.ts`:
- Around line 48-50: Update the isProcessListeningOnPort test cases to assert
mockExecFileSync receives the exact lsof executable, PID/port filters, and
LISTEN selector used by the implementation. Cover the successful invocation
assertion alongside the existing true outcome, and apply the same command
verification consistently to relevant result-mapping tests.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 8a7e43ce-487d-4583-8d3c-90efec99fbfb

📥 Commits

Reviewing files that changed from the base of the PR and between e6d9a7c and a4bab8f.

📒 Files selected for processing (11)
  • .changeset/tidy-mugs-repair.md
  • README.md
  • src/cli.ts
  • src/cmd/node.ts
  • src/devnet/fork.ts
  • src/tools/ckb-tui.ts
  • src/util/fork-safety.ts
  • tests/cli-mainnet-fork-flag.test.ts
  • tests/devnet-fork.test.ts
  • tests/fork-safety.test.ts
  • tests/node-listener.test.ts
🚧 Files skipped from review as they are similar to previous changes (2)
  • .changeset/tidy-mugs-repair.md
  • README.md

Comment thread src/cmd/node.ts
A hung lsof would block execFileSync (and with it daemon startup)
indefinitely, and its empty-stderr timeout error would be misread as a
genuine no-match. Cap the probe at 5s and classify ETIMEDOUT as
indeterminate (null) so the genesis fallback proceeds.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@tests/node-listener.test.ts`:
- Around line 81-88: Update the timeout assertion in the “bounds the lsof probe
with a timeout” test to require exactly 5000 milliseconds instead of accepting
any number, while preserving the existing lsof arguments and invocation checks.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 55e36f0b-5f50-4e4e-9018-57844c45db9d

📥 Commits

Reviewing files that changed from the base of the PR and between a4bab8f and cc3928b.

📒 Files selected for processing (2)
  • src/cmd/node.ts
  • tests/node-listener.test.ts

Comment thread tests/node-listener.test.ts
isProcessListeningOnPort short-circuits to null on win32, so the lsof
outcome-mapping tests failed on the Windows CI runner (mock never
called). Force a unix platform for the lsof-probing cases, cover the
win32 short-circuit explicitly, and pin the probe timeout to exactly
5000 ms per review feedback.
@RetricSu
RetricSu merged commit 45b0e98 into develop Jul 23, 2026
7 checks passed
@RetricSu
RetricSu deleted the agent/claude-bear/397fdf70 branch July 23, 2026 13:20
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.

0.4.9 review todo --allow-external-key-on-mainnet-fork

3 participants