mirror of
https://github.com/pezkuwichain/pezkuwi-subxt.git
synced 2026-06-18 10:41:01 +00:00
Validate chunks from disk in availability-recovery (#6078)
* Don't use corrupted chunks from disk. Otherwise we would be going to dispute the candidate and get slashed. * Add tests
This commit is contained in:
@@ -189,6 +189,7 @@ struct TestState {
|
||||
|
||||
available_data: AvailableData,
|
||||
chunks: Vec<ErasureChunk>,
|
||||
invalid_chunks: Vec<ErasureChunk>,
|
||||
}
|
||||
|
||||
impl TestState {
|
||||
@@ -273,6 +274,26 @@ impl TestState {
|
||||
)
|
||||
}
|
||||
|
||||
async fn respond_to_query_all_request_invalid(
|
||||
&self,
|
||||
virtual_overseer: &mut VirtualOverseer,
|
||||
send_chunk: impl Fn(usize) -> bool,
|
||||
) {
|
||||
assert_matches!(
|
||||
overseer_recv(virtual_overseer).await,
|
||||
AllMessages::AvailabilityStore(
|
||||
AvailabilityStoreMessage::QueryAllChunks(_, tx)
|
||||
) => {
|
||||
let v = self.invalid_chunks.iter()
|
||||
.filter(|c| send_chunk(c.index.0 as usize))
|
||||
.cloned()
|
||||
.collect();
|
||||
|
||||
let _ = tx.send(v);
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
async fn test_chunk_requests(
|
||||
&self,
|
||||
candidate_hash: CandidateHash,
|
||||
@@ -454,6 +475,22 @@ impl Default for TestState {
|
||||
&available_data,
|
||||
|_, _| {},
|
||||
);
|
||||
// Mess around:
|
||||
let invalid_chunks = chunks
|
||||
.iter()
|
||||
.cloned()
|
||||
.map(|mut chunk| {
|
||||
if chunk.chunk.len() >= 2 && chunk.chunk[0] != chunk.chunk[1] {
|
||||
chunk.chunk[0] = chunk.chunk[1];
|
||||
} else if chunk.chunk.len() >= 1 {
|
||||
chunk.chunk[0] = !chunk.chunk[0];
|
||||
} else {
|
||||
chunk.proof = Proof::dummy_proof();
|
||||
}
|
||||
chunk
|
||||
})
|
||||
.collect();
|
||||
debug_assert_ne!(chunks, invalid_chunks);
|
||||
|
||||
candidate.descriptor.erasure_root = erasure_root;
|
||||
candidate.descriptor.relay_parent = Hash::repeat_byte(10);
|
||||
@@ -468,6 +505,7 @@ impl Default for TestState {
|
||||
persisted_validation_data,
|
||||
available_data,
|
||||
chunks,
|
||||
invalid_chunks,
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1284,6 +1322,57 @@ fn does_not_query_local_validator() {
|
||||
});
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn invalid_local_chunk_is_ignored() {
|
||||
let test_state = TestState::default();
|
||||
|
||||
test_harness_chunks_only(|mut virtual_overseer, req_cfg| async move {
|
||||
overseer_signal(
|
||||
&mut virtual_overseer,
|
||||
OverseerSignal::ActiveLeaves(ActiveLeavesUpdate::start_work(ActivatedLeaf {
|
||||
hash: test_state.current.clone(),
|
||||
number: 1,
|
||||
status: LeafStatus::Fresh,
|
||||
span: Arc::new(jaeger::Span::Disabled),
|
||||
})),
|
||||
)
|
||||
.await;
|
||||
|
||||
let (tx, rx) = oneshot::channel();
|
||||
|
||||
overseer_send(
|
||||
&mut virtual_overseer,
|
||||
AvailabilityRecoveryMessage::RecoverAvailableData(
|
||||
test_state.candidate.clone(),
|
||||
test_state.session_index,
|
||||
None,
|
||||
tx,
|
||||
),
|
||||
)
|
||||
.await;
|
||||
|
||||
test_state.test_runtime_api(&mut virtual_overseer).await;
|
||||
test_state.respond_to_available_data_query(&mut virtual_overseer, false).await;
|
||||
test_state
|
||||
.respond_to_query_all_request_invalid(&mut virtual_overseer, |i| i == 0)
|
||||
.await;
|
||||
|
||||
let candidate_hash = test_state.candidate.hash();
|
||||
|
||||
test_state
|
||||
.test_chunk_requests(
|
||||
candidate_hash,
|
||||
&mut virtual_overseer,
|
||||
test_state.threshold() - 1,
|
||||
|i| if i == 0 { panic!("requested from local validator") } else { Has::Yes },
|
||||
)
|
||||
.await;
|
||||
|
||||
assert_eq!(rx.await.unwrap().unwrap(), test_state.available_data);
|
||||
(virtual_overseer, req_cfg)
|
||||
});
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn parallel_request_calculation_works_as_expected() {
|
||||
let num_validators = 100;
|
||||
|
||||
Reference in New Issue
Block a user