Skip to content

Commit f9c8a56

Browse files
authored
Merge pull request #719 from evoskuil/master
Store block size and weight both in txs, update qinterface.
2 parents 50f7d33 + 99dfd1f commit f9c8a56

File tree

11 files changed

+216
-80
lines changed

11 files changed

+216
-80
lines changed

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

Lines changed: 28 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -110,7 +110,7 @@ hashes CLASS::get_tx_keys(const header_link& link) const NOEXCEPT
110110
TEMPLATE
111111
size_t CLASS::get_tx_count(const header_link& link) const NOEXCEPT
112112
{
113-
table::txs::get_tx_quantity txs{};
113+
table::txs::get_tx_count txs{};
114114
if (!store_.txs.at(to_txs(link), txs))
115115
return {};
116116

@@ -175,6 +175,15 @@ bool CLASS::get_tx_position(size_t& out, const tx_link& link) const NOEXCEPT
175175
return true;
176176
}
177177

178+
TEMPLATE
179+
size_t CLASS::get_tx_size(const tx_link& link,
180+
bool witness) const NOEXCEPT
181+
{
182+
size_t light{}, heavy{};
183+
return get_tx_sizes(light, heavy, link) ? (witness ? heavy : light) :
184+
max_uint64;
185+
}
186+
178187
TEMPLATE
179188
bool CLASS::get_tx_sizes(size_t& light, size_t& heavy,
180189
const tx_link& link) const NOEXCEPT
@@ -192,10 +201,25 @@ bool CLASS::get_tx_sizes(size_t& light, size_t& heavy,
192201
// ----------------------------------------------------------------------------
193202

194203
TEMPLATE
195-
size_t CLASS::get_block_size(const header_link& link) const NOEXCEPT
204+
size_t CLASS::get_block_size(const header_link& link,
205+
bool witness) const NOEXCEPT
206+
{
207+
size_t light{}, heavy{};
208+
return get_block_sizes(light, heavy, link) ? (witness ? heavy : light) :
209+
max_uint64;
210+
}
211+
212+
TEMPLATE
213+
bool CLASS::get_block_sizes(size_t& light, size_t& heavy,
214+
const header_link& link) const NOEXCEPT
196215
{
197-
table::txs::get_block_size txs{};
198-
return store_.txs.at(to_txs(link), txs) ? txs.wire : zero;
216+
table::txs::get_sizes sizes{};
217+
if (!store_.txs.at(to_txs(link), sizes))
218+
return false;
219+
220+
light = sizes.light;
221+
heavy = sizes.heavy;
222+
return true;
199223
}
200224

201225
TEMPLATE

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

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -392,14 +392,18 @@ code CLASS::set_code(const block& block, const header_link& key,
392392
if ((ec = set_code(fk++, *tx, bypass)))
393393
return ec;
394394

395-
using bytes = linkage<schema::size>::integer;
395+
// Optional hash, only has value on height intervals.
396396
auto interval = create_interval(key, height);
397-
const auto size = block.serialized_size(true);
398-
const auto wire = possible_narrow_cast<bytes>(size);
399397

400-
// Depth is only used for genesis (is_zero(tx_fks[0])).
398+
// Depth is only set by writer for genesis (is_zero(tx_fks[0])).
401399
const auto depth = store_.interval_depth();
402400

401+
using bytes = linkage<schema::size>::integer;
402+
const auto light = possible_narrow_cast<bytes>(
403+
block.serialized_size(false));
404+
const auto heavy = possible_narrow_cast<bytes>
405+
(block.serialized_size(true));
406+
403407
// ========================================================================
404408
const auto scope = store_.get_transactor();
405409
constexpr auto positive = true;
@@ -413,8 +417,9 @@ code CLASS::set_code(const block& block, const header_link& key,
413417
return store_.txs.put(to_txs(key), table::txs::put_group
414418
{
415419
{},
416-
wire,
417420
count,
421+
light,
422+
heavy,
418423
tx_fks,
419424
std::move(interval),
420425
depth

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

Lines changed: 48 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,14 +27,55 @@
2727
#include <utility>
2828
#include <bitcoin/database/define.hpp>
2929

30+
#define SLOW_FEES
31+
3032
namespace libbitcoin {
3133
namespace database {
3234

33-
// TODO: optimize.
35+
// private
36+
TEMPLATE
37+
constexpr size_t CLASS::virtual_size(size_t light, size_t heavy) NOEXCEPT
38+
{
39+
using namespace system;
40+
using namespace system::chain;
41+
constexpr auto scale = base_size_contribution + total_size_contribution;
42+
43+
const auto weight = ceilinged_add(
44+
ceilinged_multiply(base_size_contribution, light),
45+
ceilinged_multiply(total_size_contribution, heavy));
46+
47+
// Block weight is 3 * nominal size * + 1 * witness size [bip141].
48+
return ceilinged_divide(weight, scale);
49+
}
50+
51+
TEMPLATE
52+
bool CLASS::get_tx_virtual_size(uint64_t& out,
53+
const tx_link& link) const NOEXCEPT
54+
{
55+
size_t light{}, heavy{};
56+
if (!get_tx_sizes(light, heavy, link))
57+
return false;
58+
59+
out = virtual_size(light, heavy);
60+
return true;
61+
}
62+
63+
TEMPLATE
64+
bool CLASS::get_block_virtual_size(uint64_t& out,
65+
const header_link& link) const NOEXCEPT
66+
{
67+
size_t light{}, heavy{};
68+
if (!get_block_sizes(light, heavy, link))
69+
return false;
70+
71+
out = virtual_size(light, heavy);
72+
return true;
73+
}
3474

3575
TEMPLATE
3676
uint64_t CLASS::get_tx_fee(const tx_link& link) const NOEXCEPT
3777
{
78+
#if defined(SLOW_FEES)
3879
const auto tx = get_transaction(link, false);
3980
if (!tx)
4081
return max_uint64;
@@ -43,6 +84,12 @@ uint64_t CLASS::get_tx_fee(const tx_link& link) const NOEXCEPT
4384
return zero;
4485

4586
return populate_without_metadata(*tx) ? tx->fee() : max_uint64;
87+
#else
88+
// Get heavy and light sizes for the tx link and compute virtual size.
89+
// Get and total value for each output of the tx link.
90+
// Get all outputs links spent by the tx link (spends).
91+
// Get and total value for each spend (todo: move value to outs).
92+
#endif
4693
}
4794

4895
TEMPLATE

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

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ size_t CLASS::get_candidate_size(size_t top) const NOEXCEPT
3838
{
3939
size_t wire{};
4040
for (auto height = zero; height <= top; ++height)
41-
wire += get_block_size(to_candidate(height));
41+
wire += get_block_size(to_candidate(height), true);
4242

4343
return wire;
4444
}
@@ -55,7 +55,7 @@ size_t CLASS::get_confirmed_size(size_t top) const NOEXCEPT
5555
{
5656
size_t wire{};
5757
for (auto height = zero; height <= top; ++height)
58-
wire += get_block_size(to_confirmed(height));
58+
wire += get_block_size(to_confirmed(height), true);
5959

6060
return wire;
6161
}

include/bitcoin/database/query.hpp

Lines changed: 16 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -341,14 +341,19 @@ class query
341341
inline point_key get_point_key(const point_link& link) const NOEXCEPT;
342342
inline hash_digest get_point_hash(const point_link& link) const NOEXCEPT;
343343

344-
/// False implies not confirmed.
345-
bool get_tx_height(size_t& out, const tx_link& link) const NOEXCEPT;
344+
/// False position implies not confirmed (or fault).
346345
bool get_tx_position(size_t& out, const tx_link& link) const NOEXCEPT;
347-
bool get_tx_sizes(size_t& light, size_t& is_locked,
346+
bool get_tx_height(size_t& out, const tx_link& link) const NOEXCEPT;
347+
348+
/// Sizes.
349+
size_t get_tx_size(const tx_link& link, bool witness) const NOEXCEPT;
350+
size_t get_block_size(const header_link& link, bool witness) const NOEXCEPT;
351+
bool get_block_sizes(size_t& light, size_t& heavy,
352+
const header_link& link) const NOEXCEPT;
353+
bool get_tx_sizes(size_t& light, size_t& heavy,
348354
const tx_link& link) const NOEXCEPT;
349355

350356
/// Terminal implies not found, false implies fault.
351-
size_t get_block_size(const header_link& link) const NOEXCEPT;
352357
height_link get_height(const hash_digest& key) const NOEXCEPT;
353358
height_link get_height(const header_link& link) const NOEXCEPT;
354359
bool get_height(size_t& out, const hash_digest& key) const NOEXCEPT;
@@ -401,6 +406,12 @@ class query
401406
/// Fees.
402407
/// -----------------------------------------------------------------------
403408

409+
/// Virtual size incorporates witnesses if archived.
410+
bool get_tx_virtual_size(uint64_t& out,
411+
const tx_link& link) const NOEXCEPT;
412+
bool get_block_virtual_size(uint64_t& out,
413+
const header_link& link) const NOEXCEPT;
414+
404415
/// Total fee value by tx or block.
405416
uint64_t get_tx_fee(const tx_link& link) const NOEXCEPT;
406417
uint64_t get_block_fee(const header_link& link) const NOEXCEPT;
@@ -771,6 +782,7 @@ class query
771782
template <typename Functor>
772783
static inline code parallel_address_transform(std::atomic_bool& cancel,
773784
outpoints& out, const output_links& links, Functor&& functor) NOEXCEPT;
785+
static constexpr size_t virtual_size(size_t light, size_t heavy) NOEXCEPT;
774786

775787
// Not thread safe.
776788
size_t get_fork_() const NOEXCEPT;

include/bitcoin/database/tables/archives/transaction.hpp

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,8 @@ namespace libbitcoin {
2929
namespace database {
3030
namespace table {
3131

32+
// TODO: merge coinbase bit (saves about 1GB).
33+
3234
/// Transaction is a canonical record hash table.
3335
struct transaction
3436
: public hash_map<schema::transaction>
@@ -146,11 +148,14 @@ struct transaction
146148
inline bool to_data(finalizer& sink) const NOEXCEPT
147149
{
148150
using namespace system;
151+
const auto light = possible_narrow_cast<bytes::integer>(
152+
tx.serialized_size(false));
153+
const auto heavy = possible_narrow_cast<bytes::integer>
154+
(tx.serialized_size(true));
155+
149156
sink.write_byte(to_int<uint8_t>(tx.is_coinbase()));
150-
sink.write_little_endian<bytes::integer, bytes::size>(
151-
possible_narrow_cast<bytes::integer>(tx.serialized_size(false)));
152-
sink.write_little_endian<bytes::integer, bytes::size>(
153-
possible_narrow_cast<bytes::integer>(tx.serialized_size(true)));
157+
sink.write_little_endian<bytes::integer, bytes::size>(light);
158+
sink.write_little_endian<bytes::integer, bytes::size>(heavy);
154159
sink.write_little_endian<uint32_t>(tx.locktime());
155160
sink.write_little_endian<uint32_t>(tx.version());
156161
sink.write_little_endian<ix::integer, ix::size>(ins_count);

0 commit comments

Comments
 (0)