From 2590fb1844a6718eff4beaa6981df3cbb382b1f1 Mon Sep 17 00:00:00 2001 From: iceseer Date: Fri, 12 Apr 2024 11:14:06 +0300 Subject: [PATCH 01/71] cache Signed-off-by: iceseer --- core/common/ref_cache.hpp | 95 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 95 insertions(+) create mode 100644 core/common/ref_cache.hpp diff --git a/core/common/ref_cache.hpp b/core/common/ref_cache.hpp new file mode 100644 index 0000000000..4830071d3d --- /dev/null +++ b/core/common/ref_cache.hpp @@ -0,0 +1,95 @@ +/** + * Copyright Quadrivium LLC + * All Rights Reserved + * SPDX-License-Identifier: Apache-2.0 + */ + +#pragma once + +#include +#include + +namespace kagome { + + /** + * @brief Cache keeps an item inside if any reference exists. If all references lost, then item removes from cache. If an item exists, then it returns new reference on it. + */ + template + struct RefCache : std::enable_shared_from_this { + using Container = std::map>; + using Iterator = Container::iterator; + using SRefCache = std::shared_ptr; + using Value = std::decay_t; + using Key = K; + + struct RefObj { + template + RefObj(Args &&...args) : obj_(std::forward(args)...) { + + } + + ~RefObj() { + BOOST_ASSERT(keeper_); + keeper_->remove(it_); + } + + private: + void store_internal_refs(Iterator it, SRefCache keeper) { + BOOST_ASSERT(keeper); + BOOST_ASSERT(!keeper_); + + it_ = it; + keeper_ = keeper; + } + + friend struct RefCache; + Value obj_; + Iterator it_; + SRefCache keeper_; + }; + using SRefObj = std::shared_ptr; + + /** + * @brief returns an element, if exists. Otherway `nullopt`. + * @param k is a key of an element + */ + std::optional get(const Key &k) { + [[likely]] if (auto it = items_.find(k); it != items_.end()) { + auto obj = it->second.lock(); + BOOST_ASSERT(obj); + return obj; + } + return std::nullopt; + } + + /** + * @brief returns an existed element or creates new one and store it in cache. + * @param k is a key of an element + * @param f is a functor to create RefObj + */ + template + SRefObj get_or_insert(const Key &k, F &&f) { + [[likely]] if (auto it = items_.find(k); it != items_.end()) { + auto obj = it->second.lock(); + BOOST_ASSERT(obj); + return obj; + } + + auto obj = std::make_shared(std::forward(f)()); + auto [it, inserted] = items_.emplace(k, obj); + BOOST_ASSERT(inserted); + + obj->store_internal_refs(it, shared_from_this()); + return obj; + } + + private: + void remove(const Iterator &it) { + items_.erase(it); + } + + friend struct RefObj; + Container items_; + }; + +} \ No newline at end of file From c046edffbbc6ff6a5e381cc01126aaee5c52d3cf Mon Sep 17 00:00:00 2001 From: iceseer Date: Fri, 12 Apr 2024 11:55:32 +0300 Subject: [PATCH 02/71] 1 Signed-off-by: iceseer --- core/common/ref_cache.hpp | 180 ++++++++++++++++++++++---------------- 1 file changed, 103 insertions(+), 77 deletions(-) diff --git a/core/common/ref_cache.hpp b/core/common/ref_cache.hpp index 4830071d3d..47ab5137e8 100644 --- a/core/common/ref_cache.hpp +++ b/core/common/ref_cache.hpp @@ -8,88 +8,114 @@ #include #include +#include namespace kagome { - /** - * @brief Cache keeps an item inside if any reference exists. If all references lost, then item removes from cache. If an item exists, then it returns new reference on it. - */ - template - struct RefCache : std::enable_shared_from_this { - using Container = std::map>; - using Iterator = Container::iterator; - using SRefCache = std::shared_ptr; - using Value = std::decay_t; - using Key = K; - - struct RefObj { - template - RefObj(Args &&...args) : obj_(std::forward(args)...) { - - } - - ~RefObj() { - BOOST_ASSERT(keeper_); - keeper_->remove(it_); - } - - private: - void store_internal_refs(Iterator it, SRefCache keeper) { - BOOST_ASSERT(keeper); - BOOST_ASSERT(!keeper_); - - it_ = it; - keeper_ = keeper; - } - - friend struct RefCache; - Value obj_; - Iterator it_; - SRefCache keeper_; - }; - using SRefObj = std::shared_ptr; - - /** - * @brief returns an element, if exists. Otherway `nullopt`. - * @param k is a key of an element - */ - std::optional get(const Key &k) { - [[likely]] if (auto it = items_.find(k); it != items_.end()) { - auto obj = it->second.lock(); - BOOST_ASSERT(obj); - return obj; - } - return std::nullopt; - } - - /** - * @brief returns an existed element or creates new one and store it in cache. - * @param k is a key of an element - * @param f is a functor to create RefObj - */ - template - SRefObj get_or_insert(const Key &k, F &&f) { - [[likely]] if (auto it = items_.find(k); it != items_.end()) { - auto obj = it->second.lock(); - BOOST_ASSERT(obj); - return obj; - } - - auto obj = std::make_shared(std::forward(f)()); - auto [it, inserted] = items_.emplace(k, obj); - BOOST_ASSERT(inserted); - - obj->store_internal_refs(it, shared_from_this()); - return obj; + /** + * @brief Cache keeps an item inside if any reference exists. If all + * references lost, then item removes from cache. If an item exists, then it + * returns new reference on it. + */ + template + struct RefCache : std::enable_shared_from_this> { + struct RefObj; + + using Value = std::decay_t; + using Container = std::map>; + using Iterator = typename Container::iterator; + using SRefCache = std::shared_ptr; + using Key = K; + + struct RefObj { + template + RefObj(Args &&...args) : obj_(std::forward(args)...) {} + + RefObj(RefObj &&) = default; + RefObj(const RefObj &) = delete; + + RefObj &operator=(RefObj &&) = delete; + RefObj &operator=(const RefObj &) = delete; + + ~RefObj() { + if (keeper_) { + keeper_->remove(it_); } + } - private: - void remove(const Iterator &it) { - items_.erase(it); - } + Value &value_mut() { + return obj_; + } + + const Value &value() const { + return obj_; + } + + private: + void store_internal_refs(Iterator it, SRefCache keeper) { + BOOST_ASSERT(keeper); + BOOST_ASSERT(!keeper_); - friend struct RefObj; - Container items_; + it_ = it; + keeper_ = keeper; + } + + friend struct RefCache; + Value obj_; + Iterator it_; + SRefCache keeper_; }; + using SRefObj = std::shared_ptr; + + static SRefCache create() { + return SRefCache(new RefCache()); + } -} \ No newline at end of file + /** + * @brief returns an element, if exists. Otherway `nullopt`. + * @param k is a key of an element + */ + std::optional get(const Key &k) { + [[likely]] if (auto it = items_.find(k); it != items_.end()) { + auto obj = it->second.lock(); + BOOST_ASSERT(obj); + return obj; + } + return std::nullopt; + } + + /** + * @brief returns an existed element or creates new one and store it in + * cache. + * @param k is a key of an element + * @param f is a functor to create RefObj + */ + template + SRefObj get_or_insert(const Key &k, F &&f) { + [[likely]] if (auto it = items_.find(k); it != items_.end()) { + auto obj = it->second.lock(); + BOOST_ASSERT(obj); + return obj; + } + + auto obj = std::make_shared(std::forward(f)()); + auto [it, inserted] = items_.emplace(k, obj); + BOOST_ASSERT(inserted); + + BOOST_ASSERT(this->shared_from_this()); + obj->store_internal_refs(it, this->shared_from_this()); + return obj; + } + + private: + RefCache() = default; + + void remove(const Iterator &it) { + items_.erase(it); + } + + friend struct RefObj; + Container items_; + }; + +} // namespace kagome \ No newline at end of file From 06a44c30d6548a08a777995a24c1cc149a47fb8c Mon Sep 17 00:00:00 2001 From: iceseer Date: Mon, 15 Apr 2024 11:00:33 +0300 Subject: [PATCH 03/71] 2 Signed-off-by: iceseer --- .../validator/impl/parachain_processor.cpp | 132 +++++++++--------- .../validator/parachain_processor.hpp | 11 +- 2 files changed, 73 insertions(+), 70 deletions(-) diff --git a/core/parachain/validator/impl/parachain_processor.cpp b/core/parachain/validator/impl/parachain_processor.cpp index cf89d92e13..7154933c94 100644 --- a/core/parachain/validator/impl/parachain_processor.cpp +++ b/core/parachain/validator/impl/parachain_processor.cpp @@ -134,6 +134,7 @@ namespace kagome::parachain { app_config_(app_config), babe_status_observable_(std::move(babe_status_observable)), query_audi_{std::move(query_audi)}, + per_session_(RefCache::create()), chain_sub_{std::move(chain_sub_engine)}, worker_pool_handler_{worker_thread_pool.handler(app_state_manager)}, prospective_parachains_{std::move(prospective_parachains)} { @@ -493,7 +494,7 @@ namespace kagome::parachain { peer_id, version, vi, - *parachain_state->get().groups, + parachain_state->get().per_session_state->value().groups, parachain_state->get()); } } @@ -774,6 +775,31 @@ namespace kagome::parachain { } is_parachain_validator = true; + if (!session_info) { + return Error::NO_SESSION_INFO; + } + + uint32_t minimum_backing_votes = 2; /// legacy value + if (auto r = + parachain_host_->minimum_backing_votes(relay_parent, session_index); + r.has_value()) { + minimum_backing_votes = r.value(); + } else { + SL_TRACE( + logger_, + "Querying the backing threshold from the runtime is not supported by the current Runtime API. (relay_parent={})", + relay_parent); + } + + auto per_session_state = per_session_->get_or_insert(session_index, [validator_index{validator->validatorIndex()}, minimum_backing_votes, session_info{std::move(*session_info)}]() mutable { + grid::Views grid_view = grid::makeViews(session_info.validator_groups, session_info.active_validator_indices, validator_index); + return RefCache::RefObj(PerSessionState{ + .session_info = std::move(session_info), + .groups = Groups {session_info.validator_groups, minimum_backing_votes}, + .grid_view = grid_view, + }); + }); + auto mode = prospective_parachains_->prospectiveParachainsMode(relay_parent); const auto n_cores = cores.size(); @@ -827,39 +853,17 @@ namespace kagome::parachain { } } - uint32_t minimum_backing_votes = 2; /// legacy value - if (auto r = - parachain_host_->minimum_backing_votes(relay_parent, session_index); - r.has_value()) { - minimum_backing_votes = r.value(); - } else { - SL_TRACE( - logger_, - "Querying the backing threshold from the runtime is not supported by the current Runtime API. (relay_parent={})", - relay_parent); - } - std::unordered_map authority_lookup; - std::optional groups_p; - std::optional grid_view; - if (session_info) { - grid_view = grid::makeViews(session_info->validator_groups, - session_info->active_validator_indices, - validator->validatorIndex()); - groups_p = Groups{session_info->validator_groups, minimum_backing_votes}; - for (ValidatorIndex v = 0; v < session_info->discovery_keys.size(); ++v) { - authority_lookup[session_info->discovery_keys[v]] = v; - } + for (ValidatorIndex v = 0; v < session_info->discovery_keys.size(); ++v) { + authority_lookup[session_info->discovery_keys[v]] = v; } std::optional statement_store; if (mode) { [[maybe_unused]] const auto _ = our_current_state_.implicit_view->activate_leaf(relay_parent); - if (groups_p) { - statement_store.emplace(*groups_p); - } + statement_store.emplace(per_session_state->value().groups); } SL_VERBOSE( @@ -871,18 +875,15 @@ namespace kagome::parachain { validator->validatorIndex(), relay_parent); - std::optional our_group; - if (groups_p) { - our_group = groups_p->byValidatorIndex(validator->validatorIndex()); - } return RelayParentState{ .prospective_parachains_mode = mode, .assigned_core = assigned_core, .assigned_para = assigned_para, .validator_to_group = std::move(validator_to_group), + .per_session_state = per_session_state, .seconded = {}, .our_index = validator->validatorIndex(), - .our_group = our_group, + .our_group = per_session_state->value().groups.byValidatorIndex(validator->validatorIndex()), .collations = {}, .table_context = TableContext{ @@ -896,8 +897,6 @@ namespace kagome::parachain { .minimum_backing_votes = minimum_backing_votes, .authority_lookup = std::move(authority_lookup), .local_validator = LocalValidatorState{}, - .groups = std::move(groups_p), - .grid_view = grid_view, .awaiting_validation = {}, .issued_statements = {}, .peers_advertised = {}, @@ -912,10 +911,7 @@ namespace kagome::parachain { if (rps_result.has_value()) { storeStateByRelayParent(relay_parent, std::move(rps_result.value())); } else if (rps_result.error() != Error::KEY_NOT_PRESENT) { - logger_->error( - "Relay parent state was not created. (relay parent={}, error={})", - relay_parent, - rps_result.error().message()); + SL_TRACE(logger_, "Relay parent state was not created. (relay parent={}, error={})", relay_parent, rps_result.error().message()); } } @@ -1160,11 +1156,11 @@ namespace kagome::parachain { return {}; } - if (!relay_parent_state->get().grid_view) { + if (!relay_parent_state->get().per_session_state->value().grid_view) { return {}; } - const auto &grid_topology = *relay_parent_state->get().grid_view; + const auto &grid_topology = *relay_parent_state->get().per_session_state->value().grid_view; if (manifest_summary.claimed_group_index >= grid_topology.size()) { return {}; } @@ -1199,7 +1195,7 @@ namespace kagome::parachain { auto &local_validator = *relay_parent_state->get().local_validator; auto acknowledge_res = local_validator.grid_tracker.import_manifest( grid_topology, - *relay_parent_state->get().groups, + relay_parent_state->get().per_session_state->value().groups, candidate_hash, seconding_limit, manifest_summary, @@ -1470,7 +1466,7 @@ namespace kagome::parachain { ValidatorIndex grid_sender_index) { /// TODO(iceseer): do Ensure the statement is correctly signed. Signature /// check. - grid_tracker.sent_or_received_direct_statement(*per_relay_parent.groups, + grid_tracker.sent_or_received_direct_statement(per_relay_parent.per_session_state->value().groups, statement.payload.ix, grid_sender_index, getPayload(statement), @@ -1540,7 +1536,7 @@ namespace kagome::parachain { relay_parent, local_validator.grid_tracker, *relay_parent_state.statement_store, - *relay_parent_state.groups, + relay_parent_state.per_session_state->value().groups, group_index, candidate_hash, peer_id, @@ -1619,7 +1615,7 @@ namespace kagome::parachain { "Get groups. (relay_parent={}, candidate_hash={})", manifest.relay_parent, manifest.candidate_hash); - auto group = relay_parent_state->get().groups->get(manifest.group_index); + auto group = relay_parent_state->get().per_session_state->value().groups.get(manifest.group_index); if (!group) { return; } @@ -1638,7 +1634,7 @@ namespace kagome::parachain { peer_id, network::CollationVersion::VStaging, sender_index, - *relay_parent_state->get().groups, + relay_parent_state->get().per_session_state->value().groups, relay_parent_state->get(), manifest.relay_parent, manifest.group_index, @@ -1711,7 +1707,7 @@ namespace kagome::parachain { auto &local_validator = *parachain_state->get().local_validator; auto originator_group = - parachain_state->get().groups->byValidatorIndex(stm.compact.payload.ix); + parachain_state->get().per_session_state->value().groups.byValidatorIndex(stm.compact.payload.ix); if (!originator_group) { SL_TRACE(logger_, "No correct validator index in statement. (relay parent={}, " @@ -1729,7 +1725,7 @@ namespace kagome::parachain { std::optional> grid_sender_index; for (const auto &[i, validator_knows_statement] : local_validator.grid_tracker.direct_statement_providers( - *parachain_state->get().groups, + parachain_state->get().per_session_state->value().groups, stm.compact.payload.ix, getPayload(stm.compact))) { if (i >= opt_session_info->discovery_keys.size()) { @@ -1787,7 +1783,7 @@ namespace kagome::parachain { /// check statement signature const auto was_fresh_opt = parachain_state->get().statement_store->insert( - *parachain_state->get().groups, stm.compact, StatementOrigin::Remote); + parachain_state->get().per_session_state->value().groups, stm.compact, StatementOrigin::Remote); if (!was_fresh_opt) { SL_WARN(logger_, "Accepted message from unknown validator. (relay parent={}, " @@ -1806,10 +1802,10 @@ namespace kagome::parachain { } const auto is_importable = candidates_.is_importable(candidate_hash); - if (parachain_state->get().grid_view) { + if (parachain_state->get().per_session_state->value().grid_view) { local_validator.grid_tracker.learned_fresh_statement( - *parachain_state->get().groups, - *parachain_state->get().grid_view, + parachain_state->get().per_session_state->value().groups, + *parachain_state->get().per_session_state->value().grid_view, originator_index, statement); } @@ -1870,13 +1866,13 @@ namespace kagome::parachain { auto &local_validator = *relay_parent_state.local_validator; [[maybe_unused]] auto statement_group = - relay_parent_state.groups->byValidatorIndex(originator); + relay_parent_state.per_session_state->value().groups.byValidatorIndex(originator); /// TODO(iceseer): do `cluster` targets std::vector> statement_to_peers; for (const auto v : local_validator.grid_tracker.direct_statement_targets( - *relay_parent_state.groups, originator, compact_statement)) { + relay_parent_state.per_session_state->value().groups, originator, compact_statement)) { auto peer = query_audi_->get(session_info->discovery_keys[v]); if (!peer) { continue; @@ -1898,7 +1894,7 @@ namespace kagome::parachain { statement_to_peers.emplace_back(peer->id, version); local_validator.grid_tracker.sent_or_received_direct_statement( - *relay_parent_state.groups, originator, v, compact_statement, false); + relay_parent_state.per_session_state->value().groups, originator, v, compact_statement, false); } auto se = pm_->getStreamEngine(); @@ -1940,7 +1936,7 @@ namespace kagome::parachain { return; } - auto group = relay_parent_state.groups->get(group_index); + auto group = relay_parent_state.per_session_state->value().groups.get(group_index); if (!group) { return; } @@ -1965,7 +1961,7 @@ namespace kagome::parachain { /// https://github.com/qdrvm/kagome/issues/2060 auto backing_threshold = [&]() -> std::optional { - auto bt = relay_parent_state.groups->get_size_and_backing_threshold( + auto bt = relay_parent_state.per_session_state->value().groups.get_size_and_backing_threshold( group_index); return bt ? std::get<1>(*bt) : std::optional{}; }(); @@ -2117,7 +2113,7 @@ namespace kagome::parachain { response.statements.size()); for (const auto &statement : response.statements) { parachain_state->get().statement_store->insert( - *parachain_state->get().groups, statement, StatementOrigin::Remote); + parachain_state->get().per_session_state->value().groups, statement, StatementOrigin::Remote); } auto opt_post_confirmation = @@ -2151,7 +2147,7 @@ namespace kagome::parachain { return; } - const auto &groups = *parachain_state->get().groups; + const auto &groups = parachain_state->get().per_session_state->value().groups; auto it = groups.groups.find(group_index); if (it == groups.groups.end()) { SL_WARN(logger_, @@ -2290,7 +2286,7 @@ namespace kagome::parachain { return; } - auto group = relay_parent_state->get().groups->get(*local_group); + auto group = relay_parent_state->get().per_session_state->value().groups.get(*local_group); if (!group) { return; } @@ -2608,7 +2604,7 @@ namespace kagome::parachain { BOOST_ASSERT(relay_parent_state->get().our_index); auto group = - relay_parent_state->get().groups->get(confirmed->get().group_index()); + relay_parent_state->get().per_session_state->value().groups.get(confirmed->get().group_index()); if (!group) { SL_ERROR(logger_, "Unexpected array bound for groups. (relay parent={})", @@ -2819,7 +2815,7 @@ namespace kagome::parachain { const auto relay_parent = confirmed_candidate.relay_parent(); const auto group_index = confirmed_candidate.group_index(); - if (!relay_parent_state.grid_view) { + if (!relay_parent_state.per_session_state->value().grid_view) { SL_TRACE( logger_, "Cannot handle backable candidate due to lack of topology. (candidate={}, relay_parent={})", @@ -2828,8 +2824,8 @@ namespace kagome::parachain { return; } - const auto &grid_view = *relay_parent_state.grid_view; - const auto group = relay_parent_state.groups->get(group_index); + const auto &grid_view = *relay_parent_state.per_session_state->value().grid_view; + const auto group = relay_parent_state.per_session_state->value().groups.get(group_index); if (!group) { SL_TRACE( logger_, @@ -2888,14 +2884,14 @@ namespace kagome::parachain { } local_validator.grid_tracker.manifest_sent_to( - *relay_parent_state.groups, v, candidate_hash, filter); + relay_parent_state.per_session_state->value().groups, v, candidate_hash, filter); auto msgs = post_acknowledgement_statement_messages( v, relay_parent, local_validator.grid_tracker, *relay_parent_state.statement_store, - *relay_parent_state.groups, + relay_parent_state.per_session_state->value().groups, group_index, candidate_hash, peer_opt->id, @@ -4054,7 +4050,7 @@ namespace kagome::parachain { return; } - const Groups &groups = *per_relay_parent.groups; + const Groups &groups = per_relay_parent.per_session_state->value().groups; const std::optional &local_assignment = per_relay_parent.assigned_para; const network::ValidatorIndex local_index = *per_relay_parent.our_index; @@ -4146,10 +4142,10 @@ namespace kagome::parachain { return; } - if (per_relay_parent.grid_view) { + if (per_relay_parent.per_session_state->value().grid_view) { auto &l = *per_relay_parent.local_validator; - l.grid_tracker.learned_fresh_statement(*per_relay_parent.groups, - *per_relay_parent.grid_view, + l.grid_tracker.learned_fresh_statement(per_relay_parent.per_session_state->value().groups, + *per_relay_parent.per_session_state->value().grid_view, local_index, getPayload(compact_statement)); } diff --git a/core/parachain/validator/parachain_processor.hpp b/core/parachain/validator/parachain_processor.hpp index 7b0b5cc67c..516217de74 100644 --- a/core/parachain/validator/parachain_processor.hpp +++ b/core/parachain/validator/parachain_processor.hpp @@ -40,6 +40,7 @@ #include "primitives/event_types.hpp" #include "utils/non_copyable.hpp" #include "utils/safe_object.hpp" +#include "common/ref_cache.hpp" namespace kagome::common { class MainThreadPool; @@ -249,11 +250,18 @@ namespace kagome::parachain { grid::GridTracker grid_tracker; }; + struct PerSessionState { + runtime::SessionInfo session_info; + Groups groups; + std::optional grid_view; + }; + struct RelayParentState { ProspectiveParachainsModeOpt prospective_parachains_mode; std::optional assigned_core; std::optional assigned_para; std::vector> validator_to_group; + std::shared_ptr::RefObj> per_session_state; std::optional seconded; std::optional our_index; @@ -268,8 +276,6 @@ namespace kagome::parachain { std::unordered_map authority_lookup; std::optional local_validator; - std::optional groups; - std::optional grid_view; std::unordered_set awaiting_validation; std::unordered_set issued_statements; @@ -749,6 +755,7 @@ namespace kagome::parachain { primitives::events::BabeStateSubscriptionEnginePtr babe_status_observable_; primitives::events::BabeStateEventSubscriberPtr babe_status_observer_; std::shared_ptr query_audi_; + std::shared_ptr> per_session_; primitives::events::ChainSub chain_sub_; std::shared_ptr worker_pool_handler_; From 3c16aaf64196820360d7e6cd1f4634c081d84432 Mon Sep 17 00:00:00 2001 From: iceseer Date: Mon, 15 Apr 2024 11:17:22 +0300 Subject: [PATCH 04/71] 3 Signed-off-by: iceseer --- .../validator/impl/parachain_processor.cpp | 110 ++++-------------- .../validator/parachain_processor.hpp | 2 - 2 files changed, 22 insertions(+), 90 deletions(-) diff --git a/core/parachain/validator/impl/parachain_processor.cpp b/core/parachain/validator/impl/parachain_processor.cpp index 7154933c94..c95376bf76 100644 --- a/core/parachain/validator/impl/parachain_processor.cpp +++ b/core/parachain/validator/impl/parachain_processor.cpp @@ -476,11 +476,6 @@ namespace kagome::parachain { return; } - auto opt_session_info = retrieveSessionInfo(relay_parent); - if (!opt_session_info) { - return; - } - network::CollationVersion version = network::CollationVersion::VStaging; if (peer_state->get().version) { version = *peer_state->get().version; @@ -1072,17 +1067,13 @@ namespace kagome::parachain { BOOST_ASSERT_MSG( bd, "BitfieldDistribution is not present. Check message format."); - auto opt_session_info = retrieveSessionInfo(bd->relay_parent); - if (!opt_session_info) { - SL_TRACE(logger_, - "Unexpected relay parent. No session info. (validator index={}, " - "relay_parent={})", - bd->data.payload.ix, - bd->relay_parent); + auto parachain_state = tryGetStateByRelayParent(bd->relay_parent); + if (!parachain_state) { return; } - if (bd->data.payload.ix >= opt_session_info->validators.size()) { + const auto &session_info = parachain_state->get().per_session_state->value().session_info; + if (bd->data.payload.ix >= session_info.validators.size()) { SL_TRACE( logger_, "Validator index out of bound. (validator index={}, relay_parent={})", @@ -1106,7 +1097,7 @@ namespace kagome::parachain { auto res = crypto_provider_->verify( bd->data.signature, buffer, - opt_session_info->validators[bd->data.payload.ix]); + session_info.validators[bd->data.payload.ix]); if (res.has_error() || !res.value()) { SL_TRACE( logger_, @@ -1693,14 +1684,7 @@ namespace kagome::parachain { return; } - auto opt_session_info = retrieveSessionInfo(stm.relay_parent); - if (!opt_session_info) { - SL_WARN(logger_, - "No session info for current parrent. (relay parent={})", - stm.relay_parent); - return; - } - + const auto &session_info = parachain_state->get().per_session_state->value().session_info; if (!parachain_state->get().local_validator) { return; } @@ -1728,7 +1712,7 @@ namespace kagome::parachain { parachain_state->get().per_session_state->value().groups, stm.compact.payload.ix, getPayload(stm.compact))) { - if (i >= opt_session_info->discovery_keys.size()) { + if (i >= session_info.discovery_keys.size()) { continue; } @@ -1770,7 +1754,7 @@ namespace kagome::parachain { const auto confirmed = candidates_.get_confirmed(candidate_hash); const auto is_confirmed = candidates_.is_confirmed(candidate_hash); - const auto &group = opt_session_info->validator_groups[*originator_group]; + const auto &group = session_info.validator_groups[*originator_group]; if (!is_confirmed) { request_attested_candidate(parachain_state->get(), @@ -1849,11 +1833,7 @@ namespace kagome::parachain { const RelayHash &relay_parent, RelayParentState &relay_parent_state, const IndexedAndSigned &statement) { - auto session_info = retrieveSessionInfo(relay_parent); - if (!session_info) { - return; - } - + const auto &session_info = relay_parent_state.per_session_state->value().session_info; const auto &compact_statement = getPayload(statement); const auto &candidate_hash = candidateHash(compact_statement); const auto originator = statement.payload.ix; @@ -1873,7 +1853,7 @@ namespace kagome::parachain { statement_to_peers; for (const auto v : local_validator.grid_tracker.direct_statement_targets( relay_parent_state.per_session_state->value().groups, originator, compact_statement)) { - auto peer = query_audi_->get(session_info->discovery_keys[v]); + auto peer = query_audi_->get(session_info.discovery_keys[v]); if (!peer) { continue; } @@ -1928,14 +1908,7 @@ namespace kagome::parachain { } auto &local_validator = *relay_parent_state.local_validator; - auto opt_session_info = retrieveSessionInfo(relay_parent); - if (!opt_session_info) { - SL_WARN(logger_, - "No session info for current parrent. (relay parent={})", - relay_parent); - return; - } - + const auto &session_info = relay_parent_state.per_session_state->value().session_info; auto group = relay_parent_state.per_session_state->value().groups.get(group_index); if (!group) { return; @@ -1985,9 +1958,9 @@ namespace kagome::parachain { } ValidatorIndex validator_id = 0; - for (; validator_id < opt_session_info->discovery_keys.size(); + for (; validator_id < session_info.discovery_keys.size(); ++validator_id) { - if (opt_session_info->discovery_keys[validator_id] == *audi) { + if (session_info.discovery_keys[validator_id] == *audi) { SL_TRACE(logger_, "Captured validator. (relay_parent={}, candidate_hash={})", relay_parent, @@ -2224,14 +2197,13 @@ namespace kagome::parachain { group_for_para(prs->get().availability_cores, prs->get().group_rotation_info, c->get().receipt.descriptor.para_id); - auto opt_session_info = - retrieveSessionInfo(c->get().receipt.descriptor.relay_parent); - if (!opt_session_info || !group_index - || *group_index >= opt_session_info->validator_groups.size()) { + + const auto &session_info = prs->get().per_session_state->value().session_info; + if (!group_index || *group_index >= session_info.validator_groups.size()) { return; } - const auto &group = opt_session_info->validator_groups[*group_index]; + const auto &group = session_info.validator_groups[*group_index]; send_backing_fresh_statements( *confirmed_candidate, c->get().receipt.descriptor.relay_parent, @@ -2491,20 +2463,6 @@ namespace kagome::parachain { protocol->request(peer_info, candidate_hash, std::forward(callback)); } - std::optional - ParachainProcessorImpl::retrieveSessionInfo(const RelayHash &relay_parent) { - if (auto session_index = - parachain_host_->session_index_for_child(relay_parent); - session_index.has_value()) { - if (auto session_info = parachain_host_->session_info( - relay_parent, session_index.value()); - session_info.has_value()) { - return session_info.value(); - } - } - return std::nullopt; - } - void ParachainProcessorImpl::kickOffValidationWork( const RelayHash &relay_parent, AttestingData &attesting_data, @@ -2517,13 +2475,8 @@ namespace kagome::parachain { return; } - auto session_info = retrieveSessionInfo(relay_parent); - if (!session_info) { - SL_WARN(logger_, "No session info.(relay_parent={})", relay_parent); - return; - } - - if (session_info->discovery_keys.size() <= attesting_data.from_validator) { + const auto &session_info = parachain_state.per_session_state->value().session_info; + if (session_info.discovery_keys.size() <= attesting_data.from_validator) { SL_ERROR(logger_, "Invalid validator index.(relay_parent={}, validator_index={})", relay_parent, @@ -2532,7 +2485,7 @@ namespace kagome::parachain { } const auto &authority_id = - session_info->discovery_keys[attesting_data.from_validator]; + session_info.discovery_keys[attesting_data.from_validator]; if (auto peer = query_audi_->get(authority_id)) { auto pvd{persisted_validation_data}; requestPoV( @@ -2983,16 +2936,11 @@ namespace kagome::parachain { } BOOST_ASSERT(relay_parent_state_opt->get().statement_store); - std::optional opt_session_info = - retrieveSessionInfo(relay_parent); - if (!opt_session_info) { - return; - } - + const auto &session_info = relay_parent_state_opt->get().per_session_state->value().session_info; provide_candidate_to_grid(candidate_hash, relay_parent_state_opt->get(), confirmed, - *opt_session_info); + session_info); prospective_backed_notification_fragment_tree_updates( confirmed.para_id(), confirmed.para_head()); @@ -4041,26 +3989,12 @@ namespace kagome::parachain { candidate_hash); BOOST_ASSERT(per_relay_parent.our_index); - std::optional opt_session_info = - retrieveSessionInfo(relay_parent); - if (!opt_session_info) { - SL_ERROR(logger_, - "Retrieve session info failed. (relay parent={})", - relay_parent); - return; - } const Groups &groups = per_relay_parent.per_session_state->value().groups; const std::optional &local_assignment = per_relay_parent.assigned_para; const network::ValidatorIndex local_index = *per_relay_parent.our_index; const auto local_group_opt = groups.byValidatorIndex(local_index); - if (!opt_session_info) { - SL_ERROR(logger_, - "Local validator info is not present. (relay parent={})", - relay_parent); - return; - } const GroupIndex local_group = *local_group_opt; std::optional> expected = visit_in_place( diff --git a/core/parachain/validator/parachain_processor.hpp b/core/parachain/validator/parachain_processor.hpp index 516217de74..9bd080d455 100644 --- a/core/parachain/validator/parachain_processor.hpp +++ b/core/parachain/validator/parachain_processor.hpp @@ -484,8 +484,6 @@ namespace kagome::parachain { AttestingData &attesting_data, const runtime::PersistedValidationData &persisted_validation_data, RelayParentState ¶chain_state); - std::optional retrieveSessionInfo( - const RelayHash &relay_parent); void handleFetchedCollation(PendingCollation &&pending_collation, network::CollationFetchingResponse &&response); template From 390618537fbb8cf99c2922f45c623743cc87a556 Mon Sep 17 00:00:00 2001 From: iceseer Date: Mon, 15 Apr 2024 11:21:57 +0300 Subject: [PATCH 05/71] formatting Signed-off-by: iceseer --- .../validator/impl/parachain_processor.cpp | 165 ++++++++++++------ .../validator/parachain_processor.hpp | 11 +- 2 files changed, 113 insertions(+), 63 deletions(-) diff --git a/core/parachain/validator/impl/parachain_processor.cpp b/core/parachain/validator/impl/parachain_processor.cpp index c95376bf76..61fc34bb87 100644 --- a/core/parachain/validator/impl/parachain_processor.cpp +++ b/core/parachain/validator/impl/parachain_processor.cpp @@ -485,12 +485,13 @@ namespace kagome::parachain { if (auto it = parachain_state->get().authority_lookup.find(*auth_id); it != parachain_state->get().authority_lookup.end()) { ValidatorIndex vi = it->second; - send_pending_grid_messages(relay_parent, - peer_id, - version, - vi, - parachain_state->get().per_session_state->value().groups, - parachain_state->get()); + send_pending_grid_messages( + relay_parent, + peer_id, + version, + vi, + parachain_state->get().per_session_state->value().groups, + parachain_state->get()); } } @@ -786,14 +787,23 @@ namespace kagome::parachain { relay_parent); } - auto per_session_state = per_session_->get_or_insert(session_index, [validator_index{validator->validatorIndex()}, minimum_backing_votes, session_info{std::move(*session_info)}]() mutable { - grid::Views grid_view = grid::makeViews(session_info.validator_groups, session_info.active_validator_indices, validator_index); - return RefCache::RefObj(PerSessionState{ - .session_info = std::move(session_info), - .groups = Groups {session_info.validator_groups, minimum_backing_votes}, - .grid_view = grid_view, - }); - }); + auto per_session_state = per_session_->get_or_insert( + session_index, + [validator_index{validator->validatorIndex()}, + minimum_backing_votes, + session_info{std::move(*session_info)}]() mutable { + grid::Views grid_view = + grid::makeViews(session_info.validator_groups, + session_info.active_validator_indices, + validator_index); + return RefCache::RefObj( + PerSessionState{ + .session_info = std::move(session_info), + .groups = Groups{session_info.validator_groups, + minimum_backing_votes}, + .grid_view = grid_view, + }); + }); auto mode = prospective_parachains_->prospectiveParachainsMode(relay_parent); @@ -878,7 +888,8 @@ namespace kagome::parachain { .per_session_state = per_session_state, .seconded = {}, .our_index = validator->validatorIndex(), - .our_group = per_session_state->value().groups.byValidatorIndex(validator->validatorIndex()), + .our_group = per_session_state->value().groups.byValidatorIndex( + validator->validatorIndex()), .collations = {}, .table_context = TableContext{ @@ -906,7 +917,11 @@ namespace kagome::parachain { if (rps_result.has_value()) { storeStateByRelayParent(relay_parent, std::move(rps_result.value())); } else if (rps_result.error() != Error::KEY_NOT_PRESENT) { - SL_TRACE(logger_, "Relay parent state was not created. (relay parent={}, error={})", relay_parent, rps_result.error().message()); + SL_TRACE( + logger_, + "Relay parent state was not created. (relay parent={}, error={})", + relay_parent, + rps_result.error().message()); } } @@ -1072,7 +1087,8 @@ namespace kagome::parachain { return; } - const auto &session_info = parachain_state->get().per_session_state->value().session_info; + const auto &session_info = + parachain_state->get().per_session_state->value().session_info; if (bd->data.payload.ix >= session_info.validators.size()) { SL_TRACE( logger_, @@ -1094,10 +1110,10 @@ namespace kagome::parachain { SigningContext &context = res_sc.value(); const auto buffer = context.signable(*hasher_, bd->data.payload.payload); - auto res = crypto_provider_->verify( - bd->data.signature, - buffer, - session_info.validators[bd->data.payload.ix]); + auto res = + crypto_provider_->verify(bd->data.signature, + buffer, + session_info.validators[bd->data.payload.ix]); if (res.has_error() || !res.value()) { SL_TRACE( logger_, @@ -1151,7 +1167,8 @@ namespace kagome::parachain { return {}; } - const auto &grid_topology = *relay_parent_state->get().per_session_state->value().grid_view; + const auto &grid_topology = + *relay_parent_state->get().per_session_state->value().grid_view; if (manifest_summary.claimed_group_index >= grid_topology.size()) { return {}; } @@ -1457,11 +1474,12 @@ namespace kagome::parachain { ValidatorIndex grid_sender_index) { /// TODO(iceseer): do Ensure the statement is correctly signed. Signature /// check. - grid_tracker.sent_or_received_direct_statement(per_relay_parent.per_session_state->value().groups, - statement.payload.ix, - grid_sender_index, - getPayload(statement), - true); + grid_tracker.sent_or_received_direct_statement( + per_relay_parent.per_session_state->value().groups, + statement.payload.ix, + grid_sender_index, + getPayload(statement), + true); return outcome::success(); } @@ -1606,7 +1624,9 @@ namespace kagome::parachain { "Get groups. (relay_parent={}, candidate_hash={})", manifest.relay_parent, manifest.candidate_hash); - auto group = relay_parent_state->get().per_session_state->value().groups.get(manifest.group_index); + auto group = + relay_parent_state->get().per_session_state->value().groups.get( + manifest.group_index); if (!group) { return; } @@ -1684,14 +1704,17 @@ namespace kagome::parachain { return; } - const auto &session_info = parachain_state->get().per_session_state->value().session_info; + const auto &session_info = + parachain_state->get().per_session_state->value().session_info; if (!parachain_state->get().local_validator) { return; } auto &local_validator = *parachain_state->get().local_validator; auto originator_group = - parachain_state->get().per_session_state->value().groups.byValidatorIndex(stm.compact.payload.ix); + parachain_state->get() + .per_session_state->value() + .groups.byValidatorIndex(stm.compact.payload.ix); if (!originator_group) { SL_TRACE(logger_, "No correct validator index in statement. (relay parent={}, " @@ -1767,7 +1790,9 @@ namespace kagome::parachain { /// check statement signature const auto was_fresh_opt = parachain_state->get().statement_store->insert( - parachain_state->get().per_session_state->value().groups, stm.compact, StatementOrigin::Remote); + parachain_state->get().per_session_state->value().groups, + stm.compact, + StatementOrigin::Remote); if (!was_fresh_opt) { SL_WARN(logger_, "Accepted message from unknown validator. (relay parent={}, " @@ -1833,7 +1858,8 @@ namespace kagome::parachain { const RelayHash &relay_parent, RelayParentState &relay_parent_state, const IndexedAndSigned &statement) { - const auto &session_info = relay_parent_state.per_session_state->value().session_info; + const auto &session_info = + relay_parent_state.per_session_state->value().session_info; const auto &compact_statement = getPayload(statement); const auto &candidate_hash = candidateHash(compact_statement); const auto originator = statement.payload.ix; @@ -1846,13 +1872,16 @@ namespace kagome::parachain { auto &local_validator = *relay_parent_state.local_validator; [[maybe_unused]] auto statement_group = - relay_parent_state.per_session_state->value().groups.byValidatorIndex(originator); + relay_parent_state.per_session_state->value().groups.byValidatorIndex( + originator); /// TODO(iceseer): do `cluster` targets std::vector> statement_to_peers; for (const auto v : local_validator.grid_tracker.direct_statement_targets( - relay_parent_state.per_session_state->value().groups, originator, compact_statement)) { + relay_parent_state.per_session_state->value().groups, + originator, + compact_statement)) { auto peer = query_audi_->get(session_info.discovery_keys[v]); if (!peer) { continue; @@ -1874,7 +1903,11 @@ namespace kagome::parachain { statement_to_peers.emplace_back(peer->id, version); local_validator.grid_tracker.sent_or_received_direct_statement( - relay_parent_state.per_session_state->value().groups, originator, v, compact_statement, false); + relay_parent_state.per_session_state->value().groups, + originator, + v, + compact_statement, + false); } auto se = pm_->getStreamEngine(); @@ -1908,8 +1941,10 @@ namespace kagome::parachain { } auto &local_validator = *relay_parent_state.local_validator; - const auto &session_info = relay_parent_state.per_session_state->value().session_info; - auto group = relay_parent_state.per_session_state->value().groups.get(group_index); + const auto &session_info = + relay_parent_state.per_session_state->value().session_info; + auto group = + relay_parent_state.per_session_state->value().groups.get(group_index); if (!group) { return; } @@ -1934,8 +1969,8 @@ namespace kagome::parachain { /// https://github.com/qdrvm/kagome/issues/2060 auto backing_threshold = [&]() -> std::optional { - auto bt = relay_parent_state.per_session_state->value().groups.get_size_and_backing_threshold( - group_index); + auto bt = relay_parent_state.per_session_state->value() + .groups.get_size_and_backing_threshold(group_index); return bt ? std::get<1>(*bt) : std::optional{}; }(); @@ -2086,7 +2121,9 @@ namespace kagome::parachain { response.statements.size()); for (const auto &statement : response.statements) { parachain_state->get().statement_store->insert( - parachain_state->get().per_session_state->value().groups, statement, StatementOrigin::Remote); + parachain_state->get().per_session_state->value().groups, + statement, + StatementOrigin::Remote); } auto opt_post_confirmation = @@ -2120,7 +2157,8 @@ namespace kagome::parachain { return; } - const auto &groups = parachain_state->get().per_session_state->value().groups; + const auto &groups = + parachain_state->get().per_session_state->value().groups; auto it = groups.groups.find(group_index); if (it == groups.groups.end()) { SL_WARN(logger_, @@ -2198,8 +2236,10 @@ namespace kagome::parachain { prs->get().group_rotation_info, c->get().receipt.descriptor.para_id); - const auto &session_info = prs->get().per_session_state->value().session_info; - if (!group_index || *group_index >= session_info.validator_groups.size()) { + const auto &session_info = + prs->get().per_session_state->value().session_info; + if (!group_index + || *group_index >= session_info.validator_groups.size()) { return; } @@ -2258,7 +2298,9 @@ namespace kagome::parachain { return; } - auto group = relay_parent_state->get().per_session_state->value().groups.get(*local_group); + auto group = + relay_parent_state->get().per_session_state->value().groups.get( + *local_group); if (!group) { return; } @@ -2475,7 +2517,8 @@ namespace kagome::parachain { return; } - const auto &session_info = parachain_state.per_session_state->value().session_info; + const auto &session_info = + parachain_state.per_session_state->value().session_info; if (session_info.discovery_keys.size() <= attesting_data.from_validator) { SL_ERROR(logger_, "Invalid validator index.(relay_parent={}, validator_index={})", @@ -2557,7 +2600,8 @@ namespace kagome::parachain { BOOST_ASSERT(relay_parent_state->get().our_index); auto group = - relay_parent_state->get().per_session_state->value().groups.get(confirmed->get().group_index()); + relay_parent_state->get().per_session_state->value().groups.get( + confirmed->get().group_index()); if (!group) { SL_ERROR(logger_, "Unexpected array bound for groups. (relay parent={})", @@ -2777,8 +2821,10 @@ namespace kagome::parachain { return; } - const auto &grid_view = *relay_parent_state.per_session_state->value().grid_view; - const auto group = relay_parent_state.per_session_state->value().groups.get(group_index); + const auto &grid_view = + *relay_parent_state.per_session_state->value().grid_view; + const auto group = + relay_parent_state.per_session_state->value().groups.get(group_index); if (!group) { SL_TRACE( logger_, @@ -2837,7 +2883,10 @@ namespace kagome::parachain { } local_validator.grid_tracker.manifest_sent_to( - relay_parent_state.per_session_state->value().groups, v, candidate_hash, filter); + relay_parent_state.per_session_state->value().groups, + v, + candidate_hash, + filter); auto msgs = post_acknowledgement_statement_messages( v, @@ -2936,11 +2985,10 @@ namespace kagome::parachain { } BOOST_ASSERT(relay_parent_state_opt->get().statement_store); - const auto &session_info = relay_parent_state_opt->get().per_session_state->value().session_info; - provide_candidate_to_grid(candidate_hash, - relay_parent_state_opt->get(), - confirmed, - session_info); + const auto &session_info = + relay_parent_state_opt->get().per_session_state->value().session_info; + provide_candidate_to_grid( + candidate_hash, relay_parent_state_opt->get(), confirmed, session_info); prospective_backed_notification_fragment_tree_updates( confirmed.para_id(), confirmed.para_head()); @@ -4078,10 +4126,11 @@ namespace kagome::parachain { if (per_relay_parent.per_session_state->value().grid_view) { auto &l = *per_relay_parent.local_validator; - l.grid_tracker.learned_fresh_statement(per_relay_parent.per_session_state->value().groups, - *per_relay_parent.per_session_state->value().grid_view, - local_index, - getPayload(compact_statement)); + l.grid_tracker.learned_fresh_statement( + per_relay_parent.per_session_state->value().groups, + *per_relay_parent.per_session_state->value().grid_view, + local_index, + getPayload(compact_statement)); } circulate_statement(relay_parent, per_relay_parent, compact_statement); diff --git a/core/parachain/validator/parachain_processor.hpp b/core/parachain/validator/parachain_processor.hpp index 9bd080d455..238b8cf42f 100644 --- a/core/parachain/validator/parachain_processor.hpp +++ b/core/parachain/validator/parachain_processor.hpp @@ -16,6 +16,7 @@ #include "application/app_configuration.hpp" #include "authority_discovery/query/query.hpp" +#include "common/ref_cache.hpp" #include "common/visitor.hpp" #include "crypto/hasher.hpp" #include "metrics/metrics.hpp" @@ -40,7 +41,6 @@ #include "primitives/event_types.hpp" #include "utils/non_copyable.hpp" #include "utils/safe_object.hpp" -#include "common/ref_cache.hpp" namespace kagome::common { class MainThreadPool; @@ -251,9 +251,9 @@ namespace kagome::parachain { }; struct PerSessionState { - runtime::SessionInfo session_info; - Groups groups; - std::optional grid_view; + runtime::SessionInfo session_info; + Groups groups; + std::optional grid_view; }; struct RelayParentState { @@ -261,7 +261,8 @@ namespace kagome::parachain { std::optional assigned_core; std::optional assigned_para; std::vector> validator_to_group; - std::shared_ptr::RefObj> per_session_state; + std::shared_ptr::RefObj> + per_session_state; std::optional seconded; std::optional our_index; From 2daab4e505b7e040d5d8560acb3f4b184b2920b3 Mon Sep 17 00:00:00 2001 From: iceseer Date: Mon, 15 Apr 2024 12:12:41 +0300 Subject: [PATCH 06/71] small fix Signed-off-by: iceseer --- core/parachain/validator/impl/parachain_processor.cpp | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/core/parachain/validator/impl/parachain_processor.cpp b/core/parachain/validator/impl/parachain_processor.cpp index 61fc34bb87..f946834c51 100644 --- a/core/parachain/validator/impl/parachain_processor.cpp +++ b/core/parachain/validator/impl/parachain_processor.cpp @@ -551,8 +551,17 @@ namespace kagome::parachain { } new_leaf_fragment_tree_updates(relay_parent); + // need to lock removing session infoes + std::vector< + std::shared_ptr::RefObj>> + _keeper_; + _keeper_.reserve(event.lost.size()); + for (const auto &lost : event.lost) { SL_TRACE(logger_, "Removed backing task.(relay parent={})", lost); + if (auto relay_parent_state = tryGetStateByRelayParent(lost)) { + _keeper_.emplace_back(relay_parent_state->get().per_session_state); + } our_current_state_.per_leaf.erase(lost); our_current_state_.implicit_view->deactivate_leaf(lost); From 670086041fb91f6daae0435fedaae29cbf92f781 Mon Sep 17 00:00:00 2001 From: iceseer Date: Mon, 15 Apr 2024 14:10:09 +0300 Subject: [PATCH 07/71] fixup! Signed-off-by: iceseer --- core/common/ref_cache.hpp | 2 +- .../validator/impl/parachain_processor.cpp | 22 ++++++++++++------- 2 files changed, 15 insertions(+), 9 deletions(-) diff --git a/core/common/ref_cache.hpp b/core/common/ref_cache.hpp index 47ab5137e8..b72036ca4b 100644 --- a/core/common/ref_cache.hpp +++ b/core/common/ref_cache.hpp @@ -118,4 +118,4 @@ namespace kagome { Container items_; }; -} // namespace kagome \ No newline at end of file +} // namespace kagome diff --git a/core/parachain/validator/impl/parachain_processor.cpp b/core/parachain/validator/impl/parachain_processor.cpp index f946834c51..7dc57bee05 100644 --- a/core/parachain/validator/impl/parachain_processor.cpp +++ b/core/parachain/validator/impl/parachain_processor.cpp @@ -805,11 +805,11 @@ namespace kagome::parachain { grid::makeViews(session_info.validator_groups, session_info.active_validator_indices, validator_index); + Groups g{session_info.validator_groups, minimum_backing_votes}; return RefCache::RefObj( PerSessionState{ .session_info = std::move(session_info), - .groups = Groups{session_info.validator_groups, - minimum_backing_votes}, + .groups = std::move(g), .grid_view = grid_view, }); }); @@ -869,8 +869,11 @@ namespace kagome::parachain { std::unordered_map authority_lookup; - for (ValidatorIndex v = 0; v < session_info->discovery_keys.size(); ++v) { - authority_lookup[session_info->discovery_keys[v]] = v; + for (ValidatorIndex v = 0; + v < per_session_state->value().session_info.discovery_keys.size(); + ++v) { + authority_lookup[per_session_state->value() + .session_info.discovery_keys[v]] = v; } std::optional statement_store; @@ -4040,10 +4043,13 @@ namespace kagome::parachain { const SignedFullStatementWithPVD &statement) { const CandidateHash candidate_hash = candidateHashFrom(getPayload(statement)); - SL_TRACE(logger_, - "Sharing statement. (relay parent={}, candidate hash={})", - relay_parent, - candidate_hash); + SL_TRACE( + logger_, + "Sharing statement. (relay parent={}, candidate hash={}, our_index={}, statement_ix={})", + relay_parent, + candidate_hash, + *per_relay_parent.our_index, + statement.payload.ix); BOOST_ASSERT(per_relay_parent.our_index); From f6c20fa8ddcaa49d5c06de6de722d0ef58182b37 Mon Sep 17 00:00:00 2001 From: iceseer Date: Thu, 2 May 2024 11:36:32 +0300 Subject: [PATCH 08/71] send my view and inc use count Signed-off-by: iceseer --- core/network/peer_state.hpp | 15 ++++ .../validator/impl/parachain_processor.cpp | 77 ++++++++++++++++++- .../validator/parachain_processor.hpp | 8 ++ 3 files changed, 97 insertions(+), 3 deletions(-) diff --git a/core/network/peer_state.hpp b/core/network/peer_state.hpp index e9fc9dddf5..0f4f3fd710 100644 --- a/core/network/peer_state.hpp +++ b/core/network/peer_state.hpp @@ -66,6 +66,7 @@ namespace kagome::network { LruSet known_grandpa_messages{ kPeerStateMaxKnownGrandpaMessages, }; + uint32_t use_count = 0; /// @brief parachain peer state std::optional collator_state = std::nullopt; @@ -95,6 +96,20 @@ namespace kagome::network { return fresh_implicit; } + /** + * Set of functions to manipulate in-parachain set of nodes. + */ + bool can_be_disconnected() const { + return 0 == use_count; + } + void inc_use_count() { + ++use_count; + } + void dec_use_count() { + BOOST_ASSERT(use_count > 0); + --use_count; + } + /// Whether we know that a peer knows a relay-parent. The peer knows the /// relay-parent if it is either implicit or explicit in their view. /// However, if it is implicit via an active-leaf we don't recognize, we diff --git a/core/parachain/validator/impl/parachain_processor.cpp b/core/parachain/validator/impl/parachain_processor.cpp index 7dc57bee05..01f4bea529 100644 --- a/core/parachain/validator/impl/parachain_processor.cpp +++ b/core/parachain/validator/impl/parachain_processor.cpp @@ -756,6 +756,57 @@ namespace kagome::parachain { return outcome::success(); } + void ParachainProcessorImpl::spawn_and_update_peer(ValidatorIndex vi) { + if (auto peer = query_audi_->get(vi)) { + tryOpenOutgoingValidationStream( + peer->id, + network::CollationVersion::VStaging, + [wptr{weak_from_this()}, peer_id{peer->id}](auto &&stream) { + if (auto self = wptr.lock()) { + auto ps = self->pm_->getPeerState(peer_id); + BOOST_ASSERT(ps); + + ps->get().inc_use_count(); + self->sendMyView( + peer_id, + stream, + self->router_->getValidationProtocolVStaging()); + } + }); + } + } + + ParachainProcessorImpl::PerSessionState::~PerSessionState() { + if (our_index) { + if (auto our_group = groups.byValidatorIndex(*our_index)) { + if (const auto group = groups.get(*our_group)) { + auto dec_use_count_for_peer = [&](ValidatorIndex vi) { + if (auto peer = query_audi->get(vi)) { + auto ps = pm->getPeerState(peer->id); + BOOST_ASSERT(ps); + ps->get().dec_use_count(); + } + }; + + /// update peers of our group + for (const auto vi : *group) { + dec_use_count_for_peer(vi); + } + + /// update peers in grid view + BOOST_ASSERT(*our_group < grid_view.size()); + const auto &view = grid_view[*our_group]; + for (const auto vi : view.sending) { + dec_use_count_for_peer(vi); + } + for (const auto vi : view.receiving) { + dec_use_count_for_peer(vi); + } + } + } + } + } + outcome::result ParachainProcessorImpl::initNewBackingTask( const primitives::BlockHash &relay_parent) { @@ -798,19 +849,39 @@ namespace kagome::parachain { auto per_session_state = per_session_->get_or_insert( session_index, - [validator_index{validator->validatorIndex()}, - minimum_backing_votes, - session_info{std::move(*session_info)}]() mutable { + [&]() { + const auto validator_index{validator->validatorIndex()}; grid::Views grid_view = grid::makeViews(session_info.validator_groups, session_info.active_validator_indices, validator_index); Groups g{session_info.validator_groups, minimum_backing_votes}; + if (auto our_group = g.byValidatorIndex(validator_index)) { + /// update peers of our group + const auto &group = session_info.validator_groups[*our_group]; + for (const auto vi : group) { + spawn_and_update_peer(vi); + } + + /// update peers in grid view + BOOST_ASSERT(*our_group < grid_view.size()); + const auto &view = grid_view[*our_group]; + for (const auto vi : view.sending) { + spawn_and_update_peer(vi); + } + for (const auto vi : view.receiving) { + spawn_and_update_peer(vi); + } + } + return RefCache::RefObj( PerSessionState{ .session_info = std::move(session_info), .groups = std::move(g), .grid_view = grid_view, + .our_index = validator_index, + .pm = pm_, + .query_audi = query_audi_, }); }); diff --git a/core/parachain/validator/parachain_processor.hpp b/core/parachain/validator/parachain_processor.hpp index 238b8cf42f..31ebabbf39 100644 --- a/core/parachain/validator/parachain_processor.hpp +++ b/core/parachain/validator/parachain_processor.hpp @@ -254,6 +254,12 @@ namespace kagome::parachain { runtime::SessionInfo session_info; Groups groups; std::optional grid_view; + std::optional our_index; + + std::shared_ptr pm; + std::shared_ptr query_audi; + + ~PerSessionState(); }; struct RelayParentState { @@ -649,6 +655,8 @@ namespace kagome::parachain { outcome::result initNewBackingTask( const primitives::BlockHash &relay_parent); + void spawn_and_update_peer(ValidatorIndex vi); + template bool tryOpenOutgoingCollatingStream(const libp2p::peer::PeerId &peer_id, F &&callback); From 277a2b8b411e5815990090b8588194436807f085 Mon Sep 17 00:00:00 2001 From: iceseer Date: Thu, 2 May 2024 11:54:51 +0300 Subject: [PATCH 09/71] undisconnectable peers Signed-off-by: iceseer --- core/network/peer_state.hpp | 2 +- .../validator/impl/parachain_processor.cpp | 128 +++++++++--------- .../validator/parachain_processor.hpp | 2 +- 3 files changed, 66 insertions(+), 66 deletions(-) diff --git a/core/network/peer_state.hpp b/core/network/peer_state.hpp index 0f4f3fd710..6c18576ac9 100644 --- a/core/network/peer_state.hpp +++ b/core/network/peer_state.hpp @@ -97,7 +97,7 @@ namespace kagome::network { } /** - * Set of functions to manipulate in-parachain set of nodes. + * Set of functions to manipulate in-parachain set of nodes. */ bool can_be_disconnected() const { return 0 == use_count; diff --git a/core/parachain/validator/impl/parachain_processor.cpp b/core/parachain/validator/impl/parachain_processor.cpp index 01f4bea529..80cbedfaa9 100644 --- a/core/parachain/validator/impl/parachain_processor.cpp +++ b/core/parachain/validator/impl/parachain_processor.cpp @@ -756,46 +756,49 @@ namespace kagome::parachain { return outcome::success(); } - void ParachainProcessorImpl::spawn_and_update_peer(ValidatorIndex vi) { - if (auto peer = query_audi_->get(vi)) { + void ParachainProcessorImpl::spawn_and_update_peer( + const primitives::AuthorityDiscoveryId &id) { + if (auto peer = query_audi_->get(id)) { tryOpenOutgoingValidationStream( - peer->id, - network::CollationVersion::VStaging, - [wptr{weak_from_this()}, peer_id{peer->id}](auto &&stream) { - if (auto self = wptr.lock()) { - auto ps = self->pm_->getPeerState(peer_id); - BOOST_ASSERT(ps); + peer->id, + network::CollationVersion::VStaging, + [wptr{weak_from_this()}, peer_id{peer->id}](auto &&stream) { + if (auto self = wptr.lock()) { + auto ps = self->pm_->getPeerState(peer_id); + BOOST_ASSERT(ps); - ps->get().inc_use_count(); - self->sendMyView( - peer_id, - stream, - self->router_->getValidationProtocolVStaging()); - } - }); + ps->get().inc_use_count(); + self->sendMyView(peer_id, + stream, + self->router_->getValidationProtocolVStaging()); + } + }); } } ParachainProcessorImpl::PerSessionState::~PerSessionState() { if (our_index) { if (auto our_group = groups.byValidatorIndex(*our_index)) { - if (const auto group = groups.get(*our_group)) { - auto dec_use_count_for_peer = [&](ValidatorIndex vi) { - if (auto peer = query_audi->get(vi)) { - auto ps = pm->getPeerState(peer->id); - BOOST_ASSERT(ps); - ps->get().dec_use_count(); - } - }; + BOOST_ASSERT(*our_group < session_info.validator_groups.size()); + const auto &group = session_info.validator_groups[*our_group]; - /// update peers of our group - for (const auto vi : *group) { - dec_use_count_for_peer(vi); + auto dec_use_count_for_peer = [&](ValidatorIndex vi) { + if (auto peer = query_audi->get(session_info.discovery_keys[vi])) { + auto ps = pm->getPeerState(peer->id); + BOOST_ASSERT(ps); + ps->get().dec_use_count(); } + }; - /// update peers in grid view - BOOST_ASSERT(*our_group < grid_view.size()); - const auto &view = grid_view[*our_group]; + /// update peers of our group + for (const auto vi : group) { + dec_use_count_for_peer(vi); + } + + /// update peers in grid view + if (grid_view) { + BOOST_ASSERT(*our_group < grid_view->size()); + const auto &view = (*grid_view)[*our_group]; for (const auto vi : view.sending) { dec_use_count_for_peer(vi); } @@ -847,43 +850,40 @@ namespace kagome::parachain { relay_parent); } - auto per_session_state = per_session_->get_or_insert( - session_index, - [&]() { - const auto validator_index{validator->validatorIndex()}; - grid::Views grid_view = - grid::makeViews(session_info.validator_groups, - session_info.active_validator_indices, - validator_index); - Groups g{session_info.validator_groups, minimum_backing_votes}; - if (auto our_group = g.byValidatorIndex(validator_index)) { - /// update peers of our group - const auto &group = session_info.validator_groups[*our_group]; - for (const auto vi : group) { - spawn_and_update_peer(vi); - } + auto per_session_state = per_session_->get_or_insert(session_index, [&]() { + const auto validator_index{validator->validatorIndex()}; + grid::Views grid_view = + grid::makeViews(session_info->validator_groups, + session_info->active_validator_indices, + validator_index); + Groups g{session_info->validator_groups, minimum_backing_votes}; + if (auto our_group = g.byValidatorIndex(validator_index)) { + /// update peers of our group + const auto &group = session_info->validator_groups[*our_group]; + for (const auto vi : group) { + spawn_and_update_peer(session_info->discovery_keys[vi]); + } - /// update peers in grid view - BOOST_ASSERT(*our_group < grid_view.size()); - const auto &view = grid_view[*our_group]; - for (const auto vi : view.sending) { - spawn_and_update_peer(vi); - } - for (const auto vi : view.receiving) { - spawn_and_update_peer(vi); - } - } + /// update peers in grid view + BOOST_ASSERT(*our_group < grid_view.size()); + const auto &view = grid_view[*our_group]; + for (const auto vi : view.sending) { + spawn_and_update_peer(session_info->discovery_keys[vi]); + } + for (const auto vi : view.receiving) { + spawn_and_update_peer(session_info->discovery_keys[vi]); + } + } - return RefCache::RefObj( - PerSessionState{ - .session_info = std::move(session_info), - .groups = std::move(g), - .grid_view = grid_view, - .our_index = validator_index, - .pm = pm_, - .query_audi = query_audi_, - }); - }); + return RefCache::RefObj(PerSessionState{ + .session_info = *session_info, + .groups = std::move(g), + .grid_view = grid_view, + .our_index = validator_index, + .pm = pm_, + .query_audi = query_audi_, + }); + }); auto mode = prospective_parachains_->prospectiveParachainsMode(relay_parent); diff --git a/core/parachain/validator/parachain_processor.hpp b/core/parachain/validator/parachain_processor.hpp index 31ebabbf39..31d06a2b17 100644 --- a/core/parachain/validator/parachain_processor.hpp +++ b/core/parachain/validator/parachain_processor.hpp @@ -655,7 +655,7 @@ namespace kagome::parachain { outcome::result initNewBackingTask( const primitives::BlockHash &relay_parent); - void spawn_and_update_peer(ValidatorIndex vi); + void spawn_and_update_peer(const primitives::AuthorityDiscoveryId &id); template bool tryOpenOutgoingCollatingStream(const libp2p::peer::PeerId &peer_id, From d9ac5a8935f560b3a1224a96957db7d98d3cd92e Mon Sep 17 00:00:00 2001 From: iceseer Date: Wed, 17 Apr 2024 11:39:34 +0300 Subject: [PATCH 10/71] statements store test Signed-off-by: iceseer --- .../core/parachain/prospective_parachains.cpp | 27 +++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/test/core/parachain/prospective_parachains.cpp b/test/core/parachain/prospective_parachains.cpp index de59c7e8e9..69359c1075 100644 --- a/test/core/parachain/prospective_parachains.cpp +++ b/test/core/parachain/prospective_parachains.cpp @@ -3141,3 +3141,30 @@ TEST_F(ProspectiveParachainsTest, Candidates_testHypotheticalFrontiers) { != hypotheticals.end()); } } + +TEST_F(ProspectiveParachainsTest, StatementsStore_always_provides_fresh_statements_in_order) { + const ValidatorIndex validator_a{1}; + const ValidatorIndex validator_b{2}; + const auto candidate_hash = fromNumber(42); + + //SecondedCandidateHash, ValidCandidateHash + const network::vstaging::CompactStatement valid_statement{ + network::vstaging::ValidCandidateHash { + .hash = candidate_hash, + } + }; + const network::vstaging::CompactStatement seconded_statement{ + network::vstaging::SecondedCandidateHash { + .hash = candidate_hash, + } + }; + + const SigningContext res_sc{ + .session_index = 1, + .relay_parent = fromNumber(0), + }; + + const Groups groups({{validator_a, validator_b}}, 2); + StatementStore store(groups); + +} From 195ddc469bfbde36303870e79274dc89aa68cea4 Mon Sep 17 00:00:00 2001 From: iceseer Date: Wed, 17 Apr 2024 13:20:22 +0300 Subject: [PATCH 11/71] logs Signed-off-by: iceseer --- core/parachain/validator/impl/parachain_processor.cpp | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/core/parachain/validator/impl/parachain_processor.cpp b/core/parachain/validator/impl/parachain_processor.cpp index 80cbedfaa9..08dbc9cb8b 100644 --- a/core/parachain/validator/impl/parachain_processor.cpp +++ b/core/parachain/validator/impl/parachain_processor.cpp @@ -1597,7 +1597,7 @@ namespace kagome::parachain { BOOST_ASSERT(relay_parent_state.statement_store); SL_TRACE(logger_, - "Handling incoming manifest common {} out of view", + "Handling incoming acknowledgement. (relay_parent={})", relay_parent); ManifestImportSuccessOpt x = handle_incoming_manifest_common( peer_id, @@ -1614,7 +1614,7 @@ namespace kagome::parachain { return; } - SL_TRACE(logger_, "Check local validator {} out of view", relay_parent); + SL_TRACE(logger_, "Check local validator. (relay_parent = {})", relay_parent); if (!relay_parent_state.local_validator) { return; } @@ -1622,7 +1622,7 @@ namespace kagome::parachain { const auto sender_index = x->sender_index; auto &local_validator = *relay_parent_state.local_validator; - SL_TRACE(logger_, "Post ack {} out of view", relay_parent); + SL_TRACE(logger_, "Post ack. (relay_parent = {})", relay_parent); auto messages = post_acknowledgement_statement_messages( sender_index, relay_parent, @@ -1635,7 +1635,7 @@ namespace kagome::parachain { network::CollationVersion::VStaging); if (!messages.empty()) { auto se = pm_->getStreamEngine(); - SL_TRACE(logger_, "Sending messages {} out of view", relay_parent); + SL_TRACE(logger_, "Sending messages. (relay_parent = {})", relay_parent); for (auto &msg : messages) { if (auto m = if_type(msg)) { @@ -3080,6 +3080,7 @@ namespace kagome::parachain { std::vector ParachainProcessorImpl::getBackedCandidates(const RelayHash &relay_parent) { BOOST_ASSERT(main_pool_handler_->isInCurrentThread()); + SL_TRACE(logger_, "Get backed candidates. (relay_parent={})", relay_parent); auto relay_parent_state_opt = tryGetStateByRelayParent(relay_parent); if (!relay_parent_state_opt) { From e81fdc15e431210fef7720077d9947c9008a0d9f Mon Sep 17 00:00:00 2001 From: iceseer Date: Wed, 17 Apr 2024 13:26:28 +0300 Subject: [PATCH 12/71] logs Signed-off-by: iceseer --- .../validator/impl/parachain_processor.cpp | 32 ++++++++++++++++++- 1 file changed, 31 insertions(+), 1 deletion(-) diff --git a/core/parachain/validator/impl/parachain_processor.cpp b/core/parachain/validator/impl/parachain_processor.cpp index 08dbc9cb8b..cd6f6bb153 100644 --- a/core/parachain/validator/impl/parachain_processor.cpp +++ b/core/parachain/validator/impl/parachain_processor.cpp @@ -1614,7 +1614,8 @@ namespace kagome::parachain { return; } - SL_TRACE(logger_, "Check local validator. (relay_parent = {})", relay_parent); + SL_TRACE( + logger_, "Check local validator. (relay_parent = {})", relay_parent); if (!relay_parent_state.local_validator) { return; } @@ -3135,6 +3136,13 @@ namespace kagome::parachain { relay_parent, core_idx); continue; + } else { + SL_TRACE( + logger_, + "Have backable candidate returned by prospective parachains. " + "(relay_parent={}, core_idx={})", + relay_parent, + core_idx); } const CandidateHash &c_hash = response->first; @@ -3142,6 +3150,12 @@ namespace kagome::parachain { auto per_relay_state = tryGetStateByRelayParent(r_hash); if (!per_relay_state) { + SL_TRACE(logger_, + "No relay parent state. " + "(relay_parent={}, r_state={}, core_idx={})", + relay_parent, + r_hash, + core_idx); continue; } @@ -3153,7 +3167,23 @@ namespace kagome::parachain { if (auto b = table_attested_to_backed( std::move(*attested), per_relay_state->get().table_context)) { backed.emplace_back(std::move(*b)); + } else { + SL_TRACE(logger_, + "Candidate not attested -> backed. " + "(relay_parent={}, r_state={}, c_hash={}, core_idx={})", + relay_parent, + r_hash, + c_hash, + core_idx); } + } else { + SL_TRACE(logger_, + "Candidate not attested. " + "(relay_parent={}, r_state={}, c_hash={}, core_idx={})", + relay_parent, + r_hash, + c_hash, + core_idx); } } return backed; From 2771593c27d56372415f37f1a402525bac463e6e Mon Sep 17 00:00:00 2001 From: iceseer Date: Wed, 17 Apr 2024 14:11:44 +0300 Subject: [PATCH 13/71] fixup! Signed-off-by: iceseer --- core/parachain/validator/impl/parachain_processor.cpp | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/core/parachain/validator/impl/parachain_processor.cpp b/core/parachain/validator/impl/parachain_processor.cpp index cd6f6bb153..625bd20a86 100644 --- a/core/parachain/validator/impl/parachain_processor.cpp +++ b/core/parachain/validator/impl/parachain_processor.cpp @@ -3200,6 +3200,10 @@ namespace kagome::parachain { const auto &validity_votes = data.validity_votes; const auto valid_votes = validity_votes.size(); if (valid_votes < validity_threshold) { + SL_TRACE(logger_, + "Under threshold. (valid_votes={}, validity_threshold={})", + valid_votes, + validity_threshold); return std::nullopt; } @@ -3248,10 +3252,17 @@ namespace kagome::parachain { if (auto it = context.groups.find(data.group_id); it != context.groups.end()) { len = it->second.size(); + } else { + SL_TRACE(logger_, + "No table group. (relay_parent={}, group_id={})", + relay_parent, + data.group_id); } const auto v_threshold = std::min(len, size_t(minimum_backing_votes)); return attested(data.candidate, data, v_threshold); + } else { + SL_TRACE(logger_, "No candidate info. (relay_parent={})", relay_parent); } return std::nullopt; } From 51f97fa003b6db57a31d62080ff4b753f830f7e9 Mon Sep 17 00:00:00 2001 From: iceseer Date: Thu, 18 Apr 2024 11:35:51 +0300 Subject: [PATCH 14/71] easy fixup Signed-off-by: iceseer --- core/parachain/validator/impl/parachain_processor.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/core/parachain/validator/impl/parachain_processor.cpp b/core/parachain/validator/impl/parachain_processor.cpp index 625bd20a86..7a7f6cca65 100644 --- a/core/parachain/validator/impl/parachain_processor.cpp +++ b/core/parachain/validator/impl/parachain_processor.cpp @@ -4776,14 +4776,14 @@ namespace kagome::parachain { if (prospective_candidate) { auto &&[ch, parent_head_data_hash] = *prospective_candidate; - const bool is_seconding_allowed = !relay_parent_mode - || canSecond(per_relay_parent, + const bool queue_advertisement = relay_parent_mode + && !canSecond(per_relay_parent, collator_para_id, relay_parent, ch, parent_head_data_hash); - if (!is_seconding_allowed) { + if (queue_advertisement) { SL_TRACE(logger_, "Seconding is not allowed by backing, queueing advertisement. " "(candidate hash={}, relay_parent = {}, para id={})", From bf6c1f99fe5713a3f3892112a89d359e58c1991e Mon Sep 17 00:00:00 2001 From: iceseer Date: Thu, 18 Apr 2024 22:57:27 +0300 Subject: [PATCH 15/71] fixup Signed-off-by: iceseer --- .../validator/impl/statements_store.hpp | 2 + .../core/parachain/prospective_parachains.cpp | 98 +++++++++++++++---- 2 files changed, 79 insertions(+), 21 deletions(-) diff --git a/core/parachain/validator/impl/statements_store.hpp b/core/parachain/validator/impl/statements_store.hpp index 21d706b695..0924c4052c 100644 --- a/core/parachain/validator/impl/statements_store.hpp +++ b/core/parachain/validator/impl/statements_store.hpp @@ -171,6 +171,8 @@ namespace kagome::parachain { .hash = candidate_hash, }, }); + } + for (const auto &vi : validators) { call(Fingerprint{ .index = vi, .statement = diff --git a/test/core/parachain/prospective_parachains.cpp b/test/core/parachain/prospective_parachains.cpp index 69359c1075..0b300e596e 100644 --- a/test/core/parachain/prospective_parachains.cpp +++ b/test/core/parachain/prospective_parachains.cpp @@ -11,6 +11,8 @@ #include "testutil/prepare_loggers.hpp" #include "crypto/hasher/hasher_impl.hpp" +#include "crypto/random_generator/boost_generator.hpp" +#include "crypto/sr25519/sr25519_provider_impl.hpp" #include "crypto/type_hasher.hpp" #include "mock/core/blockchain/block_tree_mock.hpp" #include "mock/core/runtime/parachain_host_mock.hpp" @@ -19,6 +21,7 @@ #include "parachain/validator/impl/candidates.hpp" #include "parachain/validator/parachain_processor.hpp" #include "parachain/validator/prospective_parachains.hpp" +#include "parachain/validator/signer.hpp" #include "runtime/runtime_api/parachain_host_types.hpp" #include "scale/kagome_scale.hpp" #include "scale/scale.hpp" @@ -104,6 +107,7 @@ class ProspectiveParachainsTest : public testing::Test { block_tree_ = std::make_shared(); prospective_parachain_ = std::make_shared( hasher_, parachain_api_, block_tree_); + sr25519_provider_ = std::make_shared(); } void TearDown() override { @@ -121,6 +125,7 @@ class ProspectiveParachainsTest : public testing::Test { std::shared_ptr parachain_api_; std::shared_ptr block_tree_; std::shared_ptr prospective_parachain_; + std::shared_ptr sr25519_provider_; static constexpr uint64_t ALLOWED_ANCESTRY_LEN = 3ull; static constexpr uint32_t MAX_POV_SIZE = 1000000; @@ -3142,29 +3147,80 @@ TEST_F(ProspectiveParachainsTest, Candidates_testHypotheticalFrontiers) { } } -TEST_F(ProspectiveParachainsTest, StatementsStore_always_provides_fresh_statements_in_order) { - const ValidatorIndex validator_a{1}; - const ValidatorIndex validator_b{2}; - const auto candidate_hash = fromNumber(42); +TEST_F(ProspectiveParachainsTest, + StatementsStore_always_provides_fresh_statements_in_order) { + const ValidatorIndex validator_a{1}; + const ValidatorIndex validator_b{2}; + const auto candidate_hash = fromNumber(42); + + // SecondedCandidateHash, ValidCandidateHash + const network::vstaging::CompactStatement valid_statement{ + network::vstaging::ValidCandidateHash{ + .hash = candidate_hash, + }}; + const network::vstaging::CompactStatement seconded_statement{ + network::vstaging::SecondedCandidateHash{ + .hash = candidate_hash, + }}; - //SecondedCandidateHash, ValidCandidateHash - const network::vstaging::CompactStatement valid_statement{ - network::vstaging::ValidCandidateHash { - .hash = candidate_hash, - } - }; - const network::vstaging::CompactStatement seconded_statement{ - network::vstaging::SecondedCandidateHash { - .hash = candidate_hash, - } - }; + const Groups groups( + std::vector>{{validator_a, validator_b}}, 2); + StatementStore store(groups); + + kagome::parachain::IndexedAndSigned + signed_valid_by_a{ + .payload = + { + .payload = valid_statement, + .ix = validator_a, + }, + .signature = {}, + }; + store.insert(groups, signed_valid_by_a, StatementOrigin::Remote); + + kagome::parachain::IndexedAndSigned + signed_seconded_by_b{ + .payload = + { + .payload = seconded_statement, + .ix = validator_b, + }, + .signature = {}, + }; + store.insert(groups, signed_seconded_by_b, StatementOrigin::Remote); - const SigningContext res_sc{ - .session_index = 1, - .relay_parent = fromNumber(0), - }; + { + std::vector vals = {validator_a, validator_b}; + std::vector> + statements; + store.fresh_statements_for_backing( + vals, + candidate_hash, + [&](const kagome::parachain::IndexedAndSigned< + network::vstaging::CompactStatement> &statement) { + statements.emplace_back(statement); + }); + ASSERT_EQ(statements.size(), 2); + ASSERT_EQ(statements[0].payload.payload, seconded_statement); + ASSERT_EQ(statements[1].payload.payload, valid_statement); + } - const Groups groups({{validator_a, validator_b}}, 2); - StatementStore store(groups); + { + std::vector vals = {validator_b, validator_a}; + std::vector> + statements; + store.fresh_statements_for_backing( + vals, + candidate_hash, + [&](const kagome::parachain::IndexedAndSigned< + network::vstaging::CompactStatement> &statement) { + statements.emplace_back(statement); + }); + ASSERT_EQ(statements.size(), 2); + ASSERT_EQ(statements[0].payload.payload, seconded_statement); + ASSERT_EQ(statements[1].payload.payload, valid_statement); + } } From 26a9e8a605e7dc4c6af5454c886e79e59cc203a2 Mon Sep 17 00:00:00 2001 From: iceseer Date: Fri, 19 Apr 2024 22:32:52 +0300 Subject: [PATCH 16/71] request statements from peer transmitted us a manifest Signed-off-by: iceseer --- .../validator/impl/parachain_processor.cpp | 39 ++++++++----------- .../validator/parachain_processor.hpp | 2 +- 2 files changed, 18 insertions(+), 23 deletions(-) diff --git a/core/parachain/validator/impl/parachain_processor.cpp b/core/parachain/validator/impl/parachain_processor.cpp index 7a7f6cca65..b3ced1c110 100644 --- a/core/parachain/validator/impl/parachain_processor.cpp +++ b/core/parachain/validator/impl/parachain_processor.cpp @@ -1764,7 +1764,7 @@ namespace kagome::parachain { "Request attested candidate. (relay_parent={}, candidate_hash={})", manifest.relay_parent, manifest.candidate_hash); - request_attested_candidate(relay_parent_state->get(), + request_attested_candidate(peer_id, relay_parent_state->get(), manifest.relay_parent, manifest.candidate_hash, manifest.group_index); @@ -1864,7 +1864,7 @@ namespace kagome::parachain { const auto &group = session_info.validator_groups[*originator_group]; if (!is_confirmed) { - request_attested_candidate(parachain_state->get(), + request_attested_candidate(peer_id, parachain_state->get(), stm.relay_parent, candidate_hash, *originator_group); @@ -2016,6 +2016,7 @@ namespace kagome::parachain { } void ParachainProcessorImpl::request_attested_candidate( + const libp2p::peer::PeerId &peer, RelayParentState &relay_parent_state, const RelayHash &relay_parent, const CandidateHash &candidate_hash, @@ -2062,18 +2063,14 @@ namespace kagome::parachain { "Enumerate peers. (relay_parent={}, candidate_hash={})", relay_parent, candidate_hash); - std::optional>> - target; - pm_->enumeratePeerState([&](const libp2p::peer::PeerId &peer, - network::PeerState &peer_state) { + std::optional target; auto audi = query_audi_->get(peer); if (!audi) { SL_TRACE(logger_, "No audi. (relay_parent={}, candidate_hash={})", relay_parent, candidate_hash); - return true; + return; } ValidatorIndex validator_id = 0; @@ -2095,7 +2092,7 @@ namespace kagome::parachain { "No filter. (relay_parent={}, candidate_hash={})", relay_parent, candidate_hash); - return true; + return; } filter->mask_seconded(unwanted_mask.seconded_in_group); @@ -2105,18 +2102,16 @@ namespace kagome::parachain { || (filter->has_seconded() && filter->backing_validators() >= *backing_threshold)) { network::vstaging::StatementFilter f(group->size()); - target.emplace(std::move(f), std::cref(peer)); - return false; + target.emplace(std::move(f)); + } else { + SL_TRACE( + logger_, + "Not pass backing threshold. (relay_parent={}, candidate_hash={})", + relay_parent, + candidate_hash); + return; } - SL_TRACE( - logger_, - "Not pass backing threshold. (relay_parent={}, candidate_hash={})", - relay_parent, - candidate_hash); - return true; - }); - if (!target) { SL_TRACE(logger_, "Target not found. (relay_parent={}, candidate_hash={})", @@ -2125,14 +2120,14 @@ namespace kagome::parachain { return; } - const auto &[um, peer] = *target; + const auto &um = *target; SL_TRACE(logger_, "Requesting. (peer={}, relay_parent={}, candidate_hash={})", - peer.get(), + peer, relay_parent, candidate_hash); router_->getFetchAttestedCandidateProtocol()->doRequest( - peer.get(), + peer, network::vstaging::AttestedCandidateRequest{ .candidate_hash = candidate_hash, .mask = um, diff --git a/core/parachain/validator/parachain_processor.hpp b/core/parachain/validator/parachain_processor.hpp index 31d06a2b17..c446fe4485 100644 --- a/core/parachain/validator/parachain_processor.hpp +++ b/core/parachain/validator/parachain_processor.hpp @@ -383,7 +383,7 @@ namespace kagome::parachain { const RelayHash &relay_parent, const CandidateHash &candidate_hash, GroupIndex group_index); - void request_attested_candidate(RelayParentState &relay_parent_state, + void request_attested_candidate(const libp2p::peer::PeerId &peer, RelayParentState &relay_parent_state, const RelayHash &relay_parent, const CandidateHash &candidate_hash, GroupIndex group_index); From 37992e2c541e0f44ec8edeed0358c459444b9c4e Mon Sep 17 00:00:00 2001 From: iceseer Date: Mon, 22 Apr 2024 15:40:36 +0300 Subject: [PATCH 17/71] fixup Signed-off-by: iceseer --- cmake/Hunter/init.cmake | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/cmake/Hunter/init.cmake b/cmake/Hunter/init.cmake index 08faaf5b20..9a9e64516a 100644 --- a/cmake/Hunter/init.cmake +++ b/cmake/Hunter/init.cmake @@ -26,5 +26,11 @@ set(HUNTER_CACHE_SERVERS CACHE STRING "Binary cache server" ) +# https://hunter.readthedocs.io/en/latest/reference/user-variables.html#hunter-use-cache-servers +# set( +# HUNTER_USE_CACHE_SERVERS NO +# CACHE STRING "Disable binary cache" +# ) + include(${CMAKE_CURRENT_LIST_DIR}/HunterGate.cmake) include(${CMAKE_CURRENT_LIST_DIR}/hunter-gate-url.cmake) From 95f8bc15f5d26d98a0160c1d51b785cacc55501f Mon Sep 17 00:00:00 2001 From: iceseer Date: Mon, 22 Apr 2024 16:59:56 +0300 Subject: [PATCH 18/71] formatting Signed-off-by: iceseer --- .../validator/impl/parachain_processor.cpp | 89 ++++++++++--------- .../validator/parachain_processor.hpp | 3 +- 2 files changed, 47 insertions(+), 45 deletions(-) diff --git a/core/parachain/validator/impl/parachain_processor.cpp b/core/parachain/validator/impl/parachain_processor.cpp index b3ced1c110..e1941c621a 100644 --- a/core/parachain/validator/impl/parachain_processor.cpp +++ b/core/parachain/validator/impl/parachain_processor.cpp @@ -1764,7 +1764,8 @@ namespace kagome::parachain { "Request attested candidate. (relay_parent={}, candidate_hash={})", manifest.relay_parent, manifest.candidate_hash); - request_attested_candidate(peer_id, relay_parent_state->get(), + request_attested_candidate(peer_id, + relay_parent_state->get(), manifest.relay_parent, manifest.candidate_hash, manifest.group_index); @@ -1864,7 +1865,8 @@ namespace kagome::parachain { const auto &group = session_info.validator_groups[*originator_group]; if (!is_confirmed) { - request_attested_candidate(peer_id, parachain_state->get(), + request_attested_candidate(peer_id, + parachain_state->get(), stm.relay_parent, candidate_hash, *originator_group); @@ -2016,7 +2018,7 @@ namespace kagome::parachain { } void ParachainProcessorImpl::request_attested_candidate( - const libp2p::peer::PeerId &peer, + const libp2p::peer::PeerId &peer, RelayParentState &relay_parent_state, const RelayHash &relay_parent, const CandidateHash &candidate_hash, @@ -2064,53 +2066,52 @@ namespace kagome::parachain { relay_parent, candidate_hash); std::optional target; - auto audi = query_audi_->get(peer); - if (!audi) { - SL_TRACE(logger_, - "No audi. (relay_parent={}, candidate_hash={})", - relay_parent, - candidate_hash); - return; - } - - ValidatorIndex validator_id = 0; - for (; validator_id < session_info.discovery_keys.size(); - ++validator_id) { - if (session_info.discovery_keys[validator_id] == *audi) { - SL_TRACE(logger_, - "Captured validator. (relay_parent={}, candidate_hash={})", - relay_parent, - candidate_hash); - break; - } - } + auto audi = query_audi_->get(peer); + if (!audi) { + SL_TRACE(logger_, + "No audi. (relay_parent={}, candidate_hash={})", + relay_parent, + candidate_hash); + return; + } - auto filter = local_validator.grid_tracker.advertised_statements( - validator_id, candidate_hash); - if (!filter) { + ValidatorIndex validator_id = 0; + for (; validator_id < session_info.discovery_keys.size(); ++validator_id) { + if (session_info.discovery_keys[validator_id] == *audi) { SL_TRACE(logger_, - "No filter. (relay_parent={}, candidate_hash={})", + "Captured validator. (relay_parent={}, candidate_hash={})", relay_parent, candidate_hash); - return; + break; } + } - filter->mask_seconded(unwanted_mask.seconded_in_group); - filter->mask_valid(unwanted_mask.validated_in_group); + auto filter = local_validator.grid_tracker.advertised_statements( + validator_id, candidate_hash); + if (!filter) { + SL_TRACE(logger_, + "No filter. (relay_parent={}, candidate_hash={})", + relay_parent, + candidate_hash); + return; + } - if (!backing_threshold - || (filter->has_seconded() - && filter->backing_validators() >= *backing_threshold)) { - network::vstaging::StatementFilter f(group->size()); - target.emplace(std::move(f)); - } else { - SL_TRACE( - logger_, - "Not pass backing threshold. (relay_parent={}, candidate_hash={})", - relay_parent, - candidate_hash); - return; - } + filter->mask_seconded(unwanted_mask.seconded_in_group); + filter->mask_valid(unwanted_mask.validated_in_group); + + if (!backing_threshold + || (filter->has_seconded() + && filter->backing_validators() >= *backing_threshold)) { + network::vstaging::StatementFilter f(group->size()); + target.emplace(std::move(f)); + } else { + SL_TRACE( + logger_, + "Not pass backing threshold. (relay_parent={}, candidate_hash={})", + relay_parent, + candidate_hash); + return; + } if (!target) { SL_TRACE(logger_, @@ -4772,7 +4773,7 @@ namespace kagome::parachain { if (prospective_candidate) { auto &&[ch, parent_head_data_hash] = *prospective_candidate; const bool queue_advertisement = relay_parent_mode - && !canSecond(per_relay_parent, + && !canSecond(per_relay_parent, collator_para_id, relay_parent, ch, diff --git a/core/parachain/validator/parachain_processor.hpp b/core/parachain/validator/parachain_processor.hpp index c446fe4485..fd8ec8af14 100644 --- a/core/parachain/validator/parachain_processor.hpp +++ b/core/parachain/validator/parachain_processor.hpp @@ -383,7 +383,8 @@ namespace kagome::parachain { const RelayHash &relay_parent, const CandidateHash &candidate_hash, GroupIndex group_index); - void request_attested_candidate(const libp2p::peer::PeerId &peer, RelayParentState &relay_parent_state, + void request_attested_candidate(const libp2p::peer::PeerId &peer, + RelayParentState &relay_parent_state, const RelayHash &relay_parent, const CandidateHash &candidate_hash, GroupIndex group_index); From 413260b158df4e0cfb721c9dfe66e5d8f7de8c88 Mon Sep 17 00:00:00 2001 From: iceseer Date: Tue, 23 Apr 2024 10:58:33 +0300 Subject: [PATCH 19/71] additional logs Signed-off-by: iceseer --- core/parachain/validator/impl/parachain_processor.cpp | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/core/parachain/validator/impl/parachain_processor.cpp b/core/parachain/validator/impl/parachain_processor.cpp index e1941c621a..e452adde62 100644 --- a/core/parachain/validator/impl/parachain_processor.cpp +++ b/core/parachain/validator/impl/parachain_processor.cpp @@ -1165,6 +1165,9 @@ namespace kagome::parachain { BOOST_ASSERT_MSG( bd, "BitfieldDistribution is not present. Check message format."); + SL_TRACE(logger_, + "Incoming `BitfieldDistributionMessage`. (relay_parent={})", + bd->relay_parent); auto parachain_state = tryGetStateByRelayParent(bd->relay_parent); if (!parachain_state) { return; @@ -2557,12 +2560,8 @@ namespace kagome::parachain { process_vstaging_statement(peer_id, val); }, [&](const auto &) {}); - }); - - // if (auto - // msg{boost::get(&message)}) { - // return; - // } + }, + [&](const auto &m) { SL_WARN(logger_, "UNSUPPORTED Version"); }); } template From 4a7c28d4a49c01e09460594c446eef93cb20d629 Mon Sep 17 00:00:00 2001 From: iceseer Date: Fri, 26 Apr 2024 10:35:46 +0300 Subject: [PATCH 20/71] rename Signed-off-by: iceseer --- core/parachain/backing/store_impl.cpp | 22 +++++++--------------- core/parachain/backing/store_impl.hpp | 4 ++-- 2 files changed, 9 insertions(+), 17 deletions(-) diff --git a/core/parachain/backing/store_impl.cpp b/core/parachain/backing/store_impl.cpp index fc9bc35ed3..1a4b4eae8f 100644 --- a/core/parachain/backing/store_impl.cpp +++ b/core/parachain/backing/store_impl.cpp @@ -37,19 +37,14 @@ namespace kagome::parachain { std::ignore = per_relay_parent_[relay_parent]; } - bool BackingStoreImpl::is_in_group( + bool BackingStoreImpl::is_member_of( const std::unordered_map> &groups, GroupIndex group, - ValidatorIndex authority) { - if (auto it = groups.find(group); it != groups.end()) { - for (const auto a : it->second) { - if (a == authority) { - return true; - } - } - } - return false; + ValidatorIndex authority) const { + const auto it = groups.find(group); + return it != groups.end() && + std::find(it->second.begin(), it->second.end(), authority) != it->second.end(); } outcome::result> @@ -66,7 +61,7 @@ namespace kagome::parachain { } BackingStore::StatementInfo &votes = it->second; - if (!is_in_group(groups, votes.group_id, from)) { + if (!is_member_of(groups, votes.group_id, from)) { return Error::UNAUTHORIZED_STATEMENT; } @@ -95,10 +90,7 @@ namespace kagome::parachain { const network::CommittedCandidateReceipt &candidate, const ValidatorSignature &signature, bool allow_multiple_seconded) { - if (auto it = groups.find(group_id); - it == groups.end() - || std::find(it->second.begin(), it->second.end(), authority) - == it->second.end()) { + if (!is_member_of(groups, group_id, authority)) { return Error::UNAUTHORIZED_STATEMENT; } diff --git a/core/parachain/backing/store_impl.hpp b/core/parachain/backing/store_impl.hpp index 7949e649b3..3d678f70c2 100644 --- a/core/parachain/backing/store_impl.hpp +++ b/core/parachain/backing/store_impl.hpp @@ -72,11 +72,11 @@ namespace kagome::parachain { } } - bool is_in_group( + bool is_member_of( const std::unordered_map> &groups, GroupIndex group, - ValidatorIndex authority); + ValidatorIndex authority) const; outcome::result> validity_vote( PerRelayParent &state, From fdd64a54a2c1c69433e7017dc0c3bb791bbfffd2 Mon Sep 17 00:00:00 2001 From: iceseer Date: Fri, 26 Apr 2024 15:38:55 +0300 Subject: [PATCH 21/71] BackedCandidate fixes Signed-off-by: iceseer --- core/network/types/collator_messages.hpp | 30 ++++++++++++++++++++++++ 1 file changed, 30 insertions(+) diff --git a/core/network/types/collator_messages.hpp b/core/network/types/collator_messages.hpp index 7079179232..2176267d41 100644 --- a/core/network/types/collator_messages.hpp +++ b/core/network/types/collator_messages.hpp @@ -206,6 +206,36 @@ namespace kagome::network { CommittedCandidateReceipt candidate; std::vector validity_votes; scale::BitVec validator_indices; + + static BackedCandidate from( + CommittedCandidateReceipt candidate_, + std::vector validity_votes_, + scale::BitVec validator_indices_, + std::optional core_index_ + ) { + BackedCandidate backed { + .candidate = std::move(candidate_), + .validity_votes = std::move(validity_votes_), + .validator_indices = std::move(validator_indices_), + }; + + if (core_index_) { + backed.inject_core_index(*core_index_); + } + + return backed; + } + + void inject_core_index(CoreIndex core_index) { + scale::BitVec core_index_to_inject; + core_index_to_inject.bits.assign(8, false); + + auto val = uint8_t(core_index); + for (size_t i = 0; i < 8; ++i) { + core_index_to_inject.bits[i] = ((1 << i) & val) >> i; + } + validator_indices.bits.insert(validator_indices.bits.end(), core_index_to_inject.bits.begin(), core_index_to_inject.bits.end()); + } }; using CandidateState = From 990cbd3d081e468be6f5de508292c8b781123579 Mon Sep 17 00:00:00 2001 From: iceseer Date: Sat, 27 Apr 2024 09:15:58 +0300 Subject: [PATCH 22/71] - ParachainHost_node_features - inject_core_index usage Signed-off-by: iceseer --- .../validator/impl/parachain_processor.cpp | 36 ++++++++++++------- .../validator/parachain_processor.hpp | 4 ++- .../runtime_api/impl/parachain_host.cpp | 13 +++++++ .../runtime_api/impl/parachain_host.hpp | 3 ++ core/runtime/runtime_api/parachain_host.hpp | 22 ++++++++++++ 5 files changed, 64 insertions(+), 14 deletions(-) diff --git a/core/parachain/validator/impl/parachain_processor.cpp b/core/parachain/validator/impl/parachain_processor.cpp index e452adde62..9b10c85a65 100644 --- a/core/parachain/validator/impl/parachain_processor.cpp +++ b/core/parachain/validator/impl/parachain_processor.cpp @@ -838,6 +838,13 @@ namespace kagome::parachain { return Error::NO_SESSION_INFO; } + bool inject_core_index = false; + if (auto r = parachain_host_->node_features(relay_parent, session_index); r.has_value()) { + if (r.value() && r.value()->bits.size() > runtime::ParachainHost::NodeFeatureIndex::ElasticScalingMVP) { + inject_core_index = r.value()->bits[runtime::ParachainHost::NodeFeatureIndex::ElasticScalingMVP]; + } + } + uint32_t minimum_backing_votes = 2; /// legacy value if (auto r = parachain_host_->minimum_backing_votes(relay_parent, session_index); @@ -990,6 +997,7 @@ namespace kagome::parachain { .issued_statements = {}, .peers_advertised = {}, .fallbacks = {}, + .inject_core_index = inject_core_index, }; } @@ -3160,7 +3168,7 @@ namespace kagome::parachain { per_relay_state->get().table_context, per_relay_state->get().minimum_backing_votes)) { if (auto b = table_attested_to_backed( - std::move(*attested), per_relay_state->get().table_context)) { + std::move(*attested), per_relay_state->get().table_context, per_relay_state->get().inject_core_index)) { backed.emplace_back(std::move(*b)); } else { SL_TRACE(logger_, @@ -3264,10 +3272,13 @@ namespace kagome::parachain { std::optional ParachainProcessorImpl::table_attested_to_backed( - AttestedCandidate &&attested, TableContext &table_context) { - const auto para_id = attested.group_id; - if (auto it = table_context.groups.find(para_id); - it != table_context.groups.end()) { + AttestedCandidate &&attested, TableContext &table_context, bool inject_core_index) { + const auto core_index = attested.group_id; + auto it = table_context.groups.find(core_index); + if (it == table_context.groups.end()) { + return std::nullopt; + } + const auto &group = it->second; scale::BitVec validator_indices{}; validator_indices.bits.resize(group.size(), false); @@ -3310,13 +3321,12 @@ namespace kagome::parachain { std::move(attested.validity_votes[pos_in_votes].second)); } - return BackingStore::BackedCandidate{ - .candidate = std::move(attested.candidate), - .validity_votes = std::move(validity_votes), - .validator_indices = std::move(validator_indices), - }; - } - return std::nullopt; + return BackingStore::BackedCandidate::from( + std::move(attested.candidate), + std::move(validity_votes), + std::move(validator_indices), + inject_core_index ? std::optional{core_index} : std::optional{} + ); } outcome::result> @@ -3634,7 +3644,7 @@ namespace kagome::parachain { .insert(candidateHash(*hasher_, attested->candidate)) .second) { if (auto backed = table_attested_to_backed(std::move(*attested), - rp_state.table_context)) { + rp_state.table_context, rp_state.inject_core_index)) { const auto para_id = backed->candidate.descriptor.para_id; SL_INFO( logger_, diff --git a/core/parachain/validator/parachain_processor.hpp b/core/parachain/validator/parachain_processor.hpp index fd8ec8af14..3910942045 100644 --- a/core/parachain/validator/parachain_processor.hpp +++ b/core/parachain/validator/parachain_processor.hpp @@ -289,6 +289,8 @@ namespace kagome::parachain { std::unordered_set peers_advertised; std::unordered_map fallbacks; std::unordered_set backed_hashes{}; + + bool inject_core_index; }; struct PerCandidateState { @@ -462,7 +464,7 @@ namespace kagome::parachain { const BackingStore::StatementInfo &data, size_t validity_threshold); std::optional table_attested_to_backed( - AttestedCandidate &&attested, TableContext &table_context); + AttestedCandidate &&attested, TableContext &table_context, bool inject_core_index); outcome::result> isParachainValidator( const primitives::BlockHash &relay_parent) const; diff --git a/core/runtime/runtime_api/impl/parachain_host.cpp b/core/runtime/runtime_api/impl/parachain_host.cpp index 82147ccf71..4548d08cc7 100644 --- a/core/runtime/runtime_api/impl/parachain_host.cpp +++ b/core/runtime/runtime_api/impl/parachain_host.cpp @@ -292,4 +292,17 @@ namespace kagome::runtime { return res; } + outcome::result> ParachainHostImpl::node_features( + const primitives::BlockHash &block, SessionIndex index) { + OUTCOME_TRY(ctx, executor_->ctx().ephemeralAt(block)); + auto res = executor_->call>( + ctx, "ParachainHost_node_features"); + if (res.has_error() + and res.error() == RuntimeExecutionError::EXPORT_FUNCTION_NOT_FOUND) { + return outcome::success(std::nullopt); + } + return res; + } + + } // namespace kagome::runtime diff --git a/core/runtime/runtime_api/impl/parachain_host.hpp b/core/runtime/runtime_api/impl/parachain_host.hpp index 33960381d4..8300c53516 100644 --- a/core/runtime/runtime_api/impl/parachain_host.hpp +++ b/core/runtime/runtime_api/impl/parachain_host.hpp @@ -115,6 +115,9 @@ namespace kagome::runtime { outcome::result> disabled_validators( const primitives::BlockHash &block) override; + outcome::result> node_features( + const primitives::BlockHash &block, SessionIndex index) override; + private: bool prepare(); void clearCaches(const std::vector &blocks); diff --git a/core/runtime/runtime_api/parachain_host.hpp b/core/runtime/runtime_api/parachain_host.hpp index 86db0c37bd..e4d5de0302 100644 --- a/core/runtime/runtime_api/parachain_host.hpp +++ b/core/runtime/runtime_api/parachain_host.hpp @@ -23,6 +23,25 @@ namespace kagome::runtime { public: virtual ~ParachainHost() = default; + using NodeFeatures = scale::BitVec; + /// A feature index used to identify a bit into the node_features array stored + /// in the HostConfiguration. + enum NodeFeatureIndex { + /// Tells if tranch0 assignments could be sent in a single certificate. + /// Reserved for: `` + EnableAssignmentsV2 = 0, + + /// This feature enables the extension of `BackedCandidate::validator_indices` by 8 bits. + /// The value stored there represents the assumed core index where the candidates + /// are backed. This is needed for the elastic scaling MVP. + ElasticScalingMVP = 1, + + /// First unassigned feature bit. + /// Every time a new feature flag is assigned it should take this value. + /// and this should be incremented. + FirstUnassigned = 2, + }; + /** * @brief Calls the ParachainHost_active_parachains function from wasm code * @return vector of ParachainId items or error if fails @@ -225,6 +244,9 @@ namespace kagome::runtime { /// Returns a list of all disabled validators at the given block. virtual outcome::result> disabled_validators( const primitives::BlockHash &block) = 0; + + virtual outcome::result> node_features( + const primitives::BlockHash &block, SessionIndex index) = 0; }; } // namespace kagome::runtime From 629f13605466c02667d8acd2a3d04ec304bc1778 Mon Sep 17 00:00:00 2001 From: iceseer Date: Sun, 28 Apr 2024 18:15:18 +0300 Subject: [PATCH 23/71] - ParachainHost_node_features - inject_core_index usage Signed-off-by: iceseer # Conflicts: # core/parachain/validator/impl/parachain_processor.cpp --- .../validator/impl/parachain_processor.cpp | 263 ++++++++++++------ .../validator/parachain_processor.hpp | 10 +- 2 files changed, 193 insertions(+), 80 deletions(-) diff --git a/core/parachain/validator/impl/parachain_processor.cpp b/core/parachain/validator/impl/parachain_processor.cpp index 9b10c85a65..de334fe740 100644 --- a/core/parachain/validator/impl/parachain_processor.cpp +++ b/core/parachain/validator/impl/parachain_processor.cpp @@ -115,7 +115,8 @@ namespace kagome::parachain { primitives::events::ChainSubscriptionEnginePtr chain_sub_engine, primitives::events::BabeStateSubscriptionEnginePtr babe_status_observable, std::shared_ptr query_audi, - std::shared_ptr prospective_parachains) + std::shared_ptr prospective_parachains, + std::shared_ptr block_tree) : pm_(std::move(pm)), runtime_info_(std::move(runtime_info)), crypto_provider_(std::move(crypto_provider)), @@ -137,7 +138,8 @@ namespace kagome::parachain { per_session_(RefCache::create()), chain_sub_{std::move(chain_sub_engine)}, worker_pool_handler_{worker_thread_pool.handler(app_state_manager)}, - prospective_parachains_{std::move(prospective_parachains)} { + prospective_parachains_{std::move(prospective_parachains)}, + block_tree_{std::move(block_tree)} { BOOST_ASSERT(pm_); BOOST_ASSERT(peer_view_); BOOST_ASSERT(crypto_provider_); @@ -155,6 +157,7 @@ namespace kagome::parachain { BOOST_ASSERT(query_audi_); BOOST_ASSERT(prospective_parachains_); BOOST_ASSERT(worker_pool_handler_); + BOOST_ASSERT(block_tree_); app_state_manager.takeControl(*this); our_current_state_.implicit_view.emplace(prospective_parachains_); @@ -2346,6 +2349,7 @@ namespace kagome::parachain { } } + /// TODO(iceseer): do remove std::optional ParachainProcessorImpl::group_for_para( const std::vector &availability_cores, const runtime::GroupDescriptor &group_rotation_info, @@ -3081,6 +3085,46 @@ namespace kagome::parachain { confirmed.para_id(), confirmed.para_head()); } + outcome::result ParachainProcessorImpl::get_block_number_under_construction(const RelayHash &relay_parent) const { + BOOST_ASSERT(main_pool_handler_->isInCurrentThread()); + + auto res_header = block_tree_->getBlockHeader(relay_parent); + if (res_header.has_error()) { + if (res_header.error() == blockchain::BlockTreeError::HEADER_NOT_FOUND) { + return 0; + } + return res_header.error(); + } + return res_header.value().number + 1; + } + + bool ParachainProcessorImpl::bitfields_indicate_availability( + size_t core_idx, + const std::vector &bitfields, + const scale::BitVec &availability_ + ) { + scale::BitVec availability{availability_}; + const auto availability_len = availability.bits.size(); + + for (const auto &bitfield : bitfields) { + const auto validator_idx{size_t(bitfield.payload.ix)}; + if (validator_idx >= availability.bits.size()) { + SL_WARN(logger_, + "attempted to set a transverse bit at idx which is greater than bitfield size. (validator_idx={}, availability_len={})", + validator_idx, + availability_len + ); + + return false; + } + + availability.bits[validator_idx] = availability.bits[validator_idx] || bitfield.payload.payload.bits[core_idx]; + } + + return 3 * approval::count_ones(availability) >= 2 * availability.bits.size(); + } + + std::vector ParachainProcessorImpl::getBackedCandidates(const RelayHash &relay_parent) { BOOST_ASSERT(main_pool_handler_->isInCurrentThread()); @@ -3091,108 +3135,160 @@ namespace kagome::parachain { return {}; } - if (relay_parent_state_opt->get().prospective_parachains_mode) { - std::vector backed; - for (size_t core_idx = 0; - core_idx < relay_parent_state_opt->get().availability_cores.size(); - ++core_idx) { - const runtime::CoreState &core = - relay_parent_state_opt->get().availability_cores[core_idx]; - std::optional> response = visit_in_place( - core, - [&](const network::ScheduledCore &scheduled_core) - -> std::optional> { - if (auto i = prospective_parachains_->answerGetBackableCandidates( - relay_parent, scheduled_core.para_id, 1, {}); - !i.empty()) { - return i[0]; - } - return std::nullopt; - }, - [&](const runtime::OccupiedCore &occupied_core) - -> std::optional> { - /// TODO(iceseer): do https://github.com/qdrvm/kagome/issues/1888 - /// `bitfields_indicate_availability` check + if (!relay_parent_state_opt->get().prospective_parachains_mode) { + return backing_store_->get(relay_parent); + } + + BlockNumber block_number; + if (auto r = get_block_number_under_construction(relay_parent); r.has_error()) { + return {}; + } else { + block_number = r.value(); + } + + using Ancestors = std::unordered_set; + const auto &availability_cores = relay_parent_state_opt->get().availability_cores; + + std::map scheduled_cores_per_para; + std::unordered_map ancestors; + ancestors.reserve(availability_cores.size()); + + const auto elastic_scaling_mvp = relay_parent_state_opt->get().inject_core_index; + const auto bitfields = bitfield_store_->getBitfields(relay_parent); + const auto cores_len = relay_parent_state_opt->get().availability_cores.size(); + + for (size_t core_idx = 0; core_idx < cores_len; ++core_idx) { + const runtime::CoreState &core = relay_parent_state_opt->get().availability_cores[core_idx]; + visit_in_place( + core, + [&](const network::ScheduledCore &scheduled_core) { + scheduled_cores_per_para[scheduled_core.para_id] += 1; + }, + [&](const runtime::OccupiedCore &occupied_core) { + const bool is_available = bitfields_indicate_availability(core_idx, bitfields, occupied_core.availability); + if (is_available) { + ancestors[occupied_core.candidate_descriptor.para_id].insert(occupied_core.candidate_hash); if (occupied_core.next_up_on_available) { - if (auto i = - prospective_parachains_->answerGetBackableCandidates( - relay_parent, - occupied_core.next_up_on_available->para_id, - 1, - {occupied_core.candidate_hash}); - !i.empty()) { - return i[0]; - } - return std::nullopt; + scheduled_cores_per_para[occupied_core.next_up_on_available->para_id] += 1; } - return std::nullopt; - }, - [&](const runtime::FreeCore &) - -> std::optional> { - return std::nullopt; - }); + } else if (occupied_core.time_out_at <= block_number) { + if (occupied_core.next_up_on_time_out) { + scheduled_cores_per_para[occupied_core.next_up_on_time_out->para_id] += 1; + } + } else { + ancestors[occupied_core.candidate_descriptor.para_id].insert(occupied_core.candidate_hash); + } + }, + [&](const runtime::FreeCore &) { + }); + } - if (!response) { - SL_TRACE(logger_, - "No backable candidate returned by prospective parachains. " - "(relay_parent={}, core_idx={})", - relay_parent, - core_idx); - continue; - } else { - SL_TRACE( - logger_, - "Have backable candidate returned by prospective parachains. " - "(relay_parent={}, core_idx={})", - relay_parent, - core_idx); - } + std::unordered_map>> selected_candidates; + selected_candidates.reserve(scheduled_cores_per_para.size()); + + auto ancestor_remove = [&] (ParachainId para_id) -> Ancestors { + auto it = ancestors.find(para_id); + if (it == ancestors.end()) { + return {}; + } + + auto result{std::move(it->second)}; + ancestors.erase(it); + return result; + }; + + for (const auto &[para_id, core_count] : scheduled_cores_per_para) { + auto para_ancestors = ancestor_remove(para_id); + if (!elastic_scaling_mvp && core_count > 1) { + continue; + } + + std::vector para_ancestors_vec( + std::move_iterator(para_ancestors.begin()), + std::move_iterator(para_ancestors.end()) + ); + auto response = prospective_parachains_->answerGetBackableCandidates( + relay_parent, + para_id, + core_count, + para_ancestors_vec); + + if (response.empty()) { + SL_TRACE(logger_, "No backable candidate returned by prospective parachains. (relay_parent={}, para_id={})", relay_parent, para_id); + continue; + } + + selected_candidates.emplace(para_id, std::move(response)); + } + SL_TRACE(logger_, "Got backable candidates. (count={})", selected_candidates.size()); - const CandidateHash &c_hash = response->first; - const RelayHash &r_hash = response->second; + std::unordered_map> backed; + backed.reserve(selected_candidates.size()); - auto per_relay_state = tryGetStateByRelayParent(r_hash); - if (!per_relay_state) { + for (const auto &[para_id, para_candidates] : selected_candidates) { + for (const auto &[c_hash, r_hash] : para_candidates) { + auto rp_state = tryGetStateByRelayParent(r_hash); + if (!rp_state) { SL_TRACE(logger_, - "No relay parent state. " - "(relay_parent={}, r_state={}, core_idx={})", + "Requested candidate's relay parent is out of view. (relay_parent={}, r_hash={}, c_hash={})", relay_parent, r_hash, - core_idx); - continue; + c_hash); + break; } if (auto attested = attested_candidate( r_hash, c_hash, - per_relay_state->get().table_context, - per_relay_state->get().minimum_backing_votes)) { + rp_state->get().table_context, + rp_state->get().minimum_backing_votes)) { if (auto b = table_attested_to_backed( - std::move(*attested), per_relay_state->get().table_context, per_relay_state->get().inject_core_index)) { - backed.emplace_back(std::move(*b)); + std::move(*attested), rp_state->get().table_context, rp_state->get().inject_core_index)) { + backed[para_id].emplace_back(std::move(*b)); } else { SL_TRACE(logger_, "Candidate not attested -> backed. " - "(relay_parent={}, r_state={}, c_hash={}, core_idx={})", + "(relay_parent={}, r_state={}, c_hash={})", relay_parent, r_hash, - c_hash, - core_idx); + c_hash); } } else { SL_TRACE(logger_, "Candidate not attested. " - "(relay_parent={}, r_state={}, c_hash={}, core_idx={})", + "(relay_parent={}, r_state={}, c_hash={})", relay_parent, r_hash, - c_hash, - core_idx); + c_hash); } } - return backed; - } else { - return backing_store_->get(relay_parent); } + + SL_TRACE(logger_, "Got backed candidates. (relay_parent={}, backed_len={})", relay_parent, backed.size()); + bool with_validation_code = false; + std::vector merged_candidates; + merged_candidates.reserve(availability_cores.size()); + + for (const auto &[_, para_candidates] : backed) { + for (const auto &candidate : para_candidates) { + if (candidate.candidate.commitments.opt_para_runtime) { + if (with_validation_code) { + break; + } else { + with_validation_code = true; + } + } + + merged_candidates.emplace_back(candidate); + } + } + + SL_TRACE(logger_, "Selected backed candidates. (n_candidates={}, n_cores={}, relay_parent={})", + merged_candidates.size(), + availability_cores.size(), + relay_parent); + + return merged_candidates; } std::optional @@ -3640,8 +3736,10 @@ namespace kagome::parachain { summary->candidate, rp_state.table_context, rp_state.minimum_backing_votes)) { + const auto candidate_hash{candidateHash(*hasher_, attested->candidate)}; + if (rp_state.backed_hashes - .insert(candidateHash(*hasher_, attested->candidate)) + .insert(candidate_hash) .second) { if (auto backed = table_attested_to_backed(std::move(*attested), rp_state.table_context, rp_state.inject_core_index)) { @@ -3661,8 +3759,14 @@ namespace kagome::parachain { } else { backing_store_->add(relay_parent, std::move(*backed)); } + } else { + SL_TRACE(logger_, "Cannot get BackedCandidate. (candidate_hash={})", candidate_hash); } + } else { + SL_TRACE(logger_, "Candidate already known. (candidate_hash={})", candidate_hash); } + } else { + SL_TRACE(logger_, "No attested candidate."); } } @@ -4342,12 +4446,13 @@ namespace kagome::parachain { relay_parent, n_validators); + const auto candidate_hash{candidate.hash(*hasher_)}; SL_INFO(logger_, "Starting validation task.(para id={}, " - "relay parent={}, peer={})", + "relay parent={}, peer={}, candidate_hash={})", candidate.descriptor.para_id, relay_parent, - peer_id); + peer_id, candidate_hash); auto _measure = std::make_shared("Parachain validation", logger_); const auto candidate_hash{candidate.hash(*hasher_)}; diff --git a/core/parachain/validator/parachain_processor.hpp b/core/parachain/validator/parachain_processor.hpp index 3910942045..3482f72ff8 100644 --- a/core/parachain/validator/parachain_processor.hpp +++ b/core/parachain/validator/parachain_processor.hpp @@ -127,7 +127,8 @@ namespace kagome::parachain { primitives::events::BabeStateSubscriptionEnginePtr babe_status_observable, std::shared_ptr query_audi, - std::shared_ptr prospective_parachains); + std::shared_ptr prospective_parachains, + std::shared_ptr block_tree); ~ParachainProcessorImpl() = default; bool prepare(); @@ -152,6 +153,12 @@ namespace kagome::parachain { outcome::result OnFetchAttestedCandidateRequest( const network::vstaging::AttestedCandidateRequest &request); + outcome::result get_block_number_under_construction(const RelayHash &relay_parent) const; + bool bitfields_indicate_availability( + size_t core_idx, + const std::vector &bitfields, + const scale::BitVec &availability + ); std::vector getBackedCandidates( const RelayHash &relay_parent) override; @@ -772,6 +779,7 @@ namespace kagome::parachain { std::default_random_engine random_; std::shared_ptr prospective_parachains_; Candidates candidates_; + std::shared_ptr block_tree_; metrics::RegistryPtr metrics_registry_ = metrics::createRegistry(); metrics::Gauge *metric_is_parachain_validator_; From 0ea468bc6edfb2a60195414c6e01d80cd907af68 Mon Sep 17 00:00:00 2001 From: iceseer Date: Sun, 28 Apr 2024 21:00:03 +0300 Subject: [PATCH 24/71] formatting Signed-off-by: iceseer --- core/network/types/collator_messages.hpp | 21 +- core/parachain/backing/store_impl.cpp | 5 +- .../validator/impl/parachain_processor.cpp | 254 ++++++++++-------- .../validator/parachain_processor.hpp | 14 +- .../runtime_api/impl/parachain_host.cpp | 6 +- core/runtime/runtime_api/parachain_host.hpp | 33 +-- 6 files changed, 187 insertions(+), 146 deletions(-) diff --git a/core/network/types/collator_messages.hpp b/core/network/types/collator_messages.hpp index 2176267d41..eb0f80d9ce 100644 --- a/core/network/types/collator_messages.hpp +++ b/core/network/types/collator_messages.hpp @@ -208,15 +208,14 @@ namespace kagome::network { scale::BitVec validator_indices; static BackedCandidate from( - CommittedCandidateReceipt candidate_, - std::vector validity_votes_, - scale::BitVec validator_indices_, - std::optional core_index_ - ) { - BackedCandidate backed { - .candidate = std::move(candidate_), - .validity_votes = std::move(validity_votes_), - .validator_indices = std::move(validator_indices_), + CommittedCandidateReceipt candidate_, + std::vector validity_votes_, + scale::BitVec validator_indices_, + std::optional core_index_) { + BackedCandidate backed{ + .candidate = std::move(candidate_), + .validity_votes = std::move(validity_votes_), + .validator_indices = std::move(validator_indices_), }; if (core_index_) { @@ -234,7 +233,9 @@ namespace kagome::network { for (size_t i = 0; i < 8; ++i) { core_index_to_inject.bits[i] = ((1 << i) & val) >> i; } - validator_indices.bits.insert(validator_indices.bits.end(), core_index_to_inject.bits.begin(), core_index_to_inject.bits.end()); + validator_indices.bits.insert(validator_indices.bits.end(), + core_index_to_inject.bits.begin(), + core_index_to_inject.bits.end()); } }; diff --git a/core/parachain/backing/store_impl.cpp b/core/parachain/backing/store_impl.cpp index 1a4b4eae8f..08c2326fd8 100644 --- a/core/parachain/backing/store_impl.cpp +++ b/core/parachain/backing/store_impl.cpp @@ -43,8 +43,9 @@ namespace kagome::parachain { GroupIndex group, ValidatorIndex authority) const { const auto it = groups.find(group); - return it != groups.end() && - std::find(it->second.begin(), it->second.end(), authority) != it->second.end(); + return it != groups.end() + && std::find(it->second.begin(), it->second.end(), authority) + != it->second.end(); } outcome::result> diff --git a/core/parachain/validator/impl/parachain_processor.cpp b/core/parachain/validator/impl/parachain_processor.cpp index de334fe740..0f41b94a96 100644 --- a/core/parachain/validator/impl/parachain_processor.cpp +++ b/core/parachain/validator/impl/parachain_processor.cpp @@ -842,9 +842,14 @@ namespace kagome::parachain { } bool inject_core_index = false; - if (auto r = parachain_host_->node_features(relay_parent, session_index); r.has_value()) { - if (r.value() && r.value()->bits.size() > runtime::ParachainHost::NodeFeatureIndex::ElasticScalingMVP) { - inject_core_index = r.value()->bits[runtime::ParachainHost::NodeFeatureIndex::ElasticScalingMVP]; + if (auto r = parachain_host_->node_features(relay_parent, session_index); + r.has_value()) { + if (r.value() + && r.value()->bits.size() > runtime::ParachainHost::NodeFeatureIndex:: + ElasticScalingMVP) { + inject_core_index = + r.value()->bits + [runtime::ParachainHost::NodeFeatureIndex::ElasticScalingMVP]; } } @@ -3085,7 +3090,9 @@ namespace kagome::parachain { confirmed.para_id(), confirmed.para_head()); } - outcome::result ParachainProcessorImpl::get_block_number_under_construction(const RelayHash &relay_parent) const { + outcome::result + ParachainProcessorImpl::get_block_number_under_construction( + const RelayHash &relay_parent) const { BOOST_ASSERT(main_pool_handler_->isInCurrentThread()); auto res_header = block_tree_->getBlockHeader(relay_parent); @@ -3099,32 +3106,33 @@ namespace kagome::parachain { } bool ParachainProcessorImpl::bitfields_indicate_availability( - size_t core_idx, - const std::vector &bitfields, - const scale::BitVec &availability_ - ) { + size_t core_idx, + const std::vector &bitfields, + const scale::BitVec &availability_) { scale::BitVec availability{availability_}; const auto availability_len = availability.bits.size(); for (const auto &bitfield : bitfields) { const auto validator_idx{size_t(bitfield.payload.ix)}; if (validator_idx >= availability.bits.size()) { - SL_WARN(logger_, - "attempted to set a transverse bit at idx which is greater than bitfield size. (validator_idx={}, availability_len={})", - validator_idx, - availability_len - ); + SL_WARN( + logger_, + "attempted to set a transverse bit at idx which is greater than bitfield size. (validator_idx={}, availability_len={})", + validator_idx, + availability_len); return false; } - availability.bits[validator_idx] = availability.bits[validator_idx] || bitfield.payload.payload.bits[core_idx]; + availability.bits[validator_idx] = + availability.bits[validator_idx] + || bitfield.payload.payload.bits[core_idx]; } - return 3 * approval::count_ones(availability) >= 2 * availability.bits.size(); + return 3 * approval::count_ones(availability) + >= 2 * availability.bits.size(); } - std::vector ParachainProcessorImpl::getBackedCandidates(const RelayHash &relay_parent) { BOOST_ASSERT(main_pool_handler_->isInCurrentThread()); @@ -3139,54 +3147,64 @@ namespace kagome::parachain { return backing_store_->get(relay_parent); } - BlockNumber block_number; - if (auto r = get_block_number_under_construction(relay_parent); r.has_error()) { + BlockNumber block_number; + if (auto r = get_block_number_under_construction(relay_parent); + r.has_error()) { return {}; } else { block_number = r.value(); } using Ancestors = std::unordered_set; - const auto &availability_cores = relay_parent_state_opt->get().availability_cores; + const auto &availability_cores = + relay_parent_state_opt->get().availability_cores; std::map scheduled_cores_per_para; std::unordered_map ancestors; ancestors.reserve(availability_cores.size()); - const auto elastic_scaling_mvp = relay_parent_state_opt->get().inject_core_index; + const auto elastic_scaling_mvp = + relay_parent_state_opt->get().inject_core_index; const auto bitfields = bitfield_store_->getBitfields(relay_parent); - const auto cores_len = relay_parent_state_opt->get().availability_cores.size(); + const auto cores_len = + relay_parent_state_opt->get().availability_cores.size(); for (size_t core_idx = 0; core_idx < cores_len; ++core_idx) { - const runtime::CoreState &core = relay_parent_state_opt->get().availability_cores[core_idx]; + const runtime::CoreState &core = + relay_parent_state_opt->get().availability_cores[core_idx]; visit_in_place( core, [&](const network::ScheduledCore &scheduled_core) { scheduled_cores_per_para[scheduled_core.para_id] += 1; }, [&](const runtime::OccupiedCore &occupied_core) { - const bool is_available = bitfields_indicate_availability(core_idx, bitfields, occupied_core.availability); + const bool is_available = bitfields_indicate_availability( + core_idx, bitfields, occupied_core.availability); if (is_available) { - ancestors[occupied_core.candidate_descriptor.para_id].insert(occupied_core.candidate_hash); + ancestors[occupied_core.candidate_descriptor.para_id].insert( + occupied_core.candidate_hash); if (occupied_core.next_up_on_available) { - scheduled_cores_per_para[occupied_core.next_up_on_available->para_id] += 1; + scheduled_cores_per_para[occupied_core.next_up_on_available + ->para_id] += 1; } } else if (occupied_core.time_out_at <= block_number) { if (occupied_core.next_up_on_time_out) { - scheduled_cores_per_para[occupied_core.next_up_on_time_out->para_id] += 1; + scheduled_cores_per_para[occupied_core.next_up_on_time_out + ->para_id] += 1; } } else { - ancestors[occupied_core.candidate_descriptor.para_id].insert(occupied_core.candidate_hash); + ancestors[occupied_core.candidate_descriptor.para_id].insert( + occupied_core.candidate_hash); } }, - [&](const runtime::FreeCore &) { - }); + [&](const runtime::FreeCore &) {}); } - std::unordered_map>> selected_candidates; + std::unordered_map>> + selected_candidates; selected_candidates.reserve(scheduled_cores_per_para.size()); - auto ancestor_remove = [&] (ParachainId para_id) -> Ancestors { + auto ancestor_remove = [&](ParachainId para_id) -> Ancestors { auto it = ancestors.find(para_id); if (it == ancestors.end()) { return {}; @@ -3204,46 +3222,52 @@ namespace kagome::parachain { } std::vector para_ancestors_vec( - std::move_iterator(para_ancestors.begin()), - std::move_iterator(para_ancestors.end()) - ); + std::move_iterator(para_ancestors.begin()), + std::move_iterator(para_ancestors.end())); auto response = prospective_parachains_->answerGetBackableCandidates( - relay_parent, - para_id, - core_count, - para_ancestors_vec); + relay_parent, para_id, core_count, para_ancestors_vec); if (response.empty()) { - SL_TRACE(logger_, "No backable candidate returned by prospective parachains. (relay_parent={}, para_id={})", relay_parent, para_id); + SL_TRACE( + logger_, + "No backable candidate returned by prospective parachains. (relay_parent={}, para_id={})", + relay_parent, + para_id); continue; } selected_candidates.emplace(para_id, std::move(response)); } - SL_TRACE(logger_, "Got backable candidates. (count={})", selected_candidates.size()); + SL_TRACE(logger_, + "Got backable candidates. (count={})", + selected_candidates.size()); - std::unordered_map> backed; + std::unordered_map> + backed; backed.reserve(selected_candidates.size()); for (const auto &[para_id, para_candidates] : selected_candidates) { for (const auto &[c_hash, r_hash] : para_candidates) { auto rp_state = tryGetStateByRelayParent(r_hash); if (!rp_state) { - SL_TRACE(logger_, - "Requested candidate's relay parent is out of view. (relay_parent={}, r_hash={}, c_hash={})", - relay_parent, - r_hash, - c_hash); + SL_TRACE( + logger_, + "Requested candidate's relay parent is out of view. (relay_parent={}, r_hash={}, c_hash={})", + relay_parent, + r_hash, + c_hash); break; } - if (auto attested = attested_candidate( - r_hash, - c_hash, - rp_state->get().table_context, - rp_state->get().minimum_backing_votes)) { - if (auto b = table_attested_to_backed( - std::move(*attested), rp_state->get().table_context, rp_state->get().inject_core_index)) { + if (auto attested = + attested_candidate(r_hash, + c_hash, + rp_state->get().table_context, + rp_state->get().minimum_backing_votes)) { + if (auto b = + table_attested_to_backed(std::move(*attested), + rp_state->get().table_context, + rp_state->get().inject_core_index)) { backed[para_id].emplace_back(std::move(*b)); } else { SL_TRACE(logger_, @@ -3264,7 +3288,10 @@ namespace kagome::parachain { } } - SL_TRACE(logger_, "Got backed candidates. (relay_parent={}, backed_len={})", relay_parent, backed.size()); + SL_TRACE(logger_, + "Got backed candidates. (relay_parent={}, backed_len={})", + relay_parent, + backed.size()); bool with_validation_code = false; std::vector merged_candidates; merged_candidates.reserve(availability_cores.size()); @@ -3283,10 +3310,12 @@ namespace kagome::parachain { } } - SL_TRACE(logger_, "Selected backed candidates. (n_candidates={}, n_cores={}, relay_parent={})", - merged_candidates.size(), - availability_cores.size(), - relay_parent); + SL_TRACE( + logger_, + "Selected backed candidates. (n_candidates={}, n_cores={}, relay_parent={})", + merged_candidates.size(), + availability_cores.size(), + relay_parent); return merged_candidates; } @@ -3367,62 +3396,62 @@ namespace kagome::parachain { } std::optional - ParachainProcessorImpl::table_attested_to_backed( - AttestedCandidate &&attested, TableContext &table_context, bool inject_core_index) { + ParachainProcessorImpl::table_attested_to_backed(AttestedCandidate &&attested, + TableContext &table_context, + bool inject_core_index) { const auto core_index = attested.group_id; auto it = table_context.groups.find(core_index); if (it == table_context.groups.end()) { return std::nullopt; } - const auto &group = it->second; - scale::BitVec validator_indices{}; - validator_indices.bits.resize(group.size(), false); + const auto &group = it->second; + scale::BitVec validator_indices{}; + validator_indices.bits.resize(group.size(), false); - std::vector> vote_positions; - vote_positions.reserve(attested.validity_votes.size()); + std::vector> vote_positions; + vote_positions.reserve(attested.validity_votes.size()); - auto position = [](const auto &container, - const auto &val) -> std::optional { - for (size_t ix = 0; ix < container.size(); ++ix) { - if (val == container[ix]) { - return ix; - } - } - return std::nullopt; - }; - - for (size_t orig_idx = 0; orig_idx < attested.validity_votes.size(); - ++orig_idx) { - const auto &id = attested.validity_votes[orig_idx].first; - if (auto p = position(group, id)) { - validator_indices.bits[*p] = true; - vote_positions.emplace_back(orig_idx, *p); - } else { - logger_->critical( - "Logic error: Validity vote from table does not correspond to " - "group."); - return std::nullopt; + auto position = [](const auto &container, + const auto &val) -> std::optional { + for (size_t ix = 0; ix < container.size(); ++ix) { + if (val == container[ix]) { + return ix; } } - std::sort( - vote_positions.begin(), - vote_positions.end(), - [](const auto &l, const auto &r) { return l.second < r.second; }); - - std::vector validity_votes; - validity_votes.reserve(vote_positions.size()); - for (const auto &[pos_in_votes, _pos_in_group] : vote_positions) { - validity_votes.emplace_back( - std::move(attested.validity_votes[pos_in_votes].second)); + return std::nullopt; + }; + + for (size_t orig_idx = 0; orig_idx < attested.validity_votes.size(); + ++orig_idx) { + const auto &id = attested.validity_votes[orig_idx].first; + if (auto p = position(group, id)) { + validator_indices.bits[*p] = true; + vote_positions.emplace_back(orig_idx, *p); + } else { + logger_->critical( + "Logic error: Validity vote from table does not correspond to " + "group."); + return std::nullopt; } + } + std::sort(vote_positions.begin(), + vote_positions.end(), + [](const auto &l, const auto &r) { return l.second < r.second; }); + + std::vector validity_votes; + validity_votes.reserve(vote_positions.size()); + for (const auto &[pos_in_votes, _pos_in_group] : vote_positions) { + validity_votes.emplace_back( + std::move(attested.validity_votes[pos_in_votes].second)); + } - return BackingStore::BackedCandidate::from( - std::move(attested.candidate), - std::move(validity_votes), - std::move(validator_indices), - inject_core_index ? std::optional{core_index} : std::optional{} - ); + return BackingStore::BackedCandidate::from( + std::move(attested.candidate), + std::move(validity_votes), + std::move(validator_indices), + inject_core_index ? std::optional{core_index} + : std::optional{}); } outcome::result> @@ -3738,11 +3767,11 @@ namespace kagome::parachain { rp_state.minimum_backing_votes)) { const auto candidate_hash{candidateHash(*hasher_, attested->candidate)}; - if (rp_state.backed_hashes - .insert(candidate_hash) - .second) { - if (auto backed = table_attested_to_backed(std::move(*attested), - rp_state.table_context, rp_state.inject_core_index)) { + if (rp_state.backed_hashes.insert(candidate_hash).second) { + if (auto backed = + table_attested_to_backed(std::move(*attested), + rp_state.table_context, + rp_state.inject_core_index)) { const auto para_id = backed->candidate.descriptor.para_id; SL_INFO( logger_, @@ -3760,10 +3789,14 @@ namespace kagome::parachain { backing_store_->add(relay_parent, std::move(*backed)); } } else { - SL_TRACE(logger_, "Cannot get BackedCandidate. (candidate_hash={})", candidate_hash); + SL_TRACE(logger_, + "Cannot get BackedCandidate. (candidate_hash={})", + candidate_hash); } } else { - SL_TRACE(logger_, "Candidate already known. (candidate_hash={})", candidate_hash); + SL_TRACE(logger_, + "Candidate already known. (candidate_hash={})", + candidate_hash); } } else { SL_TRACE(logger_, "No attested candidate."); @@ -4452,7 +4485,8 @@ namespace kagome::parachain { "relay parent={}, peer={}, candidate_hash={})", candidate.descriptor.para_id, relay_parent, - peer_id, candidate_hash); + peer_id, + candidate_hash); auto _measure = std::make_shared("Parachain validation", logger_); const auto candidate_hash{candidate.hash(*hasher_)}; diff --git a/core/parachain/validator/parachain_processor.hpp b/core/parachain/validator/parachain_processor.hpp index 3482f72ff8..c49409c2dd 100644 --- a/core/parachain/validator/parachain_processor.hpp +++ b/core/parachain/validator/parachain_processor.hpp @@ -153,12 +153,12 @@ namespace kagome::parachain { outcome::result OnFetchAttestedCandidateRequest( const network::vstaging::AttestedCandidateRequest &request); - outcome::result get_block_number_under_construction(const RelayHash &relay_parent) const; + outcome::result get_block_number_under_construction( + const RelayHash &relay_parent) const; bool bitfields_indicate_availability( - size_t core_idx, - const std::vector &bitfields, - const scale::BitVec &availability - ); + size_t core_idx, + const std::vector &bitfields, + const scale::BitVec &availability); std::vector getBackedCandidates( const RelayHash &relay_parent) override; @@ -471,7 +471,9 @@ namespace kagome::parachain { const BackingStore::StatementInfo &data, size_t validity_threshold); std::optional table_attested_to_backed( - AttestedCandidate &&attested, TableContext &table_context, bool inject_core_index); + AttestedCandidate &&attested, + TableContext &table_context, + bool inject_core_index); outcome::result> isParachainValidator( const primitives::BlockHash &relay_parent) const; diff --git a/core/runtime/runtime_api/impl/parachain_host.cpp b/core/runtime/runtime_api/impl/parachain_host.cpp index 4548d08cc7..39d9fae708 100644 --- a/core/runtime/runtime_api/impl/parachain_host.cpp +++ b/core/runtime/runtime_api/impl/parachain_host.cpp @@ -292,8 +292,9 @@ namespace kagome::runtime { return res; } - outcome::result> ParachainHostImpl::node_features( - const primitives::BlockHash &block, SessionIndex index) { + outcome::result> + ParachainHostImpl::node_features(const primitives::BlockHash &block, + SessionIndex index) { OUTCOME_TRY(ctx, executor_->ctx().ephemeralAt(block)); auto res = executor_->call>( ctx, "ParachainHost_node_features"); @@ -304,5 +305,4 @@ namespace kagome::runtime { return res; } - } // namespace kagome::runtime diff --git a/core/runtime/runtime_api/parachain_host.hpp b/core/runtime/runtime_api/parachain_host.hpp index e4d5de0302..e099ca9177 100644 --- a/core/runtime/runtime_api/parachain_host.hpp +++ b/core/runtime/runtime_api/parachain_host.hpp @@ -24,22 +24,25 @@ namespace kagome::runtime { virtual ~ParachainHost() = default; using NodeFeatures = scale::BitVec; - /// A feature index used to identify a bit into the node_features array stored - /// in the HostConfiguration. + /// A feature index used to identify a bit into the node_features array + /// stored in the HostConfiguration. enum NodeFeatureIndex { - /// Tells if tranch0 assignments could be sent in a single certificate. - /// Reserved for: `` - EnableAssignmentsV2 = 0, - - /// This feature enables the extension of `BackedCandidate::validator_indices` by 8 bits. - /// The value stored there represents the assumed core index where the candidates - /// are backed. This is needed for the elastic scaling MVP. - ElasticScalingMVP = 1, - - /// First unassigned feature bit. - /// Every time a new feature flag is assigned it should take this value. - /// and this should be incremented. - FirstUnassigned = 2, + /// Tells if tranch0 assignments could be sent in a single certificate. + /// Reserved for: + /// `` + EnableAssignmentsV2 = 0, + + /// This feature enables the extension of + /// `BackedCandidate::validator_indices` by 8 bits. + /// The value stored there represents the assumed core index where the + /// candidates + /// are backed. This is needed for the elastic scaling MVP. + ElasticScalingMVP = 1, + + /// First unassigned feature bit. + /// Every time a new feature flag is assigned it should take this value. + /// and this should be incremented. + FirstUnassigned = 2, }; /** From bf9ae01db183359f7a5229c4608230793a774cc5 Mon Sep 17 00:00:00 2001 From: iceseer Date: Sun, 28 Apr 2024 21:00:03 +0300 Subject: [PATCH 25/71] formatting Signed-off-by: iceseer From 4235111cf63fa44dc3aa639227ee5af6a4f1719e Mon Sep 17 00:00:00 2001 From: iceseer Date: Fri, 3 May 2024 15:02:41 +0300 Subject: [PATCH 26/71] fixup Signed-off-by: iceseer --- core/parachain/validator/impl/parachain_processor.cpp | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/core/parachain/validator/impl/parachain_processor.cpp b/core/parachain/validator/impl/parachain_processor.cpp index 0f41b94a96..d57d230a54 100644 --- a/core/parachain/validator/impl/parachain_processor.cpp +++ b/core/parachain/validator/impl/parachain_processor.cpp @@ -4488,11 +4488,9 @@ namespace kagome::parachain { peer_id, candidate_hash); - auto _measure = std::make_shared("Parachain validation", logger_); - const auto candidate_hash{candidate.hash(*hasher_)}; - /// TODO(iceseer): do https://github.com/qdrvm/kagome/issues/1888 /// checks if we still need to execute parachain task + auto _measure = std::make_shared("Parachain validation", logger_); auto need_to_process = our_current_state_.active_leaves.count(relay_parent) != 0ull; From 36247397ed3f4d671fa066757f7bad98d421e03a Mon Sep 17 00:00:00 2001 From: Ruslan Tushov Date: Thu, 2 May 2024 13:44:32 +0500 Subject: [PATCH 27/71] fix executor param enum (#2078) Signed-off-by: turuslan Co-authored-by: kamilsa --- core/runtime/runtime_api/parachain_host_types.hpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/core/runtime/runtime_api/parachain_host_types.hpp b/core/runtime/runtime_api/parachain_host_types.hpp index e851613f38..bfd04a84ef 100644 --- a/core/runtime/runtime_api/parachain_host_types.hpp +++ b/core/runtime/runtime_api/parachain_host_types.hpp @@ -325,7 +325,7 @@ namespace kagome::runtime { using InboundDownwardMessage = network::InboundDownwardMessage; using InboundHrmpMessage = network::InboundHrmpMessage; - enum class PvfPrepTimeoutKind { + enum class PvfPrepTimeoutKind : uint8_t { /// For prechecking requests, the time period after which the preparation /// worker is considered /// unresponsive and will be killed. @@ -340,7 +340,7 @@ namespace kagome::runtime { }; /// Type discriminator for PVF execution timeouts - enum class PvfExecTimeoutKind { + enum class PvfExecTimeoutKind : uint8_t { /// The amount of time to spend on execution during backing. Backing, From 03868773d436b49b8dfde32f65996525e77d1075 Mon Sep 17 00:00:00 2001 From: iceseer Date: Mon, 6 May 2024 12:47:36 +0300 Subject: [PATCH 28/71] fixes -> branch ! Signed-off-by: iceseer --- .../validator/impl/parachain_processor.cpp | 31 +++++++++++++------ .../validator/parachain_processor.hpp | 13 ++++++++ .../runtime_api/impl/parachain_host.cpp | 4 +-- 3 files changed, 37 insertions(+), 11 deletions(-) diff --git a/core/parachain/validator/impl/parachain_processor.cpp b/core/parachain/validator/impl/parachain_processor.cpp index d57d230a54..1ca8ee3893 100644 --- a/core/parachain/validator/impl/parachain_processor.cpp +++ b/core/parachain/validator/impl/parachain_processor.cpp @@ -779,8 +779,22 @@ namespace kagome::parachain { } } + ParachainProcessorImpl::PerSessionState::PerSessionState( + const runtime::SessionInfo &_session_info, + Groups &&_groups, + grid::Views &&_grid_view, + ValidatorIndex _our_index, + const std::shared_ptr &_pm, + const std::shared_ptr &_query_audi) + : session_info{_session_info}, + groups{std::move(_groups)}, + grid_view{std::move(_grid_view)}, + our_index{_our_index}, + pm{_pm}, + query_audi{_query_audi} {} + ParachainProcessorImpl::PerSessionState::~PerSessionState() { - if (our_index) { + if (our_index && grid_view) { if (auto our_group = groups.byValidatorIndex(*our_index)) { BOOST_ASSERT(*our_group < session_info.validator_groups.size()); const auto &group = session_info.validator_groups[*our_group]; @@ -890,14 +904,13 @@ namespace kagome::parachain { } } - return RefCache::RefObj(PerSessionState{ - .session_info = *session_info, - .groups = std::move(g), - .grid_view = grid_view, - .our_index = validator_index, - .pm = pm_, - .query_audi = query_audi_, - }); + return RefCache::RefObj( + *session_info, + std::move(g), + std::move(grid_view), + validator_index, + pm_, + query_audi_); }); auto mode = diff --git a/core/parachain/validator/parachain_processor.hpp b/core/parachain/validator/parachain_processor.hpp index c49409c2dd..ab0608b094 100644 --- a/core/parachain/validator/parachain_processor.hpp +++ b/core/parachain/validator/parachain_processor.hpp @@ -258,6 +258,12 @@ namespace kagome::parachain { }; struct PerSessionState { + PerSessionState(const PerSessionState &) = delete; + PerSessionState &operator=(const PerSessionState &) = delete; + + PerSessionState(PerSessionState &&) = default; + PerSessionState &operator=(PerSessionState &&) = delete; + runtime::SessionInfo session_info; Groups groups; std::optional grid_view; @@ -266,6 +272,13 @@ namespace kagome::parachain { std::shared_ptr pm; std::shared_ptr query_audi; + PerSessionState( + const runtime::SessionInfo &_session_info, + Groups &&_groups, + grid::Views &&_grid_view, + ValidatorIndex _our_index, + const std::shared_ptr &_pm, + const std::shared_ptr &_query_audi); ~PerSessionState(); }; diff --git a/core/runtime/runtime_api/impl/parachain_host.cpp b/core/runtime/runtime_api/impl/parachain_host.cpp index 39d9fae708..a70fc0cfdc 100644 --- a/core/runtime/runtime_api/impl/parachain_host.cpp +++ b/core/runtime/runtime_api/impl/parachain_host.cpp @@ -296,13 +296,13 @@ namespace kagome::runtime { ParachainHostImpl::node_features(const primitives::BlockHash &block, SessionIndex index) { OUTCOME_TRY(ctx, executor_->ctx().ephemeralAt(block)); - auto res = executor_->call>( + auto res = executor_->call( ctx, "ParachainHost_node_features"); if (res.has_error() and res.error() == RuntimeExecutionError::EXPORT_FUNCTION_NOT_FOUND) { return outcome::success(std::nullopt); } - return res; + return res.value(); } } // namespace kagome::runtime From 9a446ecbb288ef523c734aa6dbd22e8c526912d1 Mon Sep 17 00:00:00 2001 From: iceseer Date: Mon, 6 May 2024 19:16:11 +0300 Subject: [PATCH 29/71] fixes -> branch ! Signed-off-by: iceseer --- .../validator/impl/parachain_processor.cpp | 38 ++++++++++--------- 1 file changed, 20 insertions(+), 18 deletions(-) diff --git a/core/parachain/validator/impl/parachain_processor.cpp b/core/parachain/validator/impl/parachain_processor.cpp index 1ca8ee3893..8b8dd66479 100644 --- a/core/parachain/validator/impl/parachain_processor.cpp +++ b/core/parachain/validator/impl/parachain_processor.cpp @@ -886,24 +886,6 @@ namespace kagome::parachain { session_info->active_validator_indices, validator_index); Groups g{session_info->validator_groups, minimum_backing_votes}; - if (auto our_group = g.byValidatorIndex(validator_index)) { - /// update peers of our group - const auto &group = session_info->validator_groups[*our_group]; - for (const auto vi : group) { - spawn_and_update_peer(session_info->discovery_keys[vi]); - } - - /// update peers in grid view - BOOST_ASSERT(*our_group < grid_view.size()); - const auto &view = grid_view[*our_group]; - for (const auto vi : view.sending) { - spawn_and_update_peer(session_info->discovery_keys[vi]); - } - for (const auto vi : view.receiving) { - spawn_and_update_peer(session_info->discovery_keys[vi]); - } - } - return RefCache::RefObj( *session_info, std::move(g), @@ -913,6 +895,26 @@ namespace kagome::parachain { query_audi_); }); + if (auto our_group = per_session_state->value().groups.byValidatorIndex( + validator->validatorIndex())) { + /// update peers of our group + const auto &group = session_info->validator_groups[*our_group]; + for (const auto vi : group) { + spawn_and_update_peer(session_info->discovery_keys[vi]); + } + + /// update peers in grid view + const auto &grid_view = *per_session_state->value().grid_view; + BOOST_ASSERT(*our_group < grid_view.size()); + const auto &view = grid_view[*our_group]; + for (const auto vi : view.sending) { + spawn_and_update_peer(session_info->discovery_keys[vi]); + } + for (const auto vi : view.receiving) { + spawn_and_update_peer(session_info->discovery_keys[vi]); + } + } + auto mode = prospective_parachains_->prospectiveParachainsMode(relay_parent); const auto n_cores = cores.size(); From 320254a2ee4a08c68474212a4e44dd6ebf0b93b6 Mon Sep 17 00:00:00 2001 From: iceseer Date: Wed, 8 May 2024 18:00:27 +0300 Subject: [PATCH 30/71] fixes -> branch ! Signed-off-by: iceseer --- .../validator/impl/parachain_processor.cpp | 237 ++++++++++++------ .../validator/parachain_processor.hpp | 18 +- 2 files changed, 177 insertions(+), 78 deletions(-) diff --git a/core/parachain/validator/impl/parachain_processor.cpp b/core/parachain/validator/impl/parachain_processor.cpp index 8b8dd66479..3bc98e1889 100644 --- a/core/parachain/validator/impl/parachain_processor.cpp +++ b/core/parachain/validator/impl/parachain_processor.cpp @@ -562,15 +562,29 @@ namespace kagome::parachain { for (const auto &lost : event.lost) { SL_TRACE(logger_, "Removed backing task.(relay parent={})", lost); - if (auto relay_parent_state = tryGetStateByRelayParent(lost)) { + + auto relay_parent_state = tryGetStateByRelayParent(lost); + if (relay_parent_state) { _keeper_.emplace_back(relay_parent_state->get().per_session_state); } + our_current_state_.active_leaves.erase(lost); + std::vector pruned = [&]() -> std::vector { + if (relay_parent_state->get().prospective_parachains_mode) { + return our_current_state_.implicit_view->deactivate_leaf(lost); + } + return {lost}; + }(); + + for (const auto removed : pruned) { + our_current_state_.state_by_relay_parent.erase(removed); + /// TODO(iceseer): do https://github.com/qdrvm/kagome/issues/1888 + /// fetched_candidates ??? + } + our_current_state_.per_leaf.erase(lost); - our_current_state_.implicit_view->deactivate_leaf(lost); our_current_state_.state_by_relay_parent.erase(lost); pending_candidates.erase(lost); - our_current_state_.active_leaves.erase(lost); } our_current_state_.active_leaves[relay_parent] = prospective_parachains_->prospectiveParachainsMode(relay_parent); @@ -655,6 +669,38 @@ namespace kagome::parachain { } createBackingTask(maybe_new); } + + auto remove_if = [](bool eq, auto &it, auto &cont) { + if (eq) { + it = cont.erase(it); + } else { + ++it; + } + }; + + // para + for (auto it = our_current_state_.blocked_advertisements.begin(); + it != our_current_state_.blocked_advertisements.end();) { + // hash + for (auto it_2 = it->second.begin(); it_2 != it->second.end();) { + // adv + for (auto it_3 = it_2->second.begin(); it_3 != it_2->second.end();) { + remove_if(!tryGetStateByRelayParent(it_3->candidate_relay_parent), + it_3, + it_2->second); + } + remove_if(it_2->second.empty(), it_2, it->second); + } + remove_if( + it->second.empty(), it, our_current_state_.blocked_advertisements); + } + + auto maybe_unblocked = std::move(our_current_state_.blocked_advertisements); + requestUnblockedCollations(std::move(maybe_unblocked)); + + prune_old_advertisements(*our_current_state_.implicit_view, + our_current_state_.active_leaves, + our_current_state_.state_by_relay_parent); } void ParachainProcessorImpl::onDeactivateBlocks( @@ -3660,50 +3706,53 @@ namespace kagome::parachain { if (unblocked) { requestUnblockedCollations( - rp_state, para_id, para_head, std::move(*unblocked)); + {{para_id, {{para_head, std::move(*unblocked)}}}}); } } void ParachainProcessorImpl::requestUnblockedCollations( - ParachainProcessorImpl::RelayParentState &rp_state, - ParachainId para_id, - const Hash ¶_head, - std::vector &&blocked_vec) { - for (auto blocked = blocked_vec.begin(); blocked != blocked_vec.end();) { - const auto is_seconding_allowed = - canSecond(rp_state, - para_id, - blocked->candidate_relay_parent, - blocked->candidate_hash, - para_head); - if (is_seconding_allowed) { - auto result = - enqueueCollation(rp_state, - blocked->candidate_relay_parent, - para_id, - blocked->peer_id, - blocked->collator_id, - std::make_optional(std::make_pair( - blocked->candidate_hash, para_head))); - if (result.has_error()) { - SL_DEBUG(logger_, - "Enqueue collation failed.(candidate={}, para id={}, " - "relay_parent={}, para_head={}, peer_id={})", - blocked->candidate_hash, - para_id, - blocked->candidate_relay_parent, - para_head, - blocked->peer_id); + std::unordered_map< + ParachainId, + std::unordered_map>> + &&blocked) { + for (const auto &[para_id, v] : blocked) { + for (const auto &[para_head, blocked_tmp] : v) { + std::vector blocked_vec; + for (const auto &blocked : blocked_tmp) { + const auto is_seconding_allowed = + canSecond(para_id, + blocked.candidate_relay_parent, + blocked.candidate_hash, + para_head); + if (is_seconding_allowed) { + auto result = + enqueueCollation(blocked.candidate_relay_parent, + para_id, + blocked.peer_id, + blocked.collator_id, + std::make_optional(std::make_pair( + blocked.candidate_hash, para_head))); + if (result.has_error()) { + SL_DEBUG(logger_, + "Enqueue collation failed.(candidate={}, para id={}, " + "relay_parent={}, para_head={}, peer_id={})", + blocked.candidate_hash, + para_id, + blocked.candidate_relay_parent, + para_head, + blocked.peer_id); + } + } else { + blocked_vec.emplace_back(blocked); + } + } + + if (!blocked_vec.empty()) { + our_current_state_.blocked_advertisements[para_id][para_head] = + std::move(blocked_vec); } - blocked = blocked_vec.erase(blocked); - } else { - ++blocked; } } - if (!blocked_vec.empty()) { - our_current_state_.blocked_advertisements[para_id][para_head] = - std::move(blocked_vec); - } } template @@ -4685,6 +4734,43 @@ namespace kagome::parachain { } } + void ParachainProcessorImpl::prune_old_advertisements( + const parachain::ImplicitView &implicit_view, + const std::unordered_map + &active_leaves, + const std::unordered_map + &per_relay_parent) { + pm_->enumeratePeerState( + [&](const libp2p::peer::PeerId &peer, network::PeerState &ps) { + if (ps.collator_state) { + auto &peer_state = *ps.collator_state; + for (auto it = peer_state.advertisements.begin(); + it != peer_state.advertisements.end();) { + const auto &hash = it->first; + + bool res = false; + if (auto i = per_relay_parent.find(hash); + i != per_relay_parent.end()) { + const auto &s = i->second; + res = isRelayParentInImplicitView(hash, + s.prospective_parachains_mode, + implicit_view, + active_leaves, + peer_state.para_id); + } + + if (res) { + ++it; + } else { + it = peer_state.advertisements.erase(it); + } + } + } + + return true; + }); + } + bool ParachainProcessorImpl::isRelayParentInImplicitView( const RelayHash &relay_parent, const ProspectiveParachainsModeOpt &relay_parent_mode, @@ -4835,23 +4921,24 @@ namespace kagome::parachain { return membership; } - bool ParachainProcessorImpl::canSecond( - ParachainProcessorImpl::RelayParentState &per_relay_parent, - ParachainId candidate_para_id, - const Hash &relay_parent, - const CandidateHash &candidate_hash, - const Hash &parent_head_data_hash) { - if (per_relay_parent.prospective_parachains_mode) { - if (auto seconding_allowed = secondingSanityCheck( - HypotheticalCandidateIncomplete{ - .candidate_hash = candidate_hash, - .candidate_para = candidate_para_id, - .parent_head_data_hash = parent_head_data_hash, - .candidate_relay_parent = relay_parent}, - true)) { - for (const auto &[_, m] : *seconding_allowed) { - if (!m.empty()) { - return true; + bool ParachainProcessorImpl::canSecond(ParachainId candidate_para_id, + const Hash &relay_parent, + const CandidateHash &candidate_hash, + const Hash &parent_head_data_hash) { + auto per_relay_parent = tryGetStateByRelayParent(relay_parent); + if (per_relay_parent) { + if (per_relay_parent->get().prospective_parachains_mode) { + if (auto seconding_allowed = secondingSanityCheck( + HypotheticalCandidateIncomplete{ + .candidate_hash = candidate_hash, + .candidate_para = candidate_para_id, + .parent_head_data_hash = parent_head_data_hash, + .candidate_relay_parent = relay_parent}, + true)) { + for (const auto &[_, m] : *seconding_allowed) { + if (!m.empty()) { + return true; + } } } } @@ -4933,12 +5020,10 @@ namespace kagome::parachain { if (prospective_candidate) { auto &&[ch, parent_head_data_hash] = *prospective_candidate; - const bool queue_advertisement = relay_parent_mode - && !canSecond(per_relay_parent, - collator_para_id, - relay_parent, - ch, - parent_head_data_hash); + const bool queue_advertisement = + relay_parent_mode + && !canSecond( + collator_para_id, relay_parent, ch, parent_head_data_hash); if (queue_advertisement) { SL_TRACE(logger_, @@ -4960,8 +5045,7 @@ namespace kagome::parachain { } } - if (auto result = enqueueCollation(per_relay_parent, - relay_parent, + if (auto result = enqueueCollation(relay_parent, para_id, peer_id, collator_id, @@ -4978,7 +5062,6 @@ namespace kagome::parachain { } outcome::result ParachainProcessorImpl::enqueueCollation( - ParachainProcessorImpl::RelayParentState &per_relay_parent, const RelayHash &relay_parent, ParachainId para_id, const libp2p::peer::PeerId &peer_id, @@ -4992,9 +5075,20 @@ namespace kagome::parachain { para_id, relay_parent); + auto per_relay_parent = tryGetStateByRelayParent(relay_parent); + if (!per_relay_parent) { + SL_TRACE( + logger_, + "Candidate relay parent went out of view for valid advertisement. (peer id={}, para id={}, relay parent={})", + peer_id, + para_id, + relay_parent); + return outcome::success(); + } + const auto &relay_parent_mode = - per_relay_parent.prospective_parachains_mode; - auto &collations = per_relay_parent.collations; + per_relay_parent->get().prospective_parachains_mode; + auto &collations = per_relay_parent->get().collations; if (!collations.hasSecondedSpace(relay_parent_mode)) { SL_TRACE(logger_, @@ -5029,14 +5123,15 @@ namespace kagome::parachain { } break; case CollationStatus::Waiting: { fetchCollation( - per_relay_parent, std::move(pending_collation), collator_id); + per_relay_parent->get(), std::move(pending_collation), collator_id); } break; case CollationStatus::Seconded: { if (relay_parent_mode) { // Limit is not reached, it's allowed to second another // collation. - fetchCollation( - per_relay_parent, std::move(pending_collation), collator_id); + fetchCollation(per_relay_parent->get(), + std::move(pending_collation), + collator_id); } else { SL_TRACE(logger_, "A collation has already been seconded. (peer_id={}, para " diff --git a/core/parachain/validator/parachain_processor.hpp b/core/parachain/validator/parachain_processor.hpp index ab0608b094..848af7c7f9 100644 --- a/core/parachain/validator/parachain_processor.hpp +++ b/core/parachain/validator/parachain_processor.hpp @@ -663,6 +663,12 @@ namespace kagome::parachain { network::CollationVersion version, ValidatorIndex originator, const network::vstaging::CompactStatement &compact); + void prune_old_advertisements( + const parachain::ImplicitView &implicit_view, + const std::unordered_map + &active_leaves, + const std::unordered_map + &per_relay_parent); void provide_candidate_to_grid( const CandidateHash &candidate_hash, RelayParentState &relay_parent_state, @@ -695,7 +701,6 @@ namespace kagome::parachain { F &&callback); outcome::result enqueueCollation( - ParachainProcessorImpl::RelayParentState &per_relay_parent, const RelayHash &relay_parent, ParachainId para_id, const libp2p::peer::PeerId &peer_id, @@ -711,13 +716,12 @@ namespace kagome::parachain { ParachainId para_id, const Hash ¶_head); void requestUnblockedCollations( - ParachainProcessorImpl::RelayParentState &rp_state, - ParachainId para_id, - const Hash ¶_head, - std::vector &&unblocked); + std::unordered_map< + ParachainId, + std::unordered_map>> + &&unblocked); - bool canSecond(ParachainProcessorImpl::RelayParentState &per_relay_parent, - ParachainId candidate_para_id, + bool canSecond(ParachainId candidate_para_id, const Hash &candidate_relay_parent, const CandidateHash &candidate_hash, const Hash &parent_head_data_hash); From 6bdd67ba3b754fa3b6dc4e0daec52ffa7f6488cb Mon Sep 17 00:00:00 2001 From: Dmitriy Khaustov aka xDimon Date: Mon, 22 Apr 2024 09:23:55 +0300 Subject: [PATCH 31/71] fix: sending dispute request Signed-off-by: Dmitriy Khaustov aka xDimon --- .../dispute_coordinator/impl/sending_dispute.cpp | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/core/dispute_coordinator/impl/sending_dispute.cpp b/core/dispute_coordinator/impl/sending_dispute.cpp index a986816aaa..5a6da384df 100644 --- a/core/dispute_coordinator/impl/sending_dispute.cpp +++ b/core/dispute_coordinator/impl/sending_dispute.cpp @@ -41,15 +41,15 @@ namespace kagome::dispute { std::for_each(new_authorities.begin(), new_authorities.end(), [&](const auto &authority) { - if (deliveries_.count(authority) == 0) { + if (not deliveries_.contains(authority)) { add_authorities.emplace_back(authority); } }); // Get rid of dead/irrelevant tasks/statuses: - // SL_TRACE "Cleaning up deliveries" + SL_TRACE(logger_, "Cleaning up deliveries"); for (auto it = deliveries_.begin(); it != deliveries_.end();) { - if (new_authorities.count(it->first) == 0) { + if (not new_authorities.contains(it->first)) { it = deliveries_.erase(it); } else { ++it; @@ -136,9 +136,13 @@ namespace kagome::dispute { auto size = receivers.size(); + for (auto &[authority_id, peer_id] : receivers) { + deliveries_.emplace(authority_id, DeliveryStatus::Pending); + } + asyncSendRequests(std::move(protocol), std::move(receivers)); - SL_TRACE(logger_, "Requests dispatched. Sent {} requests", size); + SL_TRACE(logger_, "Requests dispatched ({} receivers)", size); return true; } @@ -153,12 +157,10 @@ namespace kagome::dispute { std::move(receivers)); for (auto &[authority_id, peer_id] : receivers) { - deliveries_.emplace(authority_id, DeliveryStatus::Pending); protocol->doRequest( peer_id, request_, - [wp{weak_from_this()}, authority_id(authority_id), peer_id]( - auto res) mutable { + [wp{weak_from_this()}, authority_id, peer_id](auto res) mutable { if (auto self = wp.lock()) { if (res.has_value()) { self->deliveries_[authority_id] = DeliveryStatus::Succeeded; From 60f493073ad7f52d3938ee1cbfb5bd5425705bae Mon Sep 17 00:00:00 2001 From: Dmitriy Khaustov aka xDimon Date: Mon, 13 May 2024 20:20:14 +0300 Subject: [PATCH 32/71] fix: incoming dispute requests batching Signed-off-by: Dmitriy Khaustov aka xDimon --- core/dispute_coordinator/impl/batches.cpp | 20 +-- core/dispute_coordinator/impl/batches.hpp | 10 +- .../impl/dispute_coordinator_impl.cpp | 120 ++++++++++-------- .../impl/dispute_coordinator_impl.hpp | 6 +- 4 files changed, 94 insertions(+), 62 deletions(-) diff --git a/core/dispute_coordinator/impl/batches.cpp b/core/dispute_coordinator/impl/batches.cpp index 3d54cc303b..cb9fce64e0 100644 --- a/core/dispute_coordinator/impl/batches.cpp +++ b/core/dispute_coordinator/impl/batches.cpp @@ -10,9 +10,10 @@ namespace kagome::dispute { - Batches::Batches(clock::SteadyClock &clock, + Batches::Batches(log::Logger logger, + clock::SteadyClock &clock, std::shared_ptr hasher) - : clock_(clock), hasher_(std::move(hasher)) {} + : logger_(std::move(logger)), clock_(clock), hasher_(std::move(hasher)) {} outcome::result, bool>> Batches::find_batch( const CandidateHash &candidate_hash, @@ -40,10 +41,10 @@ namespace kagome::dispute { std::vector Batches::check_batches() { std::vector imports; - // Wait for at least one batch to become ready - - BOOST_ASSERT_MSG(not waiting_queue_.empty(), - "Can't try to check if nothing waiting"); + // Can't try to check if nothing waiting + if (waiting_queue_.empty()) { + return imports; + } auto now = clock_.now(); for (;;) { @@ -65,15 +66,16 @@ namespace kagome::dispute { // Batch done if (prepared_import_opt.has_value()) { auto &prepared_import = prepared_import_opt.value(); - // LOG-TRACE: "Batch (candidate={}) became ready", candidate_hash + SL_TRACE(logger_, "Batch (candidate={}) became ready", candidate_hash); imports.push_back(std::move(prepared_import)); batches_.erase(it); continue; } // Batch alive - // LOG-TRACE: "Batch (candidate={}) found to be still alive on check", - // candidate_hash + SL_TRACE(logger_, + "Batch (candidate={}) found to be still alive on check", + candidate_hash); waiting_queue_.emplace(candidate_hash); } diff --git a/core/dispute_coordinator/impl/batches.hpp b/core/dispute_coordinator/impl/batches.hpp index e40858957b..04fa1e518b 100644 --- a/core/dispute_coordinator/impl/batches.hpp +++ b/core/dispute_coordinator/impl/batches.hpp @@ -9,6 +9,7 @@ #include "clock/clock.hpp" #include "dispute_coordinator/impl/batch.hpp" #include "dispute_coordinator/types.hpp" +#include "log/logger.hpp" #include @@ -22,7 +23,9 @@ namespace kagome::dispute { /// contained votes. class Batches final { public: - Batches(clock::SteadyClock &clock, std::shared_ptr hasher); + Batches(log::Logger logger, + clock::SteadyClock &clock, + std::shared_ptr hasher); /// Find a particular batch. /// @@ -46,7 +49,12 @@ namespace kagome::dispute { /// ready. std::vector check_batches(); + bool empty() const { + return waiting_queue_.empty(); + } + private: + log::Logger logger_; clock::SteadyClock &clock_; std::shared_ptr hasher_; diff --git a/core/dispute_coordinator/impl/dispute_coordinator_impl.cpp b/core/dispute_coordinator/impl/dispute_coordinator_impl.cpp index 458decea8b..6e2e61ebe2 100644 --- a/core/dispute_coordinator/impl/dispute_coordinator_impl.cpp +++ b/core/dispute_coordinator/impl/dispute_coordinator_impl.cpp @@ -131,7 +131,8 @@ namespace kagome::dispute { std::shared_ptr peer_view, primitives::events::ChainSubscriptionEnginePtr chain_sub_engine, LazySPtr timeline) - : system_clock_(system_clock), + : log_(log::createLogger("DisputeCoordinator", "dispute")), + system_clock_(system_clock), steady_clock_(steady_clock), session_keys_(std::move(session_keys)), storage_(std::move(storage)), @@ -157,7 +158,7 @@ namespace kagome::dispute { dispute_thread_pool.io_context()), libp2p::basic::Scheduler::Config{})}, runtime_info_(std::make_unique(api_, session_keys_)), - batches_(std::make_unique(steady_clock_, hasher_)) { + batches_(std::make_unique(log_, steady_clock_, hasher_)) { BOOST_ASSERT(session_keys_ != nullptr); BOOST_ASSERT(storage_ != nullptr); BOOST_ASSERT(sr25519_crypto_provider_ != nullptr); @@ -2200,7 +2201,13 @@ namespace kagome::dispute { return sendDisputeResponse(DisputeProcessingError::AuthorityFlooding, std::move(cb)); } - queue.emplace_back(request, std::move(cb)); + queue.emplace_back(request, + [wp{weak_from_this()}, + cb{std::move(cb)}](outcome::result res) mutable { + if (auto self = wp.lock()) { + self->sendDisputeResponse(res, std::move(cb)); + } + }); // We have at least one element to process - rate limit `timer` needs to // exist now: @@ -2372,18 +2379,19 @@ namespace kagome::dispute { auto &valid_vote = checked_valid_vote; auto &invalid_vote = checked_invalid_vote; + // Find or create batch OUTCOME_TRY(found_batch, batches_->find_batch(candidate_hash, candidate_receipt)); - auto &[batch, just_created] = found_batch; + auto [batch, just_created] = std::move(found_batch); if (just_created) { // There was no entry yet - start import immediately: - SL_TRACE(log_, - "No batch yet - triggering immediate import (candidate={}, " - "peer={})", - candidate_hash, - peer); + SL_TRACE( + log_, + "No batch yet - triggering immediate import (candidate={}, peer={})", + candidate_hash, + peer); PreparedImport prepared_import{ .candidate_receipt = batch->candidate_receipt, @@ -2392,54 +2400,66 @@ namespace kagome::dispute { }; start_import(std::move(prepared_import)); - } else { - SL_TRACE(log_, - "Batch exists - batching request (candidate={})", - candidate_hash); - auto cb_opt = - batch->add_votes(valid_vote, invalid_vote, peer, std::move(cb)); - - // Returned value means duplicate - if (cb_opt.has_value()) { - // We don't expect honest peers to send redundant votes within a - // single batch, as the timeout for retry is much higher. Still we - // don't want to punish the node as it might not be the node's - // fault. Some other (malicious) node could have been faster sending - // the same votes in order to harm the reputation of that honest - // node. Given that we already have a rate limit, if a validator - // chooses to waste available rate with redundant votes - so be it. - // The actual dispute resolution is unaffected. - SL_DEBUG(log_, - "Peer {} sent completely redundant votes within a single " - "batch - that looks fishy!", - peer); - - // While we have seen duplicate votes, we cannot confirm as we don't - // know yet whether the batch is going to be confirmed, so we assume - // the worst. We don't want to push the pending response to the - // batch either as that would be unbounded, only limited by the rate - // limit. - (*cb_opt)(BatchError::RedundantMessage); - - // } else { // FIXME testing code. must be removed - // auto prepared_import = - // batch->tick(steady_clock_.now() + - // Batch::kBatchCollectingInterval); - // if (prepared_import.has_value()) { - // start_import(std::move(prepared_import.value())); - // } - } + return outcome::success(); + } - auto ready_prepared_imports = batches_->check_batches(); - for (auto &prepared_import : ready_prepared_imports) { - start_import(std::move(prepared_import)); - } + SL_TRACE( + log_, "Batch exists - batching request (candidate={})", candidate_hash); + + auto cb_opt = + batch->add_votes(valid_vote, invalid_vote, peer, std::move(cb)); + + // Returned value means duplicate + if (cb_opt.has_value()) { + // We don't expect honest peers to send redundant votes within a single + // batch, as the timeout for retry is much higher. Still we don't want to + // punish the node as it might not be the node's fault. Some other + // (malicious) node could have been faster sending the same votes in order + // to harm the reputation of that honest node. Given that we already have + // a rate limit, if a validator chooses to waste available rate with + // redundant votes - so be it. The actual dispute resolution is + // unaffected. + + SL_DEBUG(log_, + "Peer {} sent completely redundant votes " + "within a single batch " + "- that looks fishy!", + peer); + + // While we have seen duplicate votes, we cannot confirm as we don't know + // yet whether the batch is going to be confirmed, so we assume the worst. + // We don't want to push the pending response to the batch either as that + // would be unbounded, only limited by the rate limit. + + (*cb_opt)(BatchError::RedundantMessage); } + check_batches(); + return outcome::success(); } + void DisputeCoordinatorImpl::check_batches() { + if (not batch_collecting_timer_.has_value()) { + batch_collecting_timer_ = scheduler_->scheduleWithHandle( + [wp{weak_from_this()}]() { + if (auto self = wp.lock()) { + BOOST_ASSERT(self->dispute_thread_handler_->isInCurrentThread()); + self->batch_collecting_timer_.reset(); + auto ready_prepared_imports = self->batches_->check_batches(); + for (auto &prepared_import : ready_prepared_imports) { + self->start_import(std::move(prepared_import)); + } + if (not self->batches_->empty()) { + self->check_batches(); + } + } + }, + Batch::kBatchCollectingInterval); + } + } + // https://github.com/paritytech/polkadot/blob/40974fb99c86f5c341105b7db53c7aa0df707d66/node/network/dispute-distribution/src/receiver/mod.rs#L422 void DisputeCoordinatorImpl::start_import(PreparedImport &&prepared_import) { auto [candidate_receipt, statements, requesters] = diff --git a/core/dispute_coordinator/impl/dispute_coordinator_impl.hpp b/core/dispute_coordinator/impl/dispute_coordinator_impl.hpp index 9f7dfb7356..47872b2ee1 100644 --- a/core/dispute_coordinator/impl/dispute_coordinator_impl.hpp +++ b/core/dispute_coordinator/impl/dispute_coordinator_impl.hpp @@ -259,6 +259,8 @@ namespace kagome::dispute { const network::DisputeMessage &request, CbOutcome &&cb); + void check_batches(); + void start_import(PreparedImport &&prepared_import); void sendDisputeResponse(outcome::result res, CbOutcome &&cb); @@ -273,8 +275,7 @@ namespace kagome::dispute { bool has_required_runtime(const primitives::BlockInfo &relay_parent); - log::Logger log_ = log::createLogger("DisputeCoordinator", "dispute"); - + log::Logger log_; clock::SystemClock &system_clock_; clock::SteadyClock &steady_clock_; std::shared_ptr session_keys_; @@ -344,6 +345,7 @@ namespace kagome::dispute { /// Currently active batches of imports per candidate. std::unique_ptr batches_; + std::optional batch_collecting_timer_; /// All heads we currently consider active. std::unordered_set active_heads_; From c257936c8936bc74617f301da2ed420988a4a5b4 Mon Sep 17 00:00:00 2001 From: Dmitriy Khaustov aka xDimon Date: Mon, 13 May 2024 20:21:40 +0300 Subject: [PATCH 33/71] feature: add logs Signed-off-by: Dmitriy Khaustov aka xDimon --- .../impl/dispute_coordinator_impl.cpp | 19 +++++++++++-------- 1 file changed, 11 insertions(+), 8 deletions(-) diff --git a/core/dispute_coordinator/impl/dispute_coordinator_impl.cpp b/core/dispute_coordinator/impl/dispute_coordinator_impl.cpp index 6e2e61ebe2..b1e4e27a34 100644 --- a/core/dispute_coordinator/impl/dispute_coordinator_impl.cpp +++ b/core/dispute_coordinator/impl/dispute_coordinator_impl.cpp @@ -615,16 +615,18 @@ namespace kagome::dispute { validator_signature, payload, validator_public); if (validation_res.has_error()) { + SL_CRITICAL(log_, + "Cannot validate scraped backing votes signature! {}", + validation_res.error()); return false; } if (not validation_res.value()) { + SL_CRITICAL(log_, "Scraped backing votes had invalid signature!"); return false; } return true; }; - - BOOST_ASSERT_MSG(check_sig(), - "Scraped backing votes had invalid signature!"); + BOOST_ASSERT(check_sig()); Indexed signed_dispute_statement{ { @@ -2592,11 +2594,12 @@ namespace kagome::dispute { return true; } - SL_TRACE(log_, - "Fetched ParachainHost runtime api version for relay_parent {} is " - "{}; it isn't suitable version", - relay_parent, - parachain_host_api_version); + SL_TRACE( + log_, + "Fetched ParachainHost runtime api version for relay_parent {} is {}; " + "it isn't suitable version", + relay_parent, + parachain_host_api_version); return false; } From c18e5c29a5b12ca8d98c2634ea9fa4b5f7748c94 Mon Sep 17 00:00:00 2001 From: Dmitriy Khaustov aka xDimon Date: Mon, 13 May 2024 20:22:16 +0300 Subject: [PATCH 34/71] feature: clang-format rules Signed-off-by: Dmitriy Khaustov aka xDimon --- .clang-format | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.clang-format b/.clang-format index 436359487b..5fb39bfff6 100644 --- a/.clang-format +++ b/.clang-format @@ -5,7 +5,7 @@ # BasedOnStyle: Google -BreakStringLiterals: false +BreakStringLiterals: true NamespaceIndentation: All BreakBeforeBinaryOperators: NonAssignment AlignOperands: AlignAfterOperator @@ -21,6 +21,7 @@ SortIncludes: CaseSensitive QualifierAlignment: Custom QualifierOrder: ['inline', 'static', 'constexpr', 'const', 'volatile', 'type', 'restrict'] ReferenceAlignment: Right +ReflowComments: true # uncomment in clang-format-16 #RemoveSemicolon: true #InsertNewlineAtEOF: true From 478df813a52b575ba95a4fbb13d4baf0f3924cdd Mon Sep 17 00:00:00 2001 From: kamilsa Date: Tue, 14 May 2024 09:51:04 +0500 Subject: [PATCH 35/71] Fix macos --- core/dispute_coordinator/impl/sending_dispute.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/core/dispute_coordinator/impl/sending_dispute.cpp b/core/dispute_coordinator/impl/sending_dispute.cpp index 5a6da384df..71616869a6 100644 --- a/core/dispute_coordinator/impl/sending_dispute.cpp +++ b/core/dispute_coordinator/impl/sending_dispute.cpp @@ -160,7 +160,8 @@ namespace kagome::dispute { protocol->doRequest( peer_id, request_, - [wp{weak_from_this()}, authority_id, peer_id](auto res) mutable { + [wp{weak_from_this()}, authority_id(authority_id), peer_id(peer_id)]( + auto res) mutable { if (auto self = wp.lock()) { if (res.has_value()) { self->deliveries_[authority_id] = DeliveryStatus::Succeeded; From 624fa02fc3f8e37871150581c7f762f18933964c Mon Sep 17 00:00:00 2001 From: iceseer Date: Tue, 14 May 2024 10:44:10 +0300 Subject: [PATCH 36/71] fixes -> branch ! Signed-off-by: iceseer --- core/parachain/approval/approval_distribution.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/core/parachain/approval/approval_distribution.cpp b/core/parachain/approval/approval_distribution.cpp index b17e8a4bfd..7682ebde9d 100644 --- a/core/parachain/approval/approval_distribution.cpp +++ b/core/parachain/approval/approval_distribution.cpp @@ -1324,9 +1324,10 @@ namespace kagome::parachain { }); if (outcome.has_error()) { self->logger_->warn( - "Approval validation failed.(parachain id={}, relay parent={})", + "Approval validation failed.(parachain id={}, relay parent={}, error={})", candidate_receipt.descriptor.para_id, - candidate_receipt.descriptor.relay_parent); + candidate_receipt.descriptor.relay_parent, + outcome.error()); self->dispute_coordinator_.get()->issueLocalStatement( session_index, hashed_candidate.getHash(), From c7d067757d3ecf4c3ceea1f16369a6141a075318 Mon Sep 17 00:00:00 2001 From: iceseer Date: Wed, 15 May 2024 11:04:28 +0300 Subject: [PATCH 37/71] fixes -> branch ! Signed-off-by: iceseer --- core/parachain/validator/impl/parachain_processor.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/core/parachain/validator/impl/parachain_processor.cpp b/core/parachain/validator/impl/parachain_processor.cpp index 3bc98e1889..dd07495a27 100644 --- a/core/parachain/validator/impl/parachain_processor.cpp +++ b/core/parachain/validator/impl/parachain_processor.cpp @@ -713,7 +713,6 @@ namespace kagome::parachain { backing_store_->onDeactivateLeaf(lost); av_store_->remove(lost); bitfield_store_->remove(lost); - our_current_state_.active_leaves.erase(lost); } } From e8e20c0ff0e4bf4c79bace81ce34db249e82278d Mon Sep 17 00:00:00 2001 From: iceseer Date: Wed, 15 May 2024 19:01:23 +0300 Subject: [PATCH 38/71] fixes -> branch ! Signed-off-by: iceseer --- .../validator/impl/parachain_processor.cpp | 50 +++++++++++++++++-- 1 file changed, 47 insertions(+), 3 deletions(-) diff --git a/core/parachain/validator/impl/parachain_processor.cpp b/core/parachain/validator/impl/parachain_processor.cpp index dd07495a27..decc499dbb 100644 --- a/core/parachain/validator/impl/parachain_processor.cpp +++ b/core/parachain/validator/impl/parachain_processor.cpp @@ -1031,7 +1031,7 @@ namespace kagome::parachain { SL_VERBOSE( logger_, - "Inited new backing task v2.(assigned_para={}, assigned_core={}, our index={}, relay " + "Inited new backing task v3.(assigned_para={}, assigned_core={}, our index={}, relay " "parent={})", assigned_para, assigned_core, @@ -2992,6 +2992,35 @@ namespace kagome::parachain { } const auto group_size = group->size(); + SL_TRACE( + logger_, + "======================== GRID VIEW {} {} ========================", + group_index, relay_parent); + + for (size_t k = 0; k < grid_view.size(); ++k) { + const auto &v = grid_view[k]; + SL_TRACE( + logger_, + "\tGroup {}", k + ); + for (const auto vi : v.sending) { + SL_TRACE( + logger_, + "\t\tS: {}", vi + ); + } + for (const auto vi : v.receiving) { + SL_TRACE( + logger_, + "\t\tR: {}", vi + ); + } + } + + SL_TRACE( + logger_, + "================================================================="); + auto filter = local_knowledge_filter(group_size, group_index, candidate_hash, @@ -3025,14 +3054,29 @@ namespace kagome::parachain { continue; } - /// TODO(iceseer): do check `implicit_view` for peer, saved in PeerState. - /// Get protocol from there. + auto peer_state = pm_->getPeerState(peer_opt->id); + if (!peer_state) { + continue; + } + + if (!peer_state->get().knows_relay_parent(relay_parent)) { + continue; + } + switch (action) { case grid::ManifestKind::Full: { + SL_TRACE( + logger_, + "Full manifest -> {}", v + ); manifest_peers.emplace_back(peer_opt->id, network::CollationVersion::VStaging); } break; case grid::ManifestKind::Acknowledgement: { + SL_TRACE( + logger_, + "Ack manifest -> {}", v + ); ack_peers.emplace_back(peer_opt->id, network::CollationVersion::VStaging); } break; From 382b080e07b4aa588a16d9ee1ef390c8621483c8 Mon Sep 17 00:00:00 2001 From: iceseer Date: Fri, 17 May 2024 10:37:00 +0300 Subject: [PATCH 39/71] fixes -> branch ! Signed-off-by: iceseer --- .../validator/impl/parachain_processor.cpp | 397 ++++++++++-------- .../validator/parachain_processor.hpp | 17 +- 2 files changed, 234 insertions(+), 180 deletions(-) diff --git a/core/parachain/validator/impl/parachain_processor.cpp b/core/parachain/validator/impl/parachain_processor.cpp index 50f5785aa6..af24ba11fb 100644 --- a/core/parachain/validator/impl/parachain_processor.cpp +++ b/core/parachain/validator/impl/parachain_processor.cpp @@ -15,6 +15,7 @@ #include "common/main_thread_pool.hpp" #include "common/worker_thread_pool.hpp" +#include "consensus/babe/impl/babe_digests_util.hpp" #include "crypto/hasher.hpp" #include "crypto/sr25519_provider.hpp" #include "dispute_coordinator/impl/runtime_info.hpp" @@ -116,7 +117,9 @@ namespace kagome::parachain { primitives::events::BabeStateSubscriptionEnginePtr babe_status_observable, std::shared_ptr query_audi, std::shared_ptr prospective_parachains, - std::shared_ptr block_tree) + std::shared_ptr block_tree, + LazySPtr slots_util, + std::shared_ptr babe_config_repo) : pm_(std::move(pm)), runtime_info_(std::move(runtime_info)), crypto_provider_(std::move(crypto_provider)), @@ -136,6 +139,8 @@ namespace kagome::parachain { babe_status_observable_(std::move(babe_status_observable)), query_audi_{std::move(query_audi)}, per_session_(RefCache::create()), + slots_util_(std::move(slots_util)), + babe_config_repo_(std::move(babe_config_repo)), chain_sub_{std::move(chain_sub_engine)}, worker_pool_handler_{worker_thread_pool.handler(app_state_manager)}, prospective_parachains_{std::move(prospective_parachains)}, @@ -143,6 +148,7 @@ namespace kagome::parachain { BOOST_ASSERT(pm_); BOOST_ASSERT(peer_view_); BOOST_ASSERT(crypto_provider_); + BOOST_ASSERT(babe_config_repo_); BOOST_ASSERT(router_); BOOST_ASSERT(main_pool_handler_); BOOST_ASSERT(hasher_); @@ -376,9 +382,10 @@ namespace kagome::parachain { StatementDistributionMessage{manifest}}}); } break; default: { - SL_ERROR( - logger_, - "Bug ValidationVersion::V1 should not be used in statement-distribution v2, legacy should have handled this."); + SL_ERROR(logger_, + "Bug ValidationVersion::V1 should not be used in " + "statement-distribution v2, legacy should have handled " + "this."); } break; }; } break; @@ -471,9 +478,9 @@ namespace kagome::parachain { } } break; default: { - SL_ERROR( - logger_, - "Bug ValidationVersion::V1 should not be used in statement-distribution v2, legacy should have handled this"); + SL_ERROR(logger_, + "Bug ValidationVersion::V1 should not be used in " + "statement-distribution v2, legacy should have handled this"); } break; } return {}; @@ -531,15 +538,15 @@ namespace kagome::parachain { .lost = event.lost, }); r.has_error()) { - SL_WARN( - logger_, - "Prospective parachains leaf update failed. (relay_parent={}, error={})", - relay_parent, - r.error().message()); + SL_WARN(logger_, + "Prospective parachains leaf update failed. (relay_parent={}, " + "error={})", + relay_parent, + r.error().message()); } backing_store_->onActivateLeaf(relay_parent); - createBackingTask(relay_parent); + createBackingTask(relay_parent, event.new_head); SL_TRACE(logger_, "Update my view.(new head={}, finalized={}, leaves={})", relay_parent, @@ -683,7 +690,11 @@ namespace kagome::parachain { != our_current_state_.state_by_relay_parent.end()) { continue; } - createBackingTask(maybe_new); + if (auto r = block_tree_->getBlockHeader(maybe_new); r.has_value()) { + createBackingTask(maybe_new, r.value()); + } else { + SL_ERROR(logger_, "No header found.(relay parent={})", maybe_new); + } } auto remove_if = [](bool eq, auto &it, auto &cont) { @@ -888,9 +899,23 @@ namespace kagome::parachain { } } + outcome::result + ParachainProcessorImpl::getBabeRandomness( + const primitives::BlockHeader &block_header) { + OUTCOME_TRY(babe_header, consensus::babe::getBabeBlockHeader(block_header)); + OUTCOME_TRY(epoch, + slots_util_.get()->slotToEpoch(*block_header.parentInfo(), + babe_header.slot_number)); + OUTCOME_TRY(babe_config, + babe_config_repo_->config(*block_header.parentInfo(), epoch)); + + return babe_config->randomness; + } + outcome::result ParachainProcessorImpl::initNewBackingTask( - const primitives::BlockHash &relay_parent) { + const primitives::BlockHash &relay_parent, + const network::HashedBlockHeader &block_header) { /** * It first checks if our node is a parachain validator for the relay * parent. If it is not, it returns an error. If the node is a validator, it @@ -915,6 +940,7 @@ namespace kagome::parachain { parachain_host_->session_index_for_child(relay_parent)); OUTCOME_TRY(session_info, parachain_host_->session_info(relay_parent, session_index)); + OUTCOME_TRY(randomness, getBabeRandomness(block_header)); const auto &[validator_groups, group_rotation_info] = groups; if (!validator) { @@ -945,18 +971,40 @@ namespace kagome::parachain { r.has_value()) { minimum_backing_votes = r.value(); } else { - SL_TRACE( - logger_, - "Querying the backing threshold from the runtime is not supported by the current Runtime API. (relay_parent={})", - relay_parent); + SL_TRACE(logger_, + "Querying the backing threshold from the runtime is not " + "supported by the current Runtime API. (relay_parent={})", + relay_parent); } auto per_session_state = per_session_->get_or_insert(session_index, [&]() { const auto validator_index{validator->validatorIndex()}; - grid::Views grid_view = - grid::makeViews(session_info->validator_groups, - session_info->active_validator_indices, - validator_index); + SL_TRACE( + logger_, "===> Grid build (validator_index={})", validator_index); + + grid::Views grid_view = grid::makeViews( + session_info->validator_groups, + grid::shuffle(session_info->validator_groups, randomness), + validator_index); + + SL_TRACE(logger_, + "======================== GV INIT ========================"); + + for (size_t k = 0; k < grid_view.size(); ++k) { + const auto &v = grid_view[k]; + SL_TRACE(logger_, "\tGroup {}", k); + for (const auto vi : v.sending) { + SL_TRACE(logger_, "\t\tS: {}", vi); + } + for (const auto vi : v.receiving) { + SL_TRACE(logger_, "\t\tR: {}", vi); + } + } + + SL_TRACE( + logger_, + "================================================================="); + Groups g{session_info->validator_groups, minimum_backing_votes}; return RefCache::RefObj( *session_info, @@ -1056,14 +1104,14 @@ namespace kagome::parachain { statement_store.emplace(per_session_state->value().groups); } - SL_VERBOSE( - logger_, - "Inited new backing task v3.(assigned_para={}, assigned_core={}, our index={}, relay " - "parent={})", - assigned_para, - assigned_core, - validator->validatorIndex(), - relay_parent); + SL_VERBOSE(logger_, + "Inited new backing task v3.(assigned_para={}, " + "assigned_core={}, our index={}, relay " + "parent={})", + assigned_para, + assigned_core, + validator->validatorIndex(), + relay_parent); return RelayParentState{ .prospective_parachains_mode = mode, @@ -1097,9 +1145,10 @@ namespace kagome::parachain { } void ParachainProcessorImpl::createBackingTask( - const primitives::BlockHash &relay_parent) { + const primitives::BlockHash &relay_parent, + const network::HashedBlockHeader &block_header) { BOOST_ASSERT(main_pool_handler_->isInCurrentThread()); - auto rps_result = initNewBackingTask(relay_parent); + auto rps_result = initNewBackingTask(relay_parent, block_header); if (rps_result.has_value()) { storeStateByRelayParent(relay_parent, std::move(rps_result.value())); } else if (rps_result.error() != Error::KEY_NOT_PRESENT) { @@ -1420,12 +1469,12 @@ namespace kagome::parachain { } if (acknowledge) { - SL_TRACE( - logger_, - "immediate ack, known candidate. (candidate hash={}, from={}, local_validator={})", - candidate_hash, - *sender_index, - *relay_parent_state->get().our_index); + SL_TRACE(logger_, + "immediate ack, known candidate. (candidate hash={}, from={}, " + "local_validator={})", + candidate_hash, + *sender_index, + *relay_parent_state->get().our_index); } return ManifestImportSuccess{ @@ -1571,9 +1620,9 @@ namespace kagome::parachain { }}}}); } break; default: { - SL_ERROR( - logger_, - "Bug ValidationVersion::V1 should not be used in statement-distribution v2, legacy should have handled this"); + SL_ERROR(logger_, + "Bug ValidationVersion::V1 should not be used in " + "statement-distribution v2, legacy should have handled this"); return {}; } break; }; @@ -1648,7 +1697,8 @@ namespace kagome::parachain { default: { SL_ERROR( logger_, - "Bug ValidationVersion::V1 should not be used in statement-distribution v2, legacy should have handled this"); + "Bug ValidationVersion::V1 should not be used in " + "statement-distribution v2, legacy should have handled this"); } break; } }); @@ -1788,11 +1838,11 @@ namespace kagome::parachain { return; } - SL_TRACE( - logger_, - "Handling incoming manifest common. (relay_parent={}, candidate_hash={})", - manifest.relay_parent, - manifest.candidate_hash); + SL_TRACE(logger_, + "Handling incoming manifest common. (relay_parent={}, " + "candidate_hash={})", + manifest.relay_parent, + manifest.candidate_hash); ManifestImportSuccessOpt x = handle_incoming_manifest_common( peer_id, manifest.candidate_hash, @@ -1830,11 +1880,11 @@ namespace kagome::parachain { manifest.group_index, manifest.candidate_hash, *relay_parent_state->get().statement_store); - SL_TRACE( - logger_, - "Get ack and statement messages. (relay_parent={}, candidate_hash={})", - manifest.relay_parent, - manifest.candidate_hash); + SL_TRACE(logger_, + "Get ack and statement messages. (relay_parent={}, " + "candidate_hash={})", + manifest.relay_parent, + manifest.candidate_hash); auto messages = acknowledgement_and_statement_messages( peer_id, network::CollationVersion::VStaging, @@ -2897,12 +2947,12 @@ namespace kagome::parachain { post_import_statement_actions(relay_parent, parachain_state, res.value()); if (auto result = res.value()) { if (!assigned_core || result->group_id != *assigned_core) { - SL_TRACE( - logger_, - "Registered statement from not our group(assigned_para our={}, assigned_core our={}, registered={}).", - assigned_para, - assigned_core, - result->group_id); + SL_TRACE(logger_, + "Registered statement from not our group(assigned_para " + "our={}, assigned_core our={}, registered={}).", + assigned_para, + assigned_core, + result->group_id); return; } @@ -3000,11 +3050,11 @@ namespace kagome::parachain { const auto group_index = confirmed_candidate.group_index(); if (!relay_parent_state.per_session_state->value().grid_view) { - SL_TRACE( - logger_, - "Cannot handle backable candidate due to lack of topology. (candidate={}, relay_parent={})", - candidate_hash, - relay_parent); + SL_TRACE(logger_, + "Cannot handle backable candidate due to lack of topology. " + "(candidate={}, relay_parent={})", + candidate_hash, + relay_parent); return; } @@ -3013,38 +3063,35 @@ namespace kagome::parachain { const auto group = relay_parent_state.per_session_state->value().groups.get(group_index); if (!group) { - SL_TRACE( - logger_, - "Handled backed candidate with unknown group? (candidate={}, relay_parent={}, group_index={})", - candidate_hash, - relay_parent, - group_index); + SL_TRACE(logger_, + "Handled backed candidate with unknown group? (candidate={}, " + "relay_parent={}, group_index={})", + candidate_hash, + relay_parent, + group_index); return; } const auto group_size = group->size(); - SL_TRACE( - logger_, - "======================== GRID VIEW {} {} ========================", - group_index, relay_parent); + SL_TRACE(logger_, + "======================== GRID VIEW group={} relay_parent={} " + "our_index={} our_id={} our_dk={} in_per_session={} " + "========================", + group_index, + relay_parent, + *relay_parent_state.our_index, + session_info.validators[*relay_parent_state.our_index], + session_info.discovery_keys[*relay_parent_state.our_index], + *relay_parent_state.per_session_state->value().our_index); for (size_t k = 0; k < grid_view.size(); ++k) { const auto &v = grid_view[k]; - SL_TRACE( - logger_, - "\tGroup {}", k - ); + SL_TRACE(logger_, "\tGroup {}", k); for (const auto vi : v.sending) { - SL_TRACE( - logger_, - "\t\tS: {}", vi - ); + SL_TRACE(logger_, "\t\tS: {}", vi); } for (const auto vi : v.receiving) { - SL_TRACE( - logger_, - "\t\tR: {}", vi - ); + SL_TRACE(logger_, "\t\tR: {}", vi); } } @@ -3096,18 +3143,12 @@ namespace kagome::parachain { switch (action) { case grid::ManifestKind::Full: { - SL_TRACE( - logger_, - "Full manifest -> {}", v - ); + SL_TRACE(logger_, "Full manifest -> {}", v); manifest_peers.emplace_back(peer_opt->id, network::CollationVersion::VStaging); } break; case grid::ManifestKind::Acknowledgement: { - SL_TRACE( - logger_, - "Ack manifest -> {}", v - ); + SL_TRACE(logger_, "Ack manifest -> {}", v); ack_peers.emplace_back(peer_opt->id, network::CollationVersion::VStaging); } break; @@ -3140,12 +3181,12 @@ namespace kagome::parachain { BOOST_ASSERT(se); if (!manifest_peers.empty()) { - SL_TRACE( - logger_, - "Sending manifest to v2 peers. (candidate_hash={}, local_validator={}, n_peers={})", - candidate_hash, - *relay_parent_state.our_index, - manifest_peers.size()); + SL_TRACE(logger_, + "Sending manifest to v2 peers. (candidate_hash={}, " + "local_validator={}, n_peers={})", + candidate_hash, + *relay_parent_state.our_index, + manifest_peers.size()); auto message = std::make_shared< network::WireMessage>( kagome::network::vstaging::ValidatorProtocolMessage{ @@ -3157,12 +3198,12 @@ namespace kagome::parachain { } if (!ack_peers.empty()) { - SL_TRACE( - logger_, - "Sending acknowledgement to v2 peers. (candidate_hash={}, local_validator={}, n_peers={})", - candidate_hash, - *relay_parent_state.our_index, - ack_peers.size()); + SL_TRACE(logger_, + "Sending acknowledgement to v2 peers. (candidate_hash={}, " + "local_validator={}, n_peers={})", + candidate_hash, + *relay_parent_state.our_index, + ack_peers.size()); auto message = std::make_shared< network::WireMessage>( kagome::network::vstaging::ValidatorProtocolMessage{ @@ -3174,12 +3215,12 @@ namespace kagome::parachain { } if (!post_statements.empty()) { - SL_TRACE( - logger_, - "Sending statements to v2 peers. (candidate_hash={}, local_validator={}, n_peers={})", - candidate_hash, - *relay_parent_state.our_index, - post_statements.size()); + SL_TRACE(logger_, + "Sending statements to v2 peers. (candidate_hash={}, " + "local_validator={}, n_peers={})", + candidate_hash, + *relay_parent_state.our_index, + post_statements.size()); for (auto &[peers, msg] : post_statements) { if (auto m = @@ -3250,11 +3291,11 @@ namespace kagome::parachain { for (const auto &bitfield : bitfields) { const auto validator_idx{size_t(bitfield.payload.ix)}; if (validator_idx >= availability.bits.size()) { - SL_WARN( - logger_, - "attempted to set a transverse bit at idx which is greater than bitfield size. (validator_idx={}, availability_len={})", - validator_idx, - availability_len); + SL_WARN(logger_, + "attempted to set a transverse bit at idx which is greater " + "than bitfield size. (validator_idx={}, availability_len={})", + validator_idx, + availability_len); return false; } @@ -3363,11 +3404,11 @@ namespace kagome::parachain { relay_parent, para_id, core_count, para_ancestors_vec); if (response.empty()) { - SL_TRACE( - logger_, - "No backable candidate returned by prospective parachains. (relay_parent={}, para_id={})", - relay_parent, - para_id); + SL_TRACE(logger_, + "No backable candidate returned by prospective parachains. " + "(relay_parent={}, para_id={})", + relay_parent, + para_id); continue; } @@ -3385,12 +3426,12 @@ namespace kagome::parachain { for (const auto &[c_hash, r_hash] : para_candidates) { auto rp_state = tryGetStateByRelayParent(r_hash); if (!rp_state) { - SL_TRACE( - logger_, - "Requested candidate's relay parent is out of view. (relay_parent={}, r_hash={}, c_hash={})", - relay_parent, - r_hash, - c_hash); + SL_TRACE(logger_, + "Requested candidate's relay parent is out of view. " + "(relay_parent={}, r_hash={}, c_hash={})", + relay_parent, + r_hash, + c_hash); break; } @@ -3445,12 +3486,12 @@ namespace kagome::parachain { } } - SL_TRACE( - logger_, - "Selected backed candidates. (n_candidates={}, n_cores={}, relay_parent={})", - merged_candidates.size(), - availability_cores.size(), - relay_parent); + SL_TRACE(logger_, + "Selected backed candidates. (n_candidates={}, n_cores={}, " + "relay_parent={})", + merged_candidates.size(), + availability_cores.size(), + relay_parent); return merged_candidates; } @@ -3686,7 +3727,8 @@ namespace kagome::parachain { if (statement_validator_index >= validator_to_group.size()) { SL_TRACE( logger_, - "Invalid validator index. (candidate_hash={}, validator_to_group={}, statement_validator_index={}, n_cores={})", + "Invalid validator index. (candidate_hash={}, validator_to_group={}, " + "statement_validator_index={}, n_cores={})", candidate_hash, validator_to_group.size(), statement_validator_index, @@ -3696,12 +3738,12 @@ namespace kagome::parachain { const auto group_index = validator_to_group[statement_validator_index]; if (!group_index) { - SL_TRACE( - logger_, - "Invalid validator index. Empty group. (candidate_hash={}, statement_validator_index={}, n_cores={})", - candidate_hash, - statement_validator_index, - n_cores); + SL_TRACE(logger_, + "Invalid validator index. Empty group. (candidate_hash={}, " + "statement_validator_index={}, n_cores={})", + candidate_hash, + statement_validator_index, + n_cores); return std::nullopt; } @@ -3709,13 +3751,13 @@ namespace kagome::parachain { group_rotation_info.coreForGroup(*group_index, n_cores); if (size_t(core_index) > n_cores) { - SL_WARN( - logger_, - "Invalid CoreIndex. (candidate_hash={}, core_index={}, validator={}, n_cores={})", - candidate_hash, - core_index, - statement_validator_index, - n_cores); + SL_WARN(logger_, + "Invalid CoreIndex. (candidate_hash={}, core_index={}, " + "validator={}, n_cores={})", + candidate_hash, + core_index, + statement_validator_index, + n_cores); return std::nullopt; } @@ -3737,7 +3779,8 @@ namespace kagome::parachain { [&](const runtime::FreeCore &) -> std::optional { SL_TRACE( logger_, - "Invalid CoreIndex, core is not assigned to any para_id. (candidate_hash={}, core_index={}, validator={}, n_cores={})", + "Invalid CoreIndex, core is not assigned to any para_id. " + "(candidate_hash={}, core_index={}, validator={}, n_cores={})", candidate_hash, core_index, statement_validator_index, @@ -3750,13 +3793,13 @@ namespace kagome::parachain { } if (*assigned_para_id != candidate_para_id) { - SL_TRACE( - logger_, - "Invalid CoreIndex, core is assigned to a different para_id. (candidate_hash={}, core_index={}, validator={}, n_cores={})", - candidate_hash, - core_index, - statement_validator_index, - n_cores); + SL_TRACE(logger_, + "Invalid CoreIndex, core is assigned to a different para_id. " + "(candidate_hash={}, core_index={}, validator={}, n_cores={})", + candidate_hash, + core_index, + statement_validator_index, + n_cores); return std::nullopt; } return core_index; @@ -4436,13 +4479,13 @@ namespace kagome::parachain { const SignedFullStatementWithPVD &statement) { const CandidateHash candidate_hash = candidateHashFrom(getPayload(statement)); - SL_TRACE( - logger_, - "Sharing statement. (relay parent={}, candidate hash={}, our_index={}, statement_ix={})", - relay_parent, - candidate_hash, - *per_relay_parent.our_index, - statement.payload.ix); + SL_TRACE(logger_, + "Sharing statement. (relay parent={}, candidate hash={}, " + "our_index={}, statement_ix={})", + relay_parent, + candidate_hash, + *per_relay_parent.our_index, + statement.payload.ix); BOOST_ASSERT(per_relay_parent.our_index); @@ -4656,14 +4699,14 @@ namespace kagome::parachain { return; } if (!validation_result) { - SL_WARN( - self->logger_, - "Candidate {} on relay_parent {}, para_id {} validation failed with " - "error: {}", - candidate_hash, - candidate.descriptor.relay_parent, - candidate.descriptor.para_id, - validation_result.error().message()); + SL_WARN(self->logger_, + "Candidate {} on relay_parent {}, para_id {} validation failed " + "with " + "error: {}", + candidate_hash, + candidate.descriptor.relay_parent, + candidate.descriptor.para_id, + validation_result.error().message()); return; } @@ -5157,12 +5200,12 @@ namespace kagome::parachain { auto per_relay_parent = tryGetStateByRelayParent(relay_parent); if (!per_relay_parent) { - SL_TRACE( - logger_, - "Candidate relay parent went out of view for valid advertisement. (peer id={}, para id={}, relay parent={})", - peer_id, - para_id, - relay_parent); + SL_TRACE(logger_, + "Candidate relay parent went out of view for valid " + "advertisement. (peer id={}, para id={}, relay parent={})", + peer_id, + para_id, + relay_parent); return outcome::success(); } diff --git a/core/parachain/validator/parachain_processor.hpp b/core/parachain/validator/parachain_processor.hpp index 3c52616c40..f8f2a2506a 100644 --- a/core/parachain/validator/parachain_processor.hpp +++ b/core/parachain/validator/parachain_processor.hpp @@ -18,6 +18,8 @@ #include "authority_discovery/query/query.hpp" #include "common/ref_cache.hpp" #include "common/visitor.hpp" +#include "consensus/babe/babe_config_repository.hpp" +#include "consensus/timeline/slots_util.hpp" #include "crypto/hasher.hpp" #include "metrics/metrics.hpp" #include "network/peer_manager.hpp" @@ -153,7 +155,10 @@ namespace kagome::parachain { babe_status_observable, std::shared_ptr query_audi, std::shared_ptr prospective_parachains, - std::shared_ptr block_tree); + std::shared_ptr block_tree, + LazySPtr slots_util, + std::shared_ptr + babe_config_repo); ~ParachainProcessorImpl() = default; /** @@ -599,6 +604,8 @@ namespace kagome::parachain { const RelayHash &relay_parent, const CandidateHash &candidate_hash, GroupIndex group_index); + outcome::result getBabeRandomness( + const primitives::BlockHeader &block_header); void request_attested_candidate(const libp2p::peer::PeerId &peer, RelayParentState &relay_parent_state, const RelayHash &relay_parent, @@ -931,7 +938,8 @@ namespace kagome::parachain { * @param relay_parent The hash of the relay parent block for which the * backing task is to be created. */ - void createBackingTask(const primitives::BlockHash &relay_parent); + void createBackingTask(const primitives::BlockHash &relay_parent, + const network::HashedBlockHeader &block_header); /** * @brief The `initNewBackingTask` function is responsible for initializing @@ -942,7 +950,8 @@ namespace kagome::parachain { * validator index, required collator, and table context. */ outcome::result initNewBackingTask( - const primitives::BlockHash &relay_parent); + const primitives::BlockHash &relay_parent, + const network::HashedBlockHeader &block_header); void spawn_and_update_peer(const primitives::AuthorityDiscoveryId &id); @@ -1050,6 +1059,8 @@ namespace kagome::parachain { primitives::events::BabeStateEventSubscriberPtr babe_status_observer_; std::shared_ptr query_audi_; std::shared_ptr> per_session_; + LazySPtr slots_util_; + std::shared_ptr babe_config_repo_; primitives::events::ChainSub chain_sub_; std::shared_ptr worker_pool_handler_; From 0ea84b34c33632041bc30a8ce1fe6e225c93cefa Mon Sep 17 00:00:00 2001 From: Dmitriy Khaustov aka xDimon Date: Mon, 22 Apr 2024 09:23:55 +0300 Subject: [PATCH 40/71] draft Signed-off-by: Dmitriy Khaustov aka xDimon --- .../impl/dispute_coordinator_impl.cpp | 124 ++++++++++------ .../impl/dispute_coordinator_impl.hpp | 5 +- .../impl/prioritized_selection.cpp | 20 +++ core/dispute_coordinator/types.hpp | 51 ++++++- core/log/configurator.cpp | 2 +- core/network/impl/peer_manager_impl.cpp | 30 ++-- .../0000-validator-disabling.toml | 18 +-- .../0001-parachains-pvf.toml | 134 ++++++++++++++++++ .../0001-parachains-pvf.zndsl | 84 +++++++++++ 9 files changed, 394 insertions(+), 74 deletions(-) create mode 100644 zombienet/0001-parachains-pvf/0001-parachains-pvf.toml create mode 100644 zombienet/0001-parachains-pvf/0001-parachains-pvf.zndsl diff --git a/core/dispute_coordinator/impl/dispute_coordinator_impl.cpp b/core/dispute_coordinator/impl/dispute_coordinator_impl.cpp index b1e4e27a34..fcc665cc95 100644 --- a/core/dispute_coordinator/impl/dispute_coordinator_impl.cpp +++ b/core/dispute_coordinator/impl/dispute_coordinator_impl.cpp @@ -63,7 +63,7 @@ namespace kagome::dispute { [&](const ValidDisputeStatement &kind) { return visit_in_place( kind, - [&](const Explicit &) { + [&](const Explicit &x) { std::array magic{'D', 'I', 'S', 'P'}; bool validity = true; return scale::encode( @@ -91,6 +91,15 @@ namespace kagome::dispute { std::array magic{'A', 'P', 'P', 'R'}; return scale::encode( std::tie(magic, candidate_hash, session)); + }, + [&](const ApprovalCheckingMultipleCandidates &candidates) { + std::array magic{'A', 'P', 'P', 'R'}; + if (candidates.size() == 1) { + return scale::encode( + std::tie(magic, candidates.front(), session)); + } else { + return scale::encode(std::tie(magic, candidates, session)); + } }); }, [&](const InvalidDisputeStatement &kind) { @@ -320,7 +329,7 @@ namespace kagome::dispute { // https://github.com/paritytech/polkadot/blob/40974fb99c86f5c341105b7db53c7aa0df707d66/node/core/dispute-coordinator/src/lib.rs#L298 for (auto &[session, candidate_hash, status] : active_disputes) { auto env_opt = makeCandidateEnvironment( - *session_keys_, *rolling_session_window_, session); + *session_keys_, *rolling_session_window_, session, first_leaf.hash); if (not env_opt.has_value()) { continue; } @@ -535,6 +544,7 @@ namespace kagome::dispute { auto res = process_active_leaves_update(update); if (res.has_error()) { SL_ERROR(log_, "Can't handle active list update: {}", res.error()); + std::ignore = process_active_leaves_update(update); return; } } @@ -550,18 +560,6 @@ namespace kagome::dispute { return outcome::success(); } - // Obtain the session info, for sake of `ValidatorId`s either from the - // rolling session window. Must be called _after_ `fn - // cache_session_info_for_head` which guarantees that the session info is - // available for the current session. - auto session_info_opt = rolling_session_window_->session_info(session); - if (not session_info_opt.has_value()) { - SL_WARN(log_, - "Could not retrieve session info from rolling session window"); - return outcome::success(); - } - auto &session_info = session_info_opt.value().get(); - // Scraped on-chain backing votes for the candidates with the new active // leaf as if we received them via gossip. for (auto &[candidate_receipt, backers] : @@ -571,6 +569,11 @@ namespace kagome::dispute { SL_TRACE(log_, "Importing backing votes from chain for candidate"); + OUTCOME_TRY(session, api_->session_index_for_child(relay_parent)); + OUTCOME_TRY(session_info_opt, api_->session_info(relay_parent, session)); + BOOST_ASSERT(session_info_opt.has_value()); + const auto &session_info = session_info_opt.value(); + std::vector> statements; for (auto &[validator_index, attestation] : backers) { if (validator_index >= session_info.validators.size()) { @@ -626,6 +629,9 @@ namespace kagome::dispute { } return true; }; + if (not check_sig()) { + check_sig(); + } BOOST_ASSERT(check_sig()); Indexed signed_dispute_statement{ @@ -978,12 +984,18 @@ namespace kagome::dispute { DisputeCoordinatorImpl::makeCandidateEnvironment( crypto::SessionKeys &session_keys, RollingSessionWindow &rolling_session_window, - SessionIndex session) { - auto session_info_opt = rolling_session_window.session_info(session); + SessionIndex session, + primitives::BlockHash relay_parent) { + auto session_info_opt_res = api_->session_info(relay_parent, session); + if (session_info_opt_res.has_error()) { + // TODO log + return std::nullopt; + } + auto session_info_opt = session_info_opt_res.value(); if (not session_info_opt.has_value()) { return std::nullopt; } - auto &session_info = session_info_opt.value().get(); + auto session_info = std::move(session_info_opt.value()); std::unordered_set controlled_indices; auto keypair = session_keys.getParaKeyPair(session_info.validators); @@ -992,7 +1004,7 @@ namespace kagome::dispute { } return CandidateEnvironment{.session_index = session, - .session = session_info, + .session = std::move(session_info), .controlled_indices = controlled_indices}; } @@ -1015,16 +1027,6 @@ namespace kagome::dispute { .hash(*hasher_) : boost::relaxed_get(candidate_receipt); - auto env_opt = makeCandidateEnvironment( - *session_keys_, *rolling_session_window_, session); - if (not env_opt.has_value()) { - SL_DEBUG(log_, - "We are lacking a `SessionInfo` for handling import of " - "statements."); - return outcome::success(false); - } - auto &env = env_opt.value(); - // In case we are not provided with a candidate receipt we operate under // the assumption, that a previous vote which included a // `CandidateReceipt` was seen. This holds since every block is preceded @@ -1062,6 +1064,16 @@ namespace kagome::dispute { relay_parent = old_state_opt->candidate_receipt.descriptor.relay_parent; } + auto env_opt = makeCandidateEnvironment( + *session_keys_, *rolling_session_window_, session, relay_parent); + if (not env_opt.has_value()) { + SL_DEBUG(log_, + "We are lacking a `SessionInfo` for handling import of " + "statements."); + return outcome::success(false); + } + auto &env = env_opt.value(); + auto disabled_validators_res = api_->disabled_validators(relay_parent); if (disabled_validators_res.has_error()) { SL_WARN(log_, @@ -1154,19 +1166,24 @@ namespace kagome::dispute { statements.end()); } ++imported_valid_votes; - return true; + // return true; } - auto &existing = std::get<0>(it->second); - return visit_in_place( - valid, - [&](const Explicit &) { - return not is_type(existing); - }, - [&](const BackingSeconded &) { return false; }, - [&](const BackingValid &) { return false; }, - [&](const ApprovalChecking &) { - return not is_type(existing); - }); + // auto &existing = std::get<0>(it->second); + // return visit_in_place( + // valid, + // [&](const Explicit &) { + // return not is_type(existing); + // }, + // [&](const BackingSeconded &) { return false; }, + // [&](const BackingValid &) { return false; }, + // [&](const ApprovalChecking &) { + // return not is_type(existing); + // }, + // [&](const ApprovalCheckingMultipleCandidates &) { + // return not + // is_type( + // existing); + // }); }, [&](const InvalidDisputeStatement &invalid) { auto [it, fresh] = votes.invalid.emplace( @@ -1181,9 +1198,9 @@ namespace kagome::dispute { statements.end()); } ++imported_invalid_votes; - return true; + // return true; } - return false; + // return false; }); } @@ -1467,7 +1484,11 @@ namespace kagome::dispute { sig, session}; - SL_TRACE(log_, "Sending out own approval vote"); + SL_TRACE( + log_, + "Sending out own approval vote. session={}, candidate_hash={}", + session, + candidate_hash); auto dispute_message_res = make_dispute_message( env.session, new_state.votes, statement, validator_index); @@ -1791,7 +1812,12 @@ namespace kagome::dispute { bool valid) { // https://github.com/paritytech/polkadot/blob/40974fb99c86f5c341105b7db53c7aa0df707d66/node/core/dispute-coordinator/src/initialized.rs#L1102 - SL_TRACE(log_, "Issuing local statement for candidate!"); + SL_TRACE(log_, + "Issuing local statement for candidate! " + "session={}, candidate_hash={}, relay_parent={}", + session, + candidate_hash, + candidate_receipt.descriptor.relay_parent); // Load environment: @@ -2058,7 +2084,12 @@ namespace kagome::dispute { std::move(candidate_receipt), valid); - SL_TRACE(log_, "DisputeCoordinatorMessage::IssueLocalStatement"); + SL_TRACE(log_, + "DisputeCoordinatorMessage::IssueLocalStatement. " + "session={}, candidate_hash={}, relay_parent={}", + session, + candidate_hash, + candidate_receipt.descriptor.relay_parent); auto res = issue_local_statement( candidate_hash, candidate_receipt, session, valid); @@ -2424,8 +2455,7 @@ namespace kagome::dispute { // unaffected. SL_DEBUG(log_, - "Peer {} sent completely redundant votes " - "within a single batch " + "Peer {} sent completely redundant votes within a single batch " "- that looks fishy!", peer); diff --git a/core/dispute_coordinator/impl/dispute_coordinator_impl.hpp b/core/dispute_coordinator/impl/dispute_coordinator_impl.hpp index 47872b2ee1..091e459f55 100644 --- a/core/dispute_coordinator/impl/dispute_coordinator_impl.hpp +++ b/core/dispute_coordinator/impl/dispute_coordinator_impl.hpp @@ -192,10 +192,11 @@ namespace kagome::dispute { std::vector> statements, CbOutcome &&cb); - static std::optional makeCandidateEnvironment( + std::optional makeCandidateEnvironment( crypto::SessionKeys &session_keys, RollingSessionWindow &rolling_session_window, - SessionIndex session); + SessionIndex session, + primitives::BlockHash relay_parent); outcome::result process_on_chain_votes(ScrapedOnChainVotes votes); diff --git a/core/dispute_coordinator/provisioner/impl/prioritized_selection.cpp b/core/dispute_coordinator/provisioner/impl/prioritized_selection.cpp index 359257b623..ae9f646870 100644 --- a/core/dispute_coordinator/provisioner/impl/prioritized_selection.cpp +++ b/core/dispute_coordinator/provisioner/impl/prioritized_selection.cpp @@ -96,9 +96,17 @@ namespace kagome::dispute { // Transform all `CandidateVotes` into `MultiDisputeStatementSet`. MultiDisputeStatementSet result; + + SL_TRACE(log_, "XXX >>> PrioritizedSelection::select_disputes"); + for (auto &[key, votes] : dispute_candidate_votes) { auto &[session_index, candidate_hash] = key; + SL_TRACE(log_, + "XXX session={}, candidate_hash={}", + session_index, + candidate_hash); + auto &statement_set = result.emplace_back( DisputeStatementSet{candidate_hash, session_index, {}}); @@ -108,6 +116,11 @@ namespace kagome::dispute { ValidDisputeStatement(statement), // validator_index, validator_signature); + + SL_TRACE(log_, + "XXX Valid, validator_index={}, validator_sign={}", + validator_index, + validator_signature); } for (auto &[validator_index, value] : votes.invalid) { @@ -116,9 +129,16 @@ namespace kagome::dispute { InvalidDisputeStatement(statement), validator_index, validator_signature); + + SL_TRACE(log_, + "XXX Invalid, validator_index={}, validator_sign={}", + validator_index, + validator_signature); } } + SL_TRACE(log_, "XXX <<< PrioritizedSelection::select_disputes"); + return result; } diff --git a/core/dispute_coordinator/types.hpp b/core/dispute_coordinator/types.hpp index 83b1c85d43..b748b7283b 100644 --- a/core/dispute_coordinator/types.hpp +++ b/core/dispute_coordinator/types.hpp @@ -48,10 +48,21 @@ namespace kagome::dispute { using BackingValid = Tagged; /// An approval vote from the approval checking phase. using ApprovalChecking = Tagged; + /// An approval vote from the new version. + /// We can't create this version until all nodes have been updated to support + /// it and max_approval_coalesce_count is set to more than 1. + using ApprovalCheckingMultipleCandidates = + Tagged, + struct ApprovalCheckingMultipleCandidatesTag>; /// A valid statement, of the given kind using ValidDisputeStatement = - boost::variant; + boost::variant; /// An invalid statement, of the given kind. using InvalidDisputeStatement = boost::variant; @@ -152,7 +163,7 @@ namespace kagome::dispute { /// The session the candidate appeared in. SessionIndex session_index; /// Session for above index. - SessionInfo &session; + SessionInfo session; /// Validator indices controlled by this node. std::unordered_set controlled_indices{}; }; @@ -219,7 +230,7 @@ namespace kagome::dispute { /// A set of statements about a specific candidate. struct DisputeStatementSet { - SCALE_TIE(3); + // SCALE_TIE(3); /// The candidate referenced by this set. CandidateHash candidate_hash; @@ -231,6 +242,22 @@ namespace kagome::dispute { std::vector< std::tuple> statements; + + template + friend inline Stream &operator<<(Stream &s, const DisputeStatementSet &x) { + s << x.candidate_hash; + s << x.session; + s << x.statements; + return s; + } + + template + friend inline Stream &operator>>(Stream &s, DisputeStatementSet &x) { + s >> x.candidate_hash; + s >> x.session; + s >> x.statements; + return s; + } }; /// A set of dispute statements. @@ -238,7 +265,7 @@ namespace kagome::dispute { /// Scraped runtime backing votes and resolved disputes. struct ScrapedOnChainVotes { - SCALE_TIE(3); + // SCALE_TIE(3); /// The session in which the block was included. SessionIndex session; @@ -254,6 +281,22 @@ namespace kagome::dispute { /// Note that the above `backing_validators` are /// unrelated to the backers of the disputes candidates. MultiDisputeStatementSet disputes; + + template + friend inline Stream &operator<<(Stream &s, const ScrapedOnChainVotes &x) { + s << x.session; + s << x.backing_validators_per_candidate; + s << x.disputes; + return s; + } + + template + friend inline Stream &operator>>(Stream &s, ScrapedOnChainVotes &x) { + s >> x.session; + s >> x.backing_validators_per_candidate; + s >> x.disputes; + return s; + } }; /// Describes a relay-chain block by the para-chain candidates diff --git a/core/log/configurator.cpp b/core/log/configurator.cpp index c06584eae0..b0e2b4359d 100644 --- a/core/log/configurator.cpp +++ b/core/log/configurator.cpp @@ -14,7 +14,7 @@ namespace kagome::log { sinks: - name: console type: console - stream: stderr + stream: stdout thread: name color: false latency: 0 diff --git a/core/network/impl/peer_manager_impl.cpp b/core/network/impl/peer_manager_impl.cpp index fe1fbbc300..519e7cdf0b 100644 --- a/core/network/impl/peer_manager_impl.cpp +++ b/core/network/impl/peer_manager_impl.cpp @@ -299,6 +299,8 @@ namespace kagome::network { } void PeerManagerImpl::align() { + SL_INFO(log_, "DEBUG: call align()"); + SL_TRACE(log_, "Try to align peers number"); const auto hard_limit = app_config_.inPeers() + app_config_.inPeersLight() @@ -598,6 +600,8 @@ namespace kagome::network { } void PeerManagerImpl::processDiscoveredPeer(const PeerId &peer_id) { + SL_INFO(log_, "DEBUG: call processDiscoveredPeer()"); + // Ignore himself if (isSelfPeer(peer_id)) { return; @@ -648,13 +652,16 @@ namespace kagome::network { return; } + SL_INFO(self->log_, "DEBUG: call openOutgoing::()"); + auto &peer_id = peer_info.id; if (not stream_res.has_value()) { - self->log_->verbose("Unable to create stream {} with {}: {}", - protocol->protocolName(), - peer_id, - stream_res.error()); + SL_VERBOSE(self->log_, + "Unable to create stream {} with {}: {}", + protocol->protocolName(), + peer_id, + stream_res.error()); self->connecting_peers_.erase(peer_id); self->disconnectFromPeer(peer_id); return; @@ -663,7 +670,7 @@ namespace kagome::network { ? PeerType::PEER_TYPE_OUT : PeerType::PEER_TYPE_IN; - // Add to active peer list + // Add to the active peer list if (auto [ap_it, added] = self->active_peers_.emplace( peer_id, PeerDescriptor{peer_type, self->clock_->now()}); added) { @@ -672,12 +679,11 @@ namespace kagome::network { // And remove from queue if (auto piq_it = self->peers_in_queue_.find(peer_id); piq_it != self->peers_in_queue_.end()) { - auto qtc_it = - std::find_if(self->queue_to_connect_.cbegin(), - self->queue_to_connect_.cend(), - [&peer_id = peer_id](const auto &item) { - return peer_id == item.get(); - }); + auto qtc_it = std::find_if(self->queue_to_connect_.cbegin(), + self->queue_to_connect_.cend(), + [&peer_id](const auto &item) { + return peer_id == item.get(); + }); self->queue_to_connect_.erase(qtc_it); self->peers_in_queue_.erase(piq_it); BOOST_ASSERT(self->queue_to_connect_.size() @@ -769,6 +775,8 @@ namespace kagome::network { } void PeerManagerImpl::processFullyConnectedPeer(const PeerId &peer_id) { + SL_INFO(log_, "DEBUG: call processFullyConnectedPeer()"); + // Skip connection to itself if (isSelfPeer(peer_id)) { connecting_peers_.erase(peer_id); diff --git a/zombienet/0000-validator-disabling/0000-validator-disabling.toml b/zombienet/0000-validator-disabling/0000-validator-disabling.toml index 82b1043837..d395241d25 100644 --- a/zombienet/0000-validator-disabling/0000-validator-disabling.toml +++ b/zombienet/0000-validator-disabling/0000-validator-disabling.toml @@ -21,21 +21,21 @@ requests = { memory = "2G", cpu = "1" } # [[relaychain.node_groups]] # name = "honest-validator" # count = 3 -# args = ["-lparachain=debug"] +# args = ["-lparachain=trace", "--parachain-single-process"] [[relaychain.node_groups]] name = "honest-validator" - count = 3 - args = [ "-lparachain=trace", "-lgrandpa=trace" ] + count = 4 + args = [ "-lparachain=trace", "-lgrandpa=trace", "--parachain-single-process" ] command = "kagome" prometheus_prefix = "kagome" - [[relaychain.node_groups]] - image = "{{MALUS_IMAGE}}" - name = "malus-validator" - command = "malus suggest-garbage-candidate" - args = ["-lMALUS=trace"] - count = 1 +# [[relaychain.node_groups]] +# image = "{{MALUS_IMAGE}}" +# name = "malus-validator" +# command = "malus suggest-garbage-candidate" +# args = ["-lMALUS=trace"] +# count = 1 [[parachains]] id = 1000 diff --git a/zombienet/0001-parachains-pvf/0001-parachains-pvf.toml b/zombienet/0001-parachains-pvf/0001-parachains-pvf.toml new file mode 100644 index 0000000000..5b41ab84ce --- /dev/null +++ b/zombienet/0001-parachains-pvf/0001-parachains-pvf.toml @@ -0,0 +1,134 @@ +[settings] +timeout = 1000 + +[relaychain] +chain = "rococo-local" + +[relaychain.default_resources] +limits = { memory = "4G", cpu = "2" } +requests = { memory = "2G", cpu = "1" } + + [[relaychain.nodes]] + name = "alice" + command = "kagome" + prometheus_prefix = "kagome" + args = [ "--alice", "-lparachain=debug", "-lruntime=debug", "-ldispute=trace" ] + + [[relaychain.nodes]] + name = "bob" + command = "kagome" + prometheus_prefix = "kagome" + args = [ "--bob", "-lparachain=debug", "-lruntime=debug", "-ldispute=trace" ] + + [[relaychain.nodes]] + name = "charlie" + command = "kagome" + prometheus_prefix = "kagome" + args = [ "--charlie", "-lparachain=debug", "-lruntime=debug", "-ldispute=trace" ] + + [[relaychain.nodes]] + name = "dave" + command = "kagome" + prometheus_prefix = "kagome" + args = [ "--dave", "-lparachain=debug", "-lruntime=debug", "-ldispute=trace" ] + + [[relaychain.nodes]] + name = "ferdie" + args = [ "--ferdie", "-lparachain=debug,runtime=debug" ] + + [[relaychain.nodes]] + name = "eve" + args = [ "--eve", "-lparachain=debug,runtime=debug"] + + [[relaychain.nodes]] + name = "one" + args = [ "--one", "-lparachain=debug,runtime=debug" ] + + [[relaychain.nodes]] + name = "two" + args = [ "--two", "-lparachain=debug,runtime=debug"] + +[[parachains]] +id = 2000 +addToGenesis = true +genesis_state_generator = "undying-collator export-genesis-state --pov-size=100000 --pvf-complexity=1" + + [parachains.collator] + name = "collator01" + command = "undying-collator" + args = ["-lparachain=debug", "--pov-size=100000", "--pvf-complexity=1", "--parachain-id=2000"] + +[[parachains]] +id = 2001 +addToGenesis = true +genesis_state_generator = "undying-collator export-genesis-state --pov-size=100000 --pvf-complexity=10" + + [parachains.collator] + name = "collator02" + command = "undying-collator" + args = ["-lparachain=debug", "--pov-size=100000", "--parachain-id=2001", "--pvf-complexity=10"] + +[[parachains]] +id = 2002 +addToGenesis = true +genesis_state_generator = "undying-collator export-genesis-state --pov-size=100000 --pvf-complexity=100" + + [parachains.collator] + name = "collator03" + command = "undying-collator" + args = ["-lparachain=debug", "--pov-size=100000", "--parachain-id=2002", "--pvf-complexity=100"] + +[[parachains]] +id = 2003 +addToGenesis = true +genesis_state_generator = "undying-collator export-genesis-state --pov-size=20000 --pvf-complexity=300" + + [parachains.collator] + name = "collator04" + command = "undying-collator" + args = ["-lparachain=debug", "--pov-size=20000", "--parachain-id=2003", "--pvf-complexity=300"] + +[[parachains]] +id = 2004 +addToGenesis = true +genesis_state_generator = "undying-collator export-genesis-state --pov-size=100000 --pvf-complexity=300" + + [parachains.collator] + name = "collator05" + command = "undying-collator" + args = ["-lparachain=debug", "--pov-size=100000", "--parachain-id=2004", "--pvf-complexity=300"] + +[[parachains]] +id = 2005 +addToGenesis = true +genesis_state_generator = "undying-collator export-genesis-state --pov-size=20000 --pvf-complexity=400" + + [parachains.collator] + name = "collator06" + command = "undying-collator" + args = ["-lparachain=debug", "--pov-size=20000", "--pvf-complexity=400", "--parachain-id=2005"] + +[[parachains]] +id = 2006 +addToGenesis = true +genesis_state_generator = "undying-collator export-genesis-state --pov-size=100000 --pvf-complexity=300" + + [parachains.collator] + name = "collator07" + command = "undying-collator" + args = ["-lparachain=debug", "--pov-size=100000", "--pvf-complexity=300", "--parachain-id=2006"] + +[[parachains]] +id = 2007 +addToGenesis = true +genesis_state_generator = "undying-collator export-genesis-state --pov-size=100000 --pvf-complexity=300" + + [parachains.collator] + name = "collator08" + command = "undying-collator" + args = ["-lparachain=debug", "--pov-size=100000", "--pvf-complexity=300", "--parachain-id=2007"] + +[types.Header] +number = "u64" +parent_hash = "Hash" +post_state = "Hash" diff --git a/zombienet/0001-parachains-pvf/0001-parachains-pvf.zndsl b/zombienet/0001-parachains-pvf/0001-parachains-pvf.zndsl new file mode 100644 index 0000000000..8ac805ed65 --- /dev/null +++ b/zombienet/0001-parachains-pvf/0001-parachains-pvf.zndsl @@ -0,0 +1,84 @@ +Description: PVF preparation & execution time +Network: ./0001-parachains-pvf.toml +Creds: config + +# Check authority status. +alice: reports node_roles is 4 +bob: reports node_roles is 4 +charlie: reports node_roles is 4 +dave: reports node_roles is 4 +eve: reports node_roles is 4 +ferdie: reports node_roles is 4 +one: reports node_roles is 4 +two: reports node_roles is 4 + +# Ensure parachains are registered. +alice: parachain 2000 is registered within 60 seconds +bob: parachain 2001 is registered within 60 seconds +charlie: parachain 2002 is registered within 60 seconds +dave: parachain 2003 is registered within 60 seconds +ferdie: parachain 2004 is registered within 60 seconds +eve: parachain 2005 is registered within 60 seconds +one: parachain 2006 is registered within 60 seconds +two: parachain 2007 is registered within 60 seconds + +# Ensure parachains made progress. +alice: parachain 2000 block height is at least 10 within 300 seconds +alice: parachain 2001 block height is at least 10 within 300 seconds +alice: parachain 2002 block height is at least 10 within 300 seconds +alice: parachain 2003 block height is at least 10 within 300 seconds +alice: parachain 2004 block height is at least 10 within 300 seconds +alice: parachain 2005 block height is at least 10 within 300 seconds +alice: parachain 2006 block height is at least 10 within 300 seconds +alice: parachain 2007 block height is at least 10 within 300 seconds + +alice: reports substrate_block_height{status="finalized"} is at least 30 within 400 seconds + +# Check preparation time is under 10s. +# Check all buckets <= 10. +alice: reports histogram kagome_pvf_preparation_time has at least 1 samples in buckets ["0.1", "0.5", "1", "2", "3", "10"] within 10 seconds +bob: reports histogram kagome_pvf_preparation_time has at least 1 samples in buckets ["0.1", "0.5", "1", "2", "3", "10"] within 10 seconds +charlie: reports histogram kagome_pvf_preparation_time has at least 1 samples in buckets ["0.1", "0.5", "1", "2", "3", "10"] within 10 seconds +dave: reports histogram kagome_pvf_preparation_time has at least 1 samples in buckets ["0.1", "0.5", "1", "2", "3", "10"] within 10 seconds +ferdie: reports histogram polkadot_pvf_preparation_time has at least 1 samples in buckets ["0.1", "0.5", "1", "2", "3", "10"] within 10 seconds +eve: reports histogram polkadot_pvf_preparation_time has at least 1 samples in buckets ["0.1", "0.5", "1", "2", "3", "10"] within 10 seconds +one: reports histogram polkadot_pvf_preparation_time has at least 1 samples in buckets ["0.1", "0.5", "1", "2", "3", "10"] within 10 seconds +two: reports histogram polkadot_pvf_preparation_time has at least 1 samples in buckets ["0.1", "0.5", "1", "2", "3", "10"] within 10 seconds + +# Check all buckets >= 20. +alice: reports histogram kagome_pvf_preparation_time has 0 samples in buckets ["20", "30", "60", "120", "+Inf"] within 10 seconds +bob: reports histogram kagome_pvf_preparation_time has 0 samples in buckets ["20", "30", "60", "120", "+Inf"] within 10 seconds +charlie: reports histogram kagome_pvf_preparation_time has 0 samples in buckets ["20", "30", "60", "120", "+Inf"] within 10 seconds +dave: reports histogram kagome_pvf_preparation_time has 0 samples in buckets ["20", "30", "60", "120", "+Inf"] within 10 seconds +ferdie: reports histogram polkadot_pvf_preparation_time has 0 samples in buckets ["20", "30", "60", "120", "+Inf"] within 10 seconds +eve: reports histogram polkadot_pvf_preparation_time has 0 samples in buckets ["20", "30", "60", "120", "+Inf"] within 10 seconds +one: reports histogram polkadot_pvf_preparation_time has 0 samples in buckets ["20", "30", "60", "120", "+Inf"] within 10 seconds +two: reports histogram polkadot_pvf_preparation_time has 0 samples in buckets ["20", "30", "60", "120", "+Inf"] within 10 seconds + +# Check execution time. +# There are two different timeout conditions: DEFAULT_BACKING_EXECUTION_TIMEOUT(2s) and +# DEFAULT_APPROVAL_EXECUTION_TIMEOUT(12s). Currently these are not differentiated by metrics +# because the metrics are defined in `polkadot-node-core-pvf` which is a level below +# the relevant subsystems. +# That being said, we will take the simplifying assumption of testing only the +# 2s timeout. +# We do this check by ensuring all executions fall into bucket le="2" or lower. +# First, check if we have at least 1 sample, but we should have many more. +alice: reports histogram kagome_pvf_execution_time has at least 1 samples in buckets ["0.1", "0.5", "1", "2"] within 10 seconds +bob: reports histogram kagome_pvf_execution_time has at least 1 samples in buckets ["0.1", "0.5", "1", "2"] within 10 seconds +charlie: reports histogram kagome_pvf_execution_time has at least 1 samples in buckets ["0.1", "0.5", "1", "2"] within 10 seconds +dave: reports histogram kagome_pvf_execution_time has at least 1 samples in buckets ["0.1", "0.5", "1", "2"] within 10 seconds +ferdie: reports histogram polkadot_pvf_execution_time has at least 1 samples in buckets ["0.1", "0.5", "1", "2"] within 10 seconds +eve: reports histogram polkadot_pvf_execution_time has at least 1 samples in buckets ["0.1", "0.5", "1", "2"] within 10 seconds +one: reports histogram polkadot_pvf_execution_time has at least 1 samples in buckets ["0.1", "0.5", "1", "2"] within 10 seconds +two: reports histogram polkadot_pvf_execution_time has at least 1 samples in buckets ["0.1", "0.5", "1", "2"] within 10 seconds + +# Check if we have no samples > 2s. +alice: reports histogram kagome_pvf_execution_time has 0 samples in buckets ["3", "4", "5", "6", "+Inf"] within 10 seconds +bob: reports histogram kagome_pvf_execution_time has 0 samples in buckets ["3", "4", "5", "6", "+Inf"] within 10 seconds +charlie: reports histogram kagome_pvf_execution_time has 0 samples in buckets ["3", "4", "5", "6", "+Inf"] within 10 seconds +dave: reports histogram kagome_pvf_execution_time has 0 samples in buckets ["3", "4", "5", "6", "+Inf"] within 10 seconds +ferdie: reports histogram polkadot_pvf_execution_time has 0 samples in buckets ["3", "4", "5", "6", "+Inf"] within 10 seconds +eve: reports histogram polkadot_pvf_execution_time has 0 samples in buckets ["3", "4", "5", "6", "+Inf"] within 10 seconds +one: reports histogram polkadot_pvf_execution_time has 0 samples in buckets ["3", "4", "5", "6", "+Inf"] within 10 seconds +two: reports histogram polkadot_pvf_execution_time has 0 samples in buckets ["3", "4", "5", "6", "+Inf"] within 10 seconds From eb3daf0f31e5b7b9806d3064a28fbed3b8ae8c45 Mon Sep 17 00:00:00 2001 From: Dmitriy Khaustov aka xDimon Date: Mon, 20 May 2024 17:45:56 +0300 Subject: [PATCH 41/71] tmp: disable disputes sending Signed-off-by: Dmitriy Khaustov aka xDimon --- core/dispute_coordinator/impl/dispute_coordinator_impl.cpp | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/core/dispute_coordinator/impl/dispute_coordinator_impl.cpp b/core/dispute_coordinator/impl/dispute_coordinator_impl.cpp index b1e4e27a34..d5245bf7bd 100644 --- a/core/dispute_coordinator/impl/dispute_coordinator_impl.cpp +++ b/core/dispute_coordinator/impl/dispute_coordinator_impl.cpp @@ -2507,6 +2507,12 @@ namespace kagome::dispute { } } + SL_TRACE( // FIXME It's temporary code. Remove after tests + log_, + "Dispute (candidate={}) did not send. Disabled", + candidate_hash); + return; + auto protocol = router_->getSendDisputeProtocol(); BOOST_ASSERT_MSG(protocol, "Router did not provide `send dispute` protocol"); From 398304366e8b374b9e22f12321bfdac7eb6fd1ad Mon Sep 17 00:00:00 2001 From: iceseer Date: Wed, 22 May 2024 23:03:02 +0300 Subject: [PATCH 42/71] cluster integration Signed-off-by: iceseer --- .../protocols/fetch_attested_candidate.hpp | 5 +- core/network/types/collator_messages.hpp | 8 + .../types/collator_messages_vstaging.hpp | 31 +- core/parachain/backing/cluster.hpp | 3 +- core/parachain/groups.hpp | 9 + .../validator/impl/parachain_processor.cpp | 535 ++++++++++++++++-- .../validator/parachain_processor.hpp | 64 ++- core/parachain/validator/signer.hpp | 5 + .../runtime_api/impl/parachain_host.cpp | 13 + .../runtime_api/impl/parachain_host.hpp | 6 + core/runtime/runtime_api/parachain_host.hpp | 6 + .../runtime_api/parachain_host_types.hpp | 17 + 12 files changed, 638 insertions(+), 64 deletions(-) diff --git a/core/network/impl/protocols/fetch_attested_candidate.hpp b/core/network/impl/protocols/fetch_attested_candidate.hpp index f79e0e2d1a..4812c0a61a 100644 --- a/core/network/impl/protocols/fetch_attested_candidate.hpp +++ b/core/network/impl/protocols/fetch_attested_candidate.hpp @@ -56,11 +56,12 @@ namespace kagome::network { private: std::optional> onRxRequest( - RequestType request, std::shared_ptr /*stream*/) override { + RequestType request, std::shared_ptr stream) override { base().logger()->info( "Fetching attested candidate request.(candidate={})", request.candidate_hash); - auto res = pp_->OnFetchAttestedCandidateRequest(std::move(request)); + auto res = pp_->OnFetchAttestedCandidateRequest( + std::move(request), stream->remotePeerId().value()); if (res.has_error()) { base().logger()->error( "Fetching attested candidate response failed.(error={})", diff --git a/core/network/types/collator_messages.hpp b/core/network/types/collator_messages.hpp index 2bcb169a9e..c475022cfd 100644 --- a/core/network/types/collator_messages.hpp +++ b/core/network/types/collator_messages.hpp @@ -463,6 +463,14 @@ namespace kagome::network { std::optional collator; }; + inline const CandidateHash &candidateHash(const CompactStatement &val) { + auto p = visit_in_place( + val, [&](const auto &v) -> std::reference_wrapper { + return v; + }); + return p.get(); + } + inline CandidateHash candidateHash(const crypto::Hasher &hasher, const CommittedCandidateReceipt &receipt) { auto commitments_hash = diff --git a/core/network/types/collator_messages_vstaging.hpp b/core/network/types/collator_messages_vstaging.hpp index 040d23246a..ae481b8dfd 100644 --- a/core/network/types/collator_messages_vstaging.hpp +++ b/core/network/types/collator_messages_vstaging.hpp @@ -104,6 +104,8 @@ namespace kagome::network::vstaging { } }; + using SignedCompactStatement = IndexedAndSigned; + inline const CandidateHash &candidateHash(const CompactStatement &val) { auto p = visit_in_place( val.inner_value, @@ -121,13 +123,40 @@ namespace kagome::network::vstaging { UNREACHABLE; } + inline CompactStatement from(const network::CompactStatement &stm) { + return visit_in_place( + stm, + [&](const network::CompactStatementSeconded &v) -> CompactStatement { + return CompactStatement(SecondedCandidateHash{ + .hash = v, + }); + }, + [&](const network::CompactStatementValid &v) -> CompactStatement { + return CompactStatement(ValidCandidateHash{ + .hash = v, + }); + }); + } + + inline network::CompactStatement from(const CompactStatement &stm) { + return visit_in_place( + stm.inner_value, + [&](const SecondedCandidateHash &v) -> network::CompactStatement { + return network::CompactStatementSeconded{v.hash}; + }, + [&](const ValidCandidateHash &v) -> network::CompactStatement { + return network::CompactStatementValid{v.hash}; + }, + [&](const auto &) -> network::CompactStatement { UNREACHABLE; }); + } + /// A notification of a signed statement in compact form, for a given /// relay parent. struct StatementDistributionMessageStatement { SCALE_TIE(2); RelayHash relay_parent; - IndexedAndSigned compact; + SignedCompactStatement compact; }; /// All messages for V1 for compatibility with the statement distribution diff --git a/core/parachain/backing/cluster.hpp b/core/parachain/backing/cluster.hpp index 8655b1ae72..d883f8a6c1 100644 --- a/core/parachain/backing/cluster.hpp +++ b/core/parachain/backing/cluster.hpp @@ -228,12 +228,11 @@ namespace kagome::parachain { std::vector> pending_statements_for(ValidatorIndex target) const; - private: bool knows_candidate(ValidatorIndex validator, CandidateHash candidate_hash) const; - bool can_request(ValidatorIndex target, CandidateHash candidate_hash) const; + private: // returns true if it's legal to accept a new `Seconded` message from this // validator. This is either // 1. because we've already accepted it. diff --git a/core/parachain/groups.hpp b/core/parachain/groups.hpp index 26658d668c..b806052e95 100644 --- a/core/parachain/groups.hpp +++ b/core/parachain/groups.hpp @@ -40,6 +40,15 @@ namespace kagome::parachain { } } + bool all_empty() const { + for (const auto &[_, group] : groups) { + if (!group.empty()) { + return false; + } + } + return true; + } + std::optional byValidatorIndex( ValidatorIndex validator_index) const { auto it = by_validator_index.find(validator_index); diff --git a/core/parachain/validator/impl/parachain_processor.cpp b/core/parachain/validator/impl/parachain_processor.cpp index 4b23568ed0..445584923e 100644 --- a/core/parachain/validator/impl/parachain_processor.cpp +++ b/core/parachain/validator/impl/parachain_processor.cpp @@ -82,6 +82,10 @@ OUTCOME_CPP_DEFINE_CATEGORY(kagome::parachain, return "Index out of bound"; case E::INCORRECT_BITFIELD_SIZE: return "Incorrect bitfield size"; + case E::INCORRECT_SIGNATURE: + return "Incorrect signature"; + case E::CLUSTER_TRACKER_ERROR: + return "Cluster tracker error"; } return "Unknown parachain processor error"; } @@ -319,6 +323,64 @@ namespace kagome::parachain { } } + void ParachainProcessorImpl::send_pending_cluster_statements( + const RelayHash &relay_parent, + const libp2p::peer::PeerId &peer_id, + network::CollationVersion version, + ValidatorIndex peer_validator_id, + ParachainProcessorImpl::RelayParentState &relay_parent_state) { + if (!relay_parent_state.local_validator + || relay_parent_state.local_validator->active) { + return; + } + + const auto pending_statements = + relay_parent_state.local_validator->active->cluster_tracker + .pending_statements_for(peer_validator_id); + std::deque, + network::VersionedValidatorProtocolMessage>> + messages; + for (const auto &[originator, compact] : pending_statements) { + if (!candidates_.is_confirmed(candidateHash(compact))) { + continue; + } + + auto res = + pending_statement_network_message(*relay_parent_state.statement_store, + relay_parent, + peer_id, + version, + originator, + network::vstaging::from(compact)); + + if (res) { + relay_parent_state.local_validator->active->cluster_tracker.note_sent( + peer_validator_id, originator, compact); + messages.emplace_back(*res); + } + } + + if (messages.empty()) { + return; + } + + auto se = pm_->getStreamEngine(); + BOOST_ASSERT(se); + + for (auto &[peers, msg] : messages) { + if (auto m = if_type(msg)) { + auto message = std::make_shared< + network::WireMessage>( + std::move(m->get())); + for (const auto &p : peers) { + se->send(p, router_->getValidationProtocolVStaging(), message); + } + } else { + BOOST_ASSERT(false); + } + } + } + void ParachainProcessorImpl::send_pending_grid_messages( const RelayHash &relay_parent, const libp2p::peer::PeerId &peer_id, @@ -511,6 +573,10 @@ namespace kagome::parachain { if (auto it = parachain_state->get().authority_lookup.find(*auth_id); it != parachain_state->get().authority_lookup.end()) { ValidatorIndex vi = it->second; + + send_pending_cluster_statements( + relay_parent, peer_id, version, vi, parachain_state->get()); + send_pending_grid_messages( relay_parent, peer_id, @@ -520,8 +586,6 @@ namespace kagome::parachain { parachain_state->get()); } } - - /// TODO(iceseer): do `cluster view` } void ParachainProcessorImpl::onViewUpdated(const network::ExView &event) { @@ -855,13 +919,15 @@ namespace kagome::parachain { } ParachainProcessorImpl::PerSessionState::PerSessionState( + SessionIndex _session, const runtime::SessionInfo &_session_info, Groups &&_groups, grid::Views &&_grid_view, ValidatorIndex _our_index, const std::shared_ptr &_pm, const std::shared_ptr &_query_audi) - : session_info{_session_info}, + : session{_session}, + session_info{_session_info}, groups{std::move(_groups)}, grid_view{std::move(_grid_view)}, our_index{_our_index}, @@ -902,6 +968,21 @@ namespace kagome::parachain { } } + outcome::result> + ParachainProcessorImpl::fetch_claim_queue(const RelayHash &relay_parent) { + constexpr uint32_t CLAIM_QUEUE_RUNTIME_REQUIREMENT = 11; + OUTCOME_TRY(version, parachain_host_->runtime_api_version(relay_parent)); + if (version < CLAIM_QUEUE_RUNTIME_REQUIREMENT) { + SL_TRACE(logger_, "Runtime doesn't support `request_claim_queue`"); + return std::nullopt; + } + + OUTCOME_TRY(claims, parachain_host_->claim_queue(relay_parent)); + return runtime::ClaimQueueSnapshot{ + .claimes = std::move(claims), + }; + } + outcome::result ParachainProcessorImpl::getBabeRandomness( const primitives::BlockHeader &block_header) { @@ -1010,6 +1091,7 @@ namespace kagome::parachain { Groups g{session_info->validator_groups, minimum_backing_votes}; return RefCache::RefObj( + session_index, *session_info, std::move(g), std::move(grid_view), @@ -1040,6 +1122,11 @@ namespace kagome::parachain { auto mode = prospective_parachains_->prospectiveParachainsMode(relay_parent); + BOOST_ASSERT(mode); + if (!mode) { + SL_ERROR(logger_, + "Prospective parachains are disabled. No sure for correctness"); + } const auto n_cores = cores.size(); std::unordered_map> out_groups; @@ -1107,6 +1194,25 @@ namespace kagome::parachain { statement_store.emplace(per_session_state->value().groups); } + auto maybe_claim_queue = + [&]() -> std::optional { + auto r = fetch_claim_queue(relay_parent); + if (r.has_value()) { + return r.value(); + } + return std::nullopt; + }(); + + const auto seconding_limit = mode->max_candidate_depth + 1; + std::optional local_validator = + find_active_validator_state(validator->validatorIndex(), + per_session_state->value().groups, + cores, + group_rotation_info, + maybe_claim_queue, + seconding_limit, + mode->max_candidate_depth); + SL_VERBOSE(logger_, "Inited new backing task v3.(assigned_para={}, " "assigned_core={}, our index={}, relay " @@ -1138,7 +1244,7 @@ namespace kagome::parachain { .group_rotation_info = group_rotation_info, .minimum_backing_votes = minimum_backing_votes, .authority_lookup = std::move(authority_lookup), - .local_validator = LocalValidatorState{}, + .local_validator = local_validator, .awaiting_validation = {}, .issued_statements = {}, .peers_advertised = {}, @@ -1147,6 +1253,65 @@ namespace kagome::parachain { }; } + std::optional + ParachainProcessorImpl::find_active_validator_state( + ValidatorIndex validator_index, + const Groups &groups, + const std::vector &availability_cores, + const runtime::GroupDescriptor &group_rotation_info, + const std::optional &maybe_claim_queue, + size_t seconding_limit, + size_t max_candidate_depth) { + if (groups.all_empty()) { + return std::nullopt; + } + + const auto our_group = groups.byValidatorIndex(validator_index); + if (!our_group) { + return std::nullopt; + } + + const auto core_index = + group_rotation_info.coreForGroup(*our_group, availability_cores.size()); + std::optional para_assigned_to_core; + if (maybe_claim_queue) { + para_assigned_to_core = maybe_claim_queue->get_claim_for(core_index, 0); + } else { + if (core_index < availability_cores.size()) { + const auto &core_state = availability_cores[core_index]; + visit_in_place( + core_state, + [&](const runtime::ScheduledCore &scheduled) { + para_assigned_to_core = scheduled.para_id; + }, + [&](const runtime::OccupiedCore &occupied) { + if (max_candidate_depth >= 1 && occupied.next_up_on_available) { + para_assigned_to_core = occupied.next_up_on_available->para_id; + } + }, + [](const auto &) {}); + } + } + + const auto group_validators = groups.get(*our_group); + if (!group_validators) { + return std::nullopt; + } + + return LocalValidatorState{ + .grid_tracker = {}, + .active = + ActiveValidatorState{ + .index = validator_index, + .group = *our_group, + .assignment = para_assigned_to_core, + .cluster_tracker = ClusterTracker( + {group_validators->begin(), group_validators->end()}, + seconding_limit), + }, + }; + } + void ParachainProcessorImpl::createBackingTask( const primitives::BlockHash &relay_parent, const network::HashedBlockHeader &block_header) { @@ -1935,6 +2100,60 @@ namespace kagome::parachain { } } + outcome::result< + std::reference_wrapper> + ParachainProcessorImpl::check_statement_signature( + SessionIndex session_index, + const std::vector &validators, + const RelayHash &relay_parent, + const network::vstaging::SignedCompactStatement &statement) { + OUTCOME_TRY(signing_context, + SigningContext::make(parachain_host_, relay_parent)); + OUTCOME_TRY(verified, + crypto_provider_->verify( + statement.signature, + signing_context.signable(*hasher_, getPayload(statement)), + validators[statement.payload.ix])); + + if (!verified) { + return Error::INCORRECT_SIGNATURE; + } + return std::cref(statement); + } + + outcome::result> + ParachainProcessorImpl::handle_cluster_statement( + const RelayHash &relay_parent, + ClusterTracker &cluster_tracker, + SessionIndex session, + const runtime::SessionInfo &session_info, + const network::vstaging::SignedCompactStatement &statement, + ValidatorIndex cluster_sender_index) { + const auto accept = cluster_tracker.can_receive( + cluster_sender_index, + statement.payload.ix, + network::vstaging::from(getPayload(statement))); + if (accept != outcome::success(Accept::Ok) + && accept != outcome::success(Accept::WithPrejudice)) { + SL_ERROR(logger_, "Reject outgoing error."); + return Error::CLUSTER_TRACKER_ERROR; + } + OUTCOME_TRY(_, + check_statement_signature( + session, session_info.validators, relay_parent, statement)); + + cluster_tracker.note_received( + cluster_sender_index, + statement.payload.ix, + network::vstaging::from(getPayload(statement))); + + const auto should_import = (outcome::success(Accept::Ok) == accept); + if (should_import) { + return statement; + } + return std::nullopt; + } + void ParachainProcessorImpl::handle_incoming_statement( const libp2p::peer::PeerId &peer_id, const network::vstaging::StatementDistributionMessageStatement &stm) { @@ -1975,40 +2194,70 @@ namespace kagome::parachain { /// TODO(iceseer): do `disabled validators` /// https://github.com/qdrvm/kagome/issues/2060 - /// TODO(iceseer): do `cluster validators` + auto &active = local_validator.active; + auto cluster_sender_index = [&]() -> std::optional { + std::span allowed_senders; + if (active) { + allowed_senders = active->cluster_tracker.senders_for_originator( + stm.compact.payload.ix); + } - std::optional> grid_sender_index; - for (const auto &[i, validator_knows_statement] : - local_validator.grid_tracker.direct_statement_providers( - parachain_state->get().per_session_state->value().groups, - stm.compact.payload.ix, - getPayload(stm.compact))) { - if (i >= session_info.discovery_keys.size()) { - continue; + if (auto peer = query_audi_->get(peer_id)) { + for (const auto i : allowed_senders) { + if (i < session_info.discovery_keys.size() + && *peer == session_info.discovery_keys[i]) { + return i; + } + } } + return std::nullopt; + }(); - /// TODO(iceseer): do check is authority - /// const auto &ad = opt_session_info->discovery_keys[i]; - grid_sender_index.emplace(i, validator_knows_statement); - break; - } + if (active && cluster_sender_index) { + if (handle_cluster_statement( + stm.relay_parent, + active->cluster_tracker, + parachain_state->get().per_session_state->value().session, + parachain_state->get().per_session_state->value().session_info, + stm.compact, + *cluster_sender_index) + .has_error()) { + return; + } + } else { + std::optional> grid_sender_index; + for (const auto &[i, validator_knows_statement] : + local_validator.grid_tracker.direct_statement_providers( + parachain_state->get().per_session_state->value().groups, + stm.compact.payload.ix, + getPayload(stm.compact))) { + if (i >= session_info.discovery_keys.size()) { + continue; + } - if (!grid_sender_index) { - return; - } + /// TODO(iceseer): do check is authority + /// const auto &ad = opt_session_info->discovery_keys[i]; + grid_sender_index.emplace(i, validator_knows_statement); + break; + } - const auto &[gsi, validator_knows_statement] = *grid_sender_index; - if (!validator_knows_statement) { - auto res = handle_grid_statement(stm.relay_parent, - parachain_state->get(), - local_validator.grid_tracker, - stm.compact, - gsi); - if (res.has_error()) { + if (!grid_sender_index) { + return; + } + + const auto &[gsi, validator_knows_statement] = *grid_sender_index; + if (!validator_knows_statement) { + if (handle_grid_statement(stm.relay_parent, + parachain_state->get(), + local_validator.grid_tracker, + stm.compact, + gsi) + .has_error()) { + return; + } + } else { return; } - } else { - return; } const auto &statement = getPayload(stm.compact); @@ -2112,26 +2361,78 @@ namespace kagome::parachain { const auto &compact_statement = getPayload(statement); const auto &candidate_hash = candidateHash(compact_statement); const auto originator = statement.payload.ix; + const auto is_confirmed = candidates_.is_confirmed(candidate_hash); - [[maybe_unused]] const auto is_confirmed = - candidates_.is_confirmed(candidate_hash); if (!relay_parent_state.local_validator) { return; } + enum DirectTargetKind { + Cluster, + Grid, + }; + auto &local_validator = *relay_parent_state.local_validator; - [[maybe_unused]] auto statement_group = - relay_parent_state.per_session_state->value().groups.byValidatorIndex( - originator); + auto targets = + [&]() -> std::vector> { + auto statement_group = + relay_parent_state.per_session_state->value().groups.byValidatorIndex( + originator); + + bool cluster_relevant = false; + std::vector> targets; + std::span all_cluster_targets; + + if (local_validator.active) { + auto &active = *local_validator.active; + cluster_relevant = + (statement_group && *statement_group == active.group); + if (is_confirmed && cluster_relevant) { + for (const auto v : active.cluster_tracker.targets()) { + if (active.cluster_tracker + .can_send(v, + originator, + network::vstaging::from(compact_statement)) + .has_error()) { + continue; + } + if (v == active.index) { + continue; + } + if (v >= session_info.discovery_keys.size()) { + continue; + } + targets.emplace_back(v, DirectTargetKind::Cluster); + } + } + all_cluster_targets = active.cluster_tracker.targets(); + } + + for (const auto v : local_validator.grid_tracker.direct_statement_targets( + relay_parent_state.per_session_state->value().groups, + originator, + compact_statement)) { + const auto can_use_grid = + !cluster_relevant + || std::find( + all_cluster_targets.begin(), all_cluster_targets.end(), v) + == all_cluster_targets.end(); + if (!can_use_grid) { + continue; + } + if (v >= session_info.discovery_keys.size()) { + continue; + } + targets.emplace_back(v, DirectTargetKind::Grid); + } + + return targets; + }(); - /// TODO(iceseer): do `cluster` targets std::vector> statement_to_peers; - for (const auto v : local_validator.grid_tracker.direct_statement_targets( - relay_parent_state.per_session_state->value().groups, - originator, - compact_statement)) { - auto peer = query_audi_->get(session_info.discovery_keys[v]); + for (const auto &[target, kind] : targets) { + auto peer = query_audi_->get(session_info.discovery_keys[target]); if (!peer) { continue; } @@ -2150,13 +2451,29 @@ namespace kagome::parachain { version = *peer_state->get().version; } - statement_to_peers.emplace_back(peer->id, version); - local_validator.grid_tracker.sent_or_received_direct_statement( - relay_parent_state.per_session_state->value().groups, - originator, - v, - compact_statement, - false); + switch (kind) { + case Cluster: { + auto &active = *local_validator.active; + if (active.cluster_tracker + .can_send(target, + originator, + network::vstaging::from(compact_statement)) + .has_value()) { + active.cluster_tracker.note_sent( + target, originator, network::vstaging::from(compact_statement)); + statement_to_peers.emplace_back(peer->id, version); + } + } break; + case Grid: { + statement_to_peers.emplace_back(peer->id, version); + local_validator.grid_tracker.sent_or_received_direct_statement( + relay_parent_state.per_session_state->value().groups, + originator, + target, + compact_statement, + false); + } break; + } } auto se = pm_->getStreamEngine(); @@ -2171,11 +2488,16 @@ namespace kagome::parachain { .relay_parent = relay_parent, .compact = statement, }}}); + SL_TRACE( + logger_, + "Send statements to validators. (relay_parent={}, validators_count={})", + relay_parent, + statement_to_peers.size()); for (const auto &[peer, version] : statement_to_peers) { if (version == network::CollationVersion::VStaging) { se->send(peer, router_->getValidationProtocolVStaging(), message_v2); } else { - assert(false); + BOOST_ASSERT(false); } } } @@ -2249,13 +2571,33 @@ namespace kagome::parachain { } } - auto filter = local_validator.grid_tracker.advertised_statements( - validator_id, candidate_hash); - if (!filter) { + if (validator_id >= session_info.discovery_keys.size()) { + return; + } + + auto filter = [&]() -> std::optional { + if (local_validator.active) { + if (local_validator.active->cluster_tracker.knows_candidate( + validator_id, candidate_hash)) { + return network::vstaging::StatementFilter( + local_validator.active->cluster_tracker.targets().size()); + } + } + + auto filter = local_validator.grid_tracker.advertised_statements( + validator_id, candidate_hash); + if (filter) { + return filter; + } + SL_TRACE(logger_, "No filter. (relay_parent={}, candidate_hash={})", relay_parent, candidate_hash); + return std::nullopt; + }(); + + if (!filter) { return; } @@ -2825,7 +3167,8 @@ namespace kagome::parachain { outcome::result ParachainProcessorImpl::OnFetchAttestedCandidateRequest( - const network::vstaging::AttestedCandidateRequest &request) { + const network::vstaging::AttestedCandidateRequest &request, + const libp2p::peer::PeerId &peer_id) { auto confirmed = candidates_.get_confirmed(request.candidate_hash); if (!confirmed) { return Error::NOT_CONFIRMED; @@ -2836,12 +3179,19 @@ namespace kagome::parachain { if (!relay_parent_state) { return Error::NO_STATE; } + + auto &local_validator = relay_parent_state->get().local_validator; + if (!local_validator) { + return Error::NOT_A_VALIDATOR; + } BOOST_ASSERT(relay_parent_state->get().statement_store); BOOST_ASSERT(relay_parent_state->get().our_index); - auto group = - relay_parent_state->get().per_session_state->value().groups.get( - confirmed->get().group_index()); + const auto &session_info = + relay_parent_state->get().per_session_state->value().session_info; + const auto &groups = + relay_parent_state->get().per_session_state->value().groups; + auto group = groups.get(confirmed->get().group_index()); if (!group) { SL_ERROR(logger_, "Unexpected array bound for groups. (relay parent={})", @@ -2856,6 +3206,55 @@ namespace kagome::parachain { return Error::INCORRECT_BITFIELD_SIZE; } + auto &active = local_validator->active; + auto [validator_id, is_cluster] = + [&]() -> std::pair, bool> { + std::optional validator_id; + bool is_cluster = false; + + do { + auto audi = query_audi_->get(peer_id); + if (!audi) { + SL_TRACE(logger_, "No audi. (peer={})", peer_id); + break; + } + + ValidatorIndex v = 0; + for (; v < session_info.discovery_keys.size(); ++v) { + if (session_info.discovery_keys[v] == *audi) { + SL_TRACE(logger_, + "Captured validator. (relay_parent={}, candidate_hash={})", + confirmed->get().relay_parent(), + request.candidate_hash); + break; + } + } + + if (v >= session_info.discovery_keys.size()) { + break; + } + + if (active + && active->cluster_tracker.can_request(v, request.candidate_hash)) { + validator_id = v; + is_cluster = true; + break; + } + + if (local_validator->grid_tracker.can_request(v, + request.candidate_hash)) { + validator_id = v; + break; + } + } while (false); + + return {validator_id, is_cluster}; + }(); + + if (!validator_id) { + return Error::OUT_OF_BOUND; + } + auto init_with_not = [](scale::BitVec &dst, const scale::BitVec &src) { dst.bits.reserve(src.bits.size()); for (const auto i : src.bits) { @@ -2878,6 +3277,22 @@ namespace kagome::parachain { [&](const IndexedAndSigned &statement) { statements.emplace_back(statement); }); + for (const auto &statement : statements) { + if (is_cluster) { + active->cluster_tracker.note_sent( + *validator_id, + statement.payload.ix, + network::vstaging::from(getPayload(statement))); + } else { + local_validator->grid_tracker.sent_or_received_direct_statement( + groups, + statement.payload.ix, + *validator_id, + getPayload(statement), + false); + } + } + return network::vstaging::AttestedCandidateResponse{ .candidate_receipt = confirmed->get().receipt, .persisted_validation_data = confirmed->get().persisted_validation_data, @@ -4578,6 +4993,12 @@ namespace kagome::parachain { return; } + if (per_relay_parent.local_validator + && per_relay_parent.local_validator->active) { + per_relay_parent.local_validator->active->cluster_tracker.note_issued( + local_index, network::vstaging::from(getPayload(compact_statement))); + } + if (per_relay_parent.per_session_state->value().grid_view) { auto &l = *per_relay_parent.local_validator; l.grid_tracker.learned_fresh_statement( diff --git a/core/parachain/validator/parachain_processor.hpp b/core/parachain/validator/parachain_processor.hpp index f8f2a2506a..0a79257988 100644 --- a/core/parachain/validator/parachain_processor.hpp +++ b/core/parachain/validator/parachain_processor.hpp @@ -29,6 +29,7 @@ #include "outcome/outcome.hpp" #include "parachain/availability/bitfield/signer.hpp" #include "parachain/availability/store/store.hpp" +#include "parachain/backing/cluster.hpp" #include "parachain/backing/grid_tracker.hpp" #include "parachain/backing/store.hpp" #include "parachain/pvf/precheck.hpp" @@ -119,7 +120,9 @@ namespace kagome::parachain { OUT_OF_BOUND, REJECTED_BY_PROSPECTIVE_PARACHAINS, INCORRECT_BITFIELD_SIZE, - CORE_INDEX_UNAVAILABLE + CORE_INDEX_UNAVAILABLE, + INCORRECT_SIGNATURE, + CLUSTER_TRACKER_ERROR }; static constexpr uint64_t kBackgroundWorkers = 5; @@ -235,7 +238,8 @@ namespace kagome::parachain { outcome::result OnFetchAttestedCandidateRequest( - const network::vstaging::AttestedCandidateRequest &request); + const network::vstaging::AttestedCandidateRequest &request, + const libp2p::peer::PeerId &peer_id); outcome::result get_block_number_under_construction( const RelayHash &relay_parent) const; bool bitfields_indicate_availability( @@ -359,8 +363,20 @@ namespace kagome::parachain { }; } + struct ActiveValidatorState { + // The index of the validator. + ValidatorIndex index; + // our validator group + GroupIndex group; + // the assignment of our validator group, if any. + std::optional assignment; + // the 'direct-in-group' communication at this relay-parent. + ClusterTracker cluster_tracker; + }; + struct LocalValidatorState { grid::GridTracker grid_tracker; + std::optional active; }; struct PerSessionState { @@ -370,6 +386,7 @@ namespace kagome::parachain { PerSessionState(PerSessionState &&) = default; PerSessionState &operator=(PerSessionState &&) = delete; + SessionIndex session; runtime::SessionInfo session_info; Groups groups; std::optional grid_view; @@ -379,6 +396,7 @@ namespace kagome::parachain { std::shared_ptr query_audi; PerSessionState( + SessionIndex _session, const runtime::SessionInfo &_session_info, Groups &&_groups, grid::Views &&_grid_view, @@ -565,6 +583,30 @@ namespace kagome::parachain { void process_vstaging_statement( const libp2p::peer::PeerId &peer_id, const network::vstaging::StatementDistributionMessage &msg); + + /// Checks whether a statement is allowed, whether the signature is + /// accurate, + /// and importing into the cluster tracker if successful. + /// + /// if successful, this returns a checked signed statement if it should be + /// imported or otherwise an error indicating a reputational fault. + outcome::result> + handle_cluster_statement( + const RelayHash &relay_parent, + ClusterTracker &cluster_tracker, + SessionIndex session, + const runtime::SessionInfo &session_info, + const network::vstaging::SignedCompactStatement &statement, + ValidatorIndex cluster_sender_index); + + /// Check a statement signature under this parent hash. + outcome::result< + std::reference_wrapper> + check_statement_signature( + SessionIndex session_index, + const std::vector &validators, + const RelayHash &relay_parent, + const network::vstaging::SignedCompactStatement &statement); void handle_incoming_manifest( const libp2p::peer::PeerId &peer_id, const network::vstaging::BackedCandidateManifest &msg); @@ -606,6 +648,8 @@ namespace kagome::parachain { GroupIndex group_index); outcome::result getBabeRandomness( const primitives::BlockHeader &block_header); + outcome::result> + fetch_claim_queue(const RelayHash &relay_parent); void request_attested_candidate(const libp2p::peer::PeerId &peer, RelayParentState &relay_parent_state, const RelayHash &relay_parent, @@ -917,6 +961,12 @@ namespace kagome::parachain { RelayParentState &relay_parent_state, const ConfirmedCandidate &confirmed_candidate, const runtime::SessionInfo &session_info); + void send_pending_cluster_statements( + const RelayHash &relay_parent, + const libp2p::peer::PeerId &peer_id, + network::CollationVersion version, + ValidatorIndex peer_validator_id, + ParachainProcessorImpl::RelayParentState &relay_parent_state); void send_pending_grid_messages( const RelayHash &relay_parent, const libp2p::peer::PeerId &peer_id, @@ -955,6 +1005,16 @@ namespace kagome::parachain { void spawn_and_update_peer(const primitives::AuthorityDiscoveryId &id); + std::optional + find_active_validator_state( + ValidatorIndex validator_index, + const Groups &groups, + const std::vector &availability_cores, + const runtime::GroupDescriptor &group_rotation_info, + const std::optional &maybe_claim_queue, + size_t seconding_limit, + size_t max_candidate_depth); + template bool tryOpenOutgoingCollatingStream(const libp2p::peer::PeerId &peer_id, F &&callback); diff --git a/core/parachain/validator/signer.hpp b/core/parachain/validator/signer.hpp index 92de39f27e..68873e3bf5 100644 --- a/core/parachain/validator/signer.hpp +++ b/core/parachain/validator/signer.hpp @@ -11,6 +11,7 @@ #include "crypto/key_store/session_keys.hpp" #include "crypto/sr25519_provider.hpp" #include "network/types/collator_messages.hpp" +#include "network/types/collator_messages_vstaging.hpp" #include "runtime/runtime_api/parachain_host.hpp" namespace kagome::parachain { @@ -30,6 +31,10 @@ namespace kagome::parachain { const network::Statement &v) { return toSignable(hasher, v.candidate_state); } + static auto toSignable(const crypto::Hasher &, + const network::vstaging::CompactStatement &v) { + return v; + } public: SCALE_TIE(2); diff --git a/core/runtime/runtime_api/impl/parachain_host.cpp b/core/runtime/runtime_api/impl/parachain_host.cpp index a70fc0cfdc..e66dff23e3 100644 --- a/core/runtime/runtime_api/impl/parachain_host.cpp +++ b/core/runtime/runtime_api/impl/parachain_host.cpp @@ -265,6 +265,19 @@ namespace kagome::runtime { ctx, "ParachainHost_para_backing_state", id); } + outcome::result>> + ParachainHostImpl::claim_queue(const primitives::BlockHash &block) { + OUTCOME_TRY(ctx, executor_->ctx().ephemeralAt(block)); + return executor_->call>>( + ctx, "ParachainHost_claim_queue"); + } + + outcome::result ParachainHostImpl::runtime_api_version( + const primitives::BlockHash &block) { + OUTCOME_TRY(ctx, executor_->ctx().ephemeralAt(block)); + return executor_->call(ctx, "ParachainHost_runtime_api_version"); + } + outcome::result ParachainHostImpl::staging_async_backing_params( const primitives::BlockHash &block) { diff --git a/core/runtime/runtime_api/impl/parachain_host.hpp b/core/runtime/runtime_api/impl/parachain_host.hpp index 8300c53516..3c00fcf9a6 100644 --- a/core/runtime/runtime_api/impl/parachain_host.hpp +++ b/core/runtime/runtime_api/impl/parachain_host.hpp @@ -118,6 +118,12 @@ namespace kagome::runtime { outcome::result> node_features( const primitives::BlockHash &block, SessionIndex index) override; + outcome::result>> claim_queue( + const primitives::BlockHash &block) override; + + outcome::result runtime_api_version( + const primitives::BlockHash &block) override; + private: bool prepare(); void clearCaches(const std::vector &blocks); diff --git a/core/runtime/runtime_api/parachain_host.hpp b/core/runtime/runtime_api/parachain_host.hpp index e099ca9177..c9423074b8 100644 --- a/core/runtime/runtime_api/parachain_host.hpp +++ b/core/runtime/runtime_api/parachain_host.hpp @@ -250,6 +250,12 @@ namespace kagome::runtime { virtual outcome::result> node_features( const primitives::BlockHash &block, SessionIndex index) = 0; + + virtual outcome::result>> + claim_queue(const primitives::BlockHash &block) = 0; + + virtual outcome::result runtime_api_version( + const primitives::BlockHash &block) = 0; }; } // namespace kagome::runtime diff --git a/core/runtime/runtime_api/parachain_host_types.hpp b/core/runtime/runtime_api/parachain_host_types.hpp index bfd04a84ef..38fb94074f 100644 --- a/core/runtime/runtime_api/parachain_host_types.hpp +++ b/core/runtime/runtime_api/parachain_host_types.hpp @@ -6,7 +6,9 @@ #pragma once +#include #include +#include #include "common/blob.hpp" #include "common/unused.hpp" @@ -38,6 +40,21 @@ namespace kagome::runtime { using ScheduledCore = network::ScheduledCore; using CandidateDescriptor = network::CandidateDescriptor; + struct ClaimQueueSnapshot { + SCALE_TIE(1); + std::map> claimes; + + std::optional get_claim_for(CoreIndex core_index, + size_t depth) const { + if (auto it = claimes.find(core_index); it != claimes.end()) { + if (depth < it->second.size()) { + return it->second[depth]; + } + } + return std::nullopt; + } + }; + /// Information about a core which is currently occupied. struct OccupiedCore { // NOTE: this has no ParaId as it can be deduced from the candidate From 0ae340beb7f046949b48542f781aa1f98d9123dd Mon Sep 17 00:00:00 2001 From: iceseer Date: Thu, 23 May 2024 09:18:17 +0300 Subject: [PATCH 43/71] fixup! Signed-off-by: iceseer --- .../validator/impl/parachain_processor.cpp | 30 ++++++++++++------- 1 file changed, 20 insertions(+), 10 deletions(-) diff --git a/core/parachain/validator/impl/parachain_processor.cpp b/core/parachain/validator/impl/parachain_processor.cpp index 445584923e..643f0953d8 100644 --- a/core/parachain/validator/impl/parachain_processor.cpp +++ b/core/parachain/validator/impl/parachain_processor.cpp @@ -649,23 +649,16 @@ namespace kagome::parachain { for (const auto &lost : event.lost) { SL_TRACE(logger_, "Removed backing task.(relay parent={})", lost); - if (auto relay_parent_state = tryGetStateByRelayParent(lost)) { - _keeper_.emplace_back(relay_parent_state->get().per_session_state); - } - auto relay_parent_state = tryGetStateByRelayParent(lost); if (relay_parent_state) { _keeper_.emplace_back(relay_parent_state->get().per_session_state); } our_current_state_.active_leaves.erase(lost); - std::vector pruned = [&]() -> std::vector { - if (relay_parent_state->get().prospective_parachains_mode) { - return our_current_state_.implicit_view->deactivate_leaf(lost); - } - return {lost}; - }(); + std::vector pruned = + our_current_state_.implicit_view->deactivate_leaf(lost); + ; for (const auto removed : pruned) { our_current_state_.state_by_relay_parent.erase(removed); /// TODO(iceseer): do https://github.com/qdrvm/kagome/issues/1888 @@ -3547,15 +3540,32 @@ namespace kagome::parachain { for (const auto &[v, action] : actions) { auto peer_opt = query_audi_->get(session_info.discovery_keys[v]); if (!peer_opt) { + SL_TRACE(logger_, + "No peer info. (relay_parent={}, validator_index={}, " + "candidate_hash={})", + relay_parent, + v, + candidate_hash); continue; } auto peer_state = pm_->getPeerState(peer_opt->id); if (!peer_state) { + SL_TRACE(logger_, + "No peer state. (relay_parent={}, peer={}, candidate_hash={})", + relay_parent, + peer_opt->id, + candidate_hash); continue; } if (!peer_state->get().knows_relay_parent(relay_parent)) { + SL_TRACE(logger_, + "Peer doesn't know relay parent. (relay_parent={}, peer={}, " + "candidate_hash={})", + relay_parent, + peer_opt->id, + candidate_hash); continue; } From bfe27e5e5cf87f8e0645cdc4c7dc1215916c809b Mon Sep 17 00:00:00 2001 From: iceseer Date: Thu, 23 May 2024 10:08:07 +0300 Subject: [PATCH 44/71] remove `need_to_process` check based on active_leaf Signed-off-by: iceseer --- .../validator/impl/parachain_processor.cpp | 29 ------------------- 1 file changed, 29 deletions(-) diff --git a/core/parachain/validator/impl/parachain_processor.cpp b/core/parachain/validator/impl/parachain_processor.cpp index 643f0953d8..4ce1677fc6 100644 --- a/core/parachain/validator/impl/parachain_processor.cpp +++ b/core/parachain/validator/impl/parachain_processor.cpp @@ -5106,18 +5106,6 @@ namespace kagome::parachain { /// TODO(iceseer): do https://github.com/qdrvm/kagome/issues/1888 /// checks if we still need to execute parachain task auto _measure = std::make_shared("Parachain validation", logger_); - auto need_to_process = - our_current_state_.active_leaves.count(relay_parent) != 0ull; - - if (!need_to_process) { - SL_TRACE(logger_, - "Candidate validation skipped because of extruded relay parent. " - "(relay_parent={}, parachain_id={}, candidate_hash={})", - relay_parent, - candidate.descriptor.para_id, - candidate_hash); - return; - } auto cb = [weak_self{weak_from_this()}, candidate, pov, @@ -5144,23 +5132,6 @@ namespace kagome::parachain { return; } - /// TODO(iceseer): do https://github.com/qdrvm/kagome/issues/1888 - /// checks if we still need to execute parachain task - auto need_to_process = - self->our_current_state_.active_leaves.count(relay_parent) != 0ull; - - if (!need_to_process) { - SL_TRACE( - self->logger_, - "Candidate validation skipped before erasure-coding because of " - "extruded relay parent. " - "(relay_parent={}, parachain_id={}, candidate_hash={})", - relay_parent, - candidate.descriptor.para_id, - candidate_hash); - return; - } - auto &[comms, data] = validation_result.value(); runtime::AvailableData available_data{ .pov = std::move(pov), From d324f40c5f45a16ac0138e7807797a4e0bd8a540 Mon Sep 17 00:00:00 2001 From: iceseer Date: Thu, 23 May 2024 11:29:53 +0300 Subject: [PATCH 45/71] test!!!! Signed-off-by: iceseer --- .../validator/impl/parachain_processor.cpp | 110 +++++++++--------- 1 file changed, 57 insertions(+), 53 deletions(-) diff --git a/core/parachain/validator/impl/parachain_processor.cpp b/core/parachain/validator/impl/parachain_processor.cpp index 4ce1677fc6..cdb1296680 100644 --- a/core/parachain/validator/impl/parachain_processor.cpp +++ b/core/parachain/validator/impl/parachain_processor.cpp @@ -5447,25 +5447,26 @@ namespace kagome::parachain { const Hash &relay_parent, const CandidateHash &candidate_hash, const Hash &parent_head_data_hash) { - auto per_relay_parent = tryGetStateByRelayParent(relay_parent); - if (per_relay_parent) { - if (per_relay_parent->get().prospective_parachains_mode) { - if (auto seconding_allowed = secondingSanityCheck( - HypotheticalCandidateIncomplete{ - .candidate_hash = candidate_hash, - .candidate_para = candidate_para_id, - .parent_head_data_hash = parent_head_data_hash, - .candidate_relay_parent = relay_parent}, - true)) { - for (const auto &[_, m] : *seconding_allowed) { - if (!m.empty()) { - return true; - } - } - } - } - } - return false; + return true; +// auto per_relay_parent = tryGetStateByRelayParent(relay_parent); +// if (per_relay_parent) { +// if (per_relay_parent->get().prospective_parachains_mode) { +// if (auto seconding_allowed = secondingSanityCheck( +// HypotheticalCandidateIncomplete{ +// .candidate_hash = candidate_hash, +// .candidate_para = candidate_para_id, +// .parent_head_data_hash = parent_head_data_hash, +// .candidate_relay_parent = relay_parent}, +// true)) { +// for (const auto &[_, m] : *seconding_allowed) { +// if (!m.empty()) { +// return true; +// } +// } +// } +// } +// } +// return false; } void ParachainProcessorImpl::handleAdvertisement( @@ -5636,40 +5637,43 @@ namespace kagome::parachain { .prospective_candidate = std::move(prospective_candidate), }; - switch (collations.status) { - case CollationStatus::Fetching: - case CollationStatus::WaitingOnValidation: { - SL_TRACE(logger_, - "Added collation to the pending list. (peer_id={}, para " - "id={}, relay parent={})", - peer_id, - para_id, - relay_parent); - - collations.waiting_queue.emplace_back(std::move(pending_collation), - collator_id); - } break; - case CollationStatus::Waiting: { - fetchCollation( - per_relay_parent->get(), std::move(pending_collation), collator_id); - } break; - case CollationStatus::Seconded: { - if (relay_parent_mode) { - // Limit is not reached, it's allowed to second another - // collation. - fetchCollation(per_relay_parent->get(), - std::move(pending_collation), - collator_id); - } else { - SL_TRACE(logger_, - "A collation has already been seconded. (peer_id={}, para " - "id={}, relay parent={})", - peer_id, - para_id, - relay_parent); - } - } break; - } + fetchCollation( + per_relay_parent->get(), std::move(pending_collation), collator_id); + +// switch (collations.status) { +// case CollationStatus::Fetching: +// case CollationStatus::WaitingOnValidation: { +// SL_TRACE(logger_, +// "Added collation to the pending list. (peer_id={}, para " +// "id={}, relay parent={})", +// peer_id, +// para_id, +// relay_parent); +// +// collations.waiting_queue.emplace_back(std::move(pending_collation), +// collator_id); +// } break; +// case CollationStatus::Waiting: { +// fetchCollation( +// per_relay_parent->get(), std::move(pending_collation), collator_id); +// } break; +// case CollationStatus::Seconded: { +// if (relay_parent_mode) { +// // Limit is not reached, it's allowed to second another +// // collation. +// fetchCollation(per_relay_parent->get(), +// std::move(pending_collation), +// collator_id); +// } else { +// SL_TRACE(logger_, +// "A collation has already been seconded. (peer_id={}, para " +// "id={}, relay parent={})", +// peer_id, +// para_id, +// relay_parent); +// } +// } break; +// } return outcome::success(); } From fd16fb20dacaf6727d17d96c71c6afc48aa957fd Mon Sep 17 00:00:00 2001 From: kamilsa Date: Thu, 23 May 2024 17:18:53 +0500 Subject: [PATCH 46/71] Always return true in handle_import_statements --- core/dispute_coordinator/impl/dispute_coordinator_impl.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/core/dispute_coordinator/impl/dispute_coordinator_impl.cpp b/core/dispute_coordinator/impl/dispute_coordinator_impl.cpp index 2df522b3fa..d974f8575e 100644 --- a/core/dispute_coordinator/impl/dispute_coordinator_impl.cpp +++ b/core/dispute_coordinator/impl/dispute_coordinator_impl.cpp @@ -1009,6 +1009,7 @@ namespace kagome::dispute { MaybeCandidateReceipt candidate_receipt, const SessionIndex session, std::vector> statements) { + return true; BOOST_ASSERT(initialized_); auto now = system_clock_.nowUint64(); From ab6849a046d1b0e493f502c826426d0014be5d40 Mon Sep 17 00:00:00 2001 From: iceseer Date: Thu, 23 May 2024 14:18:12 +0300 Subject: [PATCH 47/71] no test Signed-off-by: iceseer --- .../validator/impl/parachain_processor.cpp | 129 ++++++++---------- .../validator/parachain_processor.hpp | 1 - 2 files changed, 58 insertions(+), 72 deletions(-) diff --git a/core/parachain/validator/impl/parachain_processor.cpp b/core/parachain/validator/impl/parachain_processor.cpp index cdb1296680..789693a8c6 100644 --- a/core/parachain/validator/impl/parachain_processor.cpp +++ b/core/parachain/validator/impl/parachain_processor.cpp @@ -667,7 +667,6 @@ namespace kagome::parachain { our_current_state_.per_leaf.erase(lost); our_current_state_.state_by_relay_parent.erase(lost); - pending_candidates.erase(lost); } our_current_state_.active_leaves[relay_parent] = prospective_parachains_->prospectiveParachainsMode(relay_parent); @@ -1390,15 +1389,6 @@ namespace kagome::parachain { return; } - if (auto it = pending_candidates.find(pending_collation.relay_parent); - it != pending_candidates.end()) { - SL_WARN(logger_, - "Trying to insert a pending candidate on {} failed, because " - "there is already one.", - pending_collation.relay_parent); - return; - } - pending_collation.commitments_hash = receipt.commitments_hash; std::optional pvd; @@ -1426,9 +1416,6 @@ namespace kagome::parachain { /// TODO(iceseer): do https://github.com/qdrvm/kagome/issues/1888 /// fetched_collation_sanity_check - pending_candidates.insert( - std::make_pair(pending_collation.relay_parent, pending_collation)); - collations.status = CollationStatus::WaitingOnValidation; validateAsync( std::move(receipt), @@ -4708,7 +4695,6 @@ namespace kagome::parachain { }; }); - pending_candidates.erase(rp); stream_engine->send( peer_id, collation_protocol, @@ -5367,6 +5353,11 @@ namespace kagome::parachain { peer_data.collator_state->para_id); } + outcome::result kick_off_seconding( + PendingCollationFetch { mut collation_event, candidate_receipt, pov, maybe_parent_head_data }: PendingCollationFetch, + ) { + } + ParachainProcessorImpl::SecondingAllowed ParachainProcessorImpl::secondingSanityCheck( const HypotheticalCandidate &hypothetical_candidate, @@ -5447,26 +5438,25 @@ namespace kagome::parachain { const Hash &relay_parent, const CandidateHash &candidate_hash, const Hash &parent_head_data_hash) { - return true; -// auto per_relay_parent = tryGetStateByRelayParent(relay_parent); -// if (per_relay_parent) { -// if (per_relay_parent->get().prospective_parachains_mode) { -// if (auto seconding_allowed = secondingSanityCheck( -// HypotheticalCandidateIncomplete{ -// .candidate_hash = candidate_hash, -// .candidate_para = candidate_para_id, -// .parent_head_data_hash = parent_head_data_hash, -// .candidate_relay_parent = relay_parent}, -// true)) { -// for (const auto &[_, m] : *seconding_allowed) { -// if (!m.empty()) { -// return true; -// } -// } -// } -// } -// } -// return false; + auto per_relay_parent = tryGetStateByRelayParent(relay_parent); + if (per_relay_parent) { + if (per_relay_parent->get().prospective_parachains_mode) { + if (auto seconding_allowed = secondingSanityCheck( + HypotheticalCandidateIncomplete{ + .candidate_hash = candidate_hash, + .candidate_para = candidate_para_id, + .parent_head_data_hash = parent_head_data_hash, + .candidate_relay_parent = relay_parent}, + true)) { + for (const auto &[_, m] : *seconding_allowed) { + if (!m.empty()) { + return true; + } + } + } + } + } + return false; } void ParachainProcessorImpl::handleAdvertisement( @@ -5637,43 +5627,40 @@ namespace kagome::parachain { .prospective_candidate = std::move(prospective_candidate), }; - fetchCollation( - per_relay_parent->get(), std::move(pending_collation), collator_id); - -// switch (collations.status) { -// case CollationStatus::Fetching: -// case CollationStatus::WaitingOnValidation: { -// SL_TRACE(logger_, -// "Added collation to the pending list. (peer_id={}, para " -// "id={}, relay parent={})", -// peer_id, -// para_id, -// relay_parent); -// -// collations.waiting_queue.emplace_back(std::move(pending_collation), -// collator_id); -// } break; -// case CollationStatus::Waiting: { -// fetchCollation( -// per_relay_parent->get(), std::move(pending_collation), collator_id); -// } break; -// case CollationStatus::Seconded: { -// if (relay_parent_mode) { -// // Limit is not reached, it's allowed to second another -// // collation. -// fetchCollation(per_relay_parent->get(), -// std::move(pending_collation), -// collator_id); -// } else { -// SL_TRACE(logger_, -// "A collation has already been seconded. (peer_id={}, para " -// "id={}, relay parent={})", -// peer_id, -// para_id, -// relay_parent); -// } -// } break; -// } + switch (collations.status) { + case CollationStatus::Fetching: + case CollationStatus::WaitingOnValidation: { + SL_TRACE(logger_, + "Added collation to the pending list. (peer_id={}, para " + "id={}, relay parent={})", + peer_id, + para_id, + relay_parent); + + collations.waiting_queue.emplace_back(std::move(pending_collation), + collator_id); + } break; + case CollationStatus::Waiting: { + fetchCollation( + per_relay_parent->get(), std::move(pending_collation), collator_id); + } break; + case CollationStatus::Seconded: { + if (relay_parent_mode) { + // Limit is not reached, it's allowed to second another + // collation. + fetchCollation(per_relay_parent->get(), + std::move(pending_collation), + collator_id); + } else { + SL_TRACE(logger_, + "A collation has already been seconded. (peer_id={}, para " + "id={}, relay parent={})", + peer_id, + para_id, + relay_parent); + } + } break; + } return outcome::success(); } diff --git a/core/parachain/validator/parachain_processor.hpp b/core/parachain/validator/parachain_processor.hpp index 0a79257988..4a6d6eb841 100644 --- a/core/parachain/validator/parachain_processor.hpp +++ b/core/parachain/validator/parachain_processor.hpp @@ -1099,7 +1099,6 @@ namespace kagome::parachain { } statementDistributionV2; } our_current_state_; - std::unordered_map pending_candidates; std::shared_ptr main_pool_handler_; std::shared_ptr hasher_; std::shared_ptr peer_view_; From a5058bb4d26393bb35387c8cadcf2c292dff4f59 Mon Sep 17 00:00:00 2001 From: iceseer Date: Thu, 23 May 2024 20:57:57 +0300 Subject: [PATCH 48/71] kick_off_seconding Signed-off-by: iceseer --- core/network/peer_state.hpp | 85 ++++++++++- core/network/types/collator_messages.hpp | 1 + .../validator/impl/parachain_processor.cpp | 138 +++++++++++++++--- .../validator/parachain_processor.hpp | 25 +++- .../validator/prospective_parachains.hpp | 125 +++++++++------- 5 files changed, 289 insertions(+), 85 deletions(-) diff --git a/core/network/peer_state.hpp b/core/network/peer_state.hpp index 6c18576ac9..151569c86d 100644 --- a/core/network/peer_state.hpp +++ b/core/network/peer_state.hpp @@ -37,14 +37,68 @@ namespace kagome::network { std::chrono::system_clock::time_point last_active; }; + struct ProspectiveCandidate { + /// Candidate hash. + CandidateHash candidate_hash; + /// Parent head-data hash as supplied in advertisement. + Hash parent_head_data_hash; + }; + + struct PendingCollation { + /// Candidate's relay parent. + RelayHash relay_parent; + /// Parachain id. + ParachainId para_id; + /// Peer that advertised this collation. + libp2p::peer::PeerId peer_id; + /// Optional candidate hash and parent head-data hash if were + /// supplied in advertisement. + std::optional prospective_candidate; + /// Hash of the candidate's commitments. + std::optional commitments_hash; + }; + struct CollationEvent { + /// Collator id. + CollatorId collator_id; + /// The network protocol version the collator is using. + CollationVersion collator_protocol_version; + /// The requested collation data. + PendingCollation pending_collation; + }; + + struct PendingCollationFetch { + /// Collation identifier. + CollationEvent collation_event; + /// Candidate receipt. + CandidateReceipt candidate_receipt; + /// Proof of validity. + PoV pov; + /// Optional parachain parent head data. + /// Only needed for elastic scaling. + std::optional maybe_parent_head_data; + }; + + struct FetchedCollation { + /// Candidate's relay parent. + RelayHash relay_parent; + /// Parachain id. + ParachainId para_id; + /// Candidate hash. + CandidateHash candidate_hash; + /// Id of the collator the collation was fetched from. CollatorId collator_id; - struct { - RelayHash relay_parent; - network::ParachainId para_id; - libp2p::peer::PeerId peer_id; - std::optional commitments_hash; - } pending_collation; + + static FetchedCollation from(const network::CandidateReceipt &receipt, + const crypto::Hasher &hasher) { + const auto &descriptor = receipt.descriptor; + return FetchedCollation{ + .relay_parent = descriptor.relay_parent, + .para_id = descriptor.para_id, + .candidate_hash = receipt.hash(hasher), + .collator_id = descriptor.collator_id, + }; + } }; using OurView = network::View; @@ -177,3 +231,22 @@ namespace kagome::network { } } // namespace kagome::network + +template <> +struct std::hash { + size_t operator()( + const kagome::network::FetchedCollation &value) const noexcept { + using CollatorId = kagome::parachain::CollatorId; + using CandidateHash = kagome::parachain::CandidateHash; + using RelayHash = kagome::parachain::RelayHash; + using ParachainId = kagome::parachain::ParachainId; + + size_t result = std::hash()(value.relay_parent); + boost::hash_combine(result, std::hash()(value.para_id)); + boost::hash_combine(result, + std::hash()(value.candidate_hash)); + boost::hash_combine(result, std::hash()(value.collator_id)); + + return result; + } +}; diff --git a/core/network/types/collator_messages.hpp b/core/network/types/collator_messages.hpp index c475022cfd..421f15522f 100644 --- a/core/network/types/collator_messages.hpp +++ b/core/network/types/collator_messages.hpp @@ -83,6 +83,7 @@ namespace kagome::network { common::Buffer payload; }; + using PoV = ParachainBlock; using RequestPov = CandidateHash; using ResponsePov = boost::variant; diff --git a/core/parachain/validator/impl/parachain_processor.cpp b/core/parachain/validator/impl/parachain_processor.cpp index 789693a8c6..d244aef6a5 100644 --- a/core/parachain/validator/impl/parachain_processor.cpp +++ b/core/parachain/validator/impl/parachain_processor.cpp @@ -86,6 +86,8 @@ OUTCOME_CPP_DEFINE_CATEGORY(kagome::parachain, return "Incorrect signature"; case E::CLUSTER_TRACKER_ERROR: return "Cluster tracker error"; + case E::PERSISTED_VALIDATION_DATA_NOT_FOUND: + return "Persisted validation data not found"; } return "Unknown parachain processor error"; } @@ -1426,13 +1428,24 @@ namespace kagome::parachain { parachain_state.table_context.validators.size()); } - std::optional + outcome::result> ParachainProcessorImpl::requestProspectiveValidationData( - const RelayHash &relay_parent, + const RelayHash &candidate_relay_parent, const Hash &parent_head_data_hash, - ParachainId para_id) { - return prospective_parachains_->answerProspectiveValidationDataRequest( - relay_parent, parent_head_data_hash, para_id); + ParachainId para_id, + const std::optional &maybe_parent_head_data) { + auto parent_head_data = [&]() -> ParentHeadData { + if (maybe_parent_head_data) { + return ParentHeadData_WithData{*maybe_parent_head_data, + parent_head_data_hash}; + } + return parent_head_data_hash; + }(); + + OUTCOME_TRY(opt_pvd, + prospective_parachains_->answerProspectiveValidationDataRequest( + candidate_relay_parent, parent_head_data, para_id)); + return opt_pvd; } std::optional @@ -1441,21 +1454,14 @@ namespace kagome::parachain { return requestPersistedValidationData(relay_parent, para_id); } - std::optional + outcome::result> ParachainProcessorImpl::requestPersistedValidationData( const RelayHash &relay_parent, ParachainId para_id) { - auto res_data = parachain_host_->persisted_validation_data( - relay_parent, para_id, runtime::OccupiedCoreAssumption::Free); - if (res_data.has_error()) { - SL_VERBOSE(logger_, - "PersistedValidationData not found. (error={}, " - "relay_parent={} para_id={})", - res_data.error(), - relay_parent, - para_id); - return std::nullopt; - } - return std::move(res_data.value()); + OUTCOME_TRY( + pvd, + parachain_host_->persisted_validation_data( + relay_parent, para_id, runtime::OccupiedCoreAssumption::Free)); + return pvd; } void ParachainProcessorImpl::process_bitfield_distribution( @@ -3305,6 +3311,16 @@ namespace kagome::parachain { return std::nullopt; } + outcome::result< + std::reference_wrapper> + ParachainProcessorImpl::getStateByRelayParent( + const primitives::BlockHash &relay_parent) { + if (auto per_relay_parent = tryGetStateByRelayParent(relay_parent)) { + return *per_relay_parent; + } + return Error::OUT_OF_VIEW; + } + ParachainProcessorImpl::RelayParentState & ParachainProcessorImpl::storeStateByRelayParent( const primitives::BlockHash &relay_parent, RelayParentState &&val) { @@ -5353,9 +5369,89 @@ namespace kagome::parachain { peer_data.collator_state->para_id); } - outcome::result kick_off_seconding( - PendingCollationFetch { mut collation_event, candidate_receipt, pov, maybe_parent_head_data }: PendingCollationFetch, - ) { + outcome::result ParachainProcessorImpl::kick_off_seconding( + PendingCollationFetch &&pending_collation_fetch) { + REINVOKE(*main_pool_handler_, + kick_off_seconding, + std::move(pending_collation_fetch)); + + auto &collation_event = pending_collation_fetch.collation_event; + auto pending_collation = collation_event.pending_collation; + auto relay_parent = pending_collation.relay_parent; + + OUTCOME_TRY(per_relay_parent, getStateByRelayParent(relay_parent)); + auto &collations = per_relay_parent->get().collations; + auto fetched_collation = FetchedCollation::from( + pending_collation_fetch.candidate_receipt, *hasher_); + + if (our_current_state_.validator_side.fetched_candidates.contains( + fetched_collation)) { + return Error::DUPLICATE; + } + + auto &entry = + our_current_state_.validator_side.fetched_candidates[fetched_collation]; + collation_event.pending_collation.commitments_hash = + pending_collation_fetch.candidate_receipt.commitments_hash; + + const bool is_collator_v2 = (collation_event.collator_protocol_version + == CollationVersion::VStaging); + const bool have_prospective_candidate = + collation_event.pending_collation.prospective_candidate; + const bool async_backing_en = + per_relay_parent->get().prospective_parachains_mode; + + std::optional maybe_pvd; + std::optional> maybe_parent_head_and_hash; + if (is_collator_v2 && have_prospective_candidate && async_backing_en) { + OUTCOME_TRY(pvd, + requestProspectiveValidationData( + relay_parent, + collation_event.pending_collation.prospective_candidate + ->parent_head_data_hash, + pending_collation.para_id, + pending_collation_fetch.maybe_parent_head_data)); + maybe_pvd = pvd; + + if (pending_collation_fetch.maybe_parent_head_data) { + maybe_parent_head_and_hash.emplace( + *pending_collation_fetch.maybe_parent_head_data, + collation_event.pending_collation.prospective_candidate + ->parent_head_data_hash); + } + } else if ((is_collator_v2 && have_prospective_candidate) + || !is_collator_v2) { + OUTCOME_TRY( + pvd, + requestPersistedValidationData( + pending_collation_fetch.candidate_receipt.descriptor.relay_parent, + pending_collation_fetch.candidate_receipt.descriptor.para_id)); + maybe_pvd = pvd; + maybe_parent_head_and_hash = std::nullopt; + } else { + return outcome::success(); + } + + if (!maybe_pvd) { + return Error::PERSISTED_VALIDATION_DATA_NOT_FOUND; + } + + auto pvd{std::move(*maybe_pvd)}; + OUTCOME_TRY(fetched_collation_sanity_check( + collation_event.pending_collation, + pending_collation_fetch.candidate_receipt, + pvd, + maybe_parent_head_and_hash, )); + + collations.status = CollationStatus::WaitingOnValidation; + validateAsync( + std::move(pending_collation_fetch.candidate_receipt), + std::move(pending_collation_fetch.pov), + std::move(pvd), + relay_parent); + + entry = collation_event; + return outcome::success(); } ParachainProcessorImpl::SecondingAllowed diff --git a/core/parachain/validator/parachain_processor.hpp b/core/parachain/validator/parachain_processor.hpp index 4a6d6eb841..e72f3d2563 100644 --- a/core/parachain/validator/parachain_processor.hpp +++ b/core/parachain/validator/parachain_processor.hpp @@ -122,7 +122,8 @@ namespace kagome::parachain { INCORRECT_BITFIELD_SIZE, CORE_INDEX_UNAVAILABLE, INCORRECT_SIGNATURE, - CLUSTER_TRACKER_ERROR + CLUSTER_TRACKER_ERROR, + PERSISTED_VALIDATION_DATA_NOT_FOUND }; static constexpr uint64_t kBackgroundWorkers = 5; @@ -764,11 +765,13 @@ namespace kagome::parachain { /* * Logic. */ - std::optional - requestProspectiveValidationData(const RelayHash &relay_parent, - const Hash &parent_head_data_hash, - ParachainId para_id); - std::optional + outcome::result> + requestProspectiveValidationData( + const RelayHash &relay_parent, + const Hash &parent_head_data_hash, + ParachainId para_id, + const std::optional &maybe_parent_head_data); + outcome::result> requestPersistedValidationData(const RelayHash &relay_parent, ParachainId para_id); @@ -921,6 +924,9 @@ namespace kagome::parachain { network::CollationVersion version); std::optional> tryGetStateByRelayParent(const primitives::BlockHash &relay_parent); + outcome::result< + std::reference_wrapper> + getStateByRelayParent(const primitives::BlockHash &relay_parent); /** * @brief Store the state of the relay parent. @@ -1057,6 +1063,9 @@ namespace kagome::parachain { const HypotheticalCandidate &hypothetical_candidate, bool backed_in_path_only); + outcome::result kick_off_seconding( + PendingCollationFetch &&pending_collation_fetch); + std::optional importStatementToTable( const RelayHash &relay_parent, ParachainProcessorImpl::RelayParentState &relayParentState, @@ -1093,6 +1102,10 @@ namespace kagome::parachain { PendingCollationEq> collation_requests_cancel_handles; + struct { + std::unordered_map fetched_candidates; + } validator_side; + struct { std::unordered_set implicit_view; network::View view; diff --git a/core/parachain/validator/prospective_parachains.hpp b/core/parachain/validator/prospective_parachains.hpp index 502e6987cf..88928cb5a7 100644 --- a/core/parachain/validator/prospective_parachains.hpp +++ b/core/parachain/validator/prospective_parachains.hpp @@ -25,6 +25,11 @@ namespace kagome::parachain { + using ParentHeadData_OnlyHash = primitives::Hash; + using ParentHeadData_WithData = std::pair; + using ParentHeadData = + boost::variant; + class ProspectiveParachains { #ifdef CFG_TESTING public: @@ -150,20 +155,20 @@ namespace kagome::parachain { storage.relayParentByCandidateHash(child_hash)) { backable_candidates.emplace_back(child_hash, *parent_hash_opt); } else { - SL_ERROR( - logger, - "Candidate is present in fragment tree but not in candidate's storage! (child_hash={}, para_id={})", - child_hash, - para); + SL_ERROR(logger, + "Candidate is present in fragment tree but not in " + "candidate's storage! (child_hash={}, para_id={})", + child_hash, + para); } } if (backable_candidates.empty()) { - SL_TRACE( - logger, - "Could not find any backable candidate. (relay_parent={}, para_id={})", - relay_parent, - para); + SL_TRACE(logger, + "Could not find any backable candidate. (relay_parent={}, " + "para_id={})", + relay_parent, + para); } else { SL_TRACE(logger, "Found backable candidates. (relay_parent={}, count={})", @@ -184,57 +189,73 @@ namespace kagome::parachain { return fragmentTreeMembership(view.active_leaves, para, candidate); } - std::optional + outcome::result> answerProspectiveValidationDataRequest( const RelayHash &candidate_relay_parent, - const Hash &parent_head_data_hash, + const ParentHeadData &parent_head_data, ParachainId para_id) { - if (auto it = view.candidate_storage.find(para_id); - it != view.candidate_storage.end()) { - fragment::CandidateStorage &storage = it->second; - std::optional head_data = - utils::fromRefToOwn(storage.headDataByHash(parent_head_data_hash)); - std::optional relay_parent_info{}; - std::optional max_pov_size{}; - - for (const auto &[_, x] : view.active_leaves) { - auto it = x.fragment_trees.find(para_id); - if (it == x.fragment_trees.end()) { - continue; - } - const fragment::FragmentTree &fragment_tree = it->second; + auto it = view.candidate_storage.find(para_id); + if (it == view.candidate_storage.end()) { + return std::nullopt; + } - if (head_data && relay_parent_info && max_pov_size) { - break; - } - if (!relay_parent_info) { - relay_parent_info = utils::fromRefToOwn( - fragment_tree.scope.ancestorByHash(candidate_relay_parent)); - } - if (!head_data) { - const auto &required_parent = - fragment_tree.scope.base_constraints.required_parent; - if (hasher_->blake2b_256(required_parent) - == parent_head_data_hash) { - head_data = required_parent; - } - } - if (!max_pov_size) { - if (fragment_tree.scope.ancestorByHash(candidate_relay_parent)) { - max_pov_size = fragment_tree.scope.base_constraints.max_pov_size; - } - } + const auto &storage = it->second; + auto [head_data, parent_head_data_hash] = visit_in_place( + parent_head_data, + [&](const ParentHeadData_OnlyHash &parent_head_data_hash) + -> std::pair, + std::reference_wrapper> { + return {utils::fromRefToOwn( + storage.headDataByHash(parent_head_data_hash)), + parent_head_data_hash}; + }, + [&](const ParentHeadData_WithData &v) + -> std::pair, + std::reference_wrapper> { + const auto &[head_data, hash] = v; + return {head_data, hash}; + }); + + std::optional relay_parent_info{}; + std::optional max_pov_size{}; + + for (const auto &[_, x] : view.active_leaves) { + auto it = x.fragment_trees.find(para_id); + if (it == x.fragment_trees.end()) { + continue; } + const fragment::FragmentTree &fragment_tree = it->second; if (head_data && relay_parent_info && max_pov_size) { - return runtime::PersistedValidationData{ - .parent_head = *head_data, - .relay_parent_number = relay_parent_info->number, - .relay_parent_storage_root = relay_parent_info->storage_root, - .max_pov_size = (uint32_t)*max_pov_size, - }; + break; + } + if (!relay_parent_info) { + relay_parent_info = utils::fromRefToOwn( + fragment_tree.scope.ancestorByHash(candidate_relay_parent)); + } + if (!head_data) { + const auto &required_parent = + fragment_tree.scope.base_constraints.required_parent; + if (hasher_->blake2b_256(required_parent) == parent_head_data_hash) { + head_data = required_parent; + } + } + if (!max_pov_size) { + if (fragment_tree.scope.ancestorByHash(candidate_relay_parent)) { + max_pov_size = fragment_tree.scope.base_constraints.max_pov_size; + } } } + + if (head_data && relay_parent_info && max_pov_size) { + return runtime::PersistedValidationData{ + .parent_head = *head_data, + .relay_parent_number = relay_parent_info->number, + .relay_parent_storage_root = relay_parent_info->storage_root, + .max_pov_size = (uint32_t)*max_pov_size, + }; + } + return std::nullopt; } From 0575d031aaea2867ac348d3f104b581fd11d6eaa Mon Sep 17 00:00:00 2001 From: iceseer Date: Mon, 27 May 2024 19:38:55 +0300 Subject: [PATCH 49/71] impls Signed-off-by: iceseer --- core/parachain/validator/collations.hpp | 67 ++++++++++++++++--- .../validator/impl/parachain_processor.cpp | 55 +++++++++++++++ .../validator/parachain_processor.hpp | 23 ++++++- 3 files changed, 135 insertions(+), 10 deletions(-) diff --git a/core/parachain/validator/collations.hpp b/core/parachain/validator/collations.hpp index 992f89f6d2..306a4fb605 100644 --- a/core/parachain/validator/collations.hpp +++ b/core/parachain/validator/collations.hpp @@ -55,15 +55,8 @@ namespace kagome::parachain { Seconded, }; - using ProspectiveCandidate = std::pair; - - struct PendingCollation { - RelayHash relay_parent; - network::ParachainId para_id; - libp2p::peer::PeerId peer_id; - std::optional commitments_hash; - std::optional prospective_candidate; - }; + using ProspectiveCandidate = network::ProspectiveCandidate; + using PendingCollation = network::PendingCollation; struct PendingCollationHash { size_t operator()(const PendingCollation &val) const noexcept { @@ -107,6 +100,62 @@ namespace kagome::parachain { relay_parent_mode ? relay_parent_mode->max_candidate_depth + 1 : 1; return seconded_count < seconded_limit; } + + void back_to_waiting(const ProspectiveParachainsModeOpt &relay_parent_mode) { + if (status != CollationStatus::Seconded || relay_parent_mode) { + status = CollationStatus::Waiting; + } + } + + /// Returns the next collation to fetch from the `waiting_queue`. + /// + /// This will reset the status back to `Waiting` using [`CollationStatus::back_to_waiting`]. + /// + /// Returns `Some(_)` if there is any collation to fetch, the `status` is not `Seconded` and + /// the passed in `finished_one` is the currently `waiting_collation`. + std::optional> get_next_collation_to_fetch( + const std::pair> &finished_one, + const ProspectiveParachainsModeOpt &relay_parent_mode + ) { + if (fetching_from) { + const auto &[collator_id, maybe_candidate_hash] = *fetching_from; + if (collator_id != finished_one.first && (!maybe_candidate_hash || *maybe_candidate_hash != finished_one.second)) { + SL_TRACE(logger_, "Not proceeding to the next collation - has already been done."); + return std::nullopt; + } + } + + back_to_waiting(relay_parent_mode); + switch (status) { + case CollationStatus::Seconded: + return std::nullopt; + case CollationStatus::Waiting: { + if (!is_seconded_limit_reached(relay_parent_mode)) { + return std::nullopt; + } else { + if (waiting_queue.empty()) { + return std::nullopt; + } + std::pair v{std::move(waiting_queue.front())}; + waiting_queue.pop_front(); + return v; + }, + } break; + case CollationStatus::WaitingOnValidation: + case CollationStatus::Fetching: { + UNREACHABLE; + } break; + } + } + + bool is_seconded_limit_reached(const ProspectiveParachainsModeOpt &relay_parent_mode) const { + if (relay_parent_mode) { + return seconded_count < (relay_parent_mode->max_candidate_depth + 1); + } + return seconded_count < 1; + } + + }; struct HypotheticalCandidateComplete { diff --git a/core/parachain/validator/impl/parachain_processor.cpp b/core/parachain/validator/impl/parachain_processor.cpp index d244aef6a5..b4d1ef52eb 100644 --- a/core/parachain/validator/impl/parachain_processor.cpp +++ b/core/parachain/validator/impl/parachain_processor.cpp @@ -88,6 +88,12 @@ OUTCOME_CPP_DEFINE_CATEGORY(kagome::parachain, return "Cluster tracker error"; case E::PERSISTED_VALIDATION_DATA_NOT_FOUND: return "Persisted validation data not found"; + case E::PERSISTED_VALIDATION_DATA_MISMATCH: + return "Persisted validation data mismatch"; + case E::CANDIDATE_HASH_MISMATCH: + return "Candidate hash mismatch"; + case E::PARENT_HEAD_DATA_MISMATCH: + return "Parent head data mismatch"; } return "Unknown parachain processor error"; } @@ -1428,6 +1434,55 @@ namespace kagome::parachain { parachain_state.table_context.validators.size()); } + outcome::result ParachainProcessorImpl::fetched_collation_sanity_check( + const PendingCollation &advertised, + const CandidateReceipt &fetched, + const crypto::Hashed> &persisted_validation_data, + std::optional> maybe_parent_head_and_hash + ) { + if (persisted_validation_data.getHash() != fetched.descriptor.persisted_data_hash) { + return Error::PERSISTED_VALIDATION_DATA_MISMATCH; + } + + if (advertised.prospective_candidate && advertised.prospective_candidate->candidate_hash != fetched.hash(*hasher_)) { + return Error::CANDIDATE_HASH_MISMATCH; + } + + if (maybe_parent_head_and_hash && hasher_->blake2b_256(maybe_parent_head_and_hash->first) != maybe_parent_head_and_hash->second) { + return Error::PARENT_HEAD_DATA_MISMATCH; + } + + return outcome::success(); + } + + void ParachainProcessorImpl::dequeue_next_collation_and_fetch( + const RelayHash &relay_parent, + std::pair> previous_fetch + ) { + auto per_relay_state = tryGetStateByRelayParent(relay_parent); + if (!per_relay_state) { + return; + } + + while (auto collation = per_relay_state->get().collations.get_next_collation_to_fetch(previous_fetch, per_relay_state->get().prospective_parachains_mode)) { + const auto &[next, id] = *collation; + SL_TRACE(logger_,"Successfully dequeued next advertisement - fetching ... (relay_parent={}, id={})", relay_parent, id); + if (auto res = fetch_collation(next, id); res.has_error()) { + SL_TRACE(logger_, + "Failed to request a collation, dequeueing next one (relay_parent={}, para_id={}, peer_id={}, error={})", + next.relay_parent, + next.para_id, + next.peer_id, + res.error() + ); + } else { + break; + } + } + } + outcome::result> ParachainProcessorImpl::requestProspectiveValidationData( const RelayHash &candidate_relay_parent, diff --git a/core/parachain/validator/parachain_processor.hpp b/core/parachain/validator/parachain_processor.hpp index e72f3d2563..6c81144d46 100644 --- a/core/parachain/validator/parachain_processor.hpp +++ b/core/parachain/validator/parachain_processor.hpp @@ -123,7 +123,10 @@ namespace kagome::parachain { CORE_INDEX_UNAVAILABLE, INCORRECT_SIGNATURE, CLUSTER_TRACKER_ERROR, - PERSISTED_VALIDATION_DATA_NOT_FOUND + PERSISTED_VALIDATION_DATA_NOT_FOUND, + PERSISTED_VALIDATION_DATA_MISMATCH, + CANDIDATE_HASH_MISMATCH, + PARENT_HEAD_DATA_MISMATCH }; static constexpr uint64_t kBackgroundWorkers = 5; @@ -765,6 +768,12 @@ namespace kagome::parachain { /* * Logic. */ + /// Dequeue another collation and fetch. + void dequeue_next_collation_and_fetch( + const RelayHash &relay_parent, + std::pair> previous_fetch + ); + outcome::result> requestProspectiveValidationData( const RelayHash &relay_parent, @@ -775,6 +784,18 @@ namespace kagome::parachain { requestPersistedValidationData(const RelayHash &relay_parent, ParachainId para_id); + /// Performs a sanity check between advertised and fetched collations. + /// Since the persisted validation data is constructed using the advertised + /// parent head data hash, the latter doesn't require an additional check. + outcome::result fetched_collation_sanity_check( + const PendingCollation &advertised, + const CandidateReceipt &fetched, + const crypto::Hashed> &persisted_validation_data, + std::optional> maybe_parent_head_and_hash + ); + std::optional fetchPersistedValidationData(const RelayHash &relay_parent, ParachainId para_id); From 4b0b2685f71fc5b330c78ca6cdbe4545fe60f22a Mon Sep 17 00:00:00 2001 From: iceseer Date: Tue, 28 May 2024 10:51:44 +0300 Subject: [PATCH 50/71] dequeue_next_collation_and_fetch Signed-off-by: iceseer --- core/network/types/collator_messages.hpp | 8 + core/parachain/validator/collations.hpp | 105 +++++---- .../validator/impl/parachain_processor.cpp | 213 ++++++++++-------- .../validator/parachain_processor.hpp | 44 ++-- 4 files changed, 203 insertions(+), 167 deletions(-) diff --git a/core/network/types/collator_messages.hpp b/core/network/types/collator_messages.hpp index 421f15522f..c0d9ad9b35 100644 --- a/core/network/types/collator_messages.hpp +++ b/core/network/types/collator_messages.hpp @@ -182,6 +182,14 @@ namespace kagome::network { CandidateCommitments commitments; /// commitments retrieved from validation /// result and produced by the execution /// and validation parachain candidate + + CandidateReceipt to_plain(const crypto::Hasher &hasher) const { + CandidateReceipt receipt; + receipt.descriptor = descriptor, + receipt.commitments_hash = + hasher.blake2b_256(scale::encode(commitments).value()); + return receipt; + } }; struct FetchStatementRequest { diff --git a/core/parachain/validator/collations.hpp b/core/parachain/validator/collations.hpp index 306a4fb605..088e4f860f 100644 --- a/core/parachain/validator/collations.hpp +++ b/core/parachain/validator/collations.hpp @@ -101,61 +101,74 @@ namespace kagome::parachain { return seconded_count < seconded_limit; } - void back_to_waiting(const ProspectiveParachainsModeOpt &relay_parent_mode) { - if (status != CollationStatus::Seconded || relay_parent_mode) { - status = CollationStatus::Waiting; + /// Note a seconded collation for a given para. + void note_seconded() { + seconded_count += 1 } - } - /// Returns the next collation to fetch from the `waiting_queue`. - /// - /// This will reset the status back to `Waiting` using [`CollationStatus::back_to_waiting`]. - /// - /// Returns `Some(_)` if there is any collation to fetch, the `status` is not `Seconded` and - /// the passed in `finished_one` is the currently `waiting_collation`. - std::optional> get_next_collation_to_fetch( - const std::pair> &finished_one, - const ProspectiveParachainsModeOpt &relay_parent_mode - ) { - if (fetching_from) { - const auto &[collator_id, maybe_candidate_hash] = *fetching_from; - if (collator_id != finished_one.first && (!maybe_candidate_hash || *maybe_candidate_hash != finished_one.second)) { - SL_TRACE(logger_, "Not proceeding to the next collation - has already been done."); - return std::nullopt; - } + void back_to_waiting( + const ProspectiveParachainsModeOpt &relay_parent_mode) { + if (status != CollationStatus::Seconded || relay_parent_mode) { + status = CollationStatus::Waiting; + } } - back_to_waiting(relay_parent_mode); - switch (status) { - case CollationStatus::Seconded: - return std::nullopt; - case CollationStatus::Waiting: { - if (!is_seconded_limit_reached(relay_parent_mode)) { - return std::nullopt; - } else { - if (waiting_queue.empty()) { + /// Returns the next collation to fetch from the `waiting_queue`. + /// + /// This will reset the status back to `Waiting` using + /// [`CollationStatus::back_to_waiting`]. + /// + /// Returns `Some(_)` if there is any collation to fetch, the `status` is + /// not `Seconded` and the passed in `finished_one` is the currently + /// `waiting_collation`. + std::optional> + get_next_collation_to_fetch( + const std::pair> &finished_one, + const ProspectiveParachainsModeOpt &relay_parent_mode) { + if (fetching_from) { + const auto &[collator_id, maybe_candidate_hash] = *fetching_from; + if (collator_id != finished_one.first + && (!maybe_candidate_hash + || *maybe_candidate_hash != finished_one.second)) { + SL_TRACE( + logger_, + "Not proceeding to the next collation - has already been done."); + return std::nullopt; + } + } + + back_to_waiting(relay_parent_mode); + switch (status) { + case CollationStatus::Seconded: + return std::nullopt; + case CollationStatus::Waiting: { + if (!is_seconded_limit_reached(relay_parent_mode)) { return std::nullopt; + } else { + if (waiting_queue.empty()) { + return std::nullopt; + } + std::pair v{ + std::move(waiting_queue.front())}; + waiting_queue.pop_front(); + return v; } - std::pair v{std::move(waiting_queue.front())}; - waiting_queue.pop_front(); - return v; - }, - } break; - case CollationStatus::WaitingOnValidation: - case CollationStatus::Fetching: { - UNREACHABLE; - } break; + , + } break; + case CollationStatus::WaitingOnValidation: + case CollationStatus::Fetching: { + UNREACHABLE; + } break; + } } - } - bool is_seconded_limit_reached(const ProspectiveParachainsModeOpt &relay_parent_mode) const { - if (relay_parent_mode) { - return seconded_count < (relay_parent_mode->max_candidate_depth + 1); + bool is_seconded_limit_reached( + const ProspectiveParachainsModeOpt &relay_parent_mode) const { + if (relay_parent_mode) { + return seconded_count < (relay_parent_mode->max_candidate_depth + 1); + } + return seconded_count < 1; } - return seconded_count < 1; - } - - }; struct HypotheticalCandidateComplete { diff --git a/core/parachain/validator/impl/parachain_processor.cpp b/core/parachain/validator/impl/parachain_processor.cpp index b4d1ef52eb..74bf9f8895 100644 --- a/core/parachain/validator/impl/parachain_processor.cpp +++ b/core/parachain/validator/impl/parachain_processor.cpp @@ -1435,22 +1435,27 @@ namespace kagome::parachain { } outcome::result ParachainProcessorImpl::fetched_collation_sanity_check( - const PendingCollation &advertised, - const CandidateReceipt &fetched, - const crypto::Hashed> &persisted_validation_data, - std::optional> maybe_parent_head_and_hash - ) { - if (persisted_validation_data.getHash() != fetched.descriptor.persisted_data_hash) { + const PendingCollation &advertised, + const CandidateReceipt &fetched, + const crypto::Hashed> + &persisted_validation_data, + std::optional> maybe_parent_head_and_hash) { + if (persisted_validation_data.getHash() + != fetched.descriptor.persisted_data_hash) { return Error::PERSISTED_VALIDATION_DATA_MISMATCH; - } - - if (advertised.prospective_candidate && advertised.prospective_candidate->candidate_hash != fetched.hash(*hasher_)) { + } + + if (advertised.prospective_candidate + && advertised.prospective_candidate->candidate_hash + != fetched.hash(*hasher_)) { return Error::CANDIDATE_HASH_MISMATCH; - } - - if (maybe_parent_head_and_hash && hasher_->blake2b_256(maybe_parent_head_and_hash->first) != maybe_parent_head_and_hash->second) { + } + + if (maybe_parent_head_and_hash + && hasher_->blake2b_256(maybe_parent_head_and_hash->first) + != maybe_parent_head_and_hash->second) { return Error::PARENT_HEAD_DATA_MISMATCH; } @@ -1458,25 +1463,31 @@ namespace kagome::parachain { } void ParachainProcessorImpl::dequeue_next_collation_and_fetch( - const RelayHash &relay_parent, - std::pair> previous_fetch - ) { + const RelayHash &relay_parent, + std::pair> previous_fetch) { auto per_relay_state = tryGetStateByRelayParent(relay_parent); if (!per_relay_state) { return; } - while (auto collation = per_relay_state->get().collations.get_next_collation_to_fetch(previous_fetch, per_relay_state->get().prospective_parachains_mode)) { + while (auto collation = + per_relay_state->get().collations.get_next_collation_to_fetch( + previous_fetch, + per_relay_state->get().prospective_parachains_mode)) { const auto &[next, id] = *collation; - SL_TRACE(logger_,"Successfully dequeued next advertisement - fetching ... (relay_parent={}, id={})", relay_parent, id); + SL_TRACE(logger_, + "Successfully dequeued next advertisement - fetching ... " + "(relay_parent={}, id={})", + relay_parent, + id); if (auto res = fetch_collation(next, id); res.has_error()) { SL_TRACE(logger_, - "Failed to request a collation, dequeueing next one (relay_parent={}, para_id={}, peer_id={}, error={})", - next.relay_parent, - next.para_id, - next.peer_id, - res.error() - ); + "Failed to request a collation, dequeueing next one " + "(relay_parent={}, para_id={}, peer_id={}, error={})", + next.relay_parent, + next.para_id, + next.peer_id, + res.error()); } else { break; } @@ -3442,8 +3453,8 @@ namespace kagome::parachain { } AttestingData attesting{ - .candidate = candidateFromCommittedCandidateReceipt( - opt_candidate->get().candidate), + .candidate = + opt_candidate->get().candidate.to_plain(*hasher_), .pov_hash = val.committed_receipt.descriptor.pov_hash, .from_validator = statement.payload.ix, .backing = {}}; @@ -4711,82 +4722,98 @@ namespace kagome::parachain { pm_->setCollating(peer_id, pubkey, para_id); } - void ParachainProcessorImpl::handleNotify( + void ParachainProcessorImpl::notify_collation_seconded( const libp2p::peer::PeerId &peer_id, - const primitives::BlockHash &relay_parent) { - if (tryOpenOutgoingCollatingStream( - peer_id, - [peer_id, relay_parent, wptr{weak_from_this()}]( - auto && /*stream*/) { - auto self = wptr.lock(); - if (not self) { - return; - } - self->handleNotify(peer_id, relay_parent); - })) { - return; - } - + CollationVersion version, + const RelayHash &relay_parent, + const SignedFullStatementWithPVD &statement) { logger_->info("Send Seconded to collator.(peer={}, relay parent={})", peer_id, relay_parent); - auto stream_engine = pm_->getStreamEngine(); - BOOST_ASSERT(stream_engine); + network::SignedStatement stm = visit_in_place( + getPayload(statement), + [&](const StatementWithPVDSeconded &s) -> network::SignedStatement { + return { + .payload = + { + .payload = network::CandidateState{s.committed_receipt}, + .ix = p.second.payload.ix, + }, + .signature = p.second.signature, + }; + }, + [&](const StatementWithPVDValid &s) -> network::SignedStatement { + return { + .payload = + { + .payload = network::CandidateState{s.candidate_hash}, + .ix = p.second.payload.ix, + }, + .signature = p.second.signature, + }; + }); - auto collation_protocol = router_->getCollationProtocolVStaging(); - BOOST_ASSERT(collation_protocol); + pm_->getStreamEngine()->send( + peer_id, + router_->getCollationProtocolVStaging(), + std::make_shared< + network::WireMessage>( + network::vstaging::CollatorProtocolMessage( + network::vstaging::CollationMessage( + network::vstaging::CollatorProtocolMessageCollationSeconded{ + .relay_parent = relay_parent, + .statement = std::move(stm)})))); + } - auto &statements_queue = our_current_state_.seconded_statements[peer_id]; - while (!statements_queue.empty()) { - auto p{std::move(statements_queue.front())}; - statements_queue.pop_front(); - RelayHash &rp = p.first; + void ParachainProcessorImpl::notifySeconded( + const primitives::BlockHash &parent, + const SignedFullStatementWithPVD &statement) { + auto receipt = + if_type(getPayload(statement)); + if (!receipt) { + SL_TRACE(logger_, + "Seconded message received with a `Valid` statement. " + "(relay_parent={})", + parent); + return; + } - network::SignedStatement statement = visit_in_place( - getPayload(p.second), - [&](const StatementWithPVDSeconded &s) -> network::SignedStatement { - return { - .payload = - { - .payload = network::CandidateState{s.committed_receipt}, - .ix = p.second.payload.ix, - }, - .signature = p.second.signature, - }; - }, - [&](const StatementWithPVDValid &s) -> network::SignedStatement { - return { - .payload = - { - .payload = network::CandidateState{s.candidate_hash}, - .ix = p.second.payload.ix, - }, - .signature = p.second.signature, - }; - }); + auto fetched_collation = + FetchedCollation::from(receipt->to_plain(*hasher_), *hasher_); + auto it = our_current_state_.validator_side.fetched_candidates.find( + fetched_collation); + if (it == our_current_state_.validator_side.fetched_candidates.end()) { + SL_TRACE(logger_, + "Collation has been seconded, but the relay parent is " + "deactivated. (relay_parent={})", + parent); + return; + } - stream_engine->send( - peer_id, - collation_protocol, - std::make_shared< - network::WireMessage>( - network::vstaging::CollatorProtocolMessage( - network::vstaging::CollationMessage( - network::vstaging:: - CollatorProtocolMessageCollationSeconded{ - .relay_parent = rp, - .statement = std::move(statement)})))); + auto &collator_id = it->second.collator_id; + auto &pending_collation = it->second.pending_collation; + + auto &relay_parent = pending_collation.relay_parent; + auto &peer_id = pending_collation.peer_id; + auto &prospective_candidate = pending_collation.prospective_candidate; + + if (auto peer_state = pm_->getPeerState(peer_id)) { + notify_collation_seconded(peer_id, peer_data.version, relay_parent, stmt); } - } - void ParachainProcessorImpl::notify( - const libp2p::peer::PeerId &peer_id, - const primitives::BlockHash &relay_parent, - const SignedFullStatementWithPVD &statement) { - our_current_state_.seconded_statements[peer_id].emplace_back( - std::make_pair(relay_parent, statement)); - handleNotify(peer_id, relay_parent); + if (auto rp_state = tryGetStateByRelayParent(parent)) { + rp_state->get().collations.status = CollationStatus::Seconded; + rp_state->get().collations.note_seconded(); + } + + const auto maybe_candidate_hash = utils::map( + prospective_candidate, [](const auto &v) { return v.candidate_hash; }); + + dequeue_next_collation_and_fetch(parent, + {collator_id, maybe_candidate_hash}); + + /// TODO(iceseer): Bump collator reputation } bool ParachainProcessorImpl::isValidatingNode() const { @@ -4926,7 +4953,7 @@ namespace kagome::parachain { } parachain_state.issued_statements.insert(candidate_hash); - notify(peer_id, validation_result.relay_parent, stmt); + notifySeconded(validation_result.relay_parent, stmt); } } diff --git a/core/parachain/validator/parachain_processor.hpp b/core/parachain/validator/parachain_processor.hpp index 6c81144d46..cc9f97086a 100644 --- a/core/parachain/validator/parachain_processor.hpp +++ b/core/parachain/validator/parachain_processor.hpp @@ -769,10 +769,9 @@ namespace kagome::parachain { * Logic. */ /// Dequeue another collation and fetch. - void dequeue_next_collation_and_fetch( - const RelayHash &relay_parent, - std::pair> previous_fetch - ); + void dequeue_next_collation_and_fetch( + const RelayHash &relay_parent, + std::pair> previous_fetch); outcome::result> requestProspectiveValidationData( @@ -784,7 +783,7 @@ namespace kagome::parachain { requestPersistedValidationData(const RelayHash &relay_parent, ParachainId para_id); - /// Performs a sanity check between advertised and fetched collations. + /// Performs a sanity check between advertised and fetched collations. /// Since the persisted validation data is constructed using the advertised /// parent head data hash, the latter doesn't require an additional check. outcome::result fetched_collation_sanity_check( @@ -792,9 +791,9 @@ namespace kagome::parachain { const CandidateReceipt &fetched, const crypto::Hashed> &persisted_validation_data, - std::optional> maybe_parent_head_and_hash - ); + crypto::Blake2b_StreamHasher<32>> + &persisted_validation_data, + std::optional> maybe_parent_head_and_hash); std::optional fetchPersistedValidationData(const RelayHash &relay_parent, @@ -872,23 +871,13 @@ namespace kagome::parachain { return descriptor.collator_id; } - network::CandidateReceipt candidateFromCommittedCandidateReceipt( - const network::CommittedCandidateReceipt &data) const { - network::CandidateReceipt receipt; - receipt.descriptor = data.descriptor, - receipt.commitments_hash = - hasher_->blake2b_256(scale::encode(data.commitments).value()); - return receipt; - } - primitives::BlockHash candidateHashFrom( const StatementWithPVD &statement) const { return visit_in_place( statement, [&](const StatementWithPVDSeconded &val) { return hasher_->blake2b_256( - ::scale::encode(candidateFromCommittedCandidateReceipt( - val.committed_receipt)) + ::scale::encode(val.committed_receipt.to_plain(*hasher_)) .value()); }, [&](const StatementWithPVDValid &val) { return val.candidate_hash; }); @@ -921,11 +910,14 @@ namespace kagome::parachain { void share_local_statement_v1(RelayParentState &per_relay_parent, const primitives::BlockHash &relay_parent, const SignedFullStatementWithPVD &statement); - void notify(const libp2p::peer::PeerId &peer_id, - const primitives::BlockHash &relay_parent, - const SignedFullStatementWithPVD &statement); - void handleNotify(const libp2p::peer::PeerId &peer_id, - const primitives::BlockHash &relay_parent); + void notifySeconded(const primitives::BlockHash &relay_parent, + const SignedFullStatementWithPVD &statement); + + /// Notify a collator that its collation got seconded. + void notify_collation_seconded(const libp2p::peer::PeerId &peer_id, + CollationVersion version, + const RelayHash &relay_parent, + const SignedFullStatementWithPVD &statement); void onDeactivateBlocks( const primitives::events::RemoveAfterFinalizationParams &event); @@ -1104,10 +1096,6 @@ namespace kagome::parachain { struct { std::unordered_map state_by_relay_parent; - std::unordered_map< - libp2p::peer::PeerId, - std::deque>> - seconded_statements; std::optional implicit_view; std::unordered_map per_leaf; std::unordered_map per_candidate; From 7988a9bf18aa76ddc41866e978982abaf6bcece4 Mon Sep 17 00:00:00 2001 From: iceseer Date: Tue, 28 May 2024 11:14:29 +0300 Subject: [PATCH 51/71] dequeue_next_collation_and_fetch Signed-off-by: iceseer --- .../validator/impl/parachain_processor.cpp | 39 +++++++++++++++++-- .../validator/parachain_processor.hpp | 3 ++ 2 files changed, 38 insertions(+), 4 deletions(-) diff --git a/core/parachain/validator/impl/parachain_processor.cpp b/core/parachain/validator/impl/parachain_processor.cpp index 74bf9f8895..9a1414fcdb 100644 --- a/core/parachain/validator/impl/parachain_processor.cpp +++ b/core/parachain/validator/impl/parachain_processor.cpp @@ -4766,6 +4766,37 @@ namespace kagome::parachain { .statement = std::move(stm)})))); } + void ParachainProcessorImpl::notifyInvalid( + const primitives::BlockHash &parent, + const CandidateReceipt &candidate_receipt) { + auto fetched_collation = + FetchedCollation::from(candidate_receipt, *hasher_); + const auto &candidate_hash = fetched_collation.candidate_hash; + + auto it = our_current_state_.validator_side.fetched_candidates.find( + fetched_collation); + if (it == our_current_state_.validator_side.fetched_candidates.end()) { + return; + } + + if (!it->second.pending_collation.commitments_hash + || *it->second.pending_collation.commitments_hash + != candidate_receipt.commitments_hash) { + SL_ERROR(logger_, + "Reported invalid candidate for unknown `pending_candidate`! " + "(relay_parent={}, candidate_hash={})", + parent, + candidate_hash); + return; + } + + auto id = it->second.collator_id; + our_current_state_.validator_side.fetched_candidates.erase(it); + + /// TODO(iceseer): reduce collator's reputation + dequeue_next_collation_and_fetch(parent, {id, candidate_hash}); + } + void ParachainProcessorImpl::notifySeconded( const primitives::BlockHash &parent, const SignedFullStatementWithPVD &statement) { @@ -4863,8 +4894,8 @@ namespace kagome::parachain { "Candidate {} validation failed with: {}", candidate_hash, validation_result.result.error()); - /// TODO(iceseer): do https://github.com/qdrvm/kagome/issues/1888 - /// send invalid + notifyInvalid(validation_result.candidate.descriptor.relay_parent, + validation_result.candidate); return; } @@ -4913,8 +4944,8 @@ namespace kagome::parachain { candidate_hash, validation_result.relay_parent, res.error()); - /// TODO(iceseer): do https://github.com/qdrvm/kagome/issues/1888 - /// send invalid + notifyInvalid(validation_result.candidate.descriptor.relay_parent, + validation_result.candidate); return; } diff --git a/core/parachain/validator/parachain_processor.hpp b/core/parachain/validator/parachain_processor.hpp index cc9f97086a..4b5e6ce126 100644 --- a/core/parachain/validator/parachain_processor.hpp +++ b/core/parachain/validator/parachain_processor.hpp @@ -913,6 +913,9 @@ namespace kagome::parachain { void notifySeconded(const primitives::BlockHash &relay_parent, const SignedFullStatementWithPVD &statement); + void notifyInvalid(const primitives::BlockHash &parent, + const CandidateReceipt &candidate_receipt); + /// Notify a collator that its collation got seconded. void notify_collation_seconded(const libp2p::peer::PeerId &peer_id, CollationVersion version, From b8d5446e8015ae818ae42caee7ddc13e760cb21a Mon Sep 17 00:00:00 2001 From: iceseer Date: Tue, 28 May 2024 11:36:33 +0300 Subject: [PATCH 52/71] dequeue_next_collation_and_fetch Signed-off-by: iceseer --- .../validator/impl/parachain_processor.cpp | 7 +++++++ .../validator/parachain_processor.hpp | 2 ++ core/utils/pool_handler.hpp | 18 ++++++++++++++++++ 3 files changed, 27 insertions(+) diff --git a/core/parachain/validator/impl/parachain_processor.cpp b/core/parachain/validator/impl/parachain_processor.cpp index 9a1414fcdb..4e4915f901 100644 --- a/core/parachain/validator/impl/parachain_processor.cpp +++ b/core/parachain/validator/impl/parachain_processor.cpp @@ -4766,9 +4766,13 @@ namespace kagome::parachain { .statement = std::move(stm)})))); } + template void ParachainProcessorImpl::notifyInvalid( const primitives::BlockHash &parent, const CandidateReceipt &candidate_receipt) { + REINVOKE_ONCE( + *main_pool_handler_, notifyInvalid, parent, candidate_receipt); + auto fetched_collation = FetchedCollation::from(candidate_receipt, *hasher_); const auto &candidate_hash = fetched_collation.candidate_hash; @@ -4797,9 +4801,12 @@ namespace kagome::parachain { dequeue_next_collation_and_fetch(parent, {id, candidate_hash}); } + template void ParachainProcessorImpl::notifySeconded( const primitives::BlockHash &parent, const SignedFullStatementWithPVD &statement) { + REINVOKE_ONCE(*main_pool_handler_, notifySeconded, parent, statement); + auto receipt = if_type(getPayload(statement)); if (!receipt) { diff --git a/core/parachain/validator/parachain_processor.hpp b/core/parachain/validator/parachain_processor.hpp index 4b5e6ce126..2e4c638ac4 100644 --- a/core/parachain/validator/parachain_processor.hpp +++ b/core/parachain/validator/parachain_processor.hpp @@ -910,9 +910,11 @@ namespace kagome::parachain { void share_local_statement_v1(RelayParentState &per_relay_parent, const primitives::BlockHash &relay_parent, const SignedFullStatementWithPVD &statement); + template void notifySeconded(const primitives::BlockHash &relay_parent, const SignedFullStatementWithPVD &statement); + template void notifyInvalid(const primitives::BlockHash &parent, const CandidateReceipt &candidate_receipt); diff --git a/core/utils/pool_handler.hpp b/core/utils/pool_handler.hpp index ffbe0f2f48..b0c304981b 100644 --- a/core/utils/pool_handler.hpp +++ b/core/utils/pool_handler.hpp @@ -94,3 +94,21 @@ namespace kagome { }); \ } \ } while (false) + +#define REINVOKE_ONCE(ctx, func, ...) \ + do { \ + if constexpr (kReinvoke) { \ + return post( \ + ctx, \ + [weak{weak_from_this()}, \ + args = std::make_tuple(__VA_ARGS__)]() mutable { \ + if (auto self = weak.lock()) { \ + std::apply( \ + [&](auto &&...args) mutable { \ + self->func(std::forward(args)...); \ + }, \ + std::move(args)); \ + } \ + }); \ + } \ + } while (false) From 6746e3f556e9fa0fc6ae1289b956fde3c71213df Mon Sep 17 00:00:00 2001 From: iceseer Date: Tue, 28 May 2024 21:29:04 +0300 Subject: [PATCH 53/71] 1 Signed-off-by: iceseer --- core/network/types/collator_messages.hpp | 23 +- .../validator/impl/parachain_processor.cpp | 325 +++++++++--------- .../validator/parachain_processor.hpp | 6 +- 3 files changed, 179 insertions(+), 175 deletions(-) diff --git a/core/network/types/collator_messages.hpp b/core/network/types/collator_messages.hpp index c0d9ad9b35..b5b4e161ea 100644 --- a/core/network/types/collator_messages.hpp +++ b/core/network/types/collator_messages.hpp @@ -125,11 +125,28 @@ namespace kagome::network { struct CollationResponse { SCALE_TIE(2); - CandidateReceipt receipt; /// Candidate receipt - ParachainBlock pov; /// PoV block + /// Candidate receipt + CandidateReceipt receipt; + + /// PoV block + ParachainBlock pov; + }; + + struct CollationWithParentHeadData { + SCALE_TIE(3); + /// The receipt of the candidate. + CandidateReceipt receipt; + + /// Candidate's proof of validity. + ParachainBlock pov; + + /// The head data of the candidate's parent. + /// This is needed for elastic scaling to work. + HeadData parent_head_data; }; - using ReqCollationResponseData = boost::variant; + using ReqCollationResponseData = + boost::variant; /** * Sent by clients who want to retrieve the advertised collation at the diff --git a/core/parachain/validator/impl/parachain_processor.cpp b/core/parachain/validator/impl/parachain_processor.cpp index 4e4915f901..8a8e0e4b9f 100644 --- a/core/parachain/validator/impl/parachain_processor.cpp +++ b/core/parachain/validator/impl/parachain_processor.cpp @@ -666,13 +666,33 @@ namespace kagome::parachain { std::vector pruned = our_current_state_.implicit_view->deactivate_leaf(lost); - ; for (const auto removed : pruned) { our_current_state_.state_by_relay_parent.erase(removed); /// TODO(iceseer): do https://github.com/qdrvm/kagome/issues/1888 /// fetched_candidates ??? } + { /// remove cancelations + auto &container = our_current_state_.collation_requests_cancel_handles; + for (auto pc = container.begin(); pc != container.end();) { + if (pc.relay_parent != lost) { + ++pc; + } else { + pc = container.erase(pc); + } + } + } + { /// remove fetched candidates + auto &container = our_current_state_.validator_side.fetched_candidates; + for (auto pc = container.begin(); pc != container.end();) { + if (pc.relay_parent != lost) { + ++pc; + } else { + pc = container.erase(pc); + } + } + } + our_current_state_.per_leaf.erase(lost); our_current_state_.state_by_relay_parent.erase(lost); } @@ -1328,110 +1348,65 @@ namespace kagome::parachain { } } - void ParachainProcessorImpl::handleFetchedCollation( - PendingCollation &&pending_collation, + void ParachainProcessorImpl::handle_collation_fetch_response( + CollationEvent &&collation_event, network::CollationFetchingResponse &&response) { REINVOKE(*main_pool_handler_, - handleFetchedCollation, - std::move(pending_collation), + handle_collation_fetch_response, + std::move(collation_event), std::move(response)); SL_TRACE(logger_, "Processing collation from {}, relay parent: {}, para id: {}", - pending_collation.peer_id, - pending_collation.relay_parent, - pending_collation.para_id); + collation_event.pending_collation.peer_id, + collation_event.pending_collation.relay_parent, + collation_event.pending_collation.para_id); our_current_state_.collation_requests_cancel_handles.erase( - pending_collation); + collation_event.pending_collation); auto collation_response = - if_type(response.response_data); + if_type(response.response_data); if (!collation_response) { SL_WARN(logger_, "Not a CollationResponse message from {}.", - pending_collation.peer_id); + collation_event.pending_collation.peer_id); return; } - auto opt_parachain_state = - tryGetStateByRelayParent(pending_collation.relay_parent); - if (!opt_parachain_state) { - SL_TRACE(logger_, - "Fetched collation from {}:{} out of view", - pending_collation.peer_id, - pending_collation.relay_parent); - return; - } - - auto &per_relay_parent = opt_parachain_state->get(); - auto &collations = per_relay_parent.collations; - const auto &relay_parent_mode = - per_relay_parent.prospective_parachains_mode; + SL_WARN(logger_, + "Received collation (v3) (para_id={}, relay_parent={}, " + "candidate_hash={})", + collation_event.pending_collation.para_id, + collation_event.pending_collation.relay_parent, + collation_response->get().receipt.hash(*hasher_)); - network::CandidateReceipt receipt( - std::move(collation_response->get().receipt)); - network::ParachainBlock pov(std::move(collation_response->get().pov)); - const network::CandidateDescriptor &descriptor = receipt.descriptor; + PendingCollationFetch p{ + .collation_event = std::move(collation_event), + .candidate_receipt = std::move(collation_response->get().receipt), + .pov = std::move(collation_response->get().pov), + .maybe_parent_head_data = + std::move(collation_response->get().parent_head_data), + }; - /// TODO(iceseer): do https://github.com/qdrvm/kagome/issues/1888 - /// fetched_candidates ??? + auto collator_id = p.collation_event.collator_id; + auto pending_collation = p.collation_event.pending_collation; - auto ¶chain_state = opt_parachain_state->get(); - const auto &assignment = parachain_state.assigned_para; - // auto &seconded = parachain_state.seconded; - auto &issued_statements = parachain_state.issued_statements; - - const auto candidate_para_id = descriptor.para_id; - if (!assignment || candidate_para_id != *assignment) { + if (auto res = kick_off_seconding(std::move(p)); res.has_error()) { SL_WARN(logger_, - "Try to second for para_id {} out of our assignment {}.", - candidate_para_id, - assignment ? std::to_string(*assignment) : "{no assignment}"); - return; - } - - if (issued_statements.count(receipt.hash(*hasher_)) != 0) { - SL_DEBUG( - logger_, "Statement of {} already issued.", receipt.hash(*hasher_)); - return; - } - - pending_collation.commitments_hash = receipt.commitments_hash; - - std::optional pvd; - if (relay_parent_mode && pending_collation.prospective_candidate) { - pvd = requestProspectiveValidationData( - pending_collation.relay_parent, - pending_collation.prospective_candidate->second, - pending_collation.para_id); - } else if (!relay_parent_mode) { - pvd = requestPersistedValidationData(receipt.descriptor.relay_parent, - receipt.descriptor.para_id); - } else { - return; - } - - if (!pvd) { - SL_ERROR( - logger_, - "Persisted validation data not found. (relay parent={}, para={})", - pending_collation.relay_parent, - pending_collation.para_id); - return; + "Seconding aborted due to an error. (relay_parent={}, " + "para_id={}, peer_id={}, error={})", + pending_collation.relay_parent, + pending_collation.para_id, + pending_collation.peer_id, + res.error()); + + const auto maybe_candidate_hash = + utils::map(pending_collation.prospective_candidate, + [](const auto &v) { return v.candidate_hash; }); + dequeue_next_collation_and_fetch(pending_collation.relay_parent, + {collator_id, maybe_candidate_hash}); } - - /// TODO(iceseer): do https://github.com/qdrvm/kagome/issues/1888 - /// fetched_collation_sanity_check - - collations.status = CollationStatus::WaitingOnValidation; - validateAsync( - std::move(receipt), - std::move(pov), - std::move(*pvd), - pending_collation.peer_id, - pending_collation.relay_parent, - parachain_state.table_context.validators.size()); } outcome::result ParachainProcessorImpl::fetched_collation_sanity_check( @@ -3147,7 +3122,7 @@ namespace kagome::parachain { BOOST_ASSERT(main_pool_handler_->isInCurrentThread()); const auto candidate_hash{attesting_data.candidate.hash(*hasher_)}; - if (!parachain_state.awaiting_validation.insert(candidate_hash).second) { + if (parachain_state.issued_statements.contains(candidate_hash)) { return; } @@ -4829,8 +4804,11 @@ namespace kagome::parachain { return; } - auto &collator_id = it->second.collator_id; - auto &pending_collation = it->second.pending_collation; + auto collation_event{std::move(it->second)}; + our_current_state_.validator_side.fetched_candidates.erase(it); + + auto &collator_id = collation_event.collator_id; + auto &pending_collation = collation_event.pending_collation; auto &relay_parent = pending_collation.relay_parent; auto &peer_id = pending_collation.peer_id; @@ -4894,8 +4872,8 @@ namespace kagome::parachain { } auto ¶chain_state = opt_parachain_state->get(); - auto &seconded = parachain_state.seconded; const auto candidate_hash = validation_result.candidate.hash(*hasher_); + if (!validation_result.result) { SL_WARN(logger_, "Candidate {} validation failed with: {}", @@ -4906,93 +4884,94 @@ namespace kagome::parachain { return; } - if (!seconded - && parachain_state.issued_statements.count(candidate_hash) == 0) { - logger_->trace( - "Second candidate complete. (candidate={}, peer={}, relay parent={})", - candidate_hash, - peer_id, - validation_result.relay_parent); + if (parachain_state.issued_statements.contains(candidate_hash)) { + return; + } - const auto parent_head_data_hash = - hasher_->blake2b_256(validation_result.pvd.parent_head); - const auto ph = - hasher_->blake2b_256(validation_result.commitments->para_head); - if (parent_head_data_hash == ph) { - return; - } + logger_->trace( + "Second candidate complete. (candidate={}, peer={}, relay parent={})", + candidate_hash, + peer_id, + validation_result.relay_parent); - HypotheticalCandidateComplete hypothetical_candidate{ - .candidate_hash = candidate_hash, - .receipt = - network::CommittedCandidateReceipt{ - .descriptor = validation_result.candidate.descriptor, - .commitments = *validation_result.commitments, - }, - .persisted_validation_data = validation_result.pvd, - }; + const auto parent_head_data_hash = + hasher_->blake2b_256(validation_result.pvd.parent_head); + const auto ph = + hasher_->blake2b_256(validation_result.commitments->para_head); + if (parent_head_data_hash == ph) { + return; + } - fragment::FragmentTreeMembership fragment_tree_membership; - if (auto seconding_allowed = - secondingSanityCheck(hypothetical_candidate, false)) { - fragment_tree_membership = std::move(*seconding_allowed); - } else { - return; - } + HypotheticalCandidateComplete hypothetical_candidate{ + .candidate_hash = candidate_hash, + .receipt = + network::CommittedCandidateReceipt{ + .descriptor = validation_result.candidate.descriptor, + .commitments = *validation_result.commitments, + }, + .persisted_validation_data = validation_result.pvd, + }; - seconded = candidate_hash; + fragment::FragmentTreeMembership fragment_tree_membership; + if (auto seconding_allowed = + secondingSanityCheck(hypothetical_candidate, false)) { + fragment_tree_membership = std::move(*seconding_allowed); + } else { + return; + } - auto res = sign_import_and_distribute_statement( - parachain_state, validation_result); - if (res.has_error()) { - SL_WARN(logger_, - "Attempted to second candidate but was rejected by prospective " - "parachains. (candidate_hash={}, relay_parent={}, error={})", - candidate_hash, - validation_result.relay_parent, - res.error()); - notifyInvalid(validation_result.candidate.descriptor.relay_parent, - validation_result.candidate); - return; - } + seconded = candidate_hash; - if (!res.value()) { - return; - } + auto res = sign_import_and_distribute_statement( + parachain_state, validation_result); + if (res.has_error()) { + SL_WARN(logger_, + "Attempted to second candidate but was rejected by prospective " + "parachains. (candidate_hash={}, relay_parent={}, error={})", + candidate_hash, + validation_result.relay_parent, + res.error()); + notifyInvalid(validation_result.candidate.descriptor.relay_parent, + validation_result.candidate); + return; + } - auto &stmt = *res.value(); - if (auto it = our_current_state_.per_candidate.find(candidate_hash); - it != our_current_state_.per_candidate.end()) { - it->second.seconded_locally = true; - } else { + if (!res.value()) { + return; + } + + auto &stmt = *res.value(); + if (auto it = our_current_state_.per_candidate.find(candidate_hash); + it != our_current_state_.per_candidate.end()) { + it->second.seconded_locally = true; + } else { + SL_WARN(logger_, + "Missing `per_candidate` for seconded candidate. (candidate " + "hash={})", + candidate_hash); + } + + for (const auto &[leaf, depths] : fragment_tree_membership) { + auto it = our_current_state_.per_leaf.find(leaf); + if (it == our_current_state_.per_leaf.end()) { SL_WARN(logger_, - "Missing `per_candidate` for seconded candidate. (candidate " - "hash={})", - candidate_hash); + "Missing `per_leaf` for known active leaf. (leaf={})", + leaf); + continue; } - for (const auto &[leaf, depths] : fragment_tree_membership) { - auto it = our_current_state_.per_leaf.find(leaf); - if (it == our_current_state_.per_leaf.end()) { - SL_WARN(logger_, - "Missing `per_leaf` for known active leaf. (leaf={})", - leaf); - continue; - } - - ActiveLeafState &leaf_data = it->second; - auto &seconded_at_depth = - leaf_data.seconded_at_depth[validation_result.candidate.descriptor - .para_id]; + ActiveLeafState &leaf_data = it->second; + auto &seconded_at_depth = + leaf_data.seconded_at_depth[validation_result.candidate.descriptor + .para_id]; - for (const auto &depth : depths) { - seconded_at_depth.emplace(depth, candidate_hash); - } + for (const auto &depth : depths) { + seconded_at_depth.emplace(depth, candidate_hash); } - - parachain_state.issued_statements.insert(candidate_hash); - notifySeconded(validation_result.relay_parent, stmt); } + + parachain_state.issued_statements.insert(candidate_hash); + notifySeconded(validation_result.relay_parent, stmt); } void ParachainProcessorImpl::share_local_statement_v1( @@ -5217,6 +5196,18 @@ namespace kagome::parachain { n_validators); const auto candidate_hash{candidate.hash(*hasher_)}; + if (!parachain_state->get() + .awaiting_validation.insert(candidate_hash) + .second) { + return; + } + + if constexpr (kMode == ValidationTaskType::kSecond) { + if (rp_state.issued_statements.contains(candidate_hash)) { + return; + } + } + SL_INFO(logger_, "Starting validation task.(para id={}, " "relay parent={}, peer={}, candidate_hash={})", @@ -5491,9 +5482,7 @@ namespace kagome::parachain { outcome::result ParachainProcessorImpl::kick_off_seconding( PendingCollationFetch &&pending_collation_fetch) { - REINVOKE(*main_pool_handler_, - kick_off_seconding, - std::move(pending_collation_fetch)); + BOOST_ASSERT(main_pool_handler_->isInCurrentThread()); auto &collation_event = pending_collation_fetch.collation_event; auto pending_collation = collation_event.pending_collation; @@ -5945,13 +5934,11 @@ namespace kagome::parachain { peer_id, relay_parent, result.error()); - /// TODO(iceseer): do https://github.com/qdrvm/kagome/issues/1888 - /// dequeue_next_collation_and_fetch return; } - self->handleFetchedCollation(std::move(pending_collation), - std::move(result).value()); + self->handle_collation_fetch_response(std::move(pending_collation), + std::move(result).value()); }; SL_TRACE(logger_, diff --git a/core/parachain/validator/parachain_processor.hpp b/core/parachain/validator/parachain_processor.hpp index 2e4c638ac4..53f0843660 100644 --- a/core/parachain/validator/parachain_processor.hpp +++ b/core/parachain/validator/parachain_processor.hpp @@ -418,7 +418,6 @@ namespace kagome::parachain { std::shared_ptr::RefObj> per_session_state; - std::optional seconded; std::optional our_index; std::optional our_group; @@ -810,8 +809,9 @@ namespace kagome::parachain { AttestingData &attesting_data, const runtime::PersistedValidationData &persisted_validation_data, RelayParentState ¶chain_state); - void handleFetchedCollation(PendingCollation &&pending_collation, - network::CollationFetchingResponse &&response); + void handle_collation_fetch_response( + CollationEvent &&collation_event, + network::CollationFetchingResponse &&response); template std::optional createAndSignStatement( const ValidateAndSecondResult &validation_result); From 21b1243aa1d3481adc454fa46174b594d3e98196 Mon Sep 17 00:00:00 2001 From: iceseer Date: Thu, 30 May 2024 00:48:08 +0300 Subject: [PATCH 54/71] new validator code Signed-off-by: iceseer --- core/network/peer_state.hpp | 64 ------ core/network/types/collator_messages.hpp | 1 + .../types/collator_messages_vstaging.hpp | 67 ++++++ core/parachain/validator/collations.hpp | 33 +-- .../validator/impl/parachain_processor.cpp | 217 ++++++++++-------- .../validator/parachain_processor.hpp | 58 +++-- .../validator/prospective_parachains.hpp | 5 +- 7 files changed, 233 insertions(+), 212 deletions(-) diff --git a/core/network/peer_state.hpp b/core/network/peer_state.hpp index 151569c86d..3434cb621d 100644 --- a/core/network/peer_state.hpp +++ b/core/network/peer_state.hpp @@ -37,70 +37,6 @@ namespace kagome::network { std::chrono::system_clock::time_point last_active; }; - struct ProspectiveCandidate { - /// Candidate hash. - CandidateHash candidate_hash; - /// Parent head-data hash as supplied in advertisement. - Hash parent_head_data_hash; - }; - - struct PendingCollation { - /// Candidate's relay parent. - RelayHash relay_parent; - /// Parachain id. - ParachainId para_id; - /// Peer that advertised this collation. - libp2p::peer::PeerId peer_id; - /// Optional candidate hash and parent head-data hash if were - /// supplied in advertisement. - std::optional prospective_candidate; - /// Hash of the candidate's commitments. - std::optional commitments_hash; - }; - - struct CollationEvent { - /// Collator id. - CollatorId collator_id; - /// The network protocol version the collator is using. - CollationVersion collator_protocol_version; - /// The requested collation data. - PendingCollation pending_collation; - }; - - struct PendingCollationFetch { - /// Collation identifier. - CollationEvent collation_event; - /// Candidate receipt. - CandidateReceipt candidate_receipt; - /// Proof of validity. - PoV pov; - /// Optional parachain parent head data. - /// Only needed for elastic scaling. - std::optional maybe_parent_head_data; - }; - - struct FetchedCollation { - /// Candidate's relay parent. - RelayHash relay_parent; - /// Parachain id. - ParachainId para_id; - /// Candidate hash. - CandidateHash candidate_hash; - /// Id of the collator the collation was fetched from. - CollatorId collator_id; - - static FetchedCollation from(const network::CandidateReceipt &receipt, - const crypto::Hasher &hasher) { - const auto &descriptor = receipt.descriptor; - return FetchedCollation{ - .relay_parent = descriptor.relay_parent, - .para_id = descriptor.para_id, - .candidate_hash = receipt.hash(hasher), - .collator_id = descriptor.collator_id, - }; - } - }; - using OurView = network::View; struct PeerStateCompact { diff --git a/core/network/types/collator_messages.hpp b/core/network/types/collator_messages.hpp index b5b4e161ea..519b60952e 100644 --- a/core/network/types/collator_messages.hpp +++ b/core/network/types/collator_messages.hpp @@ -7,6 +7,7 @@ #pragma once #include +#include #include #include #include diff --git a/core/network/types/collator_messages_vstaging.hpp b/core/network/types/collator_messages_vstaging.hpp index ae481b8dfd..4038e03aae 100644 --- a/core/network/types/collator_messages_vstaging.hpp +++ b/core/network/types/collator_messages_vstaging.hpp @@ -360,6 +360,73 @@ namespace kagome::network { VStaging = 2, }; + struct ProspectiveCandidate { + SCALE_TIE(2); + /// Candidate hash. + CandidateHash candidate_hash; + /// Parent head-data hash as supplied in advertisement. + Hash parent_head_data_hash; + }; + + struct PendingCollation { + /// Candidate's relay parent. + RelayHash relay_parent; + /// Parachain id. + ParachainId para_id; + /// Peer that advertised this collation. + libp2p::peer::PeerId peer_id; + /// Optional candidate hash and parent head-data hash if were + /// supplied in advertisement. + std::optional prospective_candidate; + /// Hash of the candidate's commitments. + std::optional commitments_hash; + }; + + struct CollationEvent { + /// Collator id. + CollatorId collator_id; + /// The network protocol version the collator is using. + CollationVersion collator_protocol_version; + /// The requested collation data. + PendingCollation pending_collation; + }; + + struct PendingCollationFetch { + /// Collation identifier. + CollationEvent collation_event; + /// Candidate receipt. + CandidateReceipt candidate_receipt; + /// Proof of validity. + PoV pov; + /// Optional parachain parent head data. + /// Only needed for elastic scaling. + std::optional maybe_parent_head_data; + }; + + struct FetchedCollation { + SCALE_TIE(4); + + /// Candidate's relay parent. + RelayHash relay_parent; + /// Parachain id. + ParachainId para_id; + /// Candidate hash. + CandidateHash candidate_hash; + /// Id of the collator the collation was fetched from. + CollatorId collator_id; + + static FetchedCollation from(const network::CandidateReceipt &receipt, + const crypto::Hasher &hasher) { + const auto &descriptor = receipt.descriptor; + return FetchedCollation{ + .relay_parent = descriptor.relay_parent, + .para_id = descriptor.para_id, + .candidate_hash = receipt.hash(hasher), + .collator_id = descriptor.collator_id, + }; + } + }; + /** * Common WireMessage that represents messages in NetworkBridge. */ diff --git a/core/parachain/validator/collations.hpp b/core/parachain/validator/collations.hpp index 088e4f860f..73cb9b0658 100644 --- a/core/parachain/validator/collations.hpp +++ b/core/parachain/validator/collations.hpp @@ -55,8 +55,8 @@ namespace kagome::parachain { Seconded, }; - using ProspectiveCandidate = network::ProspectiveCandidate; - using PendingCollation = network::PendingCollation; + using ProspectiveCandidate = kagome::network::ProspectiveCandidate; + using PendingCollation = kagome::network::PendingCollation; struct PendingCollationHash { size_t operator()(const PendingCollation &val) const noexcept { @@ -64,8 +64,9 @@ namespace kagome::parachain { boost::hash_combine(r, std::hash()(val.relay_parent)); boost::hash_combine(r, std::hash()(val.para_id)); if (val.prospective_candidate) { - boost::hash_combine( - r, std::hash()(val.prospective_candidate->first)); + boost::hash_combine(r, + std::hash()( + val.prospective_candidate->candidate_hash)); } return r; } @@ -103,7 +104,7 @@ namespace kagome::parachain { /// Note a seconded collation for a given para. void note_seconded() { - seconded_count += 1 + seconded_count += 1; } void back_to_waiting( @@ -124,14 +125,15 @@ namespace kagome::parachain { std::optional> get_next_collation_to_fetch( const std::pair> &finished_one, - const ProspectiveParachainsModeOpt &relay_parent_mode) { + const ProspectiveParachainsModeOpt &relay_parent_mode, + log::Logger logger) { if (fetching_from) { const auto &[collator_id, maybe_candidate_hash] = *fetching_from; if (collator_id != finished_one.first && (!maybe_candidate_hash || *maybe_candidate_hash != finished_one.second)) { SL_TRACE( - logger_, + logger, "Not proceeding to the next collation - has already been done."); return std::nullopt; } @@ -144,22 +146,21 @@ namespace kagome::parachain { case CollationStatus::Waiting: { if (!is_seconded_limit_reached(relay_parent_mode)) { return std::nullopt; - } else { - if (waiting_queue.empty()) { - return std::nullopt; - } - std::pair v{ - std::move(waiting_queue.front())}; - waiting_queue.pop_front(); - return v; } - , + if (waiting_queue.empty()) { + return std::nullopt; + } + std::pair v{ + std::move(waiting_queue.front())}; + waiting_queue.pop_front(); + return v; } break; case CollationStatus::WaitingOnValidation: case CollationStatus::Fetching: { UNREACHABLE; } break; } + return std::nullopt; } bool is_seconded_limit_reached( diff --git a/core/parachain/validator/impl/parachain_processor.cpp b/core/parachain/validator/impl/parachain_processor.cpp index 8a8e0e4b9f..4115e10e33 100644 --- a/core/parachain/validator/impl/parachain_processor.cpp +++ b/core/parachain/validator/impl/parachain_processor.cpp @@ -94,6 +94,12 @@ OUTCOME_CPP_DEFINE_CATEGORY(kagome::parachain, return "Candidate hash mismatch"; case E::PARENT_HEAD_DATA_MISMATCH: return "Parent head data mismatch"; + case E::NO_PEER: + return "No peer"; + case E::ALREADY_REQUESTED: + return "Already requested"; + case E::NOT_ADVERTISED: + return "Not advertised"; } return "Unknown parachain processor error"; } @@ -675,7 +681,7 @@ namespace kagome::parachain { { /// remove cancelations auto &container = our_current_state_.collation_requests_cancel_handles; for (auto pc = container.begin(); pc != container.end();) { - if (pc.relay_parent != lost) { + if (pc->relay_parent != lost) { ++pc; } else { pc = container.erase(pc); @@ -685,7 +691,7 @@ namespace kagome::parachain { { /// remove fetched candidates auto &container = our_current_state_.validator_side.fetched_candidates; for (auto pc = container.begin(); pc != container.end();) { - if (pc.relay_parent != lost) { + if (pc->first.relay_parent != lost) { ++pc; } else { pc = container.erase(pc); @@ -1248,7 +1254,6 @@ namespace kagome::parachain { .assigned_para = assigned_para, .validator_to_group = std::move(validator_to_group), .per_session_state = per_session_state, - .seconded = {}, .our_index = validator->validatorIndex(), .our_group = per_session_state->value().groups.byValidatorIndex( validator->validatorIndex()), @@ -1349,7 +1354,7 @@ namespace kagome::parachain { } void ParachainProcessorImpl::handle_collation_fetch_response( - CollationEvent &&collation_event, + network::CollationEvent &&collation_event, network::CollationFetchingResponse &&response) { REINVOKE(*main_pool_handler_, handle_collation_fetch_response, @@ -1381,7 +1386,7 @@ namespace kagome::parachain { collation_event.pending_collation.relay_parent, collation_response->get().receipt.hash(*hasher_)); - PendingCollationFetch p{ + network::PendingCollationFetch p{ .collation_event = std::move(collation_event), .candidate_receipt = std::move(collation_response->get().receipt), .pov = std::move(collation_response->get().pov), @@ -1411,7 +1416,7 @@ namespace kagome::parachain { outcome::result ParachainProcessorImpl::fetched_collation_sanity_check( const PendingCollation &advertised, - const CandidateReceipt &fetched, + const network::CandidateReceipt &fetched, const crypto::Hashed> @@ -1448,14 +1453,15 @@ namespace kagome::parachain { while (auto collation = per_relay_state->get().collations.get_next_collation_to_fetch( previous_fetch, - per_relay_state->get().prospective_parachains_mode)) { - const auto &[next, id] = *collation; + per_relay_state->get().prospective_parachains_mode, + logger_)) { + const auto &[next, id] = std::move(*collation); SL_TRACE(logger_, "Successfully dequeued next advertisement - fetching ... " "(relay_parent={}, id={})", relay_parent, id); - if (auto res = fetch_collation(next, id); res.has_error()) { + if (auto res = fetchCollation(next, id); res.has_error()) { SL_TRACE(logger_, "Failed to request a collation, dequeueing next one " "(relay_parent={}, para_id={}, peer_id={}, error={})", @@ -1489,7 +1495,7 @@ namespace kagome::parachain { return opt_pvd; } - std::optional + outcome::result> ParachainProcessorImpl::fetchPersistedValidationData( const RelayHash &relay_parent, ParachainId para_id) { return requestPersistedValidationData(relay_parent, para_id); @@ -3022,9 +3028,14 @@ namespace kagome::parachain { std::optional stm; if (auto ccr = if_type( getPayload(statement_msg->statement).candidate_state)) { + auto res_pvd = fetchPersistedValidationData( + statement_msg->relay_parent, ccr->get().descriptor.para_id); + if (res_pvd.has_error()) { + SL_TRACE(logger_, "No pvd fetched. (error={})", res_pvd.error()); + return; + } std::optional pvd = - fetchPersistedValidationData(statement_msg->relay_parent, - ccr->get().descriptor.para_id); + std::move(*res_pvd.value()); if (!pvd) { SL_TRACE(logger_, "No pvd fetched."); return; @@ -3184,9 +3195,7 @@ namespace kagome::parachain { std::move(candidate), std::move(*p), std::move(pvd), - peer_id, - relay_parent, - parachain_state->get().table_context.validators.size()); + relay_parent); } }); } @@ -4699,7 +4708,7 @@ namespace kagome::parachain { void ParachainProcessorImpl::notify_collation_seconded( const libp2p::peer::PeerId &peer_id, - CollationVersion version, + network::CollationVersion version, const RelayHash &relay_parent, const SignedFullStatementWithPVD &statement) { logger_->info("Send Seconded to collator.(peer={}, relay parent={})", @@ -4713,9 +4722,9 @@ namespace kagome::parachain { .payload = { .payload = network::CandidateState{s.committed_receipt}, - .ix = p.second.payload.ix, + .ix = statement.payload.ix, }, - .signature = p.second.signature, + .signature = statement.signature, }; }, [&](const StatementWithPVDValid &s) -> network::SignedStatement { @@ -4723,9 +4732,9 @@ namespace kagome::parachain { .payload = { .payload = network::CandidateState{s.candidate_hash}, - .ix = p.second.payload.ix, + .ix = statement.payload.ix, }, - .signature = p.second.signature, + .signature = statement.signature, }; }); @@ -4744,12 +4753,12 @@ namespace kagome::parachain { template void ParachainProcessorImpl::notifyInvalid( const primitives::BlockHash &parent, - const CandidateReceipt &candidate_receipt) { + const network::CandidateReceipt &candidate_receipt) { REINVOKE_ONCE( *main_pool_handler_, notifyInvalid, parent, candidate_receipt); auto fetched_collation = - FetchedCollation::from(candidate_receipt, *hasher_); + network::FetchedCollation::from(candidate_receipt, *hasher_); const auto &candidate_hash = fetched_collation.candidate_hash; auto it = our_current_state_.validator_side.fetched_candidates.find( @@ -4782,9 +4791,9 @@ namespace kagome::parachain { const SignedFullStatementWithPVD &statement) { REINVOKE_ONCE(*main_pool_handler_, notifySeconded, parent, statement); - auto receipt = + auto seconded = if_type(getPayload(statement)); - if (!receipt) { + if (!seconded) { SL_TRACE(logger_, "Seconded message received with a `Valid` statement. " "(relay_parent={})", @@ -4792,8 +4801,8 @@ namespace kagome::parachain { return; } - auto fetched_collation = - FetchedCollation::from(receipt->to_plain(*hasher_), *hasher_); + auto fetched_collation = network::FetchedCollation::from( + seconded->get().committed_receipt.to_plain(*hasher_), *hasher_); auto it = our_current_state_.validator_side.fetched_candidates.find( fetched_collation); if (it == our_current_state_.validator_side.fetched_candidates.end()) { @@ -4814,8 +4823,12 @@ namespace kagome::parachain { auto &peer_id = pending_collation.peer_id; auto &prospective_candidate = pending_collation.prospective_candidate; - if (auto peer_state = pm_->getPeerState(peer_id)) { - notify_collation_seconded(peer_id, peer_data.version, relay_parent, stmt); + if (auto peer_data = pm_->getPeerState(peer_id)) { + network::CollationVersion version = network::CollationVersion::VStaging; + if (peer_data->get().version) { + version = *peer_data->get().version; + } + notify_collation_seconded(peer_id, version, relay_parent, statement); } if (auto rp_state = tryGetStateByRelayParent(parent)) { @@ -4856,17 +4869,14 @@ namespace kagome::parachain { } void ParachainProcessorImpl::onValidationComplete( - const libp2p::peer::PeerId &peer_id, const ValidateAndSecondResult &validation_result) { - logger_->trace("On validation complete. (peer={}, relay parent={})", - peer_id, + logger_->trace("On validation complete. (relay parent={})", validation_result.relay_parent); auto opt_parachain_state = tryGetStateByRelayParent(validation_result.relay_parent); if (!opt_parachain_state) { - logger_->trace("Validated candidate from {}:{} out of view", - peer_id, + logger_->trace("Validated candidate from {} out of view", validation_result.relay_parent); return; } @@ -4888,11 +4898,9 @@ namespace kagome::parachain { return; } - logger_->trace( - "Second candidate complete. (candidate={}, peer={}, relay parent={})", - candidate_hash, - peer_id, - validation_result.relay_parent); + logger_->trace("Second candidate complete. (candidate={}, relay parent={})", + candidate_hash, + validation_result.relay_parent); const auto parent_head_data_hash = hasher_->blake2b_256(validation_result.pvd.parent_head); @@ -4920,8 +4928,6 @@ namespace kagome::parachain { return; } - seconded = candidate_hash; - auto res = sign_import_and_distribute_statement( parachain_state, validation_result); if (res.has_error()) { @@ -5146,12 +5152,10 @@ namespace kagome::parachain { template void ParachainProcessorImpl::makeAvailable( - const libp2p::peer::PeerId &peer_id, const primitives::BlockHash &candidate_hash, ValidateAndSecondResult &&validate_and_second_result) { REINVOKE(*main_pool_handler_, makeAvailable, - peer_id, candidate_hash, std::move(validate_and_second_result)); @@ -5172,9 +5176,9 @@ namespace kagome::parachain { parachain_state->get().awaiting_validation.erase(candidate_hash); auto q{std::move(validate_and_second_result)}; if constexpr (kMode == ValidationTaskType::kSecond) { - onValidationComplete(peer_id, std::move(q)); + onValidationComplete(std::move(q)); } else { - onAttestComplete(peer_id, std::move(q)); + onAttestComplete(std::move(q)); } } @@ -5183,37 +5187,38 @@ namespace kagome::parachain { network::CandidateReceipt &&candidate, network::ParachainBlock &&pov, runtime::PersistedValidationData &&pvd, - const libp2p::peer::PeerId &peer_id, - const primitives::BlockHash &relay_parent, - size_t n_validators) { + const primitives::BlockHash &relay_parent) { REINVOKE(*main_pool_handler_, validateAsync, std::move(candidate), std::move(pov), std::move(pvd), - peer_id, - relay_parent, - n_validators); + relay_parent); - const auto candidate_hash{candidate.hash(*hasher_)}; - if (!parachain_state->get() - .awaiting_validation.insert(candidate_hash) - .second) { + auto parachain_state = + tryGetStateByRelayParent(candidate.descriptor.relay_parent); + if (!parachain_state) { return; } - if constexpr (kMode == ValidationTaskType::kSecond) { - if (rp_state.issued_statements.contains(candidate_hash)) { + const auto candidate_hash{candidate.hash(*hasher_)}; + if constexpr (kMode == ValidationTaskType::kAttest) { + if (parachain_state->get().issued_statements.contains(candidate_hash)) { return; } } + if (!parachain_state->get() + .awaiting_validation.insert(candidate_hash) + .second) { + return; + } + SL_INFO(logger_, "Starting validation task.(para id={}, " - "relay parent={}, peer={}, candidate_hash={})", + "relay parent={}, candidate_hash={})", candidate.descriptor.para_id, relay_parent, - peer_id, candidate_hash); /// TODO(iceseer): do https://github.com/qdrvm/kagome/issues/1888 @@ -5223,9 +5228,9 @@ namespace kagome::parachain { candidate, pov, pvd, - peer_id, relay_parent, - n_validators, + n_validators{ + parachain_state->get().table_context.validators.size()}, _measure, candidate_hash]( outcome::result validation_result) mutable { @@ -5268,7 +5273,6 @@ namespace kagome::parachain { available_data.validation_data); self->makeAvailable( - peer_id, candidate_hash, ValidateAndSecondResult{ .result = outcome::success(), @@ -5297,7 +5301,7 @@ namespace kagome::parachain { } void ParachainProcessorImpl::onAttestComplete( - const libp2p::peer::PeerId &, const ValidateAndSecondResult &result) { + const ValidateAndSecondResult &result) { auto parachain_state = tryGetStateByRelayParent(result.relay_parent); if (!parachain_state) { logger_->warn( @@ -5481,7 +5485,7 @@ namespace kagome::parachain { } outcome::result ParachainProcessorImpl::kick_off_seconding( - PendingCollationFetch &&pending_collation_fetch) { + network::PendingCollationFetch &&pending_collation_fetch) { BOOST_ASSERT(main_pool_handler_->isInCurrentThread()); auto &collation_event = pending_collation_fetch.collation_event; @@ -5489,8 +5493,8 @@ namespace kagome::parachain { auto relay_parent = pending_collation.relay_parent; OUTCOME_TRY(per_relay_parent, getStateByRelayParent(relay_parent)); - auto &collations = per_relay_parent->get().collations; - auto fetched_collation = FetchedCollation::from( + auto &collations = per_relay_parent.get().collations; + auto fetched_collation = network::FetchedCollation::from( pending_collation_fetch.candidate_receipt, *hasher_); if (our_current_state_.validator_side.fetched_candidates.contains( @@ -5498,17 +5502,15 @@ namespace kagome::parachain { return Error::DUPLICATE; } - auto &entry = - our_current_state_.validator_side.fetched_candidates[fetched_collation]; collation_event.pending_collation.commitments_hash = pending_collation_fetch.candidate_receipt.commitments_hash; const bool is_collator_v2 = (collation_event.collator_protocol_version - == CollationVersion::VStaging); + == network::CollationVersion::VStaging); const bool have_prospective_candidate = - collation_event.pending_collation.prospective_candidate; + collation_event.pending_collation.prospective_candidate.has_value(); const bool async_backing_en = - per_relay_parent->get().prospective_parachains_mode; + per_relay_parent.get().prospective_parachains_mode.has_value(); std::optional maybe_pvd; std::optional> maybe_parent_head_and_hash; @@ -5550,7 +5552,7 @@ namespace kagome::parachain { collation_event.pending_collation, pending_collation_fetch.candidate_receipt, pvd, - maybe_parent_head_and_hash, )); + maybe_parent_head_and_hash)); collations.status = CollationStatus::WaitingOnValidation; validateAsync( @@ -5559,7 +5561,8 @@ namespace kagome::parachain { std::move(pvd), relay_parent); - entry = collation_event; + our_current_state_.validator_side.fetched_candidates.emplace( + fetched_collation, collation_event); return outcome::success(); } @@ -5573,7 +5576,8 @@ namespace kagome::parachain { fragment::FragmentTreeMembership membership; const auto candidate_para = candidatePara(hypothetical_candidate); const auto candidate_relay_parent = relayParent(hypothetical_candidate); - const auto candidate_hash = candidateHash(hypothetical_candidate); + [[maybe_unused]] const auto candidate_hash = + candidateHash(hypothetical_candidate); auto proc_response = [&](std::vector &&depths, const Hash &head, @@ -5824,12 +5828,19 @@ namespace kagome::parachain { return outcome::success(); } + const auto pc = utils::map(prospective_candidate, [](const auto &p) { + return network::ProspectiveCandidate{ + .candidate_hash = p.first, + .parent_head_data_hash = p.second, + }; + }); + PendingCollation pending_collation{ .relay_parent = relay_parent, .para_id = para_id, .peer_id = peer_id, + .prospective_candidate = std::move(pc), .commitments_hash = {}, - .prospective_candidate = std::move(prospective_candidate), }; switch (collations.status) { @@ -5846,16 +5857,14 @@ namespace kagome::parachain { collator_id); } break; case CollationStatus::Waiting: { - fetchCollation( - per_relay_parent->get(), std::move(pending_collation), collator_id); + std::ignore = fetchCollation(std::move(pending_collation), collator_id); } break; case CollationStatus::Seconded: { if (relay_parent_mode) { // Limit is not reached, it's allowed to second another // collation. - fetchCollation(per_relay_parent->get(), - std::move(pending_collation), - collator_id); + std::ignore = + fetchCollation(std::move(pending_collation), collator_id); } else { SL_TRACE(logger_, "A collation has already been seconded. (peer_id={}, para " @@ -5870,20 +5879,18 @@ namespace kagome::parachain { return outcome::success(); } - void ParachainProcessorImpl::fetchCollation( - ParachainProcessorImpl::RelayParentState &per_relay_parent, - PendingCollation &&pc, - const CollatorId &id) { + outcome::result ParachainProcessorImpl::fetchCollation( + const PendingCollation &pc, const CollatorId &id) { auto peer_state = pm_->getPeerState(pc.peer_id); if (!peer_state) { SL_TRACE( logger_, "No peer state. Unknown peer. (peer id={})", pc.peer_id); - return; + return Error::NO_PEER; } const auto candidate_hash = utils::map(pc.prospective_candidate, - [](const auto &pair) { return std::cref(pair.first); }); + [](const auto &v) { return std::cref(v.candidate_hash); }); network::CollationVersion version = network::CollationVersion::VStaging; if (peer_state->get().version) { @@ -5891,15 +5898,14 @@ namespace kagome::parachain { } if (peer_state->get().hasAdvertised(pc.relay_parent, candidate_hash)) { - fetchCollation(per_relay_parent, std::move(pc), id, version); - return; + return fetchCollation(pc, id, version); } SL_WARN(logger_, "Not advertised. (peer id={})", pc.peer_id); + return Error::NOT_ADVERTISED; } - void ParachainProcessorImpl::fetchCollation( - ParachainProcessorImpl::RelayParentState &per_relay_parent, - PendingCollation &&pc, + outcome::result ParachainProcessorImpl::fetchCollation( + const PendingCollation &pc, const CollatorId &id, network::CollationVersion version) { if (our_current_state_.collation_requests_cancel_handles.count(pc) @@ -5908,12 +5914,23 @@ namespace kagome::parachain { "Already requested. (relay parent={}, para id={})", pc.relay_parent, pc.para_id); - return; + return Error::ALREADY_REQUESTED; } + auto per_relay_parent = tryGetStateByRelayParent(pc.relay_parent); + if (!per_relay_parent) { + return Error::OUT_OF_VIEW; + } + + network::CollationEvent collation_event{ + .collator_id = id, + .collator_protocol_version = version, + .pending_collation = pc, + }; + const auto peer_id = pc.peer_id; auto response_callback = - [pending_collation{pc}, wptr{weak_from_this()}]( + [collation_event{std::move(collation_event)}, wptr{weak_from_this()}]( outcome::result &&result) mutable { auto self = wptr.lock(); @@ -5921,8 +5938,10 @@ namespace kagome::parachain { return; } - const RelayHash &relay_parent = pending_collation.relay_parent; - const libp2p::peer::PeerId &peer_id = pending_collation.peer_id; + const RelayHash &relay_parent = + collation_event.pending_collation.relay_parent; + const libp2p::peer::PeerId &peer_id = + collation_event.pending_collation.peer_id; SL_TRACE(self->logger_, "Fetching collation from(peer={}, relay parent={})", @@ -5937,7 +5956,7 @@ namespace kagome::parachain { return; } - self->handle_collation_fetch_response(std::move(pending_collation), + self->handle_collation_fetch_response(std::move(collation_event), std::move(result).value()); }; @@ -5950,9 +5969,10 @@ namespace kagome::parachain { our_current_state_.collation_requests_cancel_handles.insert(std::move(pc)); const auto maybe_candidate_hash = utils::map(pc.prospective_candidate, - [](const auto &pair) { return std::cref(pair.first); }); - per_relay_parent.collations.status = CollationStatus::Fetching; - per_relay_parent.collations.fetching_from.emplace(id, maybe_candidate_hash); + [](const auto &v) { return std::cref(v.candidate_hash); }); + per_relay_parent->get().collations.status = CollationStatus::Fetching; + per_relay_parent->get().collations.fetching_from.emplace( + id, maybe_candidate_hash); if (network::CollationVersion::V1 == version) { network::CollationFetchingRequest fetch_collation_request{ @@ -5977,6 +5997,7 @@ namespace kagome::parachain { } else { UNREACHABLE; } + return outcome::success(); } } // namespace kagome::parachain diff --git a/core/parachain/validator/parachain_processor.hpp b/core/parachain/validator/parachain_processor.hpp index 53f0843660..9e1524f7d6 100644 --- a/core/parachain/validator/parachain_processor.hpp +++ b/core/parachain/validator/parachain_processor.hpp @@ -126,7 +126,10 @@ namespace kagome::parachain { PERSISTED_VALIDATION_DATA_NOT_FOUND, PERSISTED_VALIDATION_DATA_MISMATCH, CANDIDATE_HASH_MISMATCH, - PARENT_HEAD_DATA_MISMATCH + PARENT_HEAD_DATA_MISMATCH, + NO_PEER, + ALREADY_REQUESTED, + NOT_ADVERTISED }; static constexpr uint64_t kBackgroundWorkers = 5; @@ -511,9 +514,7 @@ namespace kagome::parachain { void validateAsync(network::CandidateReceipt &&candidate, network::ParachainBlock &&pov, runtime::PersistedValidationData &&pvd, - const libp2p::peer::PeerId &peer_id, - const primitives::BlockHash &relay_parent, - size_t n_validators); + const primitives::BlockHash &relay_parent); /** * @brief This function is used to make a candidate available for @@ -528,8 +529,7 @@ namespace kagome::parachain { * @param result The result of the validation and seconding process. */ template - void makeAvailable(const libp2p::peer::PeerId &peer_id, - const primitives::BlockHash &candidate_hash, + void makeAvailable(const primitives::BlockHash &candidate_hash, ValidateAndSecondResult &&result); /** @@ -787,20 +787,18 @@ namespace kagome::parachain { /// parent head data hash, the latter doesn't require an additional check. outcome::result fetched_collation_sanity_check( const PendingCollation &advertised, - const CandidateReceipt &fetched, + const network::CandidateReceipt &fetched, const crypto::Hashed> &persisted_validation_data, std::optional> maybe_parent_head_and_hash); - std::optional + outcome::result> fetchPersistedValidationData(const RelayHash &relay_parent, ParachainId para_id); - void onValidationComplete(const libp2p::peer::PeerId &peer_id, - const ValidateAndSecondResult &result); - void onAttestComplete(const libp2p::peer::PeerId &peer_id, - const ValidateAndSecondResult &result); + void onValidationComplete(const ValidateAndSecondResult &result); + void onAttestComplete(const ValidateAndSecondResult &result); void onAttestNoPoVComplete(const network::RelayHash &relay_parent, const CandidateHash &candidate_hash); @@ -810,7 +808,7 @@ namespace kagome::parachain { const runtime::PersistedValidationData &persisted_validation_data, RelayParentState ¶chain_state); void handle_collation_fetch_response( - CollationEvent &&collation_event, + network::CollationEvent &&collation_event, network::CollationFetchingResponse &&response); template std::optional createAndSignStatement( @@ -841,12 +839,11 @@ namespace kagome::parachain { const SignedFullStatementWithPVD &statement); const network::CandidateDescriptor &candidateDescriptorFrom( const network::CollationFetchingResponse &collation) { - return visit_in_place( - collation.response_data, - [](const network::CollationResponse &collation_response) - -> const network::CandidateDescriptor & { - return collation_response.receipt.descriptor; - }); + return visit_in_place(collation.response_data, + [](const auto &collation_response) + -> const network::CandidateDescriptor & { + return collation_response.receipt.descriptor; + }); } std::optional> @@ -916,11 +913,11 @@ namespace kagome::parachain { template void notifyInvalid(const primitives::BlockHash &parent, - const CandidateReceipt &candidate_receipt); + const network::CandidateReceipt &candidate_receipt); /// Notify a collator that its collation got seconded. void notify_collation_seconded(const libp2p::peer::PeerId &peer_id, - CollationVersion version, + network::CollationVersion version, const RelayHash &relay_parent, const SignedFullStatementWithPVD &statement); @@ -931,15 +928,11 @@ namespace kagome::parachain { const network::SignedBitfield &bitfield); void onUpdatePeerView(const libp2p::peer::PeerId &peer_id, const network::View &view); - void fetchCollation( - ParachainProcessorImpl::RelayParentState &per_relay_parent, - PendingCollation &&pc, - const CollatorId &id); - void fetchCollation( - ParachainProcessorImpl::RelayParentState &per_relay_parent, - PendingCollation &&pc, - const CollatorId &id, - network::CollationVersion version); + outcome::result fetchCollation(const PendingCollation &pc, + const CollatorId &id); + outcome::result fetchCollation(const PendingCollation &pc, + const CollatorId &id, + network::CollationVersion version); std::optional> tryGetStateByRelayParent(const primitives::BlockHash &relay_parent); outcome::result< @@ -1082,7 +1075,7 @@ namespace kagome::parachain { bool backed_in_path_only); outcome::result kick_off_seconding( - PendingCollationFetch &&pending_collation_fetch); + network::PendingCollationFetch &&pending_collation_fetch); std::optional importStatementToTable( const RelayHash &relay_parent, @@ -1117,7 +1110,8 @@ namespace kagome::parachain { collation_requests_cancel_handles; struct { - std::unordered_map fetched_candidates; + std::unordered_map + fetched_candidates; } validator_side; struct { diff --git a/core/parachain/validator/prospective_parachains.hpp b/core/parachain/validator/prospective_parachains.hpp index 88928cb5a7..9948afabe7 100644 --- a/core/parachain/validator/prospective_parachains.hpp +++ b/core/parachain/validator/prospective_parachains.hpp @@ -25,7 +25,7 @@ namespace kagome::parachain { - using ParentHeadData_OnlyHash = primitives::Hash; + using ParentHeadData_OnlyHash = Hash; using ParentHeadData_WithData = std::pair; using ParentHeadData = boost::variant; @@ -236,7 +236,8 @@ namespace kagome::parachain { if (!head_data) { const auto &required_parent = fragment_tree.scope.base_constraints.required_parent; - if (hasher_->blake2b_256(required_parent) == parent_head_data_hash) { + if (hasher_->blake2b_256(required_parent) + == parent_head_data_hash.get()) { head_data = required_parent; } } From 8a012e779e63eb98f8493330fd49e85ee485935b Mon Sep 17 00:00:00 2001 From: iceseer Date: Thu, 30 May 2024 10:26:37 +0300 Subject: [PATCH 55/71] ref Signed-off-by: iceseer --- .../impl/parachain_observer_impl.cpp | 35 ++++--------------- .../impl/parachain_observer_impl.hpp | 3 +- .../validator/impl/parachain_processor.cpp | 14 +++----- .../validator/parachain_processor.hpp | 3 +- 4 files changed, 16 insertions(+), 39 deletions(-) diff --git a/core/parachain/validator/impl/parachain_observer_impl.cpp b/core/parachain/validator/impl/parachain_observer_impl.cpp index b90ab7aa72..a035e976bf 100644 --- a/core/parachain/validator/impl/parachain_observer_impl.cpp +++ b/core/parachain/validator/impl/parachain_observer_impl.cpp @@ -53,7 +53,8 @@ namespace kagome::parachain { [&](network::CollatorAdvertisement &&collation_adv) { onAdvertise(peer_id, std::move(collation_adv.relay_parent), - std::nullopt); + std::nullopt, + network::CollationVersion::V1); }, [&](auto &&) { SL_WARN(logger_, "Unexpected V1 collation message from."); @@ -80,7 +81,8 @@ namespace kagome::parachain { std::move(collation_adv.relay_parent), std::make_pair( std::move(collation_adv.candidate_hash), - std::move(collation_adv.parent_head_data_hash))); + std::move(collation_adv.parent_head_data_hash)), + network::CollationVersion::VStaging); }, [&](auto &&) { SL_WARN(logger_, @@ -135,33 +137,10 @@ namespace kagome::parachain { void ParachainObserverImpl::onAdvertise( const libp2p::peer::PeerId &peer_id, primitives::BlockHash relay_parent, - std::optional> &&prospective_candidate) { - const auto peer_state = pm_->getPeerState(peer_id); - if (!peer_state) { - logger_->warn("Received collation advertisement from unknown peer {}", - peer_id); - return; - } - - auto result = pm_->retrieveCollatorData(peer_state->get(), relay_parent); - if (!result) { - logger_->warn( - "Retrieve collator {} data failed: {}", peer_id, result.error()); - return; - } - + std::optional> &&prospective_candidate, + network::CollationVersion collator_protocol_version) { processor_->handleAdvertisement( - network::CollationEvent{ - .collator_id = result.value().first, - .pending_collation = - { - .relay_parent = relay_parent, - .para_id = result.value().second, - .peer_id = peer_id, - .commitments_hash = {}, - }, - }, - std::move(prospective_candidate)); + relay_parent, peer_id, std::move(prospective_candidate)); } void ParachainObserverImpl::onDeclare(const libp2p::peer::PeerId &peer_id, diff --git a/core/parachain/validator/impl/parachain_observer_impl.hpp b/core/parachain/validator/impl/parachain_observer_impl.hpp index 294eaab418..23fc89b1ed 100644 --- a/core/parachain/validator/impl/parachain_observer_impl.hpp +++ b/core/parachain/validator/impl/parachain_observer_impl.hpp @@ -65,7 +65,8 @@ namespace kagome::parachain { void onAdvertise( const libp2p::peer::PeerId &peer_id, primitives::BlockHash relay_parent, - std::optional> &&prospective_candidate); + std::optional> &&prospective_candidate, + network::CollationVersion collator_protocol_version); void onDeclare(const libp2p::peer::PeerId &peer_id, network::CollatorPublicKey pubkey, diff --git a/core/parachain/validator/impl/parachain_processor.cpp b/core/parachain/validator/impl/parachain_processor.cpp index 4115e10e33..bb19b7808d 100644 --- a/core/parachain/validator/impl/parachain_processor.cpp +++ b/core/parachain/validator/impl/parachain_processor.cpp @@ -5669,19 +5669,15 @@ namespace kagome::parachain { } void ParachainProcessorImpl::handleAdvertisement( - network::CollationEvent &&pending_collation, + const RelayHash &relay_parent, + const libp2p::peer::PeerId &peer_id, std::optional> &&prospective_candidate) { REINVOKE(*main_pool_handler_, handleAdvertisement, - std::move(pending_collation), + relay_parent, + peer_id, std::move(prospective_candidate)); - const RelayHash &relay_parent = - pending_collation.pending_collation.relay_parent; - const libp2p::peer::PeerId &peer_id = - pending_collation.pending_collation.peer_id; - const ParachainId ¶_id = pending_collation.pending_collation.para_id; - auto opt_per_relay_parent = tryGetStateByRelayParent(relay_parent); if (!opt_per_relay_parent) { SL_TRACE( @@ -5740,7 +5736,7 @@ namespace kagome::parachain { // Get the collator id and parachain id from the result of the advertisement // insertion - const auto &[collator_id, parachain_id] = insert_res.value(); + const auto &[collator_id, para_id] = insert_res.value(); if (!per_relay_parent.collations.hasSecondedSpace(relay_parent_mode)) { SL_TRACE(logger_, "Seconded limit reached."); return; diff --git a/core/parachain/validator/parachain_processor.hpp b/core/parachain/validator/parachain_processor.hpp index 9e1524f7d6..e31bd931e2 100644 --- a/core/parachain/validator/parachain_processor.hpp +++ b/core/parachain/validator/parachain_processor.hpp @@ -191,7 +191,8 @@ namespace kagome::parachain { * prospective candidate and the hash of the parent block. */ void handleAdvertisement( - network::CollationEvent &&pending_collation, + const RelayHash &relay_parent, + const libp2p::peer::PeerId &peer_id, std::optional> &&prospective_candidate); /** From 4ff3b29996ef9084912f48ea7e594d0e5aee1fbe Mon Sep 17 00:00:00 2001 From: iceseer Date: Thu, 30 May 2024 13:12:38 +0300 Subject: [PATCH 56/71] smoke complete Signed-off-by: iceseer --- .../validator/impl/parachain_processor.cpp | 106 ++++++++++++------ .../validator/parachain_processor.hpp | 3 +- 2 files changed, 75 insertions(+), 34 deletions(-) diff --git a/core/parachain/validator/impl/parachain_processor.cpp b/core/parachain/validator/impl/parachain_processor.cpp index bb19b7808d..5783eaf65c 100644 --- a/core/parachain/validator/impl/parachain_processor.cpp +++ b/core/parachain/validator/impl/parachain_processor.cpp @@ -100,6 +100,8 @@ OUTCOME_CPP_DEFINE_CATEGORY(kagome::parachain, return "Already requested"; case E::NOT_ADVERTISED: return "Not advertised"; + case E::WRONG_PARA: + return "Wrong para id"; } return "Unknown parachain processor error"; } @@ -1361,55 +1363,93 @@ namespace kagome::parachain { std::move(collation_event), std::move(response)); + const auto &pending_collation = collation_event.pending_collation; SL_TRACE(logger_, "Processing collation from {}, relay parent: {}, para id: {}", - collation_event.pending_collation.peer_id, - collation_event.pending_collation.relay_parent, - collation_event.pending_collation.para_id); + pending_collation.peer_id, + pending_collation.relay_parent, + pending_collation.para_id); our_current_state_.collation_requests_cancel_handles.erase( - collation_event.pending_collation); + pending_collation); - auto collation_response = - if_type(response.response_data); - if (!collation_response) { - SL_WARN(logger_, - "Not a CollationResponse message from {}.", - collation_event.pending_collation.peer_id); - return; - } + outcome::result p = visit_in_place( + std::move(response.response_data), + [&](network::CollationResponse &&value) + -> outcome::result { + if (value.receipt.descriptor.para_id != pending_collation.para_id) { + SL_TRACE(logger_, + "Got wrong para ID for requested collation. " + "(expected_para_id={}, got_para_id={}, peer_id={})", + pending_collation.para_id, + value.receipt.descriptor.para_id, + pending_collation.peer_id); + return Error::WRONG_PARA; + } - SL_WARN(logger_, - "Received collation (v3) (para_id={}, relay_parent={}, " - "candidate_hash={})", - collation_event.pending_collation.para_id, - collation_event.pending_collation.relay_parent, - collation_response->get().receipt.hash(*hasher_)); + SL_TRACE(logger_, + "Received collation (para_id={}, relay_parent={}, " + "candidate_hash={})", + pending_collation.para_id, + pending_collation.relay_parent, + value.receipt.hash(*hasher_)); + + return network::PendingCollationFetch{ + .collation_event = std::move(collation_event), + .candidate_receipt = std::move(value.receipt), + .pov = std::move(value.pov), + .maybe_parent_head_data = std::nullopt, + }; + }, + [&](network::CollationWithParentHeadData &&value) + -> outcome::result { + if (value.receipt.descriptor.para_id != pending_collation.para_id) { + SL_TRACE(logger_, + "Got wrong para ID for requested collation (v3). " + "(expected_para_id={}, got_para_id={}, peer_id={})", + pending_collation.para_id, + value.receipt.descriptor.para_id, + pending_collation.peer_id); + return Error::WRONG_PARA; + } - network::PendingCollationFetch p{ - .collation_event = std::move(collation_event), - .candidate_receipt = std::move(collation_response->get().receipt), - .pov = std::move(collation_response->get().pov), - .maybe_parent_head_data = - std::move(collation_response->get().parent_head_data), - }; + SL_TRACE(logger_, + "Received collation (v3) (para_id={}, relay_parent={}, " + "candidate_hash={})", + pending_collation.para_id, + pending_collation.relay_parent, + value.receipt.hash(*hasher_)); + + return network::PendingCollationFetch{ + .collation_event = std::move(collation_event), + .candidate_receipt = std::move(value.receipt), + .pov = std::move(value.pov), + .maybe_parent_head_data = std::move(value.parent_head_data), + }; + }); + + if (p.has_error()) { + SL_TRACE(logger_, "Collation process failed (error={})", p.error()); + return; + } - auto collator_id = p.collation_event.collator_id; - auto pending_collation = p.collation_event.pending_collation; + CollatorId collator_id = p.value().collation_event.collator_id; + PendingCollation pending_collation_copy = + p.value().collation_event.pending_collation; - if (auto res = kick_off_seconding(std::move(p)); res.has_error()) { + if (auto res = kick_off_seconding(std::move(p.value())); res.has_error()) { SL_WARN(logger_, "Seconding aborted due to an error. (relay_parent={}, " "para_id={}, peer_id={}, error={})", - pending_collation.relay_parent, - pending_collation.para_id, - pending_collation.peer_id, + pending_collation_copy.relay_parent, + pending_collation_copy.para_id, + pending_collation_copy.peer_id, res.error()); const auto maybe_candidate_hash = - utils::map(pending_collation.prospective_candidate, + utils::map(pending_collation_copy.prospective_candidate, [](const auto &v) { return v.candidate_hash; }); - dequeue_next_collation_and_fetch(pending_collation.relay_parent, + dequeue_next_collation_and_fetch(pending_collation_copy.relay_parent, {collator_id, maybe_candidate_hash}); } } diff --git a/core/parachain/validator/parachain_processor.hpp b/core/parachain/validator/parachain_processor.hpp index e31bd931e2..e643984c0b 100644 --- a/core/parachain/validator/parachain_processor.hpp +++ b/core/parachain/validator/parachain_processor.hpp @@ -129,7 +129,8 @@ namespace kagome::parachain { PARENT_HEAD_DATA_MISMATCH, NO_PEER, ALREADY_REQUESTED, - NOT_ADVERTISED + NOT_ADVERTISED, + WRONG_PARA }; static constexpr uint64_t kBackgroundWorkers = 5; From 3c03ff015bbbd00cf4168a553a00521b7f16c583 Mon Sep 17 00:00:00 2001 From: iceseer Date: Thu, 30 May 2024 15:08:11 +0300 Subject: [PATCH 57/71] DO NOT COMMIT Signed-off-by: iceseer --- .../approval/approval_distribution.cpp | 116 ++---------------- 1 file changed, 8 insertions(+), 108 deletions(-) diff --git a/core/parachain/approval/approval_distribution.cpp b/core/parachain/approval/approval_distribution.cpp index 9bad3c92ea..f83489df8c 100644 --- a/core/parachain/approval/approval_distribution.cpp +++ b/core/parachain/approval/approval_distribution.cpp @@ -1240,115 +1240,15 @@ namespace kagome::parachain { ValidatorIndex validator_index, Hash block_hash, GroupIndex backing_group) { - auto on_recover_complete = [wself{weak_from_this()}, - hashed_candidate{hashed_candidate}, - block_hash, - session_index, - validator_index, - relay_block_hash]( - std::optional< - outcome::result> - &&opt_result) mutable { - auto self = wself.lock(); - if (!self) { - return; - } - - const auto &candidate_receipt = hashed_candidate.get(); - if (!opt_result) { // Unavailable - self->logger_->warn( - "No available parachain data.(session index={}, candidate " - "hash={}, relay block hash={})", - session_index, - hashed_candidate.getHash(), - relay_block_hash); - return; - } - - if (opt_result->has_error()) { - self->logger_->warn( - "Parachain data recovery failed.(error={}, session index={}, " - "candidate hash={}, relay block hash={})", - opt_result->error(), - session_index, - hashed_candidate.getHash(), - relay_block_hash); - self->dispute_coordinator_.get()->issueLocalStatement( - session_index, - hashed_candidate.getHash(), - hashed_candidate.get(), - false); - return; - } - auto &available_data = opt_result->value(); - auto result = self->parachain_host_->validation_code_by_hash( - block_hash, candidate_receipt.descriptor.validation_code_hash); - if (result.has_error() || !result.value()) { - self->logger_->warn( - "Approval state is failed. Block hash {}, session index {}, " - "validator index {}, relay parent {}", - block_hash, - session_index, - validator_index, - candidate_receipt.descriptor.relay_parent); - return; /// ApprovalState::failed + approvals_cache_.exclusiveAccess([&](auto &approvals_cache) { + if (auto it = approvals_cache.find(hashed_candidate.getHash()); + it != approvals_cache.end()) { + ApprovalCache &ac = it->second; + ac.approval_result = ApprovalOutcome::Approved; } - - self->logger_->info( - "Make exhaustive validation. Candidate hash {}, validator index " - "{}, block hash {}", - hashed_candidate.getHash(), - validator_index, - block_hash); - - runtime::ValidationCode &validation_code = *result.value(); - - auto cb = [weak_self{wself}, - hashed_candidate, - session_index, - validator_index, - relay_block_hash](outcome::result outcome) { - auto self = weak_self.lock(); - if (not self) { - return; - } - const auto &candidate_receipt = hashed_candidate.get(); - self->approvals_cache_.exclusiveAccess([&](auto &approvals_cache) { - if (auto it = approvals_cache.find(hashed_candidate.getHash()); - it != approvals_cache.end()) { - ApprovalCache &ac = it->second; - ac.approval_result = outcome.has_error() - ? ApprovalOutcome::Failed - : ApprovalOutcome::Approved; - } - }); - if (outcome.has_error()) { - self->logger_->warn( - "Approval validation failed.(parachain id={}, relay parent={}, error={})", - candidate_receipt.descriptor.para_id, - candidate_receipt.descriptor.relay_parent, - outcome.error()); - self->dispute_coordinator_.get()->issueLocalStatement( - session_index, - hashed_candidate.getHash(), - candidate_receipt, - false); - } else { - self->issue_approval( - hashed_candidate.getHash(), validator_index, relay_block_hash); - } - }; - self->pvf_->pvfValidate(available_data.validation_data, - available_data.pov, - candidate_receipt, - validation_code, - std::move(cb)); - }; - - recovery_->recover(hashed_candidate, - session_index, - backing_group, - std::move(on_recover_complete)); + }); + issue_approval( + hashed_candidate.getHash(), validator_index, relay_block_hash); } #define GET_OPT_VALUE_OR_EXIT(name, err, ...) \ From 368bb980fa9bad55cda0663f9b66bcfa2975493b Mon Sep 17 00:00:00 2001 From: iceseer Date: Wed, 5 Jun 2024 10:08:18 +0300 Subject: [PATCH 58/71] Revert "DO NOT COMMIT" This reverts commit 3c03ff015bbbd00cf4168a553a00521b7f16c583. --- .../approval/approval_distribution.cpp | 116 ++++++++++++++++-- 1 file changed, 108 insertions(+), 8 deletions(-) diff --git a/core/parachain/approval/approval_distribution.cpp b/core/parachain/approval/approval_distribution.cpp index f83489df8c..9bad3c92ea 100644 --- a/core/parachain/approval/approval_distribution.cpp +++ b/core/parachain/approval/approval_distribution.cpp @@ -1240,15 +1240,115 @@ namespace kagome::parachain { ValidatorIndex validator_index, Hash block_hash, GroupIndex backing_group) { - approvals_cache_.exclusiveAccess([&](auto &approvals_cache) { - if (auto it = approvals_cache.find(hashed_candidate.getHash()); - it != approvals_cache.end()) { - ApprovalCache &ac = it->second; - ac.approval_result = ApprovalOutcome::Approved; + auto on_recover_complete = [wself{weak_from_this()}, + hashed_candidate{hashed_candidate}, + block_hash, + session_index, + validator_index, + relay_block_hash]( + std::optional< + outcome::result> + &&opt_result) mutable { + auto self = wself.lock(); + if (!self) { + return; } - }); - issue_approval( - hashed_candidate.getHash(), validator_index, relay_block_hash); + + const auto &candidate_receipt = hashed_candidate.get(); + if (!opt_result) { // Unavailable + self->logger_->warn( + "No available parachain data.(session index={}, candidate " + "hash={}, relay block hash={})", + session_index, + hashed_candidate.getHash(), + relay_block_hash); + return; + } + + if (opt_result->has_error()) { + self->logger_->warn( + "Parachain data recovery failed.(error={}, session index={}, " + "candidate hash={}, relay block hash={})", + opt_result->error(), + session_index, + hashed_candidate.getHash(), + relay_block_hash); + self->dispute_coordinator_.get()->issueLocalStatement( + session_index, + hashed_candidate.getHash(), + hashed_candidate.get(), + false); + return; + } + auto &available_data = opt_result->value(); + auto result = self->parachain_host_->validation_code_by_hash( + block_hash, candidate_receipt.descriptor.validation_code_hash); + if (result.has_error() || !result.value()) { + self->logger_->warn( + "Approval state is failed. Block hash {}, session index {}, " + "validator index {}, relay parent {}", + block_hash, + session_index, + validator_index, + candidate_receipt.descriptor.relay_parent); + return; /// ApprovalState::failed + } + + self->logger_->info( + "Make exhaustive validation. Candidate hash {}, validator index " + "{}, block hash {}", + hashed_candidate.getHash(), + validator_index, + block_hash); + + runtime::ValidationCode &validation_code = *result.value(); + + auto cb = [weak_self{wself}, + hashed_candidate, + session_index, + validator_index, + relay_block_hash](outcome::result outcome) { + auto self = weak_self.lock(); + if (not self) { + return; + } + const auto &candidate_receipt = hashed_candidate.get(); + self->approvals_cache_.exclusiveAccess([&](auto &approvals_cache) { + if (auto it = approvals_cache.find(hashed_candidate.getHash()); + it != approvals_cache.end()) { + ApprovalCache &ac = it->second; + ac.approval_result = outcome.has_error() + ? ApprovalOutcome::Failed + : ApprovalOutcome::Approved; + } + }); + if (outcome.has_error()) { + self->logger_->warn( + "Approval validation failed.(parachain id={}, relay parent={}, error={})", + candidate_receipt.descriptor.para_id, + candidate_receipt.descriptor.relay_parent, + outcome.error()); + self->dispute_coordinator_.get()->issueLocalStatement( + session_index, + hashed_candidate.getHash(), + candidate_receipt, + false); + } else { + self->issue_approval( + hashed_candidate.getHash(), validator_index, relay_block_hash); + } + }; + self->pvf_->pvfValidate(available_data.validation_data, + available_data.pov, + candidate_receipt, + validation_code, + std::move(cb)); + }; + + recovery_->recover(hashed_candidate, + session_index, + backing_group, + std::move(on_recover_complete)); } #define GET_OPT_VALUE_OR_EXIT(name, err, ...) \ From 026c42da44dd0bbc5073320c4b28de927eb35b50 Mon Sep 17 00:00:00 2001 From: iceseer Date: Wed, 5 Jun 2024 10:09:23 +0300 Subject: [PATCH 59/71] fixup reverted eq Signed-off-by: iceseer --- .../validator/impl/parachain_processor.cpp | 51 +++++++++---------- 1 file changed, 24 insertions(+), 27 deletions(-) diff --git a/core/parachain/validator/impl/parachain_processor.cpp b/core/parachain/validator/impl/parachain_processor.cpp index 5783eaf65c..b781a50f8c 100644 --- a/core/parachain/validator/impl/parachain_processor.cpp +++ b/core/parachain/validator/impl/parachain_processor.cpp @@ -37,6 +37,21 @@ #include "utils/pool_handler.hpp" #include "utils/profiler.hpp" +#ifndef TRY_GET_OR_RET +#define TRY_GET_OR_RET(name,op) \ + auto name = (op); \ + if (!op) { \ + return; \ + } else {} +#endif //TRY_GET_OR_RET + +#ifndef CHECK_OR_RET +#define CHECK_OR_RET(op) \ + if(!(op)) { \ + return; \ + } +#endif //CHECK_OR_RET + OUTCOME_CPP_DEFINE_CATEGORY(kagome::parachain, ParachainProcessorImpl::Error, e) { @@ -204,18 +219,9 @@ namespace kagome::parachain { const primitives::BlockHash &relay_parent, const network::SignedBitfield &bitfield) { REINVOKE(*main_pool_handler_, OnBroadcastBitfields, relay_parent, bitfield); - SL_TRACE(logger_, "Distribute bitfield on {}", relay_parent); - auto relay_parent_state = tryGetStateByRelayParent(relay_parent); - if (!relay_parent_state) { - SL_TRACE(logger_, - "After `OnBroadcastBitfields` no parachain state on " - "relay_parent. (relay " - "parent={})", - relay_parent); - return; - } + TRY_GET_OR_RET(relay_parent_state, tryGetStateByRelayParent(relay_parent)); send_to_validators_group( relay_parent, {network::VersionedValidatorProtocolMessage{ @@ -247,6 +253,7 @@ namespace kagome::parachain { babe_status_observer_ = std::make_shared( babe_status_observable_, false); + babe_status_observer_->setCallback( [wself{weak_from_this()}, was_synchronized = false]( auto /*set_id*/, @@ -264,14 +271,7 @@ namespace kagome::parachain { if (was_synchronized) { if (!synchronized) { synchronized = true; - auto my_view = self->peer_view_->getMyView(); - if (!my_view) { - SL_WARN(self->logger_, - "Broadcast my view failed, " - "because my view still not exists."); - return; - } - + TRY_GET_OR_RET(my_view, self->peer_view_->getMyView()); SL_TRACE(self->logger_, "Broadcast my view because synchronized."); self->broadcastView(my_view->get().view); @@ -279,6 +279,7 @@ namespace kagome::parachain { } } }); + babe_status_observer_->subscribe( babe_status_observer_->generateSubscriptionSetId(), primitives::events::SyncStateEventType::kSyncState); @@ -326,11 +327,7 @@ namespace kagome::parachain { void ParachainProcessorImpl::onUpdatePeerView( const libp2p::peer::PeerId &peer, const network::View &new_view) { REINVOKE(*main_pool_handler_, onUpdatePeerView, peer, new_view); - - auto peer_state = pm_->getPeerState(peer); - if (!peer_state) { - return; - } + TRY_GET_OR_RET(peer_state, pm_->getPeerState(peer)); auto fresh_implicit = peer_state->get().update_view( new_view, *our_current_state_.implicit_view); @@ -345,10 +342,8 @@ namespace kagome::parachain { network::CollationVersion version, ValidatorIndex peer_validator_id, ParachainProcessorImpl::RelayParentState &relay_parent_state) { - if (!relay_parent_state.local_validator - || relay_parent_state.local_validator->active) { - return; - } + CHECK_OR_RET(relay_parent_state.local_validator); + CHECK_OR_RET(relay_parent_state.local_validator->active); const auto pending_statements = relay_parent_state.local_validator->active->cluster_tracker @@ -5296,6 +5291,7 @@ namespace kagome::parachain { .validation_data = std::move(data), }; + auto measure2 = std::make_shared("===> EC validation", self->logger_); auto chunks_res = self->validateErasureCoding(available_data, n_validators); if (chunks_res.has_error()) { @@ -5304,6 +5300,7 @@ namespace kagome::parachain { chunks_res.error()); return; } + measure2.reset(); auto &chunks = chunks_res.value(); self->notifyAvailableData(std::move(chunks), From 041ed033db889153dc9883a001fb4bcce268bc7a Mon Sep 17 00:00:00 2001 From: iceseer Date: Wed, 5 Jun 2024 11:18:47 +0300 Subject: [PATCH 60/71] ref Signed-off-by: iceseer --- cmake/Hunter/config.cmake | 14 ++-- .../validator/impl/parachain_processor.cpp | 67 ++----------------- 2 files changed, 14 insertions(+), 67 deletions(-) diff --git a/cmake/Hunter/config.cmake b/cmake/Hunter/config.cmake index d2e3160dd4..cf8ddcfbe6 100644 --- a/cmake/Hunter/config.cmake +++ b/cmake/Hunter/config.cmake @@ -40,13 +40,13 @@ hunter_config( if ("${WASM_COMPILER}" STREQUAL "WasmEdge") hunter_config( - WasmEdge - URL https://github.com/qdrvm/WasmEdge/archive/refs/tags/0.13.5-qdrvm1.zip - SHA1 3637f5df6892a762606393940539c0dcb6e9c022 - CMAKE_ARGS - WASMEDGE_BUILD_STATIC_LIB=ON - WASMEDGE_BUILD_SHARED_LIB=OFF - KEEP_PACKAGE_SOURCES + WasmEdge + URL https://github.com/qdrvm/WasmEdge/archive/refs/heads/feature/expose-jit.zip + SHA1 277cef01a9b2171538b6d3f7a18358007b41ac95 + CMAKE_ARGS + WASMEDGE_BUILD_STATIC_LIB=OFF + WASMEDGE_BUILD_SHARED_LIB=ON + KEEP_PACKAGE_SOURCES ) endif () diff --git a/core/parachain/validator/impl/parachain_processor.cpp b/core/parachain/validator/impl/parachain_processor.cpp index b781a50f8c..edab87a54a 100644 --- a/core/parachain/validator/impl/parachain_processor.cpp +++ b/core/parachain/validator/impl/parachain_processor.cpp @@ -371,13 +371,7 @@ namespace kagome::parachain { } } - if (messages.empty()) { - return; - } - auto se = pm_->getStreamEngine(); - BOOST_ASSERT(se); - for (auto &[peers, msg] : messages) { if (auto m = if_type(msg)) { auto message = std::make_shared< @@ -399,9 +393,7 @@ namespace kagome::parachain { ValidatorIndex peer_validator_id, const Groups &groups, ParachainProcessorImpl::RelayParentState &relay_parent_state) { - if (!relay_parent_state.local_validator) { - return; - } + CHECK_OR_RET(relay_parent_state.local_validator); auto pending_manifests = relay_parent_state.local_validator->grid_tracker.pending_manifests_for( @@ -417,10 +409,7 @@ namespace kagome::parachain { } const auto group_index = confirmed_candidate->get().group_index(); - auto group = groups.get(group_index); - if (!group) { - return; - } + TRY_GET_OR_RET(group, groups.get(group_index)); const auto group_size = group->size(); auto local_knowledge = @@ -504,13 +493,7 @@ namespace kagome::parachain { } } - if (messages.empty()) { - return; - } - auto se = pm_->getStreamEngine(); - BOOST_ASSERT(se); - for (auto &[peers, msg] : messages) { if (auto m = if_type(msg)) { auto message = std::make_shared< @@ -565,15 +548,8 @@ namespace kagome::parachain { main_pool_handler_ ->isInCurrentThread()); // because of pm_->getPeerState(...) - auto peer_state = pm_->getPeerState(peer_id); - if (!peer_state) { - return; - } - - auto parachain_state = tryGetStateByRelayParent(relay_parent); - if (!parachain_state) { - return; - } + TRY_GET_OR_RET(peer_state, pm_->getPeerState(peer_id)); + TRY_GET_OR_RET(parachain_state, tryGetStateByRelayParent(relay_parent)); network::CollationVersion version = network::CollationVersion::VStaging; if (peer_state->get().version) { @@ -601,12 +577,9 @@ namespace kagome::parachain { void ParachainProcessorImpl::onViewUpdated(const network::ExView &event) { REINVOKE(*main_pool_handler_, onViewUpdated, event); + CHECK_OR_RET(canProcessParachains().has_value()); const auto &relay_parent = event.new_head.hash(); - if (auto r = canProcessParachains(); r.has_error()) { - return; - } - if (const auto r = prospective_parachains_->onActiveLeavesUpdate(network::ExViewRef{ .new_head = {event.new_head}, @@ -846,12 +819,7 @@ namespace kagome::parachain { void ParachainProcessorImpl::broadcastViewToGroup( const primitives::BlockHash &relay_parent, const network::View &view) { - auto opt_parachain_state = tryGetStateByRelayParent(relay_parent); - if (!opt_parachain_state) { - SL_ERROR( - logger_, "Relay state should exist. (relay_parent)", relay_parent); - return; - } + TRY_GET_OR_RET(opt_parachain_state, tryGetStateByRelayParent(relay_parent)); std::deque group; if (auto r = runtime_info_->get_session_info(relay_parent)) { @@ -874,8 +842,6 @@ namespace kagome::parachain { const std::shared_ptr &protocol) { auto se = pm_->getStreamEngine(); - BOOST_ASSERT(se); - auto message = std::make_shared< network::WireMessage>( msg); @@ -1094,29 +1060,10 @@ namespace kagome::parachain { grid::shuffle(session_info->validator_groups, randomness), validator_index); - SL_TRACE(logger_, - "======================== GV INIT ========================"); - - for (size_t k = 0; k < grid_view.size(); ++k) { - const auto &v = grid_view[k]; - SL_TRACE(logger_, "\tGroup {}", k); - for (const auto vi : v.sending) { - SL_TRACE(logger_, "\t\tS: {}", vi); - } - for (const auto vi : v.receiving) { - SL_TRACE(logger_, "\t\tR: {}", vi); - } - } - - SL_TRACE( - logger_, - "================================================================="); - - Groups g{session_info->validator_groups, minimum_backing_votes}; return RefCache::RefObj( session_index, *session_info, - std::move(g), + Groups{session_info->validator_groups, minimum_backing_votes}, std::move(grid_view), validator_index, pm_, From 47279628ca28d332259941fd5f83427e4576daba Mon Sep 17 00:00:00 2001 From: iceseer Date: Wed, 5 Jun 2024 20:25:54 +0300 Subject: [PATCH 61/71] ref Signed-off-by: iceseer --- .../validator/impl/parachain_processor.cpp | 686 ++++++------------ .../validator/parachain_processor.hpp | 13 - 2 files changed, 210 insertions(+), 489 deletions(-) diff --git a/core/parachain/validator/impl/parachain_processor.cpp b/core/parachain/validator/impl/parachain_processor.cpp index edab87a54a..ac0a2eb6e4 100644 --- a/core/parachain/validator/impl/parachain_processor.cpp +++ b/core/parachain/validator/impl/parachain_processor.cpp @@ -38,19 +38,20 @@ #include "utils/profiler.hpp" #ifndef TRY_GET_OR_RET -#define TRY_GET_OR_RET(name,op) \ - auto name = (op); \ - if (!op) { \ - return; \ - } else {} -#endif //TRY_GET_OR_RET +#define TRY_GET_OR_RET(name, op) \ + auto name = (op); \ + if (!name) { \ + return; \ + } else { \ + } +#endif // TRY_GET_OR_RET #ifndef CHECK_OR_RET #define CHECK_OR_RET(op) \ - if(!(op)) { \ - return; \ + if (!(op)) { \ + return; \ } -#endif //CHECK_OR_RET +#endif // CHECK_OR_RET OUTCOME_CPP_DEFINE_CATEGORY(kagome::parachain, ParachainProcessorImpl::Error, @@ -221,7 +222,6 @@ namespace kagome::parachain { REINVOKE(*main_pool_handler_, OnBroadcastBitfields, relay_parent, bitfield); SL_TRACE(logger_, "Distribute bitfield on {}", relay_parent); - TRY_GET_OR_RET(relay_parent_state, tryGetStateByRelayParent(relay_parent)); send_to_validators_group( relay_parent, {network::VersionedValidatorProtocolMessage{ @@ -244,9 +244,8 @@ namespace kagome::parachain { bitfield_signer_->setBroadcastCallback( [wptr_self{weak_from_this()}](const primitives::BlockHash &relay_parent, const network::SignedBitfield &bitfield) { - if (auto self = wptr_self.lock()) { - self->OnBroadcastBitfields(relay_parent, bitfield); - } + TRY_GET_OR_RET(self, wptr_self.lock()); + self->OnBroadcastBitfields(relay_parent, bitfield); }); // Subscribe to the BABE status observable @@ -260,22 +259,22 @@ namespace kagome::parachain { bool &synchronized, auto /*event_type*/, const primitives::events::SyncStateEventParams &event) mutable { - if (auto self = wself.lock()) { - if (event == consensus::SyncState::SYNCHRONIZED) { - if (not was_synchronized) { - self->bitfield_signer_->start(); - self->pvf_precheck_->start(); - was_synchronized = true; - } + TRY_GET_OR_RET(self, wself.lock()); + + if (event == consensus::SyncState::SYNCHRONIZED) { + if (not was_synchronized) { + self->bitfield_signer_->start(); + self->pvf_precheck_->start(); + was_synchronized = true; } - if (was_synchronized) { - if (!synchronized) { - synchronized = true; - TRY_GET_OR_RET(my_view, self->peer_view_->getMyView()); - SL_TRACE(self->logger_, - "Broadcast my view because synchronized."); - self->broadcastView(my_view->get().view); - } + } + if (was_synchronized) { + if (!synchronized) { + synchronized = true; + TRY_GET_OR_RET(my_view, self->peer_view_->getMyView()); + SL_TRACE(self->logger_, + "Broadcast my view because synchronized."); + self->broadcastView(my_view->get().view); } } }); @@ -288,9 +287,8 @@ namespace kagome::parachain { chain_sub_.onDeactivate( [wptr{weak_from_this()}]( const primitives::events::RemoveAfterFinalizationParams &event) { - if (auto self = wptr.lock()) { - self->onDeactivateBlocks(event); - } + TRY_GET_OR_RET(self, wptr.lock()); + self->onDeactivateBlocks(event); }); // Set the callback for the my view observable @@ -304,9 +302,8 @@ namespace kagome::parachain { *my_view_sub_, network::PeerView::EventType::kViewUpdated, [wptr{weak_from_this()}](const network::ExView &event) { - if (auto self = wptr.lock()) { - self->onViewUpdated(event); - } + TRY_GET_OR_RET(self, wptr.lock()); + self->onViewUpdated(event); }); remote_view_sub_ = std::make_shared( @@ -316,9 +313,8 @@ namespace kagome::parachain { network::PeerView::EventType::kViewUpdated, [wptr{weak_from_this()}](const libp2p::peer::PeerId &peer_id, const network::View &view) { - if (auto self = wptr.lock()) { - self->onUpdatePeerView(peer_id, view); - } + TRY_GET_OR_RET(self, wptr.lock()); + self->onUpdatePeerView(peer_id, view); }); return true; @@ -819,8 +815,6 @@ namespace kagome::parachain { void ParachainProcessorImpl::broadcastViewToGroup( const primitives::BlockHash &relay_parent, const network::View &view) { - TRY_GET_OR_RET(opt_parachain_state, tryGetStateByRelayParent(relay_parent)); - std::deque group; if (auto r = runtime_info_->get_session_info(relay_parent)) { auto &[session, info] = r.value(); @@ -894,15 +888,13 @@ namespace kagome::parachain { peer->id, network::CollationVersion::VStaging, [wptr{weak_from_this()}, peer_id{peer->id}](auto &&stream) { - if (auto self = wptr.lock()) { - auto ps = self->pm_->getPeerState(peer_id); - BOOST_ASSERT(ps); - - ps->get().inc_use_count(); - self->sendMyView(peer_id, - stream, - self->router_->getValidationProtocolVStaging()); - } + TRY_GET_OR_RET(self, wptr.lock()); + auto ps = self->pm_->getPeerState(peer_id); + + ps->get().inc_use_count(); + self->sendMyView(peer_id, + stream, + self->router_->getValidationProtocolVStaging()); }); } } @@ -1002,7 +994,8 @@ namespace kagome::parachain { */ bool is_parachain_validator = false; ::libp2p::common::FinalAction metric_updater( - [self{this}, &is_parachain_validator] { + [wptr{weak_from_this()}, &is_parachain_validator] { + TRY_GET_OR_RET(self, wptr.lock()); self->metric_is_parachain_validator_->set(is_parachain_validator); }); OUTCOME_TRY(validators, parachain_host_->validators(relay_parent)); @@ -1370,11 +1363,7 @@ namespace kagome::parachain { }; }); - if (p.has_error()) { - SL_TRACE(logger_, "Collation process failed (error={})", p.error()); - return; - } - + CHECK_OR_RET(p.has_value()); CollatorId collator_id = p.value().collation_event.collator_id; PendingCollation pending_collation_copy = p.value().collation_event.pending_collation; @@ -1427,10 +1416,7 @@ namespace kagome::parachain { void ParachainProcessorImpl::dequeue_next_collation_and_fetch( const RelayHash &relay_parent, std::pair> previous_fetch) { - auto per_relay_state = tryGetStateByRelayParent(relay_parent); - if (!per_relay_state) { - return; - } + TRY_GET_OR_RET(per_relay_state, tryGetStateByRelayParent(relay_parent)); while (auto collation = per_relay_state->get().collations.get_next_collation_to_fetch( @@ -1503,10 +1489,7 @@ namespace kagome::parachain { SL_TRACE(logger_, "Incoming `BitfieldDistributionMessage`. (relay_parent={})", bd->relay_parent); - auto parachain_state = tryGetStateByRelayParent(bd->relay_parent); - if (!parachain_state) { - return; - } + TRY_GET_OR_RET(parachain_state, tryGetStateByRelayParent(bd->relay_parent)); const auto &session_info = parachain_state->get().per_session_state->value().session_info; @@ -1682,19 +1665,7 @@ namespace kagome::parachain { const std::deque &messages) { BOOST_ASSERT(main_pool_handler_->isInCurrentThread()); - auto relay_parent_state = tryGetStateByRelayParent(relay_parent); - if (!relay_parent_state) { - SL_TRACE(logger_, - "After `send_to_validators_group` no parachain state on " - "relay_parent. (relay " - "parent={})", - relay_parent); - return; - } - auto se = pm_->getStreamEngine(); - BOOST_ASSERT(se); - std::unordered_set group_set; if (auto r = runtime_info_->get_session_info(relay_parent)) { auto &[session, info] = r.value(); @@ -1918,20 +1889,13 @@ namespace kagome::parachain { peer_id, candidate_hash); - auto c = candidates_.get_confirmed(candidate_hash); - if (!c) { - return; - } + TRY_GET_OR_RET(c, candidates_.get_confirmed(candidate_hash)); const RelayHash &relay_parent = c->get().relay_parent(); const Hash &parent_head_data_hash = c->get().parent_head_data_hash(); GroupIndex group_index = c->get().group_index(); ParachainId para_id = c->get().para_id(); - auto opt_parachain_state = tryGetStateByRelayParent(relay_parent); - if (!opt_parachain_state) { - SL_TRACE(logger_, "Handled statement from {} out of view", relay_parent); - return; - } + TRY_GET_OR_RET(opt_parachain_state, tryGetStateByRelayParent(relay_parent)); auto &relay_parent_state = opt_parachain_state->get(); BOOST_ASSERT(relay_parent_state.statement_store); @@ -1949,15 +1913,11 @@ namespace kagome::parachain { }, para_id, grid::ManifestKind::Acknowledgement); - if (!x) { - return; - } + CHECK_OR_RET(x); SL_TRACE( logger_, "Check local validator. (relay_parent = {})", relay_parent); - if (!relay_parent_state.local_validator) { - return; - } + CHECK_OR_RET(relay_parent_state.local_validator); const auto sender_index = x->sender_index; auto &local_validator = *relay_parent_state.local_validator; @@ -1973,27 +1933,25 @@ namespace kagome::parachain { candidate_hash, peer_id, network::CollationVersion::VStaging); - if (!messages.empty()) { - auto se = pm_->getStreamEngine(); - SL_TRACE(logger_, "Sending messages. (relay_parent = {})", relay_parent); - for (auto &msg : messages) { - if (auto m = - if_type(msg)) { - auto message = std::make_shared>( - std::move(m->get())); - se->send(peer_id, router_->getValidationProtocolVStaging(), message); - } else { - assert(false); - } + + auto se = pm_->getStreamEngine(); + SL_TRACE(logger_, "Sending messages. (relay_parent = {})", relay_parent); + for (auto &msg : messages) { + if (auto m = if_type(msg)) { + auto message = std::make_shared< + network::WireMessage>( + std::move(m->get())); + se->send(peer_id, router_->getValidationProtocolVStaging(), message); + } else { + assert(false); } } } // Handles BackedCandidateManifest message - // It performs various checks and operations, and if everything is - // successful, it sends acknowledgement and statement messages to the - // validators group or sends a request to fetch the attested candidate. + // It performs various checks and operations, and if everything is + // successful, it sends acknowledgement and statement messages to the + // validators group or sends a request to fetch the attested candidate. void ParachainProcessorImpl::handle_incoming_manifest( const libp2p::peer::PeerId &peer_id, const network::vstaging::BackedCandidateManifest &manifest) { @@ -2004,22 +1962,10 @@ namespace kagome::parachain { manifest.candidate_hash, manifest.para_id, manifest.parent_head_data_hash); - auto relay_parent_state = tryGetStateByRelayParent(manifest.relay_parent); - if (!relay_parent_state) { - SL_WARN(logger_, - "After BackedCandidateManifest no parachain state on " - "relay_parent. (relay " - "parent={})", - manifest.relay_parent); - return; - } - if (!relay_parent_state->get().statement_store) { - SL_ERROR(logger_, - "Statement store is not initialized. (relay parent={})", - manifest.relay_parent); - return; - } + TRY_GET_OR_RET(relay_parent_state, + tryGetStateByRelayParent(manifest.relay_parent)); + CHECK_OR_RET(relay_parent_state->get().statement_store); SL_TRACE(logger_, "Handling incoming manifest common. (relay_parent={}, " @@ -2037,9 +1983,7 @@ namespace kagome::parachain { }, manifest.para_id, grid::ManifestKind::Full); - if (!x) { - return; - } + CHECK_OR_RET(x); const auto sender_index = x->sender_index; if (x->acknowledge) { @@ -2079,10 +2023,6 @@ namespace kagome::parachain { manifest.candidate_hash, local_knowledge); - if (messages.empty()) { - return; - } - SL_TRACE(logger_, "Send messages. (relay_parent={}, candidate_hash={})", manifest.relay_parent, @@ -2188,9 +2128,7 @@ namespace kagome::parachain { const auto &session_info = parachain_state->get().per_session_state->value().session_info; - if (!parachain_state->get().local_validator) { - return; - } + CHECK_OR_RET(parachain_state->get().local_validator); auto &local_validator = *parachain_state->get().local_validator; auto originator_group = @@ -2256,21 +2194,16 @@ namespace kagome::parachain { break; } - if (!grid_sender_index) { - return; - } - + CHECK_OR_RET(grid_sender_index); const auto &[gsi, validator_knows_statement] = *grid_sender_index; - if (!validator_knows_statement) { - if (handle_grid_statement(stm.relay_parent, - parachain_state->get(), - local_validator.grid_tracker, - stm.compact, - gsi) - .has_error()) { - return; - } - } else { + + CHECK_OR_RET(!validator_knows_statement); + if (handle_grid_statement(stm.relay_parent, + parachain_state->get(), + local_validator.grid_tracker, + stm.compact, + gsi) + .has_error()) { return; } } @@ -2283,10 +2216,7 @@ namespace kagome::parachain { stm.relay_parent, *originator_group, std::nullopt); - if (!res) { - return; - } - + CHECK_OR_RET(res); const auto confirmed = candidates_.get_confirmed(candidate_hash); const auto is_confirmed = candidates_.is_confirmed(candidate_hash); const auto &group = session_info.validator_groups[*originator_group]; @@ -2378,10 +2308,7 @@ namespace kagome::parachain { const auto originator = statement.payload.ix; const auto is_confirmed = candidates_.is_confirmed(candidate_hash); - if (!relay_parent_state.local_validator) { - return; - } - + CHECK_OR_RET(relay_parent_state.local_validator); enum DirectTargetKind { Cluster, Grid, @@ -2492,8 +2419,6 @@ namespace kagome::parachain { } auto se = pm_->getStreamEngine(); - BOOST_ASSERT(se); - auto message_v2 = std::make_shared< network::WireMessage>( kagome::network::vstaging::ValidatorProtocolMessage{ @@ -2523,18 +2448,15 @@ namespace kagome::parachain { const RelayHash &relay_parent, const CandidateHash &candidate_hash, GroupIndex group_index) { - if (!relay_parent_state.local_validator) { - return; - } + CHECK_OR_RET(relay_parent_state.local_validator); auto &local_validator = *relay_parent_state.local_validator; const auto &session_info = relay_parent_state.per_session_state->value().session_info; - auto group = - relay_parent_state.per_session_state->value().groups.get(group_index); - if (!group) { - return; - } + + TRY_GET_OR_RET( + group, + relay_parent_state.per_session_state->value().groups.get(group_index)); const auto seconding_limit = relay_parent_state.prospective_parachains_mode->max_candidate_depth + 1; @@ -2586,10 +2508,7 @@ namespace kagome::parachain { } } - if (validator_id >= session_info.discovery_keys.size()) { - return; - } - + CHECK_OR_RET(validator_id < session_info.discovery_keys.size()); auto filter = [&]() -> std::optional { if (local_validator.active) { if (local_validator.active->cluster_tracker.knows_candidate( @@ -2612,10 +2531,7 @@ namespace kagome::parachain { return std::nullopt; }(); - if (!filter) { - return; - } - + CHECK_OR_RET(filter); filter->mask_seconded(unwanted_mask.seconded_in_group); filter->mask_valid(unwanted_mask.validated_in_group); @@ -2659,10 +2575,9 @@ namespace kagome::parachain { group_index{group_index}]( outcome::result r) mutable { - if (auto self = wptr.lock()) { - self->handleFetchedStatementResponse( - std::move(r), relay_parent, candidate_hash, group_index); - } + TRY_GET_OR_RET(self, wptr.lock()); + self->handleFetchedStatementResponse( + std::move(r), relay_parent, candidate_hash, group_index); }); } @@ -2692,26 +2607,10 @@ namespace kagome::parachain { /// TODO(iceseer): do https://github.com/qdrvm/kagome/issues/1888 /// validate response - auto parachain_state = tryGetStateByRelayParent(relay_parent); - if (!parachain_state) { - SL_TRACE( - logger_, - "No relay parent data on fetch attested candidate response. (relay " - "parent={})", - relay_parent); - return; - } - - if (!parachain_state->get().statement_store) { - SL_WARN(logger_, - "No statement store. (relay parent={}, candidate={})", - relay_parent, - candidate_hash); - return; - } + TRY_GET_OR_RET(parachain_state, tryGetStateByRelayParent(relay_parent)); + CHECK_OR_RET(parachain_state->get().statement_store); const network::vstaging::AttestedCandidateResponse &response = r.value(); - SL_INFO(logger_, "Fetch attested candidate success. (relay parent={}, " "candidate={}, group index={}, statements={})", @@ -2889,24 +2788,14 @@ namespace kagome::parachain { void ParachainProcessorImpl::send_cluster_candidate_statements( const CandidateHash &candidate_hash, const RelayHash &relay_parent) { - auto relay_parent_state = tryGetStateByRelayParent(relay_parent); - if (!relay_parent_state) { - return; - } - - auto local_group = relay_parent_state->get().our_group; - if (!local_group) { - return; - } - - auto group = + TRY_GET_OR_RET(relay_parent_state, tryGetStateByRelayParent(relay_parent)); + TRY_GET_OR_RET(local_group, relay_parent_state->get().our_group); + TRY_GET_OR_RET( + group, relay_parent_state->get().per_session_state->value().groups.get( - *local_group); - if (!group) { - return; - } - auto group_size = group->size(); + *local_group)); + auto group_size = group->size(); relay_parent_state->get().statement_store->groupStatements( *group, candidate_hash, @@ -2934,10 +2823,7 @@ namespace kagome::parachain { ParachainProcessorImpl::RelayParentState &per_relay_parent, const std::vector &group, const CandidateHash &candidate_hash) { - if (!per_relay_parent.statement_store) { - return; - } - + CHECK_OR_RET(per_relay_parent.statement_store); std::vector> imported; per_relay_parent.statement_store->fresh_statements_for_backing( @@ -2979,10 +2865,10 @@ namespace kagome::parachain { [wself{weak_from_this()}, relay_parent{relay_parent}, carrying_pvd{std::move(carrying_pvd)}]() { - if (auto self = wself.lock()) { - SL_TRACE(self->logger_, "Handle statement {}", relay_parent); - self->handleStatement(relay_parent, carrying_pvd); - } + TRY_GET_OR_RET(self, wself.lock()); + + SL_TRACE(self->logger_, "Handle statement {}", relay_parent); + self->handleStatement(relay_parent, carrying_pvd); }); }); @@ -2996,9 +2882,7 @@ namespace kagome::parachain { const network::StatementDistributionMessage &msg) { BOOST_ASSERT(main_pool_handler_->isInCurrentThread()); if (auto statement_msg{boost::get(&msg)}) { - if (auto r = canProcessParachains(); r.has_error()) { - return; - } + CHECK_OR_RET(canProcessParachains().has_value()); if (auto r = isParachainValidator(statement_msg->relay_parent); r.has_error() || !r.value()) { return; @@ -3102,8 +2986,6 @@ namespace kagome::parachain { peer_info.id); auto protocol = router_->getReqPovProtocol(); - BOOST_ASSERT(protocol); - protocol->request(peer_info, candidate_hash, std::forward(callback)); } @@ -3115,9 +2997,7 @@ namespace kagome::parachain { BOOST_ASSERT(main_pool_handler_->isInCurrentThread()); const auto candidate_hash{attesting_data.candidate.hash(*hasher_)}; - if (parachain_state.issued_statements.contains(candidate_hash)) { - return; - } + CHECK_OR_RET(!parachain_state.issued_statements.contains(candidate_hash)); const auto &session_info = parachain_state.per_session_state->value().session_info; @@ -3142,43 +3022,41 @@ namespace kagome::parachain { wself{weak_from_this()}, relay_parent, peer_id{peer->id}](auto &&pov_response_result) mutable { - if (auto self = wself.lock()) { - auto parachain_state = - self->tryGetStateByRelayParent(relay_parent); - if (!parachain_state) { - SL_TRACE( - self->logger_, - "After request pov no parachain state on relay_parent {}", - relay_parent); - return; - } - - if (!pov_response_result) { - self->logger_->warn("Request PoV on relay_parent {} failed {}", - relay_parent, - pov_response_result.error()); - return; - } + TRY_GET_OR_RET(self, wself.lock()); + auto parachain_state = self->tryGetStateByRelayParent(relay_parent); + if (!parachain_state) { + SL_TRACE( + self->logger_, + "After request pov no parachain state on relay_parent {}", + relay_parent); + return; + } - network::ResponsePov &opt_pov = pov_response_result.value(); - auto p{boost::get(&opt_pov)}; - if (!p) { - self->logger_->warn("No PoV.(candidate={})", candidate_hash); - self->onAttestNoPoVComplete(relay_parent, candidate_hash); - return; - } + if (!pov_response_result) { + self->logger_->warn("Request PoV on relay_parent {} failed {}", + relay_parent, + pov_response_result.error()); + return; + } - self->logger_->info( - "PoV received.(relay_parent={}, candidate hash={}, peer={})", - relay_parent, - candidate_hash, - peer_id); - self->validateAsync( - std::move(candidate), - std::move(*p), - std::move(pvd), - relay_parent); + network::ResponsePov &opt_pov = pov_response_result.value(); + auto p{boost::get(&opt_pov)}; + if (!p) { + self->logger_->warn("No PoV.(candidate={})", candidate_hash); + self->onAttestNoPoVComplete(relay_parent, candidate_hash); + return; } + + self->logger_->info( + "PoV received.(relay_parent={}, candidate hash={}, peer={})", + relay_parent, + candidate_hash, + peer_id); + self->validateAsync( + std::move(candidate), + std::move(*p), + std::move(pvd), + relay_parent); }); } } @@ -3192,23 +3070,19 @@ namespace kagome::parachain { return Error::NOT_CONFIRMED; } - auto relay_parent_state = - tryGetStateByRelayParent(confirmed->get().relay_parent()); - if (!relay_parent_state) { - return Error::NO_STATE; - } - - auto &local_validator = relay_parent_state->get().local_validator; + OUTCOME_TRY(relay_parent_state, + getStateByRelayParent(confirmed->get().relay_parent())); + auto &local_validator = relay_parent_state.get().local_validator; if (!local_validator) { return Error::NOT_A_VALIDATOR; } - BOOST_ASSERT(relay_parent_state->get().statement_store); - BOOST_ASSERT(relay_parent_state->get().our_index); + BOOST_ASSERT(relay_parent_state.get().statement_store); + BOOST_ASSERT(relay_parent_state.get().our_index); const auto &session_info = - relay_parent_state->get().per_session_state->value().session_info; + relay_parent_state.get().per_session_state->value().session_info; const auto &groups = - relay_parent_state->get().per_session_state->value().groups; + relay_parent_state.get().per_session_state->value().groups; auto group = groups.get(confirmed->get().group_index()); if (!group) { SL_ERROR(logger_, @@ -3288,7 +3162,7 @@ namespace kagome::parachain { /// https://github.com/qdrvm/kagome/issues/2060 std::vector> statements; - relay_parent_state->get().statement_store->groupStatements( + relay_parent_state.get().statement_store->groupStatements( *group, request.candidate_hash, and_mask, @@ -3368,12 +3242,7 @@ namespace kagome::parachain { const primitives::BlockHash &relay_parent, const SignedFullStatementWithPVD &statement) { BOOST_ASSERT(main_pool_handler_->isInCurrentThread()); - - auto opt_parachain_state = tryGetStateByRelayParent(relay_parent); - if (!opt_parachain_state) { - logger_->trace("Handled statement from {} out of view", relay_parent); - return; - } + TRY_GET_OR_RET(opt_parachain_state, tryGetStateByRelayParent(relay_parent)); auto ¶chain_state = opt_parachain_state->get(); const auto &assigned_para = parachain_state.assigned_para; @@ -3487,9 +3356,7 @@ namespace kagome::parachain { RelayParentState &relay_parent_state, const ConfirmedCandidate &confirmed_candidate, const runtime::SessionInfo &session_info) { - if (!relay_parent_state.local_validator) { - return; - } + CHECK_OR_RET(relay_parent_state.local_validator); auto &local_validator = *relay_parent_state.local_validator; const auto relay_parent = confirmed_candidate.relay_parent(); @@ -3517,34 +3384,8 @@ namespace kagome::parachain { group_index); return; } - const auto group_size = group->size(); - - SL_TRACE(logger_, - "======================== GRID VIEW group={} relay_parent={} " - "our_index={} our_id={} our_dk={} in_per_session={} " - "========================", - group_index, - relay_parent, - *relay_parent_state.our_index, - session_info.validators[*relay_parent_state.our_index], - session_info.discovery_keys[*relay_parent_state.our_index], - *relay_parent_state.per_session_state->value().our_index); - - for (size_t k = 0; k < grid_view.size(); ++k) { - const auto &v = grid_view[k]; - SL_TRACE(logger_, "\tGroup {}", k); - for (const auto vi : v.sending) { - SL_TRACE(logger_, "\t\tS: {}", vi); - } - for (const auto vi : v.receiving) { - SL_TRACE(logger_, "\t\tR: {}", vi); - } - } - - SL_TRACE( - logger_, - "================================================================="); + const auto group_size = group->size(); auto filter = local_knowledge_filter(group_size, group_index, candidate_hash, @@ -3641,8 +3482,6 @@ namespace kagome::parachain { } auto se = pm_->getStreamEngine(); - BOOST_ASSERT(se); - if (!manifest_peers.empty()) { SL_TRACE(logger_, "Sending manifest to v2 peers. (candidate_hash={}, " @@ -3714,10 +3553,8 @@ namespace kagome::parachain { const auto &confirmed = confirmed_opt->get(); const auto relay_parent = confirmed.relay_parent(); - auto relay_parent_state_opt = tryGetStateByRelayParent(relay_parent); - if (!relay_parent_state_opt) { - return; - } + TRY_GET_OR_RET(relay_parent_state_opt, + tryGetStateByRelayParent(relay_parent)); BOOST_ASSERT(relay_parent_state_opt->get().statement_store); const auto &session_info = @@ -4395,10 +4232,7 @@ namespace kagome::parachain { const RelayHash &relay_parent, ParachainProcessorImpl::RelayParentState &rp_state, std::optional &summary) { - if (!summary) { - return; - } - + CHECK_OR_RET(summary); SL_TRACE(logger_, "Import result.(candidate={}, para id={}, validity votes={})", summary->candidate, @@ -4582,12 +4416,7 @@ namespace kagome::parachain { const libp2p::peer::PeerId &peer_id, const std::shared_ptr &stream, const std::shared_ptr &protocol) { - auto my_view = peer_view_->getMyView(); - if (!my_view) { - logger_->error("sendMyView failed, because my view still is not exists."); - return; - } - + TRY_GET_OR_RET(my_view, peer_view_->getMyView()); BOOST_ASSERT(protocol); logger_->info("Send my view.(peer={}, protocol={})", peer_id, @@ -4616,19 +4445,18 @@ namespace kagome::parachain { peer_state->get().version = version; if (tryOpenOutgoingCollatingStream( peer_id, [wptr{weak_from_this()}, peer_id, version](auto &&stream) { - if (auto self = wptr.lock()) { - switch (version) { - case network::CollationVersion::V1: - case network::CollationVersion::VStaging: { - self->sendMyView( - peer_id, - stream, - self->router_->getCollationProtocolVStaging()); - } break; - default: { - UNREACHABLE; - } break; - } + TRY_GET_OR_RET(self, wptr.lock()); + switch (version) { + case network::CollationVersion::V1: + case network::CollationVersion::VStaging: { + self->sendMyView( + peer_id, + stream, + self->router_->getCollationProtocolVStaging()); + } break; + default: { + UNREACHABLE; + } break; } })) { SL_DEBUG(logger_, "Initiated collation protocol with {}", peer_id); @@ -4654,19 +4482,18 @@ namespace kagome::parachain { peer_id, version, [wptr{weak_from_this()}, peer_id, version](auto &&stream) { - if (auto self = wptr.lock()) { - switch (version) { - case network::CollationVersion::V1: - case network::CollationVersion::VStaging: { - self->sendMyView( - peer_id, - stream, - self->router_->getValidationProtocolVStaging()); - } break; - default: { - UNREACHABLE; - } break; - } + TRY_GET_OR_RET(self, wptr.lock()); + switch (version) { + case network::CollationVersion::V1: + case network::CollationVersion::VStaging: { + self->sendMyView( + peer_id, + stream, + self->router_->getValidationProtocolVStaging()); + } break; + default: { + UNREACHABLE; + } break; } })) { logger_->info("Initiated validation protocol with {}", peer_id); @@ -4745,9 +4572,8 @@ namespace kagome::parachain { auto it = our_current_state_.validator_side.fetched_candidates.find( fetched_collation); - if (it == our_current_state_.validator_side.fetched_candidates.end()) { - return; - } + CHECK_OR_RET(it + != our_current_state_.validator_side.fetched_candidates.end()); if (!it->second.pending_collation.commitments_hash || *it->second.pending_collation.commitments_hash @@ -4831,38 +4657,13 @@ namespace kagome::parachain { return (app_config_.roles().flags.authority == 1); } - outcome::result ParachainProcessorImpl::advCanBeProcessed( - const primitives::BlockHash &relay_parent, - const libp2p::peer::PeerId &peer_id) { - BOOST_ASSERT(main_pool_handler_->isInCurrentThread()); - OUTCOME_TRY(canProcessParachains()); - - auto rps = our_current_state_.state_by_relay_parent.find(relay_parent); - if (rps == our_current_state_.state_by_relay_parent.end()) { - return Error::OUT_OF_VIEW; - } - - if (rps->second.peers_advertised.count(peer_id) != 0ull) { - return Error::DUPLICATE; - } - - rps->second.peers_advertised.insert(peer_id); - return outcome::success(); - } - void ParachainProcessorImpl::onValidationComplete( const ValidateAndSecondResult &validation_result) { logger_->trace("On validation complete. (relay parent={})", validation_result.relay_parent); - auto opt_parachain_state = - tryGetStateByRelayParent(validation_result.relay_parent); - if (!opt_parachain_state) { - logger_->trace("Validated candidate from {} out of view", - validation_result.relay_parent); - return; - } - + TRY_GET_OR_RET(opt_parachain_state, + tryGetStateByRelayParent(validation_result.relay_parent)); auto ¶chain_state = opt_parachain_state->get(); const auto candidate_hash = validation_result.candidate.hash(*hasher_); @@ -4876,10 +4677,7 @@ namespace kagome::parachain { return; } - if (parachain_state.issued_statements.contains(candidate_hash)) { - return; - } - + CHECK_OR_RET(!parachain_state.issued_statements.contains(candidate_hash)); logger_->trace("Second candidate complete. (candidate={}, relay parent={})", candidate_hash, validation_result.relay_parent); @@ -4888,9 +4686,7 @@ namespace kagome::parachain { hasher_->blake2b_256(validation_result.pvd.parent_head); const auto ph = hasher_->blake2b_256(validation_result.commitments->para_head); - if (parent_head_data_hash == ph) { - return; - } + CHECK_OR_RET(parent_head_data_hash != ph); HypotheticalCandidateComplete hypothetical_candidate{ .candidate_hash = candidate_hash, @@ -4903,12 +4699,9 @@ namespace kagome::parachain { }; fragment::FragmentTreeMembership fragment_tree_membership; - if (auto seconding_allowed = - secondingSanityCheck(hypothetical_candidate, false)) { - fragment_tree_membership = std::move(*seconding_allowed); - } else { - return; - } + TRY_GET_OR_RET(seconding_allowed, + secondingSanityCheck(hypothetical_candidate, false)); + fragment_tree_membership = std::move(*seconding_allowed); auto res = sign_import_and_distribute_statement( parachain_state, validation_result); @@ -4924,10 +4717,7 @@ namespace kagome::parachain { return; } - if (!res.value()) { - return; - } - + CHECK_OR_RET(res.value()); auto &stmt = *res.value(); if (auto it = our_current_state_.per_candidate.find(candidate_hash); it != our_current_state_.per_candidate.end()) { @@ -5141,15 +4931,9 @@ namespace kagome::parachain { candidate_hash, std::move(validate_and_second_result)); - auto parachain_state = - tryGetStateByRelayParent(validate_and_second_result.relay_parent); - if (!parachain_state) { - SL_TRACE(logger_, - "After validation no parachain state on relay_parent {}", - validate_and_second_result.relay_parent); - return; - } - + TRY_GET_OR_RET( + parachain_state, + tryGetStateByRelayParent(validate_and_second_result.relay_parent)); SL_INFO(logger_, "Async validation complete.(relay parent={}, para_id={})", validate_and_second_result.relay_parent, @@ -5177,25 +4961,17 @@ namespace kagome::parachain { std::move(pvd), relay_parent); - auto parachain_state = - tryGetStateByRelayParent(candidate.descriptor.relay_parent); - if (!parachain_state) { - return; - } - + TRY_GET_OR_RET(parachain_state, + tryGetStateByRelayParent(candidate.descriptor.relay_parent)); const auto candidate_hash{candidate.hash(*hasher_)}; if constexpr (kMode == ValidationTaskType::kAttest) { - if (parachain_state->get().issued_statements.contains(candidate_hash)) { - return; - } - } - - if (!parachain_state->get() - .awaiting_validation.insert(candidate_hash) - .second) { - return; + CHECK_OR_RET( + !parachain_state->get().issued_statements.contains(candidate_hash)); } + CHECK_OR_RET(parachain_state->get() + .awaiting_validation.insert(candidate_hash) + .second); SL_INFO(logger_, "Starting validation task.(para id={}, " "relay parent={}, candidate_hash={})", @@ -5216,10 +4992,7 @@ namespace kagome::parachain { _measure, candidate_hash]( outcome::result validation_result) mutable { - auto self = weak_self.lock(); - if (not self) { - return; - } + TRY_GET_OR_RET(self, weak_self.lock()); if (!validation_result) { SL_WARN(self->logger_, "Candidate {} on relay_parent {}, para_id {} validation failed " @@ -5238,7 +5011,8 @@ namespace kagome::parachain { .validation_data = std::move(data), }; - auto measure2 = std::make_shared("===> EC validation", self->logger_); + auto measure2 = + std::make_shared("===> EC validation", self->logger_); auto chunks_res = self->validateErasureCoding(available_data, n_validators); if (chunks_res.has_error()) { @@ -5273,10 +5047,7 @@ namespace kagome::parachain { pvd, [weak_self{weak_from_this()}, cb{std::move(cb)}](outcome::result r) mutable { - auto self = weak_self.lock(); - if (not self) { - return; - } + TRY_GET_OR_RET(self, weak_self.lock()); post(*self->main_pool_handler_, [cb{std::move(cb)}, r{std::move(r)}]() mutable { cb(std::move(r)); @@ -5286,14 +5057,8 @@ namespace kagome::parachain { void ParachainProcessorImpl::onAttestComplete( const ValidateAndSecondResult &result) { - auto parachain_state = tryGetStateByRelayParent(result.relay_parent); - if (!parachain_state) { - logger_->warn( - "onAttestComplete result based on unexpected relay_parent {}", - result.relay_parent); - return; - } - + TRY_GET_OR_RET(parachain_state, + tryGetStateByRelayParent(result.relay_parent)); logger_->info("Attest complete.(relay parent={}, para id={})", result.relay_parent, result.candidate.descriptor.para_id); @@ -5324,23 +5089,10 @@ namespace kagome::parachain { void ParachainProcessorImpl::onAttestNoPoVComplete( const network::RelayHash &relay_parent, const CandidateHash &candidate_hash) { - auto parachain_state = tryGetStateByRelayParent(relay_parent); - if (!parachain_state) { - logger_->warn( - "onAttestNoPoVComplete result based on unexpected relay_parent. " - "(relay_parent={}, candidate={})", - relay_parent, - candidate_hash); - return; - } + TRY_GET_OR_RET(parachain_state, tryGetStateByRelayParent(relay_parent)); auto it = parachain_state->get().fallbacks.find(candidate_hash); - if (it == parachain_state->get().fallbacks.end()) { - logger_->error( - "Internal error. Fallbacks doesn't contain candidate hash {}", - candidate_hash); - return; - } + CHECK_OR_RET(it != parachain_state->get().fallbacks.end()); /// TODO(iceseer): make rotation on validators AttestingData &attesting = it->second; @@ -5662,30 +5414,16 @@ namespace kagome::parachain { peer_id, std::move(prospective_candidate)); - auto opt_per_relay_parent = tryGetStateByRelayParent(relay_parent); - if (!opt_per_relay_parent) { - SL_TRACE( - logger_, "Relay parent unknown. (relay_parent={})", relay_parent); - return; - } - + TRY_GET_OR_RET(opt_per_relay_parent, + tryGetStateByRelayParent(relay_parent)); auto &per_relay_parent = opt_per_relay_parent->get(); const ProspectiveParachainsModeOpt &relay_parent_mode = per_relay_parent.prospective_parachains_mode; const std::optional &assignment = per_relay_parent.assigned_para; - auto peer_state = pm_->getPeerState(peer_id); - if (!peer_state) { - SL_TRACE(logger_, "Unknown peer. (peerd_id={})", peer_id); - return; - } - - const auto collator_state = peer_state->get().collator_state; - if (!collator_state) { - SL_TRACE(logger_, "Undeclared collator. (peerd_id={})", peer_id); - return; - } + TRY_GET_OR_RET(peer_state, pm_->getPeerState(peer_id)); + TRY_GET_OR_RET(collator_state, peer_state->get().collator_state); const ParachainId collator_para_id = collator_state->para_id; if (!assignment || collator_para_id != *assignment) { @@ -5897,11 +5635,7 @@ namespace kagome::parachain { return Error::ALREADY_REQUESTED; } - auto per_relay_parent = tryGetStateByRelayParent(pc.relay_parent); - if (!per_relay_parent) { - return Error::OUT_OF_VIEW; - } - + OUTCOME_TRY(per_relay_parent, getStateByRelayParent(pc.relay_parent)); network::CollationEvent collation_event{ .collator_id = id, .collator_protocol_version = version, @@ -5950,8 +5684,8 @@ namespace kagome::parachain { const auto maybe_candidate_hash = utils::map(pc.prospective_candidate, [](const auto &v) { return std::cref(v.candidate_hash); }); - per_relay_parent->get().collations.status = CollationStatus::Fetching; - per_relay_parent->get().collations.fetching_from.emplace( + per_relay_parent.get().collations.status = CollationStatus::Fetching; + per_relay_parent.get().collations.fetching_from.emplace( id, maybe_candidate_hash); if (network::CollationVersion::V1 == version) { diff --git a/core/parachain/validator/parachain_processor.hpp b/core/parachain/validator/parachain_processor.hpp index e643984c0b..0e65ab36b1 100644 --- a/core/parachain/validator/parachain_processor.hpp +++ b/core/parachain/validator/parachain_processor.hpp @@ -469,19 +469,6 @@ namespace kagome::parachain { * Validation. */ - /** - * @brief Checks if an advertisement can be processed. - * - * This function checks if an advertisement can be processed based on the - * relay parent and the peer id. It ensures that the relay parent is in the - * current view and that the advertisement has not been processed before. If - * the advertisement can be processed, it is added to the set of processed - * advertisements. - */ - outcome::result advCanBeProcessed( - const primitives::BlockHash &relay_parent, - const libp2p::peer::PeerId &peer_id); - /** * @brief Validates the erasure coding of the provided data. * From 292c38579838d0e44d271874e8327687077c0d08 Mon Sep 17 00:00:00 2001 From: iceseer Date: Wed, 5 Jun 2024 20:36:19 +0300 Subject: [PATCH 62/71] hunter Signed-off-by: iceseer --- cmake/Hunter/config.cmake | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/cmake/Hunter/config.cmake b/cmake/Hunter/config.cmake index cf8ddcfbe6..d2e3160dd4 100644 --- a/cmake/Hunter/config.cmake +++ b/cmake/Hunter/config.cmake @@ -40,13 +40,13 @@ hunter_config( if ("${WASM_COMPILER}" STREQUAL "WasmEdge") hunter_config( - WasmEdge - URL https://github.com/qdrvm/WasmEdge/archive/refs/heads/feature/expose-jit.zip - SHA1 277cef01a9b2171538b6d3f7a18358007b41ac95 - CMAKE_ARGS - WASMEDGE_BUILD_STATIC_LIB=OFF - WASMEDGE_BUILD_SHARED_LIB=ON - KEEP_PACKAGE_SOURCES + WasmEdge + URL https://github.com/qdrvm/WasmEdge/archive/refs/tags/0.13.5-qdrvm1.zip + SHA1 3637f5df6892a762606393940539c0dcb6e9c022 + CMAKE_ARGS + WASMEDGE_BUILD_STATIC_LIB=ON + WASMEDGE_BUILD_SHARED_LIB=OFF + KEEP_PACKAGE_SOURCES ) endif () From ac01e203c74ef03cfd1cda5d5dc09cfe3e1b1984 Mon Sep 17 00:00:00 2001 From: kamilsa Date: Thu, 6 Jun 2024 17:29:24 +0500 Subject: [PATCH 63/71] Revert "Always return true in handle_import_statements" This reverts commit fd16fb20dacaf6727d17d96c71c6afc48aa957fd. --- core/dispute_coordinator/impl/dispute_coordinator_impl.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/core/dispute_coordinator/impl/dispute_coordinator_impl.cpp b/core/dispute_coordinator/impl/dispute_coordinator_impl.cpp index d974f8575e..2df522b3fa 100644 --- a/core/dispute_coordinator/impl/dispute_coordinator_impl.cpp +++ b/core/dispute_coordinator/impl/dispute_coordinator_impl.cpp @@ -1009,7 +1009,6 @@ namespace kagome::dispute { MaybeCandidateReceipt candidate_receipt, const SessionIndex session, std::vector> statements) { - return true; BOOST_ASSERT(initialized_); auto now = system_clock_.nowUint64(); From d7c508a5c82d7581ea69fbf32a75ef2364c6abe7 Mon Sep 17 00:00:00 2001 From: iceseer Date: Thu, 6 Jun 2024 16:03:32 +0300 Subject: [PATCH 64/71] trace statistics Signed-off-by: iceseer --- .../parachain/availability/bitfield/store.hpp | 2 ++ .../availability/bitfield/store_impl.cpp | 7 +++++ .../availability/bitfield/store_impl.hpp | 1 + core/parachain/availability/store/store.hpp | 1 + .../availability/store/store_impl.cpp | 11 ++++++++ .../availability/store/store_impl.hpp | 2 ++ core/parachain/backing/store.hpp | 1 + core/parachain/backing/store_impl.cpp | 7 +++++ core/parachain/backing/store_impl.hpp | 2 ++ .../validator/backing_implicit_view.hpp | 10 +++++++ .../validator/impl/parachain_processor.cpp | 27 +++++++++++++++++++ .../validator/parachain_processor.hpp | 7 ++--- .../validator/prospective_parachains.hpp | 9 +++++++ 13 files changed, 82 insertions(+), 5 deletions(-) diff --git a/core/parachain/availability/bitfield/store.hpp b/core/parachain/availability/bitfield/store.hpp index e9dc7cdafa..28b70b3e2b 100644 --- a/core/parachain/availability/bitfield/store.hpp +++ b/core/parachain/availability/bitfield/store.hpp @@ -21,6 +21,8 @@ namespace kagome::parachain { virtual void putBitfield(const BlockHash &relay_parent, const SignedBitfield &bitfield) = 0; + virtual void printStoragesLoad() = 0; + /// Get bitfields for given block. virtual std::vector getBitfields( const BlockHash &relay_parent) const = 0; diff --git a/core/parachain/availability/bitfield/store_impl.cpp b/core/parachain/availability/bitfield/store_impl.cpp index 0dd60109e2..ff6db1da0f 100644 --- a/core/parachain/availability/bitfield/store_impl.cpp +++ b/core/parachain/availability/bitfield/store_impl.cpp @@ -26,6 +26,13 @@ namespace kagome::parachain { bitfields_.erase(relay_parent); } + void BitfieldStoreImpl::printStoragesLoad() { + SL_TRACE(logger_, + "[Bitfield store statistics]:" + "\n\t-> bitfields_={}", + bitfields_.size()); + } + std::vector BitfieldStoreImpl::getBitfields( const BlockHash &relay_parent) const { auto it = bitfields_.find(relay_parent); diff --git a/core/parachain/availability/bitfield/store_impl.hpp b/core/parachain/availability/bitfield/store_impl.hpp index 2d05695bd9..1a55ca83ac 100644 --- a/core/parachain/availability/bitfield/store_impl.hpp +++ b/core/parachain/availability/bitfield/store_impl.hpp @@ -23,6 +23,7 @@ namespace kagome::parachain { std::vector getBitfields( const BlockHash &relay_parent) const override; void remove(const BlockHash &relay_parent) override; + void printStoragesLoad() override; private: std::unordered_map> bitfields_; diff --git a/core/parachain/availability/store/store.hpp b/core/parachain/availability/store/store.hpp index 7f9cc092bd..10940a41d1 100644 --- a/core/parachain/availability/store/store.hpp +++ b/core/parachain/availability/store/store.hpp @@ -55,5 +55,6 @@ namespace kagome::parachain { /// Clears all data according to this relay_parent virtual void remove(const network::RelayHash &relay_parent) = 0; + virtual void printStoragesLoad() = 0; }; } // namespace kagome::parachain diff --git a/core/parachain/availability/store/store_impl.cpp b/core/parachain/availability/store/store_impl.cpp index 3172ceb484..1bf6d61946 100644 --- a/core/parachain/availability/store/store_impl.cpp +++ b/core/parachain/availability/store/store_impl.cpp @@ -102,6 +102,17 @@ namespace kagome::parachain { }); } + void AvailabilityStoreImpl::printStoragesLoad() { + state_.sharedAccess([&](auto &state) { + SL_TRACE(logger, + "[Availability store statistics]:" + "\n\t-> state.candidates={}" + "\n\t-> state.per_candidate={}", + state.candidates_.size(), + state.per_candidate_.size()); + }); + } + void AvailabilityStoreImpl::storeData(const network::RelayHash &relay_parent, const CandidateHash &candidate_hash, std::vector &&chunks, diff --git a/core/parachain/availability/store/store_impl.hpp b/core/parachain/availability/store/store_impl.hpp index bc0879944b..23984f1fe2 100644 --- a/core/parachain/availability/store/store_impl.hpp +++ b/core/parachain/availability/store/store_impl.hpp @@ -38,6 +38,7 @@ namespace kagome::parachain { const CandidateHash &candidate_hash, ErasureChunk &&chunk) override; void remove(const network::RelayHash &relay_parent) override; + void printStoragesLoad() override; private: struct PerCandidate { @@ -52,6 +53,7 @@ namespace kagome::parachain { candidates_{}; }; + log::Logger logger = log::createLogger("AvailabilityStore", "parachain"); SafeObject state_{}; }; } // namespace kagome::parachain diff --git a/core/parachain/backing/store.hpp b/core/parachain/backing/store.hpp index 7e8705dc68..1f1ce48d60 100644 --- a/core/parachain/backing/store.hpp +++ b/core/parachain/backing/store.hpp @@ -61,5 +61,6 @@ namespace kagome::parachain { virtual std::optional> getCadidateInfo(const RelayHash &relay_parent, const network::CandidateHash &candidate_hash) const = 0; + virtual void printStoragesLoad() = 0; }; } // namespace kagome::parachain diff --git a/core/parachain/backing/store_impl.cpp b/core/parachain/backing/store_impl.cpp index 08c2326fd8..c3d477c296 100644 --- a/core/parachain/backing/store_impl.cpp +++ b/core/parachain/backing/store_impl.cpp @@ -182,6 +182,13 @@ namespace kagome::parachain { return res.value(); } + void BackingStoreImpl::printStoragesLoad() { + SL_TRACE(logger, + "[Backing store statistics]:" + "\n\t-> per_relay_parent={}", + per_relay_parent_.size()); + } + std::optional> BackingStoreImpl::getCadidateInfo( const RelayHash &relay_parent, diff --git a/core/parachain/backing/store_impl.hpp b/core/parachain/backing/store_impl.hpp index 80d43f20fa..0d821f001b 100644 --- a/core/parachain/backing/store_impl.hpp +++ b/core/parachain/backing/store_impl.hpp @@ -85,6 +85,7 @@ namespace kagome::parachain { void onActivateLeaf(const RelayHash &relay_parent) override; void onDeactivateLeaf(const RelayHash &relay_parent) override; + void printStoragesLoad() override; private: struct AuthorityData { @@ -138,6 +139,7 @@ namespace kagome::parachain { std::shared_ptr hasher_; std::unordered_map per_relay_parent_; + log::Logger logger = log::createLogger("BackingStore", "parachain"); }; } // namespace kagome::parachain diff --git a/core/parachain/validator/backing_implicit_view.hpp b/core/parachain/validator/backing_implicit_view.hpp index 40576e8376..f109fa7897 100644 --- a/core/parachain/validator/backing_implicit_view.hpp +++ b/core/parachain/validator/backing_implicit_view.hpp @@ -46,6 +46,15 @@ namespace kagome::parachain { return r; } + void printStoragesLoad() { + SL_TRACE(logger, + "[Backing implicit view statistics]:" + "\n\t-> leaves={}" + "\n\t-> block_info_storage={}", + leaves.size(), + block_info_storage.size()); + } + ImplicitView(std::shared_ptr prospective_parachains); private: @@ -71,6 +80,7 @@ namespace kagome::parachain { std::unordered_map leaves; std::unordered_map block_info_storage; std::shared_ptr prospective_parachains_; + log::Logger logger = log::createLogger("BackingImplicitView", "parachain"); outcome::result fetch_fresh_leaf_and_insert_ancestry( const Hash &leaf_hash); diff --git a/core/parachain/validator/impl/parachain_processor.cpp b/core/parachain/validator/impl/parachain_processor.cpp index ac0a2eb6e4..f441922c95 100644 --- a/core/parachain/validator/impl/parachain_processor.cpp +++ b/core/parachain/validator/impl/parachain_processor.cpp @@ -787,6 +787,7 @@ namespace kagome::parachain { prune_old_advertisements(*our_current_state_.implicit_view, our_current_state_.active_leaves, our_current_state_.state_by_relay_parent); + printStoragesLoad(); } void ParachainProcessorImpl::onDeactivateBlocks( @@ -5404,6 +5405,32 @@ namespace kagome::parachain { return false; } + void ParachainProcessorImpl::printStoragesLoad() { + SL_TRACE(logger_, + "[Parachain storages statistics]:" + "\n\t-> state_by_relay_parent={}" + "\n\t-> per_leaf={}" + "\n\t-> per_candidate={}" + "\n\t-> active_leaves={}" + "\n\t-> blocked_advertisements={}" + "\n\t-> collation_requests_cancel_handles={}" + "\n\t-> validator_side.fetched_candidates={}", + our_current_state_.state_by_relay_parent.size(), + our_current_state_.per_leaf.size(), + our_current_state_.per_candidate.size(), + our_current_state_.active_leaves.size(), + our_current_state_.blocked_advertisements.size(), + our_current_state_.collation_requests_cancel_handles.size(), + our_current_state_.validator_side.fetched_candidates.size()); + if (our_current_state_.implicit_view) { + our_current_state_.implicit_view->printStoragesLoad(); + } + prospective_parachains_->printStoragesLoad(); + bitfield_store_->printStoragesLoad(); + backing_store_->printStoragesLoad(); + av_store_->printStoragesLoad(); + } + void ParachainProcessorImpl::handleAdvertisement( const RelayHash &relay_parent, const libp2p::peer::PeerId &peer_id, diff --git a/core/parachain/validator/parachain_processor.hpp b/core/parachain/validator/parachain_processor.hpp index 0e65ab36b1..ed4686ee13 100644 --- a/core/parachain/validator/parachain_processor.hpp +++ b/core/parachain/validator/parachain_processor.hpp @@ -1063,6 +1063,8 @@ namespace kagome::parachain { const HypotheticalCandidate &hypothetical_candidate, bool backed_in_path_only); + void printStoragesLoad(); + outcome::result kick_off_seconding( network::PendingCollationFetch &&pending_collation_fetch); @@ -1102,11 +1104,6 @@ namespace kagome::parachain { std::unordered_map fetched_candidates; } validator_side; - - struct { - std::unordered_set implicit_view; - network::View view; - } statementDistributionV2; } our_current_state_; std::shared_ptr main_pool_handler_; diff --git a/core/parachain/validator/prospective_parachains.hpp b/core/parachain/validator/prospective_parachains.hpp index 9948afabe7..eba3e9ce0e 100644 --- a/core/parachain/validator/prospective_parachains.hpp +++ b/core/parachain/validator/prospective_parachains.hpp @@ -73,6 +73,15 @@ namespace kagome::parachain { BOOST_ASSERT(block_tree_); } + void printStoragesLoad() { + SL_TRACE(logger, + "[Prospective parachains storages statistics]:" + "\n\t-> view.active_leaves={}" + "\n\t-> view.candidate_storage={}", + view.active_leaves.size(), + view.candidate_storage.size()); + } + std::shared_ptr getBlockTree() { BOOST_ASSERT(block_tree_); return block_tree_; From 8073861ad45d9d1d38efcb7a1b8512df326a1a77 Mon Sep 17 00:00:00 2001 From: iceseer Date: Fri, 7 Jun 2024 10:09:06 +0300 Subject: [PATCH 65/71] memory fix Signed-off-by: iceseer --- core/api/jrpc/value_converter.hpp | 15 ++ core/blockchain/impl/block_tree_impl.cpp | 66 +++--- .../approval/approval_distribution.cpp | 218 +++++++++--------- .../validator/impl/parachain_processor.cpp | 36 ++- core/primitives/event_types.hpp | 9 +- .../runtime_api/impl/parachain_host.cpp | 8 +- 6 files changed, 209 insertions(+), 143 deletions(-) diff --git a/core/api/jrpc/value_converter.hpp b/core/api/jrpc/value_converter.hpp index 1b12dcd75e..5bfeac3d2f 100644 --- a/core/api/jrpc/value_converter.hpp +++ b/core/api/jrpc/value_converter.hpp @@ -70,6 +70,10 @@ namespace kagome::api { inline jsonrpc::Value makeValue(const primitives::Version &); inline jsonrpc::Value makeValue(const primitives::Justification &); inline jsonrpc::Value makeValue(const primitives::RpcMethods &); + inline jsonrpc::Value makeValue( + const primitives::events::RemoveAfterFinalizationParams &val); + inline jsonrpc::Value makeValue( + const primitives::events::RemoveAfterFinalizationParams::HeaderInfo &val); inline jsonrpc::Value makeValue(const uint32_t &val) { return static_cast(val); @@ -150,6 +154,17 @@ namespace kagome::api { return value; } + inline jsonrpc::Value makeValue( + const primitives::events::RemoveAfterFinalizationParams &val) { + return makeValue(val.removed); + } + + inline jsonrpc::Value makeValue( + const primitives::events::RemoveAfterFinalizationParams::HeaderInfo + &val) { + return makeValue(val.hash); + } + template inline jsonrpc::Value makeValue(const common::Blob &val) { return makeValue(BufferView{val}); diff --git a/core/blockchain/impl/block_tree_impl.cpp b/core/blockchain/impl/block_tree_impl.cpp index 41c6dfbb96..b4cadc891d 100644 --- a/core/blockchain/impl/block_tree_impl.cpp +++ b/core/blockchain/impl/block_tree_impl.cpp @@ -813,9 +813,13 @@ namespace kagome::blockchain { OUTCOME_TRY(p.storage_->putJustification(justification, block_hash)); - std::vector retired_hashes; + std::vector< + primitives::events::RemoveAfterFinalizationParams::HeaderInfo> + retired_hashes; for (auto parent = node->parent(); parent; parent = parent->parent()) { - retired_hashes.emplace_back(parent->info.hash); + retired_hashes.emplace_back( + primitives::events::RemoveAfterFinalizationParams::HeaderInfo{ + parent->info.hash, parent->info.number}); } auto changes = p.tree_->finalize(node); @@ -846,12 +850,13 @@ namespace kagome::blockchain { main_pool_handler_->execute( [weak{weak_from_this()}, - retired_hashes{std::move(retired_hashes)}] { + retired{primitives::events::RemoveAfterFinalizationParams{ + std::move(retired_hashes), header.number}}] { if (auto self = weak.lock()) { self->chain_events_engine_->notify( primitives::events::ChainEventType:: kDeactivateAfterFinalization, - retired_hashes); + retired); } }); @@ -1301,7 +1306,8 @@ namespace kagome::blockchain { } std::vector extrinsics; - std::vector retired_hashes; + std::vector + retired_hashes; // remove from storage retired_hashes.reserve(changes.prune.size()); @@ -1329,33 +1335,39 @@ namespace kagome::blockchain { BOOST_ASSERT(block_header_opt.has_value()); OUTCOME_TRY(p.state_pruner_->pruneDiscarded(block_header_opt.value())); } - retired_hashes.emplace_back(block.hash); + retired_hashes.emplace_back( + primitives::events::RemoveAfterFinalizationParams::HeaderInfo{ + block.hash, block.number}); OUTCOME_TRY(p.storage_->removeBlock(block.hash)); } // trying to return extrinsics back to transaction pool - main_pool_handler_->execute([extrinsics{std::move(extrinsics)}, - wself{weak_from_this()}, - retired_hashes{ - std::move(retired_hashes)}]() mutable { - if (auto self = wself.lock()) { - auto eo = self->block_tree_data_.sharedAccess( - [&](const BlockTreeData &p) { return p.extrinsic_observer_; }); - - for (auto &&extrinsic : extrinsics) { - auto result = eo->onTxMessage(extrinsic); - if (result) { - SL_DEBUG(self->log_, "Tx {} was reapplied", result.value().toHex()); - } else { - SL_DEBUG(self->log_, "Tx was skipped: {}", result.error()); - } - } + main_pool_handler_->execute( + [extrinsics{std::move(extrinsics)}, + wself{weak_from_this()}, + retired{primitives::events::RemoveAfterFinalizationParams{ + std::move(retired_hashes), + getLastFinalizedNoLock(p).number}}]() mutable { + if (auto self = wself.lock()) { + auto eo = self->block_tree_data_.sharedAccess( + [&](const BlockTreeData &p) { return p.extrinsic_observer_; }); + + for (auto &&extrinsic : extrinsics) { + auto result = eo->onTxMessage(extrinsic); + if (result) { + SL_DEBUG( + self->log_, "Tx {} was reapplied", result.value().toHex()); + } else { + SL_DEBUG(self->log_, "Tx was skipped: {}", result.error()); + } + } - self->chain_events_engine_->notify( - primitives::events::ChainEventType::kDeactivateAfterFinalization, - retired_hashes); - } - }); + self->chain_events_engine_->notify( + primitives::events::ChainEventType:: + kDeactivateAfterFinalization, + retired); + } + }); return outcome::success(); } diff --git a/core/parachain/approval/approval_distribution.cpp b/core/parachain/approval/approval_distribution.cpp index 9bad3c92ea..2bcaf93e30 100644 --- a/core/parachain/approval/approval_distribution.cpp +++ b/core/parachain/approval/approval_distribution.cpp @@ -570,31 +570,31 @@ namespace kagome::parachain { REINVOKE(*approval_thread_handler_, clearCaches, event); approvals_cache_.exclusiveAccess([&](auto &approvals_cache) { - for (const auto &lost : event) { + for (const auto &lost : event.removed) { SL_TRACE(logger_, "Cleaning up stale pending messages.(block hash={})", - lost); - pending_known_.erase(lost); - active_tranches_.erase(lost); - approving_context_map_.erase(lost); + lost.hash); + pending_known_.erase(lost.hash); + active_tranches_.erase(lost.hash); + approving_context_map_.erase(lost.hash); /// TODO(iceseer): `blocks_by_number_` clear on finalization - if (auto block_entry = storedBlockEntries().get(lost)) { + if (auto block_entry = storedBlockEntries().get(lost.hash)) { for (const auto &candidate : block_entry->get().candidates) { recovery_->remove(candidate.second); storedCandidateEntries().extract(candidate.second); if (auto it_cached = approvals_cache.find(candidate.second); it_cached != approvals_cache.end()) { ApprovalCache &approval_cache = it_cached->second; - approval_cache.blocks_.erase(lost); + approval_cache.blocks_.erase(lost.hash); if (approval_cache.blocks_.empty()) { approvals_cache.erase(it_cached); } } } - storedBlockEntries().extract(lost); + storedBlockEntries().extract(lost.hash); } - storedDistribBlockEntries().extract(lost); + storedDistribBlockEntries().extract(lost.hash); } }); } @@ -1240,110 +1240,112 @@ namespace kagome::parachain { ValidatorIndex validator_index, Hash block_hash, GroupIndex backing_group) { - auto on_recover_complete = [wself{weak_from_this()}, - hashed_candidate{hashed_candidate}, - block_hash, - session_index, - validator_index, - relay_block_hash]( - std::optional< - outcome::result> - &&opt_result) mutable { - auto self = wself.lock(); - if (!self) { - return; - } + auto on_recover_complete = + [wself{weak_from_this()}, + hashed_candidate{hashed_candidate}, + block_hash, + session_index, + validator_index, + relay_block_hash]( + std::optional> + &&opt_result) mutable { + auto self = wself.lock(); + if (!self) { + return; + } - const auto &candidate_receipt = hashed_candidate.get(); - if (!opt_result) { // Unavailable - self->logger_->warn( - "No available parachain data.(session index={}, candidate " - "hash={}, relay block hash={})", - session_index, - hashed_candidate.getHash(), - relay_block_hash); - return; - } + const auto &candidate_receipt = hashed_candidate.get(); + if (!opt_result) { // Unavailable + self->logger_->warn( + "No available parachain data.(session index={}, candidate " + "hash={}, relay block hash={})", + session_index, + hashed_candidate.getHash(), + relay_block_hash); + return; + } - if (opt_result->has_error()) { - self->logger_->warn( - "Parachain data recovery failed.(error={}, session index={}, " - "candidate hash={}, relay block hash={})", - opt_result->error(), - session_index, - hashed_candidate.getHash(), - relay_block_hash); - self->dispute_coordinator_.get()->issueLocalStatement( - session_index, - hashed_candidate.getHash(), - hashed_candidate.get(), - false); - return; - } - auto &available_data = opt_result->value(); - auto result = self->parachain_host_->validation_code_by_hash( - block_hash, candidate_receipt.descriptor.validation_code_hash); - if (result.has_error() || !result.value()) { - self->logger_->warn( - "Approval state is failed. Block hash {}, session index {}, " - "validator index {}, relay parent {}", - block_hash, - session_index, - validator_index, - candidate_receipt.descriptor.relay_parent); - return; /// ApprovalState::failed - } + if (opt_result->has_error()) { + self->logger_->warn( + "Parachain data recovery failed.(error={}, session index={}, " + "candidate hash={}, relay block hash={})", + opt_result->error(), + session_index, + hashed_candidate.getHash(), + relay_block_hash); + self->dispute_coordinator_.get()->issueLocalStatement( + session_index, + hashed_candidate.getHash(), + hashed_candidate.get(), + false); + return; + } + auto &available_data = opt_result->value(); + auto result = self->parachain_host_->validation_code_by_hash( + block_hash, candidate_receipt.descriptor.validation_code_hash); + if (result.has_error() || !result.value()) { + self->logger_->warn( + "Approval state is failed. Block hash {}, session index {}, " + "validator index {}, relay parent {}", + block_hash, + session_index, + validator_index, + candidate_receipt.descriptor.relay_parent); + return; /// ApprovalState::failed + } - self->logger_->info( - "Make exhaustive validation. Candidate hash {}, validator index " - "{}, block hash {}", - hashed_candidate.getHash(), - validator_index, - block_hash); + self->logger_->info( + "Make exhaustive validation. Candidate hash {}, validator index " + "{}, block hash {}", + hashed_candidate.getHash(), + validator_index, + block_hash); - runtime::ValidationCode &validation_code = *result.value(); + runtime::ValidationCode &validation_code = *result.value(); - auto cb = [weak_self{wself}, - hashed_candidate, - session_index, - validator_index, - relay_block_hash](outcome::result outcome) { - auto self = weak_self.lock(); - if (not self) { - return; - } - const auto &candidate_receipt = hashed_candidate.get(); - self->approvals_cache_.exclusiveAccess([&](auto &approvals_cache) { - if (auto it = approvals_cache.find(hashed_candidate.getHash()); - it != approvals_cache.end()) { - ApprovalCache &ac = it->second; - ac.approval_result = outcome.has_error() - ? ApprovalOutcome::Failed - : ApprovalOutcome::Approved; - } - }); - if (outcome.has_error()) { - self->logger_->warn( - "Approval validation failed.(parachain id={}, relay parent={}, error={})", - candidate_receipt.descriptor.para_id, - candidate_receipt.descriptor.relay_parent, - outcome.error()); - self->dispute_coordinator_.get()->issueLocalStatement( - session_index, - hashed_candidate.getHash(), - candidate_receipt, - false); - } else { - self->issue_approval( - hashed_candidate.getHash(), validator_index, relay_block_hash); - } - }; - self->pvf_->pvfValidate(available_data.validation_data, - available_data.pov, - candidate_receipt, - validation_code, - std::move(cb)); - }; + auto cb = [weak_self{wself}, + hashed_candidate, + session_index, + validator_index, + relay_block_hash](outcome::result outcome) { + auto self = weak_self.lock(); + if (not self) { + return; + } + const auto &candidate_receipt = hashed_candidate.get(); + self->approvals_cache_.exclusiveAccess([&](auto &approvals_cache) { + if (auto it = approvals_cache.find(hashed_candidate.getHash()); + it != approvals_cache.end()) { + ApprovalCache &ac = it->second; + ac.approval_result = outcome.has_error() + ? ApprovalOutcome::Failed + : ApprovalOutcome::Approved; + } + }); + if (outcome.has_error()) { + self->logger_->warn( + "Approval validation failed.(parachain id={}, relay " + "parent={}, error={})", + candidate_receipt.descriptor.para_id, + candidate_receipt.descriptor.relay_parent, + outcome.error()); + self->dispute_coordinator_.get()->issueLocalStatement( + session_index, + hashed_candidate.getHash(), + candidate_receipt, + false); + } else { + self->issue_approval(hashed_candidate.getHash(), + validator_index, + relay_block_hash); + } + }; + self->pvf_->pvfValidate(available_data.validation_data, + available_data.pov, + candidate_receipt, + validation_code, + std::move(cb)); + }; recovery_->recover(hashed_candidate, session_index, diff --git a/core/parachain/validator/impl/parachain_processor.cpp b/core/parachain/validator/impl/parachain_processor.cpp index f441922c95..8642edfe75 100644 --- a/core/parachain/validator/impl/parachain_processor.cpp +++ b/core/parachain/validator/impl/parachain_processor.cpp @@ -794,12 +794,36 @@ namespace kagome::parachain { const primitives::events::RemoveAfterFinalizationParams &event) { REINVOKE(*main_pool_handler_, onDeactivateBlocks, event); - for (const auto &lost : event) { - SL_TRACE(logger_, "Remove from storages.(relay parent={})", lost); - - backing_store_->onDeactivateLeaf(lost); - av_store_->remove(lost); - bitfield_store_->remove(lost); + for (const auto &lost : event.removed) { + SL_TRACE(logger_, + "Remove from storages.(relay parent={}, number={})", + lost.hash, + lost.number); + + backing_store_->onDeactivateLeaf(lost.hash); + av_store_->remove(lost.hash); + bitfield_store_->remove(lost.hash); + } + + for (auto it = our_current_state_.state_by_relay_parent.begin(); + it != our_current_state_.state_by_relay_parent.end();) { + const auto &hash = it->first; + const auto &per_relay_state = it->second; + const auto header = block_tree_->getBlockHeader(hash); + + const bool keep = header.has_value() + && per_relay_state.prospective_parachains_mode + && (header.value().number + + per_relay_state.prospective_parachains_mode + ->allowed_ancestry_len + + 1) + >= event.finalized; + if (keep) { + ++it; + } else { + our_current_state_.implicit_view->deactivate_leaf(hash); + it = our_current_state_.state_by_relay_parent.erase(it); + } } } diff --git a/core/primitives/event_types.hpp b/core/primitives/event_types.hpp index 14edcdf12d..1ae24e606d 100644 --- a/core/primitives/event_types.hpp +++ b/core/primitives/event_types.hpp @@ -48,7 +48,14 @@ namespace kagome::primitives::events { using HeadsEventParams = ref_t; using RuntimeVersionEventParams = ref_t; using NewRuntimeEventParams = ref_t; - using RemoveAfterFinalizationParams = std::vector; + struct RemoveAfterFinalizationParams { + struct HeaderInfo { + primitives::BlockHash hash; + primitives::BlockNumber number; + }; + std::vector removed; + primitives::BlockNumber finalized; + }; using ChainEventParams = boost::variantclearCaches(event); + std::vector removed; + removed.reserve(event.removed.size()); + std::transform(event.removed.begin(), + event.removed.end(), + std::back_inserter(removed), + [](const auto &bi) { return bi.hash; }); + self->clearCaches(removed); } }); From 97c9cd29e46075538faf89f82cdcf14dbeb65ed7 Mon Sep 17 00:00:00 2001 From: iceseer Date: Fri, 14 Jun 2024 09:07:48 +0300 Subject: [PATCH 66/71] issues fixes Signed-off-by: iceseer --- .../impl/dispute_coordinator_impl.cpp | 41 ++++++++----------- 1 file changed, 16 insertions(+), 25 deletions(-) diff --git a/core/dispute_coordinator/impl/dispute_coordinator_impl.cpp b/core/dispute_coordinator/impl/dispute_coordinator_impl.cpp index 2df522b3fa..058698388a 100644 --- a/core/dispute_coordinator/impl/dispute_coordinator_impl.cpp +++ b/core/dispute_coordinator/impl/dispute_coordinator_impl.cpp @@ -63,7 +63,7 @@ namespace kagome::dispute { [&](const ValidDisputeStatement &kind) { return visit_in_place( kind, - [&](const Explicit &x) { + [&](const Explicit &) { std::array magic{'D', 'I', 'S', 'P'}; bool validity = true; return scale::encode( @@ -91,15 +91,6 @@ namespace kagome::dispute { std::array magic{'A', 'P', 'P', 'R'}; return scale::encode( std::tie(magic, candidate_hash, session)); - }, - [&](const ApprovalCheckingMultipleCandidates &candidates) { - std::array magic{'A', 'P', 'P', 'R'}; - if (candidates.size() == 1) { - return scale::encode( - std::tie(magic, candidates.front(), session)); - } else { - return scale::encode(std::tie(magic, candidates, session)); - } }); }, [&](const InvalidDisputeStatement &kind) { @@ -329,7 +320,7 @@ namespace kagome::dispute { // https://github.com/paritytech/polkadot/blob/40974fb99c86f5c341105b7db53c7aa0df707d66/node/core/dispute-coordinator/src/lib.rs#L298 for (auto &[session, candidate_hash, status] : active_disputes) { auto env_opt = makeCandidateEnvironment( - *session_keys_, *rolling_session_window_, session, first_leaf.hash); + *session_keys_, *rolling_session_window_, session); if (not env_opt.has_value()) { continue; } @@ -544,7 +535,6 @@ namespace kagome::dispute { auto res = process_active_leaves_update(update); if (res.has_error()) { SL_ERROR(log_, "Can't handle active list update: {}", res.error()); - std::ignore = process_active_leaves_update(update); return; } } @@ -560,6 +550,18 @@ namespace kagome::dispute { return outcome::success(); } + // Obtain the session info, for sake of `ValidatorId`s either from the + // rolling session window. Must be called _after_ `fn + // cache_session_info_for_head` which guarantees that the session info is + // available for the current session. + auto session_info_opt = rolling_session_window_->session_info(session); + if (not session_info_opt.has_value()) { + SL_WARN(log_, + "Could not retrieve session info from rolling session window"); + return outcome::success(); + } + auto &session_info = session_info_opt.value().get(); + // Scraped on-chain backing votes for the candidates with the new active // leaf as if we received them via gossip. for (auto &[candidate_receipt, backers] : @@ -569,11 +571,6 @@ namespace kagome::dispute { SL_TRACE(log_, "Importing backing votes from chain for candidate"); - OUTCOME_TRY(session, api_->session_index_for_child(relay_parent)); - OUTCOME_TRY(session_info_opt, api_->session_info(relay_parent, session)); - BOOST_ASSERT(session_info_opt.has_value()); - const auto &session_info = session_info_opt.value(); - std::vector> statements; for (auto &[validator_index, attestation] : backers) { if (validator_index >= session_info.validators.size()) { @@ -981,14 +978,8 @@ namespace kagome::dispute { DisputeCoordinatorImpl::makeCandidateEnvironment( crypto::SessionKeys &session_keys, RollingSessionWindow &rolling_session_window, - SessionIndex session, - primitives::BlockHash relay_parent) { - auto session_info_opt_res = api_->session_info(relay_parent, session); - if (session_info_opt_res.has_error()) { - // TODO log - return std::nullopt; - } - auto session_info_opt = session_info_opt_res.value(); + SessionIndex session) { + auto session_info_opt = rolling_session_window.session_info(session); if (not session_info_opt.has_value()) { return std::nullopt; } From 7e6595a0dbc45a5d20cf7963ba6e78278cd0bea7 Mon Sep 17 00:00:00 2001 From: iceseer Date: Mon, 17 Jun 2024 10:05:50 +0300 Subject: [PATCH 67/71] issues fixes Signed-off-by: iceseer --- .../impl/dispute_coordinator_impl.cpp | 83 ++++------- .../impl/dispute_coordinator_impl.hpp | 5 +- .../impl/prioritized_selection.cpp | 20 --- core/dispute_coordinator/types.hpp | 51 +------ core/log/configurator.cpp | 2 +- core/network/impl/peer_manager_impl.cpp | 30 ++-- .../0001-parachains-pvf.toml | 134 ------------------ .../0001-parachains-pvf.zndsl | 84 ----------- .../0000-validator-disabling.toml | 18 +-- 9 files changed, 56 insertions(+), 371 deletions(-) delete mode 100644 zombienet/0001-parachains-pvf/0001-parachains-pvf.toml delete mode 100644 zombienet/0001-parachains-pvf/0001-parachains-pvf.zndsl diff --git a/core/dispute_coordinator/impl/dispute_coordinator_impl.cpp b/core/dispute_coordinator/impl/dispute_coordinator_impl.cpp index 058698388a..b1e4e27a34 100644 --- a/core/dispute_coordinator/impl/dispute_coordinator_impl.cpp +++ b/core/dispute_coordinator/impl/dispute_coordinator_impl.cpp @@ -983,7 +983,7 @@ namespace kagome::dispute { if (not session_info_opt.has_value()) { return std::nullopt; } - auto session_info = std::move(session_info_opt.value()); + auto &session_info = session_info_opt.value().get(); std::unordered_set controlled_indices; auto keypair = session_keys.getParaKeyPair(session_info.validators); @@ -992,7 +992,7 @@ namespace kagome::dispute { } return CandidateEnvironment{.session_index = session, - .session = std::move(session_info), + .session = session_info, .controlled_indices = controlled_indices}; } @@ -1015,6 +1015,16 @@ namespace kagome::dispute { .hash(*hasher_) : boost::relaxed_get(candidate_receipt); + auto env_opt = makeCandidateEnvironment( + *session_keys_, *rolling_session_window_, session); + if (not env_opt.has_value()) { + SL_DEBUG(log_, + "We are lacking a `SessionInfo` for handling import of " + "statements."); + return outcome::success(false); + } + auto &env = env_opt.value(); + // In case we are not provided with a candidate receipt we operate under // the assumption, that a previous vote which included a // `CandidateReceipt` was seen. This holds since every block is preceded @@ -1052,16 +1062,6 @@ namespace kagome::dispute { relay_parent = old_state_opt->candidate_receipt.descriptor.relay_parent; } - auto env_opt = makeCandidateEnvironment( - *session_keys_, *rolling_session_window_, session, relay_parent); - if (not env_opt.has_value()) { - SL_DEBUG(log_, - "We are lacking a `SessionInfo` for handling import of " - "statements."); - return outcome::success(false); - } - auto &env = env_opt.value(); - auto disabled_validators_res = api_->disabled_validators(relay_parent); if (disabled_validators_res.has_error()) { SL_WARN(log_, @@ -1154,24 +1154,19 @@ namespace kagome::dispute { statements.end()); } ++imported_valid_votes; - // return true; + return true; } - // auto &existing = std::get<0>(it->second); - // return visit_in_place( - // valid, - // [&](const Explicit &) { - // return not is_type(existing); - // }, - // [&](const BackingSeconded &) { return false; }, - // [&](const BackingValid &) { return false; }, - // [&](const ApprovalChecking &) { - // return not is_type(existing); - // }, - // [&](const ApprovalCheckingMultipleCandidates &) { - // return not - // is_type( - // existing); - // }); + auto &existing = std::get<0>(it->second); + return visit_in_place( + valid, + [&](const Explicit &) { + return not is_type(existing); + }, + [&](const BackingSeconded &) { return false; }, + [&](const BackingValid &) { return false; }, + [&](const ApprovalChecking &) { + return not is_type(existing); + }); }, [&](const InvalidDisputeStatement &invalid) { auto [it, fresh] = votes.invalid.emplace( @@ -1186,9 +1181,9 @@ namespace kagome::dispute { statements.end()); } ++imported_invalid_votes; - // return true; + return true; } - // return false; + return false; }); } @@ -1472,11 +1467,7 @@ namespace kagome::dispute { sig, session}; - SL_TRACE( - log_, - "Sending out own approval vote. session={}, candidate_hash={}", - session, - candidate_hash); + SL_TRACE(log_, "Sending out own approval vote"); auto dispute_message_res = make_dispute_message( env.session, new_state.votes, statement, validator_index); @@ -1800,12 +1791,7 @@ namespace kagome::dispute { bool valid) { // https://github.com/paritytech/polkadot/blob/40974fb99c86f5c341105b7db53c7aa0df707d66/node/core/dispute-coordinator/src/initialized.rs#L1102 - SL_TRACE(log_, - "Issuing local statement for candidate! " - "session={}, candidate_hash={}, relay_parent={}", - session, - candidate_hash, - candidate_receipt.descriptor.relay_parent); + SL_TRACE(log_, "Issuing local statement for candidate!"); // Load environment: @@ -2072,12 +2058,7 @@ namespace kagome::dispute { std::move(candidate_receipt), valid); - SL_TRACE(log_, - "DisputeCoordinatorMessage::IssueLocalStatement. " - "session={}, candidate_hash={}, relay_parent={}", - session, - candidate_hash, - candidate_receipt.descriptor.relay_parent); + SL_TRACE(log_, "DisputeCoordinatorMessage::IssueLocalStatement"); auto res = issue_local_statement( candidate_hash, candidate_receipt, session, valid); @@ -2526,12 +2507,6 @@ namespace kagome::dispute { } } - SL_TRACE( // FIXME It's temporary code. Remove after tests - log_, - "Dispute (candidate={}) did not send. Disabled", - candidate_hash); - return; - auto protocol = router_->getSendDisputeProtocol(); BOOST_ASSERT_MSG(protocol, "Router did not provide `send dispute` protocol"); diff --git a/core/dispute_coordinator/impl/dispute_coordinator_impl.hpp b/core/dispute_coordinator/impl/dispute_coordinator_impl.hpp index 091e459f55..47872b2ee1 100644 --- a/core/dispute_coordinator/impl/dispute_coordinator_impl.hpp +++ b/core/dispute_coordinator/impl/dispute_coordinator_impl.hpp @@ -192,11 +192,10 @@ namespace kagome::dispute { std::vector> statements, CbOutcome &&cb); - std::optional makeCandidateEnvironment( + static std::optional makeCandidateEnvironment( crypto::SessionKeys &session_keys, RollingSessionWindow &rolling_session_window, - SessionIndex session, - primitives::BlockHash relay_parent); + SessionIndex session); outcome::result process_on_chain_votes(ScrapedOnChainVotes votes); diff --git a/core/dispute_coordinator/provisioner/impl/prioritized_selection.cpp b/core/dispute_coordinator/provisioner/impl/prioritized_selection.cpp index ae9f646870..359257b623 100644 --- a/core/dispute_coordinator/provisioner/impl/prioritized_selection.cpp +++ b/core/dispute_coordinator/provisioner/impl/prioritized_selection.cpp @@ -96,17 +96,9 @@ namespace kagome::dispute { // Transform all `CandidateVotes` into `MultiDisputeStatementSet`. MultiDisputeStatementSet result; - - SL_TRACE(log_, "XXX >>> PrioritizedSelection::select_disputes"); - for (auto &[key, votes] : dispute_candidate_votes) { auto &[session_index, candidate_hash] = key; - SL_TRACE(log_, - "XXX session={}, candidate_hash={}", - session_index, - candidate_hash); - auto &statement_set = result.emplace_back( DisputeStatementSet{candidate_hash, session_index, {}}); @@ -116,11 +108,6 @@ namespace kagome::dispute { ValidDisputeStatement(statement), // validator_index, validator_signature); - - SL_TRACE(log_, - "XXX Valid, validator_index={}, validator_sign={}", - validator_index, - validator_signature); } for (auto &[validator_index, value] : votes.invalid) { @@ -129,16 +116,9 @@ namespace kagome::dispute { InvalidDisputeStatement(statement), validator_index, validator_signature); - - SL_TRACE(log_, - "XXX Invalid, validator_index={}, validator_sign={}", - validator_index, - validator_signature); } } - SL_TRACE(log_, "XXX <<< PrioritizedSelection::select_disputes"); - return result; } diff --git a/core/dispute_coordinator/types.hpp b/core/dispute_coordinator/types.hpp index b748b7283b..83b1c85d43 100644 --- a/core/dispute_coordinator/types.hpp +++ b/core/dispute_coordinator/types.hpp @@ -48,21 +48,10 @@ namespace kagome::dispute { using BackingValid = Tagged; /// An approval vote from the approval checking phase. using ApprovalChecking = Tagged; - /// An approval vote from the new version. - /// We can't create this version until all nodes have been updated to support - /// it and max_approval_coalesce_count is set to more than 1. - using ApprovalCheckingMultipleCandidates = - Tagged, - struct ApprovalCheckingMultipleCandidatesTag>; /// A valid statement, of the given kind using ValidDisputeStatement = - boost::variant; + boost::variant; /// An invalid statement, of the given kind. using InvalidDisputeStatement = boost::variant; @@ -163,7 +152,7 @@ namespace kagome::dispute { /// The session the candidate appeared in. SessionIndex session_index; /// Session for above index. - SessionInfo session; + SessionInfo &session; /// Validator indices controlled by this node. std::unordered_set controlled_indices{}; }; @@ -230,7 +219,7 @@ namespace kagome::dispute { /// A set of statements about a specific candidate. struct DisputeStatementSet { - // SCALE_TIE(3); + SCALE_TIE(3); /// The candidate referenced by this set. CandidateHash candidate_hash; @@ -242,22 +231,6 @@ namespace kagome::dispute { std::vector< std::tuple> statements; - - template - friend inline Stream &operator<<(Stream &s, const DisputeStatementSet &x) { - s << x.candidate_hash; - s << x.session; - s << x.statements; - return s; - } - - template - friend inline Stream &operator>>(Stream &s, DisputeStatementSet &x) { - s >> x.candidate_hash; - s >> x.session; - s >> x.statements; - return s; - } }; /// A set of dispute statements. @@ -265,7 +238,7 @@ namespace kagome::dispute { /// Scraped runtime backing votes and resolved disputes. struct ScrapedOnChainVotes { - // SCALE_TIE(3); + SCALE_TIE(3); /// The session in which the block was included. SessionIndex session; @@ -281,22 +254,6 @@ namespace kagome::dispute { /// Note that the above `backing_validators` are /// unrelated to the backers of the disputes candidates. MultiDisputeStatementSet disputes; - - template - friend inline Stream &operator<<(Stream &s, const ScrapedOnChainVotes &x) { - s << x.session; - s << x.backing_validators_per_candidate; - s << x.disputes; - return s; - } - - template - friend inline Stream &operator>>(Stream &s, ScrapedOnChainVotes &x) { - s >> x.session; - s >> x.backing_validators_per_candidate; - s >> x.disputes; - return s; - } }; /// Describes a relay-chain block by the para-chain candidates diff --git a/core/log/configurator.cpp b/core/log/configurator.cpp index b0e2b4359d..c06584eae0 100644 --- a/core/log/configurator.cpp +++ b/core/log/configurator.cpp @@ -14,7 +14,7 @@ namespace kagome::log { sinks: - name: console type: console - stream: stdout + stream: stderr thread: name color: false latency: 0 diff --git a/core/network/impl/peer_manager_impl.cpp b/core/network/impl/peer_manager_impl.cpp index 157cf26314..0a1e9dfd33 100644 --- a/core/network/impl/peer_manager_impl.cpp +++ b/core/network/impl/peer_manager_impl.cpp @@ -299,8 +299,6 @@ namespace kagome::network { } void PeerManagerImpl::align() { - SL_INFO(log_, "DEBUG: call align()"); - SL_TRACE(log_, "Try to align peers number"); const auto hard_limit = app_config_.inPeers() + app_config_.inPeersLight() @@ -600,8 +598,6 @@ namespace kagome::network { } void PeerManagerImpl::processDiscoveredPeer(const PeerId &peer_id) { - SL_INFO(log_, "DEBUG: call processDiscoveredPeer()"); - // Ignore himself if (isSelfPeer(peer_id)) { return; @@ -652,16 +648,13 @@ namespace kagome::network { return; } - SL_INFO(self->log_, "DEBUG: call openOutgoing::()"); - auto &peer_id = peer_info.id; if (not stream_res.has_value()) { - SL_VERBOSE(self->log_, - "Unable to create stream {} with {}: {}", - protocol->protocolName(), - peer_id, - stream_res.error()); + self->log_->verbose("Unable to create stream {} with {}: {}", + protocol->protocolName(), + peer_id, + stream_res.error()); self->connecting_peers_.erase(peer_id); self->disconnectFromPeer(peer_id); return; @@ -670,7 +663,7 @@ namespace kagome::network { ? PeerType::PEER_TYPE_OUT : PeerType::PEER_TYPE_IN; - // Add to the active peer list + // Add to active peer list if (auto [ap_it, added] = self->active_peers_.emplace( peer_id, PeerDescriptor{peer_type, self->clock_->now()}); added) { @@ -679,11 +672,12 @@ namespace kagome::network { // And remove from queue if (auto piq_it = self->peers_in_queue_.find(peer_id); piq_it != self->peers_in_queue_.end()) { - auto qtc_it = std::find_if(self->queue_to_connect_.cbegin(), - self->queue_to_connect_.cend(), - [&peer_id](const auto &item) { - return peer_id == item.get(); - }); + auto qtc_it = + std::find_if(self->queue_to_connect_.cbegin(), + self->queue_to_connect_.cend(), + [&peer_id = peer_id](const auto &item) { + return peer_id == item.get(); + }); self->queue_to_connect_.erase(qtc_it); self->peers_in_queue_.erase(piq_it); BOOST_ASSERT(self->queue_to_connect_.size() @@ -775,8 +769,6 @@ namespace kagome::network { } void PeerManagerImpl::processFullyConnectedPeer(const PeerId &peer_id) { - SL_INFO(log_, "DEBUG: call processFullyConnectedPeer()"); - // Skip connection to itself if (isSelfPeer(peer_id)) { connecting_peers_.erase(peer_id); diff --git a/zombienet/0001-parachains-pvf/0001-parachains-pvf.toml b/zombienet/0001-parachains-pvf/0001-parachains-pvf.toml deleted file mode 100644 index 5b41ab84ce..0000000000 --- a/zombienet/0001-parachains-pvf/0001-parachains-pvf.toml +++ /dev/null @@ -1,134 +0,0 @@ -[settings] -timeout = 1000 - -[relaychain] -chain = "rococo-local" - -[relaychain.default_resources] -limits = { memory = "4G", cpu = "2" } -requests = { memory = "2G", cpu = "1" } - - [[relaychain.nodes]] - name = "alice" - command = "kagome" - prometheus_prefix = "kagome" - args = [ "--alice", "-lparachain=debug", "-lruntime=debug", "-ldispute=trace" ] - - [[relaychain.nodes]] - name = "bob" - command = "kagome" - prometheus_prefix = "kagome" - args = [ "--bob", "-lparachain=debug", "-lruntime=debug", "-ldispute=trace" ] - - [[relaychain.nodes]] - name = "charlie" - command = "kagome" - prometheus_prefix = "kagome" - args = [ "--charlie", "-lparachain=debug", "-lruntime=debug", "-ldispute=trace" ] - - [[relaychain.nodes]] - name = "dave" - command = "kagome" - prometheus_prefix = "kagome" - args = [ "--dave", "-lparachain=debug", "-lruntime=debug", "-ldispute=trace" ] - - [[relaychain.nodes]] - name = "ferdie" - args = [ "--ferdie", "-lparachain=debug,runtime=debug" ] - - [[relaychain.nodes]] - name = "eve" - args = [ "--eve", "-lparachain=debug,runtime=debug"] - - [[relaychain.nodes]] - name = "one" - args = [ "--one", "-lparachain=debug,runtime=debug" ] - - [[relaychain.nodes]] - name = "two" - args = [ "--two", "-lparachain=debug,runtime=debug"] - -[[parachains]] -id = 2000 -addToGenesis = true -genesis_state_generator = "undying-collator export-genesis-state --pov-size=100000 --pvf-complexity=1" - - [parachains.collator] - name = "collator01" - command = "undying-collator" - args = ["-lparachain=debug", "--pov-size=100000", "--pvf-complexity=1", "--parachain-id=2000"] - -[[parachains]] -id = 2001 -addToGenesis = true -genesis_state_generator = "undying-collator export-genesis-state --pov-size=100000 --pvf-complexity=10" - - [parachains.collator] - name = "collator02" - command = "undying-collator" - args = ["-lparachain=debug", "--pov-size=100000", "--parachain-id=2001", "--pvf-complexity=10"] - -[[parachains]] -id = 2002 -addToGenesis = true -genesis_state_generator = "undying-collator export-genesis-state --pov-size=100000 --pvf-complexity=100" - - [parachains.collator] - name = "collator03" - command = "undying-collator" - args = ["-lparachain=debug", "--pov-size=100000", "--parachain-id=2002", "--pvf-complexity=100"] - -[[parachains]] -id = 2003 -addToGenesis = true -genesis_state_generator = "undying-collator export-genesis-state --pov-size=20000 --pvf-complexity=300" - - [parachains.collator] - name = "collator04" - command = "undying-collator" - args = ["-lparachain=debug", "--pov-size=20000", "--parachain-id=2003", "--pvf-complexity=300"] - -[[parachains]] -id = 2004 -addToGenesis = true -genesis_state_generator = "undying-collator export-genesis-state --pov-size=100000 --pvf-complexity=300" - - [parachains.collator] - name = "collator05" - command = "undying-collator" - args = ["-lparachain=debug", "--pov-size=100000", "--parachain-id=2004", "--pvf-complexity=300"] - -[[parachains]] -id = 2005 -addToGenesis = true -genesis_state_generator = "undying-collator export-genesis-state --pov-size=20000 --pvf-complexity=400" - - [parachains.collator] - name = "collator06" - command = "undying-collator" - args = ["-lparachain=debug", "--pov-size=20000", "--pvf-complexity=400", "--parachain-id=2005"] - -[[parachains]] -id = 2006 -addToGenesis = true -genesis_state_generator = "undying-collator export-genesis-state --pov-size=100000 --pvf-complexity=300" - - [parachains.collator] - name = "collator07" - command = "undying-collator" - args = ["-lparachain=debug", "--pov-size=100000", "--pvf-complexity=300", "--parachain-id=2006"] - -[[parachains]] -id = 2007 -addToGenesis = true -genesis_state_generator = "undying-collator export-genesis-state --pov-size=100000 --pvf-complexity=300" - - [parachains.collator] - name = "collator08" - command = "undying-collator" - args = ["-lparachain=debug", "--pov-size=100000", "--pvf-complexity=300", "--parachain-id=2007"] - -[types.Header] -number = "u64" -parent_hash = "Hash" -post_state = "Hash" diff --git a/zombienet/0001-parachains-pvf/0001-parachains-pvf.zndsl b/zombienet/0001-parachains-pvf/0001-parachains-pvf.zndsl deleted file mode 100644 index 8ac805ed65..0000000000 --- a/zombienet/0001-parachains-pvf/0001-parachains-pvf.zndsl +++ /dev/null @@ -1,84 +0,0 @@ -Description: PVF preparation & execution time -Network: ./0001-parachains-pvf.toml -Creds: config - -# Check authority status. -alice: reports node_roles is 4 -bob: reports node_roles is 4 -charlie: reports node_roles is 4 -dave: reports node_roles is 4 -eve: reports node_roles is 4 -ferdie: reports node_roles is 4 -one: reports node_roles is 4 -two: reports node_roles is 4 - -# Ensure parachains are registered. -alice: parachain 2000 is registered within 60 seconds -bob: parachain 2001 is registered within 60 seconds -charlie: parachain 2002 is registered within 60 seconds -dave: parachain 2003 is registered within 60 seconds -ferdie: parachain 2004 is registered within 60 seconds -eve: parachain 2005 is registered within 60 seconds -one: parachain 2006 is registered within 60 seconds -two: parachain 2007 is registered within 60 seconds - -# Ensure parachains made progress. -alice: parachain 2000 block height is at least 10 within 300 seconds -alice: parachain 2001 block height is at least 10 within 300 seconds -alice: parachain 2002 block height is at least 10 within 300 seconds -alice: parachain 2003 block height is at least 10 within 300 seconds -alice: parachain 2004 block height is at least 10 within 300 seconds -alice: parachain 2005 block height is at least 10 within 300 seconds -alice: parachain 2006 block height is at least 10 within 300 seconds -alice: parachain 2007 block height is at least 10 within 300 seconds - -alice: reports substrate_block_height{status="finalized"} is at least 30 within 400 seconds - -# Check preparation time is under 10s. -# Check all buckets <= 10. -alice: reports histogram kagome_pvf_preparation_time has at least 1 samples in buckets ["0.1", "0.5", "1", "2", "3", "10"] within 10 seconds -bob: reports histogram kagome_pvf_preparation_time has at least 1 samples in buckets ["0.1", "0.5", "1", "2", "3", "10"] within 10 seconds -charlie: reports histogram kagome_pvf_preparation_time has at least 1 samples in buckets ["0.1", "0.5", "1", "2", "3", "10"] within 10 seconds -dave: reports histogram kagome_pvf_preparation_time has at least 1 samples in buckets ["0.1", "0.5", "1", "2", "3", "10"] within 10 seconds -ferdie: reports histogram polkadot_pvf_preparation_time has at least 1 samples in buckets ["0.1", "0.5", "1", "2", "3", "10"] within 10 seconds -eve: reports histogram polkadot_pvf_preparation_time has at least 1 samples in buckets ["0.1", "0.5", "1", "2", "3", "10"] within 10 seconds -one: reports histogram polkadot_pvf_preparation_time has at least 1 samples in buckets ["0.1", "0.5", "1", "2", "3", "10"] within 10 seconds -two: reports histogram polkadot_pvf_preparation_time has at least 1 samples in buckets ["0.1", "0.5", "1", "2", "3", "10"] within 10 seconds - -# Check all buckets >= 20. -alice: reports histogram kagome_pvf_preparation_time has 0 samples in buckets ["20", "30", "60", "120", "+Inf"] within 10 seconds -bob: reports histogram kagome_pvf_preparation_time has 0 samples in buckets ["20", "30", "60", "120", "+Inf"] within 10 seconds -charlie: reports histogram kagome_pvf_preparation_time has 0 samples in buckets ["20", "30", "60", "120", "+Inf"] within 10 seconds -dave: reports histogram kagome_pvf_preparation_time has 0 samples in buckets ["20", "30", "60", "120", "+Inf"] within 10 seconds -ferdie: reports histogram polkadot_pvf_preparation_time has 0 samples in buckets ["20", "30", "60", "120", "+Inf"] within 10 seconds -eve: reports histogram polkadot_pvf_preparation_time has 0 samples in buckets ["20", "30", "60", "120", "+Inf"] within 10 seconds -one: reports histogram polkadot_pvf_preparation_time has 0 samples in buckets ["20", "30", "60", "120", "+Inf"] within 10 seconds -two: reports histogram polkadot_pvf_preparation_time has 0 samples in buckets ["20", "30", "60", "120", "+Inf"] within 10 seconds - -# Check execution time. -# There are two different timeout conditions: DEFAULT_BACKING_EXECUTION_TIMEOUT(2s) and -# DEFAULT_APPROVAL_EXECUTION_TIMEOUT(12s). Currently these are not differentiated by metrics -# because the metrics are defined in `polkadot-node-core-pvf` which is a level below -# the relevant subsystems. -# That being said, we will take the simplifying assumption of testing only the -# 2s timeout. -# We do this check by ensuring all executions fall into bucket le="2" or lower. -# First, check if we have at least 1 sample, but we should have many more. -alice: reports histogram kagome_pvf_execution_time has at least 1 samples in buckets ["0.1", "0.5", "1", "2"] within 10 seconds -bob: reports histogram kagome_pvf_execution_time has at least 1 samples in buckets ["0.1", "0.5", "1", "2"] within 10 seconds -charlie: reports histogram kagome_pvf_execution_time has at least 1 samples in buckets ["0.1", "0.5", "1", "2"] within 10 seconds -dave: reports histogram kagome_pvf_execution_time has at least 1 samples in buckets ["0.1", "0.5", "1", "2"] within 10 seconds -ferdie: reports histogram polkadot_pvf_execution_time has at least 1 samples in buckets ["0.1", "0.5", "1", "2"] within 10 seconds -eve: reports histogram polkadot_pvf_execution_time has at least 1 samples in buckets ["0.1", "0.5", "1", "2"] within 10 seconds -one: reports histogram polkadot_pvf_execution_time has at least 1 samples in buckets ["0.1", "0.5", "1", "2"] within 10 seconds -two: reports histogram polkadot_pvf_execution_time has at least 1 samples in buckets ["0.1", "0.5", "1", "2"] within 10 seconds - -# Check if we have no samples > 2s. -alice: reports histogram kagome_pvf_execution_time has 0 samples in buckets ["3", "4", "5", "6", "+Inf"] within 10 seconds -bob: reports histogram kagome_pvf_execution_time has 0 samples in buckets ["3", "4", "5", "6", "+Inf"] within 10 seconds -charlie: reports histogram kagome_pvf_execution_time has 0 samples in buckets ["3", "4", "5", "6", "+Inf"] within 10 seconds -dave: reports histogram kagome_pvf_execution_time has 0 samples in buckets ["3", "4", "5", "6", "+Inf"] within 10 seconds -ferdie: reports histogram polkadot_pvf_execution_time has 0 samples in buckets ["3", "4", "5", "6", "+Inf"] within 10 seconds -eve: reports histogram polkadot_pvf_execution_time has 0 samples in buckets ["3", "4", "5", "6", "+Inf"] within 10 seconds -one: reports histogram polkadot_pvf_execution_time has 0 samples in buckets ["3", "4", "5", "6", "+Inf"] within 10 seconds -two: reports histogram polkadot_pvf_execution_time has 0 samples in buckets ["3", "4", "5", "6", "+Inf"] within 10 seconds diff --git a/zombienet/old/0000-validator-disabling/0000-validator-disabling.toml b/zombienet/old/0000-validator-disabling/0000-validator-disabling.toml index d395241d25..82b1043837 100644 --- a/zombienet/old/0000-validator-disabling/0000-validator-disabling.toml +++ b/zombienet/old/0000-validator-disabling/0000-validator-disabling.toml @@ -21,21 +21,21 @@ requests = { memory = "2G", cpu = "1" } # [[relaychain.node_groups]] # name = "honest-validator" # count = 3 -# args = ["-lparachain=trace", "--parachain-single-process"] +# args = ["-lparachain=debug"] [[relaychain.node_groups]] name = "honest-validator" - count = 4 - args = [ "-lparachain=trace", "-lgrandpa=trace", "--parachain-single-process" ] + count = 3 + args = [ "-lparachain=trace", "-lgrandpa=trace" ] command = "kagome" prometheus_prefix = "kagome" -# [[relaychain.node_groups]] -# image = "{{MALUS_IMAGE}}" -# name = "malus-validator" -# command = "malus suggest-garbage-candidate" -# args = ["-lMALUS=trace"] -# count = 1 + [[relaychain.node_groups]] + image = "{{MALUS_IMAGE}}" + name = "malus-validator" + command = "malus suggest-garbage-candidate" + args = ["-lMALUS=trace"] + count = 1 [[parachains]] id = 1000 From 60427188d431c792fc6438c580c58d279434b501 Mon Sep 17 00:00:00 2001 From: iceseer Date: Mon, 17 Jun 2024 10:35:29 +0300 Subject: [PATCH 68/71] issues fixes Signed-off-by: iceseer --- core/network/types/collator_messages.hpp | 2 +- core/utils/pool_handler.hpp | 3 +++ 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/core/network/types/collator_messages.hpp b/core/network/types/collator_messages.hpp index 519b60952e..07f75c5700 100644 --- a/core/network/types/collator_messages.hpp +++ b/core/network/types/collator_messages.hpp @@ -258,7 +258,7 @@ namespace kagome::network { auto val = uint8_t(core_index); for (size_t i = 0; i < 8; ++i) { - core_index_to_inject.bits[i] = ((1 << i) & val) >> i; + core_index_to_inject.bits[i] = (val >> i) & 1; } validator_indices.bits.insert(validator_indices.bits.end(), core_index_to_inject.bits.begin(), diff --git a/core/utils/pool_handler.hpp b/core/utils/pool_handler.hpp index b0c304981b..68321c1ec9 100644 --- a/core/utils/pool_handler.hpp +++ b/core/utils/pool_handler.hpp @@ -95,6 +95,9 @@ namespace kagome { } \ } while (false) +/// Reinvokes function once depending on `template ` argument. +/// If `true` reinvoke takes place, otherwise direct call. After reinvoke called +/// function has `false` in kReinvoke. #define REINVOKE_ONCE(ctx, func, ...) \ do { \ if constexpr (kReinvoke) { \ From d78de3bd313610a825ce788155838d244e2aeedc Mon Sep 17 00:00:00 2001 From: iceseer Date: Mon, 17 Jun 2024 11:43:27 +0300 Subject: [PATCH 69/71] test fixes Signed-off-by: iceseer --- test/core/parachain/prospective_parachains.cpp | 3 ++- test/mock/core/parachain/backing_store_mock.hpp | 2 ++ test/mock/core/parachain/bitfield_store_mock.hpp | 2 ++ test/mock/core/runtime/parachain_host_mock.hpp | 16 ++++++++++++++++ 4 files changed, 22 insertions(+), 1 deletion(-) diff --git a/test/core/parachain/prospective_parachains.cpp b/test/core/parachain/prospective_parachains.cpp index 0b300e596e..eb3dbf3023 100644 --- a/test/core/parachain/prospective_parachains.cpp +++ b/test/core/parachain/prospective_parachains.cpp @@ -610,7 +610,8 @@ class ProspectiveParachainsTest : public testing::Test { candidate_relay_parent, hasher_->blake2b_256(parent_head_data), para_id); - ASSERT_EQ(resp, expected_pvd); + ASSERT_TRUE(resp.has_value()); + ASSERT_EQ(resp.value(), expected_pvd); } }; diff --git a/test/mock/core/parachain/backing_store_mock.hpp b/test/mock/core/parachain/backing_store_mock.hpp index 780de46b5b..e32edb2878 100644 --- a/test/mock/core/parachain/backing_store_mock.hpp +++ b/test/mock/core/parachain/backing_store_mock.hpp @@ -42,6 +42,8 @@ namespace kagome::parachain { MOCK_METHOD(void, onActivateLeaf, (const RelayHash &), (override)); MOCK_METHOD(void, onDeactivateLeaf, (const RelayHash &), (override)); + + MOCK_METHOD(void, printStoragesLoad, (), (override)); }; } // namespace kagome::parachain diff --git a/test/mock/core/parachain/bitfield_store_mock.hpp b/test/mock/core/parachain/bitfield_store_mock.hpp index 20cc04885c..add8760fde 100644 --- a/test/mock/core/parachain/bitfield_store_mock.hpp +++ b/test/mock/core/parachain/bitfield_store_mock.hpp @@ -25,6 +25,8 @@ namespace kagome::parachain { (const, override)); MOCK_METHOD(void, remove, (const BlockHash &), (override)); + + MOCK_METHOD(void, printStoragesLoad, (), (override)); }; } // namespace kagome::parachain diff --git a/test/mock/core/runtime/parachain_host_mock.hpp b/test/mock/core/runtime/parachain_host_mock.hpp index c91a867cc5..b785a7f0fb 100644 --- a/test/mock/core/runtime/parachain_host_mock.hpp +++ b/test/mock/core/runtime/parachain_host_mock.hpp @@ -153,6 +153,22 @@ namespace kagome::runtime { disabled_validators, (const primitives::BlockHash &), (override)); + + MOCK_METHOD(outcome::result>, + node_features, + (const primitives::BlockHash &, SessionIndex), + (override)); + + MOCK_METHOD( + (outcome::result>>), + claim_queue, + (const primitives::BlockHash &), + (override)); + + MOCK_METHOD(outcome::result, + runtime_api_version, + (const primitives::BlockHash &), + (override)); }; } // namespace kagome::runtime From 3dd36ca8d5532f2a32358dda3019a00fc425b047 Mon Sep 17 00:00:00 2001 From: iceseer Date: Thu, 20 Jun 2024 10:07:29 +0300 Subject: [PATCH 70/71] issues Signed-off-by: iceseer --- core/network/types/collator_messages.hpp | 1 + core/network/types/collator_messages_vstaging.hpp | 2 ++ core/parachain/validator/impl/parachain_processor.cpp | 7 ++----- core/parachain/validator/parachain_processor.hpp | 3 +++ test/core/parachain/prospective_parachains.cpp | 1 + 5 files changed, 9 insertions(+), 5 deletions(-) diff --git a/core/network/types/collator_messages.hpp b/core/network/types/collator_messages.hpp index 07f75c5700..7435fb69cf 100644 --- a/core/network/types/collator_messages.hpp +++ b/core/network/types/collator_messages.hpp @@ -234,6 +234,7 @@ namespace kagome::network { std::vector validity_votes; scale::BitVec validator_indices; + /// Creates `BackedCandidate` from args. static BackedCandidate from( CommittedCandidateReceipt candidate_, std::vector validity_votes_, diff --git a/core/network/types/collator_messages_vstaging.hpp b/core/network/types/collator_messages_vstaging.hpp index 4038e03aae..9ffccc03ac 100644 --- a/core/network/types/collator_messages_vstaging.hpp +++ b/core/network/types/collator_messages_vstaging.hpp @@ -360,6 +360,8 @@ namespace kagome::network { VStaging = 2, }; + /// Candidate supplied with a para head it's built on top of. + /// polkadot/node/network/collator-protocol/src/validator_side/collation.rs struct ProspectiveCandidate { SCALE_TIE(2); /// Candidate hash. diff --git a/core/parachain/validator/impl/parachain_processor.cpp b/core/parachain/validator/impl/parachain_processor.cpp index 7f49c5e32a..db3dc64499 100644 --- a/core/parachain/validator/impl/parachain_processor.cpp +++ b/core/parachain/validator/impl/parachain_processor.cpp @@ -638,8 +638,6 @@ namespace kagome::parachain { our_current_state_.implicit_view->deactivate_leaf(lost); for (const auto removed : pruned) { our_current_state_.state_by_relay_parent.erase(removed); - /// TODO(iceseer): do https://github.com/qdrvm/kagome/issues/1888 - /// fetched_candidates ??? } { /// remove cancelations @@ -2627,9 +2625,6 @@ namespace kagome::parachain { return; } - /// TODO(iceseer): do https://github.com/qdrvm/kagome/issues/1888 - /// validate response - TRY_GET_OR_RET(parachain_state, tryGetStateByRelayParent(relay_parent)); CHECK_OR_RET(parachain_state->get().statement_store); @@ -2777,6 +2772,7 @@ namespace kagome::parachain { } } + /// TODO(iceseer): https://github.com/qdrvm/kagome/issues/2133 /// TODO(iceseer): do remove std::optional ParachainProcessorImpl::group_for_para( const std::vector &availability_cores, @@ -4613,6 +4609,7 @@ namespace kagome::parachain { our_current_state_.validator_side.fetched_candidates.erase(it); /// TODO(iceseer): reduce collator's reputation + /// https://github.com/qdrvm/kagome/issues/2134 dequeue_next_collation_and_fetch(parent, {id, candidate_hash}); } diff --git a/core/parachain/validator/parachain_processor.hpp b/core/parachain/validator/parachain_processor.hpp index 296aac36f4..8a52c7026a 100644 --- a/core/parachain/validator/parachain_processor.hpp +++ b/core/parachain/validator/parachain_processor.hpp @@ -372,6 +372,7 @@ namespace kagome::parachain { }; } + /// polkadot/node/network/statement-distribution/src/v2/mod.rs struct ActiveValidatorState { // The index of the validator. ValidatorIndex index; @@ -1065,6 +1066,8 @@ namespace kagome::parachain { void printStoragesLoad(); + /// Handle a fetched collation result. + /// polkadot/node/network/collator-protocol/src/validator_side/mod.rs outcome::result kick_off_seconding( network::PendingCollationFetch &&pending_collation_fetch); diff --git a/test/core/parachain/prospective_parachains.cpp b/test/core/parachain/prospective_parachains.cpp index eb3dbf3023..c6f8c7c298 100644 --- a/test/core/parachain/prospective_parachains.cpp +++ b/test/core/parachain/prospective_parachains.cpp @@ -3148,6 +3148,7 @@ TEST_F(ProspectiveParachainsTest, Candidates_testHypotheticalFrontiers) { } } +/// polkadot/node/network/statement-distribution/src/v2/statement_store.rs TEST_F(ProspectiveParachainsTest, StatementsStore_always_provides_fresh_statements_in_order) { const ValidatorIndex validator_a{1}; From 01d7020c18414b845dd6bde9707c08ca1384ce83 Mon Sep 17 00:00:00 2001 From: iceseer Date: Thu, 20 Jun 2024 12:05:04 +0300 Subject: [PATCH 71/71] issues Signed-off-by: iceseer --- core/parachain/availability/store/store_impl.hpp | 1 + core/parachain/backing/store.hpp | 1 + core/parachain/validator/collations.hpp | 1 + 3 files changed, 3 insertions(+) diff --git a/core/parachain/availability/store/store_impl.hpp b/core/parachain/availability/store/store_impl.hpp index 23984f1fe2..861aa2bc88 100644 --- a/core/parachain/availability/store/store_impl.hpp +++ b/core/parachain/availability/store/store_impl.hpp @@ -10,6 +10,7 @@ #include #include +#include "log/logger.hpp" #include "utils/safe_object.hpp" namespace kagome::parachain { diff --git a/core/parachain/backing/store.hpp b/core/parachain/backing/store.hpp index 1f1ce48d60..3e5f2f49d6 100644 --- a/core/parachain/backing/store.hpp +++ b/core/parachain/backing/store.hpp @@ -7,6 +7,7 @@ #pragma once #include "common/tagged.hpp" +#include "log/logger.hpp" #include "network/types/collator_messages.hpp" namespace kagome::parachain { diff --git a/core/parachain/validator/collations.hpp b/core/parachain/validator/collations.hpp index 73cb9b0658..dc9f3d452e 100644 --- a/core/parachain/validator/collations.hpp +++ b/core/parachain/validator/collations.hpp @@ -12,6 +12,7 @@ #include #include "crypto/type_hasher.hpp" +#include "log/logger.hpp" #include "network/types/collator_messages.hpp" #include "parachain/types.hpp" #include "runtime/runtime_api/parachain_host_types.hpp"