Skip to content

refactor(key-wallet): split ManagedCoreAccount into funds + keys variants#711

Open
QuantumExplorer wants to merge 3 commits intov0.42-devfrom
claude/adoring-booth-151626
Open

refactor(key-wallet): split ManagedCoreAccount into funds + keys variants#711
QuantumExplorer wants to merge 3 commits intov0.42-devfrom
claude/adoring-booth-151626

Conversation

@QuantumExplorer
Copy link
Copy Markdown
Member

@QuantumExplorer QuantumExplorer commented May 3, 2026

Summary

Structural refactor of key-wallet's managed-account types in preparation for distinguishing accounts that hold and spend funds from accounts that exist only to derive special-purpose keys.

  • Moved the existing ManagedCoreAccount struct out of managed_account/mod.rs into a dedicated managed_core_funds_account.rs and renamed it to ManagedCoreFundsAccount.
  • Added a sibling ManagedCoreKeysAccount in managed_core_keys_account.rs that mirrors the funds variant but omits balance, utxos, and spent_outpoints. Intended for accounts that primarily derive keys for special-purpose flows (identity registration, asset locks, masternode provider keys).
  • mod.rs is now a thin module file containing only pub mod declarations and re-exports.

Scope

This PR is purely structural — no behavior change.

  • ManagedAccountCollection continues to store ManagedCoreFundsAccount for every field. Wiring ManagedCoreKeysAccount into the identity / asset-lock / provider fields (and the resulting trait/accessor/transaction-checking changes) is queued for a follow-up PR.
  • The C ABI is preserved: the FFI types (FFIManagedCoreAccount, FFIManagedCoreAccountResult, FFIManagedCoreAccountCollection) and the managed_core_account_* C function names are unchanged. They now wrap the renamed Rust struct internally — invisible to FFI consumers.
  • ManagedCoreAccountManagedCoreFundsAccount rename is applied across key-wallet, key-wallet-ffi, key-wallet-manager, dash-spv, dash-spv-ffi, plus the README / CLAUDE.md / IMPLEMENTATION_SUMMARY.md doc files in key-wallet.

Test plan

  • cargo check --workspace --all-targets — clean
  • cargo test -p key-wallet --lib — 461 passed, 0 failed
  • CI passes on the remaining workspace test suites

🤖 Generated with Claude Code

Summary by CodeRabbit

  • Refactor

    • Account management system reorganized into separate fund-tracking and key-derivation account types.
    • Updated underlying account structure implementations to improve code organization.
  • Documentation

    • Updated guides and README with new account management patterns and examples.

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented May 3, 2026

Warning

Rate limit exceeded

@QuantumExplorer has exceeded the limit for the number of commits that can be reviewed per hour. Please wait 58 minutes and 54 seconds before requesting another review.

To keep reviews running without waiting, you can enable usage-based add-on for your organization. This allows additional reviews beyond the hourly cap. Account admins can enable it under billing.

⌛ How to resolve this issue?

After the wait time has elapsed, 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 have higher rate limits than the trial, open-source and free plans. In all cases, we re-allow further reviews after a brief timeout.

Please see our FAQ for further information.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: aa331801-7329-4a55-8e52-b86c7d40d9c6

📥 Commits

Reviewing files that changed from the base of the PR and between 2f1ea9e and 425bc19.

📒 Files selected for processing (23)
  • dash-spv/src/sync/mempool/sync_manager.rs
  • key-wallet-ffi/src/address_pool.rs
  • key-wallet-ffi/src/managed_account.rs
  • key-wallet-ffi/src/managed_wallet.rs
  • key-wallet-ffi/src/utxo_tests.rs
  • key-wallet/CLAUDE.md
  • key-wallet/IMPLEMENTATION_SUMMARY.md
  • key-wallet/README.md
  • key-wallet/src/account/mod.rs
  • key-wallet/src/managed_account/managed_account_collection.rs
  • key-wallet/src/managed_account/managed_core_funds_account.rs
  • key-wallet/src/managed_account/managed_core_keys_account.rs
  • key-wallet/src/managed_account/managed_platform_account.rs
  • key-wallet/src/managed_account/mod.rs
  • key-wallet/src/test_utils/account.rs
  • key-wallet/src/test_utils/wallet.rs
  • key-wallet/src/tests/balance_tests.rs
  • key-wallet/src/tests/spent_outpoints_tests.rs
  • key-wallet/src/transaction_checking/account_checker.rs
  • key-wallet/src/transaction_checking/wallet_checker.rs
  • key-wallet/src/wallet/managed_wallet_info/asset_lock_builder.rs
  • key-wallet/src/wallet/managed_wallet_info/helpers.rs
  • key-wallet/src/wallet/managed_wallet_info/managed_accounts.rs
