mirror of
https://github.com/dashpay/dash.git
synced 2024-12-24 19:42:46 +01:00
Merge bitcoin/bitcoin#23976: document and clean up MaybeUpdateMempoolForReorg
e177fcab3831b6d259da5164cabedcc9e78f6957 Replace `struct update_lock_points` with lambda (glozow) c7cd98c7176800a51e6a6b3634a26b508aa33ff2 document and clean up MaybeUpdateMempoolForReorg (glozow) Pull request description: followup to #23683, addressing https://github.com/bitcoin/bitcoin/pull/23683#issuecomment-989741186 ACKs for top commit: hebasto: ACK e177fcab3831b6d259da5164cabedcc9e78f6957, I have reviewed the code and it looks OK, I agree it can be merged. instagibbs: ACK e177fcab3831b6d259da5164cabedcc9e78f6957 MarcoFalke: Approach ACK e177fcab3831b6d259da5164cabedcc9e78f6957 😶 Tree-SHA512: 8c2709dd5cab73cde41f3e5655d5f237bacfb341f78eac026169be579528695ca628c8777b7d89760d8677a4e6786913293681cfe16ab702b30c909703e1824c
This commit is contained in:
parent
73e1861576
commit
acbf718b57
@ -311,16 +311,6 @@ public:
|
||||
}
|
||||
};
|
||||
|
||||
struct update_lock_points
|
||||
{
|
||||
explicit update_lock_points(const LockPoints& _lp) : lp(_lp) { }
|
||||
|
||||
void operator() (CTxMemPoolEntry &e) { e.UpdateLockPoints(lp); }
|
||||
|
||||
private:
|
||||
const LockPoints& lp;
|
||||
};
|
||||
|
||||
// Multi_index tag names
|
||||
struct descendant_score {};
|
||||
struct entry_time {};
|
||||
@ -634,10 +624,14 @@ public:
|
||||
bool removeSpentIndex(const uint256 txhash);
|
||||
|
||||
void removeRecursive(const CTransaction& tx, MemPoolRemovalReason reason) EXCLUSIVE_LOCKS_REQUIRED(cs);
|
||||
/** After reorg, check if mempool entries are now non-final, premature coinbase spends, or have
|
||||
* invalid lockpoints. Update lockpoints and remove entries (and descendants of entries) that
|
||||
* are no longer valid. */
|
||||
void removeForReorg(CChain& chain, std::function<bool(txiter)> check_final_and_mature) EXCLUSIVE_LOCKS_REQUIRED(cs, cs_main);
|
||||
/** After reorg, filter the entries that would no longer be valid in the next block, and update
|
||||
* the entries' cached LockPoints if needed. The mempool does not have any knowledge of
|
||||
* consensus rules. It just appplies the callable function and removes the ones for which it
|
||||
* returns true.
|
||||
* @param[in] filter_final_and_mature Predicate that checks the relevant validation rules
|
||||
* and updates an entry's LockPoints.
|
||||
* */
|
||||
void removeForReorg(CChain& chain, std::function<bool(txiter)> filter_final_and_mature) EXCLUSIVE_LOCKS_REQUIRED(cs, cs_main);
|
||||
void removeConflicts(const CTransaction& tx) EXCLUSIVE_LOCKS_REQUIRED(cs);
|
||||
void removeProTxPubKeyConflicts(const CTransaction &tx, const CKeyID &keyId) EXCLUSIVE_LOCKS_REQUIRED(cs);
|
||||
void removeProTxPubKeyConflicts(const CTransaction &tx, const CBLSLazyPublicKey &pubKey) EXCLUSIVE_LOCKS_REQUIRED(cs);
|
||||
|
@ -373,21 +373,37 @@ void CChainState::MaybeUpdateMempoolForReorg(
|
||||
// the disconnectpool that were added back and cleans up the mempool state.
|
||||
m_mempool->UpdateTransactionsFromBlock(vHashUpdate);
|
||||
|
||||
const auto check_final_and_mature = [this, flags=STANDARD_LOCKTIME_VERIFY_FLAGS](CTxMemPool::txiter it)
|
||||
// Predicate to use for filtering transactions in removeForReorg.
|
||||
// Checks whether the transaction is still final and, if it spends a coinbase output, mature.
|
||||
// Also updates valid entries' cached LockPoints if needed.
|
||||
// If false, the tx is still valid and its lockpoints are updated.
|
||||
// If true, the tx would be invalid in the next block; remove this entry and all of its descendants.
|
||||
const auto filter_final_and_mature = [this, flags=STANDARD_LOCKTIME_VERIFY_FLAGS](CTxMemPool::txiter it)
|
||||
EXCLUSIVE_LOCKS_REQUIRED(m_mempool->cs, ::cs_main) {
|
||||
bool should_remove = false;
|
||||
AssertLockHeld(m_mempool->cs);
|
||||
AssertLockHeld(::cs_main);
|
||||
const CTransaction& tx = it->GetTx();
|
||||
|
||||
// The transaction must be final.
|
||||
if (!CheckFinalTx(m_chain.Tip(), tx, flags)) return true;
|
||||
LockPoints lp = it->GetLockPoints();
|
||||
const bool validLP{TestLockPointValidity(m_chain, lp)};
|
||||
CCoinsViewMemPool view_mempool(&CoinsTip(), *m_mempool);
|
||||
if (!CheckFinalTx(m_chain.Tip(), tx, flags)
|
||||
|| !CheckSequenceLocks(m_chain.Tip(), view_mempool, tx, flags, &lp, validLP)) {
|
||||
// Note if CheckSequenceLocks fails the LockPoints may still be invalid
|
||||
// So it's critical that we remove the tx and not depend on the LockPoints.
|
||||
should_remove = true;
|
||||
} else if (it->GetSpendsCoinbase()) {
|
||||
// CheckSequenceLocks checks if the transaction will be final in the next block to be
|
||||
// created on top of the new chain. We use useExistingLockPoints=false so that, instead of
|
||||
// using the information in lp (which might now refer to a block that no longer exists in
|
||||
// the chain), it will update lp to contain LockPoints relevant to the new chain.
|
||||
if (!CheckSequenceLocks(m_chain.Tip(), view_mempool, tx, flags, &lp, validLP)) {
|
||||
// If CheckSequenceLocks fails, remove the tx and don't depend on the LockPoints.
|
||||
return true;
|
||||
} else if (!validLP) {
|
||||
// If CheckSequenceLocks succeeded, it also updated the LockPoints.
|
||||
// Now update the mempool entry lockpoints as well.
|
||||
m_mempool->mapTx.modify(it, [&lp](CTxMemPoolEntry& e) { e.UpdateLockPoints(lp); });
|
||||
}
|
||||
|
||||
// If the transaction spends any coinbase outputs, it must be mature.
|
||||
if (it->GetSpendsCoinbase()) {
|
||||
for (const CTxIn& txin : tx.vin) {
|
||||
auto it2 = m_mempool->mapTx.find(txin.prevout.hash);
|
||||
if (it2 != m_mempool->mapTx.end())
|
||||
@ -396,18 +412,16 @@ void CChainState::MaybeUpdateMempoolForReorg(
|
||||
assert(!coin.IsSpent());
|
||||
const auto mempool_spend_height{m_chain.Tip()->nHeight + 1};
|
||||
if (coin.IsSpent() || (coin.IsCoinBase() && mempool_spend_height - coin.nHeight < COINBASE_MATURITY)) {
|
||||
should_remove = true;
|
||||
break;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
// CheckSequenceLocks updates lp. Update the mempool entry LockPoints.
|
||||
if (!validLP) m_mempool->mapTx.modify(it, update_lock_points(lp));
|
||||
return should_remove;
|
||||
// Transaction is still valid and cached LockPoints are updated.
|
||||
return false;
|
||||
};
|
||||
|
||||
// We also need to remove any now-immature transactions
|
||||
m_mempool->removeForReorg(m_chain, check_final_and_mature);
|
||||
m_mempool->removeForReorg(m_chain, filter_final_and_mature);
|
||||
// Re-limit mempool size, in case we added any transactions
|
||||
LimitMempoolSize(
|
||||
*m_mempool,
|
||||
|
Loading…
Reference in New Issue
Block a user