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