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
3 changes: 0 additions & 3 deletions include/bitcoin/node/chasers/chaser.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -141,9 +141,6 @@ class BCN_API chaser
/// The confirmed chain is confirmed to maximum height or is current.
bool is_recent() const NOEXCEPT;

/// Confirmation is limited to below the lowest banked silent block height.
size_t silent_limit() const NOEXCEPT;

/// The height is at or below the top checkpoint.
bool is_under_checkpoint(size_t height) const NOEXCEPT;

Expand Down
19 changes: 18 additions & 1 deletion include/bitcoin/node/chasers/chaser_transaction.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,8 @@ class BCN_API chaser_transaction
chaser_transaction(full_node& node) NOEXCEPT;

code start() NOEXCEPT override;
void stopping(const code& ec) NOEXCEPT override;
void stop() NOEXCEPT override;

/// Validate and archive a submitted package, accepted as a whole.
/// The package is only validated when test, so nothing is archived.
Expand All @@ -59,12 +61,21 @@ class BCN_API chaser_transaction
const database::tx_links& links, const database::header_link& link,
const submit_handler& handler) NOEXCEPT;

/// Recompute the pool context, closing the pool if not current.
/// Recompute the pool context, closing the pool if not current, and map
/// scan starts: built once current, extended by block until pooling, and
/// remapped when a block archived before the latch is organized.
virtual void do_bump() NOEXCEPT;

/// Pool the unpooled txs of a reorganized block.
virtual void do_reorganized(header_t link) NOEXCEPT;

/// Map scan starts from the confirmed top (scan threadpool).
virtual void do_scan(const database::header_link& top, size_t bound,
bool remap) NOEXCEPT;

/// Complete the scan start map.
virtual void do_scanned(bool mapped) NOEXCEPT;

private:
static size_t to_rate(const system::chain::transaction& tx) NOEXCEPT;

Expand All @@ -79,10 +90,16 @@ class BCN_API chaser_transaction
const system::chain::context& ctx) NOEXCEPT;
code unconfirmable(const database::header_link& link, size_t height,
const code& ec) NOEXCEPT;
void start_scan(bool remap) NOEXCEPT;

// These are thread safe.
network::threadpool scan_threadpool_;
stopper stopping_{};

// These are protected by strand.
system::chain::context pool_{};
bool pooling_{};
bool scanning_{};
};

} // namespace node
Expand Down
20 changes: 8 additions & 12 deletions include/bitcoin/node/chasers/chaser_validate.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -41,9 +41,6 @@ class BCN_API chaser_validate
void stopping(const code& ec) NOEXCEPT override;
void stop() NOEXCEPT override;

/// Confirmation is limited to below the lowest banked silent block height.
size_t silent_limit() const NOEXCEPT;

protected:
using header_link = database::header_link;
using header_links = database::header_links;
Expand All @@ -67,14 +64,15 @@ class BCN_API chaser_validate

/// Validation.
virtual void post_block(const header_link& link, bool bypass) NOEXCEPT;
virtual void post_scan(const header_link& link, bool bypass) NOEXCEPT;
virtual void validate_block(const header_link& link, bool bypass) NOEXCEPT;
virtual void scan_block(const header_link& link, bool bypass) NOEXCEPT;
virtual code validate(bool& batched, 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 code validate_silent(const header_link& link,
const system::chain::context& ctx) NOEXCEPT;
virtual code validate_silent(const header_link& link, bool bank) NOEXCEPT;
virtual code validate_pooled(bool& pooled, const header_link& link,
const system::chain::context& ctx) NOEXCEPT;
virtual code complete_pooled(const header_link& link,
Expand Down Expand Up @@ -108,9 +106,9 @@ class BCN_API chaser_validate
virtual void process_silent_batch(bool residual) NOEXCEPT;
virtual code do_process_silent_batch(bool bank) NOEXCEPT;
virtual bool commit_silent_batch(const header_link& link,
const system::chain::block& block, size_t height) NOEXCEPT;
const system::chain::block& block) NOEXCEPT;
virtual bool commit_silent_batch(const header_link& link,
const system::chain::view::block& block, size_t height) NOEXCEPT;
const system::chain::view::block& block) NOEXCEPT;
virtual bool enter_silent_capture() NOEXCEPT;
virtual void exit_silent_capture(bool bank) NOEXCEPT;

