Skip to content

Commit d1ec9fa

Browse files
committed
Fee queries optimizations, style, comments.
1 parent b53c861 commit d1ec9fa

2 files changed

Lines changed: 25 additions & 127 deletions

File tree

include/bitcoin/database/impl/query/archive_read.ipp

Lines changed: 5 additions & 71 deletions
Original file line numberDiff line numberDiff line change
@@ -346,86 +346,20 @@ bool CLASS::get_tx_spend(uint64_t& out, const tx_link& link) const NOEXCEPT
346346
TEMPLATE
347347
bool CLASS::get_tx_fee(uint64_t& out, const tx_link& link) const NOEXCEPT
348348
{
349-
#if defined(SLOW_FEES)
350-
const auto tx = get_transaction(link, false);
351-
if (!tx)
352-
return false;
353-
354-
// Prevent coinbase populate failure.
355-
if (tx->is_coinbase())
356-
{
357-
out = zero;
358-
return true;
359-
}
360-
361-
if (!populate_without_metadata(*tx))
362-
return false;
363-
364-
out = tx->fee();
365-
return true;
366-
#elif defined(FAST_FEES)
367-
table::transaction::get_coinbase tx{};
368-
if (!store_.tx.get(link, tx))
369-
return false;
370-
371-
// Prevent coinbase overspend failure.
372-
if (tx.coinbase)
373-
{
374-
out = zero;
375-
return true;
376-
}
377-
378-
uint64_t value{}, spend{};
379-
if (!get_tx_value(value, link) || !get_tx_spend(spend, link) ||
380-
spend > value)
381-
return false;
382-
383-
out = value - spend;
384-
return true;
385-
#else // FASTER_FEES
386-
table::transaction::get_puts tx{};
387-
if (!store_.tx.get(link, tx))
349+
uint64_t value{};
350+
if (!get_tx_value(value, link))
388351
return false;
389352

390-
// Shortcircuit coinbase prevout read.
391-
if (tx.coinbase)
392-
{
393-
out = zero;
353+
// Zero input implies either zero output or coinbase (both zero).
354+
if (is_zero(value))
394355
return true;
395-
}
396-
397-
uint64_t value{};
398-
auto point_fk = tx.points_fk;
399-
for (size_t index{}; index < tx.ins_count; ++index)
400-
{
401-
table::point::get_composed point{};
402-
if (!store_.point.get(point_fk++, point))
403-
return false;
404-
405-
uint64_t one_value{};
406-
if (!get_value(one_value, to_output(point.key))) return false;
407-
value = system::ceilinged_add(value, one_value);
408-
}
409-
410-
table::outs::record outs{};
411-
outs.out_fks.resize(tx.outs_count);
412-
if (!store_.outs.get(tx.outs_fk, outs))
413-
return false;
414356

415357
uint64_t spend{};
416-
for (const auto& output_fk: outs.out_fks)
417-
{
418-
uint64_t one_spend{};
419-
if (!get_value(one_spend, output_fk)) return false;
420-
spend = system::ceilinged_add(spend, one_spend);
421-
}
422-
423-
if (spend > value)
358+
if (!get_tx_spend(spend, link) || spend > value)
424359
return false;
425360

426361
out = value - spend;
427362
return true;
428-
#endif // SLOW_FEES
429363
}
430364

431365
TEMPLATE

include/bitcoin/database/impl/query/fees.ipp

Lines changed: 20 additions & 56 deletions
Original file line numberDiff line numberDiff line change
@@ -22,17 +22,16 @@
2222
#include <atomic>
2323
#include <algorithm>
2424
#include <iterator>
25-
#include <memory>
2625
#include <numeric>
2726
#include <utility>
2827
#include <bitcoin/database/define.hpp>
2928

