26 for (
const auto& outpoint : outpoints) {
51 for (
const auto& desc_txiter : descendants) {
61 std::vector<uint256> txids_needed;
64 txids_needed.push_back(txid);
67 if (cluster.empty()) {
75 for (
const auto& txiter : cluster) {
84 for (
const auto& outpoint : outpoints_it->second) {
93 for (
const auto& txiter : cluster) {
94 const auto& txid = txiter->GetTx().GetHash();
97 std::vector<MockEntryMap::iterator> cached_descendants;
101 Assume(descendants.count(txiter) > 0);
102 for (
const auto& desc_txiter : descendants) {
103 const auto txid_desc = desc_txiter->GetTx().GetHash();
107 if (remove)
Assume(remove_desc);
109 if (!remove && !remove_desc) {
110 cached_descendants.push_back(desc_it);
114 Assume(cached_descendants.empty());
137 const CAmount ancestor_fee{e.GetModFeesWithAncestors()};
138 const int64_t ancestor_size{e.GetSizeWithAncestors()};
139 const CAmount tx_fee{e.GetModifiedFee()};
140 const int64_t tx_size{e.GetTxSize()};
145 return ancestor_fee * tx_size < tx_fee * ancestor_size ?
146 CFeeRate(ancestor_fee, ancestor_size) :
149 CFeeRate a_feerate{min_feerate(a->second)};
150 CFeeRate b_feerate{min_feerate(b->second)};
151 if (a_feerate != b_feerate) {
152 return a_feerate > b_feerate;
155 return a->first < b->first;
161 Assume(ancestors.size() >= 1);
163 for (
auto& anc : ancestors) {
171 for (
auto& descendant : it->second) {
173 Assume(descendant->second.GetModFeesWithAncestors() >= anc->second.GetModifiedFee());
174 Assume(descendant->second.vsize_with_ancestors >= anc->second.GetTxSize());
175 descendant->second.fee_with_ancestors -= anc->second.GetModifiedFee();
176 descendant->second.vsize_with_ancestors -= anc->second.GetTxSize();
180 for (
const auto& anc : ancestors) {
184 Assume(anc->second.GetModFeesWithAncestors() == 0);
185 Assume(anc->second.GetSizeWithAncestors() == 0);
200 return entry->second.GetSizeWithAncestors() >= entry->second.GetTxSize() &&
201 entry->second.GetModFeesWithAncestors() >= entry->second.GetModifiedFee();}));
204 [&](
const auto& txid){return m_entries_by_txid.find(txid) == m_entries_by_txid.end();}));
216 const auto ancestor_package_size = (*best_iter)->second.GetSizeWithAncestors();
217 const auto ancestor_package_fee = (*best_iter)->second.GetModFeesWithAncestors();
219 if (ancestor_package_fee < target_feerate.
GetFee(ancestor_package_size)) {
225 std::set<MockEntryMap::iterator, IteratorComparator> ancestors;
227 std::set<MockEntryMap::iterator, IteratorComparator> to_process;
228 to_process.insert(*best_iter);
229 while (!to_process.empty()) {
230 auto iter = to_process.begin();
231 Assume(iter != to_process.end());
232 ancestors.insert(*iter);
233 for (
const auto& input : (*iter)->second.GetTx().vin) {
235 if (ancestors.count(parent_it) == 0) {
236 to_process.insert(parent_it);
240 to_process.erase(iter);
263 for (
const auto& outpoint : it->second) {
318 Assume(target_feerate.
GetFee(it->second.GetSizeWithAncestors()) > std::min(it->second.GetModifiedFee(), it->second.GetModFeesWithAncestors()));
319 CAmount bump_fee_with_ancestors = target_feerate.
GetFee(it->second.GetSizeWithAncestors()) - it->second.GetModFeesWithAncestors();
320 CAmount bump_fee_individual = target_feerate.
GetFee(it->second.GetTxSize()) - it->second.GetModifiedFee();
321 const CAmount bump_fee{std::max(bump_fee_with_ancestors, bump_fee_individual)};
323 for (
const auto& outpoint : outpoints) {
338 std::set<MockEntryMap::iterator, IteratorComparator> ancestors;
339 std::set<MockEntryMap::iterator, IteratorComparator> to_process;
346 to_process.insert(iter);
347 ancestors.insert(iter);
350 std::set<uint256> has_been_processed;
351 while (!to_process.empty()) {
352 auto iter = to_process.begin();
354 for (
const auto& input : tx.
vin) {
356 if (!has_been_processed.count(input.prevout.hash)) {
357 to_process.insert(parent_it);
359 ancestors.insert(parent_it);
362 has_been_processed.insert(tx.
GetHash());
363 to_process.erase(iter);
365 const auto ancestor_package_size = std::accumulate(ancestors.cbegin(), ancestors.cend(), int64_t{0},
366 [](int64_t
sum,
const auto it) {return sum + it->second.GetTxSize();});
367 const auto ancestor_package_fee = std::accumulate(ancestors.cbegin(), ancestors.cend(),
CAmount{0},
368 [](
CAmount sum,
const auto it) {return sum + it->second.GetModifiedFee();});
369 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.