Skip to content

feat(key-wallet-manager): add mutable-pair accessors + insert_wallet#685

Merged
QuantumExplorer merged 2 commits into
v0.42-devfrom
claude/xenodochial-mirzakhani-f73343
Apr 28, 2026
Merged

feat(key-wallet-manager): add mutable-pair accessors + insert_wallet#685
QuantumExplorer merged 2 commits into
v0.42-devfrom
claude/xenodochial-mirzakhani-f73343

Conversation

@QuantumExplorer
Copy link
Copy Markdown
Member

@QuantumExplorer QuantumExplorer commented Apr 24, 2026

Summary

Adds three accessors on WalletManager in key-wallet-manager/src/accessors.rs that exploit the split borrow between the independent wallets: BTreeMap<WalletId, Wallet> and wallet_infos: BTreeMap<WalletId, T> maps:

  • get_wallet_and_info_mut(&mut self, id) -> Option<(&Wallet, &mut T)> — for the common mutation pattern that reads wallet config (accounts, xpub) while writing info (UTXOs, balance, tx history).
  • get_wallet_mut_and_info_mut(&mut self, id) -> Option<(&mut Wallet, &mut T)> — needed when the Wallet itself mutates (e.g. Wallet::add_account during changeset replay / on-the-fly HD account derivation).
  • insert_wallet(&mut self, wallet, info) -> Result<WalletId, WalletError> — registers a pre-built (Wallet, T) pair. Errors with WalletError::WalletExists on duplicate and calls bump_structural_revision() on success. Enables restore paths that reconstruct a wallet from persistence without going through the mnemonic-based builder.

No unsafe, no refactor, no new error variants — WalletError::WalletExists, Wallet::compute_wallet_id(), and WalletManager::bump_structural_revision() already exist on this branch.

Test plan

  • cargo fmt --all --check clean
  • cargo clippy -p key-wallet-manager --all-targets -- -D warnings clean
  • cargo test -p key-wallet-manager — 40 tests pass including 4 new accessor tests:
    • insert_wallet_rejects_duplicate — dedup returns WalletExists(id)
    • get_wallet_and_info_mut_returns_none_then_some — None pre-insert, Some post-insert, mutation through &mut T persists
    • get_wallet_mut_and_info_mut_allows_split_borrow — compile-time proof that &mut Wallet (via get_bip44_account_mut) and &mut T (via set_name) coexist in one borrow scope
    • insert_wallet_bumps_monitor_revisionmonitor_revision() strictly increases past before + info.monitor_revision()

🤖 Generated with Claude Code

Summary by CodeRabbit

  • New Features

    • Added wallet insertion with automatic ID derivation and duplicate prevention.
    • Added safe accessor methods to retrieve wallet and associated info with controlled mutability (read+mut and mut+mut variants).
  • Tests

    • Added a test ensuring duplicate wallet insertion is rejected and the reported duplicate ID matches the original.

Adds three accessors on WalletManager that exploit the split borrow
between the independent `wallets` and `wallet_infos` maps:

- `get_wallet_and_info_mut` — `(&Wallet, &mut T)` for mutations that
  read wallet config while writing info (UTXOs, balance, tx history).
- `get_wallet_mut_and_info_mut` — `(&mut Wallet, &mut T)` for cases
  that need to mutate the wallet itself (e.g. idempotent re-derivation
  of HD accounts during changeset replay).
- `insert_wallet` — register a pre-built `(Wallet, T)` pair, returns
  `WalletExists` on duplicate and bumps `structural_revision` on
  success. Enables restore paths that reconstruct wallets from
  persistence without going through the mnemonic-based builder.

Unit tests cover dedup error, split-borrow mutation across both maps,
and the monitor-revision bump on insert.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented Apr 24, 2026

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 01c6c2fc-8d4a-4c2e-89af-9addb7984fca

📥 Commits

Reviewing files that changed from the base of the PR and between 99bbfda and 503e41a.

