feat(key-wallet): CoinJoin sweep + gap-limit recovery; TransactionBuilder drain mode#819
feat(key-wallet): CoinJoin sweep + gap-limit recovery; TransactionBuilder drain mode#819llbartekll wants to merge 1 commit into
Conversation
|
Warning Review limit reached
More reviews will be available in 28 minutes and 44 seconds. Learn how PR review limits work. Your organization has used up its prepaid credits, and credit purchases are no longer available. Enable the review add-on in the billing tab to keep reviews running — you're only billed for reviews past your plan's rate limits ($0.25/file). ⌛ How to resolve this issue?After more reviews become available, a review can be triggered using the To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based credits. 🚦 How do rate limits work?CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan refill rate. For paid Pro and Pro+ PR reviews, CodeRabbit uses rolling per-developer review limits. Reviews become available again as older review attempts age out of the rolling limit window. Please see our Fair Usage Limits Policy for further information. ℹ️ Review info⚙️ Run configurationConfiguration used: Path: .coderabbit.yaml Review profile: CHILL Plan: Pro Run ID: 📒 Files selected for processing (3)
✨ Finishing Touches🧪 Generate unit tests (beta)
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. Comment |
…wallet Addresses review feedback (@ZocoLini): the CoinJoin sweep/recovery logic belongs in rust-dashcore, and the sweep should use TransactionBuilder instead of hand-rolling transaction assembly. The logic now lives upstream (dashpay/rust-dashcore#819); this bumps the pin to that commit and reduces the platform side to thin wrappers. - broadcast.rs: sweep_coinjoin_to_address resolves the account under the wallet lock, delegates build+sign to ManagedCoreFundsAccount::build_coinjoin_sweep_txs, then broadcasts (partial-failure tolerance unchanged). -458 lines. - coinjoin_recovery.rs: set_coinjoin_gap_limit delegates to ManagedCoreFundsAccount::set_coinjoin_gap_limit. -91 lines. - Cargo.toml/Cargo.lock: bump rust-dashcore pin 5c0113e7 -> 613466a4 (adds the upstream CoinJoin sweep/recovery + TransactionBuilder::sweep_to drain mode). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Codecov Report❌ Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## dev #819 +/- ##
==========================================
+ Coverage 72.91% 72.98% +0.07%
==========================================
Files 323 324 +1
Lines 71994 72310 +316
==========================================
+ Hits 52492 52776 +284
- Misses 19502 19534 +32
|
…lder drain mode Moves the wallet-level logic for the DashSync → SwiftDashSDK CoinJoin migration upstream so consumers (platform-wallet, dashwallet) wrap it instead of reimplementing transaction assembly. - `TransactionBuilder::sweep_to()`: drain mode — consume every added input into a single no-change output (`total − fee`), skipping coin selection, and reject a sub-dust output. Fee is sized from the max input length so it never undershoots at the relay minimum. - `ManagedCoreFundsAccount::build_coinjoin_sweep_txs()`: snapshot the spendable CoinJoin UTXO set, chunk it under the relay size cap, and build/sign each chunk via the drain mode. Resolves signing paths across BOTH CoinJoin chains (external `/0/` + internal `/1/`) so migrated internal-chain "change" coins sign. - `ManagedCoreFundsAccount::set_coinjoin_gap_limit()`: widen the CoinJoin pool's gap limit and materialize addresses for SPV recovery; rejects a zero gap limit (which would underflow `maintain_gap_limit`). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
613466a to
e406d1c
Compare
…wallet Addresses review feedback (@ZocoLini): the CoinJoin sweep/recovery logic belongs in rust-dashcore, and the sweep should use TransactionBuilder instead of hand-rolling transaction assembly. The logic now lives upstream (dashpay/rust-dashcore#819); this bumps the pin to that commit and reduces the platform side to thin wrappers. - broadcast.rs: sweep_coinjoin_to_address resolves the account under the wallet lock, delegates build+sign to ManagedCoreFundsAccount::build_coinjoin_sweep_txs, then broadcasts (partial-failure tolerance unchanged). -458 lines. - coinjoin_recovery.rs: set_coinjoin_gap_limit delegates to ManagedCoreFundsAccount::set_coinjoin_gap_limit. -91 lines. - Cargo.toml/Cargo.lock: bump rust-dashcore pin 5c0113e7 -> e406d1cb (adds the upstream CoinJoin sweep/recovery + TransactionBuilder::sweep_to drain mode). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
ZocoLini
left a comment
There was a problem hiding this comment.
I think there is a bunch of logic that can be recycled, did you think about a new CoinSelectionStratey that indicates we want to use all inputs?? I think our current logic can be updated to support that. Now, about the account selection, instead of anew module maybe transaction_building.rs can be updated to receive an AccountType in the build transaction methods, adding the flexibility we need to do the sweep without having to add the much logic.
Maybe give me a 'sweep' definition and what you want to be able to do and I cancontinue the PR myself
|
also, enable the pre-commit and pre-push checks in your machine pls |
What
Moves the wallet-level logic for the DashSync → SwiftDashSDK CoinJoin migration upstream into
key-wallet, so downstream consumers (platform-wallet,dashwallet-ios) wrap it rather than reimplementing transaction assembly. Post-migration CoinJoin is being dropped, so this lets a wallet find its scattered "mixed coins" and sweep them back into spendable BIP44 balance.TransactionBuilder::sweep_to(dest)— drain modeConsume every added input into a single no-change output (
total − fee), skipping coin selection entirely (a normal build re-selects a covering subset and would leave small UTXOs behind — fatal for a sweep). The fee is sized from the maximum P2PKH input length so it never undershoots at the 1 duff/byte relay minimum, and a sub-dust output is rejected.ManagedCoreFundsAccount::build_coinjoin_sweep_txs(xpub, height, dest, signer)Snapshots the spendable CoinJoin UTXO set, splits it into balanced chunks under the standard relay size limit (≤ 500 inputs/tx), and builds + signs each chunk via the drain mode. Resolves signing paths across both CoinJoin chains — external
/0/and internal/1/— from the account xpub, so a migrated wallet's internal-chain ("change") mixed coins sign correctly. Returns the signed txs; the caller broadcasts them (disjoint, so order is irrelevant and a partial broadcast can be re-run).ManagedCoreFundsAccount::set_coinjoin_gap_limit(xpub, gap_limit)Widens the CoinJoin pool's gap limit and materializes the addresses so an SPV recovery scan watches the wider window (DashSync used a gap of 400 vs the SDK default of 30). Rejects a zero gap limit (which would underflow
maintain_gap_limit) and clamps toMAX_GAP_LIMIT.Why
Addresses review feedback on dashpay/platform#3817 (@ZocoLini): this logic was implemented in
platform-wallet, which should be a thin wrapper overrust-dashcore, and the sweep hand-rolled transaction assembly instead of usingTransactionBuilder. This PR puts the generic Dash-wallet mechanics where they belong; platform-wallet now just resolves the account under its lock and delegates.Testing
cargo test -p key-wallet— 5 new unit tests pass (drain mode consumes-all / sub-dust reject, dual-chain path resolution, chunk partitioning), existingtransaction_buildertests unaffected.Notes
5c0113e7(the commit platform currently pins — 4 commits behinddev); base isdev. The platform pin advances only by this one additive commit, so there is no version drift for downstream consumers.platform-wallet-ffi. A directkey-wallet-ffisurface can follow if wanted.🤖 Generated with Claude Code