fix(wallet): restore redeemed DD positions after importdescriptors#388
Merged
JaredTate merged 3 commits intofeature/digidollar-v1from Mar 5, 2026
Merged
Conversation
Bug #8: After wallet recovery via listdescriptors/importdescriptors, the wallet GUI showed active 'Redeem DigiDollar' buttons for positions that were already redeemed. Reported multiple times by users. ROOT CAUSE (two bugs): 1. ProcessDDTxForRescan relied solely on OP_RETURN parsing to detect DD transaction types. Full-redemption REDEEM txs (ddChange == 0) have NO OP_RETURN with DD metadata, making them invisible to the rescan parser. Positions were created during MINT processing but never marked inactive when the REDEEM tx was encountered. 2. ValidatePositionStates() — which cross-checks every active position against the actual UTXO set — only ran at wallet startup (postInitProcess), never after importdescriptors or rescanblockchain rescans. FIX: 1. ProcessDDTxForRescan now uses GetDigiDollarTxType() (version field) as the primary tx type detection. The version field ALWAYS encodes the type correctly via SetDigiDollarType(). OP_RETURN parsing is retained for supplementary data extraction (DD change amounts). 2. ScanForWalletTransactions() now calls ScanForDDUTXOs() after any successful rescan completes. This runs ValidatePositionStates() which cross-checks all active positions against the UTXO set, catching any positions whose collateral was spent (redeemed). Both fixes are defense-in-depth: Fix 1 prevents the bug, Fix 2 catches any edge cases that Fix 1 might miss (e.g., blocks skipped by the fast BIP158 block filter during rescan). Includes functional test: digidollar_wallet_restore_redeem.py
These 4 p2p tests test bloom filter rejection, disconnect/ban behavior, invalid transactions, and compact blocks — none of them test Dandelion. Dandelion++ adds INV/GETDATA/NOTFOUND exchanges during peer handshake that create thread scheduling races between ThreadMessageHandler and ThreadSocketHandler on slow macOS CI runners, causing disconnect detection timeouts. Adding -dandelion=0 is proper test isolation: these tests should test what they're designed to test without interference from an unrelated feature. The dedicated p2p_dandelion.py test covers Dandelion behavior. Also removes the macOS --exclude list from ci.yml so all p2p tests now run on both platforms — no more skipped tests.
… test After disconnect_nodes(3, 4), the Dandelion stempool thread may leave the RPC HTTP connection in Request-sent state. When stop_nodes() fires in shutdown(), it gets CannotSendRequest on nodes 3/4 (Dandelion-enabled), causing the macOS ARM64 CI runner to fail with leftover processes. Add a 5s sleep post-disconnect to let Dandelion thread state drain cleanly before the test framework's stop_nodes() is called. Reproduces reliably on macOS 14 ARM64 GitHub Actions runners.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Reopens #386 with the proper Dandelion++ fix included.
Summary
Fixes Bug #8: After wallet recovery via
listdescriptors true→importdescriptors, the Qt wallet shows active "Redeem DigiDollar" buttons for positions that have already been redeemed.Root Cause (two bugs)
1. Full-redemption REDEEM txs invisible to rescan parser
ProcessDDTxForRescan()relied solely on OP_RETURN parsing. Full-redemption REDEEM transactions (ddChange == 0) have no OP_RETURN — soddTxTypestayed0, the REDEEM branch was never entered, and positions were never markedis_active = falseduring rescan.2. ValidatePositionStates() only ran at startup
Was designed as a safety net but only fired from
postInitProcess(), never afterimportdescriptorsorrescanblockchain.Fix
Fix 1:
ProcessDDTxForRescannow usesGetDigiDollarTxType(tx)(version field) as primary type detection.Fix 2:
ScanForWalletTransactions()now callsScanForDDUTXOs()after any successful rescan.Dandelion++ CI Fix
Adds
-dandelion=0to 4 p2p tests that test bloom filters, disconnect/ban, invalid txs, and compact blocks — none of which test Dandelion. Dandelion++ adds INV/GETDATA/NOTFOUND exchanges during peer handshake that cause thread scheduling races on slow macOS CI runners. The dedicatedp2p_dandelion.pytest covers Dandelion behavior. Also removes the macOS--excludelist so all p2p tests run on both platforms.Testing
digidollar_wallet_restore_redeem.pydigidollar_redemption_e2e.py,digidollar_persistence.py,digidollar_mint.py