fix(key-wallet): don't build asset locks on unconfirmed funds - #836
Conversation
|
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: Path: .coderabbit.yaml Review profile: CHILL Plan: Pro Run ID: 📒 Files selected for processing (5)
🚧 Files skipped from review as they are similar to previous changes (5)
📝 WalkthroughWalkthroughThis PR tightens trusted-change handling and final-input selection in ChangesTrust and finality enforcement
Estimated code review effort: 3 (Moderate) | ~25 minutes Sequence Diagram(s)sequenceDiagram
participant ManagedWalletInfo
participant TransactionBuilder
participant UtxoSet
participant CoinSelection
ManagedWalletInfo->>TransactionBuilder: require_final_inputs()
ManagedWalletInfo->>TransactionBuilder: build_signed()
TransactionBuilder->>UtxoSet: filter to confirmed or instantlocked UTXOs
TransactionBuilder->>CoinSelection: assemble_unsigned(filtered inputs)
CoinSelection-->>TransactionBuilder: selected funding inputs
TransactionBuilder-->>ManagedWalletInfo: signed asset-lock transaction
Possibly related issues
Possibly related PRs
Suggested labels: Suggested reviewers: 🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✨ 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 |
Codecov Report✅ All modified and coverable lines are covered by tests. Additional details and impacted files@@ Coverage Diff @@
## dev #836 +/- ##
==========================================
- Coverage 73.38% 73.32% -0.07%
==========================================
Files 324 324
Lines 72803 72923 +120
==========================================
+ Hits 53430 53472 +42
- Misses 19373 19451 +78
|
There was a problem hiding this comment.
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 `@key-wallet/src/managed_account/managed_core_funds_account.rs`:
- Around line 152-165: The trust recalculation in
update_utxos/confirm_transaction is order-dependent and can overwrite an already
trusted change output back to untrusted on reprocessing. Adjust the logic around
update_utxos in managed_core_funds_account::ManagedCoreFundsAccount so that an
existing outpoint retains its prior is_trusted state, or compute trust from a
source that does not depend on whether spent parents have already been removed
from self.utxos. Use the existing all_inputs_final_and_ours check and the trust
assignment path for new/existing UTXOs to ensure same-context self-sends remain
trusted across repeated passes.
🪄 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: c5f2ec04-9974-4a94-820c-e91ae6e69c6a
📒 Files selected for processing (5)
key-wallet/src/managed_account/managed_core_funds_account.rskey-wallet/src/transaction_checking/wallet_checker.rskey-wallet/src/wallet/managed_wallet_info/asset_lock_builder.rskey-wallet/src/wallet/managed_wallet_info/transaction_builder.rskey-wallet/src/wallet/managed_wallet_info/transaction_building.rs
Asset-lock builders selected funding UTXOs filtered only by `is_spendable`, which deliberately admits unconfirmed mempool outputs. A non-final input is not InstantSend-eligible per DIP-0010, so the resulting funding transaction could never receive the InstantSend lock or ChainLock Platform requires, and identity registration or top-up died on a 300s `AssetLockFinalityTimeout`. Add an opt-in `TransactionBuilder::require_final_inputs` that restricts coin selection to `is_confirmed || is_instantlocked` UTXOs and enable it in `build_asset_lock` and `build_asset_lock_with_signer`. Ordinary spends keep admitting unconfirmed inputs, now pinned by a regression test. Part of dashpay#832 (U2).
`Utxo::is_trusted` was set from a flat `has_owned_input && change-addr` check, so change of a self-send spending a still-unconfirmed parent was credited to the confirmed balance bucket. `Utxo::is_trusted` documents Bitcoin Core `CWalletTx::IsTrusted` parity, which is recursive: a zero-conf output is trusted only if every parent is itself trusted. Set `is_trusted` only when every input spends one of our own UTXOs that is confirmed, InstantSend-locked, or itself trusted. The stored parent flag carries the recursion transitively, and the spent parents are still present in the UTXO map at that point because insertion runs before spent-outpoint removal. Unknown or non-final parents deny trust, so funds the network may still drop never surface as confirmed. Part of dashpay#832 (U1).
17d64d5 to
2386559
Compare
ZocoLini
left a comment
There was a problem hiding this comment.
I approved but after that I thought about something, why don't we tell the CoinSelector the type of transactions is being built based on the data we have at build time and let it discard those invalid inputs for the asset lock transactions??
Whats better about it? Feel free to come up with a PR to refactor it if there is some good reason im missing (i guess centralizing it would be a good point here now after another thought..), im going to merge it like this now as lukasz seems to be quite keen on getting this merged :) |
`update_utxos` rebuilds each output with a fresh `Utxo::new` on every reprocess, so a mempool→block confirmation silently reset `is_instantlocked` (and `is_trusted` and any coin reservation) back to false. An InstantSend lock is permanent for a txid per DIP-0010 and trust only ever settles, so both now latch monotonically when an entry for the outpoint already exists, and the coin-reservation flag is carried through unchanged. `is_confirmed` stays freshly derived so a reorg can still downgrade it. Addresses CodeRabbit review comment on PR #836 #836 (comment)
Summary
Identity registration and top-up could hang for 300 seconds (
AssetLockFinalityTimeout) because the wallet funded asset locks with coins that were not final yet. A funding transaction built on such inputs can never receive an InstantSend lock, so Platform never accepts it. This fixes the twokey-walletdefects from #832:TransactionBuilder::require_final_inputs).IsTrustedbehavior thatUtxo::is_trusteddocuments. Before, change of an unconfirmed transaction showed up as confirmed and spendable.The remaining defect from the issue (U3,
dash-spvcredits its own broadcast locally without any network acceptance signal) is already tracked in #664. The BIP61rejecthandling suggested in the issue is not an option since Dash Core removed therejectmessage.Closes #832
Summary by CodeRabbit