Fixes #34599.
CWallet::AbandonTransaction walks the abandoned tx's descendants
via mapTxSpends and asserts that none of them is confirmed or in
the mempool. That holds at the consensus level — if the parent isn't
in the chain, no child can be — but the assertion runs against the
wallet's in-memory per-tx state, which can transiently diverge:
- during reorgs, where per-tx state transitions are processed individually and intermediate states are observable;
- around RBF candidates, where multiple wallet wtxs share an input
outpoint via
mapTxSpendsand so end up linked to the same parent output even though only one of them is the "real" descendant.
When the divergence is hit, the node aborts. The fix replaces the
two assert calls with a TxUpdate::UNCHANGED early-return so the
recursion safely halts at the inconsistent descendant instead of
crashing — preserving the original intent ("don't abandon something
that's confirmed or in mempool") and matching the no-assert pattern
already used by the sibling lambdas in MarkConflicted,
transactionAddedToMempool and transactionRemovedFromMempool.
A new wallet_tests/abandon_with_confirmed_descendant unit test
synthesises the inconsistency (parent TxStateInactive, child
TxStateConfirmed linked via mapTxSpends) and exercises the
assertion site directly: pre-fix it aborts, post-fix
AbandonTransaction returns true, marks the parent abandoned and
leaves the child untouched.
Precedent: PR #31757 / commit 9ef429b6ae fixed an analogous wallet assertion crash on double block disconnection by handling the inconsistent-state case rather than relying on the assertion.