Malus: improvements in dispute ancestor and suggest garbage candidate implementation (#5011)

* Implement fake validation results

Signed-off-by: Andrei Sandu <andrei-mihail@parity.io>

* refactor

Signed-off-by: Andrei Sandu <andrei-mihail@parity.io>

* cargo lock

Signed-off-by: Andrei Sandu <andrei-mihail@parity.io>

* spell check

Signed-off-by: Andrei Sandu <andrei-mihail@parity.io>

* spellcheck

Signed-off-by: Andrei Sandu <andrei-mihail@parity.io>

* typos

Signed-off-by: Andrei Sandu <andrei-mihail@parity.io>

* Review feedback

Signed-off-by: Andrei Sandu <andrei-mihail@parity.io>

* move stuff around

Signed-off-by: Andrei Sandu <andrei-mihail@parity.io>

* chores

Signed-off-by: Andrei Sandu <andrei-mihail@parity.io>

* Impl valid - still wip

Signed-off-by: Andrei Sandu <andrei-mihail@parity.io>

* fixes

Signed-off-by: Andrei Sandu <andrei-mihail@parity.io>

* fmt

Signed-off-by: Andrei Sandu <andrei-mihail@parity.io>

* Pull Ladi's implementation:
https://github.com/paritytech/polkadot/pull/4711

Co-authored-by: Lldenaurois <Ljdenaurois@gmail.com>
Co-authored-by: Andrei Sandu <andrei-mihail@parity.io>
Signed-off-by: Andrei Sandu <andrei-mihail@parity.io>

* Fix build

Signed-off-by: Andrei Sandu <andrei-mihail@parity.io>

* Logs and comments

Signed-off-by: Andrei Sandu <andrei-mihail@parity.io>

* WIP: suggest garbage candidate + implement validation result caching

Signed-off-by: Andrei Sandu <andrei-mihail@parity.io>

* fix

Signed-off-by: Andrei Sandu <andrei-mihail@parity.io>

* Do commitment hash checks in candidate validation

Signed-off-by: Andrei Sandu <andrei-mihail@parity.io>

* Minor refactor in approval, backing, dispute-coord

Signed-off-by: Andrei Sandu <andrei-mihail@parity.io>

* Working version of suggest garbage candidate

Signed-off-by: Andrei Sandu <andrei-mihail@parity.io>

* Dedup

Signed-off-by: Andrei Sandu <andrei-mihail@parity.io>

* cleanup #1

Signed-off-by: Andrei Sandu <andrei-mihail@parity.io>

* Fix tests

Signed-off-by: Andrei Sandu <andrei-mihail@parity.io>

* remove debug leftovers

Signed-off-by: Andrei Sandu <andrei-mihail@parity.io>

* fmt

Signed-off-by: Andrei Sandu <andrei-mihail@parity.io>

* Accidentally commited some local test

Signed-off-by: Andrei Sandu <andrei-mihail@parity.io>

* spellcheck

Signed-off-by: Andrei Sandu <andrei-mihail@parity.io>

* some more fixes

Signed-off-by: Andrei Sandu <andrei-mihail@parity.io>

* Refactor and fix it

Signed-off-by: Andrei Sandu <andrei-mihail@parity.io>

* review feedback

Signed-off-by: Andrei Sandu <andrei-mihail@parity.io>

* typo

Signed-off-by: Andrei Sandu <andrei-mihail@parity.io>

* tests review feedback

Signed-off-by: Andrei Sandu <andrei-mihail@parity.io>

* refactor disputer

Signed-off-by: Andrei Sandu <andrei-mihail@parity.io>

* fix tests

Signed-off-by: Andrei Sandu <andrei-mihail@parity.io>

* Fix zombienet disputes test

Signed-off-by: Andrei Sandu <andrei-mihail@parity.io>

* spellcheck

Signed-off-by: Andrei Sandu <andrei-mihail@parity.io>

* fix

Signed-off-by: Andrei Sandu <andrei-mihail@parity.io>

* Fix ui tests

Signed-off-by: Andrei Sandu <andrei-mihail@parity.io>

* fix typo

Signed-off-by: Andrei Sandu <andrei-mihail@parity.io>

Co-authored-by: Lldenaurois <Ljdenaurois@gmail.com>
This commit is contained in:
Andrei Sandu
2022-04-13 16:45:39 +03:00
committed by GitHub
parent a46237cebb
commit cddd5749d3
23 changed files with 921 additions and 529 deletions
+37 -41
View File
@@ -31,8 +31,8 @@ use futures::{
};
use polkadot_node_primitives::{
AvailableData, PoV, SignedDisputeStatement, SignedFullStatement, Statement, ValidationResult,
BACKING_EXECUTION_TIMEOUT,
AvailableData, InvalidCandidate, PoV, SignedDisputeStatement, SignedFullStatement, Statement,
ValidationResult, BACKING_EXECUTION_TIMEOUT,
};
use polkadot_node_subsystem_util::{
self as util,
@@ -41,8 +41,8 @@ use polkadot_node_subsystem_util::{
request_validators, FromJobCommand, JobSender, Validator,
};
use polkadot_primitives::v2::{
BackedCandidate, CandidateCommitments, CandidateDescriptor, CandidateHash, CandidateReceipt,
CollatorId, CommittedCandidateReceipt, CoreIndex, CoreState, Hash, Id as ParaId, SessionIndex,
BackedCandidate, CandidateCommitments, CandidateHash, CandidateReceipt, CollatorId,
CommittedCandidateReceipt, CoreIndex, CoreState, Hash, Id as ParaId, SessionIndex,
SigningContext, ValidatorId, ValidatorIndex, ValidatorSignature, ValidityAttestation,
};
use polkadot_subsystem::{
@@ -378,14 +378,14 @@ async fn request_pov(
async fn request_candidate_validation(
sender: &mut JobSender<impl SubsystemSender>,
candidate: CandidateDescriptor,
candidate_receipt: CandidateReceipt,
pov: Arc<PoV>,
) -> Result<ValidationResult, Error> {
let (tx, rx) = oneshot::channel();
sender
.send_message(CandidateValidationMessage::ValidateFromChainState(
candidate,
candidate_receipt,
pov,
BACKING_EXECUTION_TIMEOUT,
tx,
@@ -456,11 +456,9 @@ async fn validate_and_make_available(
.with_pov(&pov)
.with_para_id(candidate.descriptor().para_id)
});
request_candidate_validation(&mut sender, candidate.descriptor.clone(), pov.clone()).await?
request_candidate_validation(&mut sender, candidate.clone(), pov.clone()).await?
};
let expected_commitments_hash = candidate.commitments_hash;
let res = match v {
ValidationResult::Valid(commitments, validation_data) => {
gum::debug!(
@@ -469,41 +467,39 @@ async fn validate_and_make_available(
"Validation successful",
);
// If validation produces a new set of commitments, we vote the candidate as invalid.
if commitments.hash() != expected_commitments_hash {
gum::debug!(
target: LOG_TARGET,
candidate_hash = ?candidate.hash(),
actual_commitments = ?commitments,
"Commitments obtained with validation don't match the announced by the candidate receipt",
);
Err(candidate)
} else {
let erasure_valid = make_pov_available(
&mut sender,
n_validators,
pov.clone(),
candidate.hash(),
validation_data,
candidate.descriptor.erasure_root,
span.as_ref(),
)
.await?;
let erasure_valid = make_pov_available(
&mut sender,
n_validators,
pov.clone(),
candidate.hash(),
validation_data,
candidate.descriptor.erasure_root,
span.as_ref(),
)
.await?;
match erasure_valid {
Ok(()) => Ok((candidate, commitments, pov.clone())),
Err(InvalidErasureRoot) => {
gum::debug!(
target: LOG_TARGET,
candidate_hash = ?candidate.hash(),
actual_commitments = ?commitments,
"Erasure root doesn't match the announced by the candidate receipt",
);
Err(candidate)
},
}
match erasure_valid {
Ok(()) => Ok((candidate, commitments, pov.clone())),
Err(InvalidErasureRoot) => {
gum::debug!(
target: LOG_TARGET,
candidate_hash = ?candidate.hash(),
actual_commitments = ?commitments,
"Erasure root doesn't match the announced by the candidate receipt",
);
Err(candidate)
},
}
},
ValidationResult::Invalid(InvalidCandidate::CommitmentsHashMismatch) => {
// If validation produces a new set of commitments, we vote the candidate as invalid.
gum::warn!(
target: LOG_TARGET,
candidate_hash = ?candidate.hash(),
"Validation yielded different commitments",
);
Err(candidate)
},
ValidationResult::Invalid(reason) => {
gum::debug!(
target: LOG_TARGET,
+18 -11
View File
@@ -24,7 +24,8 @@ use futures::{future, Future};
use polkadot_node_primitives::{BlockData, InvalidCandidate};
use polkadot_node_subsystem_test_helpers as test_helpers;
use polkadot_primitives::v2::{
CollatorId, GroupRotationInfo, HeadData, PersistedValidationData, ScheduledCore,
CandidateDescriptor, CollatorId, GroupRotationInfo, HeadData, PersistedValidationData,
ScheduledCore,
};
use polkadot_subsystem::{
messages::{
@@ -332,12 +333,12 @@ fn backing_second_works() {
virtual_overseer.recv().await,
AllMessages::CandidateValidation(
CandidateValidationMessage::ValidateFromChainState(
c,
candidate_receipt,
pov,
timeout,
tx,
)
) if pov == pov && &c == candidate.descriptor() && timeout == BACKING_EXECUTION_TIMEOUT => {
) if pov == pov && &candidate_receipt.descriptor == candidate.descriptor() && timeout == BACKING_EXECUTION_TIMEOUT && candidate.commitments.hash() == candidate_receipt.commitments_hash => {
tx.send(Ok(
ValidationResult::Valid(CandidateCommitments {
head_data: expected_head_data.clone(),
@@ -419,6 +420,8 @@ fn backing_works() {
.build();
let candidate_a_hash = candidate_a.hash();
let candidate_a_commitments_hash = candidate_a.commitments.hash();
let public1 = CryptoStore::sr25519_generate_new(
&*test_state.keystore,
ValidatorId::ID,
@@ -497,7 +500,7 @@ fn backing_works() {
timeout,
tx,
)
) if pov == pov && &c == candidate_a.descriptor() && timeout == BACKING_EXECUTION_TIMEOUT => {
) if pov == pov && c.descriptor() == candidate_a.descriptor() && timeout == BACKING_EXECUTION_TIMEOUT && c.commitments_hash == candidate_a_commitments_hash=> {
tx.send(Ok(
ValidationResult::Valid(CandidateCommitments {
head_data: expected_head_data.clone(),
@@ -594,6 +597,8 @@ fn backing_works_while_validation_ongoing() {
.build();
let candidate_a_hash = candidate_a.hash();
let candidate_a_commitments_hash = candidate_a.commitments.hash();
let public1 = CryptoStore::sr25519_generate_new(
&*test_state.keystore,
ValidatorId::ID,
@@ -691,7 +696,7 @@ fn backing_works_while_validation_ongoing() {
timeout,
tx,
)
) if pov == pov && &c == candidate_a.descriptor() && timeout == BACKING_EXECUTION_TIMEOUT => {
) if pov == pov && c.descriptor() == candidate_a.descriptor() && timeout == BACKING_EXECUTION_TIMEOUT && candidate_a_commitments_hash == c.commitments_hash => {
// we never validate the candidate. our local node
// shouldn't issue any statements.
std::mem::forget(tx);
@@ -799,6 +804,8 @@ fn backing_misbehavior_works() {
.build();
let candidate_a_hash = candidate_a.hash();
let candidate_a_commitments_hash = candidate_a.commitments.hash();
let public2 = CryptoStore::sr25519_generate_new(
&*test_state.keystore,
ValidatorId::ID,
@@ -865,7 +872,7 @@ fn backing_misbehavior_works() {
timeout,
tx,
)
) if pov == pov && &c == candidate_a.descriptor() && timeout == BACKING_EXECUTION_TIMEOUT => {
) if pov == pov && c.descriptor() == candidate_a.descriptor() && timeout == BACKING_EXECUTION_TIMEOUT && candidate_a_commitments_hash == c.commitments_hash => {
tx.send(Ok(
ValidationResult::Valid(CandidateCommitments {
head_data: expected_head_data.clone(),
@@ -1025,7 +1032,7 @@ fn backing_dont_second_invalid() {
timeout,
tx,
)
) if pov == pov && &c == candidate_a.descriptor() && timeout == BACKING_EXECUTION_TIMEOUT => {
) if pov == pov && c.descriptor() == candidate_a.descriptor() && timeout == BACKING_EXECUTION_TIMEOUT => {
tx.send(Ok(ValidationResult::Invalid(InvalidCandidate::BadReturn))).unwrap();
}
);
@@ -1054,7 +1061,7 @@ fn backing_dont_second_invalid() {
timeout,
tx,
)
) if pov == pov && &c == candidate_b.descriptor() && timeout == BACKING_EXECUTION_TIMEOUT => {
) if pov == pov && c.descriptor() == candidate_b.descriptor() && timeout == BACKING_EXECUTION_TIMEOUT => {
tx.send(Ok(
ValidationResult::Valid(CandidateCommitments {
head_data: expected_head_data.clone(),
@@ -1185,7 +1192,7 @@ fn backing_second_after_first_fails_works() {
timeout,
tx,
)
) if pov == pov && &c == candidate.descriptor() && timeout == BACKING_EXECUTION_TIMEOUT => {
) if pov == pov && c.descriptor() == candidate.descriptor() && timeout == BACKING_EXECUTION_TIMEOUT && c.commitments_hash == candidate.commitments.hash() => {
tx.send(Ok(ValidationResult::Invalid(InvalidCandidate::BadReturn))).unwrap();
}
);
@@ -1319,7 +1326,7 @@ fn backing_works_after_failed_validation() {
timeout,
tx,
)
) if pov == pov && &c == candidate.descriptor() && timeout == BACKING_EXECUTION_TIMEOUT => {
) if pov == pov && c.descriptor() == candidate.descriptor() && timeout == BACKING_EXECUTION_TIMEOUT && c.commitments_hash == candidate.commitments.hash() => {
tx.send(Err(ValidationFailed("Internal test error".into()))).unwrap();
}
);
@@ -1696,7 +1703,7 @@ fn retry_works() {
timeout,
_tx,
)
) if pov == pov && &c == candidate.descriptor() && timeout == BACKING_EXECUTION_TIMEOUT
) if pov == pov && c.descriptor() == candidate.descriptor() && timeout == BACKING_EXECUTION_TIMEOUT && c.commitments_hash == candidate.commitments.hash()
);
virtual_overseer
});