From dd7d200cc23185c99b0972459d710a4cd26a4c21 Mon Sep 17 00:00:00 2001 From: evoskuil Date: Fri, 23 Feb 2024 23:01:24 -0500 Subject: [PATCH 1/9] Comments. --- src/chasers/chaser_block.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/chasers/chaser_block.cpp b/src/chasers/chaser_block.cpp index e3a9c0a7..923baac2 100644 --- a/src/chasers/chaser_block.cpp +++ b/src/chasers/chaser_block.cpp @@ -157,6 +157,7 @@ void chaser_block::do_organize(const block::cptr& block_ptr, // Block validations are bypassed when under checkpoint/milestone. if (!checkpoint::is_under(coin.checkpoints, height)) { + // Requires no population. auto error = block.check(); if (error) { @@ -164,6 +165,7 @@ void chaser_block::do_organize(const block::cptr& block_ptr, return; } + // Requires no population. error = block.check(context); if (error) { From f248395d045e143ff4e01a00d79f16903596c3a1 Mon Sep 17 00:00:00 2001 From: evoskuil Date: Sat, 24 Feb 2024 01:48:55 -0500 Subject: [PATCH 2/9] Clear chaser trees on stop. --- src/chasers/chaser_block.cpp | 5 ++++- src/chasers/chaser_header.cpp | 5 ++++- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/src/chasers/chaser_block.cpp b/src/chasers/chaser_block.cpp index 923baac2..1e5e396a 100644 --- a/src/chasers/chaser_block.cpp +++ b/src/chasers/chaser_block.cpp @@ -84,9 +84,12 @@ void chaser_block::handle_event(const code& ec, chase event_, } // private -void chaser_block::do_handle_event(const code&, chase, link) NOEXCEPT +void chaser_block::do_handle_event(const code&, chase event_, link) NOEXCEPT { BC_ASSERT_MSG(stranded(), "chaser_block"); + + if (event_ == chase::stop) + tree_.clear(); } void chaser_block::organize(const block::cptr& block, diff --git a/src/chasers/chaser_header.cpp b/src/chasers/chaser_header.cpp index 46c2b52e..fcc50c61 100644 --- a/src/chasers/chaser_header.cpp +++ b/src/chasers/chaser_header.cpp @@ -83,9 +83,12 @@ void chaser_header::handle_event(const code& ec, chase event_, } // private -void chaser_header::do_handle_event(const code&, chase, link) NOEXCEPT +void chaser_header::do_handle_event(const code&, chase event_, link) NOEXCEPT { BC_ASSERT_MSG(stranded(), "chaser_header"); + + if (event_ == chase::stop) + tree_.clear(); } void chaser_header::organize(const header::cptr& header, From f841367cef85bdd84f7c39b4ea4d1fd210806611 Mon Sep 17 00:00:00 2001 From: evoskuil Date: Sat, 24 Feb 2024 01:49:18 -0500 Subject: [PATCH 3/9] Add bitcoin.checkpoint setting to parser. --- src/parser.cpp | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/parser.cpp b/src/parser.cpp index b020dcc9..91a9d11b 100644 --- a/src/parser.cpp +++ b/src/parser.cpp @@ -365,6 +365,12 @@ options_metadata parser::load_settings() THROWS value(&configured.bitcoin.genesis_block), "The genesis block, defaults to mainnet." ) + // TODO: checkpoint/checkpoints fail to parse. + ( + "bitcoin.checkpoint", + value(&configured.bitcoin.checkpoints), + "The blockchain checkpoints, defaults to the consensus set." + ) // [version properties excluded here] ( "bitcoin.bip34_activation_threshold", From 841cbc976f96aefe3288238c1be9025599551457 Mon Sep 17 00:00:00 2001 From: evoskuil Date: Sat, 24 Feb 2024 02:12:48 -0500 Subject: [PATCH 4/9] Reduce block in failure logging during stop. --- src/protocols/protocol_block_in.cpp | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/protocols/protocol_block_in.cpp b/src/protocols/protocol_block_in.cpp index 6c558850..4b38920e 100644 --- a/src/protocols/protocol_block_in.cpp +++ b/src/protocols/protocol_block_in.cpp @@ -190,12 +190,16 @@ void protocol_block_in::complete() NOEXCEPT void protocol_block_in::handle_organize(const code& ec, const chain::block::cptr& block_ptr) NOEXCEPT { - if (ec) + if (!ec) + return; + + if (ec != network::error::service_stopped) { LOGR("Error organizing block [" << encode_hash(block_ptr->hash()) << "] from [" << authority() << "] " << ec.message()); - stop(ec); } + + stop(ec); } // private From 13817f9e7004b9317a033d0cf57084ad350a6ae9 Mon Sep 17 00:00:00 2001 From: evoskuil Date: Sat, 24 Feb 2024 02:29:24 -0500 Subject: [PATCH 5/9] Update header/block progress logging. --- src/chasers/chaser_block.cpp | 2 ++ src/chasers/chaser_header.cpp | 6 ++++-- src/protocols/protocol_block_in.cpp | 4 ++-- src/protocols/protocol_header_in_31800.cpp | 4 ++-- 4 files changed, 10 insertions(+), 6 deletions(-) diff --git a/src/chasers/chaser_block.cpp b/src/chasers/chaser_block.cpp index 1e5e396a..1a74b6d4 100644 --- a/src/chasers/chaser_block.cpp +++ b/src/chasers/chaser_block.cpp @@ -302,6 +302,8 @@ void chaser_block::do_organize(const block::cptr& block_ptr, // Notify candidate reorganization with branch point. // ------------------------------------------------------------------------ + LOGN("Block [" << encode_hash(hash) << "] at (" << height << ")."); + notify(error::success, chase::block, { possible_narrow_cast(point) }); diff --git a/src/chasers/chaser_header.cpp b/src/chasers/chaser_header.cpp index fcc50c61..0fcde020 100644 --- a/src/chasers/chaser_header.cpp +++ b/src/chasers/chaser_header.cpp @@ -143,10 +143,10 @@ void chaser_header::do_organize(const header::cptr& header_ptr, // Rolling forward chain_state eliminates requery cost. state_.reset(new chain_state(*state_, header, coin)); const auto context = state_->context(); + const auto height = state_->height(); // Checkpoints are considered chain not block/header validation. - if (checkpoint::is_conflict(coin.checkpoints, hash, - state_->height())) + if (checkpoint::is_conflict(coin.checkpoints, hash, height)) { handler(network::error::protocol_violation); return; @@ -256,6 +256,8 @@ void chaser_header::do_organize(const header::cptr& header_ptr, // Notify candidate reorganization with branch point. // ------------------------------------------------------------------------ + LOGN("Header [" << encode_hash(hash) << "] at (" << height << ")."); + notify(error::success, chase::header, { possible_narrow_cast(point) }); diff --git a/src/protocols/protocol_block_in.cpp b/src/protocols/protocol_block_in.cpp index 4b38920e..12828c22 100644 --- a/src/protocols/protocol_block_in.cpp +++ b/src/protocols/protocol_block_in.cpp @@ -151,8 +151,8 @@ bool protocol_block_in::handle_receive_block(const code& ec, organize(block_ptr, BIND2(handle_organize, _1, block_ptr)); top_ = { block_ptr->hash(), add1(top_.height()) }; - LOGP("Block [" << encode_hash(top_.hash()) << "] at (" - << top_.height() << ") from [" << authority() << "]."); + ////LOGP("Block [" << encode_hash(top_.hash()) << "] at (" + //// << top_.height() << ") from [" << authority() << "]."); // Order is reversed, so next is at back. tracker->hashes.pop_back(); diff --git a/src/protocols/protocol_header_in_31800.cpp b/src/protocols/protocol_header_in_31800.cpp index 2046b4f0..b0464faf 100644 --- a/src/protocols/protocol_header_in_31800.cpp +++ b/src/protocols/protocol_header_in_31800.cpp @@ -90,8 +90,8 @@ bool protocol_header_in_31800::handle_receive_headers(const code& ec, organize(header_ptr, BIND2(handle_organize, _1, header_ptr)); top_ = { header_ptr->hash(), add1(top_.height()) }; - LOGP("Header [" << encode_hash(top_.hash()) << "] at (" - << top_.height() << ") from [" << authority() << "]."); + ////LOGP("Header [" << encode_hash(top_.hash()) << "] at (" + //// << top_.height() << ") from [" << authority() << "]."); } // Protocol presumes max_get_headers unless complete. From 85a839626225a3f206a54120e27cca4a478d7eec Mon Sep 17 00:00:00 2001 From: evoskuil Date: Sat, 24 Feb 2024 13:13:59 -0500 Subject: [PATCH 6/9] Update error codes. --- include/bitcoin/node/error.hpp | 5 ++--- src/error.cpp | 5 ++--- test/error.cpp | 15 +++------------ 3 files changed, 7 insertions(+), 18 deletions(-) diff --git a/include/bitcoin/node/error.hpp b/include/bitcoin/node/error.hpp index 5bea182c..b3d0ee16 100644 --- a/include/bitcoin/node/error.hpp +++ b/include/bitcoin/node/error.hpp @@ -50,9 +50,8 @@ enum error_t : uint8_t // blockchain orphan_block, - orphan_header, - insufficient_work, - duplicate_block + duplicate_block, + insufficient_work }; // No current need for error_code equivalence mapping. diff --git a/src/error.cpp b/src/error.cpp index b7898be3..6cc858ed 100644 --- a/src/error.cpp +++ b/src/error.cpp @@ -41,9 +41,8 @@ DEFINE_ERROR_T_MESSAGE_MAP(error) // blockchain { orphan_block, "orphan block" }, - { orphan_header, "orphan header" }, - { insufficient_work, "insufficient work" }, - { duplicate_block, "duplicate block" } + { duplicate_block, "duplicate block" }, + { insufficient_work, "insufficient work" } }; DEFINE_ERROR_T_CATEGORY(error, "node", "node code") diff --git a/test/error.cpp b/test/error.cpp index f4772ebe..c152d227 100644 --- a/test/error.cpp +++ b/test/error.cpp @@ -95,13 +95,13 @@ BOOST_AUTO_TEST_CASE(error_t__code__orphan_block__true_exected_message) BOOST_REQUIRE_EQUAL(ec.message(), "orphan block"); } -BOOST_AUTO_TEST_CASE(error_t__code__orphan_header__true_exected_message) +BOOST_AUTO_TEST_CASE(error_t__code__duplicate_block__true_exected_message) { - constexpr auto value = error::orphan_header; + constexpr auto value = error::duplicate_block; const auto ec = code(value); BOOST_REQUIRE(ec); BOOST_REQUIRE(ec == value); - BOOST_REQUIRE_EQUAL(ec.message(), "orphan header"); + BOOST_REQUIRE_EQUAL(ec.message(), "duplicate block"); } BOOST_AUTO_TEST_CASE(error_t__code__insufficient_work__true_exected_message) @@ -113,13 +113,4 @@ BOOST_AUTO_TEST_CASE(error_t__code__insufficient_work__true_exected_message) BOOST_REQUIRE_EQUAL(ec.message(), "insufficient work"); } -BOOST_AUTO_TEST_CASE(error_t__code__duplicate_block__true_exected_message) -{ - constexpr auto value = error::duplicate_block; - const auto ec = code(value); - BOOST_REQUIRE(ec); - BOOST_REQUIRE(ec == value); - BOOST_REQUIRE_EQUAL(ec.message(), "duplicate block"); -} - BOOST_AUTO_TEST_SUITE_END() From 8e530f7e74f5f85649784c5c1acb3a263cf9aa5b Mon Sep 17 00:00:00 2001 From: evoskuil Date: Sat, 24 Feb 2024 13:29:33 -0500 Subject: [PATCH 7/9] Refine block/header first logging. --- include/bitcoin/node/chasers/chaser_block.hpp | 13 +---- .../bitcoin/node/chasers/chaser_header.hpp | 7 +-- .../node/protocols/protocol_block_in.hpp | 2 +- .../protocols/protocol_block_in_31800.hpp | 2 +- .../protocols/protocol_header_in_31800.hpp | 2 +- src/chasers/chaser_block.cpp | 49 ++----------------- src/chasers/chaser_header.cpp | 12 ++--- src/protocols/protocol_block_in.cpp | 22 ++++++--- src/protocols/protocol_block_in_31800.cpp | 30 +++++++++--- src/protocols/protocol_header_in_31800.cpp | 32 ++++++++---- 10 files changed, 78 insertions(+), 93 deletions(-) diff --git a/include/bitcoin/node/chasers/chaser_block.hpp b/include/bitcoin/node/chasers/chaser_block.hpp index 6e298de6..e783826b 100644 --- a/include/bitcoin/node/chasers/chaser_block.hpp +++ b/include/bitcoin/node/chasers/chaser_block.hpp @@ -75,10 +75,6 @@ class BCN_API chaser_block virtual bool get_is_strong(bool& strong, const uint256_t& work, size_t point) const NOEXCEPT; - /// Header timestamp is within configured span from current time. - virtual bool is_current(const system::chain::header& header, - size_t height) const NOEXCEPT; - /// Save block to tree with validation context. virtual void save(const system::chain::block::cptr& block, const system::chain::context& context) NOEXCEPT; @@ -98,19 +94,12 @@ class BCN_API chaser_block virtual void do_organize(const system::chain::block::cptr& block, const network::result_handler& handler) NOEXCEPT; - /// Properties. - /// Given non-current blocks cached in memory, should always be zero/false. - virtual const network::wall_clock::duration& currency_window() const NOEXCEPT; - virtual bool use_currency_window() const NOEXCEPT; - private: void set_prevout(const system::chain::input& input) const NOEXCEPT; void do_handle_event(const code& ec, chase event_, link value) NOEXCEPT; - // These are thread safe. + // This is thread safe. const system::chain::checkpoints& checkpoints_; - const network::wall_clock::duration currency_window_; - const bool use_currency_window_; }; } // namespace node diff --git a/include/bitcoin/node/chasers/chaser_header.hpp b/include/bitcoin/node/chasers/chaser_header.hpp index ea5fd4f9..4ba5c73b 100644 --- a/include/bitcoin/node/chasers/chaser_header.hpp +++ b/include/bitcoin/node/chasers/chaser_header.hpp @@ -61,7 +61,7 @@ class BCN_API chaser_header system::chain::chain_state::ptr state_{}; std::unordered_map tree_{}; - /// Handlers. + /// Handle chaser events. virtual void handle_event(const code& ec, chase event_, link value) NOEXCEPT; @@ -76,7 +76,8 @@ class BCN_API chaser_header virtual bool get_is_strong(bool& strong, const uint256_t& work, size_t point) const NOEXCEPT; - /// Header timestamp is within configured span from current time. + /// Header timestamp is within configured span from current time, + /// or current header is a checkpoint or milestone. virtual bool is_current(const system::chain::header& header, size_t height) const NOEXCEPT; @@ -96,7 +97,7 @@ class BCN_API chaser_header virtual void do_organize(const system::chain::header::cptr& header, const network::result_handler& handler) NOEXCEPT; - /// Properties. + /// A strong header branch is committed to store when current. virtual const network::wall_clock::duration& currency_window() const NOEXCEPT; virtual bool use_currency_window() const NOEXCEPT; diff --git a/include/bitcoin/node/protocols/protocol_block_in.hpp b/include/bitcoin/node/protocols/protocol_block_in.hpp index 8e66f4f5..df8f2eb0 100644 --- a/include/bitcoin/node/protocols/protocol_block_in.hpp +++ b/include/bitcoin/node/protocols/protocol_block_in.hpp @@ -72,7 +72,7 @@ class BCN_API protocol_block_in virtual void complete() NOEXCEPT; /// Handle organize result. - virtual void handle_organize(const code& ec, + virtual void handle_organize(const code& ec, size_t height, const system::chain::block::cptr& block_ptr) NOEXCEPT; private: diff --git a/include/bitcoin/node/protocols/protocol_block_in_31800.hpp b/include/bitcoin/node/protocols/protocol_block_in_31800.hpp index b49e2213..bd30ca75 100644 --- a/include/bitcoin/node/protocols/protocol_block_in_31800.hpp +++ b/include/bitcoin/node/protocols/protocol_block_in_31800.hpp @@ -84,7 +84,7 @@ class BCN_API protocol_block_in_31800 virtual void complete() NOEXCEPT; /// Handle organize result. - virtual void handle_organize(const code& ec, + virtual void handle_organize(const code& ec, size_t height, const system::chain::block::cptr& block_ptr) NOEXCEPT; private: diff --git a/include/bitcoin/node/protocols/protocol_header_in_31800.hpp b/include/bitcoin/node/protocols/protocol_header_in_31800.hpp index 2933b887..cfed9fa1 100644 --- a/include/bitcoin/node/protocols/protocol_header_in_31800.hpp +++ b/include/bitcoin/node/protocols/protocol_header_in_31800.hpp @@ -53,7 +53,7 @@ class BCN_API protocol_header_in_31800 virtual void complete() NOEXCEPT; /// Handle organize result. - virtual void handle_organize(const code& ec, + virtual void handle_organize(const code& ec, size_t height, const system::chain::header::cptr& header_ptr) NOEXCEPT; private: diff --git a/src/chasers/chaser_block.cpp b/src/chasers/chaser_block.cpp index 1a74b6d4..36b1b4d8 100644 --- a/src/chasers/chaser_block.cpp +++ b/src/chasers/chaser_block.cpp @@ -39,9 +39,7 @@ BC_PUSH_WARNING(NO_THROW_IN_NOEXCEPT) chaser_block::chaser_block(full_node& node) NOEXCEPT : chaser(node), - checkpoints_(node.config().bitcoin.checkpoints), - currency_window_(node.node_settings().currency_window()), - use_currency_window_(to_bool(node.node_settings().currency_window_minutes)) + checkpoints_(node.config().bitcoin.checkpoints) { } @@ -49,19 +47,6 @@ chaser_block::~chaser_block() NOEXCEPT { } -// protected -const network::wall_clock::duration& -chaser_block::currency_window() const NOEXCEPT -{ - return currency_window_; -} - -// protected -bool chaser_block::use_currency_window() const NOEXCEPT -{ - return use_currency_window_; -} - // protected code chaser_block::start() NOEXCEPT { @@ -128,7 +113,7 @@ void chaser_block::do_organize(const block::cptr& block_ptr, // Block (header and txs) already exists. if (tree_.contains(hash) || query.is_block(hash)) { - handler(error::success); + handler(error::duplicate_block); return; } @@ -136,7 +121,6 @@ void chaser_block::do_organize(const block::cptr& block_ptr, // Results from running headers-first and then restarting to blocks-first. if (!tree_.contains(previous) && !query.is_block(previous)) { - LOGR("Orphan header [" << encode_hash(hash) << "]."); handler(error::orphan_block); return; } @@ -153,7 +137,7 @@ void chaser_block::do_organize(const block::cptr& block_ptr, // Checkpoints are considered chain not block/header validation. if (checkpoint::is_conflict(coin.checkpoints, hash, height)) { - handler(network::error::protocol_violation); + handler(system::error::checkpoint_conflict); return; }; @@ -209,14 +193,7 @@ void chaser_block::do_organize(const block::cptr& block_ptr, // Compute relative work. // ------------------------------------------------------------------------ - - // Block is new top of stale branch (strength not computed). - if (!is_current(header, context.height)) - { - save(block_ptr, context); - handler(error::success); - return; - } + // Currency is not used for blocks due to excessive cache requirement. size_t point{}; uint256_t work{}; @@ -302,30 +279,12 @@ void chaser_block::do_organize(const block::cptr& block_ptr, // Notify candidate reorganization with branch point. // ------------------------------------------------------------------------ - LOGN("Block [" << encode_hash(hash) << "] at (" << height << ")."); - notify(error::success, chase::block, { possible_narrow_cast(point) }); handler(error::success); } -bool chaser_block::is_current(const header& header, - size_t height) const NOEXCEPT -{ - if (!use_currency_window()) - return true; - - // Checkpoints are already validated. Current if at a checkpoint height. - if (checkpoint::is_at(checkpoints_, height)) - return true; - - // en.wikipedia.org/wiki/Time_formatting_and_storage_bugs#Year_2106 - const auto time = wall_clock::from_time_t(header.timestamp()); - const auto current = wall_clock::now() - currency_window(); - return time >= current; -} - bool chaser_block::get_branch_work(uint256_t& work, size_t& point, hashes& tree_branch, header_links& store_branch, const header& header) const NOEXCEPT diff --git a/src/chasers/chaser_header.cpp b/src/chasers/chaser_header.cpp index 0fcde020..00b4aeaa 100644 --- a/src/chasers/chaser_header.cpp +++ b/src/chasers/chaser_header.cpp @@ -126,14 +126,14 @@ void chaser_header::do_organize(const header::cptr& header_ptr, // Header already exists. if (tree_.contains(hash) || query.is_header(hash)) { - handler(error::success); + handler(error::duplicate_block); return; } // Peer processing should have precluded orphan submission. if (!tree_.contains(previous) && !query.is_header(previous)) { - handler(error::orphan_header); + handler(error::orphan_block); return; } @@ -148,7 +148,7 @@ void chaser_header::do_organize(const header::cptr& header_ptr, // Checkpoints are considered chain not block/header validation. if (checkpoint::is_conflict(coin.checkpoints, hash, height)) { - handler(network::error::protocol_violation); + handler(system::error::checkpoint_conflict); return; } @@ -158,14 +158,14 @@ void chaser_header::do_organize(const header::cptr& header_ptr, coin.proof_of_work_limit, coin.scrypt_proof_of_work); if (error) { - handler(network::error::protocol_violation); + handler(error); return; } error = header.accept(context); if (error) { - handler(network::error::protocol_violation); + handler(error); } // Compute relative work. @@ -256,8 +256,6 @@ void chaser_header::do_organize(const header::cptr& header_ptr, // Notify candidate reorganization with branch point. // ------------------------------------------------------------------------ - LOGN("Header [" << encode_hash(hash) << "] at (" << height << ")."); - notify(error::success, chase::header, { possible_narrow_cast(point) }); diff --git a/src/protocols/protocol_block_in.cpp b/src/protocols/protocol_block_in.cpp index 12828c22..161b50ec 100644 --- a/src/protocols/protocol_block_in.cpp +++ b/src/protocols/protocol_block_in.cpp @@ -148,11 +148,14 @@ bool protocol_block_in::handle_receive_block(const code& ec, return false; } - organize(block_ptr, BIND2(handle_organize, _1, block_ptr)); + // Add block at next height. + const auto height = add1(top_.height()); - top_ = { block_ptr->hash(), add1(top_.height()) }; - ////LOGP("Block [" << encode_hash(top_.hash()) << "] at (" - //// << top_.height() << ") from [" << authority() << "]."); + // Asynchronous organization serves all channels. + organize(block_ptr, BIND3(handle_organize, _1, height, block_ptr)); + + // Set the new top and continue. Organize error will stop the channel. + top_ = { block_ptr->hash(), height }; // Order is reversed, so next is at back. tracker->hashes.pop_back(); @@ -187,16 +190,23 @@ void protocol_block_in::complete() NOEXCEPT << top_.height() << ")."); } -void protocol_block_in::handle_organize(const code& ec, +void protocol_block_in::handle_organize(const code& ec, size_t height, const chain::block::cptr& block_ptr) NOEXCEPT { if (!ec) + { + LOGP("Block [" << encode_hash(block_ptr->hash()) + << "] at (" << height << ") from [" << authority() << "] " + << ec.message()); return; + } + // This may be either a remote error or store corruption. if (ec != network::error::service_stopped) { LOGR("Error organizing block [" << encode_hash(block_ptr->hash()) - << "] from [" << authority() << "] " << ec.message()); + << "] at (" << height << ") from [" << authority() << "] " + << ec.message()); } stop(ec); diff --git a/src/protocols/protocol_block_in_31800.cpp b/src/protocols/protocol_block_in_31800.cpp index 191d510f..cf9373f4 100644 --- a/src/protocols/protocol_block_in_31800.cpp +++ b/src/protocols/protocol_block_in_31800.cpp @@ -216,11 +216,14 @@ bool protocol_block_in_31800::handle_receive_block(const code& ec, return false; } - organize(block_ptr, BIND2(handle_organize, _1, block_ptr)); + // Add block at next height. + const auto height = add1(top_.height()); - top_ = { block_ptr->hash(), add1(top_.height()) }; - LOGP("Block [" << encode_hash(top_.hash()) << "] at (" - << top_.height() << ") from [" << authority() << "]."); + // Asynchronous organization serves all channels. + organize(block_ptr, BIND3(handle_organize, _1, height, block_ptr)); + + // Set the new top and continue. Organize error will stop the channel. + top_ = { block_ptr->hash(), height }; ////// Accumulate byte count. ////bytes_ += message->cached_size; @@ -258,15 +261,26 @@ void protocol_block_in_31800::complete() NOEXCEPT << top_.height() << ")."); } -void protocol_block_in_31800::handle_organize(const code& ec, +void protocol_block_in_31800::handle_organize(const code& ec, size_t height, const chain::block::cptr& block_ptr) NOEXCEPT { - if (ec) + if (!ec) + { + LOGP("Block [" << encode_hash(block_ptr->hash()) + << "] at (" << height << ") from [" << authority() << "] " + << ec.message()); + return; + } + + // This may be either a remote error or store corruption. + if (ec != network::error::service_stopped) { LOGR("Error organizing block [" << encode_hash(block_ptr->hash()) - << "] from [" << authority() << "] " << ec.message()); - stop(ec); + << "] at (" << height << ") from [" << authority() << "] " + << ec.message()); } + + stop(ec); } diff --git a/src/protocols/protocol_header_in_31800.cpp b/src/protocols/protocol_header_in_31800.cpp index b0464faf..fd42cbcc 100644 --- a/src/protocols/protocol_header_in_31800.cpp +++ b/src/protocols/protocol_header_in_31800.cpp @@ -87,11 +87,14 @@ bool protocol_header_in_31800::handle_receive_headers(const code& ec, return false; } - organize(header_ptr, BIND2(handle_organize, _1, header_ptr)); + // Add header at next height. + const auto height = add1(top_.height()); - top_ = { header_ptr->hash(), add1(top_.height()) }; - ////LOGP("Header [" << encode_hash(top_.hash()) << "] at (" - //// << top_.height() << ") from [" << authority() << "]."); + // Asynchronous organization serves all channels. + organize(header_ptr, BIND3(handle_organize, _1, height, header_ptr)); + + // Set the new top and continue. Organize error will stop the channel. + top_ = { header_ptr->hash(), height }; } // Protocol presumes max_get_headers unless complete. @@ -117,15 +120,26 @@ void protocol_header_in_31800::complete() NOEXCEPT << top_.height() << ")."); } -void protocol_header_in_31800::handle_organize(const code& ec, +void protocol_header_in_31800::handle_organize(const code& ec, size_t height, const chain::header::cptr& header_ptr) NOEXCEPT { - if (ec) + if (!ec) + { + LOGP("Header [" << encode_hash(header_ptr->hash()) + << "] at (" << height << ") from [" << authority() << "] " + << ec.message()); + return; + } + + // This may be either a remote error or store corruption. + if (ec != network::error::service_stopped) { - LOGR("Error organizing header [" << encode_hash(header_ptr ->hash()) - << "] from [" << authority() << "] " << ec.message()); - stop(ec); + LOGR("Error organizing header [" << encode_hash(header_ptr->hash()) + << "] at (" << height << ") from [" << authority() << "] " + << ec.message()); } + + stop(ec); } // private From ac0ebd8909ff48cd7c3cf65a0c860d99823f013d Mon Sep 17 00:00:00 2001 From: evoskuil Date: Sat, 24 Feb 2024 13:29:49 -0500 Subject: [PATCH 8/9] Restore version-based protocols selection. --- include/bitcoin/node/sessions/attach.hpp | 32 ++++++++++++------------ src/sessions/session_outbound.cpp | 28 ++++++++++----------- 2 files changed, 30 insertions(+), 30 deletions(-) diff --git a/include/bitcoin/node/sessions/attach.hpp b/include/bitcoin/node/sessions/attach.hpp index caa25833..d1c23774 100644 --- a/include/bitcoin/node/sessions/attach.hpp +++ b/include/bitcoin/node/sessions/attach.hpp @@ -58,28 +58,28 @@ class attach const network::channel::ptr& channel) NOEXCEPT override { auto& self = *this; - ////const auto version = channel->negotiated_version(); + const auto version = channel->negotiated_version(); ////constexpr auto performance = false; // Attach appropriate alert, reject, ping, and/or address protocols. Session::attach_protocols(channel); // Very hard to find < 31800 peer to connect with. - ////if (version >= network::messages::level::bip130) - ////{ - //// // Headers-first synchronization (parallel block download). - //// channel->attach(self)->start(); - //// channel->attach(self)->start(); - //// ////channel->attach(self, performance)->start(); - ////} - ////else if (version >= network::messages::level::headers_protocol) - ////{ - //// // Headers-first synchronization (parallel block download). - //// channel->attach(self)->start(); - //// channel->attach(self)->start(); - //// ////channel->attach(self, performance)->start(); - ////} - ////else + if (version >= network::messages::level::bip130) + { + // Headers-first synchronization (parallel block download). + channel->attach(self)->start(); + channel->attach(self)->start(); + ////channel->attach(self, performance)->start(); + } + else if (version >= network::messages::level::headers_protocol) + { + // Headers-first synchronization (parallel block download). + channel->attach(self)->start(); + channel->attach(self)->start(); + ////channel->attach(self, performance)->start(); + } + else { // Blocks-first synchronization (no header protocol). channel->attach(self)->start(); diff --git a/src/sessions/session_outbound.cpp b/src/sessions/session_outbound.cpp index 6cab25b2..8b27a6c1 100644 --- a/src/sessions/session_outbound.cpp +++ b/src/sessions/session_outbound.cpp @@ -96,26 +96,26 @@ void session_outbound::attach_protocols( const network::channel::ptr& channel) NOEXCEPT { auto& self = *this; - ////const auto version = channel->negotiated_version(); + const auto version = channel->negotiated_version(); ////constexpr auto performance = true; // Attach appropriate alert, reject, ping, and/or address protocols. network::session_outbound::attach_protocols(channel); // Very hard to find < 31800 peer to connect with. - ////if (version >= network::messages::level::bip130) - ////{ - //// channel->attach(self)->start(); - //// channel->attach(self)->start(); - //// ////channel->attach(self, performance)->start(); - ////} - ////else if (version >= network::messages::level::headers_protocol) - ////{ - //// channel->attach(self)->start(); - //// channel->attach(self)->start(); - //// ////channel->attach(self, performance)->start(); - ////} - ////else + if (version >= network::messages::level::bip130) + { + channel->attach(self)->start(); + channel->attach(self)->start(); + ////channel->attach(self, performance)->start(); + } + else if (version >= network::messages::level::headers_protocol) + { + channel->attach(self)->start(); + channel->attach(self)->start(); + ////channel->attach(self, performance)->start(); + } + else { // Blocks-first synchronization (no header protocol). channel->attach(self)->start(); From dcc34be86fd0ecba26519eeeb8907bbd1446e387 Mon Sep 17 00:00:00 2001 From: evoskuil Date: Sat, 24 Feb 2024 13:57:59 -0500 Subject: [PATCH 9/9] Refine block/header first logging. --- src/protocols/protocol_block_in.cpp | 16 ++++++++-------- src/protocols/protocol_block_in_31800.cpp | 16 ++++++++-------- src/protocols/protocol_header_in_31800.cpp | 17 +++++++++-------- 3 files changed, 25 insertions(+), 24 deletions(-) diff --git a/src/protocols/protocol_block_in.cpp b/src/protocols/protocol_block_in.cpp index 161b50ec..f95a375c 100644 --- a/src/protocols/protocol_block_in.cpp +++ b/src/protocols/protocol_block_in.cpp @@ -193,7 +193,10 @@ void protocol_block_in::complete() NOEXCEPT void protocol_block_in::handle_organize(const code& ec, size_t height, const chain::block::cptr& block_ptr) NOEXCEPT { - if (!ec) + if (ec == network::error::service_stopped) + return; + + if (!ec || ec == error::duplicate_block) { LOGP("Block [" << encode_hash(block_ptr->hash()) << "] at (" << height << ") from [" << authority() << "] " @@ -201,13 +204,10 @@ void protocol_block_in::handle_organize(const code& ec, size_t height, return; } - // This may be either a remote error or store corruption. - if (ec != network::error::service_stopped) - { - LOGR("Error organizing block [" << encode_hash(block_ptr->hash()) - << "] at (" << height << ") from [" << authority() << "] " - << ec.message()); - } + // Assuming no store failure this is a consensus failure. + LOGR("Block [" << encode_hash(block_ptr->hash()) + << "] at (" << height << ") from [" << authority() << "] " + << ec.message()); stop(ec); } diff --git a/src/protocols/protocol_block_in_31800.cpp b/src/protocols/protocol_block_in_31800.cpp index cf9373f4..830d305e 100644 --- a/src/protocols/protocol_block_in_31800.cpp +++ b/src/protocols/protocol_block_in_31800.cpp @@ -264,7 +264,10 @@ void protocol_block_in_31800::complete() NOEXCEPT void protocol_block_in_31800::handle_organize(const code& ec, size_t height, const chain::block::cptr& block_ptr) NOEXCEPT { - if (!ec) + if (ec == network::error::service_stopped) + return; + + if (!ec || ec == error::duplicate_block) { LOGP("Block [" << encode_hash(block_ptr->hash()) << "] at (" << height << ") from [" << authority() << "] " @@ -272,13 +275,10 @@ void protocol_block_in_31800::handle_organize(const code& ec, size_t height, return; } - // This may be either a remote error or store corruption. - if (ec != network::error::service_stopped) - { - LOGR("Error organizing block [" << encode_hash(block_ptr->hash()) - << "] at (" << height << ") from [" << authority() << "] " - << ec.message()); - } + // Assuming no store failure this is a consensus failure. + LOGR("Block [" << encode_hash(block_ptr->hash()) + << "] at (" << height << ") from [" << authority() << "] " + << ec.message()); stop(ec); } diff --git a/src/protocols/protocol_header_in_31800.cpp b/src/protocols/protocol_header_in_31800.cpp index fd42cbcc..11ad9a41 100644 --- a/src/protocols/protocol_header_in_31800.cpp +++ b/src/protocols/protocol_header_in_31800.cpp @@ -23,6 +23,7 @@ #include #include #include +#include namespace libbitcoin { namespace node { @@ -123,7 +124,10 @@ void protocol_header_in_31800::complete() NOEXCEPT void protocol_header_in_31800::handle_organize(const code& ec, size_t height, const chain::header::cptr& header_ptr) NOEXCEPT { - if (!ec) + if (ec == network::error::service_stopped) + return; + + if (!ec || ec == error::duplicate_block) { LOGP("Header [" << encode_hash(header_ptr->hash()) << "] at (" << height << ") from [" << authority() << "] " @@ -131,13 +135,10 @@ void protocol_header_in_31800::handle_organize(const code& ec, size_t height, return; } - // This may be either a remote error or store corruption. - if (ec != network::error::service_stopped) - { - LOGR("Error organizing header [" << encode_hash(header_ptr->hash()) - << "] at (" << height << ") from [" << authority() << "] " - << ec.message()); - } + // Assuming no store failure this is a consensus failure. + LOGR("Header [" << encode_hash(header_ptr->hash()) + << "] at (" << height << ") from [" << authority() << "] " + << ec.message()); stop(ec); }