Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 4 additions & 6 deletions include/bitcoin/node/chasers/chaser_validate.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -67,14 +67,14 @@ class BCN_API chaser_validate
/// Validation.
virtual void post_block(const header_link& link, bool bypass) NOEXCEPT;
virtual void validate_block(const header_link& link, bool bypass) NOEXCEPT;
virtual code validate(bool& batched, bool& faulted, bool bypass,
const system::chain::block& block, const header_link& link,
const system::chain::context& ctx) NOEXCEPT;
virtual code validate(bool& batched, bool& faulted, bool& capturing,
bool bypass, const system::chain::block& block,
const header_link& link, const system::chain::context& ctx) NOEXCEPT;
virtual code populate(bool bypass, const system::chain::block& block,
const system::chain::context& ctx) NOEXCEPT;
virtual void complete_block(const code& ec, const header_link& link,
size_t height, bool bypass, bool batched=false,
bool faulted=false) NOEXCEPT;
bool faulted=false, bool capturing=false) NOEXCEPT;
virtual void notify_block(const code& ec, size_t height,
const header_link& link, bool bypass) NOEXCEPT;

Expand All @@ -92,8 +92,6 @@ class BCN_API chaser_validate

private:
static constexpr auto relaxed = std::memory_order_relaxed;
using shared_lock = const std::shared_lock<std::shared_mutex>;
using shared_lock_cptr = std::shared_ptr<shared_lock>;
using atomic_counter = std::atomic<size_t>;
using atomic_counter_ptr = std::shared_ptr<atomic_counter>;
using threshold_group = signatures::threshold_group;
Expand Down
33 changes: 19 additions & 14 deletions src/chasers/chaser_validate.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -219,7 +219,7 @@ void chaser_validate::validate_block(const header_link& link,

code ec{};
chain::context ctx{};
bool batched{}, faulted{};
bool batched{}, faulted{}, enabled{};
auto& query = archive();

// TODO: implement allocator parameter resulting in full allocation to
Expand All @@ -239,13 +239,13 @@ void chaser_validate::validate_block(const header_link& link,
if (!query.set_block_unconfirmable(link))
ec = error::validate4;
}
else if ((ec = validate(batched, faulted, bypass, *block, link, ctx)))
else if ((ec = validate(batched, faulted, enabled, bypass, *block, link, ctx)))
{
if (!query.set_block_unconfirmable(link))
ec = error::validate5;
}

complete_block(ec, link, ctx.height, bypass, batched, faulted);
complete_block(ec, link, ctx.height, bypass, batched, faulted, enabled);

// Prevent stall by posting internal event, avoiding external handlers.
if (is_one(backlog_.fetch_sub(one, relaxed)))
Expand Down Expand Up @@ -279,8 +279,8 @@ code chaser_validate::populate(bool bypass, const chain::block& block,
return error::success;
}

code chaser_validate::validate(bool& batched, bool& faulted, bool bypass,
const chain::block& block, const header_link& link,
code chaser_validate::validate(bool& batched, bool& faulted, bool& capturing,
bool bypass, const chain::block& block, const header_link& link,
const chain::context& ctx) NOEXCEPT
{
auto& query = archive();
Expand All @@ -294,13 +294,17 @@ code chaser_validate::validate(bool& batched, bool& faulted, bool bypass,
if ((ec = block.accept(ctx, subsidy_interval_, initial_subsidy_)))
return ec;

// Initialize block capture.
const auto capture = get_capture(link);

// Signature capture is enabled.
capturing = capture.enabled;

// This critical section is mutually-exclusive with batch verification.
// ====================================================================
{
const std::shared_lock lock{ mutex_ };

// Initialize block capture.
const auto capture = get_capture(link);
std::shared_lock lock{ mutex_, std::defer_lock };
if (capturing) lock.lock();

// Sequentially connect block with signature capture (if enabled).
// There is not stop during connect, so shutdown will wait on the
Expand All @@ -314,8 +318,8 @@ code chaser_validate::validate(bool& batched, bool& faulted, bool bypass,

// Threshold batch commit failed, block otherwise passed (retry).
faulted = capture.faulted;
// ================================================================
}
// ================================================================

// Prevouts optimize confirmation.
// Block will be retried if batch is faulted.
Expand All @@ -337,7 +341,8 @@ code chaser_validate::validate(bool& batched, bool& faulted, bool bypass,

// May be either concurrent or stranded.
void chaser_validate::complete_block(const code& ec, const header_link& link,
size_t height, bool bypass, bool batched, bool faulted) NOEXCEPT
size_t height, bool bypass, bool batched, bool faulted,
bool capturing) NOEXCEPT
{
// Node errors are fatal (or disk full recoverable).
if (ec && node::error::error_category::contains(ec))
Expand Down Expand Up @@ -379,9 +384,9 @@ void chaser_validate::complete_block(const code& ec, const header_link& link,
// Not failed/invalid/batched/faulted, so block is complete (maybe valid).
notify_block({}, height, link, bypass);

// Batch enabled not bypassed implies that the block is current and was
// not batched. Each such block triggers residual batch processing.
if (!bypass && batch_enabled_)
// Batch enabled not bypassed implies that the block is current and not
// batched. Each such block triggers residual batch processing (no push).
if (batch_enabled_ && !stopping_ && !capturing && !bypass)
{
POST(process_batch, true);
}
Expand Down
9 changes: 5 additions & 4 deletions src/chasers/chaser_validate_batch.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,8 @@
*/
#include <bitcoin/node/chasers/chaser_validate.hpp>

#include <ranges>
#include <shared_mutex>
#include <algorithm>
#include <mutex>
#include <bitcoin/node/define.hpp>

namespace libbitcoin {
Expand Down Expand Up @@ -70,9 +70,9 @@ void chaser_validate::process_batch(bool residual) NOEXCEPT

// Test outside of lock to prevent reader contention for nearly all calls.
auto& query = archive();
if (!residual &&
if (stopping_ || (!residual &&
(query.ecdsa_records() < batch_target_) &&
(query.schnorr_records() < batch_target_))
(query.schnorr_records() < batch_target_)))
return;

// Unique lock prevents batch table updates during evaluation, allowing the
Expand All @@ -82,6 +82,7 @@ void chaser_validate::process_batch(bool residual) NOEXCEPT
const std::unique_lock lock{ mutex_ };

// Must retest inside the lock as table updates are running concurrently.
if (stopping_) return;
const auto ecdsa = query.ecdsa_records();
const auto schnorr = query.schnorr_records();
if (!residual && (ecdsa < batch_target_) && (schnorr < batch_target_))
Expand Down
Loading