📝 Walkthrough

Walkthrough

This PR refactors the monolithic ManagedCoreAccount into two specialized managed-account types: ManagedCoreFundsAccount (full UTXO/balance/transaction tracking) and ManagedCoreKeysAccount (lightweight address/key derivation only). All dependent code—FFI bindings, collections, helpers, tests, and documentation—is systematically updated to use ManagedCoreFundsAccount for core wallet operations.

Changes

Account Type Refactoring & Propagation

Layer / File(s) Summary
Type Definitions
key-wallet/src/managed_account/managed_core_funds_account.rs, key-wallet/src/managed_account/managed_core_keys_account.rs
Introduces ManagedCoreFundsAccount with full balance/UTXO/transaction/revision tracking and ManagedCoreKeysAccount with lightweight derivation-only state. Both support address pools, transaction records, account metadata, and feature-gated BLS/EdDSA key generation. Implements ManagedAccountTrait and serde Deserialize for ManagedCoreFundsAccount.
Module Refactoring
key-wallet/src/managed_account/mod.rs
Refactors from a monolithic type definition to a wiring module that declares submodules and re-exports ManagedCoreFundsAccount and ManagedCoreKeysAccount. Removes the previous ManagedCoreAccount export.
Collection Storage
key-wallet/src/managed_account/managed_account_collection.rs
Updates all account storage fields and methods (standard_bip44_accounts, standard_bip32_accounts, coinjoin_accounts, identity/provider/dashpay pools) from ManagedCoreAccount to ManagedCoreFundsAccount. Updates all getter/setter/removal/iteration method signatures accordingly.
Documentation References
key-wallet/src/managed_account/managed_platform_account.rs
Doc comments updated to reference ManagedCoreFundsAccount instead of ManagedCoreAccount in comparison descriptions; no code changes.
FFI Bindings
key-wallet-ffi/src/address_pool.rs, key-wallet-ffi/src/managed_account.rs
FFI wrapper FFIManagedCoreAccount and lookup helpers (get_managed_account_by_type, get_managed_account_by_type_mut) now target ManagedCoreFundsAccount instead of ManagedCoreAccount.
Wallet Info Helpers
key-wallet/src/wallet/managed_wallet_info/helpers.rs
All account accessor methods (BIP44/BIP32/CoinJoin/identity/provider/dashpay) update return types from ManagedCoreAccount to ManagedCoreFundsAccount for both immutable and mutable variants.
Wallet Account Management
key-wallet/src/wallet/managed_wallet_info/managed_accounts.rs, key-wallet/src/wallet/managed_wallet_info/asset_lock_builder.rs
Account construction calls switch from ManagedCoreAccount::from_account(...) to ManagedCoreFundsAccount::from_account(...) and feature-gated constructors; funding account resolution updated to use ManagedCoreFundsAccount.
Transaction Checking
key-wallet/src/transaction_checking/account_checker.rs, key-wallet/src/transaction_checking/wallet_checker.rs
Account-checker implementation block and indexed-account iteration types updated from ManagedCoreAccount to ManagedCoreFundsAccount; wallet-checker doc comment adjusted accordingly.
Test Utilities & Fixtures
key-wallet/src/test_utils/account.rs, key-wallet/src/test_utils/wallet.rs
dummy_bip44() now defined on ManagedCoreFundsAccount and TestWalletContext::bip44_account() return type updated to &ManagedCoreFundsAccount.
Core Tests
key-wallet/src/tests/balance_tests.rs, key-wallet/src/tests/spent_outpoints_tests.rs
Account construction and deserialization in balance and spent-outpoints tests updated to use ManagedCoreFundsAccount::dummy_bip44() and ManagedCoreFundsAccount serde paths.
FFI Tests
key-wallet-ffi/src/managed_wallet.rs, key-wallet-ffi/src/utxo_tests.rs
Test account construction updated from ManagedCoreAccount::new(...) to ManagedCoreFundsAccount::new(...) in address generation, UTXO reading, and multi-account tests; added supporting dashcore type imports for UTXO fixtures.
SPV Sync Documentation
dash-spv/src/sync/mempool/sync_manager.rs
Inline comment describing revision counter location updated from ManagedCoreAccount to ManagedCoreFundsAccount; no logic changes.
User & Developer Documentation
key-wallet/README.md, key-wallet/CLAUDE.md, key-wallet/IMPLEMENTATION_SUMMARY.md, key-wallet/src/account/mod.rs
Documentation and examples updated to reference ManagedCoreFundsAccount in API overviews, usage examples, account creation patterns, and migration notes. Module re-export in src/account/mod.rs points to ManagedCoreFundsAccount.

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~50 minutes

