Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feature/disabled validators #2162

Merged
merged 6 commits into from
Aug 2, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
102 changes: 88 additions & 14 deletions core/parachain/validator/impl/parachain_processor.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -119,6 +119,8 @@ OUTCOME_CPP_DEFINE_CATEGORY(kagome::parachain,
return "Not advertised";
case E::WRONG_PARA:
return "Wrong para id";
case E::THRESHOLD_LIMIT_REACHED:
return "Threshold reached";
iceseer marked this conversation as resolved.
Show resolved Hide resolved
}
return "Unknown parachain processor error";
}
Expand Down Expand Up @@ -1046,6 +1048,8 @@ namespace kagome::parachain {
OUTCOME_TRY(session_info,
parachain_host_->session_info(relay_parent, session_index));
OUTCOME_TRY(randomness, getBabeRandomness(block_header));
OUTCOME_TRY(disabled_validators_,
parachain_host_->disabled_validators(relay_parent));
const auto &[validator_groups, group_rotation_info] = groups;

if (!validator) {
Expand Down Expand Up @@ -1214,6 +1218,14 @@ namespace kagome::parachain {
seconding_limit,
mode->max_candidate_depth);

std::unordered_set<ValidatorIndex> disabled_validators{
disabled_validators_.begin(), disabled_validators_.end()};
if (!disabled_validators.empty()) {
SL_TRACE(logger_,
"Disabled validators detected. (relay parent={})",
relay_parent);
}

SL_VERBOSE(logger_,
"Inited new backing task v3.(assigned_para={}, "
"assigned_core={}, our index={}, relay "
Expand Down Expand Up @@ -1249,6 +1261,8 @@ namespace kagome::parachain {
.issued_statements = {},
.peers_advertised = {},
.fallbacks = {},
.backed_hashes = {},
.disabled_validators = std::move(disabled_validators),
.inject_core_index = inject_core_index,
};
}
Expand Down Expand Up @@ -1577,7 +1591,7 @@ namespace kagome::parachain {
const libp2p::peer::PeerId &peer_id,
const CandidateHash &candidate_hash,
const RelayHash &relay_parent,
const ManifestSummary &manifest_summary,
ManifestSummary manifest_summary,
ParachainId para_id,
grid::ManifestKind manifest_kind) {
auto peer_state = pm_->getPeerState(peer_id);
Expand Down Expand Up @@ -1633,8 +1647,18 @@ namespace kagome::parachain {
auto group_index = manifest_summary.claimed_group_index;
auto claimed_parent_hash = manifest_summary.claimed_parent_hash;

/// TODO(iceseer): do `disabled validators`
/// https://github.com/qdrvm/kagome/issues/2060
auto group = [&]() -> std::span<const ValidatorIndex> {
if (auto g =
relay_parent_state->get().per_session_state->value().groups.get(
group_index)) {
return *g;
}
return {};
}();

auto disabled_mask = relay_parent_state->get().disabled_bitmask(group);
manifest_summary.statement_knowledge.mask_seconded(disabled_mask);
manifest_summary.statement_knowledge.mask_valid(disabled_mask);

BOOST_ASSERT(relay_parent_state->get().prospective_parachains_mode);
const auto seconding_limit =
Expand Down Expand Up @@ -2165,8 +2189,17 @@ namespace kagome::parachain {

const auto &session_info =
parachain_state->get().per_session_state->value().session_info;
CHECK_OR_RET(parachain_state->get().local_validator);
if (parachain_state->get().is_disabled(stm.compact.payload.ix)) {
SL_TRACE(
logger_,
"Ignoring a statement from disabled validator. (relay parent={}, "
"validator={})",
stm.relay_parent,
stm.compact.payload.ix);
return;
}

CHECK_OR_RET(parachain_state->get().local_validator);
auto &local_validator = *parachain_state->get().local_validator;
auto originator_group =
parachain_state->get()
Expand All @@ -2181,9 +2214,6 @@ namespace kagome::parachain {
return;
}

/// TODO(iceseer): do `disabled validators`
/// https://github.com/qdrvm/kagome/issues/2060

auto &active = local_validator.active;
auto cluster_sender_index = [&]() -> std::optional<ValidatorIndex> {
std::span<const ValidatorIndex> allowed_senders;
Expand Down Expand Up @@ -2510,9 +2540,21 @@ namespace kagome::parachain {
}
}

/// TODO(iceseer): do `disabled validators`
/// Add disabled validators to the unwanted mask.
/// https://github.com/qdrvm/kagome/issues/2060
auto disabled_mask = relay_parent_state.disabled_bitmask(*group);
if (disabled_mask.bits.size()
> unwanted_mask.seconded_in_group.bits.size()) {
unwanted_mask.seconded_in_group.bits.resize(disabled_mask.bits.size());
}
if (disabled_mask.bits.size()
> unwanted_mask.validated_in_group.bits.size()) {
unwanted_mask.validated_in_group.bits.resize(disabled_mask.bits.size());
}
for (size_t i = 0; i < disabled_mask.bits.size(); ++i) {
unwanted_mask.seconded_in_group.bits[i] =
unwanted_mask.seconded_in_group.bits[i] || disabled_mask.bits[i];
unwanted_mask.validated_in_group.bits[i] =
unwanted_mask.validated_in_group.bits[i] || disabled_mask.bits[i];
}

auto backing_threshold = [&]() -> std::optional<size_t> {
auto bt = relay_parent_state.per_session_state->value()
Expand Down Expand Up @@ -3193,16 +3235,48 @@ namespace kagome::parachain {
init_with_not(and_mask.seconded_in_group, request.mask.seconded_in_group);
init_with_not(and_mask.validated_in_group, request.mask.validated_in_group);

/// TODO(iceseer): do `disabled validators` check
/// https://github.com/qdrvm/kagome/issues/2060
std::vector<IndexedAndSigned<network::vstaging::CompactStatement>>
statements;
network::vstaging::StatementFilter sent_filter(group_size);
relay_parent_state.get().statement_store->groupStatements(
*group,
request.candidate_hash,
and_mask,
[&](const IndexedAndSigned<network::vstaging::CompactStatement>
&statement) { statements.emplace_back(statement); });
&statement) {
for (size_t ix = 0; ix < group->size(); ++ix) {
if ((*group)[ix] == statement.payload.ix) {
visit_in_place(
getPayload(statement).inner_value,
[&](const network::vstaging::SecondedCandidateHash &) {
sent_filter.seconded_in_group.bits[ix] = true;
},
[&](const network::vstaging::ValidCandidateHash &) {
sent_filter.validated_in_group.bits[ix] = true;
},
[&](const auto &) {});
}
}
statements.emplace_back(statement);
});

if (!is_cluster) {
auto threshold = std::get<1>(*groups.get_size_and_backing_threshold(
confirmed->get().group_index()));
const auto seconded_and_sufficient =
(sent_filter.has_seconded()
&& sent_filter.backing_validators() >= threshold);
if (!seconded_and_sufficient) {
SL_INFO(logger_,
"Dropping a request from a grid peer because the backing "
"threshold is no longer met. (relay_parent={}, "
"candidate_hash={}, group_index={})",
confirmed->get().relay_parent(),
request.candidate_hash,
confirmed->get().group_index());
return Error::THRESHOLD_LIMIT_REACHED;
}
}

for (const auto &statement : statements) {
if (is_cluster) {
Expand Down Expand Up @@ -3329,7 +3403,7 @@ namespace kagome::parachain {
.from_validator = statement.payload.ix,
.backing = {}};

auto const &[it, _] = fallbacks.insert(
const auto &[it, _] = fallbacks.insert(
std::make_pair(candidate_hash, std::move(attesting)));
return it->second;
},
Expand Down
22 changes: 19 additions & 3 deletions core/parachain/validator/parachain_processor.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -132,7 +132,8 @@ namespace kagome::parachain {
NO_PEER,
ALREADY_REQUESTED,
NOT_ADVERTISED,
WRONG_PARA
WRONG_PARA,
THRESHOLD_LIMIT_REACHED,
};
static constexpr uint64_t kBackgroundWorkers = 5;

Expand Down Expand Up @@ -447,9 +448,24 @@ namespace kagome::parachain {
std::unordered_set<primitives::BlockHash> issued_statements;
std::unordered_set<network::PeerId> peers_advertised;
std::unordered_map<primitives::BlockHash, AttestingData> fallbacks;
std::unordered_set<CandidateHash> backed_hashes{};
std::unordered_set<CandidateHash> backed_hashes;
std::unordered_set<ValidatorIndex> disabled_validators;

bool inject_core_index;

bool is_disabled(ValidatorIndex validator_index) const {
return disabled_validators.contains(validator_index);
}

scale::BitVec disabled_bitmask(
const std::span<const ValidatorIndex> &group) const {
scale::BitVec v;
v.bits.resize(group.size());
for (size_t ix = 0; ix < group.size(); ++ix) {
v.bits[ix] = is_disabled(group[ix]);
}
return v;
}
};

/**
Expand Down Expand Up @@ -658,7 +674,7 @@ namespace kagome::parachain {
const libp2p::peer::PeerId &peer_id,
const CandidateHash &candidate_hash,
const RelayHash &relay_parent,
const ManifestSummary &manifest_summary,
ManifestSummary manifest_summary,
ParachainId para_id,
grid::ManifestKind manifest_kind);
network::vstaging::StatementFilter local_knowledge_filter(
Expand Down
Loading