diff --git a/include/bitcoin/node/chase.hpp b/include/bitcoin/node/chase.hpp index 3a691ae2..faa11d8c 100644 --- a/include/bitcoin/node/chase.hpp +++ b/include/bitcoin/node/chase.hpp @@ -19,37 +19,49 @@ #ifndef LIBBITCOIN_NODE_CHASE_HPP #define LIBBITCOIN_NODE_CHASE_HPP +#include #include namespace libbitcoin { namespace node { +/// Event desubscriber key type. +using object_key = uint64_t; + +/// Event payload types. +using count_t = size_t; +using height_t = size_t; +using peer_t = uint64_t; +using object_t = object_key; +using header_t = database::header_link::integer; +using transaction_t = database::tx_link::integer; + enum class chase { /// Work shuffling. /// ----------------------------------------------------------------------- - /// Chasers directed to start operating (height_t). + /// Chasers directed to start operating. /// Issued by 'full_node' and handled by 'check', 'validate', 'confirm'. start, - /// Disk space is limited (count_t). - /// Issued by 'full_node' and handled by 'snapshot' and 'storage'. + /// Disk space is limited. + /// Issued by 'full_node' and handled by 'storage'. space, - /// Take a snapshot (height_t). + /// Take a snapshot. /// Issued by 'confirm' and handled by 'snapshot'. snap, - /// Chaser directed to attempt start from its current position (height_t). + /// Chaser directed to attempt start from its current position. /// Issued by 'organize' and handled by 'check', 'validate', 'confirm'. bump, - /// Channels (all) directed to stop with the given code (default). + /// Channels (all) directed to stop with the given code. /// Issued by 'full_node' and handled by 'observer'. suspend, - /// Chasers (all) directed to resume following suspend (default). + /// Chasers (all) directed to resume following suspend. /// Issued by 'full_node' and handled by 'check', 'validate', 'confirm'. resume, @@ -57,38 +69,38 @@ enum class chase /// Issued by 'storage' and handled by 'validate'. unfull, - /// Channel starved for work (object_t). - /// Issued by 'block_in_31800' and handled by 'session_outbound'. + /// Channel starved for work. + /// Issued by 'block_in_31800' and handled by 'check'. starved, - /// Channel (slow) directed to split work and stop (object_t). - /// Issued by 'session_outbound' and handled by 'block_in_31800'. + /// Channel (slow) directed to split work and stop. + /// Issued by 'check' and handled by 'block_in_31800'. split, - /// Channels (all with work) directed to split work and stop (peer_t). - /// Issued by 'session_outbound' and handled by 'block_in_31800'. + /// Channels (all with work) directed to split work and stop. + /// Issued by 'check' and handled by 'block_in_31800'. stall, - /// Channels (all with work) directed to drop work and stop (peer_t). + /// Channels (all with work) directed to drop work and stop. /// Issued by 'check' and handled by 'block_in_31800'. purge, - /// Channels (all) directed to write work count to the log (count_t). + /// Channels (all) directed to write work count to the log. /// Issued by 'executor' and handled by 'block_in_31800'. report, /// Candidate Chain. /// ----------------------------------------------------------------------- - /// A new candidate branch exists from given branch point (height_t). - /// Issued by 'block' and handled by 'confirm' and 'snapshot'. + /// A new candidate branch exists from given branch point. + /// Issued by 'block' and handled by none. blocks, - /// A new candidate branch exists from given branch point (height_t). + /// A new candidate branch exists from given branch point. /// Issued by 'header' and handled by 'check'. headers, - /// New candidate headers without txs exist (count_t). + /// New candidate headers without txs exist. /// Issued by 'check' and handled by 'block_in_31800'. download, @@ -96,85 +108,328 @@ enum class chase /// Issued by 'organize' and handled by 'check', 'validate', 'confirm'. regressed, - /// unchecked, unvalid or unconfirmable was handled (height_t). + /// unchecked, unvalid or unconfirmable was handled. /// Issued by 'organize' and handled by 'check', 'validate', 'confirm'. disorganized, /// Check/Identify. /// ----------------------------------------------------------------------- - /// A block has been downloaded, checked and stored (height_t). - /// Issued by 'block_in_31800', handled by 'check', 'validate', 'snapshot'. + /// A block has been downloaded, checked and stored. + /// Issued by 'block_in_31800', handled by 'check', 'validate'. /// Populate is bypassed for checkpoint/milestone blocks. checked, - /// A downloaded block has failed check (header_t). + /// A downloaded block has failed check. /// Issued by 'block_in_31800' and handled by 'organize'. unchecked, - /// A downloaded window is completed by check (height_t). + /// A downloaded window is completed by check. /// Issued by 'check' and handled by 'validate'. windowed, /// Accept/Connect. /// ----------------------------------------------------------------------- - /// A branch has become valid (height_t). - /// Issued by 'validate' and handled by 'check', 'confirm', 'snapshot'. + /// A branch has become valid. + /// Issued by 'validate' and handled by 'check', 'confirm'. valid, - /// A checked block has failed validation (header_t). + /// A checked block has failed validation. /// Issued by 'validate' and handled by 'organize'. unvalid, /// Confirm (block). /// ----------------------------------------------------------------------- - /// A connected block has become confirmable (header_t). - /// Issued by 'confirm' and handled by 'snapshot'. + /// A connected block has become confirmable. + /// Issued by 'confirm' and handled by none. confirmable, - /// A connected block has failed confirmability (header_t). + /// A connected block has failed confirmability. /// Issued by 'confirm' and handled by 'organize'. unconfirmable, /// Confirm (chain). /// ----------------------------------------------------------------------- - /// A current block has been organized (header_t). + /// A current block has been organized. /// Issued by 'confirm' and handled by 'protocol_header/block_out/estimator'. block, - /// The confirmed chain is no longer current (default). + /// The confirmed chain is no longer current. /// Issued by 'confirm' and handled by 'protocol_transaction_out'. stale, - /// A confirmable block has been confirmed (header_t). + /// A confirmable block has been confirmed. /// Issued by 'confirm' and handled by 'transaction'. organized, - /// A previously confirmed block has been unconfirmed (header_t). + /// A previously confirmed block has been unconfirmed. /// Issued by 'confirm' and handled by 'transaction'. reorganized, /// Mining. /// ----------------------------------------------------------------------- - /// A transaction has been added to the pool (transaction_t). + /// A transaction has been added to the pool. /// Issued by 'transaction' and handled by 'template'. transaction, - /// A candidate block (template) has been created (height_t). + /// A candidate block (template) has been created. /// Issued by 'template' and handled by [miners]. template_, /// Stop. /// ----------------------------------------------------------------------- - /// Service is stopping, accompanied by error::service_stopped (default). + /// Service is stopping, accompanied by error::service_stopped. stop }; +/// Event payloads, one per chase value, declared in chase order. +namespace chases { + +struct start +{ + static constexpr chase id{ chase::start }; +}; + +struct space +{ + static constexpr chase id{ chase::space }; +}; + +struct snap +{ + static constexpr chase id{ chase::snap }; + height_t height; +}; + +struct bump +{ + static constexpr chase id{ chase::bump }; + height_t height; +}; + +struct suspend +{ + static constexpr chase id{ chase::suspend }; +}; + +struct resume +{ + static constexpr chase id{ chase::resume }; +}; + +struct unfull +{ + static constexpr chase id{ chase::unfull }; +}; + +struct starved +{ + static constexpr chase id{ chase::starved }; + object_t channel; +}; + +struct split +{ + static constexpr chase id{ chase::split }; + object_t channel; +}; + +struct stall +{ + static constexpr chase id{ chase::stall }; + object_t channel; +}; + +struct purge +{ + static constexpr chase id{ chase::purge }; + height_t branch_point; +}; + +struct report +{ + static constexpr chase id{ chase::report }; + count_t sequence; +}; + +struct blocks +{ + static constexpr chase id{ chase::blocks }; + height_t branch_point; +}; + +struct headers +{ + static constexpr chase id{ chase::headers }; + height_t branch_point; +}; + +struct download +{ + static constexpr chase id{ chase::download }; + count_t count; +}; + +struct regressed +{ + static constexpr chase id{ chase::regressed }; + height_t branch_point; +}; + +struct disorganized +{ + static constexpr chase id{ chase::disorganized }; + height_t branch_point; +}; + +struct checked +{ + static constexpr chase id{ chase::checked }; + height_t height; +}; + +struct unchecked +{ + static constexpr chase id{ chase::unchecked }; + header_t link; +}; + +struct windowed +{ + static constexpr chase id{ chase::windowed }; + height_t height; +}; + +struct valid +{ + static constexpr chase id{ chase::valid }; + height_t height; +}; + +struct unvalid +{ + static constexpr chase id{ chase::unvalid }; + header_t link; +}; + +struct confirmable +{ + static constexpr chase id{ chase::confirmable }; + header_t link; +}; + +struct unconfirmable +{ + static constexpr chase id{ chase::unconfirmable }; + header_t link; +}; + +struct block +{ + static constexpr chase id{ chase::block }; + header_t link; +}; + +struct stale +{ + static constexpr chase id{ chase::stale }; +}; + +struct organized +{ + static constexpr chase id{ chase::organized }; + header_t link; +}; + +struct reorganized +{ + static constexpr chase id{ chase::reorganized }; + header_t link; +}; + +struct transaction +{ + static constexpr chase id{ chase::transaction }; + transaction_t link; +}; + +struct template_ +{ + static constexpr chase id{ chase::template_ }; + height_t height; +}; + +struct stop +{ + static constexpr chase id{ chase::stop }; +}; + +} // namespace chases + +/// Alternative position is the chase value, so the event carries its own type. +using event_value = std::variant +< + chases::start, + chases::space, + chases::snap, + chases::bump, + chases::suspend, + chases::resume, + chases::unfull, + chases::starved, + chases::split, + chases::stall, + chases::purge, + chases::report, + chases::blocks, + chases::headers, + chases::download, + chases::regressed, + chases::disorganized, + chases::checked, + chases::unchecked, + chases::windowed, + chases::valid, + chases::unvalid, + chases::confirmable, + chases::unconfirmable, + chases::block, + chases::stale, + chases::organized, + chases::reorganized, + chases::transaction, + chases::template_, + chases::stop +>; + +template +constexpr bool is_chase_ordered(std::index_sequence) NOEXCEPT +{ + return ((std::variant_alternative_t::id == + static_cast(Index)) && ...); +} + +static_assert(is_chase_ordered(std::make_index_sequence< + std::variant_size_v>{})); + +/// The event's chase value. +constexpr chase to_chase(const event_value& value) NOEXCEPT +{ + return static_cast(value.index()); +} + +/// The event's payload, guarded by the alternative ordering above. +template +constexpr const auto& to_payload(const event_value& value) NOEXCEPT +{ + return std::get(value); +} + } // namespace node } // namespace libbitcoin diff --git a/include/bitcoin/node/chasers/chaser.hpp b/include/bitcoin/node/chasers/chaser.hpp index ce4252da..c2b6bc64 100644 --- a/include/bitcoin/node/chasers/chaser.hpp +++ b/include/bitcoin/node/chasers/chaser.hpp @@ -101,11 +101,10 @@ class BCN_API chaser virtual object_key subscribe_chase(event_notifier&& handler) NOEXCEPT; /// Set event (does not require node strand). - virtual void notify(const code& ec, chase event_, - event_value value) const NOEXCEPT; + virtual void notify(const code& ec, event_value value) const NOEXCEPT; /// Set event to one subscriber (does not require node strand). - virtual void notify_one(object_key key, const code& ec, chase event_, + virtual void notify_one(object_key key, const code& ec, event_value value) const NOEXCEPT; /// Strand. diff --git a/include/bitcoin/node/chasers/chaser_check.hpp b/include/bitcoin/node/chasers/chaser_check.hpp index 3bf5dbd8..3c6e3bdf 100644 --- a/include/bitcoin/node/chasers/chaser_check.hpp +++ b/include/bitcoin/node/chasers/chaser_check.hpp @@ -60,8 +60,7 @@ class BCN_API chaser_check protected: virtual void handle_purged(const code& ec) NOEXCEPT; - virtual bool handle_chase(const code& ec, chase event_, - event_value value) NOEXCEPT; + virtual bool handle_chase(const code& ec, event_value value) NOEXCEPT; /// block tracking virtual void do_bump(height_t height) NOEXCEPT; diff --git a/include/bitcoin/node/chasers/chaser_confirm.hpp b/include/bitcoin/node/chasers/chaser_confirm.hpp index 8aec0191..8c83396a 100644 --- a/include/bitcoin/node/chasers/chaser_confirm.hpp +++ b/include/bitcoin/node/chasers/chaser_confirm.hpp @@ -44,8 +44,7 @@ class BCN_API chaser_confirm using header_links = database::header_links; using header_states = database::header_states; - virtual bool handle_chase(const code& ec, chase event_, - event_value value) NOEXCEPT; + virtual bool handle_chase(const code& ec, event_value value) NOEXCEPT; virtual void do_regressed(height_t branch_point) NOEXCEPT; virtual void do_validated(height_t height) NOEXCEPT; diff --git a/include/bitcoin/node/chasers/chaser_estimate.hpp b/include/bitcoin/node/chasers/chaser_estimate.hpp index a4ed0b49..832d117a 100644 --- a/include/bitcoin/node/chasers/chaser_estimate.hpp +++ b/include/bitcoin/node/chasers/chaser_estimate.hpp @@ -52,8 +52,7 @@ class BCN_API chaser_estimate bool initialized() const NOEXCEPT; protected: - virtual bool handle_chase(const code& ec, chase event_, - event_value value) NOEXCEPT; + virtual bool handle_chase(const code& ec, event_value value) NOEXCEPT; virtual void do_initialize(header_t link) NOEXCEPT; virtual void do_organized(header_t link) NOEXCEPT; diff --git a/include/bitcoin/node/chasers/chaser_organize.hpp b/include/bitcoin/node/chasers/chaser_organize.hpp index 81d30ce5..869807a5 100644 --- a/include/bitcoin/node/chasers/chaser_organize.hpp +++ b/include/bitcoin/node/chasers/chaser_organize.hpp @@ -90,8 +90,7 @@ class chaser_organize /// ----------------------------------------------------------------------- /// Handle chaser events. - virtual bool handle_chase(const code&, chase event_, - event_value value) NOEXCEPT; + virtual bool handle_chase(const code&, event_value value) NOEXCEPT; /// Organize a discovered Block, prioritized accepts a tied branch. virtual void do_organize(typename Block::cptr block, bool prioritized, @@ -120,32 +119,40 @@ class chaser_organize // Template differentiators. // ------------------------------------------------------------------------ + static constexpr bool is_block_ + { + is_same_type + }; + + using chase_object = iif; + static constexpr bool is_block() NOEXCEPT { - return is_same_type; + return is_block_; } + static constexpr auto error_duplicate() NOEXCEPT { return is_block() ? error::duplicate_block : error::duplicate_header; } + static constexpr auto error_orphan() NOEXCEPT { return is_block() ? error::orphan_block : error::orphan_header; } - static constexpr auto chase_object() NOEXCEPT - { - return is_block() ? chase::blocks : chase::headers; - } + static constexpr auto events_object_archived() NOEXCEPT { return is_block() ? events::block_archived : events::header_archived; } + static constexpr auto events_object_organized() NOEXCEPT { // Using header because block organization is in confirmation chaser. ////return is_block() ? events::block_organized : events::header_organized; return events::header_organized; } + static constexpr auto events_object_reorganized() NOEXCEPT { // Using header because block reorganized is in confirmation chaser. diff --git a/include/bitcoin/node/chasers/chaser_snapshot.hpp b/include/bitcoin/node/chasers/chaser_snapshot.hpp index 61ba3ff7..0333e5c7 100644 --- a/include/bitcoin/node/chasers/chaser_snapshot.hpp +++ b/include/bitcoin/node/chasers/chaser_snapshot.hpp @@ -46,8 +46,7 @@ class BCN_API chaser_snapshot ////virtual void do_valid(height_t height) NOEXCEPT; ////virtual void do_confirm(height_t height) NOEXCEPT; - virtual bool handle_chase(const code& ec, chase event_, - event_value value) NOEXCEPT; + virtual bool handle_chase(const code& ec, event_value value) NOEXCEPT; private: void take_snapshot(height_t height) NOEXCEPT; diff --git a/include/bitcoin/node/chasers/chaser_storage.hpp b/include/bitcoin/node/chasers/chaser_storage.hpp index 61211a8d..5b3fd42e 100644 --- a/include/bitcoin/node/chasers/chaser_storage.hpp +++ b/include/bitcoin/node/chasers/chaser_storage.hpp @@ -43,8 +43,7 @@ class BCN_API chaser_storage protected: virtual void do_reload() NOEXCEPT; virtual void do_space(size_t space) NOEXCEPT; - virtual bool handle_chase(const code& ec, chase event_, - event_value value) NOEXCEPT; + virtual bool handle_chase(const code& ec, event_value value) NOEXCEPT; private: void do_stopping(const code& ec) NOEXCEPT; diff --git a/include/bitcoin/node/chasers/chaser_template.hpp b/include/bitcoin/node/chasers/chaser_template.hpp index 7f21874e..16529511 100644 --- a/include/bitcoin/node/chasers/chaser_template.hpp +++ b/include/bitcoin/node/chasers/chaser_template.hpp @@ -39,8 +39,7 @@ class BCN_API chaser_template code start() NOEXCEPT override; protected: - virtual bool handle_chase(const code& ec, chase event_, - event_value value) NOEXCEPT; + virtual bool handle_chase(const code& ec, event_value value) NOEXCEPT; virtual void do_transaction(transaction_t value) NOEXCEPT; }; diff --git a/include/bitcoin/node/chasers/chaser_transaction.hpp b/include/bitcoin/node/chasers/chaser_transaction.hpp index 4cc6fe34..d9d0ab80 100644 --- a/include/bitcoin/node/chasers/chaser_transaction.hpp +++ b/include/bitcoin/node/chasers/chaser_transaction.hpp @@ -44,8 +44,7 @@ class BCN_API chaser_transaction bool test, submit_handler&& handler) NOEXCEPT; protected: - virtual bool handle_chase(const code& ec, chase event_, - event_value value) NOEXCEPT; + virtual bool handle_chase(const code& ec, event_value value) NOEXCEPT; virtual void do_submit(const system::chain::transactions_cptr& txs, bool test, const submit_handler& handler) NOEXCEPT; diff --git a/include/bitcoin/node/chasers/chaser_validate.hpp b/include/bitcoin/node/chasers/chaser_validate.hpp index e2d76eb8..786f98f2 100644 --- a/include/bitcoin/node/chasers/chaser_validate.hpp +++ b/include/bitcoin/node/chasers/chaser_validate.hpp @@ -55,8 +55,7 @@ class BCN_API chaser_validate BIND_TO(method, args)); } - virtual bool handle_chase(const code& ec, chase event_, - event_value value) NOEXCEPT; + virtual bool handle_chase(const code& ec, event_value value) NOEXCEPT; virtual void do_regressed(height_t branch_point) NOEXCEPT; virtual void do_checked(height_t height) NOEXCEPT; diff --git a/include/bitcoin/node/define.hpp b/include/bitcoin/node/define.hpp index 91e4f3a5..cdd799db 100644 --- a/include/bitcoin/node/define.hpp +++ b/include/bitcoin/node/define.hpp @@ -40,7 +40,6 @@ #endif /// For common types below. -#include #include namespace libbitcoin { @@ -64,41 +63,14 @@ typedef std::shared_ptr map_ptr; typedef std::function map_handler; -/// Event desubscriber key type. -using object_key = uint64_t; - -/// Event value types. -using count_t = size_t; -using height_t = size_t; -using peer_t = uint64_t; -using object_t = object_key; -using header_t = database::header_link::integer; -using transaction_t = database::tx_link::integer; - -/// std::variant types must be distinct, and xcode size_t is neither uint32_t -/// nor uint64_t, so this ensures we have the distinct set of necessary types. -using event_value = - iif, - std::variant, - iif, - std::variant, - std::variant>>; - /// Event desubscriber. -typedef network::desubscriber event_subscriber; +typedef network::desubscriber event_subscriber; typedef event_subscriber::handler event_notifier; typedef event_subscriber::completer event_completer; // Inventory messages. using type_id = network::messages::peer::inventory_item::type_id; -// NDEBUG MSVC -////static_assert(sizeof(uint64_t) == 8u); -////static_assert(sizeof(block_t) == 16u); -////static_assert(sizeof(xblock_t) == 32u); -////static_assert(sizeof(event_value) == 24u); -////static_assert(sizeof(xevent_value) == 40u); - } // namespace node } // namespace libbitcoin diff --git a/include/bitcoin/node/full_node.hpp b/include/bitcoin/node/full_node.hpp index 9eba4fa9..7a01dada 100644 --- a/include/bitcoin/node/full_node.hpp +++ b/include/bitcoin/node/full_node.hpp @@ -87,11 +87,10 @@ class BCN_API full_node /// ----------------------------------------------------------------------- /// Set chaser event. - virtual void notify(const code& ec, chase event_, - event_value value) NOEXCEPT; + virtual void notify(const code& ec, event_value value) NOEXCEPT; /// Set chaser event for the given subscriber only. - virtual void notify_one(object_key key, const code& ec, chase event_, + virtual void notify_one(object_key key, const code& ec, event_value value) NOEXCEPT; /// Call from chaser start() methods (requires strand). @@ -186,8 +185,8 @@ class BCN_API full_node private: void do_subscribe_chase(const event_notifier& handler, const event_completer& complete) NOEXCEPT; - void do_notify(const code& ec, chase event_, event_value value) NOEXCEPT; - void do_notify_one(object_key key, const code& ec, chase event_, + void do_notify(const code& ec, event_value value) NOEXCEPT; + void do_notify_one(object_key key, const code& ec, event_value value) NOEXCEPT; // These are thread safe. diff --git a/include/bitcoin/node/impl/chasers/chaser_organize.ipp b/include/bitcoin/node/impl/chasers/chaser_organize.ipp index 31df6e5d..86593a1b 100644 --- a/include/bitcoin/node/impl/chasers/chaser_organize.ipp +++ b/include/bitcoin/node/impl/chasers/chaser_organize.ipp @@ -61,7 +61,7 @@ code CLASS::start() NOEXCEPT << state_->height() << "]."); update_checkpoint(top); - SUBSCRIBE_CHASE(handle_chase, _1, _2, _3); + SUBSCRIBE_CHASE(handle_chase, _1, _2); return error::success; } @@ -89,23 +89,40 @@ void CLASS::prioritize(const system::hash_digest& hash, // ---------------------------------------------------------------------------- TEMPLATE -bool CLASS::handle_chase(const code&, chase event_, event_value value) NOEXCEPT +bool CLASS::handle_chase(const code&, event_value value) NOEXCEPT { if (closed()) return false; - switch (event_) + switch (to_chase(value)) { + // Roll back the candidate chain to confirmed top (via fork point). case chase::unchecked: + { + if (database_settings().mark_unconfirmable) + { + POST(do_disorganize, to_payload(value).link); + } + + break; + } case chase::unvalid: + { + if (database_settings().mark_unconfirmable) + { + POST(do_disorganize, to_payload(value).link); + } + + break; + } case chase::unconfirmable: { - if (!database_settings().mark_unconfirmable) - break; + if (database_settings().mark_unconfirmable) + { + POST(do_disorganize, + to_payload(value).link); + } - // Roll back the candidate chain to confirmed top (via fork point). - BC_ASSERT(std::holds_alternative(value)); - POST(do_disorganize, std::get(value)); break; } case chase::stop: @@ -273,7 +290,7 @@ void CLASS::do_organize(typename Block::cptr block, bool prioritized, // Reset chasers to the branch point. if (regress) { - notify(error::success, chase::regressed, branch_point); + notify(error::success, chases::regressed{ branch_point }); } // Push stored strong headers to candidate chain. @@ -315,21 +332,23 @@ void CLASS::do_organize(typename Block::cptr block, bool prioritized, // Checking currency before notify also avoids excessive work backlog. if (is_block() || current) { - if (!bumped_) + if (!bumped_ || regress) { // If at start the fork point is top of both chains, and next candidate // is already downloaded, then new header will arrive and download will // be skipped, resulting in stall until restart at which time the start // event will advance through all downloaded candidates and progress on - // arrivals. This bumps validation once for current strong headers. - notify(error::success, chase::bump, add1(branch_point)); + // arrivals. This bumps validation once for current strong headers, and + // again on regression, as the candidate above the branch point may + // already be downloaded when reorganizing back to a stored branch. + notify(error::success, chases::bump{ add1(branch_point) }); bumped_ = true; } // chase::headers | chase::blocks // This prevents download stall, the check chaser races ahead. // Start block downloads, which upon completion bumps validation. - notify(error::success, chase_object(), branch_point); + notify(error::success, chase_object{ branch_point }); } // Logs from candidate block parent to the candidate (forward sequential). @@ -486,10 +505,10 @@ void CLASS::do_disorganize(header_t link) NOEXCEPT state_ = state; // Candidate is same as confirmed, reset chasers to new top. - notify(error::success, chase::disorganized, fork_point); + notify(error::success, chases::disorganized{ fork_point }); // Reset all connections to ensure that new connections exist. - notify(error::success, chase::suspend, {}); + notify(error::success, chases::suspend{}); } // Private setters diff --git a/include/bitcoin/node/impl/sessions/session_peer.ipp b/include/bitcoin/node/impl/sessions/session_peer.ipp index 95e62383..16ef7727 100644 --- a/include/bitcoin/node/impl/sessions/session_peer.ipp +++ b/include/bitcoin/node/impl/sessions/session_peer.ipp @@ -50,7 +50,7 @@ inline void CLASS::attach_handshake(const channel_ptr& channel, network::result_handler&& handler) NOEXCEPT { BC_ASSERT(channel->stranded()); - BC_ASSERT(channel->paused()); + BC_ASSERT(!channel->held()); // Set the current top for version protocol, before handshake. const auto top = this->archive().get_top_confirmed(); @@ -65,7 +65,7 @@ TEMPLATE inline void CLASS::attach_protocols(const channel_ptr& channel) NOEXCEPT { BC_ASSERT(channel->stranded()); - BC_ASSERT(channel->paused()); + BC_ASSERT(channel->held()); using namespace system; using namespace network; diff --git a/include/bitcoin/node/protocols/protocol_block_in_31800.hpp b/include/bitcoin/node/protocols/protocol_block_in_31800.hpp index 4f1358be..7dd789bd 100644 --- a/include/bitcoin/node/protocols/protocol_block_in_31800.hpp +++ b/include/bitcoin/node/protocols/protocol_block_in_31800.hpp @@ -61,8 +61,7 @@ class BCN_API protocol_block_in_31800 virtual void do_get_downloads(count_t count) NOEXCEPT; /// Handle chaser events. - virtual bool handle_chase(const code& ec, chase event_, - event_value value) NOEXCEPT; + virtual bool handle_chase(const code& ec, event_value value) NOEXCEPT; /// Manage work splitting. bool is_idle() const NOEXCEPT override; diff --git a/include/bitcoin/node/protocols/protocol_block_out_106.hpp b/include/bitcoin/node/protocols/protocol_block_out_106.hpp index 7e3c8f96..53424f5c 100644 --- a/include/bitcoin/node/protocols/protocol_block_out_106.hpp +++ b/include/bitcoin/node/protocols/protocol_block_out_106.hpp @@ -19,7 +19,6 @@ #ifndef LIBBITCOIN_NODE_PROTOCOLS_PROTOCOL_BLOCK_OUT_106_HPP #define LIBBITCOIN_NODE_PROTOCOLS_PROTOCOL_BLOCK_OUT_106_HPP -#include #include #include @@ -40,8 +39,7 @@ class BCN_API protocol_block_out_106 session->system_settings().top_checkpoint().height()), node_pruned_(session->node_settings().limited_blocks), node_witness_(session->node_settings().provide_witness), - allow_overlapped_(session->node_settings().allow_overlapped), - network::tracker(session->log) + network::tracker(session->log) { } @@ -61,8 +59,7 @@ class BCN_API protocol_block_out_106 virtual bool superseded() const NOEXCEPT; /// Handle chaser events. - virtual bool handle_chase(const code& ec, chase event_, - event_value value) NOEXCEPT; + virtual bool handle_chase(const code& ec, event_value value) NOEXCEPT; /// Process block announcement. virtual bool do_announce(header_t link) NOEXCEPT; @@ -71,13 +68,15 @@ class BCN_API protocol_block_out_106 const get_blocks::cptr& message) NOEXCEPT; virtual bool handle_receive_get_data(const code& ec, const get_data::cptr& message) NOEXCEPT; - virtual void send_block(const code& ec) NOEXCEPT; + virtual void send_block(const code& ec, size_t index, + const get_data::cptr& message, const gate_t::ptr& gate) NOEXCEPT; /// The item cannot be served, stops the channel and returns false. virtual bool handle_unservable(const inventory_item& item) NOEXCEPT; /// Send any unservable items accumulated above, false if none. - virtual bool report_unservable() NOEXCEPT; + virtual bool report_unservable(size_t index, + const get_data::cptr& message, const gate_t::ptr& gate) NOEXCEPT; private: using inventory = network::messages::peer::inventory; @@ -86,16 +85,11 @@ class BCN_API protocol_block_out_106 const database::header_link& link) NOEXCEPT; bool is_under_checkpoint(const database::header_link& link) NOEXCEPT; inventory create_inventory(const get_blocks& locator) const NOEXCEPT; - void merge_inventory(const inventory_items& items) NOEXCEPT; // These are thread safe. const size_t top_checkpoint_height_; const bool node_pruned_; const bool node_witness_; - const bool allow_overlapped_; - - // This is protected by strand. - std::deque backlog_{}; }; } // namespace node diff --git a/include/bitcoin/node/protocols/protocol_block_out_70001.hpp b/include/bitcoin/node/protocols/protocol_block_out_70001.hpp index 09104759..f9ed70d3 100644 --- a/include/bitcoin/node/protocols/protocol_block_out_70001.hpp +++ b/include/bitcoin/node/protocols/protocol_block_out_70001.hpp @@ -45,7 +45,8 @@ class BCN_API protocol_block_out_70001 bool handle_unservable(const inventory_item& item) NOEXCEPT override; /// Replies not_found with the accumulated items, false if none. - bool report_unservable() NOEXCEPT override; + bool report_unservable(size_t index, const get_data::cptr& message, + const gate_t::ptr& gate) NOEXCEPT override; private: // This is thread safe. diff --git a/include/bitcoin/node/protocols/protocol_filter_out_70015.hpp b/include/bitcoin/node/protocols/protocol_filter_out_70015.hpp index f15d16e7..53b8b102 100644 --- a/include/bitcoin/node/protocols/protocol_filter_out_70015.hpp +++ b/include/bitcoin/node/protocols/protocol_filter_out_70015.hpp @@ -52,7 +52,8 @@ class BCN_API protocol_filter_out_70015 private: using ancestry_ptr = std::shared_ptr; - void send_filter(const code& ec, const ancestry_ptr& ancestry) NOEXCEPT; + void send_filter(const code& ec, const ancestry_ptr& ancestry, + const gate_t::ptr& gate) NOEXCEPT; }; } // namespace node diff --git a/include/bitcoin/node/protocols/protocol_header_out_70012.hpp b/include/bitcoin/node/protocols/protocol_header_out_70012.hpp index b97e8268..52d29ab1 100644 --- a/include/bitcoin/node/protocols/protocol_header_out_70012.hpp +++ b/include/bitcoin/node/protocols/protocol_header_out_70012.hpp @@ -47,8 +47,7 @@ class BCN_API protocol_header_out_70012 protected: /// Handle chaser events. - virtual bool handle_chase(const code& ec, chase event_, - event_value value) NOEXCEPT; + virtual bool handle_chase(const code& ec, event_value value) NOEXCEPT; /// Process block announcement. virtual bool do_announce(header_t link) NOEXCEPT; diff --git a/include/bitcoin/node/protocols/protocol_observer.hpp b/include/bitcoin/node/protocols/protocol_observer.hpp index b7423596..0522cbdd 100644 --- a/include/bitcoin/node/protocols/protocol_observer.hpp +++ b/include/bitcoin/node/protocols/protocol_observer.hpp @@ -57,8 +57,7 @@ class BCN_API protocol_observer protected: /// Handle chaser events. - virtual bool handle_chase(const code& ec, chase event_, - event_value value) NOEXCEPT; + virtual bool handle_chase(const code& ec, event_value value) NOEXCEPT; /// Accept incoming inventory message. virtual bool handle_receive_inventory(const code& ec, diff --git a/include/bitcoin/node/protocols/protocol_peer.hpp b/include/bitcoin/node/protocols/protocol_peer.hpp index 743323e2..36a0404d 100644 --- a/include/bitcoin/node/protocols/protocol_peer.hpp +++ b/include/bitcoin/node/protocols/protocol_peer.hpp @@ -37,6 +37,7 @@ class BCN_API protocol_peer public: // Replace base class channel_t (network::channel_peer). using channel_t = node::channel_peer; + using gate_t = network::channel_peer::gate_t; protected: /// Constructors. @@ -94,11 +95,10 @@ class BCN_API protocol_peer using network::protocol_peer::notify; /// Set a chaser event. - virtual void notify(const code& ec, chase event_, - event_value value) const NOEXCEPT; + virtual void notify(const code& ec, event_value value) const NOEXCEPT; /// Set a chaser event. - virtual void notify_one(object_key key, const code& ec, chase event_, + virtual void notify_one(object_key key, const code& ec, event_value value) const NOEXCEPT; private: diff --git a/include/bitcoin/node/protocols/protocol_transaction_in_106.hpp b/include/bitcoin/node/protocols/protocol_transaction_in_106.hpp index 606866c1..5d667fc7 100644 --- a/include/bitcoin/node/protocols/protocol_transaction_in_106.hpp +++ b/include/bitcoin/node/protocols/protocol_transaction_in_106.hpp @@ -56,8 +56,10 @@ class BCN_API protocol_transaction_in_106 /// Accept incoming transaction message. virtual bool handle_receive_transaction(const code& ec, const network::messages::peer::transaction::cptr& message) NOEXCEPT; - virtual void handle_submit(const code& ec, size_t index) NOEXCEPT; - virtual void do_handle_submit(const code& ec) NOEXCEPT; + virtual void handle_submit(const code& ec, size_t index, + const gate_t::ptr& gate) NOEXCEPT; + virtual void do_handle_submit(const code& ec, + const gate_t::ptr& gate) NOEXCEPT; private: /// Squash duplicates and provide constant time retrieval. diff --git a/include/bitcoin/node/protocols/protocol_transaction_in_70013.hpp b/include/bitcoin/node/protocols/protocol_transaction_in_70013.hpp index cb37d00e..0db53f90 100644 --- a/include/bitcoin/node/protocols/protocol_transaction_in_70013.hpp +++ b/include/bitcoin/node/protocols/protocol_transaction_in_70013.hpp @@ -41,7 +41,8 @@ class BCN_API protocol_transaction_in_70013 protected: /// The peer is advised of the fee rate and of suspension (see fee_filter). - void do_handle_submit(const code& ec) NOEXCEPT override; + void do_handle_submit(const code& ec, + const gate_t::ptr& gate) NOEXCEPT override; }; } // namespace node diff --git a/include/bitcoin/node/protocols/protocol_transaction_out_106.hpp b/include/bitcoin/node/protocols/protocol_transaction_out_106.hpp index b515b23b..06528d00 100644 --- a/include/bitcoin/node/protocols/protocol_transaction_out_106.hpp +++ b/include/bitcoin/node/protocols/protocol_transaction_out_106.hpp @@ -50,8 +50,7 @@ class BCN_API protocol_transaction_out_106 using inventory_items = network::messages::peer::inventory_items; /// Handle chaser events. - virtual bool handle_chase(const code& ec, chase event_, - event_value value) NOEXCEPT; + virtual bool handle_chase(const code& ec, event_value value) NOEXCEPT; /// Process tx announcement. virtual bool do_announce(transaction_t link) NOEXCEPT; @@ -59,7 +58,8 @@ class BCN_API protocol_transaction_out_106 virtual bool handle_receive_get_data(const code& ec, const network::messages::peer::get_data::cptr& message) NOEXCEPT; virtual void send_transaction(const code& ec, size_t index, - const network::messages::peer::get_data::cptr& message) NOEXCEPT; + const network::messages::peer::get_data::cptr& message, + const gate_t::ptr& gate) NOEXCEPT; /// The item cannot be served, false terminates the send loop. virtual bool handle_unservable( @@ -67,7 +67,8 @@ class BCN_API protocol_transaction_out_106 /// Replies not_found with the accumulated items, false if none. virtual bool report_unservable(size_t index, - const network::messages::peer::get_data::cptr& message) NOEXCEPT; + const network::messages::peer::get_data::cptr& message, + const gate_t::ptr& gate) NOEXCEPT; virtual bool announce(const system::hash_digest& hash) NOEXCEPT; diff --git a/include/bitcoin/node/protocols/protocol_transaction_out_70001.hpp b/include/bitcoin/node/protocols/protocol_transaction_out_70001.hpp index 021af7b9..b02510c8 100644 --- a/include/bitcoin/node/protocols/protocol_transaction_out_70001.hpp +++ b/include/bitcoin/node/protocols/protocol_transaction_out_70001.hpp @@ -47,8 +47,8 @@ class BCN_API protocol_transaction_out_70001 /// Replies not_found with the accumulated items, false if none. bool report_unservable(size_t index, - const network::messages::peer::get_data::cptr& message) NOEXCEPT - override; + const network::messages::peer::get_data::cptr& message, + const gate_t::ptr& gate) NOEXCEPT override; private: // This is thread safe. diff --git a/include/bitcoin/node/protocols/protocol_transaction_out_70013.hpp b/include/bitcoin/node/protocols/protocol_transaction_out_70013.hpp index 687ee6a3..289c012f 100644 --- a/include/bitcoin/node/protocols/protocol_transaction_out_70013.hpp +++ b/include/bitcoin/node/protocols/protocol_transaction_out_70013.hpp @@ -44,8 +44,7 @@ class BCN_API protocol_transaction_out_70013 protected: /// Handle chaser events. - bool handle_chase(const code& ec, chase event_, - event_value value) NOEXCEPT override; + bool handle_chase(const code& ec, event_value value) NOEXCEPT override; /// Capture the peer's minimum fee rate for announcements. virtual bool handle_receive_fee_filter(const code& ec, diff --git a/include/bitcoin/node/sessions/session.hpp b/include/bitcoin/node/sessions/session.hpp index ebc3d85b..0dff8aa2 100644 --- a/include/bitcoin/node/sessions/session.hpp +++ b/include/bitcoin/node/sessions/session.hpp @@ -65,11 +65,10 @@ class BCN_API session /// ----------------------------------------------------------------------- /// Set a chaser event. - virtual void notify(const code& ec, chase event_, - event_value value) const NOEXCEPT; + virtual void notify(const code& ec, event_value value) const NOEXCEPT; /// Set chaser event for the given subscriber only. - virtual void notify_one(object_key key, const code& ec, chase event_, + virtual void notify_one(object_key key, const code& ec, event_value value) const NOEXCEPT; /// Subscribe to chaser events (requires node strand). diff --git a/include/bitcoin/node/settings.hpp b/include/bitcoin/node/settings.hpp index d398af19..d6d48501 100644 --- a/include/bitcoin/node/settings.hpp +++ b/include/bitcoin/node/settings.hpp @@ -39,7 +39,6 @@ class BCN_API settings bool headers_first; bool thread_priority; bool memory_priority; - bool allow_overlapped; bool provide_blocks; bool require_blocks; bool provide_witness; diff --git a/src/chasers/chaser.cpp b/src/chasers/chaser.cpp index 7d6f7c35..3e0ea12c 100644 --- a/src/chasers/chaser.cpp +++ b/src/chasers/chaser.cpp @@ -93,16 +93,15 @@ object_key chaser::subscribe_chase(event_notifier&& handler) NOEXCEPT return node_.subscribe_chase(std::move(handler)); } -void chaser::notify(const code& ec, chase event_, - event_value value) const NOEXCEPT +void chaser::notify(const code& ec, event_value value) const NOEXCEPT { - node_.notify(ec, event_, value); + node_.notify(ec, value); } -void chaser::notify_one(object_key key, const code& ec, chase event_, +void chaser::notify_one(object_key key, const code& ec, event_value value) const NOEXCEPT { - node_.notify_one(key, ec, event_, value); + node_.notify_one(key, ec, value); } // Strand. diff --git a/src/chasers/chaser_check.cpp b/src/chasers/chaser_check.cpp index bb27cc7c..dc93be89 100644 --- a/src/chasers/chaser_check.cpp +++ b/src/chasers/chaser_check.cpp @@ -99,7 +99,7 @@ code chaser_check::start() NOEXCEPT const auto added = set_unassociated(); LOGN("Fork point (" << requested_ << ") unassociated (" << added << ")."); - SUBSCRIBE_CHASE(handle_chase, _1, _2, _3); + SUBSCRIBE_CHASE(handle_chase, _1, _2); return error::success; } @@ -110,21 +110,19 @@ void chaser_check::stopping(const code& ec) NOEXCEPT chaser::stopping(ec); } -bool chaser_check::handle_chase(const code&, chase event_, - event_value value) NOEXCEPT +bool chaser_check::handle_chase(const code&, event_value value) NOEXCEPT { if (closed()) return false; - switch (event_) + switch (to_chase(value)) { // Performance. // ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ case chase::starved: { // When a channel becomes starved notify other(s) to split work. - BC_ASSERT(std::holds_alternative(value)); - POST(do_starved, std::get(value)); + POST(do_starved, to_payload(value).channel); break; } // Track downloaded. @@ -138,30 +136,32 @@ bool chaser_check::handle_chase(const code&, chase event_, } case chase::checked: { - BC_ASSERT(std::holds_alternative(value)); - POST(do_checked, std::get(value)); + POST(do_checked, to_payload(value).height); break; } case chase::regressed: + { + POST(do_regressed, + to_payload(value).branch_point); + break; + } case chase::disorganized: { - BC_ASSERT(std::holds_alternative(value)); - POST(do_regressed, std::get(value)); + POST(do_regressed, + to_payload(value).branch_point); break; } // Track chain. // ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ case chase::headers: { - BC_ASSERT(std::holds_alternative(value)); - POST(do_headers, std::get(value)); + POST(do_headers, to_payload(value).branch_point); break; } case chase::valid: ////case chase::prevalid: { - BC_ASSERT(std::holds_alternative(value)); - POST(do_advanced, std::get(value)); + POST(do_advanced, to_payload(value).height); break; } case chase::stop: @@ -239,12 +239,12 @@ void chaser_check::do_starved(object_t self) NOEXCEPT speeds_.erase(slowest); // Notify slow channel to split itself (in favor of 'self' channel). - notify_one(slow, error::success, chase::split, self); + notify_one(slow, error::success, chases::split{ self }); return; } // With no speeds recorded there may still be channels with work. - notify(error::success, chase::stall, self); + notify(error::success, chases::stall{ self }); } // update @@ -344,15 +344,18 @@ void chaser_check::do_regressed(height_t branch_point) NOEXCEPT { BC_ASSERT(stranded()); - // Inconsequential regression, work isn't there yet. - if (branch_point >= position()) + // Inconsequential regression, neither position nor window is there yet. + if (branch_point >= std::max(position(), requested_)) return; - // Update position, purge outstanding work, and wait on track completion. - set_position(branch_point); + // Update position and window, purge outstanding work, and wait on track + // completion. The window must follow the position or the gap it awaits + // is never requested. + set_position(std::min(branch_point, position())); + requested_ = advanced_ = position(); stop_tracking(); maps_.clear(); - notify(error::success, chase::purge, branch_point); + notify(error::success, chases::purge{ branch_point }); } // track downloaded in order (to move download window) @@ -396,7 +399,7 @@ void chaser_check::do_bump(height_t) NOEXCEPT // Notify validator that no more blocks are coming. if (height == requested_) - notify(error::success, chase::windowed, height); + notify(error::success, chases::windowed{ height }); } do_headers({}); @@ -410,7 +413,7 @@ void chaser_check::do_headers(height_t) NOEXCEPT BC_ASSERT(stranded()); if (const auto added = set_unassociated(); is_nonzero(added)) - notify(error::success, chase::download, added); + notify(error::success, chases::download{ added }); } // get/put hashes @@ -456,7 +459,7 @@ void chaser_check::do_put_hashes(const map_ptr& map, return; if (set_map(map)) - notify(error::success, chase::download, map->size()); + notify(error::success, chases::download{ map->size() }); handler(error::success); } diff --git a/src/chasers/chaser_confirm.cpp b/src/chasers/chaser_confirm.cpp index 4fe53701..2a164d29 100644 --- a/src/chasers/chaser_confirm.cpp +++ b/src/chasers/chaser_confirm.cpp @@ -53,7 +53,7 @@ code chaser_confirm::start() NOEXCEPT // Construct is too early to create the unstarted timer. stale_timer_ = std::make_shared(log, strand()); - SUBSCRIBE_CHASE(handle_chase, _1, _2, _3); + SUBSCRIBE_CHASE(handle_chase, _1, _2); return error::success; } @@ -74,8 +74,7 @@ void chaser_confirm::do_stopping(const code&) NOEXCEPT } } -bool chaser_confirm::handle_chase(const code&, chase event_, - event_value value) NOEXCEPT +bool chaser_confirm::handle_chase(const code&, event_value value) NOEXCEPT { if (closed()) return false; @@ -85,7 +84,7 @@ bool chaser_confirm::handle_chase(const code&, chase event_, if (suspended()) return true; - switch (event_) + switch (to_chase(value)) { case chase::resume: case chase::start: @@ -96,17 +95,19 @@ bool chaser_confirm::handle_chase(const code&, chase event_, } case chase::valid: { - // value is validated block height. - BC_ASSERT(std::holds_alternative(value)); - POST(do_validated, std::get(value)); + POST(do_validated, to_payload(value).height); break; } case chase::regressed: + { + POST(do_regressed, + to_payload(value).branch_point); + break; + } case chase::disorganized: { - // value is regression branch_point. - BC_ASSERT(std::holds_alternative(value)); - POST(do_regressed, std::get(value)); + POST(do_regressed, + to_payload(value).branch_point); break; } case chase::stop: @@ -297,7 +298,7 @@ void chaser_confirm::organize(header_states& fork, const header_links& popped, // Prevent stall by posting internal event, avoiding external handlers. // Posts new work, preventing recursion and releasing reorganization lock. - handle_chase(error::success, chase::bump, height_t{}); + handle_chase(error::success, chases::bump{}); } bool chaser_confirm::confirm_block(const header_link& link, size_t height, @@ -362,14 +363,14 @@ bool chaser_confirm::notify_block(const code& ec, size_t height, if (ec) { // UNCONFIRMABLE BLOCK (not a fault but discontinue) - notify(ec, chase::unconfirmable, link); + notify(ec, chases::unconfirmable{ link }); fire(events::block_unconfirmable, height); LOGR("Unconfirmable block [" << height << "] " << ec.message()); return false; } // CONFIRMABLE BLOCK - notify(error::success, chase::confirmable, link); + notify(error::success, chases::confirmable{ link }); fire(events::block_confirmed, height); LOGV("Block confirmed: " << height << (bypass ? " (bypass)" : "")); return true; @@ -387,7 +388,7 @@ bool chaser_confirm::set_reorganized(const header_link& link, if (!archive().pop_confirmed()) return false; - notify(error::success, chase::reorganized, link); + notify(error::success, chases::reorganized{ link }); fire(events::block_reorganized, confirmed_height); LOGV("Block reorganized: " << confirmed_height); return true; @@ -420,7 +421,7 @@ bool chaser_confirm::set_organized(const header_link& link, if (!query.push_confirmed(link, !is_under_checkpoint(confirmed_height))) return false; - notify(error::success, chase::organized, link); + notify(error::success, chases::organized{ link }); fire(events::block_organized, confirmed_height); LOGV("Block organized: " << confirmed_height); @@ -452,7 +453,7 @@ void chaser_confirm::announce(const header_link& link, height_t) NOEXCEPT // Announce newly-organized blocks when confirmed chain is current. if (is_current_chain(true)) { - notify(error::success, chase::block, link); + notify(error::success, chases::block{ link }); start_stale_timer(); } } @@ -489,7 +490,7 @@ void chaser_confirm::handle_stale_timer(const code& ec) NOEXCEPT return; } - notify(error::success, chase::stale, {}); + notify(error::success, chases::stale{}); } BC_POP_WARNING() diff --git a/src/chasers/chaser_estimate.cpp b/src/chasers/chaser_estimate.cpp index 254bdda2..46da0282 100644 --- a/src/chasers/chaser_estimate.cpp +++ b/src/chasers/chaser_estimate.cpp @@ -46,7 +46,7 @@ code chaser_estimate::start() NOEXCEPT { if (node_settings().fee_estimate_enabled()) { - SUBSCRIBE_CHASE(handle_chase, _1, _2, _3); + SUBSCRIBE_CHASE(handle_chase, _1, _2); } return error::success; @@ -108,8 +108,7 @@ bool chaser_estimate::initialized() const NOEXCEPT // ---------------------------------------------------------------------------- // protected -bool chaser_estimate::handle_chase(const code&, chase event_, - event_value value) NOEXCEPT +bool chaser_estimate::handle_chase(const code&, event_value value) NOEXCEPT { if (closed()) return false; @@ -118,7 +117,7 @@ bool chaser_estimate::handle_chase(const code&, chase event_, ////if (suspended()) //// return true; - switch (event_) + switch (to_chase(value)) { // chase::block is only sent when current. This is captured as a cheap // way to test currency for initialization. Once initialized it is not @@ -128,8 +127,7 @@ bool chaser_estimate::handle_chase(const code&, chase event_, { if (!initialized()) { - BC_ASSERT(std::holds_alternative(value)); - POST(do_initialize, std::get(value)); + POST(do_initialize, to_payload(value).link); } break; @@ -138,8 +136,8 @@ bool chaser_estimate::handle_chase(const code&, chase event_, { if (initialized()) { - BC_ASSERT(std::holds_alternative(value)); - POST(do_organized, std::get(value)); + POST(do_organized, + to_payload(value).link); } break; @@ -148,8 +146,8 @@ bool chaser_estimate::handle_chase(const code&, chase event_, { if (initialized()) { - BC_ASSERT(std::holds_alternative(value)); - POST(do_reorganized, std::get(value)); + POST(do_reorganized, + to_payload(value).link); } break; diff --git a/src/chasers/chaser_snapshot.cpp b/src/chasers/chaser_snapshot.cpp index 59c766a9..04df0e3f 100644 --- a/src/chasers/chaser_snapshot.cpp +++ b/src/chasers/chaser_snapshot.cpp @@ -65,15 +65,14 @@ code chaser_snapshot::start() NOEXCEPT ////if (enabled_confirm_) //// confirm_ = std::max(archive().get_top_confirmed(), checkpoint()); - SUBSCRIBE_CHASE(handle_chase, _1, _2, _3); + SUBSCRIBE_CHASE(handle_chase, _1, _2); return error::success; } // event handlers // ---------------------------------------------------------------------------- -bool chaser_snapshot::handle_chase(const code&, chase event_, - event_value value) NOEXCEPT +bool chaser_snapshot::handle_chase(const code&, event_value value) NOEXCEPT { if (closed()) return false; @@ -83,7 +82,7 @@ bool chaser_snapshot::handle_chase(const code&, chase event_, if (suspended()) return true; - switch (event_) + switch (to_chase(value)) { // blocks first and headers first (checked) messages ////case chase::blocks: @@ -119,14 +118,12 @@ bool chaser_snapshot::handle_chase(const code&, chase event_, if (pruned_.load(std::memory_order_relaxed)) break; - BC_ASSERT(std::holds_alternative(value)); - POST(do_prune, std::get(value)); + POST(do_prune, to_payload(value).link); break; } case chase::snap: { - BC_ASSERT(std::holds_alternative(value)); - POST(do_snap, std::get(value)); + POST(do_snap, to_payload(value).height); break; } default: diff --git a/src/chasers/chaser_storage.cpp b/src/chasers/chaser_storage.cpp index 5ab3a18e..40e2e9d9 100644 --- a/src/chasers/chaser_storage.cpp +++ b/src/chasers/chaser_storage.cpp @@ -50,7 +50,7 @@ code chaser_storage::start() NOEXCEPT // Construct is too early to create the unstarted timer. disk_timer_ = std::make_shared(log, strand(), seconds{1}); - SUBSCRIBE_CHASE(handle_chase, _1, _2, _3); + SUBSCRIBE_CHASE(handle_chase, _1, _2); return error::success; } @@ -73,13 +73,12 @@ void chaser_storage::do_stopping(const code&) NOEXCEPT // event handlers // ---------------------------------------------------------------------------- -bool chaser_storage::handle_chase(const code&, chase event_, - event_value) NOEXCEPT +bool chaser_storage::handle_chase(const code&, event_value value) NOEXCEPT { if (closed()) return false; - switch (event_) + switch (to_chase(value)) { case chase::space: { @@ -166,7 +165,7 @@ void chaser_storage::do_reload() NOEXCEPT else { // Recovery from disk full message sent in addition to chase::resume. - notify(error::success, chase::unfull, {}); + notify(error::success, chases::unfull{}); resume(); const auto span = duration_cast(logger::now() - start); diff --git a/src/chasers/chaser_template.cpp b/src/chasers/chaser_template.cpp index 3582a915..b235165b 100644 --- a/src/chasers/chaser_template.cpp +++ b/src/chasers/chaser_template.cpp @@ -43,15 +43,14 @@ chaser_template::chaser_template(full_node& node) NOEXCEPT // TODO: initialize template state. code chaser_template::start() NOEXCEPT { - SUBSCRIBE_CHASE(handle_chase, _1, _2, _3); + SUBSCRIBE_CHASE(handle_chase, _1, _2); return error::success; } // event handlers // ---------------------------------------------------------------------------- -bool chaser_template::handle_chase(const code&, chase event_, - event_value value) NOEXCEPT +bool chaser_template::handle_chase(const code&, event_value value) NOEXCEPT { if (closed()) return false; @@ -62,12 +61,11 @@ bool chaser_template::handle_chase(const code&, chase event_, return true; // TODO: also handle confirmed/unconfirmed. - switch (event_) + switch (to_chase(value)) { case chase::transaction: { - BC_ASSERT(std::holds_alternative(value)); - POST(do_transaction, std::get(value)); + POST(do_transaction, to_payload(value).link); break; } case chase::stop: diff --git a/src/chasers/chaser_transaction.cpp b/src/chasers/chaser_transaction.cpp index 9dcc6789..eb08c329 100644 --- a/src/chasers/chaser_transaction.cpp +++ b/src/chasers/chaser_transaction.cpp @@ -46,7 +46,7 @@ chaser_transaction::chaser_transaction(full_node& node) NOEXCEPT code chaser_transaction::start() NOEXCEPT { - SUBSCRIBE_CHASE(handle_chase, _1, _2, _3); + SUBSCRIBE_CHASE(handle_chase, _1, _2); POST(do_bump); return error::success; } @@ -54,13 +54,12 @@ code chaser_transaction::start() NOEXCEPT // event handlers // ---------------------------------------------------------------------------- -bool chaser_transaction::handle_chase(const code&, chase event_, - event_value) NOEXCEPT +bool chaser_transaction::handle_chase(const code&, event_value value) NOEXCEPT { if (closed()) return false; - switch (event_) + switch (to_chase(value)) { case chase::organized: case chase::reorganized: @@ -167,7 +166,7 @@ void chaser_transaction::do_submit(const transactions_cptr& txs, bool test, } fire(events::tx_archived, to_rate(tx)); - notify(error::success, chase::transaction, transaction_t{ link }); + notify(error::success, chases::transaction{ link }); } handler(error::success, {}); diff --git a/src/chasers/chaser_validate.cpp b/src/chasers/chaser_validate.cpp index 03101aed..06786311 100644 --- a/src/chasers/chaser_validate.cpp +++ b/src/chasers/chaser_validate.cpp @@ -66,16 +66,17 @@ code chaser_validate::start() NOEXCEPT if (const auto ec = start_batch()) return fault(ec); - SUBSCRIBE_CHASE(handle_chase, _1, _2, _3); + SUBSCRIBE_CHASE(handle_chase, _1, _2); return error::success; } -bool chaser_validate::handle_chase(const code&, chase event_, - event_value value) NOEXCEPT +bool chaser_validate::handle_chase(const code&, event_value value) NOEXCEPT { if (closed()) return false; + const auto event_ = to_chase(value); + // Latch recovering from disk full, before suspension is lifted. // Because in-flight blocks are lost, reset position when backlog clears. if (event_ == chase::unfull) @@ -113,27 +114,28 @@ bool chaser_validate::handle_chase(const code&, chase event_, } case chase::checked: { - // value is checked block height. - BC_ASSERT(std::holds_alternative(value)); - POST(do_checked, std::get(value)); + POST(do_checked, to_payload(value).height); break; } case chase::windowed: { - // value is last height in window. Called directly (not posted): - // the drain must never depend on scheduling, which saturated - // validations can exhaust for the entire window (strand for - // admission-side control, never for release-side). - BC_ASSERT(std::holds_alternative(value)); + // Called directly (not posted): the drain must never depend on + // scheduling, which saturated validations can exhaust for the + // entire window (strand for admission-side control, never for + // release-side). process_batch(is_residual()); break; } case chase::regressed: + { + POST(do_regressed, + to_payload(value).branch_point); + break; + } case chase::disorganized: { - // value is regression branch_point. - BC_ASSERT(std::holds_alternative(value)); - POST(do_regressed, std::get(value)); + POST(do_regressed, + to_payload(value).branch_point); break; } case chase::stop: @@ -267,7 +269,7 @@ void chaser_validate::complete_block(const code& ec, const header_link& link, if (is_zero(validate_backlog_.load()) && !stranded()) { // Prevent stall by posting internal event, avoiding external handlers. - handle_chase({}, chase::bump, height_t{}); + handle_chase({}, chases::bump{}); } // Node errors are fatal (or disk full recoverable). @@ -327,14 +329,15 @@ void chaser_validate::notify_block(const code& ec, size_t height, if (ec) { // INVALID BLOCK (not a fault but discontinue) - if (!startup) notify(ec, chase::unvalid, link); + if (!startup) notify(ec, chases::unvalid{ link }); fire(events::block_unconfirmable, height); LOGR("Invalid block [" << height << "] " << ec.message()); return; } // VALID BLOCK - if (!startup) notify(ec, chase::valid, possible_wide_cast(height)); + if (!startup) + notify(ec, chases::valid{ possible_wide_cast(height) }); fire(events::block_validated, height); LOGV("Block validated: " << height << (bypass ? " (bypass)" : "")); } diff --git a/src/full_node.cpp b/src/full_node.cpp index a538b38a..e031e657 100644 --- a/src/full_node.cpp +++ b/src/full_node.cpp @@ -115,7 +115,7 @@ void full_node::do_run(const result_handler& handler) NOEXCEPT // Bump sequential chasers to their starting heights. // This will kick off lagging validations even if not current. - do_notify(error::success, chase::start, height_t{}); + do_notify(error::success, chases::start{}); // Start services after network is running. net::do_run(handler); @@ -156,7 +156,7 @@ void full_node::do_close() NOEXCEPT chaser_snapshot_.stopping(network::error::service_stopped); chaser_storage_.stopping(network::error::service_stopped); - event_subscriber_.stop(network::error::service_stopped, chase::stop, {}); + event_subscriber_.stop(network::error::service_stopped, chases::stop{}); net::do_close(); } @@ -204,36 +204,34 @@ void full_node::put_hashes(const map_ptr& map, // Events. // ---------------------------------------------------------------------------- -void full_node::notify(const code& ec, chase event_, - event_value value) NOEXCEPT +void full_node::notify(const code& ec, event_value value) NOEXCEPT { boost::asio::post(strand(), std::bind(&full_node::do_notify, - this, ec, event_, value)); + this, ec, value)); } // private -void full_node::do_notify(const code& ec, chase event_, - event_value value) NOEXCEPT +void full_node::do_notify(const code& ec, event_value value) NOEXCEPT { BC_ASSERT(stranded()); - event_subscriber_.notify(ec, event_, value); + event_subscriber_.notify(ec, value); } -void full_node::notify_one(object_key key, const code& ec, chase event_, +void full_node::notify_one(object_key key, const code& ec, event_value value) NOEXCEPT { boost::asio::post(strand(), std::bind(&full_node::do_notify_one, - this, key, ec, event_, value)); + this, key, ec, value)); } // private -void full_node::do_notify_one(object_key key, const code& ec, chase event_, +void full_node::do_notify_one(object_key key, const code& ec, event_value value) NOEXCEPT { BC_ASSERT(stranded()); - event_subscriber_.notify_one(key, ec, event_, value); + event_subscriber_.notify_one(key, ec, value); } object_key full_node::subscribe_chase(event_notifier&& handler) NOEXCEPT @@ -263,7 +261,7 @@ void full_node::do_subscribe_chase(const event_notifier& handler, void full_node::unsubscribe_chase(object_key key) NOEXCEPT { - notify_one(key, network::error::service_stopped, chase::stop, {}); + notify_one(key, network::error::service_stopped, chases::stop{}); } // Suspensions. @@ -284,7 +282,7 @@ bool full_node::resume() NOEXCEPT } LOGS("Resuming network."); - notify(error::success, chase::resume, {}); + notify(error::success, chases::resume{}); return net::resume(); } @@ -293,7 +291,7 @@ void full_node::suspend(const code& ec) NOEXCEPT { LOGS("Suspending network, " << ec.message()); net::suspend(ec); - notify(error::suspended_channel, chase::suspend, {}); + notify(error::suspended_channel, chases::suspend{}); } void full_node::fault(const code& ec) NOEXCEPT @@ -302,7 +300,7 @@ void full_node::fault(const code& ec) NOEXCEPT { LOGF("Disk full [" << query_.get_space() << "] bytes required following, " << ec.message()); - notify(ec, chase::space, {}); + notify(ec, chases::space{}); } else if (query_.is_fault()) { diff --git a/src/protocols/protocol_block_in_31800.cpp b/src/protocols/protocol_block_in_31800.cpp index 803efa29..27994db6 100644 --- a/src/protocols/protocol_block_in_31800.cpp +++ b/src/protocols/protocol_block_in_31800.cpp @@ -49,7 +49,7 @@ void protocol_block_in_31800::start() NOEXCEPT return; // Events subscription is asynchronous, events may be missed. - subscribe_chase(BIND(handle_chase, _1, _2, _3)); + subscribe_chase(BIND(handle_chase, _1, _2)); SUBSCRIBE_CHANNEL(block, handle_receive_block, _1, _2); protocol_performer::start(); } @@ -95,14 +95,14 @@ bool protocol_block_in_31800::is_idle() const NOEXCEPT return map_->empty(); } -bool protocol_block_in_31800::handle_chase(const code&, chase event_, +bool protocol_block_in_31800::handle_chase(const code&, event_value value) NOEXCEPT { // Do not pass ec to stopped as it is not a call status. if (stopped()) return false; - switch (event_) + switch (to_chase(value)) { case chase::split: { @@ -131,14 +131,12 @@ bool protocol_block_in_31800::handle_chase(const code&, chase event_, // There are count blocks to download at/above given header. // chase::headers is only sent for current candidate chain, and this // chase::download is only sent as a consequence of chase::headers. - BC_ASSERT(std::holds_alternative(value)); - POST(do_get_downloads, std::get(value)); + POST(do_get_downloads, to_payload(value).count); break; } case chase::report: { - BC_ASSERT(std::holds_alternative(value)); - POST(do_report, std::get(value)); + POST(do_report, to_payload(value).sequence); break; } case chase::stop: @@ -324,7 +322,7 @@ bool protocol_block_in_31800::handle_receive_block(const code& ec, LOGR("Block failed check [" << encode_hash(hash) << ":" << height << "] from [" << opposite() << "] " << code.message()); - notify(error::success, chase::unchecked, link); + notify(error::success, chases::unchecked{ link }); fire(events::block_unconfirmable, height); stop(code); return false; @@ -351,7 +349,7 @@ bool protocol_block_in_31800::handle_receive_block(const code& ec, LOGP("Downloaded block [" << encode_hash(hash) << ":" << height << "] from [" << opposite() << "]."); - notify(ec, chase::checked, height); + notify(ec, chases::checked{ height }); fire(events::block_archived, height); count(block.serialized_size(true)); @@ -425,7 +423,7 @@ void protocol_block_in_31800::handle_get_hashes(const code& ec, if (map->empty()) { - notify(error::success, chase::starved, events_key()); + notify(error::success, chases::starved{ events_key() }); return; } diff --git a/src/protocols/protocol_block_out_106.cpp b/src/protocols/protocol_block_out_106.cpp index ccd1d63a..18b8d023 100644 --- a/src/protocols/protocol_block_out_106.cpp +++ b/src/protocols/protocol_block_out_106.cpp @@ -51,7 +51,7 @@ void protocol_block_out_106::start() NOEXCEPT return; // Events subscription is asynchronous, events may be missed. - subscribe_chase(BIND(handle_chase, _1, _2, _3)); + subscribe_chase(BIND(handle_chase, _1, _2)); SUBSCRIBE_CHANNEL(get_data, handle_receive_get_data, _1, _2); SUBSCRIBE_CHANNEL(get_blocks, handle_receive_get_blocks, _1, _2); protocol_peer::start(); @@ -68,20 +68,18 @@ void protocol_block_out_106::stopping(const code& ec) NOEXCEPT // handle events (block) // ---------------------------------------------------------------------------- -bool protocol_block_out_106::handle_chase(const code&, chase event_, +bool protocol_block_out_106::handle_chase(const code&, event_value value) NOEXCEPT { // Do not pass ec to stopped as it is not a call status. if (stopped() || superseded()) return false; - switch (event_) + switch (to_chase(value)) { case chase::block: { - // value is organized block pk. - BC_ASSERT(std::holds_alternative(value)); - POST(do_announce, std::get(value)); + POST(do_announce, to_payload(value).link); break; } default: @@ -163,42 +161,15 @@ bool protocol_block_out_106::handle_receive_get_data(const code& ec, if (is_zero(size)) return true; - const auto total = ceilinged_add(backlog_.size(), size); - if (total > network::messages::peer::max_inventory) - { - LOGR("Blocks requested (" << total << ") exceeds inv limit [" - << opposite() << "]."); - stop(network::error::protocol_violation); - return false; - } - - // Satoshi sends overlapping get_data requests, but assumes that the - // recipient is blocking *all traffic* until the previous is completed. - // So to prevent frequent drops of satoshi peers, and not let one protocol - // block all others, we must accumulate the requests into a backlog. If the - // backlog exceeds the *individual* message limit we drop the peer. - const auto idle = backlog_.empty(); - if (!allow_overlapped_ && !idle) - { - LOGR("Overlapping block requests [" << opposite() << "]."); - stop(network::error::protocol_violation); - return false; - } - - // Append the new inventory the request queue. - merge_inventory(message->items); - - // Bump the idle async send loop if no pending send. - if (idle) - send_block(error::success); - + send_block(error::success, zero, message, gate()); return true; } // Outbound (block). // ---------------------------------------------------------------------------- -void protocol_block_out_106::send_block(const code& ec) NOEXCEPT +void protocol_block_out_106::send_block(const code& ec, size_t index, + const get_data::cptr& message, const gate_t::ptr& gate) NOEXCEPT { BC_ASSERT(stranded()); if (stopped(ec)) @@ -206,13 +177,16 @@ void protocol_block_out_106::send_block(const code& ec) NOEXCEPT const auto& query = archive(); - // Drain unservable items from the front of the backlog. The derived + // Drain unservable items, skipping non-block inventory. The derived // protocol accumulates them if it reports them, and otherwise stops the - // channel on the first. Copied because each is handled after the pop. + // channel on the first. database::header_link link{}; - while (!backlog_.empty()) + for (; index < message->items.size(); ++index) { - const auto item = backlog_.front(); + const auto& item = message->items.at(index); + if (!item.is_block()) + continue; + if (item.is_witness_type() && !node_witness_) { LOGR("Unsupported witness get_data from [" << opposite() << "]."); @@ -224,18 +198,18 @@ void protocol_block_out_106::send_block(const code& ec) NOEXCEPT if (is_servable(item, link)) break; - backlog_.pop_front(); if (!handle_unservable(item)) return; } // The report resumes this loop on completion, so it precedes the block. - if (report_unservable()) + if (report_unservable(index, message, gate)) return; - if (backlog_.empty()) return; + if (index >= message->items.size()) + return; - const auto item = backlog_.front(); + const auto& item = message->items.at(index); const auto witness = item.is_witness_type(); const auto start = logger::now(); messages::peer::block out @@ -249,16 +223,14 @@ void protocol_block_out_106::send_block(const code& ec) NOEXCEPT LOGV("Requested block " << encode_hash(item.hash) << " from [" << opposite() << "] not obtained."); - backlog_.pop_front(); if (handle_unservable(item)) - report_unservable(); + report_unservable(add1(index), message, gate); return; } - backlog_.pop_front(); span(events::block_usecs, start); - SEND(std::move(out), send_block, _1); + SEND(std::move(out), send_block, _1, add1(index), message, gate); } // The checkpoint, milestone and association queries assume an archived header. @@ -308,7 +280,8 @@ bool protocol_block_out_106::handle_unservable( } // There is nothing to report below bip37, the channel is stopped above. -bool protocol_block_out_106::report_unservable() NOEXCEPT +bool protocol_block_out_106::report_unservable(size_t, + const get_data::cptr&, const gate_t::ptr&) NOEXCEPT { BC_ASSERT(stranded()); return false; @@ -317,13 +290,6 @@ bool protocol_block_out_106::report_unservable() NOEXCEPT // utilities // ---------------------------------------------------------------------------- -void protocol_block_out_106::merge_inventory( - const inventory_items& items) NOEXCEPT -{ - for (const auto& item: items) - if (item.is_block()) - backlog_.push_back(item); -} protocol_block_out_106::inventory protocol_block_out_106::create_inventory( const get_blocks& locator) const NOEXCEPT diff --git a/src/protocols/protocol_block_out_70001.cpp b/src/protocols/protocol_block_out_70001.cpp index 06bc39b0..2ce81d94 100644 --- a/src/protocols/protocol_block_out_70001.cpp +++ b/src/protocols/protocol_block_out_70001.cpp @@ -52,7 +52,8 @@ bool protocol_block_out_70001::handle_unservable( // The items are answered and the send loop resumed, as with a block, so // nothing is produced until the prior write completes. -bool protocol_block_out_70001::report_unservable() NOEXCEPT +bool protocol_block_out_70001::report_unservable(size_t index, + const get_data::cptr& message, const gate_t::ptr& gate) NOEXCEPT { BC_ASSERT(stranded()); @@ -62,7 +63,7 @@ bool protocol_block_out_70001::report_unservable() NOEXCEPT auto items = std::move(unservable_); unservable_.clear(); - SEND(not_found{ std::move(items) }, send_block, _1); + SEND(not_found{ std::move(items) }, send_block, _1, index, message, gate); return true; } diff --git a/src/protocols/protocol_filter_out_70015.cpp b/src/protocols/protocol_filter_out_70015.cpp index 52bd329d..46a16d9f 100644 --- a/src/protocols/protocol_filter_out_70015.cpp +++ b/src/protocols/protocol_filter_out_70015.cpp @@ -220,25 +220,20 @@ bool protocol_filter_out_70015::handle_receive_get_filters(const code& ec, return false; } - // Post so the completion resubscribe runs outside the current notify(). span(events::ancestry_msecs, start); - POST(send_filter, error::success, ancestry); - return false; + send_filter(error::success, ancestry, gate()); + return true; } void protocol_filter_out_70015::send_filter(const code& ec, - const ancestry_ptr& ancestry) NOEXCEPT + const ancestry_ptr& ancestry, const gate_t::ptr& gate) NOEXCEPT { BC_ASSERT(stranded()); if (stopped(ec)) return; if (ancestry->empty()) - { - // Complete, resubscribe to get_client_filters. - SUBSCRIBE_CHANNEL(get_client_filters, handle_receive_get_filters, _1, _2); return; - } const auto& query = archive(); const auto start = logger::now(); @@ -255,7 +250,7 @@ void protocol_filter_out_70015::send_filter(const code& ec, out.block_hash = query.get_header_key(link); out.filter_type = client_filter::type_id::neutrino; span(events::filter_msecs, start); - SEND(out, send_filter, _1, ancestry); + SEND(out, send_filter, _1, ancestry, gate); } BC_POP_WARNING() diff --git a/src/protocols/protocol_header_out_70012.cpp b/src/protocols/protocol_header_out_70012.cpp index 49e23952..2e8f49a4 100644 --- a/src/protocols/protocol_header_out_70012.cpp +++ b/src/protocols/protocol_header_out_70012.cpp @@ -59,20 +59,18 @@ void protocol_header_out_70012::stopping(const code& ec) NOEXCEPT // handle events (block) // ---------------------------------------------------------------------------- -bool protocol_header_out_70012::handle_chase(const code&, chase event_, +bool protocol_header_out_70012::handle_chase(const code&, event_value value) NOEXCEPT { // Do not pass ec to stopped as it is not a call status. if (stopped()) return false; - switch (event_) + switch (to_chase(value)) { case chase::block: { - // value is organized block pk. - BC_ASSERT(std::holds_alternative(value)); - POST(do_announce, std::get(value)); + POST(do_announce, to_payload(value).link); break; } default: @@ -130,7 +128,7 @@ bool protocol_header_out_70012::handle_receive_send_headers(const code& ec, return false; // Events subscription is asynchronous, events may be missed. - subscribe_chase(BIND(handle_chase, _1, _2, _3)); + subscribe_chase(BIND(handle_chase, _1, _2)); return false; } diff --git a/src/protocols/protocol_observer.cpp b/src/protocols/protocol_observer.cpp index faf45e36..586047f0 100644 --- a/src/protocols/protocol_observer.cpp +++ b/src/protocols/protocol_observer.cpp @@ -43,7 +43,7 @@ void protocol_observer::start() NOEXCEPT return; // Events subscription is asynchronous, events may be missed. - subscribe_chase(BIND(handle_chase, _1, _2, _3)); + subscribe_chase(BIND(handle_chase, _1, _2)); if (relay_disallowed_) { @@ -66,14 +66,13 @@ void protocol_observer::stopping(const code& ec) NOEXCEPT // handle events (suspend) // ---------------------------------------------------------------------------- -bool protocol_observer::handle_chase(const code& ec, chase event_, - event_value) NOEXCEPT +bool protocol_observer::handle_chase(const code& ec, event_value value) NOEXCEPT { // Do not pass ec to stopped as it is not a call status. if (stopped()) return false; - switch (event_) + switch (to_chase(value)) { case chase::suspend: { diff --git a/src/protocols/protocol_peer.cpp b/src/protocols/protocol_peer.cpp index e67b88f4..259ac16c 100644 --- a/src/protocols/protocol_peer.cpp +++ b/src/protocols/protocol_peer.cpp @@ -81,16 +81,15 @@ bool protocol_peer::was_announced(const system::hash_digest& hash) const NOEXCEP // Events notification. // ---------------------------------------------------------------------------- -void protocol_peer::notify(const code& ec, chase event_, - event_value value) const NOEXCEPT +void protocol_peer::notify(const code& ec, event_value value) const NOEXCEPT { - session_->notify(ec, event_, value); + session_->notify(ec, value); } -void protocol_peer::notify_one(object_key key, const code& ec, chase event_, +void protocol_peer::notify_one(object_key key, const code& ec, event_value value) const NOEXCEPT { - session_->notify_one(key, ec, event_, value); + session_->notify_one(key, ec, value); } } // namespace node diff --git a/src/protocols/protocol_transaction_in_106.cpp b/src/protocols/protocol_transaction_in_106.cpp index 71a79088..3b331f70 100644 --- a/src/protocols/protocol_transaction_in_106.cpp +++ b/src/protocols/protocol_transaction_in_106.cpp @@ -148,19 +148,21 @@ bool protocol_transaction_in_106::handle_receive_transaction(const code& ec, } submit(to_shared(chain::transaction_cptrs{ tx }), false, - BIND(handle_submit, _1, _2)); + BIND(handle_submit, _1, _2, gate())); return true; } // protected -void protocol_transaction_in_106::handle_submit(const code& ec, size_t) NOEXCEPT +void protocol_transaction_in_106::handle_submit(const code& ec, size_t, + const gate_t::ptr& gate) NOEXCEPT { - POST(do_handle_submit, ec); + POST(do_handle_submit, ec, gate); } // protected -void protocol_transaction_in_106::do_handle_submit(const code& ec) NOEXCEPT +void protocol_transaction_in_106::do_handle_submit(const code& ec, + const gate_t::ptr&) NOEXCEPT { BC_ASSERT(stranded()); diff --git a/src/protocols/protocol_transaction_in_70013.cpp b/src/protocols/protocol_transaction_in_70013.cpp index 7457e8cb..0dddc1f2 100644 --- a/src/protocols/protocol_transaction_in_70013.cpp +++ b/src/protocols/protocol_transaction_in_70013.cpp @@ -36,7 +36,8 @@ BC_PUSH_WARNING(NO_VALUE_OR_CONST_REF_SHARED_PTR) // bip133: the peer is sent our rate when current and the maximum otherwise, so // a tx below the rate, or any tx while suspended, is sent against instruction. -void protocol_transaction_in_70013::do_handle_submit(const code& ec) NOEXCEPT +void protocol_transaction_in_70013::do_handle_submit(const code& ec, + const gate_t::ptr& gate) NOEXCEPT { BC_ASSERT(stranded()); @@ -50,7 +51,7 @@ void protocol_transaction_in_70013::do_handle_submit(const code& ec) NOEXCEPT return; } - protocol_transaction_in_70001::do_handle_submit(ec); + protocol_transaction_in_70001::do_handle_submit(ec, gate); } BC_POP_WARNING() diff --git a/src/protocols/protocol_transaction_out_106.cpp b/src/protocols/protocol_transaction_out_106.cpp index a2b71837..370df746 100644 --- a/src/protocols/protocol_transaction_out_106.cpp +++ b/src/protocols/protocol_transaction_out_106.cpp @@ -44,7 +44,7 @@ void protocol_transaction_out_106::start() NOEXCEPT return; // Events subscription is asynchronous, events may be missed. - subscribe_chase(BIND(handle_chase, _1, _2, _3)); + subscribe_chase(BIND(handle_chase, _1, _2)); SUBSCRIBE_CHANNEL(get_data, handle_receive_get_data, _1, _2); protocol_peer::start(); @@ -62,20 +62,18 @@ void protocol_transaction_out_106::stopping(const code& ec) NOEXCEPT // handle events (transaction) // ---------------------------------------------------------------------------- -bool protocol_transaction_out_106::handle_chase(const code&, chase event_, +bool protocol_transaction_out_106::handle_chase(const code&, event_value value) NOEXCEPT { // Do not pass ec to stopped as it is not a call status. if (stopped()) return false; - switch (event_) + switch (to_chase(value)) { case chase::transaction: { - // value is organized tx pk. - BC_ASSERT(std::holds_alternative(value)); - POST(do_announce, std::get(value)); + POST(do_announce, to_payload(value).link); break; } default: @@ -133,9 +131,8 @@ bool protocol_transaction_out_106::handle_receive_get_data(const code& ec, if (stopped(ec)) return false; - // Post so the completion resubscribe runs outside the current notify(). - POST(send_transaction, error::success, zero, message); - return false; + send_transaction(error::success, zero, message, gate()); + return true; } // Outbound (tx). @@ -146,7 +143,8 @@ bool protocol_transaction_out_106::handle_receive_get_data(const code& ec, // using MSG_TX getdata messages." (derived protocol) void protocol_transaction_out_106::send_transaction(const code& ec, - size_t index, const get_data::cptr& message) NOEXCEPT + size_t index, const get_data::cptr& message, + const gate_t::ptr& gate) NOEXCEPT { BC_ASSERT(stranded()); @@ -189,18 +187,13 @@ void protocol_transaction_out_106::send_transaction(const code& ec, } // The report resumes this loop on completion, so it precedes the tx. - if (report_unservable(index, message)) + if (report_unservable(index, message, gate)) return; - // BUGBUG: registration race. if (index >= message->items.size()) - { - // Complete, resubscribe to transaction requests. - SUBSCRIBE_CHANNEL(get_data, handle_receive_get_data, _1, _2); return; - } - SEND(transaction{ ptr }, send_transaction, _1, add1(index), message); + SEND(transaction{ ptr }, send_transaction, _1, add1(index), message, gate); } // not_found is undefined below bip37, so the channel is stopped instead. @@ -218,7 +211,7 @@ bool protocol_transaction_out_106::handle_unservable( // There is nothing to report below bip37, the channel is stopped above. bool protocol_transaction_out_106::report_unservable(size_t, - const get_data::cptr&) NOEXCEPT + const get_data::cptr&, const gate_t::ptr&) NOEXCEPT { return false; } diff --git a/src/protocols/protocol_transaction_out_70001.cpp b/src/protocols/protocol_transaction_out_70001.cpp index dbe638ee..5a9a415b 100644 --- a/src/protocols/protocol_transaction_out_70001.cpp +++ b/src/protocols/protocol_transaction_out_70001.cpp @@ -52,7 +52,7 @@ bool protocol_transaction_out_70001::handle_unservable( // The items are answered and the send loop resumed, as with a transaction, so // nothing is produced until the prior write completes. bool protocol_transaction_out_70001::report_unservable(size_t index, - const get_data::cptr& message) NOEXCEPT + const get_data::cptr& message, const gate_t::ptr& gate) NOEXCEPT { BC_ASSERT(stranded()); @@ -62,7 +62,8 @@ bool protocol_transaction_out_70001::report_unservable(size_t index, auto items = std::move(unservable_); unservable_.clear(); - SEND(not_found{ std::move(items) }, send_transaction, _1, index, message); + SEND(not_found{ std::move(items) }, send_transaction, _1, index, + message, gate); return true; } diff --git a/src/protocols/protocol_transaction_out_70013.cpp b/src/protocols/protocol_transaction_out_70013.cpp index 4c45f0a9..859ea349 100644 --- a/src/protocols/protocol_transaction_out_70013.cpp +++ b/src/protocols/protocol_transaction_out_70013.cpp @@ -69,13 +69,13 @@ void protocol_transaction_out_70013::do_send_fee_filter() NOEXCEPT } bool protocol_transaction_out_70013::handle_chase(const code& ec, - chase event_, event_value value) NOEXCEPT + event_value value) NOEXCEPT { // Do not pass ec to stopped as it is not a call status. if (stopped()) return false; - switch (event_) + switch (to_chase(value)) { case chase::block: case chase::stale: @@ -89,7 +89,7 @@ bool protocol_transaction_out_70013::handle_chase(const code& ec, } } - return protocol_transaction_out_70001::handle_chase(ec, event_, value); + return protocol_transaction_out_70001::handle_chase(ec, value); } // Inbound (feefilter). diff --git a/src/sessions/session.cpp b/src/sessions/session.cpp index 9088b546..74c92c3f 100644 --- a/src/sessions/session.cpp +++ b/src/sessions/session.cpp @@ -77,16 +77,15 @@ void session::put_hashes(const map_ptr& map, // Events. // ---------------------------------------------------------------------------- -void session::notify(const code& ec, chase event_, - event_value value) const NOEXCEPT +void session::notify(const code& ec, event_value value) const NOEXCEPT { - node_.notify(ec, event_, value); + node_.notify(ec, value); } -void session::notify_one(object_key key, const code& ec, chase event_, +void session::notify_one(object_key key, const code& ec, event_value value) const NOEXCEPT { - node_.notify_one(key, ec, event_, value); + node_.notify_one(key, ec, value); } object_key session::subscribe_chase(event_notifier&& handler) NOEXCEPT diff --git a/src/settings.cpp b/src/settings.cpp index 5c0fe32e..f699509b 100644 --- a/src/settings.cpp +++ b/src/settings.cpp @@ -34,7 +34,6 @@ settings::settings() NOEXCEPT headers_first{ true }, memory_priority{ true }, thread_priority{ true }, - allow_overlapped{ true }, provide_blocks{ true }, require_blocks{ true }, provide_witness{ true }, diff --git a/test/settings.cpp b/test/settings.cpp index ab380d32..534b63bb 100644 --- a/test/settings.cpp +++ b/test/settings.cpp @@ -35,7 +35,6 @@ BOOST_AUTO_TEST_CASE(settings__node__default_context__expected) BOOST_REQUIRE_EQUAL(node.headers_first, true); BOOST_REQUIRE_EQUAL(node.memory_priority, true); BOOST_REQUIRE_EQUAL(node.thread_priority, true); - BOOST_REQUIRE_EQUAL(node.allow_overlapped, true); BOOST_REQUIRE_EQUAL(node.provide_blocks, true); BOOST_REQUIRE_EQUAL(node.require_blocks, true); BOOST_REQUIRE_EQUAL(node.provide_witness, true);