Expand All @@ -119,9 +117,7 @@ class BCN_API chaser_validate
bool stranded() const NOEXCEPT override;

private:
using atomic_height = std::atomic<size_t>;
using atomic_counter = std::atomic<size_t>;
using bank_heights = std::array<atomic_height, two>;
struct counters
{
atomic_counter ecdsa_{};
Expand Down Expand Up @@ -151,12 +147,13 @@ class BCN_API chaser_validate

// Batching helpers.
template <typename Block>
bool commit_silent_(const header_link& link, const Block& block,
size_t height) NOEXCEPT;
bool commit_silent_(const header_link& link,
const Block& block) NOEXCEPT;
bool is_residual() NOEXCEPT;
bool is_mature(bool residual) NOEXCEPT;
bool is_silent_capturing(const header_link& link) NOEXCEPT;
bool is_silent_mature(bool residual) NOEXCEPT;
bool is_silent_empty() const NOEXCEPT;
std::string log_rate(const std::string& name, size_t signatures,
size_t milliseconds, bool device) const NOEXCEPT;

Expand All @@ -176,7 +173,6 @@ class BCN_API chaser_validate
std::atomic_bool silent_draining_{};
std::atomic_bool silent_bank_{};
std::array<atomic_counter, two> silent_writers_{};
bank_heights silent_heights_{ max_size_t, max_size_t };
counters counters_{};
stopper stopping_{};

Expand Down
1 change: 1 addition & 0 deletions include/bitcoin/node/error.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -122,6 +122,7 @@ enum error_t : uint8_t
transaction5,
transaction6,
transaction7,
transaction8,
estimates_initialize,
estimates_push1,
estimates_push2,
Expand Down
3 changes: 0 additions & 3 deletions include/bitcoin/node/full_node.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -165,9 +165,6 @@ class BCN_API full_node
/// The confirmed chain is confirmed to maximum height or is current.
virtual bool is_recent() const NOEXCEPT;

/// Confirmation is limited to below the lowest banked silent block height.
virtual size_t silent_limit() const NOEXCEPT;

/// Zulu time at which the node started.
virtual time_t start_time() const NOEXCEPT;

Expand Down
5 changes: 0 additions & 5 deletions src/chasers/chaser.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -171,11 +171,6 @@ bool chaser::is_recent() const NOEXCEPT
return node_.is_recent();
}

size_t chaser::silent_limit() const NOEXCEPT
{
return node_.silent_limit();
}

bool chaser::is_under_checkpoint(size_t height) const NOEXCEPT
{
return height <= checkpoint();
Expand Down
2 changes: 1 addition & 1 deletion src/chasers/chaser_confirm.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -161,7 +161,7 @@ void chaser_confirm::do_bumped(height_t) NOEXCEPT
// Guarded by candidate interlock.
size_t fork_point{};
const auto& query = archive();
auto fork = query.get_validated_fork(fork_point, silent_limit());
auto fork = query.get_validated_fork(fork_point);

// Fork may be empty if candidates were reorganized.
if (fork.empty())
Expand Down
94 changes: 82 additions & 12 deletions src/chasers/chaser_transaction.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,8 @@ BC_PUSH_WARNING(NO_THROW_IN_NOEXCEPT)
BC_PUSH_WARNING(NO_VALUE_OR_CONST_REF_SHARED_PTR)

chaser_transaction::chaser_transaction(full_node& node) NOEXCEPT
: chaser(node)
: chaser(node),
scan_threadpool_(one, node.node_settings().thread_priority_())
{
}

Expand All @@ -49,6 +50,22 @@ code chaser_transaction::start() NOEXCEPT
return error::success;
}

void chaser_transaction::stopping(const code& ec) NOEXCEPT
{
stopping_.store(true);
scan_threadpool_.stop();
chaser::stopping(ec);
}

void chaser_transaction::stop() NOEXCEPT
{
if (!scan_threadpool_.join())
{
BC_ASSERT_MSG(false, "failed to join threadpool");
std::abort();
}
}