Possibly related PRs

Suggested labels

ready-for-review

Suggested reviewers

  • ZocoLini

Poem

🐰 One account splits in two,
Funds and keys, each with their view,
Lighter states and heavier care,
All the tests now paired just right,
The refactor shines so bright!

🚥 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 title accurately and concisely describes the main structural refactor: splitting ManagedCoreAccount into separate funds and keys variants.
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 unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch claude/adoring-booth-151626

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
Review rate limit: 0/1 reviews remaining, refill in 58 minutes and 54 seconds.

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

@codecov
Copy link
Copy Markdown

codecov Bot commented May 3, 2026

Codecov Report

❌ Patch coverage is 39.94280% with 630 lines in your changes missing coverage. Please review.
✅ Project coverage is 70.28%. Comparing base (fcaf66e) to head (425bc19).

Files with missing lines Patch % Lines
...t/src/managed_account/managed_core_keys_account.rs 0.00% 305 Missing ⚠️
.../src/managed_account/managed_core_funds_account.rs 55.93% 297 Missing ⚠️
...y-wallet/src/wallet/managed_wallet_info/helpers.rs 57.14% 18 Missing ⚠️
...src/wallet/managed_wallet_info/managed_accounts.rs 16.66% 5 Missing ⚠️
.../src/managed_account/managed_account_collection.rs 80.00% 3 Missing ⚠️
key-wallet-ffi/src/address_pool.rs 0.00% 2 Missing ⚠️
Additional details and impacted files
@@              Coverage Diff              @@
##           v0.42-dev     #711      +/-   ##
=============================================
- Coverage      70.57%   70.28%   -0.29%     
=============================================
  Files            319      320       +1     
  Lines          68211    68527     +316     
=============================================
+ Hits           48142    48167      +25     
- Misses         20069    20360     +291     
Flag Coverage Δ
core 75.81% <ø> (ø)
ffi 43.37% <60.00%> (ø)
rpc 20.00% <ø> (ø)
spv 87.32% <ø> (+0.10%) ⬆️
wallet 68.56% <39.84%> (-1.09%) ⬇️
Files with missing lines Coverage Δ
dash-spv/src/sync/mempool/sync_manager.rs 98.72% <ø> (ø)
key-wallet-ffi/src/managed_account.rs 53.43% <100.00%> (ø)
key-wallet-ffi/src/managed_wallet.rs 79.17% <100.00%> (ø)
key-wallet/src/account/mod.rs 62.79% <ø> (ø)
...et/src/managed_account/managed_platform_account.rs 64.28% <ø> (ø)
...wallet/src/transaction_checking/account_checker.rs 67.02% <100.00%> (ø)
...-wallet/src/transaction_checking/wallet_checker.rs 99.39% <ø> (ø)
...c/wallet/managed_wallet_info/asset_lock_builder.rs 79.61% <100.00%> (ø)
key-wallet-ffi/src/address_pool.rs 36.03% <0.00%> (ø)
.../src/managed_account/managed_account_collection.rs 55.66% <80.00%> (ø)
... and 4 more

... and 3 files with indirect coverage changes

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.

