mirror of
https://github.com/bitcoin/bitcoin.git
synced 2025-04-29 14:59:39 -04:00
wallet, tests: mark unconflicted txs as inactive
In `blockDisconnected`, for each transaction in the block, look for any wallet transactions spending the same inputs. If any of these transactions were marked conflicted, they are now marked as inactive. Co-authored-by: ariard <antoine.riard@gmail.com>
This commit is contained in:
parent
096487c4dc
commit
dced203162
2 changed files with 32 additions and 8 deletions
|
@ -1446,8 +1446,36 @@ void CWallet::blockDisconnected(const interfaces::BlockInfo& block)
|
||||||
// future with a stickier abandoned state or even removing abandontransaction call.
|
// future with a stickier abandoned state or even removing abandontransaction call.
|
||||||
m_last_block_processed_height = block.height - 1;
|
m_last_block_processed_height = block.height - 1;
|
||||||
m_last_block_processed = *Assert(block.prev_hash);
|
m_last_block_processed = *Assert(block.prev_hash);
|
||||||
|
|
||||||
|
int disconnect_height = block.height;
|
||||||
|
|
||||||
for (const CTransactionRef& ptx : Assert(block.data)->vtx) {
|
for (const CTransactionRef& ptx : Assert(block.data)->vtx) {
|
||||||
SyncTransaction(ptx, TxStateInactive{});
|
SyncTransaction(ptx, TxStateInactive{});
|
||||||
|
|
||||||
|
for (const CTxIn& tx_in : ptx->vin) {
|
||||||
|
// No other wallet transactions conflicted with this transaction
|
||||||
|
if (mapTxSpends.count(tx_in.prevout) < 1) continue;
|
||||||
|
|
||||||
|
std::pair<TxSpends::const_iterator, TxSpends::const_iterator> range = mapTxSpends.equal_range(tx_in.prevout);
|
||||||
|
|
||||||
|
// For all of the spends that conflict with this transaction
|
||||||
|
for (TxSpends::const_iterator _it = range.first; _it != range.second; ++_it) {
|
||||||
|
CWalletTx& wtx = mapWallet.find(_it->second)->second;
|
||||||
|
|
||||||
|
if (!wtx.isConflicted()) continue;
|
||||||
|
|
||||||
|
auto try_updating_state = [&](CWalletTx& tx) {
|
||||||
|
if (!tx.isConflicted()) return TxUpdate::UNCHANGED;
|
||||||
|
if (tx.state<TxStateConflicted>()->conflicting_block_height >= disconnect_height) {
|
||||||
|
tx.m_state = TxStateInactive{};
|
||||||
|
return TxUpdate::CHANGED;
|
||||||
|
}
|
||||||
|
return TxUpdate::UNCHANGED;
|
||||||
|
};
|
||||||
|
|
||||||
|
RecursiveUpdateTxState(wtx.tx->GetHash(), try_updating_state);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -226,20 +226,16 @@ class AbandonConflictTest(BitcoinTestFramework):
|
||||||
assert_equal(double_spend["walletconflicts"], [txAB1])
|
assert_equal(double_spend["walletconflicts"], [txAB1])
|
||||||
|
|
||||||
# Verify that B and C's 10 BTC outputs are available for spending again because AB1 is now conflicted
|
# Verify that B and C's 10 BTC outputs are available for spending again because AB1 is now conflicted
|
||||||
|
assert_equal(alice.gettransaction(txAB1)["confirmations"], -1)
|
||||||
newbalance = alice.getbalance()
|
newbalance = alice.getbalance()
|
||||||
assert_equal(newbalance, balance + Decimal("20"))
|
assert_equal(newbalance, balance + Decimal("20"))
|
||||||
balance = newbalance
|
balance = newbalance
|
||||||
|
|
||||||
# There is currently a minor bug around this and so this test doesn't work. See Issue #7315
|
# Invalidate the block with the double spend. B & C's 10 BTC outputs should no longer be available
|
||||||
# Invalidate the block with the double spend and B's 10 BTC output should no longer be available
|
|
||||||
# Don't think C's should either
|
|
||||||
self.nodes[0].invalidateblock(self.nodes[0].getbestblockhash())
|
self.nodes[0].invalidateblock(self.nodes[0].getbestblockhash())
|
||||||
|
assert_equal(alice.gettransaction(txAB1)["confirmations"], 0)
|
||||||
newbalance = alice.getbalance()
|
newbalance = alice.getbalance()
|
||||||
#assert_equal(newbalance, balance - Decimal("10"))
|
assert_equal(newbalance, balance - Decimal("20"))
|
||||||
self.log.info("If balance has not declined after invalidateblock then out of mempool wallet tx which is no longer")
|
|
||||||
self.log.info("conflicted has not resumed causing its inputs to be seen as spent. See Issue #7315")
|
|
||||||
assert_equal(balance, newbalance)
|
|
||||||
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
AbandonConflictTest().main()
|
AbandonConflictTest().main()
|
||||||
|
|
Loading…
Add table
Reference in a new issue