30-
// virtual_size
31-
// ----------------------------------------------------------------------------
32-
3329
namespace libbitcoin {
3430
namespace database {
3531

32+
// virtual_size
33+
// ----------------------------------------------------------------------------
34+
3635
TEMPLATE
3736
bool CLASS::get_tx_virtual_size(size_t& out,
3837
const tx_link& link) const NOEXCEPT
@@ -63,70 +62,36 @@ bool CLASS::get_block_virtual_size(size_t& out,
6362
TEMPLATE
6463
bool CLASS::get_tx_fees(fee_rate& out, const tx_link& link) const NOEXCEPT
6564
{
66-
#if defined(SLOW_FEES)
65+
// This is somehow ~15-20% less efficient.
66+
////return get_tx_virtual_size(out.bytes, link) && get_tx_fee(out.fee, link);
6767
const auto tx = get_transaction(link, false);
6868
if (!tx || tx->is_coinbase() || !populate_without_metadata(*tx))
6969
return false;
7070

7171
out.bytes = tx->virtual_size();
7272
out.fee = tx->fee();
7373
return true;
74-
#else
75-
table::transaction::get_coinbase tx{};
76-
if (!store_.tx.get(link, tx) || tx.coinbase)
77-
return false;
78-
79-
return get_tx_virtual_size(out.bytes, link) && get_tx_fee(out.fee, link);
80-
#endif // SLOW_FEES
8174
}
82-
75+
8376
TEMPLATE
8477
bool CLASS::get_block_fees(fee_rates& out,
8578
const header_link& link) const NOEXCEPT
8679
{
87-
#if defined(SLOW_FEES)
88-
out.clear();
89-
const auto block = get_block(link, false);
90-
if (!block)
91-
return false;
92-
93-
block->populate();
94-
if (!populate_without_metadata(*block))
95-
return false;
96-
97-
const auto& txs = *block->transactions_ptr();
98-
if (txs.empty())
99-
return false;
100-
101-
out.reserve(txs.size());
102-
for (auto tx = std::next(txs.begin()); tx != txs.end(); ++tx)
103-
out.emplace_back((*tx)->virtual_size(), (*tx)->fee());
104-
105-
return true;
106-
#else // FAST_FEES|FASTER_FEES
10780
out.clear();
10881
table::txs::get_txs txs{};
10982
if (!store_.txs.at(to_txs(link), txs) || (txs.tx_fks.size() < one))
11083
return false;
11184

112-
std::atomic_bool fail{};
11385
out.resize(sub1(txs.tx_fks.size()));
114-
const auto begin = std::next(txs.tx_fks.begin());
115-
constexpr auto parallel = poolstl::execution::par;
116-
constexpr auto relaxed = std::memory_order_relaxed;
86+
const auto end = txs.tx_fks.end();
87+
auto rate = out.begin();
11788

118-
std::transform(parallel, begin, txs.tx_fks.end(), out.begin(),
119-
[&](const auto& tx_fk) NOEXCEPT
120-
{
121-
fee_rate rate{};
122-
if (!fail.load(relaxed) && !get_tx_fees(rate, tx_fk))
123-
fail.store(true, relaxed);
124-
125-
return rate;
126-
});
89+
// Skip coinbase.
90+
for (auto tx = std::next(txs.tx_fks.begin()); tx != end; ++tx)
91+
if (!get_tx_fees(*rate++, *tx))
92+
return false;
12793

128-
return !fail.load(relaxed);
129-
#endif // SLOW_FEES
94+
return true;
13095
}
13196

13297
TEMPLATE
@@ -137,20 +102,19 @@ bool CLASS::get_branch_fees(std::atomic_bool& cancel, fee_rate_sets& out,
137102
if (is_zero(count))
138103
return true;
139104

140-
if (system::is_add_overflow(start, sub1(count)))
141-
return false;
142-
143-
const auto last = start + sub1(count);
144-
if (last > get_top_confirmed())
105+
if (system::is_add_overflow(start, sub1(count)) ||
106+
(start + sub1(count) > get_top_confirmed()))
145107
return false;
146108

147109
out.resize(count);
110+
std::atomic_bool fail{};
148111
std::vector<size_t> offsets(count);
149112
std::iota(offsets.begin(), offsets.end(), zero);
150-
151-
std::atomic_bool fail{};
113+
constexpr auto parallel = poolstl::execution::par;
152114
constexpr auto relaxed = std::memory_order_relaxed;
153-
std::for_each(poolstl::execution::par, offsets.begin(), offsets.end(),
115+
116+
// Parallel execution saves ~50%.
117+
std::for_each(parallel, offsets.begin(), offsets.end(),
154118
[&](const size_t& offset) NOEXCEPT
155119
{
156120
if (fail.load(relaxed))

0 commit comments

Comments
 (0)