📒 Files selected for processing (1)
  • key-wallet-manager/src/accessors.rs
🚧 Files skipped from review as they are similar to previous changes (1)
  • key-wallet-manager/src/accessors.rs

📝 Walkthrough

Walkthrough

Three new methods are added to WalletManager<T>: get_wallet_and_info_mut (returns Option<(&Wallet, &mut T)>), get_wallet_mut_and_info_mut (returns Option<(&mut Wallet, &mut T)>), and insert_wallet (computes ID, rejects duplicates with WalletError::WalletExists, inserts into maps, and bumps structural revision).

Changes

Cohort / File(s) Summary
Wallet Manager APIs
key-wallet-manager/src/accessors.rs
Added three public methods: get_wallet_and_info_mut (immutable wallet + mutable info), get_wallet_mut_and_info_mut (mutable wallet + mutable info), and insert_wallet (compute WalletId, error on duplicate, insert into wallets and wallet_infos, bump structural revision). Added a test confirming duplicate insertion is rejected and the reported duplicate ID matches the original.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Poem

🐰 I hopped into code where wallets lie,

I paired a borrow and gave a try,
I guarded ids with watchful eyes,
I bumped the revision, to no surprise,
Duplicate thieves—out goes their prize!

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The PR title accurately summarizes the main changes: adding three mutable-pair accessors and an insert_wallet method to WalletManager.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch claude/xenodochial-mirzakhani-f73343

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.

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

🧹 Nitpick comments (2)
key-wallet-manager/src/accessors.rs (2)

316-337: Nit: assertion comment doesn't match the assertion.

The inline comment says "the delta must be >= 1", but the assert! uses a strict >, i.e. it requires delta > info_revision (equivalent to structural delta >= 1). The assertion is correct — just the comment is slightly misleading. Consider rewording to "so the structural delta must be >= 1, i.e. after > before + info_revision."

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@key-wallet-manager/src/accessors.rs` around lines 316 - 337, The inline
comment in the test function insert_wallet_bumps_monitor_revision is misleading:
it says "the delta must be >= 1" but the assertion uses a strict greater-than
(after > before + info_revision); update the comment near
manager.monitor_revision() / info.monitor_revision() to state "so the structural
delta must be >= 1, i.e. `after > before + info_revision`" (or similar wording)
so the comment matches the assertion semantics.

63-72: Optional: collapse duplicate lookup via Entry API.

contains_key followed by insert performs two B-tree traversals for the common (non-duplicate) case. Using BTreeMap::entry makes the uniqueness check and insertion a single traversal and expresses intent more directly.

♻️ Proposed refactor
     pub fn insert_wallet(&mut self, wallet: Wallet, info: T) -> Result<WalletId, WalletError> {
         let wallet_id = wallet.compute_wallet_id();
-        if self.wallets.contains_key(&wallet_id) {
-            return Err(WalletError::WalletExists(wallet_id));
-        }
-        self.wallets.insert(wallet_id, wallet);
+        match self.wallets.entry(wallet_id) {
+            std::collections::btree_map::Entry::Occupied(_) => {
+                return Err(WalletError::WalletExists(wallet_id));
+            }
+            std::collections::btree_map::Entry::Vacant(e) => {
+                e.insert(wallet);
+            }
+        }
         self.wallet_infos.insert(wallet_id, info);
         self.bump_structural_revision();
         Ok(wallet_id)
     }

Also worth noting: this method only guards against collisions in self.wallets. If — due to an earlier bug or partial failure — wallet_infos already contained an entry for wallet_id while wallets did not, the old info would be silently overwritten. In practice the two maps are expected to stay in lockstep, but a debug_assert!(!self.wallet_infos.contains_key(&wallet_id)) before the wallet_infos.insert would make that invariant explicit.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@key-wallet-manager/src/accessors.rs` around lines 63 - 72, Replace the
two-step contains_key + insert in insert_wallet with a single BTreeMap::entry
operation on self.wallets to perform uniqueness check and insert in one
traversal (refer to insert_wallet, WalletId, WalletError, self.wallets); after a
successful insertion, add debug_assert! to ensure self.wallet_infos does not
already contain the same wallet_id before inserting into self.wallet_infos and
then call bump_structural_revision() and return Ok(wallet_id).
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Nitpick comments:
In `@key-wallet-manager/src/accessors.rs`:
- Around line 316-337: The inline comment in the test function
insert_wallet_bumps_monitor_revision is misleading: it says "the delta must be
>= 1" but the assertion uses a strict greater-than (after > before +
info_revision); update the comment near manager.monitor_revision() /
info.monitor_revision() to state "so the structural delta must be >= 1, i.e.
`after > before + info_revision`" (or similar wording) so the comment matches
the assertion semantics.
- Around line 63-72: Replace the two-step contains_key + insert in insert_wallet
with a single BTreeMap::entry operation on self.wallets to perform uniqueness
check and insert in one traversal (refer to insert_wallet, WalletId,
WalletError, self.wallets); after a successful insertion, add debug_assert! to
ensure self.wallet_infos does not already contain the same wallet_id before
inserting into self.wallet_infos and then call bump_structural_revision() and
return Ok(wallet_id).

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: a5474659-a423-4dc1-a0df-ad2723c6e80a

