mirror of
https://github.com/pezkuwichain/pezkuwi-subxt.git
synced 2026-05-30 17:31:03 +00:00
Dispute distribution implementation (#3282)
* Dispute protocol. * Dispute distribution protocol. * Get network requests routed. * WIP: Basic dispute sender logic. * Basic validator determination logic. * WIP: Getting things to typecheck. * Slightly larger timeout. * More typechecking stuff. * Cleanup. * Finished most of the sending logic. * Handle active leaves updates - Cleanup dead disputes - Update sends for new sessions - Retry on errors * Pass sessions in already. * Startup dispute sending. * Provide incoming decoding facilities and use them in statement-distribution. * Relaxed runtime util requirements. We only need a `SubsystemSender` not a full `SubsystemContext`. * Better usability of incoming requests. Make it possible to consume stuff without clones. * Add basic receiver functionality. * Cleanup + fixes for sender. * One more sender fix. * Start receiver. * Make sure to send responses back. * WIP: Exposed authority discovery * Make tests pass. * Fully featured receiver. * Decrease cost of `NotAValidator`. * Make `RuntimeInfo` LRU cache size configurable. * Cache more sessions. * Fix collator protocol. * Disable metrics for now. * Make dispute-distribution a proper subsystem. * Fix naming. * Code style fixes. * Factored out 4x copied mock function. * WIP: Tests. * Whitespace cleanup. * Accessor functions. * More testing. * More Debug instances. * Fix busy loop. * Working tests. * More tests. * Cleanup. * Fix build. * Basic receiving test. * Non validator message gets dropped. * More receiving tests. * Test nested and subsequent imports. * Fix spaces. * Better formatted imports. * Import cleanup. * Metrics. * Message -> MuxedMessage * Message -> MuxedMessage * More review remarks. * Add missing metrics.rs. * Fix flaky test. * Dispute coordinator - deliver confirmations. * Send out `DisputeMessage` on issue local statement. * Unwire dispute distribution. * Review remarks. * Review remarks. * Better docs.
This commit is contained in:
@@ -83,6 +83,9 @@ pub enum Error {
|
||||
#[error(transparent)]
|
||||
Oneshot(#[from] oneshot::Canceled),
|
||||
|
||||
#[error("Oneshot receiver died")]
|
||||
OneshotSendFailed,
|
||||
|
||||
#[error(transparent)]
|
||||
Participation(#[from] ParticipationError),
|
||||
}
|
||||
@@ -159,6 +162,7 @@ async fn handle_incoming(
|
||||
candidate_receipt,
|
||||
session,
|
||||
n_validators,
|
||||
report_availability,
|
||||
} => {
|
||||
if let Some((_, block_hash)) = state.recent_block {
|
||||
participate(
|
||||
@@ -168,6 +172,7 @@ async fn handle_incoming(
|
||||
candidate_receipt,
|
||||
session,
|
||||
n_validators,
|
||||
report_availability,
|
||||
)
|
||||
.await
|
||||
} else {
|
||||
@@ -184,6 +189,7 @@ async fn participate(
|
||||
candidate_receipt: CandidateReceipt,
|
||||
session: SessionIndex,
|
||||
n_validators: u32,
|
||||
report_availability: oneshot::Sender<bool>,
|
||||
) -> Result<(), Error> {
|
||||
let (recover_available_data_tx, recover_available_data_rx) = oneshot::channel();
|
||||
let (code_tx, code_rx) = oneshot::channel();
|
||||
@@ -203,14 +209,21 @@ async fn participate(
|
||||
.await;
|
||||
|
||||
let available_data = match recover_available_data_rx.await? {
|
||||
Ok(data) => data,
|
||||
Ok(data) => {
|
||||
report_availability.send(true).map_err(|_| Error::OneshotSendFailed)?;
|
||||
data
|
||||
}
|
||||
Err(RecoveryError::Invalid) => {
|
||||
report_availability.send(true).map_err(|_| Error::OneshotSendFailed)?;
|
||||
|
||||
// the available data was recovered but it is invalid, therefore we'll
|
||||
// vote negatively for the candidate dispute
|
||||
cast_invalid_vote(ctx, candidate_hash, candidate_receipt, session).await;
|
||||
return Ok(());
|
||||
}
|
||||
Err(RecoveryError::Unavailable) => {
|
||||
report_availability.send(false).map_err(|_| Error::OneshotSendFailed)?;
|
||||
|
||||
return Err(ParticipationError::MissingAvailableData(candidate_hash).into());
|
||||
}
|
||||
};
|
||||
|
||||
@@ -80,7 +80,7 @@ async fn activate_leaf(virtual_overseer: &mut VirtualOverseer, block_number: Blo
|
||||
.await;
|
||||
}
|
||||
|
||||
async fn participate(virtual_overseer: &mut VirtualOverseer) {
|
||||
async fn participate(virtual_overseer: &mut VirtualOverseer) -> oneshot::Receiver<bool> {
|
||||
let commitments = CandidateCommitments::default();
|
||||
let candidate_receipt = {
|
||||
let mut receipt = CandidateReceipt::default();
|
||||
@@ -91,6 +91,8 @@ async fn participate(virtual_overseer: &mut VirtualOverseer) {
|
||||
let session = 1;
|
||||
let n_validators = 10;
|
||||
|
||||
let (report_availability, receive_availability) = oneshot::channel();
|
||||
|
||||
virtual_overseer
|
||||
.send(FromOverseer::Communication {
|
||||
msg: DisputeParticipationMessage::Participate {
|
||||
@@ -98,12 +100,14 @@ async fn participate(virtual_overseer: &mut VirtualOverseer) {
|
||||
candidate_receipt: candidate_receipt.clone(),
|
||||
session,
|
||||
n_validators,
|
||||
report_availability,
|
||||
},
|
||||
})
|
||||
.await;
|
||||
})
|
||||
.await;
|
||||
receive_availability
|
||||
}
|
||||
|
||||
async fn recover_available_data(virtual_overseer: &mut VirtualOverseer) {
|
||||
async fn recover_available_data(virtual_overseer: &mut VirtualOverseer, receive_availability: oneshot::Receiver<bool>) {
|
||||
let pov_block = PoV {
|
||||
block_data: BlockData(Vec::new()),
|
||||
};
|
||||
@@ -122,6 +126,8 @@ async fn recover_available_data(virtual_overseer: &mut VirtualOverseer) {
|
||||
},
|
||||
"overseer did not receive recover available data message",
|
||||
);
|
||||
|
||||
assert_eq!(receive_availability.await.expect("Availability should get reported"), true);
|
||||
}
|
||||
|
||||
async fn fetch_validation_code(virtual_overseer: &mut VirtualOverseer) {
|
||||
@@ -166,7 +172,7 @@ async fn store_available_data(virtual_overseer: &mut VirtualOverseer, success: b
|
||||
fn cannot_participate_when_recent_block_state_is_missing() {
|
||||
test_harness(|mut virtual_overseer| {
|
||||
Box::pin(async move {
|
||||
participate(&mut virtual_overseer).await;
|
||||
let _ = participate(&mut virtual_overseer).await;
|
||||
|
||||
virtual_overseer
|
||||
})
|
||||
@@ -175,7 +181,7 @@ fn cannot_participate_when_recent_block_state_is_missing() {
|
||||
test_harness(|mut virtual_overseer| {
|
||||
Box::pin(async move {
|
||||
activate_leaf(&mut virtual_overseer, 10).await;
|
||||
participate(&mut virtual_overseer).await;
|
||||
let _ = participate(&mut virtual_overseer).await;
|
||||
|
||||
// after activating at least one leaf the recent block
|
||||
// state should be available which should lead to trying
|
||||
@@ -199,7 +205,7 @@ fn cannot_participate_if_cannot_recover_available_data() {
|
||||
test_harness(|mut virtual_overseer| {
|
||||
Box::pin(async move {
|
||||
activate_leaf(&mut virtual_overseer, 10).await;
|
||||
participate(&mut virtual_overseer).await;
|
||||
let receive_availability = participate(&mut virtual_overseer).await;
|
||||
|
||||
assert_matches!(
|
||||
virtual_overseer.recv().await,
|
||||
@@ -211,6 +217,8 @@ fn cannot_participate_if_cannot_recover_available_data() {
|
||||
"overseer did not receive recover available data message",
|
||||
);
|
||||
|
||||
assert_eq!(receive_availability.await.expect("Availability should get reported"), false);
|
||||
|
||||
virtual_overseer
|
||||
})
|
||||
});
|
||||
@@ -221,8 +229,8 @@ fn cannot_participate_if_cannot_recover_validation_code() {
|
||||
test_harness(|mut virtual_overseer| {
|
||||
Box::pin(async move {
|
||||
activate_leaf(&mut virtual_overseer, 10).await;
|
||||
participate(&mut virtual_overseer).await;
|
||||
recover_available_data(&mut virtual_overseer).await;
|
||||
let receive_availability = participate(&mut virtual_overseer).await;
|
||||
recover_available_data(&mut virtual_overseer, receive_availability).await;
|
||||
|
||||
assert_matches!(
|
||||
virtual_overseer.recv().await,
|
||||
@@ -248,7 +256,7 @@ fn cast_invalid_vote_if_available_data_is_invalid() {
|
||||
test_harness(|mut virtual_overseer| {
|
||||
Box::pin(async move {
|
||||
activate_leaf(&mut virtual_overseer, 10).await;
|
||||
participate(&mut virtual_overseer).await;
|
||||
let receive_availability = participate(&mut virtual_overseer).await;
|
||||
|
||||
assert_matches!(
|
||||
virtual_overseer.recv().await,
|
||||
@@ -260,6 +268,8 @@ fn cast_invalid_vote_if_available_data_is_invalid() {
|
||||
"overseer did not receive recover available data message",
|
||||
);
|
||||
|
||||
assert_eq!(receive_availability.await.expect("Availability should get reported"), true);
|
||||
|
||||
assert_matches!(
|
||||
virtual_overseer.recv().await,
|
||||
AllMessages::DisputeCoordinator(DisputeCoordinatorMessage::IssueLocalStatement(
|
||||
@@ -281,8 +291,8 @@ fn cast_invalid_vote_if_validation_fails_or_is_invalid() {
|
||||
test_harness(|mut virtual_overseer| {
|
||||
Box::pin(async move {
|
||||
activate_leaf(&mut virtual_overseer, 10).await;
|
||||
participate(&mut virtual_overseer).await;
|
||||
recover_available_data(&mut virtual_overseer).await;
|
||||
let receive_availability = participate(&mut virtual_overseer).await;
|
||||
recover_available_data(&mut virtual_overseer, receive_availability).await;
|
||||
fetch_validation_code(&mut virtual_overseer).await;
|
||||
store_available_data(&mut virtual_overseer, true).await;
|
||||
|
||||
@@ -317,8 +327,8 @@ fn cast_invalid_vote_if_validation_passes_but_commitments_dont_match() {
|
||||
test_harness(|mut virtual_overseer| {
|
||||
Box::pin(async move {
|
||||
activate_leaf(&mut virtual_overseer, 10).await;
|
||||
participate(&mut virtual_overseer).await;
|
||||
recover_available_data(&mut virtual_overseer).await;
|
||||
let receive_availability = participate(&mut virtual_overseer).await;
|
||||
recover_available_data(&mut virtual_overseer, receive_availability).await;
|
||||
fetch_validation_code(&mut virtual_overseer).await;
|
||||
store_available_data(&mut virtual_overseer, true).await;
|
||||
|
||||
@@ -357,8 +367,8 @@ fn cast_valid_vote_if_validation_passes() {
|
||||
test_harness(|mut virtual_overseer| {
|
||||
Box::pin(async move {
|
||||
activate_leaf(&mut virtual_overseer, 10).await;
|
||||
participate(&mut virtual_overseer).await;
|
||||
recover_available_data(&mut virtual_overseer).await;
|
||||
let receive_availability = participate(&mut virtual_overseer).await;
|
||||
recover_available_data(&mut virtual_overseer, receive_availability).await;
|
||||
fetch_validation_code(&mut virtual_overseer).await;
|
||||
store_available_data(&mut virtual_overseer, true).await;
|
||||
|
||||
@@ -393,8 +403,8 @@ fn failure_to_store_available_data_does_not_preclude_participation() {
|
||||
test_harness(|mut virtual_overseer| {
|
||||
Box::pin(async move {
|
||||
activate_leaf(&mut virtual_overseer, 10).await;
|
||||
participate(&mut virtual_overseer).await;
|
||||
recover_available_data(&mut virtual_overseer).await;
|
||||
let receive_availability = participate(&mut virtual_overseer).await;
|
||||
recover_available_data(&mut virtual_overseer, receive_availability).await;
|
||||
fetch_validation_code(&mut virtual_overseer).await;
|
||||
// the store available data request should fail
|
||||
store_available_data(&mut virtual_overseer, false).await;
|
||||
|
||||
Reference in New Issue
Block a user