Skip to content
This repository was archived by the owner on Nov 15, 2023. It is now read-only.
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
33 changes: 26 additions & 7 deletions node/core/dispute-coordinator/src/import.rs
Original file line number Diff line number Diff line change
Expand Up @@ -179,6 +179,9 @@ pub struct CandidateVoteState<Votes> {

/// Current dispute status, if there is any.
dispute_status: Option<DisputeStatus>,

/// Are there `byzantine threshold + 1` invalid votes
byzantine_threshold_against: bool,
}

impl CandidateVoteState<CandidateVotes> {
Expand All @@ -191,7 +194,12 @@ impl CandidateVoteState<CandidateVotes> {
valid: ValidCandidateVotes::new(),
invalid: BTreeMap::new(),
};
Self { votes, own_vote: OwnVoteState::CannotVote, dispute_status: None }
Self {
votes,
own_vote: OwnVoteState::CannotVote,
dispute_status: None,
byzantine_threshold_against: false,
}
}

/// Create a new `CandidateVoteState` from already existing votes.
Expand All @@ -205,7 +213,7 @@ impl CandidateVoteState<CandidateVotes> {
// We have a dispute, if we have votes on both sides:
let is_disputed = !votes.invalid.is_empty() && !votes.valid.raw().is_empty();

let dispute_status = if is_disputed {
let (dispute_status, byzantine_threshold_against) = if is_disputed {
let mut status = DisputeStatus::active();
let byzantine_threshold = polkadot_primitives::byzantine_threshold(n_validators);
let is_confirmed = votes.voted_indices().len() > byzantine_threshold;
Expand All @@ -221,12 +229,12 @@ impl CandidateVoteState<CandidateVotes> {
if concluded_against {
status = status.conclude_against(now);
};
Some(status)
(Some(status), votes.invalid.len() > byzantine_threshold)
} else {
None
(None, false)
};

Self { votes, own_vote, dispute_status }
Self { votes, own_vote, dispute_status, byzantine_threshold_against }
}

/// Import fresh statements.
Expand Down Expand Up @@ -328,8 +336,12 @@ impl CandidateVoteState<CandidateVotes> {

/// Extract `CandidateVotes` for handling import of new statements.
fn into_old_state(self) -> (CandidateVotes, CandidateVoteState<()>) {
let CandidateVoteState { votes, own_vote, dispute_status } = self;
(votes, CandidateVoteState { votes: (), own_vote, dispute_status })
let CandidateVoteState { votes, own_vote, dispute_status, byzantine_threshold_against } =
self;
(
votes,
CandidateVoteState { votes: (), own_vote, dispute_status, byzantine_threshold_against },
)
}
}

Expand Down Expand Up @@ -477,6 +489,13 @@ impl ImportResult {
self.is_freshly_concluded_against() || self.is_freshly_concluded_for()
}

/// Whether or not the invalid vote count for the dispute went beyond the byzantine threshold
/// after the last import
pub fn has_fresh_byzantine_threshold_against(&self) -> bool {
!self.old_state().byzantine_threshold_against &&
self.new_state().byzantine_threshold_against
}

/// Modify this `ImportResult`s, by importing additional approval votes.
///
/// Both results and `new_state` will be changed as if those approval votes had been in the
Expand Down
2 changes: 1 addition & 1 deletion node/core/dispute-coordinator/src/initialized.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1094,7 +1094,7 @@ impl Initialized {

// Notify ChainSelection if a dispute has concluded against a candidate. ChainSelection
// will need to mark the candidate's relay parent as reverted.
if import_result.is_freshly_concluded_against() {
if import_result.has_fresh_byzantine_threshold_against() {
let blocks_including = self.scraper.get_blocks_including_candidate(&candidate_hash);
for (parent_block_number, parent_block_hash) in &blocks_including {
gum::trace!(
Expand Down
Loading