Actionable comments posted: 6

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@key-wallet/IMPLEMENTATION_SUMMARY.md`:
- Around line 183-186: The example uses the old method
get_next_receive_address() which no longer exists on ManagedCoreFundsAccount;
update the call to the renamed API (replace get_next_receive_address() with the
current method on ManagedCoreFundsAccount, e.g., get_receive_address()) and add
the necessary import for ManagedCoreFundsAccount so the snippet is
copy-pasteable; ensure you call ManagedCoreFundsAccount::from_account(&account)
followed by the new instance method name instead of get_next_receive_address().

In `@key-wallet/src/managed_account/managed_core_funds_account.rs`:
- Around line 421-452: confirm_transaction currently only updates context and
UTXOs for existing TransactionRecord, so changes in account_match from gap-limit
rescans leave net_amount/direction and input/output roles stale; modify
confirm_transaction (and use TransactionRecord/record_transaction helpers) to
detect when the stored match differs from the new account_match and refresh the
stored TransactionRecord's derived metadata (net_amount, direction, input/output
role flags) by re-running the same computation used in record_transaction (or by
replacing the entry with a newly constructed TransactionRecord while preserving
transaction_type and context), then continue to update UTXOs and return changed
appropriately; refer to confirm_transaction, TransactionRecord,
record_transaction, update_utxos, and account_match to locate code to change.
- Around line 296-304: The pool-mutating helpers (e.g., mark_address_used, batch
derivation helpers, non-standard next_address/_with_info paths, provider-key
helpers) must bump the monitor revision just like
next_receive_address/next_change_address do; update each of these functions
(including mark_address_used and the batch/alternate derivation functions
referenced in the review) to call the same monitor_revision invalidation logic
(increment the metadata.monitor_revision or call the existing helper that bumps
it and sets last_used) immediately when they extend or mutate the watched
address pools, before returning, so the mempool/filter consumers will refresh
their watched set; locate calls to managed_account_type.mark_address_used, the
batch derivation routines, and any provider-key derivation helpers and add the
identical revision-bump step there.

In `@key-wallet/src/managed_account/managed_core_keys_account.rs`:
- Around line 257-261: The account mutation methods must bump the
monitor_revision when they actually change address/pool state: update
mark_address_used (and similarly next_address, next_address_with_info, and any
provider-key helper that mutates pool state) to increment or set
self.metadata.monitor_revision (e.g., to Self::current_timestamp() or
self.metadata.monitor_revision.wrapping_add(1)) only when the underlying
mutation returned true/succeeded; locate the mutation by the methods
managed_account_type.mark_address_used, next_address, next_address_with_info,
and provider-key helper calls, and add the monitor_revision update immediately
after a successful mutation return path so the monitor sees the new address set.

In `@key-wallet/src/managed_account/mod.rs`:
- Around line 19-27: Keep a compatibility alias named ManagedCoreAccount
pointing to ManagedCoreFundsAccount and mark it deprecated for one release
cycle: add a public alias (pub type ManagedCoreAccount =
ManagedCoreFundsAccount) with a #[deprecated(...)] attribute and a short note
steering callers to ManagedCoreFundsAccount; place this alongside the existing
pub use ManagedCoreFundsAccount export in mod.rs so existing imports continue to
work while signalling the new name.

In `@key-wallet/src/tests/spent_outpoints_tests.rs`:
- Around line 90-95: The test only checks serde round-trips but not that the
private spent_outpoints set is actually rebuilt; change one of the
post-deserialization assertions to exercise behavior that depends on
spent_outpoints (e.g., attempt to apply/insert a duplicate spend and assert it
is rejected or not considered spendable). After deserializing into
ManagedCoreFundsAccount, call the public API that records or validates spends
(use the existing methods on ManagedCoreFundsAccount such as the
transaction-add/apply method or a spendability check) to try to spend the same
outpoint twice and assert the second spend fails or reports unspendable; this
will prove spent_outpoints was reconstructed. Ensure you replace one of the
existing serde assertions (like the transactions.len() check) with this
duplicate-spend/spendability assertion and leave the other serde checks intact.
🪄 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: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 06e6eb8a-3905-4949-aa3f-e042afddfa66

📥 Commits

Reviewing files that changed from the base of the PR and between ca507a9 and 2f1ea9e.

📒 Files selected for processing (23)
  • dash-spv/src/sync/mempool/sync_manager.rs
  • key-wallet-ffi/src/address_pool.rs
  • key-wallet-ffi/src/managed_account.rs
  • key-wallet-ffi/src/managed_wallet.rs
  • key-wallet-ffi/src/utxo_tests.rs
  • key-wallet/CLAUDE.md
  • key-wallet/IMPLEMENTATION_SUMMARY.md
  • key-wallet/README.md
  • key-wallet/src/account/mod.rs
  • key-wallet/src/managed_account/managed_account_collection.rs
  • key-wallet/src/managed_account/managed_core_funds_account.rs
  • key-wallet/src/managed_account/managed_core_keys_account.rs
  • key-wallet/src/managed_account/managed_platform_account.rs
  • key-wallet/src/managed_account/mod.rs
  • key-wallet/src/test_utils/account.rs
  • key-wallet/src/test_utils/wallet.rs
  • key-wallet/src/tests/balance_tests.rs
  • key-wallet/src/tests/spent_outpoints_tests.rs
  • key-wallet/src/transaction_checking/account_checker.rs
  • key-wallet/src/transaction_checking/wallet_checker.rs
  • key-wallet/src/wallet/managed_wallet_info/asset_lock_builder.rs
  • key-wallet/src/wallet/managed_wallet_info/helpers.rs
  • key-wallet/src/wallet/managed_wallet_info/managed_accounts.rs

Comment thread key-wallet/IMPLEMENTATION_SUMMARY.md Outdated
Comment on lines +296 to +304
/// Mark an address as used
pub fn mark_address_used(&mut self, address: &Address) -> bool {
// Update metadata timestamp
self.metadata.last_used = Some(Self::current_timestamp());

// Use the account type's mark_address_used method
// The address pools already track gap limits internally
self.managed_account_type.mark_address_used(address)
}
Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot May 3, 2026

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Pool-mutating derivation helpers need the same monitor_revision invalidation as the standard single-address helpers.

next_receive_address/next_change_address already bump the revision, but the batch helpers, non-standard next_address(_with_info) paths, provider-key helpers, and mark_address_used do not. If any of those extend the watched set, mempool/filter consumers will keep monitoring the old address set until some later mutation happens to bump the counter.

Also applies to: 709-788, 793-1068

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

In `@key-wallet/src/managed_account/managed_core_funds_account.rs` around lines
296 - 304, The pool-mutating helpers (e.g., mark_address_used, batch derivation
helpers, non-standard next_address/_with_info paths, provider-key helpers) must
bump the monitor revision just like next_receive_address/next_change_address do;
update each of these functions (including mark_address_used and the
batch/alternate derivation functions referenced in the review) to call the same
monitor_revision invalidation logic (increment the metadata.monitor_revision or
call the existing helper that bumps it and sets last_used) immediately when they
extend or mutate the watched address pools, before returning, so the
mempool/filter consumers will refresh their watched set; locate calls to
managed_account_type.mark_address_used, the batch derivation routines, and any
provider-key derivation helpers and add the identical revision-bump step there.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

Tracked as #713 — agreed it's a real gap, just out of scope for this structural-only PR.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

@QuantumExplorer, understood — thanks for the confirmation! I'll keep the comment open until #713 is resolved. The structural refactor looks clean as-is.


🧠 Learnings used
Learnt from: QuantumExplorer
Repo: dashpay/rust-dashcore PR: 711
File: key-wallet/src/managed_account/mod.rs:19-27
Timestamp: 2026-05-03T16:28:16.898Z
Learning: In the `key-wallet` crate, when reviewing the `managed_account` module for type renames/splits (e.g., `ManagedCoreAccount` -> `ManagedCoreFundsAccount`, plus separate “funds-free” variants), avoid recommending deprecated compatibility type aliases for the old Rust types. This code is intended for in-tree Rust use only (no external Rust consumers), and callsites are expected to be migrated in the same PR. Backward compatibility is handled separately at the C/FFI layer, which should remain unchanged by these Rust-only renames.

Comment on lines +421 to +452
pub(crate) fn confirm_transaction(
&mut self,
tx: &Transaction,
account_match: &AccountMatch,
context: TransactionContext,
transaction_type: TransactionType,
) -> bool {
if !self.transactions.contains_key(&tx.txid()) {
self.record_transaction(tx, account_match, context, transaction_type);
return true;
}

let mut changed = false;
if let Some(tx_record) = self.transactions.get_mut(&tx.txid()) {
debug_assert_eq!(
tx_record.transaction_type,
transaction_type,
"transaction_type changed between recordings for {}",
tx.txid()
);
if tx_record.context != context {
let was_confirmed = tx_record.context.confirmed();
tx_record.update_context(context.clone());
// Only signal a change when confirmation status actually changes,
// not for upgrades within the confirmed state (e.g. InBlock → InChainLockedBlock).
// TODO: emit a change event for InBlock → InChainLockedBlock once chainlock
// wallet transaction events are properly handled
changed = !was_confirmed;
}
}
self.update_utxos(tx, account_match, context);
changed
Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot May 3, 2026

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major | 🏗️ Heavy lift

Refresh the stored TransactionRecord when rescans change account_match.

This method claims to handle “potentially new address matches from gap limit rescans”, but for an already-recorded tx it only updates context and UTXOs. net_amount, direction, and the input/output roles stay frozen from the first recording, so a tx confirmed after a gap-limit rescan can still show stale wallet metadata.

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

In `@key-wallet/src/managed_account/managed_core_funds_account.rs` around lines
421 - 452, confirm_transaction currently only updates context and UTXOs for
existing TransactionRecord, so changes in account_match from gap-limit rescans
leave net_amount/direction and input/output roles stale; modify
confirm_transaction (and use TransactionRecord/record_transaction helpers) to
detect when the stored match differs from the new account_match and refresh the
stored TransactionRecord's derived metadata (net_amount, direction, input/output
role flags) by re-running the same computation used in record_transaction (or by
replacing the entry with a newly constructed TransactionRecord while preserving
transaction_type and context), then continue to update UTXOs and return changed
appropriately; refer to confirm_transaction, TransactionRecord,
record_transaction, update_utxos, and account_match to locate code to change.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

Tracked as #714 — agreed, but out of scope for this structural-only PR (the function is moved verbatim here).

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

@QuantumExplorer, understood — thanks for tracking it in #714. Since this is a verbatim move with no behavioral changes, deferring the fix is the right call for this structural PR.


🧠 Learnings used
Learnt from: QuantumExplorer
Repo: dashpay/rust-dashcore PR: 711
File: key-wallet/src/managed_account/mod.rs:19-27
Timestamp: 2026-05-03T16:28:16.898Z
Learning: In the `key-wallet` crate, when reviewing the `managed_account` module for type renames/splits (e.g., `ManagedCoreAccount` -> `ManagedCoreFundsAccount`, plus separate “funds-free” variants), avoid recommending deprecated compatibility type aliases for the old Rust types. This code is intended for in-tree Rust use only (no external Rust consumers), and callsites are expected to be migrated in the same PR. Backward compatibility is handled separately at the C/FFI layer, which should remain unchanged by these Rust-only renames.

Comment on lines +257 to +261
/// Mark an address as used
pub fn mark_address_used(&mut self, address: &Address) -> bool {
self.metadata.last_used = Some(Self::current_timestamp());
self.managed_account_type.mark_address_used(address)
}
Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot May 3, 2026

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Bump monitor_revision on successful key/address-pool mutations.

These paths can grow or otherwise change the monitored address set, but none of them invalidate monitor_revision. That means a keys-only account can derive fresh identity/provider addresses and still keep watching the old filter until some unrelated code bumps the revision manually.

Suggested direction
 pub fn mark_address_used(&mut self, address: &Address) -> bool {
     self.metadata.last_used = Some(Self::current_timestamp());
-    self.managed_account_type.mark_address_used(address)
+    let changed = self.managed_account_type.mark_address_used(address);
+    if changed {
+        self.bump_monitor_revision();
+    }
+    changed
 }

Apply the same pattern to next_address, next_address_with_info, and the provider-key helpers whenever they actually mutate pool state.

Also applies to: 283-518

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

In `@key-wallet/src/managed_account/managed_core_keys_account.rs` around lines 257
- 261, The account mutation methods must bump the monitor_revision when they
actually change address/pool state: update mark_address_used (and similarly
next_address, next_address_with_info, and any provider-key helper that mutates
pool state) to increment or set self.metadata.monitor_revision (e.g., to
Self::current_timestamp() or self.metadata.monitor_revision.wrapping_add(1))
only when the underlying mutation returned true/succeeded; locate the mutation
by the methods managed_account_type.mark_address_used, next_address,
next_address_with_info, and provider-key helper calls, and add the
monitor_revision update immediately after a successful mutation return path so
the monitor sees the new address set.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

Tracked as #715 — and the matching gap on the funds variant is #713. ManagedCoreKeysAccount is dead code in this PR, so fixing it now would just diverge from the funds-side behavior. Most natural to address alongside #713 before PR 2 wires this struct into the collection.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

@QuantumExplorer, understood — that's a sensible sequencing. Keeping the keys variant's behavior in sync with the funds variant once #713 lands (and before this struct is wired into the collection) is cleaner than a partial fix now. I'll track this against #715.


🧠 Learnings used
Learnt from: QuantumExplorer
Repo: dashpay/rust-dashcore PR: 711
File: key-wallet/src/managed_account/mod.rs:19-27
Timestamp: 2026-05-03T16:28:16.898Z
Learning: In the `key-wallet` crate, when reviewing the `managed_account` module for type renames/splits (e.g., `ManagedCoreAccount` -> `ManagedCoreFundsAccount`, plus separate “funds-free” variants), avoid recommending deprecated compatibility type aliases for the old Rust types. This code is intended for in-tree Rust use only (no external Rust consumers), and callsites are expected to be migrated in the same PR. Backward compatibility is handled separately at the C/FFI layer, which should remain unchanged by these Rust-only renames.

Comment thread key-wallet/src/managed_account/mod.rs
Comment on lines 90 to 95
// Verify the rebuilt set by serializing again and comparing transactions
// (spent_outpoints is private, so we test behavior through a second round-trip
// to confirm stability)
let json2 = serde_json::to_string(&deserialized).unwrap();
let deserialized2: ManagedCoreAccount = serde_json::from_str(&json2).unwrap();
let deserialized2: ManagedCoreFundsAccount = serde_json::from_str(&json2).unwrap();
assert_eq!(deserialized2.transactions.len(), 1);
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

Exercise the rebuilt spent set directly.

These assertions only prove that transaction inputs survive serde; they would still pass if spent_outpoints stopped being reconstructed. Please switch one of the checks to behavior that depends on the private spent set (e.g. a duplicate-spend/spendability assertion).

Also applies to: 137-149

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

In `@key-wallet/src/tests/spent_outpoints_tests.rs` around lines 90 - 95, The test
only checks serde round-trips but not that the private spent_outpoints set is
actually rebuilt; change one of the post-deserialization assertions to exercise
behavior that depends on spent_outpoints (e.g., attempt to apply/insert a
duplicate spend and assert it is rejected or not considered spendable). After
deserializing into ManagedCoreFundsAccount, call the public API that records or
validates spends (use the existing methods on ManagedCoreFundsAccount such as
the transaction-add/apply method or a spendability check) to try to spend the
same outpoint twice and assert the second spend fails or reports unspendable;
this will prove spent_outpoints was reconstructed. Ensure you replace one of the
existing serde assertions (like the transactions.len() check) with this
duplicate-spend/spendability assertion and leave the other serde checks intact.

@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented May 3, 2026

This PR has merge conflicts with the base branch. Please rebase or merge the base branch into your branch to resolve them.

QuantumExplorer and others added 3 commits May 4, 2026 05:29
…ants

Move the existing struct out of `managed_account/mod.rs` into a dedicated
`managed_core_funds_account.rs` and rename it to `ManagedCoreFundsAccount`
to make room for a sibling `ManagedCoreKeysAccount` that omits funds-tracking
state (`balance`, `utxos`, `spent_outpoints`). The keys variant is intended
for accounts that derive special-purpose keys (identity registration, asset
locks, masternode provider keys) but is not yet wired into
`ManagedAccountCollection` — that migration follows in a subsequent PR.

This change is purely structural: `ManagedAccountCollection` continues to
store `ManagedCoreFundsAccount` for every account type and behavior is
unchanged. The C ABI is preserved — `FFIManagedCoreAccount` and the
`managed_core_account_*` C functions keep their original names and now wrap
the renamed Rust struct internally.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…Account

- Sort imports and rewrap long signatures (rustfmt fixes flagged by pre-commit)
- Qualify the `[\`ManagedCoreFundsAccount\`]` intra-doc links in
  `managed_core_keys_account.rs` to `[\`crate::managed_account::ManagedCoreFundsAccount\`]`
  so rustdoc can resolve them under `-D warnings`

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…N_SUMMARY

The example called `get_next_receive_address()`, which is not a method on
this struct. Replace with the real `next_receive_address(...)` signature so
the snippet compiles.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@QuantumExplorer QuantumExplorer force-pushed the claude/adoring-booth-151626 branch from 2b9fbad to 425bc19 Compare May 3, 2026 22:30
@github-actions github-actions Bot removed the merge-conflict The PR conflicts with the target branch. label May 3, 2026
Copy link
Copy Markdown
Member Author

@QuantumExplorer QuantumExplorer left a comment

Choose a reason for hiding this comment

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

Self Reviewed

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