From 477f3aee569ecbc992eff4bf18393a62098e9d0d Mon Sep 17 00:00:00 2001 From: Kevin Heifner Date: Tue, 23 Apr 2024 12:45:46 -0500 Subject: [PATCH 1/9] GH-8 Add similar helper functions as block_header for extensions --- libraries/chain/block.cpp | 34 +++++++++++++++++-- libraries/chain/include/eosio/chain/block.hpp | 6 ++++ 2 files changed, 38 insertions(+), 2 deletions(-) diff --git a/libraries/chain/block.cpp b/libraries/chain/block.cpp index 14af857a88..67e228ef15 100644 --- a/libraries/chain/block.cpp +++ b/libraries/chain/block.cpp @@ -1,6 +1,6 @@ #include -namespace eosio { namespace chain { +namespace eosio::chain { void additional_block_signatures_extension::reflector_init() { static_assert( fc::raw::has_feature_reflector_init_on_unpacked_reflected_types, "additional_block_signatures_extension expects FC to support reflector_init" ); @@ -63,7 +63,37 @@ namespace eosio { namespace chain { } return results; + } + + std::optional signed_block::extract_extension(uint16_t extension_id)const { + using decompose_t = block_extension_types::decompose_t; + + for( size_t i = 0; i < block_extensions.size(); ++i ) { + const auto& e = block_extensions[i]; + auto id = e.first; + + if (id != extension_id) + continue; + + std::optional ext; + ext.emplace(); + + auto match = decompose_t::extract( id, e.second, *ext ); + EOS_ASSERT( match, invalid_block_extension, + "Block extension with id type ${id} is not supported", + ("id", id) + ); + + return ext; + } + + return {}; + } + bool signed_block::contains_extension(uint16_t extension_id)const { + return std::any_of(block_extensions.cbegin(), block_extensions.cend(), [&](const auto& p) { + return p.first == extension_id; + }); } -} } /// namespace eosio::chain +} /// namespace eosio::chain diff --git a/libraries/chain/include/eosio/chain/block.hpp b/libraries/chain/include/eosio/chain/block.hpp index 29cbd63245..8183a144da 100644 --- a/libraries/chain/include/eosio/chain/block.hpp +++ b/libraries/chain/include/eosio/chain/block.hpp @@ -101,6 +101,12 @@ namespace eosio { namespace chain { extensions_type block_extensions; flat_multimap validate_and_extract_extensions()const; + std::optional extract_extension(uint16_t extension_id)const; + template Ext extract_extension()const { + assert(contains_extension(Ext::extension_id())); + return std::get(*extract_extension(Ext::extension_id())); + } + bool contains_extension(uint16_t extension_id)const; }; using signed_block_ptr = std::shared_ptr; From 2a188893bbff32598c77baca59eb7acc7fdbdba4 Mon Sep 17 00:00:00 2001 From: Kevin Heifner Date: Tue, 23 Apr 2024 12:47:09 -0500 Subject: [PATCH 2/9] GH-8 Add accessor for head active finalizer policy --- libraries/chain/controller.cpp | 8 +++++++- libraries/chain/include/eosio/chain/controller.hpp | 3 +++ 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/libraries/chain/controller.cpp b/libraries/chain/controller.cpp index 3a853a9126..7830d5ab5d 100644 --- a/libraries/chain/controller.cpp +++ b/libraries/chain/controller.cpp @@ -4052,7 +4052,7 @@ struct controller_impl { if( switch_fork ) { auto head_fork_comp_str = apply(chain_head, [](auto& head) -> std::string { return log_fork_comparison(*head); }); ilog("switching forks from ${chid} (block number ${chn}) ${c} to ${nhid} (block number ${nhn}) ${n}", - ("chid", chain_head.id())("chn}", chain_head.block_num())("nhid", new_head->id())("nhn", new_head->block_num()) + ("chid", chain_head.id())("chn", chain_head.block_num())("nhid", new_head->id())("nhn", new_head->block_num()) ("c", head_fork_comp_str)("n", log_fork_comparison(*new_head))); // not possible to log transaction specific info when switching forks @@ -5311,6 +5311,12 @@ const producer_authority_schedule* controller::next_producers()const { return my->pending->next_producers(); } +finalizer_policy_ptr controller::head_active_finalizer_policy()const { + return apply_s(my->chain_head, [](const auto& head) { + return head->active_finalizer_policy; + }); +} + bool controller::light_validation_allowed() const { return my->light_validation_allowed(); } diff --git a/libraries/chain/include/eosio/chain/controller.hpp b/libraries/chain/include/eosio/chain/controller.hpp index 322191821c..421f90b9bc 100644 --- a/libraries/chain/include/eosio/chain/controller.hpp +++ b/libraries/chain/include/eosio/chain/controller.hpp @@ -265,6 +265,9 @@ namespace eosio::chain { // post-instant-finality this always returns nullptr const producer_authority_schedule* pending_producers_legacy()const; + // returns nullptr pre-savanna + finalizer_policy_ptr head_active_finalizer_policy()const; + void set_if_irreversible_block_id(const block_id_type& id); uint32_t if_irreversible_block_num() const; From 077248bf84adda1cf5cea8e8220cac61c61be05a Mon Sep 17 00:00:00 2001 From: Kevin Heifner Date: Tue, 23 Apr 2024 12:48:15 -0500 Subject: [PATCH 3/9] GH-8 Info log missing votes in block and warn log missing vote for configured finalizer --- .../eosio/producer_plugin/producer_plugin.hpp | 8 ++ plugins/producer_plugin/producer_plugin.cpp | 90 ++++++++++++++++++- plugins/prometheus_plugin/metrics.hpp | 33 +++++++ 3 files changed, 128 insertions(+), 3 deletions(-) diff --git a/plugins/producer_plugin/include/eosio/producer_plugin/producer_plugin.hpp b/plugins/producer_plugin/include/eosio/producer_plugin/producer_plugin.hpp index 495d1b91a6..d32df33bea 100644 --- a/plugins/producer_plugin/include/eosio/producer_plugin/producer_plugin.hpp +++ b/plugins/producer_plugin/include/eosio/producer_plugin/producer_plugin.hpp @@ -145,6 +145,13 @@ class producer_plugin : public appbase::plugin { static void set_test_mode(bool m) { test_mode_ = m; } + struct vote_block_metrics { + uint32_t block_num = 0; + std::vector strong_votes; + std::vector weak_votes; + std::vector no_votes; + }; + struct speculative_block_metrics { account_name block_producer{}; uint32_t block_num = 0; @@ -188,6 +195,7 @@ class producer_plugin : public appbase::plugin { void register_update_produced_block_metrics(std::function&&); void register_update_speculative_block_metrics(std::function&&); void register_update_incoming_block_metrics(std::function&&); + void register_update_vote_block_metrics(std::function&&); inline static bool test_mode_{false}; // to be moved into appbase (application_base) diff --git a/plugins/producer_plugin/producer_plugin.cpp b/plugins/producer_plugin/producer_plugin.cpp index b572c2e7ff..a4f16f6ebb 100644 --- a/plugins/producer_plugin/producer_plugin.cpp +++ b/plugins/producer_plugin/producer_plugin.cpp @@ -494,6 +494,7 @@ class producer_plugin_impl : public std::enable_shared_from_this _signature_providers; chain::bls_pub_priv_key_map_t _finalizer_keys; // public, private + std::set _finalizers; std::set _producers; boost::asio::deadline_timer _timer; block_timing_util::producer_watermarks _producer_watermarks; @@ -550,6 +551,7 @@ class producer_plugin_impl : public std::enable_shared_from_this _update_produced_block_metrics; std::function _update_speculative_block_metrics; std::function _update_incoming_block_metrics; + std::function _update_vote_block_metrics; // ro for read-only struct ro_trx_t { @@ -626,7 +628,74 @@ class producer_plugin_impl : public std::enable_shared_from_this not_voted; + + auto check_weak = [](const auto& weak_votes, size_t i) { + return weak_votes && (*weak_votes)[i]; + }; + + if (qc._strong_votes) { + const auto& votes = *qc._strong_votes; + auto& finalizers = active_finalizer_policy->finalizers; + assert(votes.size() == finalizers.size()); + for (size_t i = 0; i < votes.size(); ++i) { + if (!votes[i] && !check_weak(qc._weak_votes, i)) { + not_voted.push_back(finalizers[i].description); + if (_finalizers.contains(finalizers[i].public_key)) { + fc_wlog(vote_logger, "Block ${n}:${id} has no votes from our finalizer: ${v}", + ("n", block_num)("id", id.str().substr(8,16))("v", finalizers[i].description)); + } + } + } + } + if (!not_voted.empty()) { + fc_ilog(vote_logger, "Block ${n}:${id} has no votes for: ${v}", + ("n", block_num)("id", id.str().substr(8,16))("v", not_voted)); + } + } + } + + void update_vote_block_metrics(block_num_type block_num, + const finalizer_policy_ptr& active_finalizer_policy, + const valid_quorum_certificate& qc ) { + if (_update_vote_block_metrics) { + producer_plugin::vote_block_metrics m; + m.block_num = block_num; + auto add_votes = [&](const auto& votes, std::vector& desc, std::set& not_voted) { + assert(votes.size() == active_finalizer_policy->finalizers.size()); + for (size_t i = 0; i < votes.size(); ++i) { + if (votes[i]) { + desc.push_back(active_finalizer_policy->finalizers[i].description); + } else { + not_voted.insert(i); + } + } + }; + std::set not_voted; + if (qc._strong_votes) { + add_votes(*qc._strong_votes, m.strong_votes, not_voted); + } + if (qc._weak_votes) { + std::set not_voted_weak; + add_votes(*qc._weak_votes, m.weak_votes, not_voted_weak); + std::set no_votes; + std::ranges::set_intersection(not_voted, not_voted_weak, std::inserter(no_votes, no_votes.end())); + not_voted.swap(no_votes); + } + if (!not_voted.empty()) { + for (auto i : not_voted) { + m.no_votes.push_back(active_finalizer_policy->finalizers.at(i).description); + } + } + _update_vote_block_metrics(std::move(m)); + } + } + + void on_block(const signed_block_ptr& block, const block_id_type& id) { auto& chain = chain_plug->chain(); auto before = _unapplied_transactions.size(); _unapplied_transactions.clear_applied(block); @@ -634,6 +703,16 @@ class producer_plugin_impl : public std::enable_shared_from_this 0) { fc_dlog(_log, "Removed applied transactions before: ${before}, after: ${after}", ("before", before)("after", _unapplied_transactions.size())); } + if (vote_logger.is_enabled(fc::log_level::info) || _update_vote_block_metrics) { + if (block->contains_extension(quorum_certificate_extension::extension_id())) { + if (const auto& active_finalizers = chain.head_active_finalizer_policy()) { + const auto& qc_ext = block->extract_extension(); + const auto& qc = qc_ext.qc.qc; + log_missing_votes(block->block_num(), id, active_finalizers, qc); + update_vote_block_metrics(block->block_num(), active_finalizers, qc); + } + } + } } void on_block_header(const signed_block_ptr& block) { @@ -1128,6 +1207,7 @@ void producer_plugin_impl::plugin_initialize(const boost::program_options::varia if (bls) { const auto& [pubkey, privkey] = *bls; _finalizer_keys[pubkey.to_string()] = privkey.to_string(); + _finalizers.insert(pubkey); } } catch(secure_enclave_exception& e) { elog("Error with Secure Enclave signature provider: ${e}; ignoring ${val}", ("e", e.top_message())("val", key_spec_pair)); @@ -1340,8 +1420,8 @@ void producer_plugin_impl::plugin_startup() { chain.set_node_finalizer_keys(_finalizer_keys); _accepted_block_connection.emplace(chain.accepted_block().connect([this](const block_signal_params& t) { - const auto& [ block, _ ] = t; - on_block(block); + const auto& [ block, id ] = t; + on_block(block, id); })); _accepted_block_header_connection.emplace(chain.accepted_block_header().connect([this](const block_signal_params& t) { const auto& [ block, _ ] = t; @@ -2906,4 +2986,8 @@ void producer_plugin::register_update_incoming_block_metrics(std::function_update_incoming_block_metrics = std::move(fun); } +void producer_plugin::register_update_vote_block_metrics(std::function&& fun) { + my->_update_vote_block_metrics = std::move(fun); +} + } // namespace eosio diff --git a/plugins/prometheus_plugin/metrics.hpp b/plugins/prometheus_plugin/metrics.hpp index 656d27a408..6d3098aa2f 100644 --- a/plugins/prometheus_plugin/metrics.hpp +++ b/plugins/prometheus_plugin/metrics.hpp @@ -65,6 +65,12 @@ struct catalog_type { p2p_connection_metrics p2p_metrics; // producer plugin + struct vote_metrics { + Gauge& block_num; + prometheus::Family& voted; + }; + vote_metrics block_votes; + prometheus::Family& cpu_usage_us; prometheus::Family& net_usage_us; @@ -140,6 +146,10 @@ struct catalog_type { , .connection_start_time{family("nodeos_p2p_connection_start_time", "time of last connection to peer")} , .peer_addr{family("nodeos_p2p_peer_addr", "peer address")} } + , block_votes{ + .block_num{build("nodeos_block_num", "current block number")} + , .voted{family("nodeos_block_votes", "votes incorporated into a block, -1 weak, 1 strong")} + } , cpu_usage_us(family("nodeos_cpu_usage_us_total", "total cpu usage in microseconds for blocks")) , net_usage_us(family("nodeos_net_usage_us_total", "total net usage in microseconds for blocks")) , last_irreversible(build("nodeos_last_irreversible", "last irreversible block number")) @@ -234,6 +244,25 @@ struct catalog_type { } } + void update(const producer_plugin::vote_block_metrics&& metrics) { + block_votes.block_num.Set(metrics.block_num); + + auto add_and_set_gauge = [&](auto& fam, const auto& prod, const auto& value) { + auto& gauge = fam.Add({{"producer", prod}}); + gauge.Set(value); + }; + + for (const auto& v : metrics.strong_votes) { + add_and_set_gauge(block_votes.voted, v, 1); + } + for (const auto& v : metrics.weak_votes) { + add_and_set_gauge(block_votes.voted, v, -1); + } + for (const auto& v : metrics.no_votes) { + add_and_set_gauge(block_votes.voted, v, 0); + } + } + void update(block_metrics& blk_metrics, const producer_plugin::speculative_block_metrics& metrics) { blk_metrics.num_blocks_created.Increment(1); blk_metrics.current_block_num.Set(metrics.block_num); @@ -323,6 +352,10 @@ struct catalog_type { [&strand, this](const producer_plugin::incoming_block_metrics& metrics) { strand.post([metrics, this]() { update(metrics); }); }); + producer.register_update_vote_block_metrics( + [&strand, this](const producer_plugin::vote_block_metrics&& metrics) { + strand.post([metrics{std::move(metrics)}, this]() mutable { update(std::move(metrics)); }); + }); } }; From 38e4547d708ff8fb203a3c044e5e3bc01d603382 Mon Sep 17 00:00:00 2001 From: Kevin Heifner Date: Tue, 23 Apr 2024 13:04:53 -0500 Subject: [PATCH 4/9] GH-8 Do not log no vote messages if syncing. --- plugins/producer_plugin/producer_plugin.cpp | 50 +++++++++++---------- 1 file changed, 26 insertions(+), 24 deletions(-) diff --git a/plugins/producer_plugin/producer_plugin.cpp b/plugins/producer_plugin/producer_plugin.cpp index a4f16f6ebb..9b20a1673d 100644 --- a/plugins/producer_plugin/producer_plugin.cpp +++ b/plugins/producer_plugin/producer_plugin.cpp @@ -628,40 +628,42 @@ class producer_plugin_impl : public std::enable_shared_from_this not_voted; - - auto check_weak = [](const auto& weak_votes, size_t i) { - return weak_votes && (*weak_votes)[i]; - }; - - if (qc._strong_votes) { - const auto& votes = *qc._strong_votes; - auto& finalizers = active_finalizer_policy->finalizers; - assert(votes.size() == finalizers.size()); - for (size_t i = 0; i < votes.size(); ++i) { - if (!votes[i] && !check_weak(qc._weak_votes, i)) { - not_voted.push_back(finalizers[i].description); - if (_finalizers.contains(finalizers[i].public_key)) { - fc_wlog(vote_logger, "Block ${n}:${id} has no votes from our finalizer: ${v}", - ("n", block_num)("id", id.str().substr(8,16))("v", finalizers[i].description)); + if (fc::time_point::now() - block->timestamp < fc::minutes(5) || (block->block_num() % 1000 == 0)) { + std::vector not_voted; + + auto check_weak = [](const auto& weak_votes, size_t i) { + return weak_votes && (*weak_votes)[i]; + }; + + if (qc._strong_votes) { + const auto& votes = *qc._strong_votes; + auto& finalizers = active_finalizer_policy->finalizers; + assert(votes.size() == finalizers.size()); + for (size_t i = 0; i < votes.size(); ++i) { + if (!votes[i] && !check_weak(qc._weak_votes, i)) { + not_voted.push_back(finalizers[i].description); + if (_finalizers.contains(finalizers[i].public_key)) { + fc_wlog(vote_logger, "Block ${n}:${id} has no votes from our finalizer: ${v}", + ("n", block->block_num())("id", id.str().substr(8,16))("v", finalizers[i].description)); + } } } } - } - if (!not_voted.empty()) { - fc_ilog(vote_logger, "Block ${n}:${id} has no votes for: ${v}", - ("n", block_num)("id", id.str().substr(8,16))("v", not_voted)); + if (!not_voted.empty()) { + fc_ilog(vote_logger, "Block ${n}:${id} has no votes for: ${v}", + ("n", block->block_num())("id", id.str().substr(8,16))("v", not_voted)); + } } } } void update_vote_block_metrics(block_num_type block_num, const finalizer_policy_ptr& active_finalizer_policy, - const valid_quorum_certificate& qc ) { + const valid_quorum_certificate& qc) { if (_update_vote_block_metrics) { producer_plugin::vote_block_metrics m; m.block_num = block_num; @@ -708,7 +710,7 @@ class producer_plugin_impl : public std::enable_shared_from_thisextract_extension(); const auto& qc = qc_ext.qc.qc; - log_missing_votes(block->block_num(), id, active_finalizers, qc); + log_missing_votes(block, id, active_finalizers, qc); update_vote_block_metrics(block->block_num(), active_finalizers, qc); } } From 484d40e53afcef19eff4d9b32c8b5940ba41e757 Mon Sep 17 00:00:00 2001 From: Kevin Heifner Date: Tue, 23 Apr 2024 13:19:12 -0500 Subject: [PATCH 5/9] GH-8 Update help --- plugins/prometheus_plugin/metrics.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/prometheus_plugin/metrics.hpp b/plugins/prometheus_plugin/metrics.hpp index 6d3098aa2f..cb913f5b34 100644 --- a/plugins/prometheus_plugin/metrics.hpp +++ b/plugins/prometheus_plugin/metrics.hpp @@ -148,7 +148,7 @@ struct catalog_type { } , block_votes{ .block_num{build("nodeos_block_num", "current block number")} - , .voted{family("nodeos_block_votes", "votes incorporated into a block, -1 weak, 1 strong")} + , .voted{family("nodeos_block_votes", "votes incorporated into a block, -1 weak, 1 strong, 0 no vote")} } , cpu_usage_us(family("nodeos_cpu_usage_us_total", "total cpu usage in microseconds for blocks")) , net_usage_us(family("nodeos_net_usage_us_total", "total net usage in microseconds for blocks")) From 914f1177f7ef041052083b07cc34a0d3e590c0d8 Mon Sep 17 00:00:00 2001 From: Kevin Heifner Date: Tue, 23 Apr 2024 15:31:05 -0500 Subject: [PATCH 6/9] GH-8 Shortcut out on id > extension_id --- libraries/chain/block.cpp | 3 +++ libraries/chain/block_header.cpp | 3 +++ 2 files changed, 6 insertions(+) diff --git a/libraries/chain/block.cpp b/libraries/chain/block.cpp index 67e228ef15..a6b3e42132 100644 --- a/libraries/chain/block.cpp +++ b/libraries/chain/block.cpp @@ -65,6 +65,7 @@ namespace eosio::chain { return results; } + // Does not validate ordering, assumes validate_and_extract_extensions() has been called in verify_qc_claim() std::optional signed_block::extract_extension(uint16_t extension_id)const { using decompose_t = block_extension_types::decompose_t; @@ -72,6 +73,8 @@ namespace eosio::chain { const auto& e = block_extensions[i]; auto id = e.first; + if (id > extension_id) + break; if (id != extension_id) continue; diff --git a/libraries/chain/block_header.cpp b/libraries/chain/block_header.cpp index 4c94d47625..7ac95b9f39 100644 --- a/libraries/chain/block_header.cpp +++ b/libraries/chain/block_header.cpp @@ -65,6 +65,7 @@ namespace eosio { namespace chain { return results; } + // Does not validate ordering, assumes validate_and_extract_header_extensions() has been called in block_state creation std::optional block_header::extract_header_extension(uint16_t extension_id)const { using decompose_t = block_header_extension_types::decompose_t; @@ -72,6 +73,8 @@ namespace eosio { namespace chain { const auto& e = header_extensions[i]; auto id = e.first; + if (id > extension_id) + break; if (id != extension_id) continue; From 56ea22e03c859c163671bab034da1896bc47faf7 Mon Sep 17 00:00:00 2001 From: Kevin Heifner Date: Tue, 23 Apr 2024 15:31:45 -0500 Subject: [PATCH 7/9] GH-8 Update log messages --- plugins/producer_plugin/producer_plugin.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/plugins/producer_plugin/producer_plugin.cpp b/plugins/producer_plugin/producer_plugin.cpp index 9b20a1673d..6be98a91db 100644 --- a/plugins/producer_plugin/producer_plugin.cpp +++ b/plugins/producer_plugin/producer_plugin.cpp @@ -647,14 +647,14 @@ class producer_plugin_impl : public std::enable_shared_from_thisblock_num())("id", id.str().substr(8,16))("v", finalizers[i].description)); + fc_wlog(vote_logger, "Local finalizer ${f} did not vote on block ${n}:${id}", + ("f", finalizers[i].description)("n", block->block_num())("id", id.str().substr(8,16))); } } } } if (!not_voted.empty()) { - fc_ilog(vote_logger, "Block ${n}:${id} has no votes for: ${v}", + fc_ilog(vote_logger, "Block ${n}:${id} has no votes from finalizers: ${v}", ("n", block->block_num())("id", id.str().substr(8,16))("v", not_voted)); } } From 96e2f68cee32531f926f41df5cbdaac011ed8fa0 Mon Sep 17 00:00:00 2001 From: Kevin Heifner Date: Tue, 23 Apr 2024 15:32:18 -0500 Subject: [PATCH 8/9] GH-8 Use dynamic_bitset for not_voted calculation --- plugins/producer_plugin/producer_plugin.cpp | 26 ++++++++++----------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/plugins/producer_plugin/producer_plugin.cpp b/plugins/producer_plugin/producer_plugin.cpp index 6be98a91db..1075c15144 100644 --- a/plugins/producer_plugin/producer_plugin.cpp +++ b/plugins/producer_plugin/producer_plugin.cpp @@ -667,31 +667,31 @@ class producer_plugin_impl : public std::enable_shared_from_this& desc, std::set& not_voted) { + auto add_votes = [&](const auto& votes, std::vector& desc) { assert(votes.size() == active_finalizer_policy->finalizers.size()); for (size_t i = 0; i < votes.size(); ++i) { if (votes[i]) { desc.push_back(active_finalizer_policy->finalizers[i].description); - } else { - not_voted.insert(i); } } }; - std::set not_voted; if (qc._strong_votes) { - add_votes(*qc._strong_votes, m.strong_votes, not_voted); + add_votes(*qc._strong_votes, m.strong_votes); } if (qc._weak_votes) { - std::set not_voted_weak; - add_votes(*qc._weak_votes, m.weak_votes, not_voted_weak); - std::set no_votes; - std::ranges::set_intersection(not_voted, not_voted_weak, std::inserter(no_votes, no_votes.end())); - not_voted.swap(no_votes); + add_votes(*qc._weak_votes, m.weak_votes); } - if (!not_voted.empty()) { - for (auto i : not_voted) { - m.no_votes.push_back(active_finalizer_policy->finalizers.at(i).description); + if (m.strong_votes.size() + m.weak_votes.size() != active_finalizer_policy->finalizers.size()) { + fc::dynamic_bitset not_voted(active_finalizer_policy->finalizers.size()); + if (qc._strong_votes) { + not_voted = *qc._strong_votes; + } + if (qc._weak_votes) { + assert(not_voted.size() == qc._weak_votes->size()); + not_voted |= *qc._weak_votes; } + not_voted.flip(); + add_votes(not_voted, m.no_votes); } _update_vote_block_metrics(std::move(m)); } From e6b8d8b882faed704245ead52dd9762fd1002f8c Mon Sep 17 00:00:00 2001 From: Kevin Heifner Date: Wed, 24 Apr 2024 06:55:41 -0500 Subject: [PATCH 9/9] GH-8 Add assert that extensions are sorted --- libraries/chain/block.cpp | 2 ++ libraries/chain/block_header.cpp | 2 ++ libraries/chain/include/eosio/chain/block.hpp | 3 ++- 3 files changed, 6 insertions(+), 1 deletion(-) diff --git a/libraries/chain/block.cpp b/libraries/chain/block.cpp index a6b3e42132..b75778c4ff 100644 --- a/libraries/chain/block.cpp +++ b/libraries/chain/block.cpp @@ -69,6 +69,8 @@ namespace eosio::chain { std::optional signed_block::extract_extension(uint16_t extension_id)const { using decompose_t = block_extension_types::decompose_t; + assert(std::ranges::is_sorted(block_extensions)); // currently all extensions are unique so default compare works + for( size_t i = 0; i < block_extensions.size(); ++i ) { const auto& e = block_extensions[i]; auto id = e.first; diff --git a/libraries/chain/block_header.cpp b/libraries/chain/block_header.cpp index 7ac95b9f39..18763f99f6 100644 --- a/libraries/chain/block_header.cpp +++ b/libraries/chain/block_header.cpp @@ -69,6 +69,8 @@ namespace eosio { namespace chain { std::optional block_header::extract_header_extension(uint16_t extension_id)const { using decompose_t = block_header_extension_types::decompose_t; + assert(std::ranges::is_sorted(header_extensions)); // currently all extensions are unique so default compare works + for( size_t i = 0; i < header_extensions.size(); ++i ) { const auto& e = header_extensions[i]; auto id = e.first; diff --git a/libraries/chain/include/eosio/chain/block.hpp b/libraries/chain/include/eosio/chain/block.hpp index 8183a144da..895df9cb1e 100644 --- a/libraries/chain/include/eosio/chain/block.hpp +++ b/libraries/chain/include/eosio/chain/block.hpp @@ -79,7 +79,8 @@ namespace eosio { namespace chain { } using block_extension_types = detail::block_extension_types< - additional_block_signatures_extension, quorum_certificate_extension + additional_block_signatures_extension, + quorum_certificate_extension >; using block_extension = block_extension_types::block_extension_t;