0
0
Fork 0
mirror of https://github.com/bitcoin/bitcoin.git synced 2025-02-02 09:46:52 -05:00

MiniMiner: use FeeFrac in AncestorFeerateComparator

Comparing using FeeFracs is more precise, allows us to simply the
code since FeeFrac comparison internally does cross-multiplication,
and avoids potential overflow in the multiplication.

Previously, we were only comparing feerates up to 0.001sat/vB precision,
since CFeeRate comparison just looks at their respective nSatoshisPerK.
This could lead to MiniMiner selecting packages in the wrong order (i.e.
by txid) if their feerates were less than 0.001sat/vB different.
This commit is contained in:
glozow 2024-07-09 13:47:30 +01:00
parent 1f9d30744d
commit de273d5300

View file

@ -174,7 +174,7 @@ MiniMiner::MiniMiner(const std::vector<MiniMinerMempoolEntry>& manual_entries,
SanityCheck(); SanityCheck();
} }
// Compare by min(ancestor feerate, individual feerate), then iterator // Compare by min(ancestor feerate, individual feerate), then txid
// //
// Under the ancestor-based mining approach, high-feerate children can pay for parents, but high-feerate // Under the ancestor-based mining approach, high-feerate children can pay for parents, but high-feerate
// parents do not incentive inclusion of their children. Therefore the mining algorithm only considers // parents do not incentive inclusion of their children. Therefore the mining algorithm only considers
@ -183,21 +183,13 @@ struct AncestorFeerateComparator
{ {
template<typename I> template<typename I>
bool operator()(const I& a, const I& b) const { bool operator()(const I& a, const I& b) const {
auto min_feerate = [](const MiniMinerMempoolEntry& e) -> CFeeRate { auto min_feerate = [](const MiniMinerMempoolEntry& e) -> FeeFrac {
const CAmount ancestor_fee{e.GetModFeesWithAncestors()}; FeeFrac self_feerate(e.GetModifiedFee(), e.GetTxSize());
const int64_t ancestor_size{e.GetSizeWithAncestors()}; FeeFrac ancestor_feerate(e.GetModFeesWithAncestors(), e.GetSizeWithAncestors());
const CAmount tx_fee{e.GetModifiedFee()}; return std::min(ancestor_feerate, self_feerate);
const int64_t tx_size{e.GetTxSize()};
// Comparing ancestor feerate with individual feerate:
// ancestor_fee / ancestor_size <= tx_fee / tx_size
// Avoid division and possible loss of precision by
// multiplying both sides by the sizes:
return ancestor_fee * tx_size < tx_fee * ancestor_size ?
CFeeRate(ancestor_fee, ancestor_size) :
CFeeRate(tx_fee, tx_size);
}; };
CFeeRate a_feerate{min_feerate(a->second)}; FeeFrac a_feerate{min_feerate(a->second)};
CFeeRate b_feerate{min_feerate(b->second)}; FeeFrac b_feerate{min_feerate(b->second)};
if (a_feerate != b_feerate) { if (a_feerate != b_feerate) {
return a_feerate > b_feerate; return a_feerate > b_feerate;
} }