From fed30fbf84b6e366311155ed610ef0d05e9db9c3 Mon Sep 17 00:00:00 2001 From: iceseer Date: Tue, 8 Aug 2023 11:13:18 +0300 Subject: [PATCH 01/38] session info request Signed-off-by: iceseer --- .../approval/approval_distribution.cpp | 39 ++++++++++++++++++- 1 file changed, 37 insertions(+), 2 deletions(-) diff --git a/core/parachain/approval/approval_distribution.cpp b/core/parachain/approval/approval_distribution.cpp index 9520e1ac78..b584880434 100644 --- a/core/parachain/approval/approval_distribution.cpp +++ b/core/parachain/approval/approval_distribution.cpp @@ -1268,7 +1268,25 @@ namespace kagome::parachain { GET_OPT_VALUE_OR_EXIT(block_entry, AssignmentCheckResult::Bad, storedBlockEntries().get(assignment.block_hash)); - auto &session_info = block_entry.session_info; + + std::optional opt_session_info{}; + if (auto session_info_res = parachain_host_->session_info(block_entry.parent_hash, block_entry.session); session_info_res.has_value()) { + opt_session_info = std::move(session_info_res.value()); + } else { + logger_->warn( + "Assignment. Session info runtime request failed. (parent_hash={}, session_index={}, error={})", + block_entry.parent_hash, block_entry.session, session_info_res.error().message()); + return AssignmentCheckResult::Bad; + } + + if (!opt_session_info) { + logger_->debug( + "Can't obtain SessionInfo. (parent_hash={}, session_index={})", + block_entry.parent_hash, block_entry.session); + return AssignmentCheckResult::Bad; + } + + runtime::SessionInfo &session_info = *opt_session_info; if (candidate_index >= block_entry.candidates.size()) { logger_->warn( "Candidate index more than candidates array.(candidate index={})", @@ -1348,7 +1366,24 @@ namespace kagome::parachain { block_entry, ApprovalCheckResult::Bad, storedBlockEntries().get(approval.payload.payload.block_hash)); - auto &session_info = block_entry.session_info; + std::optional opt_session_info{}; + if (auto session_info_res = parachain_host_->session_info(approval.payload.payload.block_hash, block_entry.session); session_info_res.has_value()) { + opt_session_info = std::move(session_info_res.value()); + } else { + logger_->warn( + "Approval. Session info runtime request failed. (block_hash={}, session_index={}, error={})", + approval.payload.payload.block_hash, block_entry.session, session_info_res.error().message()); + return ApprovalCheckResult::Bad; + } + + if (!opt_session_info) { + logger_->debug( + "Can't obtain SessionInfo. (parent_hash={}, session_index={})", + approval.payload.payload.block_hash, block_entry.session); + return ApprovalCheckResult::Bad; + } + + runtime::SessionInfo &session_info = *opt_session_info; if (approval.payload.payload.candidate_index >= block_entry.candidates.size()) { logger_->warn( From 888f829c436e25b99e7646c7f05bbe614533a575 Mon Sep 17 00:00:00 2001 From: iceseer Date: Tue, 8 Aug 2023 12:02:56 +0300 Subject: [PATCH 02/38] fixup Signed-off-by: iceseer --- .../approval/approval_distribution.cpp | 110 +++++++++++++++--- 1 file changed, 95 insertions(+), 15 deletions(-) diff --git a/core/parachain/approval/approval_distribution.cpp b/core/parachain/approval/approval_distribution.cpp index b584880434..e84324e317 100644 --- a/core/parachain/approval/approval_distribution.cpp +++ b/core/parachain/approval/approval_distribution.cpp @@ -764,7 +764,30 @@ namespace kagome::parachain { kagome::parachain::approval::ApprovalStatus>> ApprovalDistribution::approval_status(const BlockEntry &block_entry, CandidateEntry &candidate_entry) { - auto &session_info = block_entry.session_info; + std::optional opt_session_info{}; + if (auto session_info_res = parachain_host_->session_info( + block_entry.parent_hash, block_entry.session); + session_info_res.has_value()) { + opt_session_info = std::move(session_info_res.value()); + } else { + logger_->warn( + "Approval status. Session info runtime request failed. " + "(block_hash={}, session_index={}, error={})", + block_entry.parent_hash, + block_entry.session, + session_info_res.error().message()); + return std::nullopt; + } + + if (!opt_session_info) { + logger_->debug( + "Can't obtain SessionInfo. (parent_hash={}, session_index={})", + block_entry.parent_hash, + block_entry.session); + return std::nullopt; + } + + runtime::SessionInfo &session_info = *opt_session_info; const auto block_hash = block_entry.block_hash; const auto tranche_now = @@ -1270,20 +1293,26 @@ namespace kagome::parachain { storedBlockEntries().get(assignment.block_hash)); std::optional opt_session_info{}; - if (auto session_info_res = parachain_host_->session_info(block_entry.parent_hash, block_entry.session); session_info_res.has_value()) { + if (auto session_info_res = parachain_host_->session_info( + block_entry.parent_hash, block_entry.session); + session_info_res.has_value()) { opt_session_info = std::move(session_info_res.value()); } else { logger_->warn( - "Assignment. Session info runtime request failed. (parent_hash={}, session_index={}, error={})", - block_entry.parent_hash, block_entry.session, session_info_res.error().message()); - return AssignmentCheckResult::Bad; + "Assignment. Session info runtime request failed. (parent_hash={}, " + "session_index={}, error={})", + block_entry.parent_hash, + block_entry.session, + session_info_res.error().message()); + return AssignmentCheckResult::Bad; } if (!opt_session_info) { logger_->debug( "Can't obtain SessionInfo. (parent_hash={}, session_index={})", - block_entry.parent_hash, block_entry.session); - return AssignmentCheckResult::Bad; + block_entry.parent_hash, + block_entry.session); + return AssignmentCheckResult::Bad; } runtime::SessionInfo &session_info = *opt_session_info; @@ -1367,20 +1396,26 @@ namespace kagome::parachain { ApprovalCheckResult::Bad, storedBlockEntries().get(approval.payload.payload.block_hash)); std::optional opt_session_info{}; - if (auto session_info_res = parachain_host_->session_info(approval.payload.payload.block_hash, block_entry.session); session_info_res.has_value()) { + if (auto session_info_res = parachain_host_->session_info( + approval.payload.payload.block_hash, block_entry.session); + session_info_res.has_value()) { opt_session_info = std::move(session_info_res.value()); } else { logger_->warn( - "Approval. Session info runtime request failed. (block_hash={}, session_index={}, error={})", - approval.payload.payload.block_hash, block_entry.session, session_info_res.error().message()); - return ApprovalCheckResult::Bad; + "Approval. Session info runtime request failed. (block_hash={}, " + "session_index={}, error={})", + approval.payload.payload.block_hash, + block_entry.session, + session_info_res.error().message()); + return ApprovalCheckResult::Bad; } if (!opt_session_info) { logger_->debug( "Can't obtain SessionInfo. (parent_hash={}, session_index={})", - approval.payload.payload.block_hash, block_entry.session); - return ApprovalCheckResult::Bad; + approval.payload.payload.block_hash, + block_entry.session); + return ApprovalCheckResult::Bad; } runtime::SessionInfo &session_info = *opt_session_info; @@ -1851,7 +1886,30 @@ namespace kagome::parachain { return; } - auto &session_info = block_entry.session_info; + std::optional opt_session_info{}; + if (auto session_info_res = parachain_host_->session_info( + block_entry.parent_hash, block_entry.session); + session_info_res.has_value()) { + opt_session_info = std::move(session_info_res.value()); + } else { + logger_->warn( + "Issue approval. Session info runtime request failed. " + "(block_hash={}, session_index={}, error={})", + block_entry.parent_hash, + block_entry.session, + session_info_res.error().message()); + return; + } + + if (!opt_session_info) { + logger_->debug( + "Can't obtain SessionInfo. (parent_hash={}, session_index={})", + block_entry.parent_hash, + block_entry.session); + return; + } + + runtime::SessionInfo &session_info = *opt_session_info; if (*candidate_index >= block_entry.candidates.size()) { logger_->warn( "Received malformed request to approve out-of-bounds candidate index " @@ -2248,8 +2306,30 @@ namespace kagome::parachain { auto &block_entry = opt_block_entry->get(); auto &candidate_entry = opt_candidate_entry->get(); - auto &session_info = opt_block_entry->get().session_info; + std::optional opt_session_info{}; + if (auto session_info_res = parachain_host_->session_info( + block_entry.parent_hash, block_entry.session); + session_info_res.has_value()) { + opt_session_info = std::move(session_info_res.value()); + } else { + logger_->warn( + "Handle tranche. Session info runtime request failed. " + "(block_hash={}, session_index={}, error={})", + block_entry.parent_hash, + block_entry.session, + session_info_res.error().message()); + return; + } + if (!opt_session_info) { + logger_->debug( + "Can't obtain SessionInfo. (parent_hash={}, session_index={})", + block_entry.parent_hash, + block_entry.session); + return; + } + + runtime::SessionInfo &session_info = *opt_session_info; const auto block_tick = slotNumberToTick(config_.slot_duration_millis, block_entry.slot); const auto no_show_duration = slotNumberToTick(config_.slot_duration_millis, From 92412bb132f8a86d4b543c52c5ba8efb821c5ea0 Mon Sep 17 00:00:00 2001 From: iceseer Date: Tue, 8 Aug 2023 12:36:49 +0300 Subject: [PATCH 03/38] Revert "fixup" This reverts commit 459bce90c3c9181e4edaff1bf00eb0425cdc02ba. --- .../approval/approval_distribution.cpp | 110 +++--------------- 1 file changed, 15 insertions(+), 95 deletions(-) diff --git a/core/parachain/approval/approval_distribution.cpp b/core/parachain/approval/approval_distribution.cpp index e84324e317..b584880434 100644 --- a/core/parachain/approval/approval_distribution.cpp +++ b/core/parachain/approval/approval_distribution.cpp @@ -764,30 +764,7 @@ namespace kagome::parachain { kagome::parachain::approval::ApprovalStatus>> ApprovalDistribution::approval_status(const BlockEntry &block_entry, CandidateEntry &candidate_entry) { - std::optional opt_session_info{}; - if (auto session_info_res = parachain_host_->session_info( - block_entry.parent_hash, block_entry.session); - session_info_res.has_value()) { - opt_session_info = std::move(session_info_res.value()); - } else { - logger_->warn( - "Approval status. Session info runtime request failed. " - "(block_hash={}, session_index={}, error={})", - block_entry.parent_hash, - block_entry.session, - session_info_res.error().message()); - return std::nullopt; - } - - if (!opt_session_info) { - logger_->debug( - "Can't obtain SessionInfo. (parent_hash={}, session_index={})", - block_entry.parent_hash, - block_entry.session); - return std::nullopt; - } - - runtime::SessionInfo &session_info = *opt_session_info; + auto &session_info = block_entry.session_info; const auto block_hash = block_entry.block_hash; const auto tranche_now = @@ -1293,26 +1270,20 @@ namespace kagome::parachain { storedBlockEntries().get(assignment.block_hash)); std::optional opt_session_info{}; - if (auto session_info_res = parachain_host_->session_info( - block_entry.parent_hash, block_entry.session); - session_info_res.has_value()) { + if (auto session_info_res = parachain_host_->session_info(block_entry.parent_hash, block_entry.session); session_info_res.has_value()) { opt_session_info = std::move(session_info_res.value()); } else { logger_->warn( - "Assignment. Session info runtime request failed. (parent_hash={}, " - "session_index={}, error={})", - block_entry.parent_hash, - block_entry.session, - session_info_res.error().message()); - return AssignmentCheckResult::Bad; + "Assignment. Session info runtime request failed. (parent_hash={}, session_index={}, error={})", + block_entry.parent_hash, block_entry.session, session_info_res.error().message()); + return AssignmentCheckResult::Bad; } if (!opt_session_info) { logger_->debug( "Can't obtain SessionInfo. (parent_hash={}, session_index={})", - block_entry.parent_hash, - block_entry.session); - return AssignmentCheckResult::Bad; + block_entry.parent_hash, block_entry.session); + return AssignmentCheckResult::Bad; } runtime::SessionInfo &session_info = *opt_session_info; @@ -1396,26 +1367,20 @@ namespace kagome::parachain { ApprovalCheckResult::Bad, storedBlockEntries().get(approval.payload.payload.block_hash)); std::optional opt_session_info{}; - if (auto session_info_res = parachain_host_->session_info( - approval.payload.payload.block_hash, block_entry.session); - session_info_res.has_value()) { + if (auto session_info_res = parachain_host_->session_info(approval.payload.payload.block_hash, block_entry.session); session_info_res.has_value()) { opt_session_info = std::move(session_info_res.value()); } else { logger_->warn( - "Approval. Session info runtime request failed. (block_hash={}, " - "session_index={}, error={})", - approval.payload.payload.block_hash, - block_entry.session, - session_info_res.error().message()); - return ApprovalCheckResult::Bad; + "Approval. Session info runtime request failed. (block_hash={}, session_index={}, error={})", + approval.payload.payload.block_hash, block_entry.session, session_info_res.error().message()); + return ApprovalCheckResult::Bad; } if (!opt_session_info) { logger_->debug( "Can't obtain SessionInfo. (parent_hash={}, session_index={})", - approval.payload.payload.block_hash, - block_entry.session); - return ApprovalCheckResult::Bad; + approval.payload.payload.block_hash, block_entry.session); + return ApprovalCheckResult::Bad; } runtime::SessionInfo &session_info = *opt_session_info; @@ -1886,30 +1851,7 @@ namespace kagome::parachain { return; } - std::optional opt_session_info{}; - if (auto session_info_res = parachain_host_->session_info( - block_entry.parent_hash, block_entry.session); - session_info_res.has_value()) { - opt_session_info = std::move(session_info_res.value()); - } else { - logger_->warn( - "Issue approval. Session info runtime request failed. " - "(block_hash={}, session_index={}, error={})", - block_entry.parent_hash, - block_entry.session, - session_info_res.error().message()); - return; - } - - if (!opt_session_info) { - logger_->debug( - "Can't obtain SessionInfo. (parent_hash={}, session_index={})", - block_entry.parent_hash, - block_entry.session); - return; - } - - runtime::SessionInfo &session_info = *opt_session_info; + auto &session_info = block_entry.session_info; if (*candidate_index >= block_entry.candidates.size()) { logger_->warn( "Received malformed request to approve out-of-bounds candidate index " @@ -2306,30 +2248,8 @@ namespace kagome::parachain { auto &block_entry = opt_block_entry->get(); auto &candidate_entry = opt_candidate_entry->get(); - std::optional opt_session_info{}; - if (auto session_info_res = parachain_host_->session_info( - block_entry.parent_hash, block_entry.session); - session_info_res.has_value()) { - opt_session_info = std::move(session_info_res.value()); - } else { - logger_->warn( - "Handle tranche. Session info runtime request failed. " - "(block_hash={}, session_index={}, error={})", - block_entry.parent_hash, - block_entry.session, - session_info_res.error().message()); - return; - } + auto &session_info = opt_block_entry->get().session_info; - if (!opt_session_info) { - logger_->debug( - "Can't obtain SessionInfo. (parent_hash={}, session_index={})", - block_entry.parent_hash, - block_entry.session); - return; - } - - runtime::SessionInfo &session_info = *opt_session_info; const auto block_tick = slotNumberToTick(config_.slot_duration_millis, block_entry.slot); const auto no_show_duration = slotNumberToTick(config_.slot_duration_millis, From 05cec5ef839654e8486638d8349d08436ed926a7 Mon Sep 17 00:00:00 2001 From: iceseer Date: Tue, 8 Aug 2023 12:36:55 +0300 Subject: [PATCH 04/38] Revert "session info request" This reverts commit 7abbaf33b1f9aa222adc8ae38c4844ba57e5fe59. --- .../approval/approval_distribution.cpp | 39 +------------------ 1 file changed, 2 insertions(+), 37 deletions(-) diff --git a/core/parachain/approval/approval_distribution.cpp b/core/parachain/approval/approval_distribution.cpp index b584880434..9520e1ac78 100644 --- a/core/parachain/approval/approval_distribution.cpp +++ b/core/parachain/approval/approval_distribution.cpp @@ -1268,25 +1268,7 @@ namespace kagome::parachain { GET_OPT_VALUE_OR_EXIT(block_entry, AssignmentCheckResult::Bad, storedBlockEntries().get(assignment.block_hash)); - - std::optional opt_session_info{}; - if (auto session_info_res = parachain_host_->session_info(block_entry.parent_hash, block_entry.session); session_info_res.has_value()) { - opt_session_info = std::move(session_info_res.value()); - } else { - logger_->warn( - "Assignment. Session info runtime request failed. (parent_hash={}, session_index={}, error={})", - block_entry.parent_hash, block_entry.session, session_info_res.error().message()); - return AssignmentCheckResult::Bad; - } - - if (!opt_session_info) { - logger_->debug( - "Can't obtain SessionInfo. (parent_hash={}, session_index={})", - block_entry.parent_hash, block_entry.session); - return AssignmentCheckResult::Bad; - } - - runtime::SessionInfo &session_info = *opt_session_info; + auto &session_info = block_entry.session_info; if (candidate_index >= block_entry.candidates.size()) { logger_->warn( "Candidate index more than candidates array.(candidate index={})", @@ -1366,24 +1348,7 @@ namespace kagome::parachain { block_entry, ApprovalCheckResult::Bad, storedBlockEntries().get(approval.payload.payload.block_hash)); - std::optional opt_session_info{}; - if (auto session_info_res = parachain_host_->session_info(approval.payload.payload.block_hash, block_entry.session); session_info_res.has_value()) { - opt_session_info = std::move(session_info_res.value()); - } else { - logger_->warn( - "Approval. Session info runtime request failed. (block_hash={}, session_index={}, error={})", - approval.payload.payload.block_hash, block_entry.session, session_info_res.error().message()); - return ApprovalCheckResult::Bad; - } - - if (!opt_session_info) { - logger_->debug( - "Can't obtain SessionInfo. (parent_hash={}, session_index={})", - approval.payload.payload.block_hash, block_entry.session); - return ApprovalCheckResult::Bad; - } - - runtime::SessionInfo &session_info = *opt_session_info; + auto &session_info = block_entry.session_info; if (approval.payload.payload.candidate_index >= block_entry.candidates.size()) { logger_->warn( From 3d2036dd7e6256c988115455e4b851a27cad85eb Mon Sep 17 00:00:00 2001 From: iceseer Date: Tue, 8 Aug 2023 13:56:43 +0300 Subject: [PATCH 05/38] log Signed-off-by: iceseer --- core/parachain/approval/approval_distribution.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/core/parachain/approval/approval_distribution.cpp b/core/parachain/approval/approval_distribution.cpp index 9520e1ac78..28a12acb7b 100644 --- a/core/parachain/approval/approval_distribution.cpp +++ b/core/parachain/approval/approval_distribution.cpp @@ -1464,6 +1464,10 @@ namespace kagome::parachain { switch ( check_and_import_assignment(assignment, claimed_candidate_index)) { case AssignmentCheckResult::Accepted: + SL_TRACE(logger_, + "Assignment accepted. (peer id={}, block hash={})", + source->get(), + block_hash); break; case AssignmentCheckResult::Bad: SL_WARN(logger_, From 74223f3e065d66e2755576ab01e2867f29b0af5a Mon Sep 17 00:00:00 2001 From: iceseer Date: Wed, 9 Aug 2023 21:44:58 +0300 Subject: [PATCH 06/38] knowledge # Conflicts: # core/parachain/approval/approval_distribution.hpp --- .../approval/approval_distribution.cpp | 18 +++- .../approval/approval_distribution.hpp | 11 ++- core/parachain/approval/knowledge.hpp | 83 +++++++++++++++++++ 3 files changed, 109 insertions(+), 3 deletions(-) create mode 100644 core/parachain/approval/knowledge.hpp diff --git a/core/parachain/approval/approval_distribution.cpp b/core/parachain/approval/approval_distribution.cpp index 28a12acb7b..9fef672b9e 100644 --- a/core/parachain/approval/approval_distribution.cpp +++ b/core/parachain/approval/approval_distribution.cpp @@ -1018,6 +1018,8 @@ namespace kagome::parachain { storedDistribBlockEntries().set(meta.hash, DistribBlockEntry{ .candidates = std::move(candidates), + .knowledge = {}, + .known_by = {}, }); } @@ -1459,8 +1461,22 @@ namespace kagome::parachain { } } + auto message_subject{ + std::make_tuple(block_hash, claimed_candidate_index, validator_index)}; + approval::MessageKindAssignment message_kind{}; + if (source) { - /// TODO(iceseer): vector-clock for knowledge + /// if the assignment is known to be valid, reward the peer + if (entry.knowledge.contains(message_subject, message_kind)) { + /// TODO(iceseer): modify reputation + const auto &peer_id = source->get(); + if (auto it = entry.known_by.find(peer_id); + it != entry.known_by.end()) { + SL_TRACE(logger_, "Known assignment. (peer id={})", peer_id); + it->second.received.insert(message_subject, message_kind); + } + } + switch ( check_and_import_assignment(assignment, claimed_candidate_index)) { case AssignmentCheckResult::Accepted: diff --git a/core/parachain/approval/approval_distribution.hpp b/core/parachain/approval/approval_distribution.hpp index af734966f9..9730844ae3 100644 --- a/core/parachain/approval/approval_distribution.hpp +++ b/core/parachain/approval/approval_distribution.hpp @@ -26,6 +26,7 @@ #include "network/peer_view.hpp" #include "network/types/collator_messages.hpp" #include "parachain/approval/approved_ancestor.hpp" +#include "parachain/approval/knowledge.hpp" #include "parachain/approval/store.hpp" #include "parachain/availability/recovery/recovery.hpp" #include "parachain/validator/parachain_processor.hpp" @@ -351,14 +352,20 @@ namespace kagome::parachain { /// for the same candidate, if it is included by multiple blocks - this is /// likely the case when there are forks. struct DistribCandidateEntry { - std::unordered_map messages; + std::unordered_map messages{}; }; /// Information about blocks in our current view as well as whether peers /// know of them. struct DistribBlockEntry { /// A votes entry for each candidate indexed by [`CandidateIndex`]. - std::vector candidates; + std::vector candidates{}; + /// Our knowledge of messages. + approval::Knowledge knowledge{}; + /// Peers who we know are aware of this block and thus, the candidates + /// within it. This maps to their knowledge of messages. + std::unordered_map + known_by{}; }; /// Metadata regarding approval of a particular block, by way of approval of diff --git a/core/parachain/approval/knowledge.hpp b/core/parachain/approval/knowledge.hpp new file mode 100644 index 0000000000..d8f509d2dc --- /dev/null +++ b/core/parachain/approval/knowledge.hpp @@ -0,0 +1,83 @@ +/** + * Copyright Soramitsu Co., Ltd. All Rights Reserved. + * SPDX-License-Identifier: Apache-2.0 + */ + +#ifndef KAGOME_KNOWLEDGE_HPP +#define KAGOME_KNOWLEDGE_HPP + +#include + +#include "common/visitor.hpp" +#include "consensus/babe/common.hpp" +#include "consensus/validation/prepare_transcript.hpp" +#include "outcome/outcome.hpp" +#include "parachain/approval/state.hpp" +#include "parachain/types.hpp" + +namespace kagome::parachain::approval { + + struct MessageKindAssignment {}; + struct MessageKindApproval {}; + using MessageKind = + boost::variant; + using MessageSubject = std::tuple; + + struct MessageSubjectHash { + auto operator()(const MessageSubject &obj) const { + size_t value{0ull}; + std::apply( + [&](const auto &...v) { (..., boost::hash_combine(value, v)); }, obj); + return value; + } + }; + + struct Knowledge { + // When there is no entry, this means the message is unknown + // When there is an entry with `MessageKind::Assignment`, the assignment is + // known. When there is an entry with `MessageKind::Approval`, the + // assignment and approval are known. + std::unordered_map + known_messages{}; + + bool contains(const MessageSubject &message, + const MessageKind &kind) const { + auto it = known_messages.find(message); + if (it == known_messages.end()) { + return false; + } + if (is_type(kind)) { + return true; + } + return is_type(it->second); + } + + bool insert(const MessageSubject &message, const MessageKind &kind) { + const auto &[it, inserted] = known_messages.emplace(message, kind); + if (inserted) { + return true; + } + if (is_type(it->second) + && is_type(kind)) { + it->second = MessageKindApproval{}; + return true; + } + return false; + } + }; + + struct PeerKnowledge { + /// The knowledge we've sent to the peer. + Knowledge sent{}; + /// The knowledge we've received from the peer. + Knowledge received{}; + + bool contains(const MessageSubject &message, + const MessageKind &kind) const { + return sent.contains(message, kind) || received.contains(message, kind); + } + }; + +} // namespace kagome::parachain::approval + +#endif // KAGOME_KNOWLEDGE_HPP From cb5c9101bbb417a316878c2264e64580de466071 Mon Sep 17 00:00:00 2001 From: iceseer Date: Wed, 9 Aug 2023 23:25:40 +0300 Subject: [PATCH 07/38] knowledge --- .../approval/approval_distribution.cpp | 154 +++++++++++++++--- .../approval/approval_distribution.hpp | 4 +- 2 files changed, 133 insertions(+), 25 deletions(-) diff --git a/core/parachain/approval/approval_distribution.cpp b/core/parachain/approval/approval_distribution.cpp index 9fef672b9e..937bfc2826 100644 --- a/core/parachain/approval/approval_distribution.cpp +++ b/core/parachain/approval/approval_distribution.cpp @@ -1466,10 +1466,10 @@ namespace kagome::parachain { approval::MessageKindAssignment message_kind{}; if (source) { + const auto &peer_id = source->get(); /// if the assignment is known to be valid, reward the peer if (entry.knowledge.contains(message_subject, message_kind)) { /// TODO(iceseer): modify reputation - const auto &peer_id = source->get(); if (auto it = entry.known_by.find(peer_id); it != entry.known_by.end()) { SL_TRACE(logger_, "Known assignment. (peer id={})", peer_id); @@ -1479,35 +1479,57 @@ namespace kagome::parachain { switch ( check_and_import_assignment(assignment, claimed_candidate_index)) { - case AssignmentCheckResult::Accepted: + case AssignmentCheckResult::Accepted: { SL_TRACE(logger_, "Assignment accepted. (peer id={}, block hash={})", source->get(), block_hash); - break; - case AssignmentCheckResult::Bad: + entry.knowledge.known_messages[message_subject] = message_kind; + if (auto it = entry.known_by.find(peer_id); + it != entry.known_by.end()) { + it->second.received.insert(message_subject, message_kind); + } + } break; + case AssignmentCheckResult::Bad: { SL_WARN(logger_, "Got bad assignment from peer. (peer id={}, block hash={})", source->get(), block_hash); + } return; - case AssignmentCheckResult::TooFarInFuture: + case AssignmentCheckResult::TooFarInFuture: { SL_TRACE( logger_, "Got an assignment too far in the future. (peer id={}, block " "hash={})", source->get(), block_hash); + } return; - case AssignmentCheckResult::AcceptedDuplicate: + case AssignmentCheckResult::AcceptedDuplicate: { SL_TRACE(logger_, "Got duplicated assignment. (peer id={}, block hash={})", source->get(), block_hash); + } return; } } else { - /// TODO(iceseer): vector-clock for knowledge + if (!entry.knowledge.insert(message_subject, message_kind)) { + SL_WARN(logger_, + "Importing locally an already known assignment. " + "(block_hash={}, candidate index={}, validator index={})", + std::get<0>(message_subject), + std::get<1>(message_subject), + std::get<2>(message_subject)); + return; + } + SL_TRACE(logger_, + "Importing locally a new assignment. (block_hash={}, candidate " + "index={}, validator index={})", + std::get<0>(message_subject), + std::get<1>(message_subject), + std::get<2>(message_subject)); } const auto local = !source; @@ -1576,20 +1598,77 @@ namespace kagome::parachain { } } + auto message_subject{ + std::make_tuple(block_hash, candidate_index, validator_index)}; + approval::MessageKindApproval message_kind{}; + if (source) { - /// TODO(iceseer): vector-clock for knowledge + const auto &peer_id = source->get(); + if (!entry.knowledge.contains(message_subject, + approval::MessageKindAssignment{})) { + SL_TRACE(logger_, + "Unknown approval assignment. (peer id={}, block hash={}, " + "candidate={}, validator={})", + peer_id, + std::get<0>(message_subject), + std::get<1>(message_subject), + std::get<2>(message_subject)); + return; + } + + /// TODO(iceseer): known_by + + /// if the approval is known to be valid, reward the peer + if (entry.knowledge.contains(message_subject, message_kind)) { + SL_TRACE(logger_, + "Known approval. (peer id={}, block hash={}, " + "candidate={}, validator={})", + peer_id, + std::get<0>(message_subject), + std::get<1>(message_subject), + std::get<2>(message_subject)); + + if (auto it = entry.known_by.find(peer_id); + it != entry.known_by.end()) { + it->second.received.insert(message_subject, message_kind); + } + return; + } + switch (check_and_import_approval(vote)) { - case ApprovalCheckResult::Accepted: - break; - case ApprovalCheckResult::Bad: + case ApprovalCheckResult::Accepted: { + entry.knowledge.insert(message_subject, message_kind); + if (auto it = entry.known_by.find(peer_id); + it != entry.known_by.end()) { + it->second.received.insert(message_subject, message_kind); + } + } break; + case ApprovalCheckResult::Bad: { logger_->warn( - "Got bad approval from peer. (peer id={}, block hash={})", + "Got a bad approval from peer. (peer id={}, block hash={})", source->get(), block_hash); + } return; } } else { - /// TODO(iceseer): vector-clock for knowledge + if (!entry.knowledge.insert(message_subject, message_kind)) { + // if we already imported an approval, there is no need to distribute it + // again + SL_WARN(logger_, + "Importing locally an already known approval. " + "(block_hash={}, candidate index={}, validator index={})", + std::get<0>(message_subject), + std::get<1>(message_subject), + std::get<2>(message_subject)); + return; + } + SL_TRACE(logger_, + "Importing locally a new approval. (block_hash={}, candidate " + "index={}, validator index={})", + std::get<0>(message_subject), + std::get<1>(message_subject), + std::get<2>(message_subject)); } if (auto it = candidate_entry.messages.find(validator_index); @@ -1608,7 +1687,29 @@ namespace kagome::parachain { validator_index); return; } - runDistributeApproval(vote); + + auto peer_filter = [&](const auto &peer, const auto &peer_kn) { + if (source && peer == source->get()) { + return false; + } + return peer_kn.sent.contains(message_subject, + approval::MessageKindAssignment{}); + }; + + std::unordered_set peers{}; + for (const auto &[peer_id, peer_knowledge] : entry.known_by) { + if (peer_filter(peer_id, peer_knowledge)) { + peers.insert(peer_id); + if (auto it = entry.known_by.find(peer_id); + it != entry.known_by.end()) { + it->second.sent.insert(message_subject, message_kind); + } + } + } + + if (!peers.empty()) { + runDistributeApproval(vote, std::move(peers)); + } } void ApprovalDistribution::getApprovalSignaturesForCandidate( @@ -1788,23 +1889,28 @@ namespace kagome::parachain { } void ApprovalDistribution::runDistributeApproval( - const network::IndirectSignedApprovalVote &_vote) { - REINVOKE_1(this_context_, runDistributeApproval, _vote, vote); + const network::IndirectSignedApprovalVote &_vote, + std::unordered_set &&_peers) { + REINVOKE_2( + this_context_, runDistributeApproval, _vote, _peers, vote, peers); logger_->info( - "Distributing our approval vote on candidate (block={}, index={})", + "Sending an approval to peers. (block={}, index={}, num peers={})", vote.payload.payload.block_hash, - vote.payload.payload.candidate_index); + vote.payload.payload.candidate_index, + peers.size()); auto se = pm_->getStreamEngine(); BOOST_ASSERT(se); - se->broadcast(router_->getValidationProtocol(), - std::make_shared< - network::WireMessage>( - network::ApprovalDistributionMessage{network::Approvals{ - .approvals = {vote}, - }})); + se->broadcast( + router_->getValidationProtocol(), + std::make_shared< + network::WireMessage>( + network::ApprovalDistributionMessage{network::Approvals{ + .approvals = {vote}, + }}), + [&](const libp2p::peer::PeerId &p) { return peers.count(p) != 0ull; }); } void ApprovalDistribution::issue_approval(const CandidateHash &can_hash, diff --git a/core/parachain/approval/approval_distribution.hpp b/core/parachain/approval/approval_distribution.hpp index 9730844ae3..067660b986 100644 --- a/core/parachain/approval/approval_distribution.hpp +++ b/core/parachain/approval/approval_distribution.hpp @@ -613,7 +613,9 @@ namespace kagome::parachain { const approval::IndirectAssignmentCert &indirect_cert, CandidateIndex candidate_index); - void runDistributeApproval(const network::IndirectSignedApprovalVote &vote); + void runDistributeApproval( + const network::IndirectSignedApprovalVote &vote, + std::unordered_set &&peers); void runScheduleWakeup(const primitives::BlockHash &block_hash, primitives::BlockNumber block_number, From c0354aac3d11627cb69b511bd8cd6d21566926b8 Mon Sep 17 00:00:00 2001 From: iceseer Date: Thu, 10 Aug 2023 00:14:49 +0300 Subject: [PATCH 08/38] known_by --- .../approval/approval_distribution.cpp | 28 +++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/core/parachain/approval/approval_distribution.cpp b/core/parachain/approval/approval_distribution.cpp index 937bfc2826..cd1491ccdf 100644 --- a/core/parachain/approval/approval_distribution.cpp +++ b/core/parachain/approval/approval_distribution.cpp @@ -544,6 +544,9 @@ namespace kagome::parachain { internal_context_->start(); thread_pool_context_->start(); this_context_.start(); + + /// TODO(iceseer): clear `known_by` when peer disconnected + return true; } @@ -1467,6 +1470,31 @@ namespace kagome::parachain { if (source) { const auto &peer_id = source->get(); + + if (auto it = entry.known_by.find(peer_id); it != entry.known_by.end()) { + if (auto &peer_knowledge = it->second; + peer_knowledge.contains(message_subject, message_kind)) { + if (!peer_knowledge.received.insert(message_subject, message_kind)) { + SL_TRACE(logger_, + "Duplicate assignment. (peer id={}, block_hash={}, " + "candidate index={}, validator index={})", + peer_id, + std::get<0>(message_subject), + std::get<1>(message_subject), + std::get<2>(message_subject)); + } + return; + } + } else { + SL_WARN(logger_, + "Assignment from a peer is out of view. (peer id={}, " + "block_hash={}, candidate index={}, validator index={})", + peer_id, + std::get<0>(message_subject), + std::get<1>(message_subject), + std::get<2>(message_subject)); + } + /// if the assignment is known to be valid, reward the peer if (entry.knowledge.contains(message_subject, message_kind)) { /// TODO(iceseer): modify reputation From 5b50e2a31bd8a362bfd5ac092cf7aaa5d7949835 Mon Sep 17 00:00:00 2001 From: iceseer Date: Thu, 10 Aug 2023 00:40:35 +0300 Subject: [PATCH 09/38] known_by --- .../approval/approval_distribution.cpp | 64 +++++++++++++++---- .../approval/approval_distribution.hpp | 3 +- 2 files changed, 53 insertions(+), 14 deletions(-) diff --git a/core/parachain/approval/approval_distribution.cpp b/core/parachain/approval/approval_distribution.cpp index cd1491ccdf..05b956f060 100644 --- a/core/parachain/approval/approval_distribution.cpp +++ b/core/parachain/approval/approval_distribution.cpp @@ -1535,8 +1535,14 @@ namespace kagome::parachain { } return; case AssignmentCheckResult::AcceptedDuplicate: { + if (auto it = entry.known_by.find(peer_id); + it != entry.known_by.end()) { + auto &peer_knowledge = it->second; + peer_knowledge.received.insert(message_subject, message_kind); + } SL_TRACE(logger_, - "Got duplicated assignment. (peer id={}, block hash={})", + "Got an `AcceptedDuplicate` assignment. (peer id={}, block " + "hash={})", source->get(), block_hash); } @@ -1570,7 +1576,34 @@ namespace kagome::parachain { }) .first->second; - runDistributeAssignment(assignment, claimed_candidate_index); + auto peer_filter = [&](const auto &peer, const auto &peer_kn) { + if (source && peer == source->get()) { + return false; + } + + const bool already_sent = + peer_kn.sent.contains(message_subject, + approval::MessageKindAssignment{}) + || peer_kn.sent.contains(message_subject, + approval::MessageKindApproval{}); + return !already_sent; + }; + + std::unordered_set peers{}; + for (const auto &[peer_id, peer_knowledge] : entry.known_by) { + if (peer_filter(peer_id, peer_knowledge)) { + peers.insert(peer_id); + if (auto it = entry.known_by.find(peer_id); + it != entry.known_by.end()) { + it->second.sent.insert(message_subject, message_kind); + } + } + } + + if (!peers.empty()) { + runDistributeAssignment( + assignment, claimed_candidate_index, std::move(peers)); + } } void ApprovalDistribution::import_and_circulate_approval( @@ -1889,13 +1922,16 @@ namespace kagome::parachain { void ApprovalDistribution::runDistributeAssignment( const approval::IndirectAssignmentCert &_indirect_cert, - CandidateIndex _candidate_index) { - REINVOKE_2(this_context_, + CandidateIndex _candidate_index, + std::unordered_set &&_peers) { + REINVOKE_3(this_context_, runDistributeAssignment, _indirect_cert, _candidate_index, + _peers, indirect_cert, - candidate_index); + candidate_index, + peers); logger_->info( "Distributing assignment on candidate (block hash={}, candidate " @@ -1906,14 +1942,16 @@ namespace kagome::parachain { auto se = pm_->getStreamEngine(); BOOST_ASSERT(se); - se->broadcast(router_->getValidationProtocol(), - std::make_shared< - network::WireMessage>( - network::ApprovalDistributionMessage{network::Assignments{ - .assignments = {network::Assignment{ - .indirect_assignment_cert = indirect_cert, - .candidate_ix = candidate_index, - }}}})); + se->broadcast( + router_->getValidationProtocol(), + std::make_shared< + network::WireMessage>( + network::ApprovalDistributionMessage{network::Assignments{ + .assignments = {network::Assignment{ + .indirect_assignment_cert = indirect_cert, + .candidate_ix = candidate_index, + }}}}), + [&](const libp2p::peer::PeerId &p) { return peers.count(p) != 0ull; }); } void ApprovalDistribution::runDistributeApproval( diff --git a/core/parachain/approval/approval_distribution.hpp b/core/parachain/approval/approval_distribution.hpp index 067660b986..79a27cd92c 100644 --- a/core/parachain/approval/approval_distribution.hpp +++ b/core/parachain/approval/approval_distribution.hpp @@ -611,7 +611,8 @@ namespace kagome::parachain { void runDistributeAssignment( const approval::IndirectAssignmentCert &indirect_cert, - CandidateIndex candidate_index); + CandidateIndex candidate_index, + std::unordered_set &&peers); void runDistributeApproval( const network::IndirectSignedApprovalVote &vote, From 4f6287c8a8b46b19adb936f2281249bfb80dd9df Mon Sep 17 00:00:00 2001 From: iceseer Date: Thu, 10 Aug 2023 00:49:26 +0300 Subject: [PATCH 10/38] known_by --- .../approval/approval_distribution.cpp | 25 ++++++++++++++++++- 1 file changed, 24 insertions(+), 1 deletion(-) diff --git a/core/parachain/approval/approval_distribution.cpp b/core/parachain/approval/approval_distribution.cpp index 05b956f060..122e23f720 100644 --- a/core/parachain/approval/approval_distribution.cpp +++ b/core/parachain/approval/approval_distribution.cpp @@ -1677,7 +1677,30 @@ namespace kagome::parachain { return; } - /// TODO(iceseer): known_by + // check if our knowledge of the peer already contains this approval + if (auto it = entry.known_by.find(peer_id); it != entry.known_by.end()) { + if (auto &peer_knowledge = it->second; + peer_knowledge.contains(message_subject, message_kind)) { + if (!peer_knowledge.received.insert(message_subject, message_kind)) { + SL_TRACE(logger_, + "Duplicate approval. (peer id={}, block_hash={}, " + "candidate index={}, validator index={})", + peer_id, + std::get<0>(message_subject), + std::get<1>(message_subject), + std::get<2>(message_subject)); + } + return; + } + } else { + SL_TRACE(logger_, + "Approval from a peer is out of view. (peer id={}, " + "block_hash={}, candidate index={}, validator index={})", + peer_id, + std::get<0>(message_subject), + std::get<1>(message_subject), + std::get<2>(message_subject)); + } /// if the approval is known to be valid, reward the peer if (entry.knowledge.contains(message_subject, message_kind)) { From 708834c8e17b5d622821517152ef28253453fe9a Mon Sep 17 00:00:00 2001 From: iceseer Date: Thu, 10 Aug 2023 11:26:35 +0300 Subject: [PATCH 11/38] fixup! Signed-off-by: iceseer --- core/parachain/approval/approval_distribution.cpp | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/core/parachain/approval/approval_distribution.cpp b/core/parachain/approval/approval_distribution.cpp index 122e23f720..e4630f9e91 100644 --- a/core/parachain/approval/approval_distribution.cpp +++ b/core/parachain/approval/approval_distribution.cpp @@ -52,9 +52,9 @@ OUTCOME_CPP_DEFINE_CATEGORY(kagome::parachain, ApprovalDistribution::Error, e) { return "Unknown approval-distribution error"; } -static constexpr uint64_t kTickDurationMs = 500; -static constexpr kagome::network::Tick kApprovalDelay = 2; -static constexpr kagome::network::Tick kTickTooFarInFuture = 20; // 10 seconds. +static constexpr uint64_t kTickDurationMs = 500ull; +static constexpr kagome::network::Tick kApprovalDelay = 2ull; +static constexpr kagome::network::Tick kTickTooFarInFuture = 20ull; // 10 seconds. namespace { @@ -262,9 +262,7 @@ namespace { auto const is_no_show = !has_approved && no_show_at <= drifted_tick_now; if (!is_no_show && !has_approved) { - next_no_show = - std::min(no_show_at + clock_drift, - next_no_show ? *next_no_show : uint64_t{0ull}); + next_no_show = kagome::parachain::approval::min_or_some(next_no_show, std::make_optional(no_show_at + clock_drift)); } if (is_no_show) { ++no_shows; From 6a6171f8efee4ef59ef3e66c84b306abc034ac80 Mon Sep 17 00:00:00 2001 From: Dmitriy Khaustov aka xDimon Date: Fri, 11 Aug 2023 11:30:56 +0300 Subject: [PATCH 12/38] fix from Alex --- core/parachain/approval/approval_distribution.cpp | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/core/parachain/approval/approval_distribution.cpp b/core/parachain/approval/approval_distribution.cpp index e4630f9e91..45003630e8 100644 --- a/core/parachain/approval/approval_distribution.cpp +++ b/core/parachain/approval/approval_distribution.cpp @@ -561,6 +561,7 @@ namespace kagome::parachain { lost); pending_known_.erase(lost); active_tranches_.erase(lost); + approving_context_map_.erase(lost); if (auto block_entry = storedBlockEntries().get(lost)) { for (const auto &candidate : block_entry->get().candidates) { @@ -1059,11 +1060,6 @@ namespace kagome::parachain { ->get_executor() .running_in_this_thread()); - /// clear unuseful heads - for (const auto &l_head : updated.lost) { - approving_context_map_.erase(l_head); - } - const auto block_number = updated.new_head.number; auto parent_hash{updated.new_head.parent_hash}; if (approving_context_map_.count(head) != 0ull) { From 323f725aff4239932ab72965e1b62821333eb15b Mon Sep 17 00:00:00 2001 From: iceseer Date: Tue, 15 Aug 2023 12:26:21 +0300 Subject: [PATCH 13/38] patch --- core/parachain/CMakeLists.txt | 1 + .../approval/approval_distribution.cpp | 207 +++++++++++---- .../approval/approval_distribution.hpp | 58 ++-- test/core/crypto/crypto_store/CMakeLists.txt | 1 + .../crypto/crypto_store/crypto_store_test.cpp | 247 ++++++++++++++++-- 5 files changed, 416 insertions(+), 98 deletions(-) diff --git a/core/parachain/CMakeLists.txt b/core/parachain/CMakeLists.txt index 3f59c0b936..a88ffd1f7c 100644 --- a/core/parachain/CMakeLists.txt +++ b/core/parachain/CMakeLists.txt @@ -25,4 +25,5 @@ target_link_libraries(validator_parachain crypto_store network erasure_coding_crust::ec-cpp + waitable_timer ) diff --git a/core/parachain/approval/approval_distribution.cpp b/core/parachain/approval/approval_distribution.cpp index 45003630e8..ed802d0b47 100644 --- a/core/parachain/approval/approval_distribution.cpp +++ b/core/parachain/approval/approval_distribution.cpp @@ -4,6 +4,7 @@ */ #include +#include #include "clock/impl/basic_waitable_timer.hpp" #include "common/visitor.hpp" @@ -17,6 +18,7 @@ #include "parachain/approval/approval_distribution.hpp" #include "parachain/approval/state.hpp" #include "primitives/authority.hpp" +#include "primitives/math.hpp" #include "runtime/runtime_api/parachain_host_types.hpp" #include "utils/async_sequence.hpp" #include "utils/weak_from_shared.hpp" @@ -54,7 +56,8 @@ OUTCOME_CPP_DEFINE_CATEGORY(kagome::parachain, ApprovalDistribution::Error, e) { static constexpr uint64_t kTickDurationMs = 500ull; static constexpr kagome::network::Tick kApprovalDelay = 2ull; -static constexpr kagome::network::Tick kTickTooFarInFuture = 20ull; // 10 seconds. +static constexpr kagome::network::Tick kTickTooFarInFuture = + 20ull; // 10 seconds. namespace { @@ -262,7 +265,8 @@ namespace { auto const is_no_show = !has_approved && no_show_at <= drifted_tick_now; if (!is_no_show && !has_approved) { - next_no_show = kagome::parachain::approval::min_or_some(next_no_show, std::make_optional(no_show_at + clock_drift)); + next_no_show = kagome::parachain::approval::min_or_some( + next_no_show, std::make_optional(no_show_at + clock_drift)); } if (is_no_show) { ++no_shows; @@ -588,7 +592,6 @@ namespace kagome::parachain { return std::make_pair((ValidatorIndex)ix, std::move(res.value())); } } - SL_TRACE(logger_, "No assignment key"); return std::nullopt; } @@ -600,22 +603,9 @@ namespace kagome::parachain { const CandidateIncludedList &leaving_cores) { if (config.n_cores == 0 || config.assignment_keys.empty() || config.validator_groups.empty()) { - SL_TRACE(logger_, - "Not producing assignments because config is degenerate " - "(n_cores:{}, has_assignment_keys:{}, has_validator_groups:{})", - config.n_cores, - config.assignment_keys.size(), - config.validator_groups.size()); return {}; } - SL_INFO(logger_, - "Compute assignments." - "(n_cores:{}, has_assignment_keys:{}, has_validator_groups:{})", - config.n_cores, - config.assignment_keys.size(), - config.validator_groups.size()); - std::optional> founded_key = findAssignmentKey(keystore, config); if (!founded_key) { @@ -692,14 +682,12 @@ namespace kagome::parachain { std::move(babe_config); acu.second.included_candidates = std::move(included); - acu.second.session_index = session_index; - acu.second.session_info = std::move(session_info); acu.second.babe_epoch = epoch_number; acu.second.babe_block_header = std::move(babe_block_header); acu.second.authorities = std::move(authorities); acu.second.randomness = std::move(randomness); - this->try_process_approving_context(acu); + this->try_process_approving_context(acu, session_index, session_info); }); } @@ -716,7 +704,9 @@ namespace kagome::parachain { } void ApprovalDistribution::try_process_approving_context( - ApprovalDistribution::ApprovingContextUnit &acu) { + ApprovalDistribution::ApprovingContextUnit &acu, + SessionIndex session_index, + const runtime::SessionInfo &session_info) { ApprovingContext &ac = acu.second; if (!ac.is_complete()) { return; @@ -745,18 +735,17 @@ namespace kagome::parachain { return; } auto assignments = compute_assignments( - keystore_, *ac.session_info, relay_vrf, *ac.included_candidates); + keystore_, session_info, relay_vrf, *ac.included_candidates); /// TODO(iceseer): force approve impl ac.complete_callback(ImportedBlockInfo{ .included_candidates = std::move(*ac.included_candidates), - .session_index = *ac.session_index, + .session_index = session_index, .assignments = std::move(assignments), - .n_validators = ac.session_info->validators.size(), + .n_validators = session_info.validators.size(), .relay_vrf_story = relay_vrf, .slot = unsafe_vrf.slot, - .session_info = std::move(*ac.session_info), .force_approve = std::nullopt}); } @@ -766,7 +755,30 @@ namespace kagome::parachain { kagome::parachain::approval::ApprovalStatus>> ApprovalDistribution::approval_status(const BlockEntry &block_entry, CandidateEntry &candidate_entry) { - auto &session_info = block_entry.session_info; + std::optional opt_session_info{}; + if (auto session_info_res = parachain_host_->session_info( + block_entry.parent_hash, block_entry.session); + session_info_res.has_value()) { + opt_session_info = std::move(session_info_res.value()); + } else { + logger_->warn( + "Approval status. Session info runtime request failed. " + "(block_hash={}, session_index={}, error={})", + block_entry.parent_hash, + block_entry.session, + session_info_res.error().message()); + return std::nullopt; + } + + if (!opt_session_info) { + logger_->debug( + "Can't obtain SessionInfo. (parent_hash={}, session_index={})", + block_entry.parent_hash, + block_entry.session); + return std::nullopt; + } + + runtime::SessionInfo &session_info = *opt_session_info; const auto block_hash = block_entry.block_hash; const auto tranche_now = @@ -866,7 +878,7 @@ namespace kagome::parachain { const primitives::BlockHash &block_hash, const primitives::BlockHash &parent_hash, scale::BitVec &&approved_bitfield, - ImportedBlockInfo &&block_info) { + const ImportedBlockInfo &block_info) { std::vector> entries; std::vector> candidates; if (auto blocks = storedBlocks().get_or_create(block_number); @@ -881,10 +893,6 @@ namespace kagome::parachain { for (const auto &[candidateHash, candidateReceipt, coreIndex, groupIndex] : block_info.included_candidates) { std::optional> assignment{}; - if (auto assignment_it = block_info.assignments.find(coreIndex); - assignment_it != block_info.assignments.end()) { - assignment = assignment_it->second; - } auto candidate_entry = storedCandidateEntries().get_or_create(candidateHash, @@ -910,7 +918,6 @@ namespace kagome::parachain { .parent_hash = parent_hash, .block_number = block_number, .session = block_info.session_index, - .session_info = std::move(block_info.session_info), .slot = block_info.slot, .relay_vrf_story = std::move(block_info.relay_vrf_story), .candidates = std::move(candidates), @@ -933,33 +940,49 @@ namespace kagome::parachain { block_hash, parent_hash); + OUTCOME_TRY(session_info, + parachain_host_->session_info(block_hash, + imported_block.session_index)); + + if (!session_info) { + SL_TRACE(logger_, + "No session info. (block number={}, block hash={}, " + "parent hash={}, session index={})", + block_number, + block_hash, + parent_hash, + imported_block.session_index); + return Error::NO_SESSION_INFO; + } + const auto block_tick = slotNumberToTick(config_.slot_duration_millis, imported_block.slot); - const auto no_show_duration = - slotNumberToTick(config_.slot_duration_millis, - imported_block.session_info.no_show_slots); + const auto no_show_duration = slotNumberToTick(config_.slot_duration_millis, + session_info->no_show_slots); - const auto needed_approvals = imported_block.session_info.needed_approvals; + const auto needed_approvals = session_info->needed_approvals; const auto num_candidates = imported_block.included_candidates.size(); scale::BitVec approved_bitfield; size_t num_ones = 0ull; if (0 == needed_approvals) { - SL_TRACE(logger_, "Auto-approving all candidates: {}", block_hash); + SL_TRACE(logger_, "Insta-approving all candidates. {}", block_hash); approved_bitfield.bits.insert( - approved_bitfield.bits.begin(), num_candidates, true); + approved_bitfield.bits.end(), num_candidates, true); num_ones = num_candidates; } else { approved_bitfield.bits.insert( - approved_bitfield.bits.begin(), num_candidates, false); + approved_bitfield.bits.end(), num_candidates, false); for (size_t ix = 0; ix < imported_block.included_candidates.size(); ++ix) { const auto &[_0, _1, _2, backing_group] = imported_block.included_candidates[ix]; - const auto backing_group_size = - imported_block.session_info.validator_groups[backing_group].size(); + const size_t backing_group_size = + ((backing_group < session_info->validator_groups.size()) + ? session_info->validator_groups[backing_group].size() + : 0ull); if (math::sat_sub_unsigned(imported_block.n_validators, backing_group_size) < needed_approvals) { @@ -986,7 +1009,7 @@ namespace kagome::parachain { block_hash, parent_hash, std::move(approved_bitfield), - std::move(imported_block))); + imported_block)); std::vector candidates; for (const auto &[hash, _0, _1, _2] : imported_block.included_candidates) { @@ -1072,10 +1095,8 @@ namespace kagome::parachain { ApprovingContext{ .block_header = updated.new_head, .included_candidates = std::nullopt, - .session_index = std::nullopt, .babe_block_header = std::nullopt, .babe_epoch = std::nullopt, - .session_info = std::nullopt, .complete_callback_context = internal_context_->io_context(), .complete_callback = [wself{weak_from_this()}, @@ -1267,7 +1288,31 @@ namespace kagome::parachain { GET_OPT_VALUE_OR_EXIT(block_entry, AssignmentCheckResult::Bad, storedBlockEntries().get(assignment.block_hash)); - auto &session_info = block_entry.session_info; + + std::optional opt_session_info{}; + if (auto session_info_res = parachain_host_->session_info( + block_entry.parent_hash, block_entry.session); + session_info_res.has_value()) { + opt_session_info = std::move(session_info_res.value()); + } else { + logger_->warn( + "Assignment. Session info runtime request failed. (parent_hash={}, " + "session_index={}, error={})", + block_entry.parent_hash, + block_entry.session, + session_info_res.error().message()); + return AssignmentCheckResult::Bad; + } + + if (!opt_session_info) { + logger_->debug( + "Can't obtain SessionInfo. (parent_hash={}, session_index={})", + block_entry.parent_hash, + block_entry.session); + return AssignmentCheckResult::Bad; + } + + runtime::SessionInfo &session_info = *opt_session_info; if (candidate_index >= block_entry.candidates.size()) { logger_->warn( "Candidate index more than candidates array.(candidate index={})", @@ -1347,7 +1392,30 @@ namespace kagome::parachain { block_entry, ApprovalCheckResult::Bad, storedBlockEntries().get(approval.payload.payload.block_hash)); - auto &session_info = block_entry.session_info; + std::optional opt_session_info{}; + if (auto session_info_res = parachain_host_->session_info( + approval.payload.payload.block_hash, block_entry.session); + session_info_res.has_value()) { + opt_session_info = std::move(session_info_res.value()); + } else { + logger_->warn( + "Approval. Session info runtime request failed. (block_hash={}, " + "session_index={}, error={})", + approval.payload.payload.block_hash, + block_entry.session, + session_info_res.error().message()); + return ApprovalCheckResult::Bad; + } + + if (!opt_session_info) { + logger_->debug( + "Can't obtain SessionInfo. (parent_hash={}, session_index={})", + approval.payload.payload.block_hash, + block_entry.session); + return ApprovalCheckResult::Bad; + } + + runtime::SessionInfo &session_info = *opt_session_info; if (approval.payload.payload.candidate_index >= block_entry.candidates.size()) { logger_->warn( @@ -2025,7 +2093,30 @@ namespace kagome::parachain { return; } - auto &session_info = block_entry.session_info; + std::optional opt_session_info{}; + if (auto session_info_res = parachain_host_->session_info( + block_entry.parent_hash, block_entry.session); + session_info_res.has_value()) { + opt_session_info = std::move(session_info_res.value()); + } else { + logger_->warn( + "Issue approval. Session info runtime request failed. " + "(block_hash={}, session_index={}, error={})", + block_entry.parent_hash, + block_entry.session, + session_info_res.error().message()); + return; + } + + if (!opt_session_info) { + logger_->debug( + "Can't obtain SessionInfo. (parent_hash={}, session_index={})", + block_entry.parent_hash, + block_entry.session); + return; + } + + runtime::SessionInfo &session_info = *opt_session_info; if (*candidate_index >= block_entry.candidates.size()) { logger_->warn( "Received malformed request to approve out-of-bounds candidate index " @@ -2422,8 +2513,30 @@ namespace kagome::parachain { auto &block_entry = opt_block_entry->get(); auto &candidate_entry = opt_candidate_entry->get(); - auto &session_info = opt_block_entry->get().session_info; + std::optional opt_session_info{}; + if (auto session_info_res = parachain_host_->session_info( + block_entry.parent_hash, block_entry.session); + session_info_res.has_value()) { + opt_session_info = std::move(session_info_res.value()); + } else { + logger_->warn( + "Handle tranche. Session info runtime request failed. " + "(block_hash={}, session_index={}, error={})", + block_entry.parent_hash, + block_entry.session, + session_info_res.error().message()); + return; + } + + if (!opt_session_info) { + logger_->debug( + "Can't obtain SessionInfo. (parent_hash={}, session_index={})", + block_entry.parent_hash, + block_entry.session); + return; + } + runtime::SessionInfo &session_info = *opt_session_info; const auto block_tick = slotNumberToTick(config_.slot_duration_millis, block_entry.slot); const auto no_show_duration = slotNumberToTick(config_.slot_duration_millis, diff --git a/core/parachain/approval/approval_distribution.hpp b/core/parachain/approval/approval_distribution.hpp index 79a27cd92c..c1de18b704 100644 --- a/core/parachain/approval/approval_distribution.hpp +++ b/core/parachain/approval/approval_distribution.hpp @@ -112,7 +112,7 @@ namespace kagome::parachain { our_assignment{assignment}, approved(false) { assignments.bits.insert( - assignments.bits.begin(), assignments_size, false); + assignments.bits.end(), assignments_size, false); } /// Whether a validator is already assigned. @@ -207,7 +207,7 @@ namespace kagome::parachain { SessionIndex session_index, size_t approvals_size) : candidate(receipt), session(session_index) { - approvals.bits.insert(approvals.bits.begin(), approvals_size, false); + approvals.bits.insert(approvals.bits.end(), approvals_size, false); } std::optional> approval_entry( @@ -276,6 +276,19 @@ namespace kagome::parachain { /// AppStateManager impl bool prepare(); + using CandidateIncludedList = + std::vector>; + using AssignmentsList = std::unordered_map; + + static AssignmentsList compute_assignments( + const std::shared_ptr &keystore, + const runtime::SessionInfo &config, + const RelayVRFStory &relay_vrf_story, + const CandidateIncludedList &leaving_cores); + void onValidationProtocolMsg( const libp2p::peer::PeerId &peer_id, const network::ValidatorProtocolMessage &message); @@ -294,13 +307,6 @@ namespace kagome::parachain { const primitives::BlockInfo &max) const override; private: - using CandidateIncludedList = - std::vector>; - using AssignmentsList = std::unordered_map; - struct ImportedBlockInfo { CandidateIncludedList included_candidates; SessionIndex session_index; @@ -308,27 +314,24 @@ namespace kagome::parachain { size_t n_validators; RelayVRFStory relay_vrf_story; consensus::babe::BabeSlotNumber slot; - runtime::SessionInfo session_info; std::optional force_approve; }; struct ApprovingContext { primitives::BlockHeader block_header; std::optional included_candidates; - std::optional session_index; std::optional babe_block_header; std::optional babe_epoch; std::optional randomness; std::optional authorities; - std::optional session_info; std::shared_ptr complete_callback_context; std::function &&)> complete_callback; bool is_complete() const { - return included_candidates && babe_epoch && session_index - && session_info && babe_block_header && randomness && authorities; + return included_candidates && babe_epoch && babe_block_header + && randomness && authorities; } }; @@ -375,7 +378,6 @@ namespace kagome::parachain { primitives::BlockHash parent_hash; primitives::BlockNumber block_number; SessionIndex session; - runtime::SessionInfo session_info; consensus::babe::BabeSlotNumber slot; RelayVRFStory relay_vrf_story; // The candidates included as-of this block and the index of the core they @@ -424,11 +426,12 @@ namespace kagome::parachain { /// Information about a block and imported candidates. struct BlockImportedCandidates { - primitives::BlockHash block_hash; - primitives::BlockNumber block_number; - network::Tick block_tick; - network::Tick no_show_duration; - std::vector> imported_candidates; + primitives::BlockHash block_hash{}; + primitives::BlockNumber block_number{}; + network::Tick block_tick{}; + network::Tick no_show_duration{}; + std::vector> + imported_candidates{}; }; using AssignmentOrApproval = @@ -480,12 +483,6 @@ namespace kagome::parachain { primitives::AuthorityList, primitives::Randomness>>; - AssignmentsList compute_assignments( - const std::shared_ptr &keystore, - const runtime::SessionInfo &config, - const RelayVRFStory &relay_vrf_story, - const CandidateIncludedList &leaving_cores); - void imported_block_info(const primitives::BlockHash &block_hash, const primitives::BlockHeader &block_header); @@ -533,9 +530,12 @@ namespace kagome::parachain { template void for_ACU(const primitives::BlockHash &block_hash, Func &&func); - void try_process_approving_context(ApprovingContextUnit &acu); + void try_process_approving_context( + ApprovingContextUnit &acu, + SessionIndex session_index, + const runtime::SessionInfo &session_info); - std::optional> + static std::optional> findAssignmentKey(const std::shared_ptr &keystore, const runtime::SessionInfo &config); @@ -550,7 +550,7 @@ namespace kagome::parachain { const primitives::BlockHash &block_hash, const primitives::BlockHash &parent_hash, scale::BitVec &&approved_bitfield, - ImportedBlockInfo &&block_info); + const ImportedBlockInfo &block_info); void on_active_leaves_update(const network::ExView &updated); diff --git a/test/core/crypto/crypto_store/CMakeLists.txt b/test/core/crypto/crypto_store/CMakeLists.txt index 185598659a..b59a159c0b 100644 --- a/test/core/crypto/crypto_store/CMakeLists.txt +++ b/test/core/crypto/crypto_store/CMakeLists.txt @@ -16,6 +16,7 @@ addtest(crypto_store_test target_link_libraries(crypto_store_test crypto_store base_fs_test + validator_parachain ) addtest(session_keys_test diff --git a/test/core/crypto/crypto_store/crypto_store_test.cpp b/test/core/crypto/crypto_store/crypto_store_test.cpp index d5a6975e7d..26be14ae38 100644 --- a/test/core/crypto/crypto_store/crypto_store_test.cpp +++ b/test/core/crypto/crypto_store/crypto_store_test.cpp @@ -15,10 +15,16 @@ #include "crypto/random_generator/boost_generator.hpp" #include "crypto/sr25519/sr25519_provider_impl.hpp" +#include +#include #include "testutil/outcome.hpp" #include "testutil/prepare_loggers.hpp" #include "testutil/storage/base_fs_test.hpp" +#include "common/blob.hpp" +#include "common/visitor.hpp" +#include "parachain/approval/approval_distribution.hpp" + using kagome::common::Blob; using kagome::common::Buffer; using kagome::crypto::Bip39Provider; @@ -121,6 +127,49 @@ struct CryptoStoreTest : public test::BaseFS_Test { return kagome::filesystem::exists(file_path); } + template + auto assignment_keys_plus_random(std::shared_ptr &cs, + const char *const (&accounts)[N], + size_t random) { + for (const auto &acc : accounts) { + [[maybe_unused]] auto _ = + cs->generateSr25519Keypair(KnownKeyTypeId::KEY_TYPE_ASGN, + std::string_view{acc}) + .value(); + } + for (size_t ix = 0ull; ix < random; ++ix) { + auto seed = std::to_string(ix); + [[maybe_unused]] auto _ = + cs->generateSr25519Keypair(KnownKeyTypeId::KEY_TYPE_ASGN, + std::string_view{seed}) + .value(); + } + return cs->getSr25519PublicKeys(KnownKeyTypeId::KEY_TYPE_ASGN).value(); + } + + auto create_crypto_store() { + auto hasher = std::make_shared(); + auto csprng = std::make_shared(); + auto ecdsa_provider = std::make_shared(hasher); + auto ed25519_provider = std::make_shared(hasher); + auto sr25519_provider = std::make_shared(); + + auto pbkdf2_provider = std::make_shared(); + auto bip39_provider = + std::make_shared(std::move(pbkdf2_provider), hasher); + + auto keystore_path = kagome::filesystem::path(__FILE__).parent_path() + / "subkey_keys" / "keystore"; + + return std::make_shared( + std::make_shared(std::move(ecdsa_provider)), + std::make_shared(std::move(ed25519_provider)), + std::make_shared(std::move(sr25519_provider)), + bip39_provider, + csprng, + kagome::crypto::KeyFileStorage::createAt(keystore_path).value()); + } + std::shared_ptr bip39_provider; std::shared_ptr crypto_store; std::string mnemonic; @@ -319,26 +368,180 @@ TEST_F(CryptoStoreTest, getSr25519PublicKeysSuccess) { * Currently incompatible with subkey because subkey doesn't append key type to * filename */ -TEST(CryptoStoreCompatibilityTest, DISABLED_SubkeyCompat) { - auto hasher = std::make_shared(); - auto csprng = std::make_shared(); - auto ecdsa_provider = std::make_shared(hasher); - auto ed25519_provider = std::make_shared(hasher); - auto sr25519_provider = std::make_shared(); - - auto pbkdf2_provider = std::make_shared(); - auto bip39_provider = - std::make_shared(std::move(pbkdf2_provider), hasher); - auto keystore_path = kagome::filesystem::path(__FILE__).parent_path() - / "subkey_keys" / "keystore"; - auto crypto_store = std::make_shared( - std::make_shared(std::move(ecdsa_provider)), - std::make_shared(std::move(ed25519_provider)), - std::make_shared(std::move(sr25519_provider)), - bip39_provider, - csprng, - kagome::crypto::KeyFileStorage::createAt(keystore_path).value()); - EXPECT_OUTCOME_TRUE( - keys, crypto_store->getEd25519PublicKeys(KnownKeyTypeId::KEY_TYPE_BABE)); - ASSERT_EQ(keys.size(), 1); +TEST_F(CryptoStoreTest, succeeds_empty_for_0_cores) { + auto cs = create_crypto_store(); + auto asgn_keys = + assignment_keys_plus_random(cs, {"//Alice", "//Bob", "//Charlie"}, 0ull); + + ::RelayVRFStory vrf_story; + ::memset(vrf_story.data, 42, sizeof(vrf_story.data)); + + kagome::runtime::SessionInfo si; + for (const auto &a : asgn_keys) { + si.assignment_keys.emplace_back(a); + } + + si.n_cores = 0; + si.zeroth_delay_tranche_width = 10; + si.relay_vrf_modulo_samples = 3; + si.n_delay_tranches = 40; + + kagome::parachain::ApprovalDistribution::CandidateIncludedList + leaving_cores{}; + + auto assignments = + kagome::parachain::ApprovalDistribution::compute_assignments( + cs, si, vrf_story, leaving_cores); + + ASSERT_EQ(assignments.size(), 0ull); +} + +TEST_F(CryptoStoreTest, assign_to_nonzero_core) { + auto cs = create_crypto_store(); + auto asgn_keys = + assignment_keys_plus_random(cs, {"//Alice", "//Bob", "//Charlie"}, 0ull); + + auto c_a = + kagome::common::Hash256::fromHexWithPrefix( + "0x0000000000000000000000000000000000000000000000000000000000000000") + .value(); + auto c_b = + kagome::common::Hash256::fromHexWithPrefix( + "0x0101010101010101010101010101010101010101010101010101010101010101") + .value(); + + ::RelayVRFStory vrf_story; + ::memset(vrf_story.data, 42, sizeof(vrf_story.data)); + + kagome::runtime::SessionInfo si; + for (const auto &a : asgn_keys) { + si.assignment_keys.emplace_back(a); + } + + si.validator_groups.emplace_back( + std::vector{0}); + si.validator_groups.emplace_back( + std::vector{1, 2}); + si.n_cores = 2; + si.zeroth_delay_tranche_width = 10; + si.relay_vrf_modulo_samples = 3; + si.n_delay_tranches = 40; + + kagome::parachain::ApprovalDistribution::CandidateIncludedList leaving_cores = + {std::make_tuple(c_a, + kagome::network::CandidateReceipt{}, + (kagome::parachain::CoreIndex)0, + (kagome::parachain::GroupIndex)0), + std::make_tuple(c_b, + kagome::network::CandidateReceipt{}, + (kagome::parachain::CoreIndex)1, + (kagome::parachain::GroupIndex)1)}; + auto assignments = + kagome::parachain::ApprovalDistribution::compute_assignments( + cs, si, vrf_story, leaving_cores); + + ASSERT_EQ(assignments.size(), 1ull); + + auto it = assignments.find(1ull); + ASSERT_TRUE(it != assignments.end()); + + const kagome::parachain::ApprovalDistribution::OurAssignment &our_assignment = + it->second; + ASSERT_EQ(our_assignment.tranche, 0ull); + ASSERT_EQ(our_assignment.validator_index, 0); + ASSERT_EQ(our_assignment.triggered, false); + + ASSERT_TRUE( + kagome::is_type( + our_assignment.cert.kind)); + if (auto k = + kagome::if_type( + our_assignment.cert.kind)) { + ASSERT_EQ(k->get().sample, 2); + } + + const uint8_t + vrf_output[kagome::crypto::constants::sr25519::vrf::OUTPUT_SIZE] = { + 228, 179, 248, 78, 77, 169, 23, 184, 138, 204, 148, + 183, 13, 41, 176, 163, 162, 6, 237, 158, 220, 225, + 97, 251, 51, 144, 207, 239, 189, 2, 7, 66}; + ASSERT_EQ(0, + memcmp(&our_assignment.cert.vrf.output, + vrf_output, + kagome::crypto::constants::sr25519::vrf::OUTPUT_SIZE)); } + +TEST_F(CryptoStoreTest, assignments_produced_for_non_backing) { + auto cs = create_crypto_store(); + auto asgn_keys = + assignment_keys_plus_random(cs, {"//Alice", "//Bob", "//Charlie"}, 0ull); + + auto c_a = + kagome::common::Hash256::fromHexWithPrefix( + "0x0000000000000000000000000000000000000000000000000000000000000000") + .value(); + auto c_b = + kagome::common::Hash256::fromHexWithPrefix( + "0x0101010101010101010101010101010101010101010101010101010101010101") + .value(); + + ::RelayVRFStory vrf_story; + ::memset(vrf_story.data, 42, sizeof(vrf_story.data)); + + kagome::runtime::SessionInfo si; + for (const auto &a : asgn_keys) { + si.assignment_keys.emplace_back(a); + } + + si.validator_groups.emplace_back( + std::vector{0}); + si.validator_groups.emplace_back( + std::vector{1, 2}); + si.n_cores = 2; + si.zeroth_delay_tranche_width = 10; + si.relay_vrf_modulo_samples = 3; + si.n_delay_tranches = 40; + + kagome::parachain::ApprovalDistribution::CandidateIncludedList leaving_cores = + {std::make_tuple(c_a, + kagome::network::CandidateReceipt{}, + (kagome::parachain::CoreIndex)0, + (kagome::parachain::GroupIndex)1), + std::make_tuple(c_b, + kagome::network::CandidateReceipt{}, + (kagome::parachain::CoreIndex)1, + (kagome::parachain::GroupIndex)0)}; + auto assignments = + kagome::parachain::ApprovalDistribution::compute_assignments( + cs, si, vrf_story, leaving_cores); + + ASSERT_EQ(assignments.size(), 1ull); + + auto it = assignments.find(0ull); + ASSERT_TRUE(it != assignments.end()); + + const kagome::parachain::ApprovalDistribution::OurAssignment &our_assignment = + it->second; + ASSERT_EQ(our_assignment.tranche, 0ull); + ASSERT_EQ(our_assignment.validator_index, 0); + ASSERT_EQ(our_assignment.triggered, false); + + ASSERT_TRUE( + kagome::is_type( + our_assignment.cert.kind)); + if (auto k = + kagome::if_type( + our_assignment.cert.kind)) { + ASSERT_EQ(k->get().sample, 0); + } + + const uint8_t + vrf_output[kagome::crypto::constants::sr25519::vrf::OUTPUT_SIZE] = { + 34, 247, 30, 171, 146, 67, 68, 83, 108, 206, 61, + 154, 115, 28, 180, 81, 28, 90, 68, 166, 49, 220, + 157, 41, 235, 223, 152, 45, 190, 202, 216, 39}; + ASSERT_EQ(0, + memcmp(&our_assignment.cert.vrf.output, + vrf_output, + kagome::crypto::constants::sr25519::vrf::OUTPUT_SIZE)); +} \ No newline at end of file From 1b22d1f1eae56be9cd27dd2aa396c94ee088e3ab Mon Sep 17 00:00:00 2001 From: iceseer Date: Tue, 15 Aug 2023 18:25:29 +0300 Subject: [PATCH 14/38] unify --- .../approval/approval_distribution.cpp | 52 +++++++++++++++++++ .../approval/approval_distribution.hpp | 7 +++ 2 files changed, 59 insertions(+) diff --git a/core/parachain/approval/approval_distribution.cpp b/core/parachain/approval/approval_distribution.cpp index ed802d0b47..300b482306 100644 --- a/core/parachain/approval/approval_distribution.cpp +++ b/core/parachain/approval/approval_distribution.cpp @@ -1045,6 +1045,7 @@ namespace kagome::parachain { .candidates = std::move(candidates), .knowledge = {}, .known_by = {}, + .number = meta.number, }); } @@ -2607,6 +2608,57 @@ namespace kagome::parachain { approval::WakeupProcessed{}); } + void ApprovalDistribution::unify_with_peer( + StoreUnit> &entries, + size_t total_peers, + const libp2p::peer::PeerId &peer_id, + const network::View &view) { + std::vector assignments_to_send; + std::vector approvals_to_send; + + const auto view_finalized_number = view.finalized_number_; + for (const auto &head : view.heads_) { + primitives::BlockHash block = head; + while (true) { + auto entry = entries.get(block); + if (!entry || entry->get().number <= view_finalized_number) { + break; + } + + if (entry.known_by.count(peer_id) != 0ull) { + break; + } + + auto &peer_knowledge = entry.known_by[peer_id]; + for (uint32_t candidate_index = 0; + candidate_index < entry.candidates.size(); + ++candidate_index) { + auto &c = entry.candidates[candidate_index]; + for (auto &[validator, message_state] : c.messages) { + auto message_subject{ + std::make_tuple(block, candidate_index, validator)}; + const auto &cert = visit_in_place( + message_state.approval_state, + [](const DistribApprovalStateAssigned &val) { return val; }, + [](const DistribApprovalStateApproved &val) { + const auto &[cert, _] = val; + return cert; + }); + network::Assignment assignment_message{ + .indirect_assignment_cert = + approval::IndirectAssignmentCert{ + .block_hash = block, + .validator = validator, + .cert = cert, + }, + .candidate_ix = candidate_index, + }; + } + } + } + } + } + primitives::BlockInfo ApprovalDistribution::approvedAncestor( const primitives::BlockInfo &min, const primitives::BlockInfo &max) const { diff --git a/core/parachain/approval/approval_distribution.hpp b/core/parachain/approval/approval_distribution.hpp index c1de18b704..bd93f88c0c 100644 --- a/core/parachain/approval/approval_distribution.hpp +++ b/core/parachain/approval/approval_distribution.hpp @@ -369,6 +369,8 @@ namespace kagome::parachain { /// within it. This maps to their knowledge of messages. std::unordered_map known_by{}; + /// The number of the block. + primitives::BlockNumber number; }; /// Metadata regarding approval of a particular block, by way of approval of @@ -539,6 +541,11 @@ namespace kagome::parachain { findAssignmentKey(const std::shared_ptr &keystore, const runtime::SessionInfo &config); + void unify_with_peer(StoreUnit> &entries, + size_t total_peers, + const libp2p::peer::PeerId &peer_id, + const network::View &view); + outcome::result processImportedBlock( primitives::BlockNumber block_number, const primitives::BlockHash &block_hash, From 461e04621a8b49e4fc47833fc1a190878dc9fdf3 Mon Sep 17 00:00:00 2001 From: iceseer Date: Tue, 15 Aug 2023 20:04:50 +0300 Subject: [PATCH 15/38] intermediate --- .../approval/approval_distribution.cpp | 77 +++++++++++++++---- .../approval/approval_distribution.hpp | 2 + 2 files changed, 62 insertions(+), 17 deletions(-) diff --git a/core/parachain/approval/approval_distribution.cpp b/core/parachain/approval/approval_distribution.cpp index 300b482306..44dcd9780f 100644 --- a/core/parachain/approval/approval_distribution.cpp +++ b/core/parachain/approval/approval_distribution.cpp @@ -1046,6 +1046,7 @@ namespace kagome::parachain { .knowledge = {}, .known_by = {}, .number = meta.number, + .parent_hash = meta.parent_hash, }); } @@ -2614,17 +2615,18 @@ namespace kagome::parachain { const libp2p::peer::PeerId &peer_id, const network::View &view) { std::vector assignments_to_send; - std::vector approvals_to_send; + std::vector approvals_to_send; const auto view_finalized_number = view.finalized_number_; for (const auto &head : view.heads_) { primitives::BlockHash block = head; while (true) { - auto entry = entries.get(block); - if (!entry || entry->get().number <= view_finalized_number) { + auto opt_entry = entries.get(block); + if (!opt_entry || opt_entry->get().number <= view_finalized_number) { break; } + auto &entry = opt_entry->get(); if (entry.known_by.count(peer_id) != 0ull) { break; } @@ -2637,24 +2639,65 @@ namespace kagome::parachain { for (auto &[validator, message_state] : c.messages) { auto message_subject{ std::make_tuple(block, candidate_index, validator)}; - const auto &cert = visit_in_place( + const auto &[ref_cert, opt_ref_approval_sig] = visit_in_place( message_state.approval_state, - [](const DistribApprovalStateAssigned &val) { return val; }, - [](const DistribApprovalStateApproved &val) { - const auto &[cert, _] = val; - return cert; + [](const DistribApprovalStateAssigned &cert) + -> std::pair< + std::reference_wrapper, + std::optional< + std::reference_wrapper>> { + return std::make_pair(std::cref(cert), std::nullopt); + }, + [](const DistribApprovalStateApproved &val) + -> std::pair< + std::reference_wrapper, + std::optional< + std::reference_wrapper>> { + const auto &[cert, sig] = val; + return std::make_pair(std::cref(cert), std::cref(sig)); }); - network::Assignment assignment_message{ - .indirect_assignment_cert = - approval::IndirectAssignmentCert{ - .block_hash = block, - .validator = validator, - .cert = cert, - }, - .candidate_ix = candidate_index, - }; + + if (!peer_knowledge.contains(message_subject, + approval::MessageKindAssignment{})) { + peer_knowledge.sent.insert(message_subject, + approval::MessageKindAssignment{}); + + assignments_to_send.emplace_back(network::Assignment{ + .indirect_assignment_cert = + approval::IndirectAssignmentCert{ + .block_hash = block, + .validator = validator, + .cert = ref_cert.get(), + }, + .candidate_ix = candidate_index, + }); + } + + if (opt_ref_approval_sig) { + if (!peer_knowledge.contains(message_subject, + approval::MessageKindApproval{})) { + peer_knowledge.sent.insert(message_subject, + approval::MessageKindApproval{}); + + approvals_to_send.emplace_back( + network::IndirectSignedApprovalVote{ + .payload = + { + .payload = + network::ApprovalVote{ + .block_hash = block, + .candidate_index = candidate_index, + }, + .ix = validator, + }, + .signature = opt_ref_approval_sig->get(), + }); + } + } } } + + block = entry.parent_hash; } } } diff --git a/core/parachain/approval/approval_distribution.hpp b/core/parachain/approval/approval_distribution.hpp index bd93f88c0c..af890a3eff 100644 --- a/core/parachain/approval/approval_distribution.hpp +++ b/core/parachain/approval/approval_distribution.hpp @@ -371,6 +371,8 @@ namespace kagome::parachain { known_by{}; /// The number of the block. primitives::BlockNumber number; + /// The parent hash of the block. + RelayHash parent_hash; }; /// Metadata regarding approval of a particular block, by way of approval of From 6290f40c77b46de074ee1f7598f3c4cc821f7a1b Mon Sep 17 00:00:00 2001 From: iceseer Date: Tue, 15 Aug 2023 20:43:30 +0300 Subject: [PATCH 16/38] intermediate --- .../approval/approval_distribution.cpp | 71 +++++++++++++++++++ .../approval/approval_distribution.hpp | 7 ++ 2 files changed, 78 insertions(+) diff --git a/core/parachain/approval/approval_distribution.cpp b/core/parachain/approval/approval_distribution.cpp index 44dcd9780f..5fc1d9cd6e 100644 --- a/core/parachain/approval/approval_distribution.cpp +++ b/core/parachain/approval/approval_distribution.cpp @@ -23,6 +23,9 @@ #include "utils/async_sequence.hpp" #include "utils/weak_from_shared.hpp" +static constexpr size_t kMaxAssignmentBatchSize = 200ull; +static constexpr size_t kMaxApprovalBatchSize = 300ull; + OUTCOME_CPP_DEFINE_CATEGORY(kagome::parachain, ApprovalDistribution::Error, e) { using E = kagome::parachain::ApprovalDistribution::Error; switch (e) { @@ -2041,6 +2044,67 @@ namespace kagome::parachain { [&](const libp2p::peer::PeerId &p) { return peers.count(p) != 0ull; }); } + void ApprovalDistribution::send_assignments_batched( + std::deque &&_assignments, + const libp2p::peer::PeerId &_peer_id) { + REINVOKE_2(this_context_, + send_assignments_batched, + _assignments, + _peer_id, + assignments, + peer_id); + + auto se = pm_->getStreamEngine(); + BOOST_ASSERT(se); // kMaxAssignmentBatchSize + + while (!assignments.empty()) { + auto begin = assignments.begin(); + auto end = (assignments.size() > kMaxAssignmentBatchSize) + ? assignments.begin() + kMaxAssignmentBatchSize + : assignments.end(); + + auto msg = std::make_shared< + network::WireMessage>( + network::ApprovalDistributionMessage{network::Assignments{ + .assignments = std::vector(begin, end), + }}); + + se->send(peer_id, router_->getValidationProtocol(), msg); + assignments.erase(begin, end); + } + } + + void ApprovalDistribution::send_approvals_batched( + std::deque &&_approvals, + const libp2p::peer::PeerId &_peer_id) { + REINVOKE_2(this_context_, + send_approvals_batched, + _approvals, + _peer_id, + approvals, + peer_id); + + auto se = pm_->getStreamEngine(); + BOOST_ASSERT(se); // kMaxApprovalBatchSize + + while (!approvals.empty()) { + auto begin = approvals.begin(); + auto end = (approvals.size() > kMaxApprovalBatchSize) + ? approvals.begin() + kMaxApprovalBatchSize + : approvals.end(); + + auto msg = std::make_shared< + network::WireMessage>( + network::ApprovalDistributionMessage{network::Approvals{ + .approvals = + std::vector(begin, end), + }}); + + se->send(peer_id, router_->getValidationProtocol(), msg); + approvals.erase(begin, end); + } + } + void ApprovalDistribution::runDistributeApproval( const network::IndirectSignedApprovalVote &_vote, std::unordered_set &&_peers) { @@ -2700,6 +2764,13 @@ namespace kagome::parachain { block = entry.parent_hash; } } + + if (!assignments_to_send.empty()) { + SL_TRACE(logger_, + "Sending assignments to unified peer. (peer id={}, count={})", + peer_id, + assignments_to_send.size()); + } } primitives::BlockInfo ApprovalDistribution::approvedAncestor( diff --git a/core/parachain/approval/approval_distribution.hpp b/core/parachain/approval/approval_distribution.hpp index af890a3eff..7f300fd821 100644 --- a/core/parachain/approval/approval_distribution.hpp +++ b/core/parachain/approval/approval_distribution.hpp @@ -623,6 +623,13 @@ namespace kagome::parachain { CandidateIndex candidate_index, std::unordered_set &&peers); + void send_assignments_batched(std::deque &&assignments, + const libp2p::peer::PeerId &peer_id); + + void send_approvals_batched( + std::deque &&approvals, + const libp2p::peer::PeerId &peer_id); + void runDistributeApproval( const network::IndirectSignedApprovalVote &vote, std::unordered_set &&peers); From 7b23af1e0914e3403c03a45466e3d0f8445f744c Mon Sep 17 00:00:00 2001 From: iceseer Date: Tue, 15 Aug 2023 21:29:21 +0300 Subject: [PATCH 17/38] unify_with_peers --- .../approval/approval_distribution.cpp | 74 +++++++++++++++---- .../approval/approval_distribution.hpp | 10 ++- 2 files changed, 69 insertions(+), 15 deletions(-) diff --git a/core/parachain/approval/approval_distribution.cpp b/core/parachain/approval/approval_distribution.cpp index 5fc1d9cd6e..fa4c171cf6 100644 --- a/core/parachain/approval/approval_distribution.cpp +++ b/core/parachain/approval/approval_distribution.cpp @@ -530,6 +530,21 @@ namespace kagome::parachain { } }); + remote_view_sub_ = std::make_shared( + peer_view_->getRemoteViewObservable(), false); + remote_view_sub_->subscribe(remote_view_sub_->generateSubscriptionSetId(), + network::PeerView::EventType::kViewUpdated); + remote_view_sub_->setCallback( + [wptr{weak_from_this()}](auto /*set_id*/, + auto && /*internal_obj*/, + auto /*event_type*/, + const libp2p::peer::PeerId &peer_id, + const network::View &view) { + if (auto self = wptr.lock()) { + self->store_remote_view(peer_id, view); + } + }); + chain_sub_ = std::make_shared( peer_view_->intoChainEventsEngine()); chain_sub_->subscribe( @@ -555,6 +570,13 @@ namespace kagome::parachain { return true; } + void ApprovalDistribution::store_remote_view( + const libp2p::peer::PeerId &_peer_id, const network::View &_view) { + REINVOKE_2( + *internal_context_, store_remote_view, _peer_id, _view, peer_id, view); + peer_views_[peer_id] = std::move(view); + } + void ApprovalDistribution::clearCaches( const primitives::events::ChainEventParams &ev) { REINVOKE_1(*internal_context_, clearCaches, ev, event); @@ -935,6 +957,7 @@ namespace kagome::parachain { primitives::BlockNumber block_number, const primitives::BlockHash &block_hash, const primitives::BlockHash &parent_hash, + primitives::BlockNumber finalized_block_number, ApprovalDistribution::ImportedBlockInfo &&imported_block) { SL_TRACE(logger_, "Star imported block processing. (block number={}, block hash={}, " @@ -1019,14 +1042,16 @@ namespace kagome::parachain { candidates.emplace_back(hash); } - runNewBlocks(approval::BlockApprovalMeta{ - .hash = block_hash, - .number = block_number, - .parent_hash = parent_hash, - .candidates = std::move(candidates), - .slot = imported_block.slot, - .session = imported_block.session_index, - }); + runNewBlocks( + approval::BlockApprovalMeta{ + .hash = block_hash, + .number = block_number, + .parent_hash = parent_hash, + .candidates = std::move(candidates), + .slot = imported_block.slot, + .session = imported_block.session_index, + }, + finalized_block_number); return BlockImportedCandidates{.block_hash = block_hash, .block_number = block_number, @@ -1035,7 +1060,9 @@ namespace kagome::parachain { .imported_candidates = std::move(entries)}; } - void ApprovalDistribution::runNewBlocks(approval::BlockApprovalMeta &&meta) { + void ApprovalDistribution::runNewBlocks( + approval::BlockApprovalMeta &&meta, + primitives::BlockNumber finalized_block_number) { std::optional new_hash; if (!storedDistribBlockEntries().get(meta.hash)) { const auto candidates_count = meta.candidates.size(); @@ -1054,7 +1081,18 @@ namespace kagome::parachain { } logger_->trace("Got new block.(hash={})", new_hash); - /// TODO(iceseer): intersection in views + for (const auto &[peed_id, view] : peer_views_) { + for (const auto &h : view.heads_) { + if (h == meta.hash) { + unify_with_peer(storedDistribBlockEntries(), + peed_id, + network::View{ + .heads_ = {h}, + .finalized_number_ = finalized_block_number, + }); + } + } + } for (auto it = pending_known_.begin(); it != pending_known_.end();) { if (!storedDistribBlockEntries().get(it->first)) { @@ -1107,6 +1145,7 @@ namespace kagome::parachain { [wself{weak_from_this()}, block_hash{head}, block_number, + finalized_block_number{updated.view.finalized_number_}, parent_hash{std::move(parent_hash)}, func(std::forward(func))]( outcome::result &&block_info) mutable { @@ -1126,6 +1165,7 @@ namespace kagome::parachain { block_number, block_hash, parent_hash, + finalized_block_number, std::move(block_info.value()))); }}); @@ -2675,11 +2715,10 @@ namespace kagome::parachain { void ApprovalDistribution::unify_with_peer( StoreUnit> &entries, - size_t total_peers, const libp2p::peer::PeerId &peer_id, const network::View &view) { - std::vector assignments_to_send; - std::vector approvals_to_send; + std::deque assignments_to_send; + std::deque approvals_to_send; const auto view_finalized_number = view.finalized_number_; for (const auto &head : view.heads_) { @@ -2770,6 +2809,15 @@ namespace kagome::parachain { "Sending assignments to unified peer. (peer id={}, count={})", peer_id, assignments_to_send.size()); + send_assignments_batched(std::move(assignments_to_send), peer_id); + } + + if (!approvals_to_send.empty()) { + SL_TRACE(logger_, + "Sending approvals to unified peer. (peer id={}, count={})", + peer_id, + assignments_to_send.size()); + send_approvals_batched(std::move(approvals_to_send), peer_id); } } diff --git a/core/parachain/approval/approval_distribution.hpp b/core/parachain/approval/approval_distribution.hpp index 7f300fd821..25871ea444 100644 --- a/core/parachain/approval/approval_distribution.hpp +++ b/core/parachain/approval/approval_distribution.hpp @@ -544,7 +544,6 @@ namespace kagome::parachain { const runtime::SessionInfo &config); void unify_with_peer(StoreUnit> &entries, - size_t total_peers, const libp2p::peer::PeerId &peer_id, const network::View &view); @@ -552,6 +551,7 @@ namespace kagome::parachain { primitives::BlockNumber block_number, const primitives::BlockHash &block_hash, const primitives::BlockHash &parent_hash, + primitives::BlockNumber finalized_block_number, ImportedBlockInfo &&block_info); outcome::result>> @@ -589,7 +589,8 @@ namespace kagome::parachain { const network::CandidateReceipt &candidate, GroupIndex backing_group); - void runNewBlocks(approval::BlockApprovalMeta &&approval_meta); + void runNewBlocks(approval::BlockApprovalMeta &&approval_meta, + primitives::BlockNumber finalized_block_number); std::optional sign_approval( const crypto::Sr25519PublicKey &pubkey, @@ -641,6 +642,9 @@ namespace kagome::parachain { void clearCaches(const primitives::events::ChainEventParams &event); + void store_remote_view(const libp2p::peer::PeerId &peer_id, + const network::View &view); + auto &storedBlocks() { return as>>(store_); @@ -676,6 +680,7 @@ namespace kagome::parachain { const ApprovalVotingSubsystem config_; std::shared_ptr peer_view_; network::PeerView::MyViewSubscriberPtr my_view_sub_; + network::PeerView::PeerViewSubscriberPtr remote_view_sub_; std::shared_ptr chain_sub_; Store>, @@ -697,6 +702,7 @@ namespace kagome::parachain { Hash, std::vector>> pending_known_; + std::unordered_map peer_views_; /// thread_pool_ context access using ScheduledCandidateTimer = From 399bfb00ba908ab0155cf2dc8db1aad31abbfb03 Mon Sep 17 00:00:00 2001 From: iceseer Date: Tue, 15 Aug 2023 22:03:49 +0300 Subject: [PATCH 18/38] unify_with_peers complete --- .../approval/approval_distribution.cpp | 21 +++++++++++++++++++ .../approval/approval_distribution.hpp | 2 ++ 2 files changed, 23 insertions(+) diff --git a/core/parachain/approval/approval_distribution.cpp b/core/parachain/approval/approval_distribution.cpp index fa4c171cf6..1141e5f8e0 100644 --- a/core/parachain/approval/approval_distribution.cpp +++ b/core/parachain/approval/approval_distribution.cpp @@ -574,6 +574,25 @@ namespace kagome::parachain { const libp2p::peer::PeerId &_peer_id, const network::View &_view) { REINVOKE_2( *internal_context_, store_remote_view, _peer_id, _view, peer_id, view); + + primitives::BlockNumber old_finalized_number{0ull}; + if (auto it = peer_views_.find(peer_id); it != peer_views_.end()) { + old_finalized_number = it->second.finalized_number_; + } + + for (primitives::BlockNumber bn = old_finalized_number; + bn <= view.finalized_number_; + ++bn) { + if (auto it = blocks_by_number_.find(bn); it != blocks_by_number_.end()) { + for (const auto &bh : it->second) { + if (auto opt_entry = storedDistribBlockEntries().get(bh)) { + opt_entry->get().known_by.erase(peer_id); + } + } + } + } + + unify_with_peer(storedDistribBlockEntries(), peer_id, view); peer_views_[peer_id] = std::move(view); } @@ -591,6 +610,7 @@ namespace kagome::parachain { pending_known_.erase(lost); active_tranches_.erase(lost); approving_context_map_.erase(lost); + /// TODO(iceseer): `blocks_by_number_` clear on finalization if (auto block_entry = storedBlockEntries().get(lost)) { for (const auto &candidate : block_entry->get().candidates) { @@ -1078,6 +1098,7 @@ namespace kagome::parachain { .number = meta.number, .parent_hash = meta.parent_hash, }); + blocks_by_number_[meta.number].insert(meta.hash); } logger_->trace("Got new block.(hash={})", new_hash); diff --git a/core/parachain/approval/approval_distribution.hpp b/core/parachain/approval/approval_distribution.hpp index 25871ea444..2dd732d28e 100644 --- a/core/parachain/approval/approval_distribution.hpp +++ b/core/parachain/approval/approval_distribution.hpp @@ -703,6 +703,8 @@ namespace kagome::parachain { std::vector>> pending_known_; std::unordered_map peer_views_; + std::map> + blocks_by_number_; /// thread_pool_ context access using ScheduledCandidateTimer = From 972a2c1e81241e5afc8bb5670400f5d52cff6f18 Mon Sep 17 00:00:00 2001 From: iceseer Date: Wed, 16 Aug 2023 10:37:31 +0300 Subject: [PATCH 19/38] parent hash fixup --- core/parachain/approval/approval_distribution.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/core/parachain/approval/approval_distribution.cpp b/core/parachain/approval/approval_distribution.cpp index 1141e5f8e0..21cec2b2d5 100644 --- a/core/parachain/approval/approval_distribution.cpp +++ b/core/parachain/approval/approval_distribution.cpp @@ -858,7 +858,7 @@ namespace kagome::parachain { OUTCOME_TRY(session_index, parachain_host_->session_index_for_child(parent_hash)); OUTCOME_TRY(session_info, - parachain_host_->session_info(block_hash, session_index)); + parachain_host_->session_info(parent_hash, session_index)); if (!session_info) { SL_ERROR(logger_, @@ -987,7 +987,7 @@ namespace kagome::parachain { parent_hash); OUTCOME_TRY(session_info, - parachain_host_->session_info(block_hash, + parachain_host_->session_info(parent_hash, imported_block.session_index)); if (!session_info) { @@ -2607,8 +2607,8 @@ namespace kagome::parachain { target_block.erase(target_candidate_it); if (ec) { - SL_ERROR(self->logger_, - "error happened while waiting on tranche the " + SL_TRACE(self->logger_, + "Tranche operation waiting failed " "timer: {}", ec.message()); return; From 7f3eea64888c485cbbc5675c191e8fbd04900dc2 Mon Sep 17 00:00:00 2001 From: iceseer Date: Wed, 16 Aug 2023 10:50:42 +0300 Subject: [PATCH 20/38] parent hash fixup --- core/parachain/approval/approval_distribution.cpp | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/core/parachain/approval/approval_distribution.cpp b/core/parachain/approval/approval_distribution.cpp index 21cec2b2d5..540c4a59da 100644 --- a/core/parachain/approval/approval_distribution.cpp +++ b/core/parachain/approval/approval_distribution.cpp @@ -802,7 +802,7 @@ namespace kagome::parachain { CandidateEntry &candidate_entry) { std::optional opt_session_info{}; if (auto session_info_res = parachain_host_->session_info( - block_entry.parent_hash, block_entry.session); + block_entry.block_hash, block_entry.session); session_info_res.has_value()) { opt_session_info = std::move(session_info_res.value()); } else { @@ -858,7 +858,7 @@ namespace kagome::parachain { OUTCOME_TRY(session_index, parachain_host_->session_index_for_child(parent_hash)); OUTCOME_TRY(session_info, - parachain_host_->session_info(parent_hash, session_index)); + parachain_host_->session_info(block_hash, session_index)); if (!session_info) { SL_ERROR(logger_, @@ -987,7 +987,7 @@ namespace kagome::parachain { parent_hash); OUTCOME_TRY(session_info, - parachain_host_->session_info(parent_hash, + parachain_host_->session_info(block_hash, imported_block.session_index)); if (!session_info) { @@ -1357,7 +1357,7 @@ namespace kagome::parachain { std::optional opt_session_info{}; if (auto session_info_res = parachain_host_->session_info( - block_entry.parent_hash, block_entry.session); + block_entry.block_hash, block_entry.session); session_info_res.has_value()) { opt_session_info = std::move(session_info_res.value()); } else { @@ -2222,7 +2222,7 @@ namespace kagome::parachain { std::optional opt_session_info{}; if (auto session_info_res = parachain_host_->session_info( - block_entry.parent_hash, block_entry.session); + block_entry.block_hash, block_entry.session); session_info_res.has_value()) { opt_session_info = std::move(session_info_res.value()); } else { @@ -2642,7 +2642,7 @@ namespace kagome::parachain { auto &candidate_entry = opt_candidate_entry->get(); std::optional opt_session_info{}; if (auto session_info_res = parachain_host_->session_info( - block_entry.parent_hash, block_entry.session); + block_entry.block_hash, block_entry.session); session_info_res.has_value()) { opt_session_info = std::move(session_info_res.value()); } else { From 2cbfcd4de81a02a69706061f7697228ab7970c3d Mon Sep 17 00:00:00 2001 From: iceseer Date: Wed, 16 Aug 2023 11:19:24 +0300 Subject: [PATCH 21/38] minor fix --- core/parachain/approval/approval_distribution.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/parachain/approval/approval_distribution.cpp b/core/parachain/approval/approval_distribution.cpp index 1cbdb61e30..f068cd3b25 100644 --- a/core/parachain/approval/approval_distribution.cpp +++ b/core/parachain/approval/approval_distribution.cpp @@ -858,7 +858,7 @@ namespace kagome::parachain { const primitives::BlockHash &block_hash, const primitives::BlockHash &parent_hash) { OUTCOME_TRY(session_index, - parachain_host_->session_index_for_child(parent_hash)); + parachain_host_->session_index_for_child(block_hash)); OUTCOME_TRY(session_info, parachain_host_->session_info(block_hash, session_index)); From a965875bd870b2f8c66d040732e64b22d715cae5 Mon Sep 17 00:00:00 2001 From: iceseer Date: Wed, 16 Aug 2023 11:48:16 +0300 Subject: [PATCH 22/38] Revert "minor fix" This reverts commit 2cbfcd4de81a02a69706061f7697228ab7970c3d. --- core/parachain/approval/approval_distribution.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/parachain/approval/approval_distribution.cpp b/core/parachain/approval/approval_distribution.cpp index f068cd3b25..1cbdb61e30 100644 --- a/core/parachain/approval/approval_distribution.cpp +++ b/core/parachain/approval/approval_distribution.cpp @@ -858,7 +858,7 @@ namespace kagome::parachain { const primitives::BlockHash &block_hash, const primitives::BlockHash &parent_hash) { OUTCOME_TRY(session_index, - parachain_host_->session_index_for_child(block_hash)); + parachain_host_->session_index_for_child(parent_hash)); OUTCOME_TRY(session_info, parachain_host_->session_info(block_hash, session_index)); From b0b217e5a304b713a470ff2aee613601bc3f77ce Mon Sep 17 00:00:00 2001 From: iceseer Date: Wed, 16 Aug 2023 11:49:25 +0300 Subject: [PATCH 23/38] parent_hash fix This reverts commit 2cbfcd4de81a02a69706061f7697228ab7970c3d. --- core/parachain/approval/approval_distribution.cpp | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/core/parachain/approval/approval_distribution.cpp b/core/parachain/approval/approval_distribution.cpp index 1cbdb61e30..001268612b 100644 --- a/core/parachain/approval/approval_distribution.cpp +++ b/core/parachain/approval/approval_distribution.cpp @@ -804,7 +804,7 @@ namespace kagome::parachain { CandidateEntry &candidate_entry) { std::optional opt_session_info{}; if (auto session_info_res = parachain_host_->session_info( - block_entry.block_hash, block_entry.session); + block_entry.parent_hash, block_entry.session); session_info_res.has_value()) { opt_session_info = std::move(session_info_res.value()); } else { @@ -860,7 +860,7 @@ namespace kagome::parachain { OUTCOME_TRY(session_index, parachain_host_->session_index_for_child(parent_hash)); OUTCOME_TRY(session_info, - parachain_host_->session_info(block_hash, session_index)); + parachain_host_->session_info(parent_hash, session_index)); if (!session_info) { SL_ERROR(logger_, @@ -991,7 +991,7 @@ namespace kagome::parachain { parent_hash); OUTCOME_TRY(session_info, - parachain_host_->session_info(block_hash, + parachain_host_->session_info(parent_hash, imported_block.session_index)); if (!session_info) { @@ -1369,7 +1369,7 @@ namespace kagome::parachain { std::optional opt_session_info{}; if (auto session_info_res = parachain_host_->session_info( - block_entry.block_hash, block_entry.session); + block_entry.parent_hash, block_entry.session); session_info_res.has_value()) { opt_session_info = std::move(session_info_res.value()); } else { @@ -2232,7 +2232,7 @@ namespace kagome::parachain { std::optional opt_session_info{}; if (auto session_info_res = parachain_host_->session_info( - block_entry.block_hash, block_entry.session); + block_entry.parent_hash, block_entry.session); session_info_res.has_value()) { opt_session_info = std::move(session_info_res.value()); } else { @@ -2652,7 +2652,7 @@ namespace kagome::parachain { auto &candidate_entry = opt_candidate_entry->get(); std::optional opt_session_info{}; if (auto session_info_res = parachain_host_->session_info( - block_entry.block_hash, block_entry.session); + block_entry.parent_hash, block_entry.session); session_info_res.has_value()) { opt_session_info = std::move(session_info_res.value()); } else { From c07152bd4cf87bbe8c9d0587953da6021a3323cb Mon Sep 17 00:00:00 2001 From: iceseer Date: Wed, 16 Aug 2023 17:15:49 +0300 Subject: [PATCH 24/38] hashes --- core/parachain/approval/approval_distribution.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/core/parachain/approval/approval_distribution.cpp b/core/parachain/approval/approval_distribution.cpp index 001268612b..19e24772e8 100644 --- a/core/parachain/approval/approval_distribution.cpp +++ b/core/parachain/approval/approval_distribution.cpp @@ -860,7 +860,7 @@ namespace kagome::parachain { OUTCOME_TRY(session_index, parachain_host_->session_index_for_child(parent_hash)); OUTCOME_TRY(session_info, - parachain_host_->session_info(parent_hash, session_index)); + parachain_host_->session_info(block_hash, session_index)); if (!session_info) { SL_ERROR(logger_, @@ -991,7 +991,7 @@ namespace kagome::parachain { parent_hash); OUTCOME_TRY(session_info, - parachain_host_->session_info(parent_hash, + parachain_host_->session_info(block_hash, imported_block.session_index)); if (!session_info) { From e6252337397237730372bd8ce5ce1e4a79b2de9b Mon Sep 17 00:00:00 2001 From: iceseer Date: Wed, 16 Aug 2023 17:49:44 +0300 Subject: [PATCH 25/38] log --- core/parachain/approval/approval_distribution.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/core/parachain/approval/approval_distribution.cpp b/core/parachain/approval/approval_distribution.cpp index 19e24772e8..f34ad01c77 100644 --- a/core/parachain/approval/approval_distribution.cpp +++ b/core/parachain/approval/approval_distribution.cpp @@ -2710,6 +2710,10 @@ namespace kagome::parachain { BOOST_ASSERT(storedCandidateEntries().get(candidate_hash)->get() == candidate_entry); } + SL_TRACE(logger_, + "Wakeup processed. (should trigger={}, cert={})", + should_trigger, + (bool)maybe_cert); if (maybe_cert) { const auto &[cert, val_index, tranche] = *maybe_cert; From f709863f9d0d785daa5559c96b6ddeda198639b6 Mon Sep 17 00:00:00 2001 From: iceseer Date: Wed, 16 Aug 2023 18:05:14 +0300 Subject: [PATCH 26/38] 1 --- core/parachain/approval/approval_distribution.cpp | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/core/parachain/approval/approval_distribution.cpp b/core/parachain/approval/approval_distribution.cpp index f34ad01c77..47dd9dcb34 100644 --- a/core/parachain/approval/approval_distribution.cpp +++ b/core/parachain/approval/approval_distribution.cpp @@ -360,9 +360,11 @@ namespace { const kagome::parachain::approval::RequiredTranches &required_tranches, kagome::network::DelayTranche const tranche_now) { if (!approval_entry.our_assignment) { + SL_TRACE(logger_, "No assignment"); return false; } if (approval_entry.our_assignment->triggered) { + SL_TRACE(logger_, "Already triggered"); return false; } if (approval_entry.our_assignment->tranche == 0) { @@ -370,11 +372,13 @@ namespace { } if (kagome::is_type( required_tranches)) { - return !kagome::parachain::approval::is_approved( + const bool r = !kagome::parachain::approval::is_approved( checkApproval(candidate_entry, approval_entry, kagome::parachain::approval::AllRequiredTranche{}), std::numeric_limits::max()); + SL_TRACE(logger_, "AllRequiredTranche return. (res={})", r); + return r; } if (auto pending = kagome::if_type< const kagome::parachain::approval::PendingRequiredTranche>( @@ -382,12 +386,15 @@ namespace { const auto drifted_tranche_now = kagome::math::sat_sub_unsigned( tranche_now, kagome::network::DelayTranche(pending->get().clock_drift)); - return approval_entry.our_assignment->tranche + const auto r = approval_entry.our_assignment->tranche <= pending->get().maximum_broadcast && approval_entry.our_assignment->tranche <= drifted_tranche_now; + SL_TRACE(logger_, "PendingRequiredTranche return. (res={})", r); + return r; } if (kagome::is_type( required_tranches)) { + SL_TRACE(logger_, "ExactRequiredTranche return false."); return false; } UNREACHABLE; From 4fbf5fecd24e7b2e8f6ded75f16fd33a61d6a6d4 Mon Sep 17 00:00:00 2001 From: iceseer Date: Wed, 16 Aug 2023 18:39:17 +0300 Subject: [PATCH 27/38] 2 --- .../approval/approval_distribution.cpp | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) diff --git a/core/parachain/approval/approval_distribution.cpp b/core/parachain/approval/approval_distribution.cpp index 47dd9dcb34..0a7c972b59 100644 --- a/core/parachain/approval/approval_distribution.cpp +++ b/core/parachain/approval/approval_distribution.cpp @@ -386,7 +386,8 @@ namespace { const auto drifted_tranche_now = kagome::math::sat_sub_unsigned( tranche_now, kagome::network::DelayTranche(pending->get().clock_drift)); - const auto r = approval_entry.our_assignment->tranche + const auto r = + approval_entry.our_assignment->tranche <= pending->get().maximum_broadcast && approval_entry.our_assignment->tranche <= drifted_tranche_now; SL_TRACE(logger_, "PendingRequiredTranche return. (res={})", r); @@ -902,6 +903,20 @@ namespace kagome::parachain { OUTCOME_TRY(epoch, babe_util_->slotToEpoch(*block_header.parentInfo(), babe_digests.second.slot_number)); + OUTCOME_TRY(epoch2, + babe_util_->slotToEpoch( + primitives::BlockInfo(block_header.number, block_hash), + babe_digests.second.slot_number)); + + SL_TRACE(logger_, + "REQUEST BABE DATA. (epoch={}, randomness={}, epoch2={})", + epoch, + babe_config.randomness.toHex(), + epoch2); + + for (const auto &a : babe_config.authorities) { + SL_TRACE(logger_, "Auth. (a={})", a); + } return std::make_tuple(epoch, std::move(babe_digests.second), From 08dc3ab4a7a4b732ce4ed32c61ece2e6d9e4e35d Mon Sep 17 00:00:00 2001 From: iceseer Date: Wed, 16 Aug 2023 19:07:27 +0300 Subject: [PATCH 28/38] 3 --- core/parachain/approval/approval_distribution.cpp | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/core/parachain/approval/approval_distribution.cpp b/core/parachain/approval/approval_distribution.cpp index 0a7c972b59..8e7ce3092d 100644 --- a/core/parachain/approval/approval_distribution.cpp +++ b/core/parachain/approval/approval_distribution.cpp @@ -789,6 +789,8 @@ namespace kagome::parachain { logger_->warn("Relay VRF return error.(error={})", res.error().message()); return; } + + SL_TRACE(logger_, "UNSAFE VRF: {}", common::BufferView(relay_vrf.data, sizeof(relay_vrf.data)).toHex()); auto assignments = compute_assignments( keystore_, session_info, relay_vrf, *ac.included_candidates); @@ -903,16 +905,11 @@ namespace kagome::parachain { OUTCOME_TRY(epoch, babe_util_->slotToEpoch(*block_header.parentInfo(), babe_digests.second.slot_number)); - OUTCOME_TRY(epoch2, - babe_util_->slotToEpoch( - primitives::BlockInfo(block_header.number, block_hash), - babe_digests.second.slot_number)); SL_TRACE(logger_, - "REQUEST BABE DATA. (epoch={}, randomness={}, epoch2={})", + "REQUEST BABE DATA. (epoch={}, randomness={})", epoch, - babe_config.randomness.toHex(), - epoch2); + babe_config.randomness.toHex()); for (const auto &a : babe_config.authorities) { SL_TRACE(logger_, "Auth. (a={})", a); From 72a15622083f0d4974626715e176905bd00adcb2 Mon Sep 17 00:00:00 2001 From: iceseer Date: Wed, 16 Aug 2023 19:09:27 +0300 Subject: [PATCH 29/38] logger_ --- .../approval/approval_distribution.cpp | 22 +++++++++++-------- 1 file changed, 13 insertions(+), 9 deletions(-) diff --git a/core/parachain/approval/approval_distribution.cpp b/core/parachain/approval/approval_distribution.cpp index 8e7ce3092d..4413c48624 100644 --- a/core/parachain/approval/approval_distribution.cpp +++ b/core/parachain/approval/approval_distribution.cpp @@ -358,13 +358,14 @@ namespace { const kagome::parachain::ApprovalDistribution::CandidateEntry &candidate_entry, const kagome::parachain::approval::RequiredTranches &required_tranches, - kagome::network::DelayTranche const tranche_now) { + kagome::network::DelayTranche const tranche_now, + kagome::log::Logger &logger) { if (!approval_entry.our_assignment) { - SL_TRACE(logger_, "No assignment"); + SL_TRACE(logger, "No assignment"); return false; } if (approval_entry.our_assignment->triggered) { - SL_TRACE(logger_, "Already triggered"); + SL_TRACE(logger, "Already triggered"); return false; } if (approval_entry.our_assignment->tranche == 0) { @@ -377,7 +378,7 @@ namespace { approval_entry, kagome::parachain::approval::AllRequiredTranche{}), std::numeric_limits::max()); - SL_TRACE(logger_, "AllRequiredTranche return. (res={})", r); + SL_TRACE(logger, "AllRequiredTranche return. (res={})", r); return r; } if (auto pending = kagome::if_type< @@ -390,7 +391,7 @@ namespace { approval_entry.our_assignment->tranche <= pending->get().maximum_broadcast && approval_entry.our_assignment->tranche <= drifted_tranche_now; - SL_TRACE(logger_, "PendingRequiredTranche return. (res={})", r); + SL_TRACE(logger, "PendingRequiredTranche return. (res={})", r); return r; } if (kagome::is_type( @@ -402,7 +403,7 @@ namespace { } outcome::result checkAssignmentCert( - kagome::network::CoreIndex claimed_core_index, + kagome::network::CreIndex claimed_core_index, kagome::network::ValidatorIndex validator_index, const kagome::runtime::SessionInfo &config, const RelayVRFStory &relay_vrf_story, @@ -790,7 +791,10 @@ namespace kagome::parachain { return; } - SL_TRACE(logger_, "UNSAFE VRF: {}", common::BufferView(relay_vrf.data, sizeof(relay_vrf.data)).toHex()); + SL_TRACE( + logger_, + "UNSAFE VRF: {}", + common::BufferView(relay_vrf.data, sizeof(relay_vrf.data)).toHex()); auto assignments = compute_assignments( keystore_, session_info, relay_vrf, *ac.included_candidates); @@ -912,7 +916,7 @@ namespace kagome::parachain { babe_config.randomness.toHex()); for (const auto &a : babe_config.authorities) { - SL_TRACE(logger_, "Auth. (a={})", a); + SL_TRACE(logger_, "Auth. (a={})", a.id.id.toHex()); } return std::make_tuple(epoch, @@ -2719,7 +2723,7 @@ namespace kagome::parachain { no_show_duration, session_info.needed_approvals); const auto should_trigger = shouldTriggerAssignment( - approval_entry, candidate_entry, tta, tranche_now); + approval_entry, candidate_entry, tta, tranche_now, logger_); const auto backing_group = approval_entry.backing_group; const auto &candidate_receipt = candidate_entry.candidate; From 11581e3439dc0a8d4169ee08df934aad12bf32dd Mon Sep 17 00:00:00 2001 From: iceseer Date: Thu, 17 Aug 2023 09:51:24 +0300 Subject: [PATCH 30/38] 4 --- .../approval/approval_distribution.cpp | 18 ++++++++++++------ .../approval/approval_distribution.hpp | 6 ++++-- 2 files changed, 16 insertions(+), 8 deletions(-) diff --git a/core/parachain/approval/approval_distribution.cpp b/core/parachain/approval/approval_distribution.cpp index 4413c48624..63df438f16 100644 --- a/core/parachain/approval/approval_distribution.cpp +++ b/core/parachain/approval/approval_distribution.cpp @@ -396,14 +396,14 @@ namespace { } if (kagome::is_type( required_tranches)) { - SL_TRACE(logger_, "ExactRequiredTranche return false."); + SL_TRACE(logger, "ExactRequiredTranche return false."); return false; } UNREACHABLE; } outcome::result checkAssignmentCert( - kagome::network::CreIndex claimed_core_index, + kagome::network::CoreIndex claimed_core_index, kagome::network::ValidatorIndex validator_index, const kagome::runtime::SessionInfo &config, const RelayVRFStory &relay_vrf_story, @@ -638,7 +638,12 @@ namespace kagome::parachain { std::optional> ApprovalDistribution::findAssignmentKey( const std::shared_ptr &keystore, - const runtime::SessionInfo &config) { + const runtime::SessionInfo &config, + log::Logger &logger) { + auto keys = keystore->getSr25519PublicKeys(crypto::KEY_TYPE_ASGN).value(); + for (const auto &key : keys) { + SL_TRACE(logger, "PK FOR ASSIGNMENT: {}", key.toHex()); + } for (size_t ix = 0; ix < config.assignment_keys.size(); ++ix) { const auto &pk = config.assignment_keys[ix]; if (auto res = keystore->findSr25519Keypair( @@ -656,14 +661,15 @@ namespace kagome::parachain { const std::shared_ptr &keystore, const runtime::SessionInfo &config, const RelayVRFStory &relay_vrf_story, - const CandidateIncludedList &leaving_cores) { + const CandidateIncludedList &leaving_cores, + log::Logger &logger) { if (config.n_cores == 0 || config.assignment_keys.empty() || config.validator_groups.empty()) { return {}; } std::optional> - founded_key = findAssignmentKey(keystore, config); + founded_key = findAssignmentKey(keystore, config, logger); if (!founded_key) { return {}; } @@ -796,7 +802,7 @@ namespace kagome::parachain { "UNSAFE VRF: {}", common::BufferView(relay_vrf.data, sizeof(relay_vrf.data)).toHex()); auto assignments = compute_assignments( - keystore_, session_info, relay_vrf, *ac.included_candidates); + keystore_, session_info, relay_vrf, *ac.included_candidates, logger_); /// TODO(iceseer): force approve impl diff --git a/core/parachain/approval/approval_distribution.hpp b/core/parachain/approval/approval_distribution.hpp index 96467d229c..0464007d68 100644 --- a/core/parachain/approval/approval_distribution.hpp +++ b/core/parachain/approval/approval_distribution.hpp @@ -290,7 +290,8 @@ namespace kagome::parachain { const std::shared_ptr &keystore, const runtime::SessionInfo &config, const RelayVRFStory &relay_vrf_story, - const CandidateIncludedList &leaving_cores); + const CandidateIncludedList &leaving_cores, + log::Logger &logger); void onValidationProtocolMsg( const libp2p::peer::PeerId &peer_id, @@ -544,7 +545,8 @@ namespace kagome::parachain { static std::optional> findAssignmentKey(const std::shared_ptr &keystore, - const runtime::SessionInfo &config); + const runtime::SessionInfo &config, + log::Logger &logger); void unify_with_peer(StoreUnit> &entries, const libp2p::peer::PeerId &peer_id, From bbe33e83c72048932365014c30822b62738882b5 Mon Sep 17 00:00:00 2001 From: iceseer Date: Thu, 17 Aug 2023 10:48:32 +0300 Subject: [PATCH 31/38] 5 --- core/parachain/approval/approval_distribution.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/core/parachain/approval/approval_distribution.cpp b/core/parachain/approval/approval_distribution.cpp index 63df438f16..1e55129fad 100644 --- a/core/parachain/approval/approval_distribution.cpp +++ b/core/parachain/approval/approval_distribution.cpp @@ -971,6 +971,10 @@ namespace kagome::parachain { for (const auto &[candidateHash, candidateReceipt, coreIndex, groupIndex] : block_info.included_candidates) { std::optional> assignment{}; + if (auto assignment_it = block_info.assignments.find(coreIndex); + assignment_it != block_info.assignments.end()) { + assignment = assignment_it->second; + } auto candidate_entry = storedCandidateEntries().get_or_create(candidateHash, From 2e930c7ffef7af4024f125f14d2c8d8d1d12a8d0 Mon Sep 17 00:00:00 2001 From: iceseer Date: Thu, 17 Aug 2023 10:59:54 +0300 Subject: [PATCH 32/38] 6 --- core/parachain/approval/approval_distribution.cpp | 2 +- core/parachain/approval/approval_distribution.hpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/core/parachain/approval/approval_distribution.cpp b/core/parachain/approval/approval_distribution.cpp index 1e55129fad..cfee195c82 100644 --- a/core/parachain/approval/approval_distribution.cpp +++ b/core/parachain/approval/approval_distribution.cpp @@ -970,7 +970,7 @@ namespace kagome::parachain { candidates.reserve(block_info.included_candidates.size()); for (const auto &[candidateHash, candidateReceipt, coreIndex, groupIndex] : block_info.included_candidates) { - std::optional> assignment{}; + std::optional> assignment{}; if (auto assignment_it = block_info.assignments.find(coreIndex); assignment_it != block_info.assignments.end()) { assignment = assignment_it->second; diff --git a/core/parachain/approval/approval_distribution.hpp b/core/parachain/approval/approval_distribution.hpp index 0464007d68..85c15a2bb3 100644 --- a/core/parachain/approval/approval_distribution.hpp +++ b/core/parachain/approval/approval_distribution.hpp @@ -108,7 +108,7 @@ namespace kagome::parachain { ApprovalEntry( GroupIndex group_index, - std::optional> assignment, + std::optional> assignment, size_t assignments_size) : backing_group{group_index}, our_assignment{assignment}, From 232cb42e787855dee902521ea0f0c6ca70d8a0e0 Mon Sep 17 00:00:00 2001 From: iceseer Date: Thu, 17 Aug 2023 12:53:44 +0300 Subject: [PATCH 33/38] log fixup --- core/parachain/approval/approval_distribution.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/parachain/approval/approval_distribution.cpp b/core/parachain/approval/approval_distribution.cpp index cfee195c82..839fd1775a 100644 --- a/core/parachain/approval/approval_distribution.cpp +++ b/core/parachain/approval/approval_distribution.cpp @@ -2884,7 +2884,7 @@ namespace kagome::parachain { SL_TRACE(logger_, "Sending approvals to unified peer. (peer id={}, count={})", peer_id, - assignments_to_send.size()); + approvals_to_send.size()); send_approvals_batched(std::move(approvals_to_send), peer_id); } } From 04be85e86886c45b4408913930dc219270a51256 Mon Sep 17 00:00:00 2001 From: iceseer Date: Thu, 17 Aug 2023 14:00:23 +0300 Subject: [PATCH 34/38] async pendings --- .../approval/approval_distribution.cpp | 74 +++++++++++-------- 1 file changed, 42 insertions(+), 32 deletions(-) diff --git a/core/parachain/approval/approval_distribution.cpp b/core/parachain/approval/approval_distribution.cpp index 839fd1775a..5dae8c2236 100644 --- a/core/parachain/approval/approval_distribution.cpp +++ b/core/parachain/approval/approval_distribution.cpp @@ -1138,42 +1138,52 @@ namespace kagome::parachain { blocks_by_number_[meta.number].insert(meta.hash); } - logger_->trace("Got new block.(hash={})", new_hash); - for (const auto &[peed_id, view] : peer_views_) { - for (const auto &h : view.heads_) { - if (h == meta.hash) { - unify_with_peer(storedDistribBlockEntries(), - peed_id, - network::View{ - .heads_ = {h}, - .finalized_number_ = finalized_block_number, - }); + internal_context_->execute([wself{weak_from_this()}, + new_hash, + finalized_block_number, + meta{std::move(meta)}]() { + if (auto self = wself.lock()) { + SL_TRACE(self->logger_, "Got new block.(hash={})", new_hash); + for (const auto &[peed_id, view] : self->peer_views_) { + for (const auto &h : view.heads_) { + if (h == meta.hash) { + self->unify_with_peer( + self->storedDistribBlockEntries(), + peed_id, + network::View{ + .heads_ = {h}, + .finalized_number_ = finalized_block_number, + }); + } + } } - } - } - for (auto it = pending_known_.begin(); it != pending_known_.end();) { - if (!storedDistribBlockEntries().get(it->first)) { - ++it; - } else { - logger_->trace("Processing pending assignment/approvals.(count={})", - it->second.size()); - for (auto i = it->second.begin(); i != it->second.end(); ++i) { - visit_in_place( - i->second, - [&](const network::Assignment &assignment) { - import_and_circulate_assignment( - i->first, - assignment.indirect_assignment_cert, - assignment.candidate_ix); - }, - [&](const network::IndirectSignedApprovalVote &approval) { - import_and_circulate_approval(i->first, approval); - }); + for (auto it = self->pending_known_.begin(); + it != self->pending_known_.end();) { + if (!self->storedDistribBlockEntries().get(it->first)) { + ++it; + } else { + self->logger_->trace( + "Processing pending assignment/approvals.(count={})", + it->second.size()); + for (auto i = it->second.begin(); i != it->second.end(); ++i) { + visit_in_place( + i->second, + [&](const network::Assignment &assignment) { + self->import_and_circulate_assignment( + i->first, + assignment.indirect_assignment_cert, + assignment.candidate_ix); + }, + [&](const network::IndirectSignedApprovalVote &approval) { + self->import_and_circulate_approval(i->first, approval); + }); + } + it = self->pending_known_.erase(it); + } } - it = pending_known_.erase(it); } - } + }); } template From 422836dea1d23165664931ecfccc397c56bbaf28 Mon Sep 17 00:00:00 2001 From: iceseer Date: Thu, 17 Aug 2023 14:11:27 +0300 Subject: [PATCH 35/38] TEST DO NOT PUSH --- .../approval/approval_distribution.cpp | 36 ++++++++----------- .../approval/approval_distribution.hpp | 6 ++-- 2 files changed, 17 insertions(+), 25 deletions(-) diff --git a/core/parachain/approval/approval_distribution.cpp b/core/parachain/approval/approval_distribution.cpp index 5dae8c2236..7331a51b45 100644 --- a/core/parachain/approval/approval_distribution.cpp +++ b/core/parachain/approval/approval_distribution.cpp @@ -2624,12 +2624,12 @@ namespace kagome::parachain { const auto ms_wakeup_after = math::sat_sub_unsigned(ms_wakeup, ms_now); auto &target_block = active_tranches_[block_hash]; - auto target_candidate = target_block.find(candidate_hash); - if (target_candidate != target_block.end()) { - if (target_candidate->second.first <= tick) { - return; - } - } + // auto target_candidate = target_block.find(candidate_hash); + /* if (target_candidate != target_block.end()) { + if (target_candidate->second.first <= tick) { + return; + } + }*/ SL_TRACE(logger_, "Scheduling wakeup. (block_hash={}, candidate_hash={}, " @@ -2653,26 +2653,18 @@ namespace kagome::parachain { .running_in_this_thread()); if (auto target_block_it = self->active_tranches_.find(block_hash); target_block_it != self->active_tranches_.end()) { - auto &target_block = target_block_it->second; - if (auto target_candidate_it = target_block.find(candidate_hash); - target_candidate_it != target_block.end()) { - t = std::move(target_candidate_it->second.second); - target_block.erase(target_candidate_it); - - if (ec) { - SL_TRACE(self->logger_, - "Tranche operation waiting failed " - "timer: {}", - ec.message()); - return; - } - self->handleTranche(block_hash, block_number, candidate_hash); + if (ec) { + SL_TRACE(self->logger_, + "Tranche operation waiting failed " + "timer: {}", + ec.message()); + return; } + self->handleTranche(block_hash, block_number, candidate_hash); } } }); - target_block.insert_or_assign(candidate_hash, - std::make_pair(tick, std::move(t))); + target_block[candidate_hash].emplace_back(tick, std::move(t)); } void ApprovalDistribution::handleTranche( diff --git a/core/parachain/approval/approval_distribution.hpp b/core/parachain/approval/approval_distribution.hpp index 85c15a2bb3..b2a40273d7 100644 --- a/core/parachain/approval/approval_distribution.hpp +++ b/core/parachain/approval/approval_distribution.hpp @@ -714,9 +714,9 @@ namespace kagome::parachain { blocks_by_number_; /// thread_pool_ context access - using ScheduledCandidateTimer = - std::unordered_map>>; + using ScheduledCandidateTimer = std::unordered_map< + CandidateHash, + std::vector>>>; std::unordered_map active_tranches_; From 33627c0cfe84d8319eeb2920c12c91c98f5ebcc9 Mon Sep 17 00:00:00 2001 From: iceseer Date: Fri, 18 Aug 2023 11:16:10 +0300 Subject: [PATCH 36/38] approval cache --- .../impl/dispute_coordinator_impl.cpp | 2 +- .../approval/approval_distribution.cpp | 86 +++++++++++++------ .../approval/approval_distribution.hpp | 7 ++ 3 files changed, 70 insertions(+), 25 deletions(-) diff --git a/core/dispute_coordinator/impl/dispute_coordinator_impl.cpp b/core/dispute_coordinator/impl/dispute_coordinator_impl.cpp index ccd9560033..43368fa3eb 100644 --- a/core/dispute_coordinator/impl/dispute_coordinator_impl.cpp +++ b/core/dispute_coordinator/impl/dispute_coordinator_impl.cpp @@ -1847,7 +1847,7 @@ namespace kagome::dispute { return cb(res.as_failure()); } - auto &valid_import = res.value(); + [[maybe_unused]] auto &valid_import = res.value(); return cb(outcome::success()); } diff --git a/core/parachain/approval/approval_distribution.cpp b/core/parachain/approval/approval_distribution.cpp index 7331a51b45..4d9367695e 100644 --- a/core/parachain/approval/approval_distribution.cpp +++ b/core/parachain/approval/approval_distribution.cpp @@ -614,24 +614,34 @@ namespace kagome::parachain { if (const auto value = if_type( event)) { - for (const auto &lost : value->get()) { - SL_TRACE(logger_, - "Cleaning up stale pending messages.(block hash={})", - lost); - pending_known_.erase(lost); - active_tranches_.erase(lost); - approving_context_map_.erase(lost); - /// TODO(iceseer): `blocks_by_number_` clear on finalization - - if (auto block_entry = storedBlockEntries().get(lost)) { - for (const auto &candidate : block_entry->get().candidates) { - recovery_->remove(candidate.second); - storedCandidateEntries().extract(candidate.second); + approvals_cache_.exclusiveAccess([&](auto &approvals_cache) { + for (const auto &lost : value->get()) { + SL_TRACE(logger_, + "Cleaning up stale pending messages.(block hash={})", + lost); + pending_known_.erase(lost); + active_tranches_.erase(lost); + approving_context_map_.erase(lost); + /// TODO(iceseer): `blocks_by_number_` clear on finalization + + if (auto block_entry = storedBlockEntries().get(lost)) { + 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); + if (approval_cache.blocks_.empty()) { + approvals_cache.erase(it_cached); + } + } + } + storedBlockEntries().extract(lost); } - storedBlockEntries().extract(lost); + storedDistribBlockEntries().extract(lost); } - storedDistribBlockEntries().extract(lost); - } + }); } } @@ -1357,6 +1367,13 @@ namespace kagome::parachain { candidate_receipt, validation_code); + self->approvals_cache_.exclusiveAccess([&](auto &approvals_cache) { + if (auto it = approvals_cache.find(candidate_hash); + it != approvals_cache.end()) { + ApprovalCache &ac = it->second; + ac.approval_result = outcome; + } + }); if (ApprovalOutcome::Approved == outcome) { self->issue_approval( candidate_hash, validator_index, relay_block_hash); @@ -2396,14 +2413,35 @@ namespace kagome::parachain { import_and_circulate_assignment( std::nullopt, indirect_cert, candidate_index); - /// TODO(iceseer): make cache by 'candidate_hash' - launch_approval(relay_block_hash, - candidate_hash, - session, - candidate, - validator_index, - block_hash, - backing_group); + + std::optional approval_state = + approvals_cache_.exclusiveAccess( + [&](auto &approvals_cache) -> std::optional { + if (auto it = approvals_cache.find(candidate_hash); + it != approvals_cache.end()) { + it->second.blocks_.insert(relay_block_hash); + return it->second.approval_result; + } + approvals_cache.emplace( + candidate_hash, + ApprovalCache{ + .blocks_ = {relay_block_hash}, + .approval_result = ApprovalOutcome::Failed, + }); + return std::nullopt; + }); + + if (!approval_state) { + launch_approval(relay_block_hash, + candidate_hash, + session, + candidate, + validator_index, + block_hash, + backing_group); + } else if (*approval_state == ApprovalOutcome::Approved) { + issue_approval(candidate_hash, validator_index, block_hash); + } } void ApprovalDistribution::schedule_wakeup_action( diff --git a/core/parachain/approval/approval_distribution.hpp b/core/parachain/approval/approval_distribution.hpp index b2a40273d7..0a10e9e5d0 100644 --- a/core/parachain/approval/approval_distribution.hpp +++ b/core/parachain/approval/approval_distribution.hpp @@ -720,6 +720,13 @@ namespace kagome::parachain { std::unordered_map active_tranches_; + struct ApprovalCache { + std::unordered_set blocks_; + ApprovalOutcome approval_result; + }; + SafeObject, std::mutex> + approvals_cache_; + log::Logger logger_ = log::createLogger("ApprovalDistribution", "parachain"); }; From 44fd9a88f14455373074fd179deea175b5e3822e Mon Sep 17 00:00:00 2001 From: iceseer Date: Fri, 18 Aug 2023 11:38:50 +0300 Subject: [PATCH 37/38] tests --- test/core/CMakeLists.txt | 1 + test/core/crypto/crypto_store/CMakeLists.txt | 1 - .../crypto/crypto_store/crypto_store_test.cpp | 247 ++------------- test/core/parachain/CMakeLists.txt | 13 + test/core/parachain/assignments.cpp | 294 ++++++++++++++++++ 5 files changed, 330 insertions(+), 226 deletions(-) create mode 100644 test/core/parachain/CMakeLists.txt create mode 100644 test/core/parachain/assignments.cpp diff --git a/test/core/CMakeLists.txt b/test/core/CMakeLists.txt index c24182ea26..5d0da9502a 100644 --- a/test/core/CMakeLists.txt +++ b/test/core/CMakeLists.txt @@ -24,3 +24,4 @@ add_subdirectory(subscription) add_subdirectory(telemetry) add_subdirectory(transaction_pool) add_subdirectory(dispute_coordinator) +add_subdirectory(parachain) diff --git a/test/core/crypto/crypto_store/CMakeLists.txt b/test/core/crypto/crypto_store/CMakeLists.txt index b59a159c0b..185598659a 100644 --- a/test/core/crypto/crypto_store/CMakeLists.txt +++ b/test/core/crypto/crypto_store/CMakeLists.txt @@ -16,7 +16,6 @@ addtest(crypto_store_test target_link_libraries(crypto_store_test crypto_store base_fs_test - validator_parachain ) addtest(session_keys_test diff --git a/test/core/crypto/crypto_store/crypto_store_test.cpp b/test/core/crypto/crypto_store/crypto_store_test.cpp index 26be14ae38..d5a6975e7d 100644 --- a/test/core/crypto/crypto_store/crypto_store_test.cpp +++ b/test/core/crypto/crypto_store/crypto_store_test.cpp @@ -15,16 +15,10 @@ #include "crypto/random_generator/boost_generator.hpp" #include "crypto/sr25519/sr25519_provider_impl.hpp" -#include -#include #include "testutil/outcome.hpp" #include "testutil/prepare_loggers.hpp" #include "testutil/storage/base_fs_test.hpp" -#include "common/blob.hpp" -#include "common/visitor.hpp" -#include "parachain/approval/approval_distribution.hpp" - using kagome::common::Blob; using kagome::common::Buffer; using kagome::crypto::Bip39Provider; @@ -127,49 +121,6 @@ struct CryptoStoreTest : public test::BaseFS_Test { return kagome::filesystem::exists(file_path); } - template - auto assignment_keys_plus_random(std::shared_ptr &cs, - const char *const (&accounts)[N], - size_t random) { - for (const auto &acc : accounts) { - [[maybe_unused]] auto _ = - cs->generateSr25519Keypair(KnownKeyTypeId::KEY_TYPE_ASGN, - std::string_view{acc}) - .value(); - } - for (size_t ix = 0ull; ix < random; ++ix) { - auto seed = std::to_string(ix); - [[maybe_unused]] auto _ = - cs->generateSr25519Keypair(KnownKeyTypeId::KEY_TYPE_ASGN, - std::string_view{seed}) - .value(); - } - return cs->getSr25519PublicKeys(KnownKeyTypeId::KEY_TYPE_ASGN).value(); - } - - auto create_crypto_store() { - auto hasher = std::make_shared(); - auto csprng = std::make_shared(); - auto ecdsa_provider = std::make_shared(hasher); - auto ed25519_provider = std::make_shared(hasher); - auto sr25519_provider = std::make_shared(); - - auto pbkdf2_provider = std::make_shared(); - auto bip39_provider = - std::make_shared(std::move(pbkdf2_provider), hasher); - - auto keystore_path = kagome::filesystem::path(__FILE__).parent_path() - / "subkey_keys" / "keystore"; - - return std::make_shared( - std::make_shared(std::move(ecdsa_provider)), - std::make_shared(std::move(ed25519_provider)), - std::make_shared(std::move(sr25519_provider)), - bip39_provider, - csprng, - kagome::crypto::KeyFileStorage::createAt(keystore_path).value()); - } - std::shared_ptr bip39_provider; std::shared_ptr crypto_store; std::string mnemonic; @@ -368,180 +319,26 @@ TEST_F(CryptoStoreTest, getSr25519PublicKeysSuccess) { * Currently incompatible with subkey because subkey doesn't append key type to * filename */ -TEST_F(CryptoStoreTest, succeeds_empty_for_0_cores) { - auto cs = create_crypto_store(); - auto asgn_keys = - assignment_keys_plus_random(cs, {"//Alice", "//Bob", "//Charlie"}, 0ull); - - ::RelayVRFStory vrf_story; - ::memset(vrf_story.data, 42, sizeof(vrf_story.data)); - - kagome::runtime::SessionInfo si; - for (const auto &a : asgn_keys) { - si.assignment_keys.emplace_back(a); - } - - si.n_cores = 0; - si.zeroth_delay_tranche_width = 10; - si.relay_vrf_modulo_samples = 3; - si.n_delay_tranches = 40; - - kagome::parachain::ApprovalDistribution::CandidateIncludedList - leaving_cores{}; - - auto assignments = - kagome::parachain::ApprovalDistribution::compute_assignments( - cs, si, vrf_story, leaving_cores); - - ASSERT_EQ(assignments.size(), 0ull); -} - -TEST_F(CryptoStoreTest, assign_to_nonzero_core) { - auto cs = create_crypto_store(); - auto asgn_keys = - assignment_keys_plus_random(cs, {"//Alice", "//Bob", "//Charlie"}, 0ull); - - auto c_a = - kagome::common::Hash256::fromHexWithPrefix( - "0x0000000000000000000000000000000000000000000000000000000000000000") - .value(); - auto c_b = - kagome::common::Hash256::fromHexWithPrefix( - "0x0101010101010101010101010101010101010101010101010101010101010101") - .value(); - - ::RelayVRFStory vrf_story; - ::memset(vrf_story.data, 42, sizeof(vrf_story.data)); - - kagome::runtime::SessionInfo si; - for (const auto &a : asgn_keys) { - si.assignment_keys.emplace_back(a); - } - - si.validator_groups.emplace_back( - std::vector{0}); - si.validator_groups.emplace_back( - std::vector{1, 2}); - si.n_cores = 2; - si.zeroth_delay_tranche_width = 10; - si.relay_vrf_modulo_samples = 3; - si.n_delay_tranches = 40; - - kagome::parachain::ApprovalDistribution::CandidateIncludedList leaving_cores = - {std::make_tuple(c_a, - kagome::network::CandidateReceipt{}, - (kagome::parachain::CoreIndex)0, - (kagome::parachain::GroupIndex)0), - std::make_tuple(c_b, - kagome::network::CandidateReceipt{}, - (kagome::parachain::CoreIndex)1, - (kagome::parachain::GroupIndex)1)}; - auto assignments = - kagome::parachain::ApprovalDistribution::compute_assignments( - cs, si, vrf_story, leaving_cores); - - ASSERT_EQ(assignments.size(), 1ull); - - auto it = assignments.find(1ull); - ASSERT_TRUE(it != assignments.end()); - - const kagome::parachain::ApprovalDistribution::OurAssignment &our_assignment = - it->second; - ASSERT_EQ(our_assignment.tranche, 0ull); - ASSERT_EQ(our_assignment.validator_index, 0); - ASSERT_EQ(our_assignment.triggered, false); - - ASSERT_TRUE( - kagome::is_type( - our_assignment.cert.kind)); - if (auto k = - kagome::if_type( - our_assignment.cert.kind)) { - ASSERT_EQ(k->get().sample, 2); - } - - const uint8_t - vrf_output[kagome::crypto::constants::sr25519::vrf::OUTPUT_SIZE] = { - 228, 179, 248, 78, 77, 169, 23, 184, 138, 204, 148, - 183, 13, 41, 176, 163, 162, 6, 237, 158, 220, 225, - 97, 251, 51, 144, 207, 239, 189, 2, 7, 66}; - ASSERT_EQ(0, - memcmp(&our_assignment.cert.vrf.output, - vrf_output, - kagome::crypto::constants::sr25519::vrf::OUTPUT_SIZE)); +TEST(CryptoStoreCompatibilityTest, DISABLED_SubkeyCompat) { + auto hasher = std::make_shared(); + auto csprng = std::make_shared(); + auto ecdsa_provider = std::make_shared(hasher); + auto ed25519_provider = std::make_shared(hasher); + auto sr25519_provider = std::make_shared(); + + auto pbkdf2_provider = std::make_shared(); + auto bip39_provider = + std::make_shared(std::move(pbkdf2_provider), hasher); + auto keystore_path = kagome::filesystem::path(__FILE__).parent_path() + / "subkey_keys" / "keystore"; + auto crypto_store = std::make_shared( + std::make_shared(std::move(ecdsa_provider)), + std::make_shared(std::move(ed25519_provider)), + std::make_shared(std::move(sr25519_provider)), + bip39_provider, + csprng, + kagome::crypto::KeyFileStorage::createAt(keystore_path).value()); + EXPECT_OUTCOME_TRUE( + keys, crypto_store->getEd25519PublicKeys(KnownKeyTypeId::KEY_TYPE_BABE)); + ASSERT_EQ(keys.size(), 1); } - -TEST_F(CryptoStoreTest, assignments_produced_for_non_backing) { - auto cs = create_crypto_store(); - auto asgn_keys = - assignment_keys_plus_random(cs, {"//Alice", "//Bob", "//Charlie"}, 0ull); - - auto c_a = - kagome::common::Hash256::fromHexWithPrefix( - "0x0000000000000000000000000000000000000000000000000000000000000000") - .value(); - auto c_b = - kagome::common::Hash256::fromHexWithPrefix( - "0x0101010101010101010101010101010101010101010101010101010101010101") - .value(); - - ::RelayVRFStory vrf_story; - ::memset(vrf_story.data, 42, sizeof(vrf_story.data)); - - kagome::runtime::SessionInfo si; - for (const auto &a : asgn_keys) { - si.assignment_keys.emplace_back(a); - } - - si.validator_groups.emplace_back( - std::vector{0}); - si.validator_groups.emplace_back( - std::vector{1, 2}); - si.n_cores = 2; - si.zeroth_delay_tranche_width = 10; - si.relay_vrf_modulo_samples = 3; - si.n_delay_tranches = 40; - - kagome::parachain::ApprovalDistribution::CandidateIncludedList leaving_cores = - {std::make_tuple(c_a, - kagome::network::CandidateReceipt{}, - (kagome::parachain::CoreIndex)0, - (kagome::parachain::GroupIndex)1), - std::make_tuple(c_b, - kagome::network::CandidateReceipt{}, - (kagome::parachain::CoreIndex)1, - (kagome::parachain::GroupIndex)0)}; - auto assignments = - kagome::parachain::ApprovalDistribution::compute_assignments( - cs, si, vrf_story, leaving_cores); - - ASSERT_EQ(assignments.size(), 1ull); - - auto it = assignments.find(0ull); - ASSERT_TRUE(it != assignments.end()); - - const kagome::parachain::ApprovalDistribution::OurAssignment &our_assignment = - it->second; - ASSERT_EQ(our_assignment.tranche, 0ull); - ASSERT_EQ(our_assignment.validator_index, 0); - ASSERT_EQ(our_assignment.triggered, false); - - ASSERT_TRUE( - kagome::is_type( - our_assignment.cert.kind)); - if (auto k = - kagome::if_type( - our_assignment.cert.kind)) { - ASSERT_EQ(k->get().sample, 0); - } - - const uint8_t - vrf_output[kagome::crypto::constants::sr25519::vrf::OUTPUT_SIZE] = { - 34, 247, 30, 171, 146, 67, 68, 83, 108, 206, 61, - 154, 115, 28, 180, 81, 28, 90, 68, 166, 49, 220, - 157, 41, 235, 223, 152, 45, 190, 202, 216, 39}; - ASSERT_EQ(0, - memcmp(&our_assignment.cert.vrf.output, - vrf_output, - kagome::crypto::constants::sr25519::vrf::OUTPUT_SIZE)); -} \ No newline at end of file diff --git a/test/core/parachain/CMakeLists.txt b/test/core/parachain/CMakeLists.txt new file mode 100644 index 0000000000..37c23ba2d3 --- /dev/null +++ b/test/core/parachain/CMakeLists.txt @@ -0,0 +1,13 @@ +# +# Copyright Soramitsu Co., Ltd. All Rights Reserved. +# SPDX-License-Identifier: Apache-2.0 +# + +addtest(assignments_test + assignments.cpp + ) +target_link_libraries(assignments_test + crypto_store + base_fs_test + validator_parachain + ) diff --git a/test/core/parachain/assignments.cpp b/test/core/parachain/assignments.cpp new file mode 100644 index 0000000000..a5fd58df92 --- /dev/null +++ b/test/core/parachain/assignments.cpp @@ -0,0 +1,294 @@ +/** + * Copyright Soramitsu Co., Ltd. All Rights Reserved. + * SPDX-License-Identifier: Apache-2.0 + */ + +#include "crypto/crypto_store/crypto_store_impl.hpp" + +#include + +#include "crypto/bip39/impl/bip39_provider_impl.hpp" +#include "crypto/ecdsa/ecdsa_provider_impl.hpp" +#include "crypto/ed25519/ed25519_provider_impl.hpp" +#include "crypto/hasher/hasher_impl.hpp" +#include "crypto/pbkdf2/impl/pbkdf2_provider_impl.hpp" +#include "crypto/random_generator/boost_generator.hpp" +#include "crypto/sr25519/sr25519_provider_impl.hpp" + +#include +#include +#include "testutil/outcome.hpp" +#include "testutil/prepare_loggers.hpp" +#include "testutil/storage/base_fs_test.hpp" + +#include "common/blob.hpp" +#include "common/visitor.hpp" +#include "parachain/approval/approval_distribution.hpp" + +using kagome::common::Blob; +using kagome::common::Buffer; +using kagome::crypto::Bip39Provider; +using kagome::crypto::Bip39ProviderImpl; +using kagome::crypto::BoostRandomGenerator; +using kagome::crypto::CryptoStore; +using kagome::crypto::CryptoStoreError; +using kagome::crypto::CryptoStoreImpl; +using kagome::crypto::EcdsaKeypair; +using kagome::crypto::EcdsaPrivateKey; +using kagome::crypto::EcdsaProvider; +using kagome::crypto::EcdsaProviderImpl; +using kagome::crypto::EcdsaPublicKey; +using kagome::crypto::EcdsaSuite; +using kagome::crypto::Ed25519Keypair; +using kagome::crypto::Ed25519PrivateKey; +using kagome::crypto::Ed25519Provider; +using kagome::crypto::Ed25519ProviderImpl; +using kagome::crypto::Ed25519PublicKey; +using kagome::crypto::Ed25519Seed; +using kagome::crypto::Ed25519Suite; +using kagome::crypto::HasherImpl; +using kagome::crypto::KeyTypeId; +using kagome::crypto::KnownKeyTypeId; +using kagome::crypto::Pbkdf2Provider; +using kagome::crypto::Pbkdf2ProviderImpl; +using kagome::crypto::Sr25519Keypair; +using kagome::crypto::Sr25519Provider; +using kagome::crypto::Sr25519ProviderImpl; +using kagome::crypto::Sr25519PublicKey; +using kagome::crypto::Sr25519SecretKey; +using kagome::crypto::Sr25519Seed; +using kagome::crypto::Sr25519Suite; + +static CryptoStoreImpl::Path assignments_directory = + kagome::filesystem::temp_directory_path() / "assignments_test"; + +struct AssignmentsTest : public test::BaseFS_Test { + static void SetUpTestCase() { + testutil::prepareLoggers(); + } + + AssignmentsTest() : BaseFS_Test(assignments_directory) {} + + void SetUp() override {} + + template + auto assignment_keys_plus_random(std::shared_ptr &cs, + const char *const (&accounts)[N], + size_t random) { + for (const auto &acc : accounts) { + [[maybe_unused]] auto _ = + cs->generateSr25519Keypair(KnownKeyTypeId::KEY_TYPE_ASGN, + std::string_view{acc}) + .value(); + } + for (size_t ix = 0ull; ix < random; ++ix) { + auto seed = std::to_string(ix); + [[maybe_unused]] auto _ = + cs->generateSr25519Keypair(KnownKeyTypeId::KEY_TYPE_ASGN, + std::string_view{seed}) + .value(); + } + return cs->getSr25519PublicKeys(KnownKeyTypeId::KEY_TYPE_ASGN).value(); + } + + auto create_crypto_store() { + auto hasher = std::make_shared(); + auto csprng = std::make_shared(); + auto ecdsa_provider = std::make_shared(hasher); + auto ed25519_provider = std::make_shared(hasher); + auto sr25519_provider = std::make_shared(); + + auto pbkdf2_provider = std::make_shared(); + auto bip39_provider = + std::make_shared(std::move(pbkdf2_provider), hasher); + + auto keystore_path = kagome::filesystem::path(__FILE__).parent_path() + / "subkey_keys" / "keystore"; + + return std::make_shared( + std::make_shared(std::move(ecdsa_provider)), + std::make_shared(std::move(ed25519_provider)), + std::make_shared(std::move(sr25519_provider)), + bip39_provider, + csprng, + kagome::crypto::KeyFileStorage::createAt(keystore_path).value()); + } +}; + +TEST_F(AssignmentsTest, succeeds_empty_for_0_cores) { + auto cs = create_crypto_store(); + auto asgn_keys = + assignment_keys_plus_random(cs, {"//Alice", "//Bob", "//Charlie"}, 0ull); + + ::RelayVRFStory vrf_story; + ::memset(vrf_story.data, 42, sizeof(vrf_story.data)); + + kagome::runtime::SessionInfo si; + for (const auto &a : asgn_keys) { + si.assignment_keys.emplace_back(a); + } + + si.n_cores = 0; + si.zeroth_delay_tranche_width = 10; + si.relay_vrf_modulo_samples = 3; + si.n_delay_tranches = 40; + + kagome::parachain::ApprovalDistribution::CandidateIncludedList + leaving_cores{}; + + auto assignments = + kagome::parachain::ApprovalDistribution::compute_assignments( + cs, si, vrf_story, leaving_cores, logger); + + ASSERT_EQ(assignments.size(), 0ull); +} + +TEST_F(AssignmentsTest, assign_to_nonzero_core) { + auto cs = create_crypto_store(); + auto asgn_keys = + assignment_keys_plus_random(cs, {"//Alice", "//Bob", "//Charlie"}, 0ull); + + auto c_a = + kagome::common::Hash256::fromHexWithPrefix( + "0x0000000000000000000000000000000000000000000000000000000000000000") + .value(); + auto c_b = + kagome::common::Hash256::fromHexWithPrefix( + "0x0101010101010101010101010101010101010101010101010101010101010101") + .value(); + + ::RelayVRFStory vrf_story; + ::memset(vrf_story.data, 42, sizeof(vrf_story.data)); + + kagome::runtime::SessionInfo si; + for (const auto &a : asgn_keys) { + si.assignment_keys.emplace_back(a); + } + + si.validator_groups.emplace_back( + std::vector{0}); + si.validator_groups.emplace_back( + std::vector{1, 2}); + si.n_cores = 2; + si.zeroth_delay_tranche_width = 10; + si.relay_vrf_modulo_samples = 3; + si.n_delay_tranches = 40; + + kagome::parachain::ApprovalDistribution::CandidateIncludedList leaving_cores = + {std::make_tuple(c_a, + kagome::network::CandidateReceipt{}, + (kagome::parachain::CoreIndex)0, + (kagome::parachain::GroupIndex)0), + std::make_tuple(c_b, + kagome::network::CandidateReceipt{}, + (kagome::parachain::CoreIndex)1, + (kagome::parachain::GroupIndex)1)}; + auto assignments = + kagome::parachain::ApprovalDistribution::compute_assignments( + cs, si, vrf_story, leaving_cores, logger); + + ASSERT_EQ(assignments.size(), 1ull); + + auto it = assignments.find(1ull); + ASSERT_TRUE(it != assignments.end()); + + const kagome::parachain::ApprovalDistribution::OurAssignment &our_assignment = + it->second; + ASSERT_EQ(our_assignment.tranche, 0ull); + ASSERT_EQ(our_assignment.validator_index, 0); + ASSERT_EQ(our_assignment.triggered, false); + + ASSERT_TRUE( + kagome::is_type( + our_assignment.cert.kind)); + if (auto k = + kagome::if_type( + our_assignment.cert.kind)) { + ASSERT_EQ(k->get().sample, 2); + } + + const uint8_t + vrf_output[kagome::crypto::constants::sr25519::vrf::OUTPUT_SIZE] = { + 228, 179, 248, 78, 77, 169, 23, 184, 138, 204, 148, + 183, 13, 41, 176, 163, 162, 6, 237, 158, 220, 225, + 97, 251, 51, 144, 207, 239, 189, 2, 7, 66}; + ASSERT_EQ(0, + memcmp(&our_assignment.cert.vrf.output, + vrf_output, + kagome::crypto::constants::sr25519::vrf::OUTPUT_SIZE)); +} + +TEST_F(AssignmentsTest, assignments_produced_for_non_backing) { + auto cs = create_crypto_store(); + auto asgn_keys = + assignment_keys_plus_random(cs, {"//Alice", "//Bob", "//Charlie"}, 0ull); + + auto c_a = + kagome::common::Hash256::fromHexWithPrefix( + "0x0000000000000000000000000000000000000000000000000000000000000000") + .value(); + auto c_b = + kagome::common::Hash256::fromHexWithPrefix( + "0x0101010101010101010101010101010101010101010101010101010101010101") + .value(); + + ::RelayVRFStory vrf_story; + ::memset(vrf_story.data, 42, sizeof(vrf_story.data)); + + kagome::runtime::SessionInfo si; + for (const auto &a : asgn_keys) { + si.assignment_keys.emplace_back(a); + } + + si.validator_groups.emplace_back( + std::vector{0}); + si.validator_groups.emplace_back( + std::vector{1, 2}); + si.n_cores = 2; + si.zeroth_delay_tranche_width = 10; + si.relay_vrf_modulo_samples = 3; + si.n_delay_tranches = 40; + + kagome::parachain::ApprovalDistribution::CandidateIncludedList leaving_cores = + {std::make_tuple(c_a, + kagome::network::CandidateReceipt{}, + (kagome::parachain::CoreIndex)0, + (kagome::parachain::GroupIndex)1), + std::make_tuple(c_b, + kagome::network::CandidateReceipt{}, + (kagome::parachain::CoreIndex)1, + (kagome::parachain::GroupIndex)0)}; + auto assignments = + kagome::parachain::ApprovalDistribution::compute_assignments( + cs, si, vrf_story, leaving_cores, logger); + + ASSERT_EQ(assignments.size(), 1ull); + + auto it = assignments.find(0ull); + ASSERT_TRUE(it != assignments.end()); + + const kagome::parachain::ApprovalDistribution::OurAssignment &our_assignment = + it->second; + ASSERT_EQ(our_assignment.tranche, 0ull); + ASSERT_EQ(our_assignment.validator_index, 0); + ASSERT_EQ(our_assignment.triggered, false); + + ASSERT_TRUE( + kagome::is_type( + our_assignment.cert.kind)); + if (auto k = + kagome::if_type( + our_assignment.cert.kind)) { + ASSERT_EQ(k->get().sample, 0); + } + + const uint8_t + vrf_output[kagome::crypto::constants::sr25519::vrf::OUTPUT_SIZE] = { + 34, 247, 30, 171, 146, 67, 68, 83, 108, 206, 61, + 154, 115, 28, 180, 81, 28, 90, 68, 166, 49, 220, + 157, 41, 235, 223, 152, 45, 190, 202, 216, 39}; + ASSERT_EQ(0, + memcmp(&our_assignment.cert.vrf.output, + vrf_output, + kagome::crypto::constants::sr25519::vrf::OUTPUT_SIZE)); +} \ No newline at end of file From 736f1072e3256e2d34fea5e9089b0bf977c013bd Mon Sep 17 00:00:00 2001 From: iceseer Date: Sun, 20 Aug 2023 21:40:26 +0300 Subject: [PATCH 38/38] issues fixes --- .../approval/approval_distribution.cpp | 88 +++++-------------- .../approval/approval_distribution.hpp | 6 +- core/parachain/approval/knowledge.hpp | 15 ++-- test/core/parachain/assignments.cpp | 47 +++------- 4 files changed, 44 insertions(+), 112 deletions(-) diff --git a/core/parachain/approval/approval_distribution.cpp b/core/parachain/approval/approval_distribution.cpp index 4d9367695e..36c55e7389 100644 --- a/core/parachain/approval/approval_distribution.cpp +++ b/core/parachain/approval/approval_distribution.cpp @@ -358,14 +358,11 @@ namespace { const kagome::parachain::ApprovalDistribution::CandidateEntry &candidate_entry, const kagome::parachain::approval::RequiredTranches &required_tranches, - kagome::network::DelayTranche const tranche_now, - kagome::log::Logger &logger) { + kagome::network::DelayTranche const tranche_now) { if (!approval_entry.our_assignment) { - SL_TRACE(logger, "No assignment"); return false; } if (approval_entry.our_assignment->triggered) { - SL_TRACE(logger, "Already triggered"); return false; } if (approval_entry.our_assignment->tranche == 0) { @@ -373,13 +370,11 @@ namespace { } if (kagome::is_type( required_tranches)) { - const bool r = !kagome::parachain::approval::is_approved( + return !kagome::parachain::approval::is_approved( checkApproval(candidate_entry, approval_entry, kagome::parachain::approval::AllRequiredTranche{}), std::numeric_limits::max()); - SL_TRACE(logger, "AllRequiredTranche return. (res={})", r); - return r; } if (auto pending = kagome::if_type< const kagome::parachain::approval::PendingRequiredTranche>( @@ -387,16 +382,12 @@ namespace { const auto drifted_tranche_now = kagome::math::sat_sub_unsigned( tranche_now, kagome::network::DelayTranche(pending->get().clock_drift)); - const auto r = - approval_entry.our_assignment->tranche + return approval_entry.our_assignment->tranche <= pending->get().maximum_broadcast && approval_entry.our_assignment->tranche <= drifted_tranche_now; - SL_TRACE(logger, "PendingRequiredTranche return. (res={})", r); - return r; } if (kagome::is_type( required_tranches)) { - SL_TRACE(logger, "ExactRequiredTranche return false."); return false; } UNREACHABLE; @@ -648,12 +639,7 @@ namespace kagome::parachain { std::optional> ApprovalDistribution::findAssignmentKey( const std::shared_ptr &keystore, - const runtime::SessionInfo &config, - log::Logger &logger) { - auto keys = keystore->getSr25519PublicKeys(crypto::KEY_TYPE_ASGN).value(); - for (const auto &key : keys) { - SL_TRACE(logger, "PK FOR ASSIGNMENT: {}", key.toHex()); - } + const runtime::SessionInfo &config) { for (size_t ix = 0; ix < config.assignment_keys.size(); ++ix) { const auto &pk = config.assignment_keys[ix]; if (auto res = keystore->findSr25519Keypair( @@ -671,15 +657,14 @@ namespace kagome::parachain { const std::shared_ptr &keystore, const runtime::SessionInfo &config, const RelayVRFStory &relay_vrf_story, - const CandidateIncludedList &leaving_cores, - log::Logger &logger) { + const CandidateIncludedList &leaving_cores) { if (config.n_cores == 0 || config.assignment_keys.empty() || config.validator_groups.empty()) { return {}; } std::optional> - founded_key = findAssignmentKey(keystore, config, logger); + founded_key = findAssignmentKey(keystore, config); if (!founded_key) { return {}; } @@ -807,12 +792,8 @@ namespace kagome::parachain { return; } - SL_TRACE( - logger_, - "UNSAFE VRF: {}", - common::BufferView(relay_vrf.data, sizeof(relay_vrf.data)).toHex()); auto assignments = compute_assignments( - keystore_, session_info, relay_vrf, *ac.included_candidates, logger_); + keystore_, session_info, relay_vrf, *ac.included_candidates); /// TODO(iceseer): force approve impl @@ -926,15 +907,6 @@ namespace kagome::parachain { babe_util_->slotToEpoch(*block_header.parentInfo(), babe_digests.second.slot_number)); - SL_TRACE(logger_, - "REQUEST BABE DATA. (epoch={}, randomness={})", - epoch, - babe_config.randomness.toHex()); - - for (const auto &a : babe_config.authorities) { - SL_TRACE(logger_, "Auth. (a={})", a.id.id.toHex()); - } - return std::make_tuple(epoch, std::move(babe_digests.second), std::move(babe_config.authorities), @@ -1665,7 +1637,7 @@ namespace kagome::parachain { auto message_subject{ std::make_tuple(block_hash, claimed_candidate_index, validator_index)}; - approval::MessageKindAssignment message_kind{}; + auto message_kind{approval::MessageKind::Assignment}; if (source) { const auto &peer_id = source->get(); @@ -1782,20 +1754,17 @@ namespace kagome::parachain { const bool already_sent = peer_kn.sent.contains(message_subject, - approval::MessageKindAssignment{}) + approval::MessageKind::Assignment) || peer_kn.sent.contains(message_subject, - approval::MessageKindApproval{}); + approval::MessageKind::Approval); return !already_sent; }; std::unordered_set peers{}; - for (const auto &[peer_id, peer_knowledge] : entry.known_by) { + for (auto &[peer_id, peer_knowledge] : entry.known_by) { if (peer_filter(peer_id, peer_knowledge)) { peers.insert(peer_id); - if (auto it = entry.known_by.find(peer_id); - it != entry.known_by.end()) { - it->second.sent.insert(message_subject, message_kind); - } + peer_knowledge.sent.insert(message_subject, message_kind); } } @@ -1859,12 +1828,12 @@ namespace kagome::parachain { auto message_subject{ std::make_tuple(block_hash, candidate_index, validator_index)}; - approval::MessageKindApproval message_kind{}; + auto message_kind{approval::MessageKind::Approval}; if (source) { const auto &peer_id = source->get(); if (!entry.knowledge.contains(message_subject, - approval::MessageKindAssignment{})) { + approval::MessageKind::Assignment)) { SL_TRACE(logger_, "Unknown approval assignment. (peer id={}, block hash={}, " "candidate={}, validator={})", @@ -1975,17 +1944,14 @@ namespace kagome::parachain { return false; } return peer_kn.sent.contains(message_subject, - approval::MessageKindAssignment{}); + approval::MessageKind::Assignment); }; std::unordered_set peers{}; - for (const auto &[peer_id, peer_knowledge] : entry.known_by) { + for (auto &[peer_id, peer_knowledge] : entry.known_by) { if (peer_filter(peer_id, peer_knowledge)) { peers.insert(peer_id); - if (auto it = entry.known_by.find(peer_id); - it != entry.known_by.end()) { - it->second.sent.insert(message_subject, message_kind); - } + peer_knowledge.sent.insert(message_subject, message_kind); } } @@ -2662,13 +2628,6 @@ namespace kagome::parachain { const auto ms_wakeup_after = math::sat_sub_unsigned(ms_wakeup, ms_now); auto &target_block = active_tranches_[block_hash]; - // auto target_candidate = target_block.find(candidate_hash); - /* if (target_candidate != target_block.end()) { - if (target_candidate->second.first <= tick) { - return; - } - }*/ - SL_TRACE(logger_, "Scheduling wakeup. (block_hash={}, candidate_hash={}, " "block_number={}, tick={}, after={})", @@ -2693,8 +2652,7 @@ namespace kagome::parachain { target_block_it != self->active_tranches_.end()) { if (ec) { SL_TRACE(self->logger_, - "Tranche operation waiting failed " - "timer: {}", + "Tranche operation waiting failed timer: {}", ec.message()); return; } @@ -2773,7 +2731,7 @@ namespace kagome::parachain { no_show_duration, session_info.needed_approvals); const auto should_trigger = shouldTriggerAssignment( - approval_entry, candidate_entry, tta, tranche_now, logger_); + approval_entry, candidate_entry, tta, tranche_now); const auto backing_group = approval_entry.backing_group; const auto &candidate_receipt = candidate_entry.candidate; @@ -2869,9 +2827,9 @@ namespace kagome::parachain { }); if (!peer_knowledge.contains(message_subject, - approval::MessageKindAssignment{})) { + approval::MessageKind::Assignment)) { peer_knowledge.sent.insert(message_subject, - approval::MessageKindAssignment{}); + approval::MessageKind::Assignment); assignments_to_send.emplace_back(network::Assignment{ .indirect_assignment_cert = @@ -2886,9 +2844,9 @@ namespace kagome::parachain { if (opt_ref_approval_sig) { if (!peer_knowledge.contains(message_subject, - approval::MessageKindApproval{})) { + approval::MessageKind::Approval)) { peer_knowledge.sent.insert(message_subject, - approval::MessageKindApproval{}); + approval::MessageKind::Approval); approvals_to_send.emplace_back( network::IndirectSignedApprovalVote{ diff --git a/core/parachain/approval/approval_distribution.hpp b/core/parachain/approval/approval_distribution.hpp index 0a10e9e5d0..3e3bb15ee2 100644 --- a/core/parachain/approval/approval_distribution.hpp +++ b/core/parachain/approval/approval_distribution.hpp @@ -290,8 +290,7 @@ namespace kagome::parachain { const std::shared_ptr &keystore, const runtime::SessionInfo &config, const RelayVRFStory &relay_vrf_story, - const CandidateIncludedList &leaving_cores, - log::Logger &logger); + const CandidateIncludedList &leaving_cores); void onValidationProtocolMsg( const libp2p::peer::PeerId &peer_id, @@ -545,8 +544,7 @@ namespace kagome::parachain { static std::optional> findAssignmentKey(const std::shared_ptr &keystore, - const runtime::SessionInfo &config, - log::Logger &logger); + const runtime::SessionInfo &config); void unify_with_peer(StoreUnit> &entries, const libp2p::peer::PeerId &peer_id, diff --git a/core/parachain/approval/knowledge.hpp b/core/parachain/approval/knowledge.hpp index d8f509d2dc..0bfe2cfed2 100644 --- a/core/parachain/approval/knowledge.hpp +++ b/core/parachain/approval/knowledge.hpp @@ -17,10 +17,7 @@ namespace kagome::parachain::approval { - struct MessageKindAssignment {}; - struct MessageKindApproval {}; - using MessageKind = - boost::variant; + enum struct MessageKind { Assignment, Approval }; using MessageSubject = std::tuple; struct MessageSubjectHash { @@ -46,10 +43,10 @@ namespace kagome::parachain::approval { if (it == known_messages.end()) { return false; } - if (is_type(kind)) { + if (MessageKind::Assignment == kind) { return true; } - return is_type(it->second); + return MessageKind::Approval == it->second; } bool insert(const MessageSubject &message, const MessageKind &kind) { @@ -57,9 +54,9 @@ namespace kagome::parachain::approval { if (inserted) { return true; } - if (is_type(it->second) - && is_type(kind)) { - it->second = MessageKindApproval{}; + if (MessageKind::Assignment == it->second + && MessageKind::Approval == kind) { + it->second = MessageKind::Approval; return true; } return false; diff --git a/test/core/parachain/assignments.cpp b/test/core/parachain/assignments.cpp index a5fd58df92..d6e7cbe765 100644 --- a/test/core/parachain/assignments.cpp +++ b/test/core/parachain/assignments.cpp @@ -27,37 +27,7 @@ using kagome::common::Blob; using kagome::common::Buffer; -using kagome::crypto::Bip39Provider; -using kagome::crypto::Bip39ProviderImpl; -using kagome::crypto::BoostRandomGenerator; -using kagome::crypto::CryptoStore; -using kagome::crypto::CryptoStoreError; -using kagome::crypto::CryptoStoreImpl; -using kagome::crypto::EcdsaKeypair; -using kagome::crypto::EcdsaPrivateKey; -using kagome::crypto::EcdsaProvider; -using kagome::crypto::EcdsaProviderImpl; -using kagome::crypto::EcdsaPublicKey; -using kagome::crypto::EcdsaSuite; -using kagome::crypto::Ed25519Keypair; -using kagome::crypto::Ed25519PrivateKey; -using kagome::crypto::Ed25519Provider; -using kagome::crypto::Ed25519ProviderImpl; -using kagome::crypto::Ed25519PublicKey; -using kagome::crypto::Ed25519Seed; -using kagome::crypto::Ed25519Suite; -using kagome::crypto::HasherImpl; -using kagome::crypto::KeyTypeId; -using kagome::crypto::KnownKeyTypeId; -using kagome::crypto::Pbkdf2Provider; -using kagome::crypto::Pbkdf2ProviderImpl; -using kagome::crypto::Sr25519Keypair; -using kagome::crypto::Sr25519Provider; -using kagome::crypto::Sr25519ProviderImpl; -using kagome::crypto::Sr25519PublicKey; -using kagome::crypto::Sr25519SecretKey; -using kagome::crypto::Sr25519Seed; -using kagome::crypto::Sr25519Suite; +using namespace kagome::crypto; static CryptoStoreImpl::Path assignments_directory = kagome::filesystem::temp_directory_path() / "assignments_test"; @@ -115,6 +85,9 @@ struct AssignmentsTest : public test::BaseFS_Test { } }; +/** + * There should be no assignments in no cores available. + */ TEST_F(AssignmentsTest, succeeds_empty_for_0_cores) { auto cs = create_crypto_store(); auto asgn_keys = @@ -138,11 +111,14 @@ TEST_F(AssignmentsTest, succeeds_empty_for_0_cores) { auto assignments = kagome::parachain::ApprovalDistribution::compute_assignments( - cs, si, vrf_story, leaving_cores, logger); + cs, si, vrf_story, leaving_cores); ASSERT_EQ(assignments.size(), 0ull); } +/** + * There should be an assignment for a 1 core. + */ TEST_F(AssignmentsTest, assign_to_nonzero_core) { auto cs = create_crypto_store(); auto asgn_keys = @@ -185,7 +161,7 @@ TEST_F(AssignmentsTest, assign_to_nonzero_core) { (kagome::parachain::GroupIndex)1)}; auto assignments = kagome::parachain::ApprovalDistribution::compute_assignments( - cs, si, vrf_story, leaving_cores, logger); + cs, si, vrf_story, leaving_cores); ASSERT_EQ(assignments.size(), 1ull); @@ -218,6 +194,9 @@ TEST_F(AssignmentsTest, assign_to_nonzero_core) { kagome::crypto::constants::sr25519::vrf::OUTPUT_SIZE)); } +/** + * There should be an assignment for a 1 core. + */ TEST_F(AssignmentsTest, assignments_produced_for_non_backing) { auto cs = create_crypto_store(); auto asgn_keys = @@ -260,7 +239,7 @@ TEST_F(AssignmentsTest, assignments_produced_for_non_backing) { (kagome::parachain::GroupIndex)0)}; auto assignments = kagome::parachain::ApprovalDistribution::compute_assignments( - cs, si, vrf_story, leaving_cores, logger); + cs, si, vrf_story, leaving_cores); ASSERT_EQ(assignments.size(), 1ull);