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

Commit

Permalink
Merge branch 'master' into ao-rm-unused-dep
Browse files Browse the repository at this point in the history
* master:
  Bump trie-db from 0.23.0 to 0.23.1 (#4867)
  Ignore redundant dispute messages (#4854)
  collation-generation: Support compressed PoVs directly (#4825)
  Forward `enable_overseer_always` (#4858)
  • Loading branch information
ordian committed Feb 8, 2022
2 parents 7593865 + 1e5d10d commit cf9a2af
Show file tree
Hide file tree
Showing 12 changed files with 230 additions and 46 deletions.
26 changes: 18 additions & 8 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions cli/src/command.rs
Original file line number Diff line number Diff line change
Expand Up @@ -280,6 +280,7 @@ where
cli.run.beefy,
jaeger_agent,
None,
false,
overseer_gen,
)
.map(|full| full.task_manager)
Expand Down
4 changes: 1 addition & 3 deletions node/collation-generation/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -309,9 +309,7 @@ async fn handle_new_activations<Context: SubsystemContext>(

// Apply compression to the block data.
let pov = {
let pov = polkadot_node_primitives::maybe_compress_pov(
collation.proof_of_validity,
);
let pov = collation.proof_of_validity.into_compressed();
let encoded_size = pov.encoded_size();

// As long as `POV_BOMB_LIMIT` is at least `max_pov_size`, this ensures
Expand Down
21 changes: 8 additions & 13 deletions node/collation-generation/src/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,9 @@ mod handle_new_activations {
task::{Context as FuturesContext, Poll},
Future,
};
use polkadot_node_primitives::{BlockData, Collation, CollationResult, PoV, POV_BOMB_LIMIT};
use polkadot_node_primitives::{
BlockData, Collation, CollationResult, MaybeCompressedPoV, PoV,
};
use polkadot_node_subsystem::{
errors::RuntimeApiError,
messages::{AllMessages, RuntimeApiMessage, RuntimeApiRequest},
Expand All @@ -41,24 +43,16 @@ mod handle_new_activations {
horizontal_messages: vec![],
new_validation_code: None,
head_data: dummy_head_data(),
proof_of_validity: PoV { block_data: BlockData(Vec::new()) },
proof_of_validity: MaybeCompressedPoV::Raw(PoV { block_data: BlockData(Vec::new()) }),
processed_downward_messages: 0_u32,
hrmp_watermark: 0_u32.into(),
}
}

fn test_collation_compressed() -> Collation {
let mut collation = test_collation();
let compressed = PoV {
block_data: BlockData(
sp_maybe_compressed_blob::compress(
&collation.proof_of_validity.block_data.0,
POV_BOMB_LIMIT,
)
.unwrap(),
),
};
collation.proof_of_validity = compressed;
let compressed = collation.proof_of_validity.clone().into_compressed();
collation.proof_of_validity = MaybeCompressedPoV::Compressed(compressed);
collation
}

Expand Down Expand Up @@ -309,7 +303,8 @@ mod handle_new_activations {
// we expect a single message to be sent, containing a candidate receipt.
// we don't care too much about the `commitments_hash` right now, but let's ensure that we've calculated the
// correct descriptor
let expect_pov_hash = test_collation_compressed().proof_of_validity.hash();
let expect_pov_hash =
test_collation_compressed().proof_of_validity.into_compressed().hash();
let expect_validation_data_hash = test_validation_data().hash();
let expect_relay_parent = Hash::repeat_byte(4);
let expect_validation_code_hash = ValidationCode(vec![1, 2, 3]).hash();
Expand Down
47 changes: 36 additions & 11 deletions node/core/dispute-coordinator/src/real/initialized.rs
Original file line number Diff line number Diff line change
Expand Up @@ -779,14 +779,21 @@ impl Initialized {
// There is one exception: A sufficiently sophisticated attacker could prevent
// us from seeing the backing votes by witholding arbitrary blocks, and hence we do
// not have a `CandidateReceipt` available.
let mut votes = match overlay_db
let (mut votes, mut votes_changed) = match overlay_db
.load_candidate_votes(session, &candidate_hash)?
.map(CandidateVotes::from)
{
Some(votes) => votes,
Some(votes) => (votes, false),
None =>
if let MaybeCandidateReceipt::Provides(candidate_receipt) = candidate_receipt {
CandidateVotes { candidate_receipt, valid: Vec::new(), invalid: Vec::new() }
(
CandidateVotes {
candidate_receipt,
valid: Vec::new(),
invalid: Vec::new(),
},
true,
)
} else {
tracing::warn!(
target: LOG_TARGET,
Expand Down Expand Up @@ -841,22 +848,34 @@ impl Initialized {

match statement.statement().clone() {
DisputeStatement::Valid(valid_kind) => {
self.metrics.on_valid_vote();
insert_into_statement_vec(
let fresh = insert_into_statement_vec(
&mut votes.valid,
valid_kind,
*val_index,
statement.validator_signature().clone(),
);

if !fresh {
continue
}

votes_changed = true;
self.metrics.on_valid_vote();
},
DisputeStatement::Invalid(invalid_kind) => {
self.metrics.on_invalid_vote();
insert_into_statement_vec(
let fresh = insert_into_statement_vec(
&mut votes.invalid,
invalid_kind,
*val_index,
statement.validator_signature().clone(),
);

if !fresh {
continue
}

votes_changed = true;
self.metrics.on_invalid_vote();
},
}
}
Expand All @@ -871,7 +890,7 @@ impl Initialized {

// Potential spam:
if !is_confirmed {
let mut free_spam_slots = false;
let mut free_spam_slots = statements.is_empty();
for (statement, index) in statements.iter() {
free_spam_slots |= statement.statement().is_backing() ||
self.spam_slots.add_unconfirmed(session, candidate_hash, *index);
Expand Down Expand Up @@ -988,7 +1007,10 @@ impl Initialized {
overlay_db.write_recent_disputes(recent_disputes);
}

overlay_db.write_candidate_votes(session, candidate_hash, votes.into());
// Only write when votes have changed.
if votes_changed {
overlay_db.write_candidate_votes(session, candidate_hash, votes.into());
}

Ok(ImportStatementsResult::ValidImport)
}
Expand Down Expand Up @@ -1145,18 +1167,21 @@ impl MuxedMessage {
}
}

// Returns 'true' if no other vote by that validator was already
// present and 'false' otherwise. Same semantics as `HashSet`.
fn insert_into_statement_vec<T>(
vec: &mut Vec<(T, ValidatorIndex, ValidatorSignature)>,
tag: T,
val_index: ValidatorIndex,
val_signature: ValidatorSignature,
) {
) -> bool {
let pos = match vec.binary_search_by_key(&val_index, |x| x.1) {
Ok(_) => return, // no duplicates needed.
Ok(_) => return false, // no duplicates needed.
Err(p) => p,
};

vec.insert(pos, (tag, val_index, val_signature));
true
}

#[derive(Debug, Clone)]
Expand Down
109 changes: 109 additions & 0 deletions node/core/dispute-coordinator/src/real/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1548,3 +1548,112 @@ fn negative_issue_local_statement_only_triggers_import() {
})
});
}

#[test]
fn empty_import_still_writes_candidate_receipt() {
test_harness(|mut test_state, mut virtual_overseer| {
Box::pin(async move {
let session = 1;

test_state.handle_resume_sync(&mut virtual_overseer, session).await;

let candidate_receipt = make_valid_candidate_receipt();
let candidate_hash = candidate_receipt.hash();

test_state.activate_leaf_at_session(&mut virtual_overseer, session, 1).await;

let (tx, rx) = oneshot::channel();
virtual_overseer
.send(FromOverseer::Communication {
msg: DisputeCoordinatorMessage::ImportStatements {
candidate_hash,
candidate_receipt: candidate_receipt.clone(),
session,
statements: Vec::new(),
pending_confirmation: tx,
},
})
.await;

rx.await.unwrap();

let backend = DbBackend::new(test_state.db.clone(), test_state.config.column_config());

let votes = backend.load_candidate_votes(session, &candidate_hash).unwrap().unwrap();
assert_eq!(votes.invalid.len(), 0);
assert_eq!(votes.valid.len(), 0);
assert_eq!(votes.candidate_receipt, candidate_receipt);

virtual_overseer.send(FromOverseer::Signal(OverseerSignal::Conclude)).await;
assert!(virtual_overseer.try_recv().await.is_none());

test_state
})
});
}

#[test]
fn redundant_votes_ignored() {
test_harness(|mut test_state, mut virtual_overseer| {
Box::pin(async move {
let session = 1;

test_state.handle_resume_sync(&mut virtual_overseer, session).await;

let candidate_receipt = make_valid_candidate_receipt();
let candidate_hash = candidate_receipt.hash();

test_state.activate_leaf_at_session(&mut virtual_overseer, session, 1).await;

let valid_vote =
test_state.issue_statement_with_index(1, candidate_hash, session, true).await;

let valid_vote_2 =
test_state.issue_statement_with_index(1, candidate_hash, session, true).await;

assert!(valid_vote.validator_signature() != valid_vote_2.validator_signature());

let (tx, rx) = oneshot::channel();
virtual_overseer
.send(FromOverseer::Communication {
msg: DisputeCoordinatorMessage::ImportStatements {
candidate_hash,
candidate_receipt: candidate_receipt.clone(),
session,
statements: vec![(valid_vote.clone(), ValidatorIndex(1))],
pending_confirmation: tx,
},
})
.await;

rx.await.unwrap();

let (tx, rx) = oneshot::channel();
virtual_overseer
.send(FromOverseer::Communication {
msg: DisputeCoordinatorMessage::ImportStatements {
candidate_hash,
candidate_receipt: candidate_receipt.clone(),
session,
statements: vec![(valid_vote_2, ValidatorIndex(1))],
pending_confirmation: tx,
},
})
.await;

rx.await.unwrap();

let backend = DbBackend::new(test_state.db.clone(), test_state.config.column_config());

let votes = backend.load_candidate_votes(session, &candidate_hash).unwrap().unwrap();
assert_eq!(votes.invalid.len(), 0);
assert_eq!(votes.valid.len(), 1);
assert_eq!(&votes.valid[0].2, valid_vote.validator_signature());

virtual_overseer.send(FromOverseer::Signal(OverseerSignal::Conclude)).await;
assert!(virtual_overseer.try_recv().await.is_none());

test_state
})
});
}
Loading

0 comments on commit cf9a2af

Please sign in to comment.