Skip to content
This repository has been archived by the owner on Nov 15, 2023. It is now read-only.

Fixes/improvements for disputes #3753

Merged
merged 4 commits into from
Sep 1, 2021
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
5 changes: 3 additions & 2 deletions node/core/dispute-coordinator/src/dummy.rs
Original file line number Diff line number Diff line change
Expand Up @@ -233,13 +233,14 @@ async fn handle_incoming(
},
DisputeCoordinatorMessage::IssueLocalStatement(_, _, _, _) => {},
DisputeCoordinatorMessage::DetermineUndisputedChain {
base_number,
base: (base_number, base_hash),
block_descriptions,
tx,
} => {
let undisputed_chain = block_descriptions
.last()
.map(|e| (base_number + block_descriptions.len() as BlockNumber, e.block_hash));
.map(|e| (base_number + block_descriptions.len() as BlockNumber, e.block_hash))
.unwrap_or((base_number, base_hash));

let _ = tx.send(undisputed_chain);
},
Expand Down
45 changes: 35 additions & 10 deletions node/core/dispute-coordinator/src/real/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -582,12 +582,12 @@ async fn handle_incoming(
.await?;
},
DisputeCoordinatorMessage::DetermineUndisputedChain {
base_number,
base: (base_number, base_hash),
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: split this into base_number and base_hash instead on the messages already, base is never used as tuple.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

They really belong together, so I liked the grouping to highlight that relationship.

block_descriptions,
tx,
} => {
let undisputed_chain =
determine_undisputed_chain(overlay_db, base_number, block_descriptions)?;
determine_undisputed_chain(overlay_db, base_number, base_hash, block_descriptions)?;

let _ = tx.send(undisputed_chain);
},
Expand Down Expand Up @@ -882,7 +882,7 @@ async fn issue_local_statement(

// Do import
if !statements.is_empty() {
let (pending_confirmation, _rx) = oneshot::channel();
let (pending_confirmation, rx) = oneshot::channel();
handle_import_statements(
ctx,
overlay_db,
Expand All @@ -895,6 +895,32 @@ async fn issue_local_statement(
pending_confirmation,
)
.await?;
match rx.await {
Err(_) => {
tracing::error!(
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I suspect these will get noisy.

Metrics?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

actually no, those should not be noisy. The errors I would not expect to happen at all (hence errors) and the trace also only happens on IssueLocalVote, which should also not be noisy as this only happens on disputes and we will only vote once per dispute, so this should really be very low volume.

target: LOG_TARGET,
?candidate_hash,
?session,
"pending confirmation receiver got dropped by `handle_import_statements` for our own votes!"
);
},
Ok(ImportStatementsResult::InvalidImport) => {
tracing::error!(
target: LOG_TARGET,
?candidate_hash,
?session,
"handle_import_statements` considers our own votes invalid!"
);
},
Ok(ImportStatementsResult::ValidImport) => {
tracing::trace!(
target: LOG_TARGET,
?candidate_hash,
?session,
"handle_import_statements` successfully imported our vote!"
);
},
}
}

Ok(())
Expand Down Expand Up @@ -970,11 +996,13 @@ fn make_dispute_message(
fn determine_undisputed_chain(
overlay_db: &mut OverlayedBackend<'_, impl Backend>,
base_number: BlockNumber,
base_hash: Hash,
block_descriptions: Vec<BlockDescription>,
) -> Result<Option<(BlockNumber, Hash)>, Error> {
) -> Result<(BlockNumber, Hash), Error> {
let last = block_descriptions
.last()
.map(|e| (base_number + block_descriptions.len() as BlockNumber, e.block_hash));
.map(|e| (base_number + block_descriptions.len() as BlockNumber, e.block_hash))
.unwrap_or((base_number, base_hash));

// Fast path for no disputes.
let recent_disputes = match overlay_db.load_recent_disputes()? {
Expand All @@ -992,12 +1020,9 @@ fn determine_undisputed_chain(
for (i, BlockDescription { session, candidates, .. }) in block_descriptions.iter().enumerate() {
if candidates.iter().any(|c| is_possibly_invalid(*session, *c)) {
if i == 0 {
return Ok(None)
return Ok((base_number, base_hash))
} else {
return Ok(Some((
base_number + i as BlockNumber,
block_descriptions[i - 1].block_hash,
)))
return Ok((base_number + i as BlockNumber, block_descriptions[i - 1].block_hash))
}
}
}
Expand Down
18 changes: 10 additions & 8 deletions node/core/dispute-coordinator/src/real/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -645,13 +645,14 @@ fn finality_votes_ignore_disputed_candidates() {
{
let (tx, rx) = oneshot::channel();

let base_block = Hash::repeat_byte(0x0f);
let block_hash_a = Hash::repeat_byte(0x0a);
let block_hash_b = Hash::repeat_byte(0x0b);

virtual_overseer
.send(FromOverseer::Communication {
msg: DisputeCoordinatorMessage::DetermineUndisputedChain {
base_number: 10,
base: (10, base_block),
block_descriptions: vec![BlockDescription {
block_hash: block_hash_a,
session,
Expand All @@ -662,13 +663,13 @@ fn finality_votes_ignore_disputed_candidates() {
})
.await;

assert!(rx.await.unwrap().is_none());
assert_eq!(rx.await.unwrap(), (10, base_block));

let (tx, rx) = oneshot::channel();
virtual_overseer
.send(FromOverseer::Communication {
msg: DisputeCoordinatorMessage::DetermineUndisputedChain {
base_number: 10,
base: (10, base_block),
block_descriptions: vec![
BlockDescription {
block_hash: block_hash_a,
Expand All @@ -686,7 +687,7 @@ fn finality_votes_ignore_disputed_candidates() {
})
.await;

assert_eq!(rx.await.unwrap(), Some((11, block_hash_a)));
assert_eq!(rx.await.unwrap(), (11, block_hash_a));
}

virtual_overseer.send(FromOverseer::Signal(OverseerSignal::Conclude)).await;
Expand Down Expand Up @@ -777,13 +778,14 @@ fn supermajority_valid_dispute_may_be_finalized() {
{
let (tx, rx) = oneshot::channel();

let base_hash = Hash::repeat_byte(0x0f);
let block_hash_a = Hash::repeat_byte(0x0a);
let block_hash_b = Hash::repeat_byte(0x0b);

virtual_overseer
.send(FromOverseer::Communication {
msg: DisputeCoordinatorMessage::DetermineUndisputedChain {
base_number: 10,
base: (10, base_hash),
block_descriptions: vec![BlockDescription {
block_hash: block_hash_a,
session,
Expand All @@ -794,13 +796,13 @@ fn supermajority_valid_dispute_may_be_finalized() {
})
.await;

assert_eq!(rx.await.unwrap(), Some((11, block_hash_a)));
assert_eq!(rx.await.unwrap(), (11, block_hash_a));

let (tx, rx) = oneshot::channel();
virtual_overseer
.send(FromOverseer::Communication {
msg: DisputeCoordinatorMessage::DetermineUndisputedChain {
base_number: 10,
base: (10, base_hash),
block_descriptions: vec![
BlockDescription {
block_hash: block_hash_a,
Expand All @@ -818,7 +820,7 @@ fn supermajority_valid_dispute_may_be_finalized() {
})
.await;

assert_eq!(rx.await.unwrap(), Some((12, block_hash_b)));
assert_eq!(rx.await.unwrap(), (12, block_hash_b));
}

virtual_overseer.send(FromOverseer::Signal(OverseerSignal::Conclude)).await;
Expand Down
2 changes: 1 addition & 1 deletion node/network/availability-recovery/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -93,7 +93,7 @@ const COST_INVALID_REQUEST: Rep = Rep::CostMajor("Peer sent unparsable request")
#[cfg(not(test))]
const TIMEOUT_START_NEW_REQUESTS: Duration = CHUNK_REQUEST_TIMEOUT;
#[cfg(test)]
const TIMEOUT_START_NEW_REQUESTS: Duration = Duration::from_millis(4);
const TIMEOUT_START_NEW_REQUESTS: Duration = Duration::from_millis(10);

/// The Availability Recovery Subsystem.
pub struct AvailabilityRecoverySubsystem {
Expand Down
5 changes: 2 additions & 3 deletions node/service/src/relay_chain_selection.rs
Original file line number Diff line number Diff line change
Expand Up @@ -434,7 +434,7 @@ where
overseer
.send_msg(
DisputeCoordinatorMessage::DetermineUndisputedChain {
base_number: target_number,
base: (target_number, target_hash),
block_descriptions: subchain_block_descriptions,
tx,
},
Expand All @@ -444,8 +444,7 @@ where
let (subchain_number, subchain_head) = rx
.await
.map_err(Error::OverseerDisconnected)
.map_err(|e| ConsensusError::Other(Box::new(e)))?
.unwrap_or_else(|| (subchain_number, subchain_head));
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Here we would previously use subchain_number/subchain_head in case we get None from the dispute coordinator.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Got it

.map_err(|e| ConsensusError::Other(Box::new(e)))?;

// The the total lag accounting for disputes.
let lag_disputes = initial_leaf_number.saturating_sub(subchain_number);
Expand Down
6 changes: 4 additions & 2 deletions node/service/src/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -398,18 +398,20 @@ async fn test_skeleton(
);

tracing::trace!("determine undisputed chain response: {:?}", undisputed_chain);

let target_block_number = chain.number(target_block_hash).unwrap().unwrap();
assert_matches!(
overseer_recv(
virtual_overseer
).await,
AllMessages::DisputeCoordinator(
DisputeCoordinatorMessage::DetermineUndisputedChain {
base_number: _,
base: _,
block_descriptions: _,
tx,
}
) => {
tx.send(undisputed_chain).unwrap();
tx.send(undisputed_chain.unwrap_or((target_block_number, target_block_hash))).unwrap();
});
}

Expand Down
10 changes: 5 additions & 5 deletions node/subsystem-types/src/messages.rs
Original file line number Diff line number Diff line change
Expand Up @@ -189,7 +189,7 @@ impl BoundToRelayParent for CollatorProtocolMessage {
/// Messages received by the dispute coordinator subsystem.
#[derive(Debug)]
pub enum DisputeCoordinatorMessage {
/// Import a statement by a validator about a candidate.
/// Import statements by validators about a candidate.
///
/// The subsystem will silently discard ancient statements or sets of only dispute-specific statements for
/// candidates that are previously unknown to the subsystem. The former is simply because ancient
Expand Down Expand Up @@ -251,12 +251,12 @@ pub enum DisputeCoordinatorMessage {
/// is typically the number of the last finalized block but may be slightly higher. This block
/// is inevitably going to be finalized so it is not accounted for by this function.
DetermineUndisputedChain {
/// The number of the lowest possible block to vote on.
base_number: BlockNumber,
/// The lowest possible block to vote on.
base: (BlockNumber, Hash),
/// Descriptions of all the blocks counting upwards from the block after the base number
block_descriptions: Vec<BlockDescription>,
/// A response channel - `None` to vote on base, `Some` to vote higher.
tx: oneshot::Sender<Option<(BlockNumber, Hash)>>,
/// The block to vote on, might be base in case there is no better.
tx: oneshot::Sender<(BlockNumber, Hash)>,
},
}

Expand Down