@@ -174,6 +174,58 @@ class NodeImpl : public Node
174174 int64_t getTotalBytesSent () override { return m_context->connman ? m_context->connman ->GetTotalBytesSent () : 0 ; }
175175 size_t getMempoolSize () override { return m_context->mempool ? m_context->mempool ->size () : 0 ; }
176176 size_t getMempoolDynamicUsage () override { return m_context->mempool ? m_context->mempool ->DynamicMemoryUsage () : 0 ; }
177+ interfaces::mempool_feehistogram getMempoolFeeHistogram () override {
178+ /* TODO: define log scale formular for dynamically creating the
179+ * feelimits but with the property of not constantly changing
180+ * (and thus screw up client implementations) */
181+ static const std::vector<CAmount> feelimits{1 , 2 , 3 , 4 , 5 , 6 , 7 , 8 , 10 ,
182+ 12 , 14 , 17 , 20 , 25 , 30 , 40 , 50 , 60 , 70 , 80 , 100 ,
183+ 120 , 140 , 170 , 200 , 250 , 300 , 400 , 500 , 600 , 700 , 800 , 1000 ,
184+ 1200 , 1400 , 1700 , 2000 , 2500 , 3000 , 4000 , 5000 , 6000 , 7000 , 8000 , 10000 };
185+
186+ /* keep histogram per...
187+ * ... cumulated tx sizes
188+ * ... txns (count)
189+ * ... cumulated fees */
190+ std::vector<uint64_t > sizes (feelimits.size (), 0 );
191+ std::vector<uint64_t > count (feelimits.size (), 0 );
192+ std::vector<uint64_t > fees (feelimits.size (), 0 );
193+
194+ {
195+ LOCK (m_context->mempool ->cs );
196+ for (const CTxMemPoolEntry& e : m_context->mempool ->mapTx ) {
197+ int size = (int )e.GetTxSize ();
198+ CAmount fee = e.GetFee ();
199+ uint64_t asize = e.GetSizeWithAncestors ();
200+ CAmount afees = e.GetModFeesWithAncestors ();
201+ uint64_t dsize = e.GetSizeWithDescendants ();
202+ CAmount dfees = e.GetModFeesWithDescendants ();
203+
204+ CAmount fpb = fee / size; // fee per byte
205+ CAmount afpb = afees / asize; // fee per byte including ancestors
206+ CAmount dfpb = dfees / dsize; // fee per byte including descendants
207+ CAmount tfpb = (afees + dfees - fee) / (asize + dsize - size);
208+ CAmount feeperbyte = std::max (std::min (dfpb, tfpb), std::min (fpb, afpb));
209+
210+ // distribute feerates into feelimits
211+ for (size_t i = 0 ; i < feelimits.size (); i++) {
212+ if (feeperbyte >= feelimits[i] && (i == feelimits.size () - 1 || feeperbyte < feelimits[i + 1 ])) {
213+ sizes[i] += size;
214+ count[i]++;
215+ fees[i] += fee;
216+ break ;
217+ }
218+ }
219+ }
220+ }
221+ interfaces::mempool_feehistogram feeinfo;
222+ for (size_t i = 0 ; i < feelimits.size (); i++) {
223+ feeinfo.push_back ({sizes[i], fees[i], count[i], feelimits[i], (i == feelimits.size () - 1 ? std::numeric_limits<int64_t >::max () : feelimits[i + 1 ])});
224+ }
225+
226+ return feeinfo;
227+ }
228+
177229 bool getHeaderTip (int & height, int64_t & block_time) override
178230 {
179231 LOCK (::cs_main);
0 commit comments