mirror of
https://github.com/bitcoin/bitcoin.git
synced 2025-03-09 21:57:20 +01:00
test: Add CheckMempoolEphemeralInvariants
Checks that transactions in mempool with dust follow expected invariants.
This commit is contained in:
parent
e2e30e89ba
commit
127719f516
2 changed files with 60 additions and 0 deletions
|
@ -141,6 +141,54 @@ std::optional<std::string> CheckPackageMempoolAcceptResult(const Package& txns,
|
|||
return std::nullopt;
|
||||
}
|
||||
|
||||
std::vector<uint32_t> GetDustIndexes(const CTransactionRef tx_ref, CFeeRate dust_relay_rate)
|
||||
{
|
||||
std::vector<uint32_t> dust_indexes;
|
||||
for (size_t i = 0; i < tx_ref->vout.size(); ++i) {
|
||||
const auto& output = tx_ref->vout[i];
|
||||
if (IsDust(output, dust_relay_rate)) dust_indexes.push_back(i);
|
||||
}
|
||||
|
||||
return dust_indexes;
|
||||
}
|
||||
|
||||
void CheckMempoolEphemeralInvariants(const CTxMemPool& tx_pool)
|
||||
{
|
||||
LOCK(tx_pool.cs);
|
||||
for (const auto& tx_info : tx_pool.infoAll()) {
|
||||
const auto& entry = *Assert(tx_pool.GetEntry(tx_info.tx->GetHash()));
|
||||
|
||||
std::vector<uint32_t> dust_indexes = GetDustIndexes(tx_info.tx, tx_pool.m_opts.dust_relay_feerate);
|
||||
|
||||
Assert(dust_indexes.size() < 2);
|
||||
|
||||
if (dust_indexes.empty()) continue;
|
||||
|
||||
// Transaction must have no base fee
|
||||
Assert(entry.GetFee() == 0 && entry.GetModifiedFee() == 0);
|
||||
|
||||
// Transaction has single dust; make sure it's swept or will not be mined
|
||||
const auto& children = entry.GetMemPoolChildrenConst();
|
||||
|
||||
// Multiple children should never happen as non-dust-spending child
|
||||
// can get mined as package
|
||||
Assert(children.size() < 2);
|
||||
|
||||
if (children.empty()) {
|
||||
// No children and no fees; modified fees aside won't get mined so it's fine
|
||||
// Happens naturally if child spend is RBF cycled away.
|
||||
continue;
|
||||
}
|
||||
|
||||
// Only-child should be spending the dust
|
||||
const auto& only_child = children.begin()->get().GetTx();
|
||||
COutPoint dust_outpoint{tx_info.tx->GetHash(), dust_indexes[0]};
|
||||
Assert(std::any_of(only_child.vin.begin(), only_child.vin.end(), [&dust_outpoint](const CTxIn& txin) {
|
||||
return txin.prevout == dust_outpoint;
|
||||
}));
|
||||
}
|
||||
}
|
||||
|
||||
void CheckMempoolTRUCInvariants(const CTxMemPool& tx_pool)
|
||||
{
|
||||
LOCK(tx_pool.cs);
|
||||
|
|
|
@ -47,6 +47,18 @@ std::optional<std::string> CheckPackageMempoolAcceptResult(const Package& txns,
|
|||
bool expect_valid,
|
||||
const CTxMemPool* mempool);
|
||||
|
||||
/** Check that we never get into a state where an ephemeral dust
|
||||
* transaction would be mined without the spend of the dust
|
||||
* also being mined. This assumes standardness checks are being
|
||||
* enforced.
|
||||
*/
|
||||
void CheckMempoolEphemeralInvariants(const CTxMemPool& tx_pool);
|
||||
|
||||
/** Return indexes of the transaction's outputs that are considered dust
|
||||
* at given dust_relay_rate.
|
||||
*/
|
||||
std::vector<uint32_t> GetDustIndexes(const CTransactionRef tx_ref, CFeeRate dust_relay_rate);
|
||||
|
||||
/** For every transaction in tx_pool, check TRUC invariants:
|
||||
* - a TRUC tx's ancestor count must be within TRUC_ANCESTOR_LIMIT
|
||||
* - a TRUC tx's descendant count must be within TRUC_DESCENDANT_LIMIT
|
||||
|
|
Loading…
Add table
Reference in a new issue