// event handlers
// ----------------------------------------------------------------------------

Expand Down Expand Up @@ -89,26 +106,79 @@ void chaser_transaction::do_bump() NOEXCEPT
{
BC_ASSERT(stranded());
pooling_ = false;
if (closed() || !is_current_chain(true))
return;

// Pooling is a permanent store property, so it requires relay.
if (closed() || !network_settings().enable_relay || !is_current_chain(true))
auto& query = archive();
if (network_settings().enable_relay)
{
const auto top = query.get_top_confirmed();
const auto state = query.get_confirmed_chain_state(system_settings(),
query.to_confirmed(top), top);

if (!state)
{
fault(error::transaction1);
return;
}

// The context of the next block, in which a pool tx would confirm.
pool_ = chain_state{ *state, system_settings() }.context();
query.set_pooling();
pooling_ = true;
}

// Scan starts are mapped after the latch, as pooled rows are unordered.
if (!query.silent_enabled() || scanning_)
return;

auto& query = archive();
const auto top = query.get_top_confirmed();
const auto state = query.get_confirmed_chain_state(system_settings(),
query.to_confirmed(top), top);
// A complete map reaches genesis, and keeps up with the top until latched.
// Rows of a block archived before the latch may precede mapped starts.
const auto top = query.to_confirmed(query.get_top_confirmed());
const auto unmapped = query.get_scan_start(top).is_terminal();
if (query.get_scan_start(query.to_confirmed(zero)).is_terminal())
start_scan(true);
else if (unmapped && !query.is_pooling())
start_scan(false);
else if (unmapped && query.to_coinbase(top) < query.get_latch_tx())
start_scan(true);
}

void chaser_transaction::start_scan(bool remap) NOEXCEPT
{
BC_ASSERT(stranded());
scanning_ = true;

if (!state)
const auto& query = archive();
const auto bound = query.is_pooling() ? query.get_scan_frontier() :
max_size_t;
const auto top = query.to_confirmed(query.get_top_confirmed());
boost::asio::post(scan_threadpool_.service(),
BIND(do_scan, top, bound, remap));
}

void chaser_transaction::do_scan(const database::header_link& top,
size_t bound, bool remap) NOEXCEPT
{
POST(do_scanned, archive().set_scan_starts(stopping_, top, bound, remap));
}

// Blocks organized during the map are mapped by the bump that follows.
void chaser_transaction::do_scanned(bool mapped) NOEXCEPT
{
BC_ASSERT(stranded());
scanning_ = false;
if (closed())
return;

if (!mapped)
{
fault(error::transaction1);
fault(error::transaction8);
return;
}

// The context of the next block, in which a pool tx would confirm.
pool_ = chain_state{ *state, system_settings() }.context();
query.set_pooling();
pooling_ = true;
do_bump();
}

// Pooled in block order under the block context, excluding any confirmed (by
Expand Down
29 changes: 27 additions & 2 deletions src/chasers/chaser_validate.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -223,8 +223,26 @@ void chaser_validate::do_bumped(height_t height) NOEXCEPT
return;

const auto bypass = database::is_bypass(state);
if (database::is_validated(state) ||
(bypass && !filter_ && !query.is_silent(link, height)))
if (database::is_validated(state))
{
if (database::is_scanned(state))
{
complete_block(error::success, link, height, true);
}
else if (!is_silent_empty())
{
// Banked, scanned by the drain of its bank (which bumps).
process_silent_batch(true);
return;
}
else
{
// Its bank was dropped by restore.
++validate_backlog_;
post_scan(link, bypass);
}
}
else if (bypass && !filter_ && !query.is_silent(link, height))
{
complete_block(error::success, link, height, true);
}
Expand All @@ -247,6 +265,13 @@ void chaser_validate::post_block(const header_link& link,
PARALLEL(validate_block, link, bypass);
}

void chaser_validate::post_scan(const header_link& link,
bool bypass) NOEXCEPT
{
BC_ASSERT(stranded());
PARALLEL(scan_block, link, 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 capturing) NOEXCEPT
Expand Down
Loading
Loading