24 for (
const auto& outpoint : outpoints) {
49 for (
const auto& desc_txiter : descendants) {
59 std::vector<uint256> txids_needed;
62 txids_needed.push_back(txid);
65 if (cluster.empty()) {
73 for (
const auto& txiter : cluster) {
82 for (
const auto& outpoint : outpoints_it->second) {
91 for (
const auto& txiter : cluster) {
92 const auto& txid = txiter->GetTx().GetHash();
95 std::vector<MockEntryMap::iterator> cached_descendants;
99 Assume(descendants.count(txiter) > 0);
100 for (
const auto& desc_txiter : descendants) {
101 const auto txid_desc = desc_txiter->GetTx().GetHash();
105 if (remove)
Assume(remove_desc);
107 if (!remove && !remove_desc) {
108 cached_descendants.push_back(desc_it);
112 Assume(cached_descendants.empty());
135 const CAmount ancestor_fee{e.GetModFeesWithAncestors()};
136 const int64_t ancestor_size{e.GetSizeWithAncestors()};
137 const CAmount tx_fee{e.GetModifiedFee()};
138 const int64_t tx_size{e.GetTxSize()};
143 return ancestor_fee * tx_size < tx_fee * ancestor_size ?
144 CFeeRate(ancestor_fee, ancestor_size) :
147 CFeeRate a_feerate{min_feerate(a->second)};
148 CFeeRate b_feerate{min_feerate(b->second)};
149 if (a_feerate != b_feerate) {
150 return a_feerate > b_feerate;
153 return a->first < b->first;
159 Assume(ancestors.size() >= 1);
161 for (
auto& anc : ancestors) {
169 for (
auto& descendant : it->second) {
171 Assume(descendant->second.GetModFeesWithAncestors() >= anc->second.GetModifiedFee());
172 Assume(descendant->second.GetSizeWithAncestors() >= anc->second.GetTxSize());
173 descendant->second.UpdateAncestorState(-anc->second.GetTxSize(), -anc->second.GetModifiedFee());
177 for (
const auto& anc : ancestors) {
181 Assume(anc->second.GetModFeesWithAncestors() == 0);
182 Assume(anc->second.GetSizeWithAncestors() == 0);
197 return entry->second.GetSizeWithAncestors() >= entry->second.GetTxSize() &&
198 entry->second.GetModFeesWithAncestors() >= entry->second.GetModifiedFee();}));
201 [&](
const auto& txid){return m_entries_by_txid.find(txid) == m_entries_by_txid.end();}));
213 const auto ancestor_package_size = (*best_iter)->second.GetSizeWithAncestors();
214 const auto ancestor_package_fee = (*best_iter)->second.GetModFeesWithAncestors();
216 if (ancestor_package_fee < target_feerate.
GetFee(ancestor_package_size)) {
222 std::set<MockEntryMap::iterator, IteratorComparator> ancestors;
224 std::set<MockEntryMap::iterator, IteratorComparator> to_process;
225 to_process.insert(*best_iter);
226 while (!to_process.empty()) {
227 auto iter = to_process.begin();
228 Assume(iter != to_process.end());
229 ancestors.insert(*iter);
230 for (
const auto& input : (*iter)->second.GetTx().vin) {
232 if (ancestors.count(parent_it) == 0) {
233 to_process.insert(parent_it);
237 to_process.erase(iter);
260 for (
const auto& outpoint : it->second) {
315 Assume(target_feerate.
GetFee(it->second.GetSizeWithAncestors()) > std::min(it->second.GetModifiedFee(), it->second.GetModFeesWithAncestors()));
316 CAmount bump_fee_with_ancestors = target_feerate.
GetFee(it->second.GetSizeWithAncestors()) - it->second.GetModFeesWithAncestors();
317 CAmount bump_fee_individual = target_feerate.
GetFee(it->second.GetTxSize()) - it->second.GetModifiedFee();
318 const CAmount bump_fee{std::max(bump_fee_with_ancestors, bump_fee_individual)};
320 for (
const auto& outpoint : outpoints) {
335 std::set<MockEntryMap::iterator, IteratorComparator> ancestors;
336 std::set<MockEntryMap::iterator, IteratorComparator> to_process;
343 to_process.insert(iter);
344 ancestors.insert(iter);
347 std::set<uint256> has_been_processed;
348 while (!to_process.empty()) {
349 auto iter = to_process.begin();
351 for (
const auto& input : tx.
vin) {
353 if (!has_been_processed.count(input.prevout.hash)) {
354 to_process.insert(parent_it);
356 ancestors.insert(parent_it);
359 has_been_processed.insert(tx.
GetHash());
360 to_process.erase(iter);
362 const auto ancestor_package_size = std::accumulate(ancestors.cbegin(), ancestors.cend(), int64_t{0},
363 [](int64_t
sum,
const auto it) {return sum + it->second.GetTxSize();});
364 const auto ancestor_package_fee = std::accumulate(ancestors.cbegin(), ancestors.cend(),
CAmount{0},
365 [](
CAmount sum,
const auto it) {return sum + it->second.GetModifiedFee();});
366 return target_feerate.
GetFee(ancestor_package_size) - ancestor_package_fee;
int64_t CAmount
Amount in satoshis (Can be negative)
#define Assume(val)
Assume is the identity function.
Fee rate in satoshis per kilovirtualbyte: CAmount / kvB.
CAmount GetFee(uint32_t num_bytes) const
Return the fee in satoshis for the given vsize in vbytes.
The basic transaction that is broadcasted on the network and contained in blocks.
const uint256 & GetHash() const
const std::vector< CTxIn > vin
CTxMemPool stores valid-according-to-the-current-best-chain transactions that may be included in the ...
RecursiveMutex cs
This mutex needs to be locked when accessing mapTx or other members that are guarded by it.
std::optional< txiter > GetIter(const uint256 &txid) const EXCLUSIVE_LOCKS_REQUIRED(cs)
Returns an iterator to the given hash, if found.
std::vector< txiter > GatherClusters(const std::vector< uint256 > &txids) const EXCLUSIVE_LOCKS_REQUIRED(cs)
Collect the entire cluster of connected transactions for each transaction in txids.
std::set< txiter, CompareIteratorByHash > setEntries
bool exists(const GenTxid >xid) const
const CTransaction * GetConflictTx(const COutPoint &prevout) const EXCLUSIVE_LOCKS_REQUIRED(cs)
Get the transaction in the pool that spends the same prevout.
void CalculateDescendants(txiter it, setEntries &setDescendants) const EXCLUSIVE_LOCKS_REQUIRED(cs)
Populate setDescendants with all in-mempool descendants of hash.
static GenTxid Txid(const uint256 &hash)
std::map< uint256, std::vector< MockEntryMap::iterator > > m_descendant_set_by_txid
Map of txid to its descendants.
void BuildMockTemplate(const CFeeRate &target_feerate)
Build a block template until the target feerate is hit.
std::map< COutPoint, CAmount > CalculateBumpFees(const CFeeRate &target_feerate)
Construct a new block template and, for each outpoint corresponding to a transaction that did not mak...
std::map< uint256, std::vector< COutPoint > > m_requested_outpoints_by_txid
std::optional< CAmount > CalculateTotalBumpFees(const CFeeRate &target_feerate)
Construct a new block template and, calculate the cost of bumping all transactions that did not make ...
std::set< uint256 > m_in_block
void DeleteAncestorPackage(const std::set< MockEntryMap::iterator, IteratorComparator > &ancestors)
Consider this ancestor package "mined" so remove all these entries from our data structures.
std::map< uint256, MiniMinerMempoolEntry > m_entries_by_txid
Main data structure holding the entries, can be indexed by txid.
void SanityCheck() const
Perform some checks.
std::vector< MockEntryMap::iterator > m_entries
Vector of entries, can be sorted by ancestor feerate.
MiniMiner(const CTxMemPool &mempool, const std::vector< COutPoint > &outpoints)
std::set< uint256 > m_to_be_replaced
std::map< COutPoint, CAmount > m_bump_fees
bool m_ready_to_calculate
bool operator()(const I &a, const I &b) const
bilingual_str _(const char *psz)
Translation function.