1
1
mirror of https://github.com/bitcoin/bitcoin.git synced 2024-05-17 23:56:39 +00:00

refactor: Make CTxMemPoolEntry only explicitly copyable

This has the goal of prohibiting users from accidentally creating
runtime failures, e.g. by interacting with iterator_to with a copied
entry.

CTxMemPoolEntry is already implicitly not move-constructable. So be
explicit about this and use a std::list to collect the values in the
policy_estimator fuzz test instead of a std::vector.

Co-authored-by: Anthony Towns <aj@erisian.com.au>
This commit is contained in:
TheCharlatan 2023-11-17 20:28:14 +01:00
parent 22025d06e5
commit 705e3f1de0
No known key found for this signature in database
GPG Key ID: 9B79B45691DB4173
3 changed files with 15 additions and 3 deletions

View File

@ -71,6 +71,11 @@ public:
typedef std::set<CTxMemPoolEntryRef, CompareIteratorByHash> Children; typedef std::set<CTxMemPoolEntryRef, CompareIteratorByHash> Children;
private: private:
CTxMemPoolEntry(const CTxMemPoolEntry&) = default;
struct ExplicitCopyTag {
explicit ExplicitCopyTag() = default;
};
const CTransactionRef tx; const CTransactionRef tx;
mutable Parents m_parents; mutable Parents m_parents;
mutable Children m_children; mutable Children m_children;
@ -122,6 +127,13 @@ public:
nModFeesWithAncestors{nFee}, nModFeesWithAncestors{nFee},
nSigOpCostWithAncestors{sigOpCost} {} nSigOpCostWithAncestors{sigOpCost} {}
CTxMemPoolEntry(ExplicitCopyTag, const CTxMemPoolEntry& entry) : CTxMemPoolEntry(entry) {}
CTxMemPoolEntry& operator=(const CTxMemPoolEntry&) = delete;
CTxMemPoolEntry(CTxMemPoolEntry&&) = delete;
CTxMemPoolEntry& operator=(CTxMemPoolEntry&&) = delete;
static constexpr ExplicitCopyTag ExplicitCopy{};
const CTransaction& GetTx() const { return *this->tx; } const CTransaction& GetTx() const { return *this->tx; }
CTransactionRef GetSharedTx() const { return this->tx; } CTransactionRef GetSharedTx() const { return this->tx; }
const CAmount& GetFee() const { return nFee; } const CAmount& GetFee() const { return nFee; }

View File

@ -49,7 +49,7 @@ FUZZ_TARGET(policy_estimator, .init = initialize_policy_estimator)
} }
}, },
[&] { [&] {
std::vector<CTxMemPoolEntry> mempool_entries; std::list<CTxMemPoolEntry> mempool_entries;
LIMITED_WHILE(fuzzed_data_provider.ConsumeBool(), 10000) LIMITED_WHILE(fuzzed_data_provider.ConsumeBool(), 10000)
{ {
const std::optional<CMutableTransaction> mtx = ConsumeDeserializable<CMutableTransaction>(fuzzed_data_provider, TX_WITH_WITNESS); const std::optional<CMutableTransaction> mtx = ConsumeDeserializable<CMutableTransaction>(fuzzed_data_provider, TX_WITH_WITNESS);
@ -58,7 +58,7 @@ FUZZ_TARGET(policy_estimator, .init = initialize_policy_estimator)
break; break;
} }
const CTransaction tx{*mtx}; const CTransaction tx{*mtx};
mempool_entries.push_back(ConsumeTxMemPoolEntry(fuzzed_data_provider, tx)); mempool_entries.emplace_back(CTxMemPoolEntry::ExplicitCopy, ConsumeTxMemPoolEntry(fuzzed_data_provider, tx));
} }
std::vector<const CTxMemPoolEntry*> ptrs; std::vector<const CTxMemPoolEntry*> ptrs;
ptrs.reserve(mempool_entries.size()); ptrs.reserve(mempool_entries.size());

View File

@ -438,7 +438,7 @@ void CTxMemPool::addUnchecked(const CTxMemPoolEntry &entry, setEntries &setAnces
// Add to memory pool without checking anything. // Add to memory pool without checking anything.
// Used by AcceptToMemoryPool(), which DOES do // Used by AcceptToMemoryPool(), which DOES do
// all the appropriate checks. // all the appropriate checks.
indexed_transaction_set::iterator newit = mapTx.insert(entry).first; indexed_transaction_set::iterator newit = mapTx.emplace(CTxMemPoolEntry::ExplicitCopy, entry).first;
// Update transaction for any feeDelta created by PrioritiseTransaction // Update transaction for any feeDelta created by PrioritiseTransaction
CAmount delta{0}; CAmount delta{0};