Skip to content

Commit 2427dd8

Browse files
committed
use the accumulated disabled state per session
1 parent 681883b commit 2427dd8

File tree

2 files changed

+48
-65
lines changed

2 files changed

+48
-65
lines changed

polkadot/node/network/statement-distribution/src/v2/mod.rs

Lines changed: 44 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
//! Implementation of the v2 statement distribution protocol,
1818
//! designed for asynchronous backing.
1919
20+
use bitvec::prelude::{BitVec, Lsb0};
2021
use polkadot_node_network_protocol::{
2122
self as net_protocol,
2223
grid_topology::SessionGridTopology,
@@ -63,7 +64,7 @@ use futures::{
6364
use std::{
6465
collections::{
6566
hash_map::{Entry, HashMap},
66-
HashSet,
67+
BTreeSet, HashSet,
6768
},
6869
time::{Duration, Instant},
6970
};
@@ -162,6 +163,9 @@ struct PerSessionState {
162163
// getting the topology from the gossip-support subsystem
163164
grid_view: Option<grid::SessionTopologyView>,
164165
local_validator: Option<ValidatorIndex>,
166+
// We assume that the validators are never re-enabled per session
167+
// and store the latest state here.
168+
disabled_validators: BTreeSet<ValidatorIndex>,
165169
}
166170

167171
impl PerSessionState {
@@ -183,6 +187,7 @@ impl PerSessionState {
183187
authority_lookup,
184188
grid_view: None,
185189
local_validator: local_validator.map(|(_key, index)| index),
190+
disabled_validators: BTreeSet::new(),
186191
}
187192
}
188193

@@ -195,6 +200,34 @@ impl PerSessionState {
195200

196201
self.grid_view = Some(grid_view);
197202
}
203+
204+
/// A convenience function to generate a disabled bitmask for the given backing group.
205+
/// The output bits are set to `true` for validators that are disabled.
206+
/// Returns `None` if the group index is out of bounds.
207+
pub fn disabled_bitmask(&self, group: GroupIndex) -> Option<BitVec<u8, Lsb0>> {
208+
let group = self.groups.get(group)?;
209+
let group_size = group.len();
210+
let mut mask = BitVec::repeat(false, group_size);
211+
for (i, v) in group.iter().enumerate() {
212+
if self.is_disabled(v) {
213+
mask.set(i, true);
214+
}
215+
}
216+
Some(mask)
217+
}
218+
219+
/// Returns `true` if the given validator is disabled in the current session.
220+
pub fn is_disabled(&self, validator_index: &ValidatorIndex) -> bool {
221+
self.disabled_validators.contains(validator_index)
222+
}
223+
224+
/// Extend the set of disabled validators for the current session.
225+
pub fn extend_disabled_validators(
226+
&mut self,
227+
disabled: impl IntoIterator<Item = ValidatorIndex>,
228+
) {
229+
self.disabled_validators.extend(disabled);
230+
}
198231
}
199232

200233
pub(crate) struct State {
@@ -483,9 +516,6 @@ pub(crate) async fn handle_active_leaves_update<Context>(
483516
.map_err(JfyiError::RuntimeApiUnavailable)?
484517
.map_err(JfyiError::FetchDisabledValidators)?;
485518

486-
// deduplicate and order
487-
let disabled_validators = disabled_validators.into_iter().collect();
488-
489519
let group_rotation_info =
490520
polkadot_node_subsystem_util::request_validator_groups(new_relay_parent, ctx.sender())
491521
.await
@@ -529,9 +559,11 @@ pub(crate) async fn handle_active_leaves_update<Context>(
529559

530560
let per_session = state
531561
.per_session
532-
.get(&session_index)
562+
.get_mut(&session_index)
533563
.expect("either existed or just inserted; qed");
534564

565+
per_session.extend_disabled_validators(disabled_validators);
566+
535567
let local_validator = per_session.local_validator.and_then(|v| {
536568
find_local_validator_state(
537569
v,
@@ -546,7 +578,7 @@ pub(crate) async fn handle_active_leaves_update<Context>(
546578
new_relay_parent,
547579
PerRelayParentState {
548580
local_validator,
549-
statement_store: StatementStore::new(&per_session.groups, &disabled_validators),
581+
statement_store: StatementStore::new(&per_session.groups),
550582
availability_cores,
551583
group_rotation_info,
552584
seconding_limit,
@@ -1313,10 +1345,7 @@ async fn handle_incoming_statement<Context>(
13131345
},
13141346
};
13151347

1316-
if per_relay_parent
1317-
.statement_store
1318-
.is_disabled(&statement.unchecked_validator_index())
1319-
{
1348+
if per_session.is_disabled(&statement.unchecked_validator_index()) {
13201349
gum::debug!(
13211350
target: LOG_TARGET,
13221351
?relay_parent,
@@ -1450,17 +1479,6 @@ async fn handle_incoming_statement<Context>(
14501479

14511480
return
14521481
},
1453-
Err(statement_store::Error::ValidatorDisabled) => {
1454-
// sanity: should never happen, checked above.
1455-
gum::warn!(
1456-
target: LOG_TARGET,
1457-
?relay_parent,
1458-
validator_index = ?originator_index,
1459-
"Error - accepted message from disabled validator."
1460-
);
1461-
1462-
return
1463-
},
14641482
Ok(known) => known,
14651483
};
14661484

@@ -2024,11 +2042,7 @@ async fn handle_incoming_manifest_common<'a, Context>(
20242042
let claimed_parent_hash = manifest_summary.claimed_parent_hash;
20252043

20262044
// Ignore votes from disabled validators when counting towards the threshold.
2027-
let disabled_mask = per_session
2028-
.groups
2029-
.get(group_index)
2030-
.map(|group| relay_parent_state.statement_store.disabled_bitmask(group))
2031-
.unwrap_or_default();
2045+
let disabled_mask = per_session.disabled_bitmask(group_index).unwrap_or_default();
20322046
manifest_summary.statement_knowledge.mask_seconded(&disabled_mask);
20332047
manifest_summary.statement_knowledge.mask_valid(&disabled_mask);
20342048

@@ -2622,7 +2636,9 @@ pub(crate) async fn handle_response<Context>(
26222636
Some(g) => g,
26232637
};
26242638

2625-
let disabled_mask = relay_parent_state.statement_store.disabled_bitmask(group);
2639+
let disabled_mask = per_session
2640+
.disabled_bitmask(group_index)
2641+
.expect("group_index checked above; qed");
26262642

26272643
let res = response.validate_response(
26282644
&mut state.request_manager,
@@ -2800,11 +2816,7 @@ pub(crate) fn answer_request(state: &mut State, message: ResponderMessage) {
28002816
};
28012817

28022818
// Ignore disabled validators when sending the response.
2803-
let disabled_mask = per_session
2804-
.groups
2805-
.get(confirmed.group_index())
2806-
.map(|group| relay_parent_state.statement_store.disabled_bitmask(group))
2807-
.unwrap_or_default();
2819+
let disabled_mask = per_session.disabled_bitmask(confirmed.group_index()).unwrap_or_default();
28082820
and_mask.mask_seconded(&disabled_mask);
28092821
and_mask.mask_valid(&disabled_mask);
28102822

polkadot/node/network/statement-distribution/src/v2/statement_store.rs

Lines changed: 4 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -28,10 +28,7 @@ use polkadot_node_network_protocol::v2::StatementFilter;
2828
use polkadot_primitives::{
2929
CandidateHash, CompactStatement, GroupIndex, SignedStatement, ValidatorIndex,
3030
};
31-
use std::collections::{
32-
hash_map::{Entry as HEntry, HashMap},
33-
BTreeSet,
34-
};
31+
use std::collections::hash_map::{Entry as HEntry, HashMap};
3532

3633
use super::groups::Groups;
3734

@@ -71,7 +68,7 @@ pub struct StatementStore {
7168

7269
impl StatementStore {
7370
/// Create a new [`StatementStore`]
74-
pub fn new(groups: &Groups, disabled: &BTreeSet<ValidatorIndex>) -> Self {
71+
pub fn new(groups: &Groups) -> Self {
7572
let mut validator_meta = HashMap::new();
7673
for (g, group) in groups.all().iter().enumerate() {
7774
for (i, v) in group.iter().enumerate() {
@@ -81,7 +78,6 @@ impl StatementStore {
8178
seconded_count: 0,
8279
within_group_index: i,
8380
group: GroupIndex(g as _),
84-
is_disabled: disabled.contains(v),
8581
},
8682
);
8783
}
@@ -95,7 +91,7 @@ impl StatementStore {
9591
}
9692

9793
/// Insert a statement. Returns `true` if was not known already, `false` if it was.
98-
/// Ignores statements by unknown and disabled validators and returns an error.
94+
/// Ignores statements by unknown validators and returns an error.
9995
pub fn insert(
10096
&mut self,
10197
groups: &Groups,
@@ -107,9 +103,6 @@ impl StatementStore {
107103
None => return Err(Error::ValidatorUnknown),
108104
Some(m) => m,
109105
};
110-
if validator_meta.is_disabled {
111-
return Err(Error::ValidatorDisabled)
112-
}
113106

114107
let compact = statement.payload().clone();
115108
let fingerprint = (validator_index, compact.clone());
@@ -161,25 +154,6 @@ impl StatementStore {
161154
Ok(true)
162155
}
163156

164-
/// Returns true if the validator is disabled as of current relay parent.
165-
pub fn is_disabled(&self, index: &ValidatorIndex) -> bool {
166-
self.validator_meta.get(&index).map(|m| m.is_disabled).unwrap_or(false)
167-
}
168-
169-
/// A convenience funtion to generate a disabled bitmask for the given backing group.
170-
/// The output bits are set to `true` for validators that are disabled.
171-
/// The group size should match the size of the backing group.
172-
pub fn disabled_bitmask(&self, group: &[ValidatorIndex]) -> BitVec<u8, BitOrderLsb0> {
173-
let group_size = group.len();
174-
let mut mask = BitVec::repeat(false, group_size);
175-
for (i, v) in group.iter().enumerate() {
176-
if self.is_disabled(v) {
177-
mask.set(i, true);
178-
}
179-
}
180-
mask
181-
}
182-
183157
/// Fill a `StatementFilter` to be used in the grid topology with all statements
184158
/// we are already aware of.
185159
pub fn fill_statement_filter(
@@ -275,12 +249,10 @@ impl StatementStore {
275249
}
276250
}
277251

278-
/// Error indicating that the validator was unknown or disabled.
252+
/// Error when inserting a statement into the statement store.
279253
pub enum Error {
280254
/// The validator was unknown.
281255
ValidatorUnknown,
282-
/// A statement from a disabled validator should be rejected.
283-
ValidatorDisabled,
284256
}
285257

286258
type Fingerprint = (ValidatorIndex, CompactStatement);
@@ -289,7 +261,6 @@ struct ValidatorMeta {
289261
group: GroupIndex,
290262
within_group_index: usize,
291263
seconded_count: usize,
292-
is_disabled: bool,
293264
}
294265

295266
struct GroupStatements {

0 commit comments

Comments
 (0)