Skip to content

Commit

Permalink
Merge branch 'fix_mempool_hist' into HEAD
Browse files Browse the repository at this point in the history
  • Loading branch information
cculianu committed Sep 29, 2023
2 parents b4a7a90 + 1ad892d commit ac5e08e
Show file tree
Hide file tree
Showing 3 changed files with 22 additions and 10 deletions.
27 changes: 19 additions & 8 deletions src/Mempool.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
#include <cassert>
#include <functional>
#include <map>
#include <optional>
#include <utility>

void Mempool::clear() {
Expand All @@ -33,32 +34,42 @@ void Mempool::clear() {
hashXTxs.rehash(0);
}

auto Mempool::calcCompactFeeHistogram(double binSize) const -> FeeHistogramVec
auto Mempool::calcCompactFeeHistogram(unsigned binSizeBytes) const -> FeeHistogramVec
{
// this algorithm is taken from:
// https://github.com/Electron-Cash/electrumx/blob/fbd00416d804c286eb7de856e9399efb07a2ceaf/electrumx/server/mempool.py#L139
// This algorithm is taken from:
// https://github.com/spesmilo/electrumx/blob/bbd985a95db63cada13254bb766f174e9ab674d0/electrumx/server/mempool.py#L154
FeeHistogramVec ret;
std::map<unsigned, unsigned, std::greater<unsigned>> histogram; // sorted map, descending order by key

for (const auto & [txid, tx] : txs) {
if (tx->fee < bitcoin::Amount::zero()) continue; // skip negative fees (coinbase txn, etc)
const auto feeRate = unsigned(tx->fee / bitcoin::Amount::satoshi()) // sats
/ std::max(tx->sizeBytes, 1u); // per byte
histogram[feeRate] += tx->sizeBytes; // accumulate size by feeRate
}

// now, compact the bins
// Now, compact the bins
ret.reserve(8);
unsigned cumSize = 0;
double r = 0.;
double binSize = static_cast<double>(binSizeBytes);
std::optional<unsigned> prevFeeRate;

for (const auto & [feeRate, size] : histogram) {
// If there is a big lump of txns at this specific size,
// add the previous item now (if not added already)
if (double(size) > 2.0 * binSize && prevFeeRate && cumSize > 0) {
ret.emplace_back(*prevFeeRate, cumSize);
cumSize = 0;
binSize *= 1.1;
}
// Now work on perhaps adding this item
cumSize += size;
if (cumSize + r > binSize) {
ret.push_back(FeeHistogramItem{feeRate, cumSize});
r += double(cumSize) - binSize;
if (cumSize > binSize) {
ret.emplace_back(feeRate, cumSize);
cumSize = 0;
binSize *= 1.1;
}
prevFeeRate = feeRate;
}
ret.shrink_to_fit(); // save memory
return ret;
Expand Down
3 changes: 2 additions & 1 deletion src/Mempool.h
Original file line number Diff line number Diff line change
Expand Up @@ -209,12 +209,13 @@ struct Mempool
struct FeeHistogramItem {
unsigned feeRate = 0; // in sats/B, quotient truncated to uint.
unsigned cumulativeSize = 0; // bin size, cumulative bytes
FeeHistogramItem(unsigned fr, unsigned cs) : feeRate{fr}, cumulativeSize{cs} {}
};
using FeeHistogramVec = std::vector<FeeHistogramItem>;
/// This function is potentially going to take a couple of ms at worst on very large mempools. Even a 1.5k tx
/// mempool takes under 1 ms on average hardware, so it's very fast. Storage calls this in refreshMempoolHistogram
/// from a periodic background task kicked off in Controller.
FeeHistogramVec calcCompactFeeHistogram(double binSize = 1e5 /* binSize in bytes */) const;
FeeHistogramVec calcCompactFeeHistogram(unsigned binSize = 30'000 /* binSize in bytes */) const;

// -- Dump (for JSONesque debug support)

Expand Down
2 changes: 1 addition & 1 deletion src/Servers.h
Original file line number Diff line number Diff line change
Expand Up @@ -334,7 +334,7 @@ protected slots:
[[nodiscard]] static QVariantMap unspentItemToVariantMap(const Storage::UnspentItem &);
};

/// Implements the ElectrumX/ElectronX JSON-RPC protocol, version 1.4.4.
/// Implements the Electrum Cash JSON-RPC protocol: https://electrum-cash-protocol.readthedocs.io/en/latest/index.html
/// See also ServerSSL (subclass) which is identical but serves to SSL clients. (This class serves to TCP clients).
class Server : public ServerBase
{
Expand Down

0 comments on commit ac5e08e

Please sign in to comment.