mirror of
https://github.com/bitcoin/bitcoin.git
synced 2026-01-20 15:19:07 +01:00
wallet: track mempool conflicts
Behavior changes are: - if a tx has a mempool conflict, the wallet will not attempt to rebroadcast it - if a txo is spent by a mempool-conflicted tx, that txo is no longer considered spent
This commit is contained in:
@@ -753,7 +753,7 @@ bool CWallet::IsSpent(const COutPoint& outpoint) const
|
||||
const auto mit = mapWallet.find(wtxid);
|
||||
if (mit != mapWallet.end()) {
|
||||
const auto& wtx = mit->second;
|
||||
if (!wtx.isAbandoned() && !wtx.isBlockConflicted())
|
||||
if (!wtx.isAbandoned() && !wtx.isBlockConflicted() && !wtx.isMempoolConflicted())
|
||||
return true; // Spent
|
||||
}
|
||||
}
|
||||
@@ -1360,7 +1360,10 @@ void CWallet::MarkConflicted(const uint256& hashBlock, int conflicting_height, c
|
||||
void CWallet::RecursiveUpdateTxState(const uint256& tx_hash, const TryUpdatingStateFn& try_updating_state) EXCLUSIVE_LOCKS_REQUIRED(cs_wallet) {
|
||||
// Do not flush the wallet here for performance reasons
|
||||
WalletBatch batch(GetDatabase(), false);
|
||||
RecursiveUpdateTxState(&batch, tx_hash, try_updating_state);
|
||||
}
|
||||
|
||||
void CWallet::RecursiveUpdateTxState(WalletBatch* batch, const uint256& tx_hash, const TryUpdatingStateFn& try_updating_state) EXCLUSIVE_LOCKS_REQUIRED(cs_wallet) {
|
||||
std::set<uint256> todo;
|
||||
std::set<uint256> done;
|
||||
|
||||
@@ -1377,7 +1380,7 @@ void CWallet::RecursiveUpdateTxState(const uint256& tx_hash, const TryUpdatingSt
|
||||
TxUpdate update_state = try_updating_state(wtx);
|
||||
if (update_state != TxUpdate::UNCHANGED) {
|
||||
wtx.MarkDirty();
|
||||
batch.WriteTx(wtx);
|
||||
if (batch) batch->WriteTx(wtx);
|
||||
// Iterate over all its outputs, and update those tx states as well (if applicable)
|
||||
for (unsigned int i = 0; i < wtx.tx->vout.size(); ++i) {
|
||||
std::pair<TxSpends::const_iterator, TxSpends::const_iterator> range = mapTxSpends.equal_range(COutPoint(Txid::FromUint256(now), i));
|
||||
@@ -1418,6 +1421,20 @@ void CWallet::transactionAddedToMempool(const CTransactionRef& tx) {
|
||||
if (it != mapWallet.end()) {
|
||||
RefreshMempoolStatus(it->second, chain());
|
||||
}
|
||||
|
||||
const Txid& txid = tx->GetHash();
|
||||
|
||||
for (const CTxIn& tx_in : tx->vin) {
|
||||
// For each wallet transaction spending this prevout..
|
||||
for (auto range = mapTxSpends.equal_range(tx_in.prevout); range.first != range.second; range.first++) {
|
||||
const uint256& spent_id = range.first->second;
|
||||
// Skip the recently added tx
|
||||
if (spent_id == txid) continue;
|
||||
RecursiveUpdateTxState(/*batch=*/nullptr, spent_id, [&txid](CWalletTx& wtx) EXCLUSIVE_LOCKS_REQUIRED(cs_wallet) {
|
||||
return wtx.mempool_conflicts.insert(txid).second ? TxUpdate::CHANGED : TxUpdate::UNCHANGED;
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void CWallet::transactionRemovedFromMempool(const CTransactionRef& tx, MemPoolRemovalReason reason) {
|
||||
@@ -1455,6 +1472,21 @@ void CWallet::transactionRemovedFromMempool(const CTransactionRef& tx, MemPoolRe
|
||||
// https://github.com/bitcoin-core/bitcoin-devwiki/wiki/Wallet-Transaction-Conflict-Tracking
|
||||
SyncTransaction(tx, TxStateInactive{});
|
||||
}
|
||||
|
||||
const Txid& txid = tx->GetHash();
|
||||
|
||||
for (const CTxIn& tx_in : tx->vin) {
|
||||
// Iterate over all wallet transactions spending txin.prev
|
||||
// and recursively mark them as no longer conflicting with
|
||||
// txid
|
||||
for (auto range = mapTxSpends.equal_range(tx_in.prevout); range.first != range.second; range.first++) {
|
||||
const uint256& spent_id = range.first->second;
|
||||
|
||||
RecursiveUpdateTxState(/*batch=*/nullptr, spent_id, [&txid](CWalletTx& wtx) EXCLUSIVE_LOCKS_REQUIRED(cs_wallet) {
|
||||
return wtx.mempool_conflicts.erase(txid) ? TxUpdate::CHANGED : TxUpdate::UNCHANGED;
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void CWallet::blockConnected(ChainstateRole role, const interfaces::BlockInfo& block)
|
||||
|
||||
Reference in New Issue
Block a user