Skip to content

Commit e8a8520

Browse files
authored
Merge pull request #642 from evoskuil/master
Optimize native rest block/tx details queries.
2 parents b3ad636 + f1ef4e6 commit e8a8520

1 file changed

Lines changed: 48 additions & 49 deletions

File tree

src/protocols/protocol_native.cpp

Lines changed: 48 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -350,58 +350,57 @@ bool protocol_native::handle_get_block_details(const code& ec,
350350
return true;
351351
}
352352

353-
database::context context{};
354353
const auto& query = archive();
355354
const auto link = to_header(height, hash);
356355

357-
// Missing header.
358-
if (!query.get_context(context, link))
359-
{
360-
send_not_found();
361-
return true;
362-
}
363-
364-
const auto block = query.get_block(link, true);
365-
366-
// Unassociated header.
367-
if (!block)
356+
// Missing block.
357+
if (!query.is_associated(link))
368358
{
369359
send_not_found();
370360
return true;
371361
}
372362

373-
// Internal population (optimization).
374-
block->populate();
363+
const auto count = query.get_tx_count(link);
364+
const auto key = hash.has_value() ? *hash.value() :
365+
query.get_header_key(link);
375366

376-
// Missing prevouts (not ready).
377-
if (!query.populate_without_metadata(*block))
367+
database::context context{};
368+
size_t nominal{}, maximal{};
369+
uint64_t value{}, spend{}, claim{};
370+
if (is_zero(count) || key == system::null_hash ||
371+
!query.get_tx_spend(claim, query.to_coinbase(link)) ||
372+
!query.get_block_sizes(nominal, maximal, link) ||
373+
!query.get_block_value(value, link) ||
374+
!query.get_block_spend(spend, link) ||
375+
!query.get_context(context, link) ||
376+
is_subtract_overflow(value, spend))
378377
{
379-
send_not_found();
378+
send_internal_server_error(database::error::integrity);
380379
return true;
381380
}
382381

383-
const auto fees = block->fees();
382+
const auto fees = floored_subtract(value, spend);
384383
const auto& settings = system_settings();
385-
const auto bip16 = context.is_enabled(chain::flags::bip16_rule);
386384
const auto bip42 = context.is_enabled(chain::flags::bip42_rule);
387-
const auto bip141 = context.is_enabled(chain::flags::bip141_rule);
388385
const auto subsidy = chain::block::subsidy(context.height,
389386
settings.subsidy_interval_blocks, settings.initial_subsidy(), bip42);
390387

388+
// sigops is not cached, so removed for now.
391389
boost::json::object object
392390
{
393-
{ "hash", encode_hash(block->hash()) },
391+
{ "hash", encode_hash(key) },
394392
{ "height", context.height },
395-
{ "count", block->transactions() },
396-
{ "sigops", block->signature_operations(bip16, bip141) },
397-
{ "segregated", block->is_segregated() },
398-
{ "nominal", block->serialized_size(false) },
399-
{ "maximal", block->serialized_size(true) },
400-
{ "weight", block->weight() },
393+
{ "count", count },
394+
{ "segregated", maximal != maximal },
395+
{ "nominal", nominal },
396+
{ "maximal", maximal },
397+
{ "weight", chain::weighted_size(nominal, maximal) },
398+
{ "virtual", chain::virtual_size(nominal, maximal) },
399+
{ "value", value },
400+
{ "claim", claim },
401401
{ "fees", fees },
402402
{ "subsidy", subsidy },
403-
{ "reward", ceilinged_add(fees, subsidy) },
404-
{ "claim", block->claim() },
403+
{ "reward", ceilinged_add(fees, subsidy) }
405404
};
406405

407406
send_json(std::move(object), 512);
@@ -672,36 +671,39 @@ bool protocol_native::handle_get_tx_details(const code& ec,
672671

673672
const auto& query = archive();
674673
const auto link = query.to_tx(*hash);
675-
const auto tx = query.get_transaction(link, true);
676674

677675
// Missing tx.
678-
if (!tx)
676+
if (link.is_terminal())
679677
{
680678
send_not_found();
681679
return true;
682680
}
683681

684-
// Non-coinbase missing prevouts (not ready).
685-
const auto coinbase = query.is_coinbase(link);
686-
if (!coinbase && !query.populate_without_metadata(*tx))
682+
uint64_t value{}, spend{};
683+
size_t nominal{}, maximal{};
684+
if (!query.get_tx_sizes(nominal, maximal, link) ||
685+
!query.get_tx_value(value, link) ||
686+
!query.get_tx_spend(spend, link) ||
687+
is_subtract_overflow(value, spend))
687688
{
688-
send_not_found();
689+
send_internal_server_error(database::error::integrity);
689690
return true;
690691
}
691692

693+
// sigops and wtxid are not cached, so removed for now.
692694
boost::json::object object
693695
{
694-
{ "wtxid", encode_hash(tx->get_hash(true)) },
695-
{ "segregated", tx->is_segregated() },
696-
{ "coinbase", coinbase },
697-
{ "nominal", tx->serialized_size(false) },
698-
{ "maximal", tx->serialized_size(true) },
699-
{ "weight", tx->weight() },
700-
{ "value", tx->value() },
701-
{ "spend", tx->spend() },
702-
{ "fee", tx->fee() }
696+
{ "segregated", maximal != maximal },
697+
{ "coinbase", query.is_coinbase(link) },
698+
{ "nominal", nominal },
699+
{ "maximal", maximal },
700+
{ "weight", chain::weighted_size(nominal, maximal) },
701+
{ "virtual", chain::virtual_size(nominal, maximal) },
702+
{ "value", value },
703+
{ "spend", spend },
704+
{ "fee", floored_subtract(value, spend) }
703705
};
704-
706+
705707
size_t position{};
706708
if (query.get_tx_position(position, link))
707709
{
@@ -712,13 +714,10 @@ bool protocol_native::handle_get_tx_details(const code& ec,
712714
return true;
713715
}
714716

715-
const auto bip16 = context.is_enabled(chain::flags::bip16_rule);
716-
const auto bip141 = context.is_enabled(chain::flags::bip141_rule);
717717
object["confirmed"] = boost::json::object
718718
{
719719
{ "height", context.height },
720-
{ "position", position },
721-
{ "sigops", tx->signature_operations(bip16, bip141) }
720+
{ "position", position }
722721
};
723722
}
724723

0 commit comments

Comments
 (0)