diff --git a/include/bitcoin/node/chase.hpp b/include/bitcoin/node/chase.hpp index 557e3143..891be398 100644 --- a/include/bitcoin/node/chase.hpp +++ b/include/bitcoin/node/chase.hpp @@ -134,15 +134,15 @@ enum class chase /// ----------------------------------------------------------------------- /// A current block has been organized (header_t). - /// Issued by 'transaction' and handled by 'protocol_header/block_out'. + /// Issued by 'confirm' and handled by 'protocol_header/block_out/estimator'. block, /// A confirmable block has been confirmed (header_t). - /// Issued by 'confirm' [and handled by 'transaction']. + /// Issued by 'confirm' and handled by 'transaction'. organized, /// A previously confirmed block has been unconfirmed (header_t). - /// Issued by 'confirm' [and handled by 'transaction']. + /// Issued by 'confirm' and handled by 'transaction'. reorganized, /// Mining. diff --git a/include/bitcoin/node/chasers/chaser.hpp b/include/bitcoin/node/chasers/chaser.hpp index 6d9cab57..bea55dc7 100644 --- a/include/bitcoin/node/chasers/chaser.hpp +++ b/include/bitcoin/node/chasers/chaser.hpp @@ -39,7 +39,7 @@ class BCN_API chaser public: DELETE_COPY_MOVE_DESTRUCT(chaser); - /// Must be called from node strand. + /// Should be called from node strand. virtual code start() NOEXCEPT = 0; /// Override to capture non-blocking stopping. diff --git a/include/bitcoin/node/error.hpp b/include/bitcoin/node/error.hpp index b9db21af..a4562997 100644 --- a/include/bitcoin/node/error.hpp +++ b/include/bitcoin/node/error.hpp @@ -98,6 +98,7 @@ enum error_t : uint8_t confirm10, confirm11, confirm12, + estimate_failed, estimates_failed, estimates_disabled, estimates_premature diff --git a/src/chasers/chaser_check.cpp b/src/chasers/chaser_check.cpp index 768ce4af..68e72f98 100644 --- a/src/chasers/chaser_check.cpp +++ b/src/chasers/chaser_check.cpp @@ -90,7 +90,6 @@ map_ptr chaser_check::split(const map_ptr& map) NOEXCEPT code chaser_check::start() NOEXCEPT { - BC_ASSERT(stranded()); start_tracking(); set_position(archive().get_fork()); requested_ = advanced_ = position(); diff --git a/src/chasers/chaser_confirm.cpp b/src/chasers/chaser_confirm.cpp index 56ee6a9e..d1fb50b7 100644 --- a/src/chasers/chaser_confirm.cpp +++ b/src/chasers/chaser_confirm.cpp @@ -42,7 +42,6 @@ chaser_confirm::chaser_confirm(full_node& node) NOEXCEPT code chaser_confirm::start() NOEXCEPT { - BC_ASSERT(stranded()); const auto& query = archive(); set_position(query.get_fork()); diff --git a/src/chasers/chaser_estimate.cpp b/src/chasers/chaser_estimate.cpp index cbb9b0b5..5573985d 100644 --- a/src/chasers/chaser_estimate.cpp +++ b/src/chasers/chaser_estimate.cpp @@ -44,9 +44,7 @@ chaser_estimate::chaser_estimate(full_node& node) NOEXCEPT code chaser_estimate::start() NOEXCEPT { - BC_ASSERT(stranded()); - - if (is_zero(node_settings().fee_estimate_enabled())) + if (node_settings().fee_estimate_enabled()) { SUBSCRIBE_CHASE(handle_chase, _1, _2, _3); } @@ -72,12 +70,6 @@ void chaser_estimate::estimate(size_t target, estimator::mode mode, return; } - if (!initialized()) - { - handler(error::estimates_premature, {}); - return; - } - POST(do_estimate, target, mode, std::move(handler)); } @@ -86,7 +78,20 @@ void chaser_estimate::do_estimate(size_t target, estimator::mode mode, const estimate_handler& handler) NOEXCEPT { BC_ASSERT(stranded()); - handler(error::success, estimator_->estimate(target, mode)); + + // Check this under strand so that chase can initialize first. + if (!initialized()) + { + handler(error::estimates_premature, {}); + return; + } + + const auto value = estimator_->estimate(target, mode); + const auto ec = (value < to_unsigned(max_int64) ? error::success : + error::estimate_failed); + + // Successful value is always castable to int64_t. + handler(ec, value); } size_t chaser_estimate::top_height() const NOEXCEPT @@ -113,12 +118,10 @@ bool chaser_estimate::handle_chase(const code&, chase event_, ////if (suspended()) //// return true; - if (!is_current(true)) - return true; - switch (event_) { - case chase::organized: + // chase::block is only sent when current (may need to file gaps). + case chase::block: { BC_ASSERT(std::holds_alternative(value)); POST(do_organized, std::get(value)); @@ -147,7 +150,8 @@ void chaser_estimate::do_organized(header_t) NOEXCEPT { BC_ASSERT(stranded()); - if (initialize()) + // TODO: make gap safe (get estimator top and adjust). + if (initialized() || initialize()) estimator_->push(archive()); } @@ -155,7 +159,8 @@ void chaser_estimate::do_reorganized(header_t) NOEXCEPT { BC_ASSERT(stranded()); - if (initialize()) + // TODO: make gap safe (get estimator top and adjust). + if (initialized()) estimator_->pop(archive()); } @@ -167,9 +172,6 @@ bool chaser_estimate::initialize() NOEXCEPT { BC_ASSERT(stranded()); - if (initialized()) - return true; - // Preempt initialize fault when horizon exceeds chain length. const auto horizon = node_settings().fee_estimate_horizon_(); if (horizon > add1(archive().get_top_confirmed())) diff --git a/src/chasers/chaser_header.cpp b/src/chasers/chaser_header.cpp index 97a78388..0b0da56c 100644 --- a/src/chasers/chaser_header.cpp +++ b/src/chasers/chaser_header.cpp @@ -35,7 +35,6 @@ chaser_header::chaser_header(full_node& node) NOEXCEPT code chaser_header::start() NOEXCEPT { - BC_ASSERT(stranded()); if (!initialize_milestone()) return fault(error::header1); diff --git a/src/chasers/chaser_snapshot.cpp b/src/chasers/chaser_snapshot.cpp index 01a487d4..9eefc134 100644 --- a/src/chasers/chaser_snapshot.cpp +++ b/src/chasers/chaser_snapshot.cpp @@ -52,8 +52,6 @@ chaser_snapshot::chaser_snapshot(full_node& node) NOEXCEPT code chaser_snapshot::start() NOEXCEPT { - BC_ASSERT(stranded()); - // Initial values assume all stops or starts are snapped. // get_top_validated is an expensive scan. diff --git a/src/chasers/chaser_storage.cpp b/src/chasers/chaser_storage.cpp index 306caa45..7abbd33d 100644 --- a/src/chasers/chaser_storage.cpp +++ b/src/chasers/chaser_storage.cpp @@ -47,8 +47,6 @@ chaser_storage::chaser_storage(full_node& node) NOEXCEPT code chaser_storage::start() NOEXCEPT { - BC_ASSERT(stranded()); - // Construct is too early to create the unstarted timer. disk_timer_ = std::make_shared(log, strand(), seconds{1}); diff --git a/src/chasers/chaser_template.cpp b/src/chasers/chaser_template.cpp index 80d45e03..b6aa2077 100644 --- a/src/chasers/chaser_template.cpp +++ b/src/chasers/chaser_template.cpp @@ -43,7 +43,6 @@ chaser_template::chaser_template(full_node& node) NOEXCEPT // TODO: initialize template state. code chaser_template::start() NOEXCEPT { - BC_ASSERT(stranded()); SUBSCRIBE_CHASE(handle_chase, _1, _2, _3); return error::success; } diff --git a/src/chasers/chaser_transaction.cpp b/src/chasers/chaser_transaction.cpp index 347a5336..ee6a5fcb 100644 --- a/src/chasers/chaser_transaction.cpp +++ b/src/chasers/chaser_transaction.cpp @@ -43,7 +43,6 @@ chaser_transaction::chaser_transaction(full_node& node) NOEXCEPT // TODO: initialize tx graph from store, log and stop on error. code chaser_transaction::start() NOEXCEPT { - BC_ASSERT(stranded()); SUBSCRIBE_CHASE(handle_chase, _1, _2, _3); return error::success; } diff --git a/src/error.cpp b/src/error.cpp index 33fafa00..173935ea 100644 --- a/src/error.cpp +++ b/src/error.cpp @@ -88,6 +88,7 @@ DEFINE_ERROR_T_MESSAGE_MAP(error) { confirm10, "confirm10" }, { confirm11, "confirm11" }, { confirm12, "confirm12" }, + { estimate_failed, "estimate_failed" }, { estimates_failed, "estimates_failed" }, { estimates_disabled, "estimates_disabled" }, { estimates_premature, "estimates_premature" } diff --git a/test/error.cpp b/test/error.cpp index cb4699ba..9b385bbc 100644 --- a/test/error.cpp +++ b/test/error.cpp @@ -225,6 +225,15 @@ BOOST_AUTO_TEST_CASE(error_t__code__confirm1__true_expected_message) BOOST_REQUIRE_EQUAL(ec.message(), "confirm1"); } +BOOST_AUTO_TEST_CASE(error_t__code__estimate_failed__true_expected_message) +{ + constexpr auto value = error::estimate_failed; + const auto ec = code(value); + BOOST_REQUIRE(ec); + BOOST_REQUIRE(ec == value); + BOOST_REQUIRE_EQUAL(ec.message(), "estimate_failed"); +} + BOOST_AUTO_TEST_CASE(error_t__code__estimates_failed__true_expected_message) { constexpr auto value = error::estimates_failed;