📥 Commits

Reviewing files that changed from the base of the PR and between 0093278 and 99bbfda.

📒 Files selected for processing (1)
  • key-wallet-manager/src/accessors.rs

coderabbitai[bot]
coderabbitai Bot previously approved these changes Apr 24, 2026
@codecov
Copy link
Copy Markdown

codecov Bot commented Apr 24, 2026

Codecov Report

❌ Patch coverage is 53.33333% with 14 lines in your changes missing coverage. Please review.
✅ Project coverage is 70.21%. Comparing base (0093278) to head (503e41a).
⚠️ Report is 8 commits behind head on v0.42-dev.

Files with missing lines Patch % Lines
key-wallet-manager/src/accessors.rs 53.33% 14 Missing ⚠️
Additional details and impacted files
@@              Coverage Diff              @@
##           v0.42-dev     #685      +/-   ##
=============================================
- Coverage      70.22%   70.21%   -0.01%     
=============================================
  Files            319      319              
  Lines          66686    66937     +251     
=============================================
+ Hits           46830    47003     +173     
- Misses         19856    19934      +78     
Flag Coverage Δ
core 75.81% <ø> (ø)
ffi 44.40% <ø> (-0.78%) ⬇️
rpc 20.00% <ø> (ø)
spv 86.58% <ø> (+0.07%) ⬆️
wallet 69.05% <53.33%> (+0.25%) ⬆️
Files with missing lines Coverage Δ
key-wallet-manager/src/accessors.rs 54.03% <53.33%> (-7.84%) ⬇️

... and 46 files with indirect coverage changes

@github-actions github-actions Bot added the ready-for-review CodeRabbit has approved this PR label Apr 24, 2026
xdustinface
xdustinface previously approved these changes Apr 24, 2026
Comment thread key-wallet-manager/src/accessors.rs Outdated
Comment thread key-wallet-manager/src/accessors.rs Outdated
Comment thread key-wallet-manager/src/accessors.rs Outdated
Per ZocoLini's review on #685: the type system already proves the
mutable-borrow accessors return the right shape, and monitor_revision is
covered elsewhere. Keep insert_wallet_rejects_duplicate since it
exercises actual error-path logic.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@github-actions github-actions Bot removed the ready-for-review CodeRabbit has approved this PR label Apr 28, 2026
@QuantumExplorer QuantumExplorer merged commit da28aca into v0.42-dev Apr 28, 2026
37 of 38 checks passed
@QuantumExplorer QuantumExplorer deleted the claude/xenodochial-mirzakhani-f73343 branch April 28, 2026 04:35
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.

3 participants