From bec4168baa5de648a148aed0494cea78d661662d Mon Sep 17 00:00:00 2001 From: eskimor <eskimor@users.noreply.github.com> Date: Sun, 22 Jan 2023 20:21:37 +0100 Subject: [PATCH] Fix some unjustified disputes (#6103) * Fix indentation + add warning on participation errors. * Don't vote invalid on internal errors. * Don't dispute on code compression error. * Remove CodeDecompressionError * Candidate not invalid if PVF preparation fails. Instead: Report error. * Fix malus * Add clarifying comment. * cargo fmt * Fix indentation. --- .../node/core/candidate-validation/src/lib.rs | 16 +-- .../core/candidate-validation/src/tests.rs | 4 +- .../dispute-coordinator/src/initialized.rs | 99 ++++++++++--------- .../src/participation/mod.rs | 2 +- polkadot/node/malus/src/variants/common.rs | 4 - polkadot/node/primitives/src/lib.rs | 2 - 6 files changed, 64 insertions(+), 63 deletions(-) diff --git a/polkadot/node/core/candidate-validation/src/lib.rs b/polkadot/node/core/candidate-validation/src/lib.rs index 58d91946830..ff5073da56a 100644 --- a/polkadot/node/core/candidate-validation/src/lib.rs +++ b/polkadot/node/core/candidate-validation/src/lib.rs @@ -527,8 +527,9 @@ async fn validate_candidate_exhaustive( Err(e) => { gum::info!(target: LOG_TARGET, ?para_id, err=?e, "Invalid candidate (validation code)"); - // If the validation code is invalid, the candidate certainly is. - return Ok(ValidationResult::Invalid(InvalidCandidate::CodeDecompressionFailure)) + // Code already passed pre-checking, if decompression fails now this most likley means + // some local corruption happened. + return Err(ValidationFailed("Code decompression failed".to_string())) }, }; @@ -560,7 +561,6 @@ async fn validate_candidate_exhaustive( match result { Err(ValidationError::InternalError(e)) => Err(ValidationFailed(e)), - Err(ValidationError::InvalidCandidate(WasmInvalidCandidate::HardTimeout)) => Ok(ValidationResult::Invalid(InvalidCandidate::Timeout)), Err(ValidationError::InvalidCandidate(WasmInvalidCandidate::WorkerReportedError(e))) => @@ -569,9 +569,13 @@ async fn validate_candidate_exhaustive( Ok(ValidationResult::Invalid(InvalidCandidate::ExecutionError( "ambiguous worker death".to_string(), ))), - Err(ValidationError::InvalidCandidate(WasmInvalidCandidate::PrepareError(e))) => - Ok(ValidationResult::Invalid(InvalidCandidate::ExecutionError(e))), - + Err(ValidationError::InvalidCandidate(WasmInvalidCandidate::PrepareError(e))) => { + // In principle if preparation of the `WASM` fails, the current candidate can not be the + // reason for that. So we can't say whether it is invalid or not in addition with + // pre-checking enabled only valid runtimes should ever get enacted, so we can be + // reasonably sure that this is some local problem on the current node. + Err(ValidationFailed(e)) + }, Ok(res) => if res.head_data.hash() != candidate_receipt.descriptor.para_head { gum::info!(target: LOG_TARGET, ?para_id, "Invalid candidate (para_head)"); diff --git a/polkadot/node/core/candidate-validation/src/tests.rs b/polkadot/node/core/candidate-validation/src/tests.rs index 445ea118f3d..c47df9589e4 100644 --- a/polkadot/node/core/candidate-validation/src/tests.rs +++ b/polkadot/node/core/candidate-validation/src/tests.rs @@ -799,7 +799,7 @@ fn compressed_code_works() { } #[test] -fn code_decompression_failure_is_invalid() { +fn code_decompression_failure_is_error() { let validation_data = PersistedValidationData { max_pov_size: 1024, ..Default::default() }; let pov = PoV { block_data: BlockData(vec![1; 32]) }; let head_data = HeadData(vec![1, 1, 1]); @@ -842,7 +842,7 @@ fn code_decompression_failure_is_invalid() { &Default::default(), )); - assert_matches!(v, Ok(ValidationResult::Invalid(InvalidCandidate::CodeDecompressionFailure))); + assert_matches!(v, Err(_)); } #[test] diff --git a/polkadot/node/core/dispute-coordinator/src/initialized.rs b/polkadot/node/core/dispute-coordinator/src/initialized.rs index 9d934c4956c..daab2838d7e 100644 --- a/polkadot/node/core/dispute-coordinator/src/initialized.rs +++ b/polkadot/node/core/dispute-coordinator/src/initialized.rs @@ -198,59 +198,62 @@ impl Initialized { gum::trace!(target: LOG_TARGET, "Waiting for message"); let mut overlay_db = OverlayedBackend::new(backend); let default_confirm = Box::new(|| Ok(())); - let confirm_write = - match MuxedMessage::receive(ctx, &mut self.participation_receiver).await? { - MuxedMessage::Participation(msg) => { - gum::trace!(target: LOG_TARGET, "MuxedMessage::Participation"); - let ParticipationStatement { - session, + let confirm_write = match MuxedMessage::receive(ctx, &mut self.participation_receiver) + .await? + { + MuxedMessage::Participation(msg) => { + gum::trace!(target: LOG_TARGET, "MuxedMessage::Participation"); + let ParticipationStatement { + session, + candidate_hash, + candidate_receipt, + outcome, + } = self.participation.get_participation_result(ctx, msg).await?; + if let Some(valid) = outcome.validity() { + gum::trace!( + target: LOG_TARGET, + ?session, + ?candidate_hash, + ?valid, + "Issuing local statement based on participation outcome." + ); + self.issue_local_statement( + ctx, + &mut overlay_db, candidate_hash, candidate_receipt, - outcome, - } = self.participation.get_participation_result(ctx, msg).await?; - if let Some(valid) = outcome.validity() { - gum::trace!( - target: LOG_TARGET, - ?session, - ?candidate_hash, - ?valid, - "Issuing local statement based on participation outcome." - ); - self.issue_local_statement( - ctx, - &mut overlay_db, - candidate_hash, - candidate_receipt, - session, - valid, - clock.now(), - ) - .await?; - } + session, + valid, + clock.now(), + ) + .await?; + } else { + gum::warn!(target: LOG_TARGET, ?outcome, "Dispute participation failed"); + } + default_confirm + }, + MuxedMessage::Subsystem(msg) => match msg { + FromOrchestra::Signal(OverseerSignal::Conclude) => return Ok(()), + FromOrchestra::Signal(OverseerSignal::ActiveLeaves(update)) => { + gum::trace!(target: LOG_TARGET, "OverseerSignal::ActiveLeaves"); + self.process_active_leaves_update( + ctx, + &mut overlay_db, + update, + clock.now(), + ) + .await?; default_confirm }, - MuxedMessage::Subsystem(msg) => match msg { - FromOrchestra::Signal(OverseerSignal::Conclude) => return Ok(()), - FromOrchestra::Signal(OverseerSignal::ActiveLeaves(update)) => { - gum::trace!(target: LOG_TARGET, "OverseerSignal::ActiveLeaves"); - self.process_active_leaves_update( - ctx, - &mut overlay_db, - update, - clock.now(), - ) - .await?; - default_confirm - }, - FromOrchestra::Signal(OverseerSignal::BlockFinalized(_, n)) => { - gum::trace!(target: LOG_TARGET, "OverseerSignal::BlockFinalized"); - self.scraper.process_finalized_block(&n); - default_confirm - }, - FromOrchestra::Communication { msg } => - self.handle_incoming(ctx, &mut overlay_db, msg, clock.now()).await?, + FromOrchestra::Signal(OverseerSignal::BlockFinalized(_, n)) => { + gum::trace!(target: LOG_TARGET, "OverseerSignal::BlockFinalized"); + self.scraper.process_finalized_block(&n); + default_confirm }, - }; + FromOrchestra::Communication { msg } => + self.handle_incoming(ctx, &mut overlay_db, msg, clock.now()).await?, + }, + }; if !overlay_db.is_empty() { let ops = overlay_db.into_write_ops(); diff --git a/polkadot/node/core/dispute-coordinator/src/participation/mod.rs b/polkadot/node/core/dispute-coordinator/src/participation/mod.rs index 78a3a259207..f813b216b6a 100644 --- a/polkadot/node/core/dispute-coordinator/src/participation/mod.rs +++ b/polkadot/node/core/dispute-coordinator/src/participation/mod.rs @@ -373,7 +373,7 @@ async fn participate( err, ); - send_result(&mut result_sender, req, ParticipationOutcome::Invalid).await; + send_result(&mut result_sender, req, ParticipationOutcome::Error).await; }, Ok(Ok(ValidationResult::Invalid(invalid))) => { diff --git a/polkadot/node/malus/src/variants/common.rs b/polkadot/node/malus/src/variants/common.rs index d92a7315467..3a3cc19aef1 100644 --- a/polkadot/node/malus/src/variants/common.rs +++ b/polkadot/node/malus/src/variants/common.rs @@ -62,8 +62,6 @@ pub enum FakeCandidateValidationError { ParamsTooLarge, /// Code size is over the limit. CodeTooLarge, - /// Code does not decompress correctly. - CodeDecompressionFailure, /// PoV does not decompress correctly. POVDecompressionFailure, /// Validation function returned invalid data. @@ -89,8 +87,6 @@ impl Into<InvalidCandidate> for FakeCandidateValidationError { FakeCandidateValidationError::Timeout => InvalidCandidate::Timeout, FakeCandidateValidationError::ParamsTooLarge => InvalidCandidate::ParamsTooLarge(666), FakeCandidateValidationError::CodeTooLarge => InvalidCandidate::CodeTooLarge(666), - FakeCandidateValidationError::CodeDecompressionFailure => - InvalidCandidate::CodeDecompressionFailure, FakeCandidateValidationError::POVDecompressionFailure => InvalidCandidate::PoVDecompressionFailure, FakeCandidateValidationError::BadReturn => InvalidCandidate::BadReturn, diff --git a/polkadot/node/primitives/src/lib.rs b/polkadot/node/primitives/src/lib.rs index 2d76a14c115..4c141e622e0 100644 --- a/polkadot/node/primitives/src/lib.rs +++ b/polkadot/node/primitives/src/lib.rs @@ -237,8 +237,6 @@ pub enum InvalidCandidate { ParamsTooLarge(u64), /// Code size is over the limit. CodeTooLarge(u64), - /// Code does not decompress correctly. - CodeDecompressionFailure, /// PoV does not decompress correctly. PoVDecompressionFailure, /// Validation function returned invalid data. -- GitLab