Skip to content

feat(key-wallet): expose reserved outpoints for cross-account input selection#905

Open
bfoss765 wants to merge 2 commits into
dashpay:devfrom
bfoss765:feat/expose-reserved-outpoints
Open

feat(key-wallet): expose reserved outpoints for cross-account input selection#905
bfoss765 wants to merge 2 commits into
dashpay:devfrom
bfoss765:feat/expose-reserved-outpoints

Conversation

@bfoss765

@bfoss765 bfoss765 commented Jul 17, 2026

Copy link
Copy Markdown
Contributor

Motivation

Cross-account input sweeps in platform-wallet need to exclude UTXOs that an in-flight transaction build has already reserved, and today the reservation ledger is pub(crate) so they cannot.

The ReservationSet (added in #812) bridges the window between selecting a build's inputs and processing its broadcast back into the wallet: reserved inputs are skipped by that account's own coin selection through set_funding. But its read surface — ManagedCoreFundsAccount::reservations() and ReservationSet::reserved() — is crate-private.

A caller that selects inputs across accounts (force-adding a non-primary account's spendable_utxos() into a shared sweep) bypasses that account's coin selector and therefore its reservation awareness. spendable_utxos() filters on spendability (maturity/lock) only. So after a broadcast leaves inputs reserved, a rebuild/retry can reselect the same foreign inputs and produce a conflicting transaction.

This is the review finding on dashpay/platform#4074 (asset-lock funding from all accounts): the union sweep in rs-platform-wallet's asset_lock/build.rs force-adds non-primary accounts' spendable_utxos() via add_inputs, bypassing reservation awareness.

Change (additive — no existing signatures change)

Two new public read methods on ManagedCoreFundsAccount:

  • reserved_outpoints(current_height) -> HashSet<OutPoint> — a read-only, TTL-swept snapshot of the outpoints currently reserved by in-flight builds.
  • spendable_utxos_excluding_reserved(last_processed_height) -> BTreeSet<&Utxo> — the reservation-aware counterpart of spendable_utxos, intended for cross-account sweeps.

spendable_utxos() semantics are intentionally left unchanged, since other callers rely on the maturity-only behaviour; keeping the new API additive keeps the change small and unblocks the platform-wallet consumer.

Tests

Added reserved_outpoints_are_excluded_from_spendable_and_reappear_on_release (in key-wallet/src/tests/spent_outpoints_tests.rs), proving that a reserved outpoint is:

  • visible via reserved_outpoints,
  • excluded from spendable_utxos_excluding_reserved while still present in the unchanged spendable_utxos,
  • and reappears in the excluding enumeration once the reservation is released.

Validation

cargo test -p key-wallet    # 549 passed; 0 failed (+ integration suites green)
cargo clippy -p key-wallet --all-targets   # clean
cargo fmt -p key-wallet -- --check         # clean

Intended consumer / follow-up

The platform-side consumption is a follow-up once this merges and the rust-dashcore pin advances: dashpay/platform#4074's union sweep in packages/rs-platform-wallet/src/wallet/asset_lock/build.rs should call spendable_utxos_excluding_reserved(...) (or consult reserved_outpoints(...)) instead of the raw spendable_utxos() when force-adding non-primary accounts' inputs.

🤖 Generated with Claude Code

Summary by CodeRabbit

  • New Features
    • Added reservation-aware views that report which outpoints are currently reserved by in-progress account activity.
    • Reserved UTXOs are now excluded from spendable selection to help avoid double-spending while a transaction is being built.
    • Expired reservations are automatically omitted from reservation results.
    • Released reservations become eligible for spending again.
  • Tests
    • Added a unit test covering the reserve/exclude/release behavior for spendable UTXOs and reserved outpoints.

…election

The UTXO reservation ledger (ReservationSet) is consulted by an account's
own coin selection via set_funding, but its read surface — reservations()
and ReservationSet::reserved() — is pub(crate). A caller that selects
inputs across accounts, force-adding another account's spendable_utxos()
into a shared sweep, bypasses that account's selector and so its
reservation awareness. spendable_utxos() filters on spendability only, so
after a broadcast leaves inputs reserved a rebuild/retry can reselect the
same foreign inputs and produce a conflicting transaction.

Add two additive public methods on ManagedCoreFundsAccount:

- reserved_outpoints(current_height) -> HashSet<OutPoint>: a read-only
  snapshot of the currently reserved outpoints, TTL-swept at the given
  height.
- spendable_utxos_excluding_reserved(last_processed_height): the
  reservation-aware counterpart of spendable_utxos, for cross-account
  sweeps.

Existing spendable_utxos() semantics are unchanged so current callers are
unaffected. Covered by a unit test proving a reserved outpoint is visible
via the new read API, excluded from the excluding enumeration while still
present in spendable_utxos, and reappears once released.

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

coderabbitai Bot commented Jul 17, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

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: bc3733d3-2def-43d0-a0c7-2dfd111c61d6

📥 Commits

Reviewing files that changed from the base of the PR and between 05d4196 and 1c35664.

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

📝 Walkthrough

Walkthrough

ManagedCoreFundsAccount now exposes active reserved outpoints and provides spendable UTXO enumeration that excludes reservations evaluated at a specified height. Tests cover reservation, exclusion, preservation of the existing view, and reappearance after release.

Changes

Reservation-aware UTXO selection

Layer / File(s) Summary
Reservation-aware account APIs
key-wallet/src/managed_account/managed_core_funds_account.rs
Adds public methods for retrieving active reserved outpoints and filtering spendable UTXOs against reservations with height-based TTL evaluation.
Reservation behavior validation
key-wallet/src/tests/spent_outpoints_tests.rs
Verifies reserved UTXOs are excluded only from the reservation-aware enumeration and reappear after release.

Estimated code review effort: 3 (Moderate) | ~15–30 minutes

Possibly related PRs

🚥 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 clearly summarizes the main change: exposing reserved outpoints for cross-account input selection.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
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.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

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.

coderabbitai[bot]
coderabbitai Bot previously approved these changes Jul 17, 2026
@codecov

codecov Bot commented Jul 17, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 74.51%. Comparing base (19690d3) to head (1c35664).

Additional details and impacted files
@@            Coverage Diff             @@
##              dev     #905      +/-   ##
==========================================
- Coverage   74.54%   74.51%   -0.04%     
==========================================
  Files         327      327              
  Lines       75032    75047      +15     
==========================================
- Hits        55936    55923      -13     
- Misses      19096    19124      +28     
Flag Coverage Δ
core 77.29% <ø> (ø)
ffi 50.64% <ø> (-0.31%) ⬇️
rpc 20.00% <ø> (ø)
spv 91.19% <ø> (-0.02%) ⬇️
wallet 74.45% <100.00%> (+0.04%) ⬆️
Files with missing lines Coverage Δ
.../src/managed_account/managed_core_funds_account.rs 78.63% <100.00%> (+0.77%) ⬆️

... and 18 files with indirect coverage changes

The public reserved_outpoints doc linked [`ReservationSet`], a pub(crate)
type, tripping rustdoc::private-intra-doc-links (-D warnings) and failing
the Documentation CI check. Plain-code span instead of an intra-doc link.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@github-actions github-actions Bot added the ready-for-review CodeRabbit has approved this PR label Jul 17, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

ready-for-review CodeRabbit has approved this PR

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant