mirror of
https://github.com/pezkuwichain/pezkuwi-subxt.git
synced 2026-04-26 23:57:56 +00:00
cargo +nightly fmt (#3540)
* cargo +nightly fmt * add cargo-fmt check to ci * update ci * fmt * fmt * skip macro * ignore bridges
This commit is contained in:
@@ -18,40 +18,42 @@
|
||||
|
||||
#![warn(missing_docs)]
|
||||
|
||||
use std::collections::{HashMap, VecDeque};
|
||||
use std::pin::Pin;
|
||||
use std::{
|
||||
collections::{HashMap, VecDeque},
|
||||
pin::Pin,
|
||||
};
|
||||
|
||||
use futures::{channel::oneshot, prelude::*, stream::FuturesUnordered};
|
||||
use futures::future::{BoxFuture, RemoteHandle, FutureExt};
|
||||
use futures::task::{Context, Poll};
|
||||
use futures::{
|
||||
channel::oneshot,
|
||||
future::{BoxFuture, FutureExt, RemoteHandle},
|
||||
prelude::*,
|
||||
stream::FuturesUnordered,
|
||||
task::{Context, Poll},
|
||||
};
|
||||
use lru::LruCache;
|
||||
use rand::seq::SliceRandom;
|
||||
|
||||
use polkadot_primitives::v1::{
|
||||
AuthorityDiscoveryId, CandidateReceipt, CandidateHash,
|
||||
Hash, ValidatorId, ValidatorIndex,
|
||||
SessionInfo, SessionIndex, BlakeTwo256, HashT, GroupIndex, BlockNumber,
|
||||
use polkadot_erasure_coding::{branch_hash, branches, obtain_chunks_v1, recovery_threshold};
|
||||
use polkadot_node_network_protocol::{
|
||||
request_response::{
|
||||
self as req_res, request::RequestError, OutgoingRequest, Recipient, Requests,
|
||||
},
|
||||
IfDisconnected,
|
||||
};
|
||||
use polkadot_node_primitives::{AvailableData, ErasureChunk};
|
||||
use polkadot_node_subsystem_util::request_session_info;
|
||||
use polkadot_primitives::v1::{
|
||||
AuthorityDiscoveryId, BlakeTwo256, BlockNumber, CandidateHash, CandidateReceipt, GroupIndex,
|
||||
Hash, HashT, SessionIndex, SessionInfo, ValidatorId, ValidatorIndex,
|
||||
};
|
||||
use polkadot_node_primitives::{ErasureChunk, AvailableData};
|
||||
use polkadot_subsystem::{
|
||||
overseer::{self, Subsystem},
|
||||
SubsystemContext, SubsystemResult, SubsystemError, SpawnedSubsystem, FromOverseer,
|
||||
OverseerSignal, ActiveLeavesUpdate, SubsystemSender,
|
||||
errors::RecoveryError,
|
||||
jaeger,
|
||||
messages::{
|
||||
AvailabilityStoreMessage, AvailabilityRecoveryMessage, NetworkBridgeMessage,
|
||||
},
|
||||
messages::{AvailabilityRecoveryMessage, AvailabilityStoreMessage, NetworkBridgeMessage},
|
||||
overseer::{self, Subsystem},
|
||||
ActiveLeavesUpdate, FromOverseer, OverseerSignal, SpawnedSubsystem, SubsystemContext,
|
||||
SubsystemError, SubsystemResult, SubsystemSender,
|
||||
};
|
||||
use polkadot_node_network_protocol::{
|
||||
IfDisconnected,
|
||||
request_response::{
|
||||
self as req_res, OutgoingRequest, Recipient, Requests,
|
||||
request::RequestError,
|
||||
},
|
||||
};
|
||||
use polkadot_node_subsystem_util::request_session_info;
|
||||
use polkadot_erasure_coding::{branches, branch_hash, recovery_threshold, obtain_chunks_v1};
|
||||
|
||||
mod error;
|
||||
|
||||
@@ -82,9 +84,8 @@ struct RequestChunksPhase {
|
||||
// request the chunk from them.
|
||||
shuffling: VecDeque<ValidatorIndex>,
|
||||
received_chunks: HashMap<ValidatorIndex, ErasureChunk>,
|
||||
requesting_chunks: FuturesUnordered<BoxFuture<
|
||||
'static,
|
||||
Result<Option<ErasureChunk>, (ValidatorIndex, RequestError)>>,
|
||||
requesting_chunks: FuturesUnordered<
|
||||
BoxFuture<'static, Result<Option<ErasureChunk>, (ValidatorIndex, RequestError)>>,
|
||||
>,
|
||||
}
|
||||
|
||||
@@ -125,9 +126,7 @@ impl RequestFromBackersPhase {
|
||||
fn new(mut backers: Vec<ValidatorIndex>) -> Self {
|
||||
backers.shuffle(&mut rand::thread_rng());
|
||||
|
||||
RequestFromBackersPhase {
|
||||
shuffled_backers: backers,
|
||||
}
|
||||
RequestFromBackersPhase { shuffled_backers: backers }
|
||||
}
|
||||
|
||||
// Run this phase to completion.
|
||||
@@ -144,29 +143,41 @@ impl RequestFromBackersPhase {
|
||||
);
|
||||
loop {
|
||||
// Pop the next backer, and proceed to next phase if we're out.
|
||||
let validator_index = self.shuffled_backers.pop().ok_or_else(|| RecoveryError::Unavailable)?;
|
||||
let validator_index =
|
||||
self.shuffled_backers.pop().ok_or_else(|| RecoveryError::Unavailable)?;
|
||||
|
||||
// Request data.
|
||||
let (req, res) = OutgoingRequest::new(
|
||||
Recipient::Authority(params.validator_authority_keys[validator_index.0 as usize].clone()),
|
||||
Recipient::Authority(
|
||||
params.validator_authority_keys[validator_index.0 as usize].clone(),
|
||||
),
|
||||
req_res::v1::AvailableDataFetchingRequest { candidate_hash: params.candidate_hash },
|
||||
);
|
||||
|
||||
sender.send_message(NetworkBridgeMessage::SendRequests(
|
||||
vec![Requests::AvailableDataFetching(req)],
|
||||
IfDisconnected::TryConnect,
|
||||
).into()).await;
|
||||
sender
|
||||
.send_message(
|
||||
NetworkBridgeMessage::SendRequests(
|
||||
vec![Requests::AvailableDataFetching(req)],
|
||||
IfDisconnected::TryConnect,
|
||||
)
|
||||
.into(),
|
||||
)
|
||||
.await;
|
||||
|
||||
match res.await {
|
||||
Ok(req_res::v1::AvailableDataFetchingResponse::AvailableData(data)) => {
|
||||
if reconstructed_data_matches_root(params.validators.len(), ¶ms.erasure_root, &data) {
|
||||
if reconstructed_data_matches_root(
|
||||
params.validators.len(),
|
||||
¶ms.erasure_root,
|
||||
&data,
|
||||
) {
|
||||
tracing::trace!(
|
||||
target: LOG_TARGET,
|
||||
candidate_hash = ?params.candidate_hash,
|
||||
"Received full data",
|
||||
);
|
||||
|
||||
return Ok(data);
|
||||
return Ok(data)
|
||||
} else {
|
||||
tracing::debug!(
|
||||
target: LOG_TARGET,
|
||||
@@ -177,8 +188,8 @@ impl RequestFromBackersPhase {
|
||||
|
||||
// it doesn't help to report the peer with req/res.
|
||||
}
|
||||
}
|
||||
Ok(req_res::v1::AvailableDataFetchingResponse::NoSuchData) => {}
|
||||
},
|
||||
Ok(req_res::v1::AvailableDataFetchingResponse::NoSuchData) => {},
|
||||
Err(e) => tracing::debug!(
|
||||
target: LOG_TARGET,
|
||||
candidate_hash = ?params.candidate_hash,
|
||||
@@ -239,34 +250,34 @@ impl RequestChunksPhase {
|
||||
index: validator_index,
|
||||
};
|
||||
|
||||
let (req, res) = OutgoingRequest::new(
|
||||
Recipient::Authority(validator),
|
||||
raw_request.clone(),
|
||||
);
|
||||
let (req, res) =
|
||||
OutgoingRequest::new(Recipient::Authority(validator), raw_request.clone());
|
||||
|
||||
sender.send_message(NetworkBridgeMessage::SendRequests(
|
||||
vec![Requests::ChunkFetching(req)],
|
||||
IfDisconnected::TryConnect,
|
||||
).into()).await;
|
||||
sender
|
||||
.send_message(
|
||||
NetworkBridgeMessage::SendRequests(
|
||||
vec![Requests::ChunkFetching(req)],
|
||||
IfDisconnected::TryConnect,
|
||||
)
|
||||
.into(),
|
||||
)
|
||||
.await;
|
||||
|
||||
self.requesting_chunks.push(Box::pin(async move {
|
||||
match res.await {
|
||||
Ok(req_res::v1::ChunkFetchingResponse::Chunk(chunk))
|
||||
=> Ok(Some(chunk.recombine_into_chunk(&raw_request))),
|
||||
Ok(req_res::v1::ChunkFetchingResponse::Chunk(chunk)) =>
|
||||
Ok(Some(chunk.recombine_into_chunk(&raw_request))),
|
||||
Ok(req_res::v1::ChunkFetchingResponse::NoSuchChunk) => Ok(None),
|
||||
Err(e) => Err((validator_index, e)),
|
||||
}
|
||||
}));
|
||||
} else {
|
||||
break;
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
async fn wait_for_chunks(
|
||||
&mut self,
|
||||
params: &InteractionParams,
|
||||
) {
|
||||
async fn wait_for_chunks(&mut self, params: &InteractionParams) {
|
||||
// Wait for all current requests to conclude or time-out, or until we reach enough chunks.
|
||||
while let Some(request_result) = self.requesting_chunks.next().await {
|
||||
match request_result {
|
||||
@@ -275,11 +286,9 @@ impl RequestChunksPhase {
|
||||
|
||||
let validator_index = chunk.index;
|
||||
|
||||
if let Ok(anticipated_hash) = branch_hash(
|
||||
¶ms.erasure_root,
|
||||
&chunk.proof,
|
||||
chunk.index.0 as usize,
|
||||
) {
|
||||
if let Ok(anticipated_hash) =
|
||||
branch_hash(¶ms.erasure_root, &chunk.proof, chunk.index.0 as usize)
|
||||
{
|
||||
let erasure_chunk_hash = BlakeTwo256::hash(&chunk.chunk);
|
||||
|
||||
if erasure_chunk_hash != anticipated_hash {
|
||||
@@ -303,8 +312,8 @@ impl RequestChunksPhase {
|
||||
"Invalid Merkle proof",
|
||||
);
|
||||
}
|
||||
}
|
||||
Ok(None) => {}
|
||||
},
|
||||
Ok(None) => {},
|
||||
Err((validator_index, e)) => {
|
||||
tracing::debug!(
|
||||
target: LOG_TARGET,
|
||||
@@ -314,17 +323,19 @@ impl RequestChunksPhase {
|
||||
);
|
||||
|
||||
match e {
|
||||
RequestError::InvalidResponse(_) => {}
|
||||
RequestError::InvalidResponse(_) => {},
|
||||
RequestError::NetworkError(_) | RequestError::Canceled(_) => {
|
||||
self.shuffling.push_front(validator_index);
|
||||
}
|
||||
},
|
||||
}
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
// Stop waiting for requests when we either can already recover the data
|
||||
// or have gotten firm 'No' responses from enough validators.
|
||||
if self.can_conclude(params) { break }
|
||||
if self.can_conclude(params) {
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -336,9 +347,11 @@ impl RequestChunksPhase {
|
||||
// First query the store for any chunks we've got.
|
||||
{
|
||||
let (tx, rx) = oneshot::channel();
|
||||
sender.send_message(
|
||||
AvailabilityStoreMessage::QueryAllChunks(params.candidate_hash, tx).into()
|
||||
).await;
|
||||
sender
|
||||
.send_message(
|
||||
AvailabilityStoreMessage::QueryAllChunks(params.candidate_hash, tx).into(),
|
||||
)
|
||||
.await;
|
||||
|
||||
match rx.await {
|
||||
Ok(chunks) => {
|
||||
@@ -350,14 +363,14 @@ impl RequestChunksPhase {
|
||||
for chunk in chunks {
|
||||
self.received_chunks.insert(chunk.index, chunk);
|
||||
}
|
||||
}
|
||||
},
|
||||
Err(oneshot::Canceled) => {
|
||||
tracing::warn!(
|
||||
target: LOG_TARGET,
|
||||
candidate_hash = ?params.candidate_hash,
|
||||
"Failed to reach the availability store"
|
||||
);
|
||||
}
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
@@ -373,7 +386,7 @@ impl RequestChunksPhase {
|
||||
"Data recovery is not possible",
|
||||
);
|
||||
|
||||
return Err(RecoveryError::Unavailable);
|
||||
return Err(RecoveryError::Unavailable)
|
||||
}
|
||||
|
||||
self.launch_parallel_requests(params, sender).await;
|
||||
@@ -388,7 +401,11 @@ impl RequestChunksPhase {
|
||||
self.received_chunks.values().map(|c| (&c.chunk[..], c.index.0 as usize)),
|
||||
) {
|
||||
Ok(data) => {
|
||||
if reconstructed_data_matches_root(params.validators.len(), ¶ms.erasure_root, &data) {
|
||||
if reconstructed_data_matches_root(
|
||||
params.validators.len(),
|
||||
¶ms.erasure_root,
|
||||
&data,
|
||||
) {
|
||||
tracing::trace!(
|
||||
target: LOG_TARGET,
|
||||
candidate_hash = ?params.candidate_hash,
|
||||
@@ -407,7 +424,7 @@ impl RequestChunksPhase {
|
||||
|
||||
Err(RecoveryError::Invalid)
|
||||
}
|
||||
}
|
||||
},
|
||||
Err(err) => {
|
||||
tracing::trace!(
|
||||
target: LOG_TARGET,
|
||||
@@ -419,7 +436,7 @@ impl RequestChunksPhase {
|
||||
|
||||
Err(RecoveryError::Invalid)
|
||||
},
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -447,8 +464,8 @@ fn reconstructed_data_matches_root(
|
||||
err = ?e,
|
||||
"Failed to obtain chunks",
|
||||
);
|
||||
return false;
|
||||
}
|
||||
return false
|
||||
},
|
||||
};
|
||||
|
||||
let branches = branches(&chunks);
|
||||
@@ -461,20 +478,23 @@ impl<S: SubsystemSender> Interaction<S> {
|
||||
// First just see if we have the data available locally.
|
||||
{
|
||||
let (tx, rx) = oneshot::channel();
|
||||
self.sender.send_message(
|
||||
AvailabilityStoreMessage::QueryAvailableData(self.params.candidate_hash, tx).into()
|
||||
).await;
|
||||
self.sender
|
||||
.send_message(
|
||||
AvailabilityStoreMessage::QueryAvailableData(self.params.candidate_hash, tx)
|
||||
.into(),
|
||||
)
|
||||
.await;
|
||||
|
||||
match rx.await {
|
||||
Ok(Some(data)) => return Ok(data),
|
||||
Ok(None) => {}
|
||||
Ok(None) => {},
|
||||
Err(oneshot::Canceled) => {
|
||||
tracing::warn!(
|
||||
target: LOG_TARGET,
|
||||
candidate_hash = ?self.params.candidate_hash,
|
||||
"Failed to reach the availability store",
|
||||
)
|
||||
}
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
@@ -486,16 +506,14 @@ impl<S: SubsystemSender> Interaction<S> {
|
||||
match from_backers.run(&self.params, &mut self.sender).await {
|
||||
Ok(data) => break Ok(data),
|
||||
Err(RecoveryError::Invalid) => break Err(RecoveryError::Invalid),
|
||||
Err(RecoveryError::Unavailable) => {
|
||||
self.phase = InteractionPhase::RequestChunks(
|
||||
RequestChunksPhase::new(self.params.validators.len() as _)
|
||||
)
|
||||
}
|
||||
Err(RecoveryError::Unavailable) =>
|
||||
self.phase = InteractionPhase::RequestChunks(RequestChunksPhase::new(
|
||||
self.params.validators.len() as _,
|
||||
)),
|
||||
}
|
||||
}
|
||||
InteractionPhase::RequestChunks(ref mut from_all) => {
|
||||
break from_all.run(&self.params, &mut self.sender).await;
|
||||
}
|
||||
},
|
||||
InteractionPhase::RequestChunks(ref mut from_all) =>
|
||||
break from_all.run(&self.params, &mut self.sender).await,
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -514,7 +532,7 @@ impl Future for InteractionHandle {
|
||||
fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
|
||||
let mut indices_to_remove = Vec::new();
|
||||
for (i, awaiting) in self.awaiting.iter_mut().enumerate().rev() {
|
||||
if let Poll::Ready(()) = awaiting.poll_canceled(cx) {
|
||||
if let Poll::Ready(()) = awaiting.poll_canceled(cx) {
|
||||
indices_to_remove.push(i);
|
||||
}
|
||||
}
|
||||
@@ -537,7 +555,7 @@ impl Future for InteractionHandle {
|
||||
"All receivers for available data dropped.",
|
||||
);
|
||||
|
||||
return Poll::Ready(None);
|
||||
return Poll::Ready(None)
|
||||
}
|
||||
|
||||
let remote = &mut self.remote;
|
||||
@@ -580,21 +598,16 @@ where
|
||||
Context: overseer::SubsystemContext<Message = AvailabilityRecoveryMessage>,
|
||||
{
|
||||
fn start(self, ctx: Context) -> SpawnedSubsystem {
|
||||
let future = self.run(ctx)
|
||||
let future = self
|
||||
.run(ctx)
|
||||
.map_err(|e| SubsystemError::with_origin("availability-recovery", e))
|
||||
.boxed();
|
||||
SpawnedSubsystem {
|
||||
name: "availability-recovery-subsystem",
|
||||
future,
|
||||
}
|
||||
SpawnedSubsystem { name: "availability-recovery-subsystem", future }
|
||||
}
|
||||
}
|
||||
|
||||
/// Handles a signal from the overseer.
|
||||
async fn handle_signal(
|
||||
state: &mut State,
|
||||
signal: OverseerSignal,
|
||||
) -> SubsystemResult<bool> {
|
||||
async fn handle_signal(state: &mut State, signal: OverseerSignal) -> SubsystemResult<bool> {
|
||||
match signal {
|
||||
OverseerSignal::Conclude => Ok(true),
|
||||
OverseerSignal::ActiveLeaves(ActiveLeavesUpdate { activated, .. }) => {
|
||||
@@ -606,8 +619,8 @@ async fn handle_signal(
|
||||
}
|
||||
|
||||
Ok(false)
|
||||
}
|
||||
OverseerSignal::BlockFinalized(_, _) => Ok(false)
|
||||
},
|
||||
OverseerSignal::BlockFinalized(_, _) => Ok(false),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -636,18 +649,14 @@ where
|
||||
|
||||
let phase = backing_group
|
||||
.and_then(|g| session_info.validator_groups.get(g.0 as usize))
|
||||
.map(|group| InteractionPhase::RequestFromBackers(
|
||||
RequestFromBackersPhase::new(group.clone())
|
||||
))
|
||||
.unwrap_or_else(|| InteractionPhase::RequestChunks(
|
||||
RequestChunksPhase::new(params.validators.len() as _)
|
||||
));
|
||||
.map(|group| {
|
||||
InteractionPhase::RequestFromBackers(RequestFromBackersPhase::new(group.clone()))
|
||||
})
|
||||
.unwrap_or_else(|| {
|
||||
InteractionPhase::RequestChunks(RequestChunksPhase::new(params.validators.len() as _))
|
||||
});
|
||||
|
||||
let interaction = Interaction {
|
||||
sender: ctx.sender().clone(),
|
||||
params,
|
||||
phase,
|
||||
};
|
||||
let interaction = Interaction { sender: ctx.sender().clone(), params, phase };
|
||||
|
||||
let (remote, remote_handle) = interaction.run().remote_handle();
|
||||
|
||||
@@ -694,43 +703,32 @@ where
|
||||
"Error responding with an availability recovery result",
|
||||
);
|
||||
}
|
||||
return Ok(());
|
||||
return Ok(())
|
||||
}
|
||||
|
||||
if let Some(i) = state.interactions.iter_mut().find(|i| i.candidate_hash == candidate_hash) {
|
||||
i.awaiting.push(response_sender);
|
||||
return Ok(());
|
||||
return Ok(())
|
||||
}
|
||||
|
||||
let _span = span.child("not-cached");
|
||||
let session_info = request_session_info(
|
||||
state.live_block.1,
|
||||
session_index,
|
||||
ctx.sender(),
|
||||
).await.await.map_err(error::Error::CanceledSessionInfo)??;
|
||||
let session_info = request_session_info(state.live_block.1, session_index, ctx.sender())
|
||||
.await
|
||||
.await
|
||||
.map_err(error::Error::CanceledSessionInfo)??;
|
||||
|
||||
let _span = span.child("session-info-ctx-received");
|
||||
match session_info {
|
||||
Some(session_info) => {
|
||||
launch_interaction(
|
||||
state,
|
||||
ctx,
|
||||
session_info,
|
||||
receipt,
|
||||
backing_group,
|
||||
response_sender,
|
||||
).await
|
||||
}
|
||||
Some(session_info) =>
|
||||
launch_interaction(state, ctx, session_info, receipt, backing_group, response_sender)
|
||||
.await,
|
||||
None => {
|
||||
tracing::warn!(
|
||||
target: LOG_TARGET,
|
||||
"SessionInfo is `None` at {:?}", state.live_block,
|
||||
);
|
||||
tracing::warn!(target: LOG_TARGET, "SessionInfo is `None` at {:?}", state.live_block,);
|
||||
response_sender
|
||||
.send(Err(RecoveryError::Unavailable))
|
||||
.map_err(|_| error::Error::CanceledResponseSender)?;
|
||||
Ok(())
|
||||
}
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
@@ -744,9 +742,8 @@ where
|
||||
Context: overseer::SubsystemContext<Message = AvailabilityRecoveryMessage>,
|
||||
{
|
||||
let (tx, rx) = oneshot::channel();
|
||||
ctx.send_message(
|
||||
AvailabilityStoreMessage::QueryAvailableData(candidate_hash, tx),
|
||||
).await;
|
||||
ctx.send_message(AvailabilityStoreMessage::QueryAvailableData(candidate_hash, tx))
|
||||
.await;
|
||||
|
||||
Ok(rx.await.map_err(error::Error::CanceledQueryFullData)?)
|
||||
}
|
||||
@@ -762,10 +759,7 @@ impl AvailabilityRecoverySubsystem {
|
||||
Self { fast_path: false }
|
||||
}
|
||||
|
||||
async fn run<Context>(
|
||||
self,
|
||||
mut ctx: Context,
|
||||
) -> SubsystemResult<()>
|
||||
async fn run<Context>(self, mut ctx: Context) -> SubsystemResult<()>
|
||||
where
|
||||
Context: SubsystemContext<Message = AvailabilityRecoveryMessage>,
|
||||
Context: overseer::SubsystemContext<Message = AvailabilityRecoveryMessage>,
|
||||
|
||||
@@ -14,27 +14,26 @@
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Polkadot. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
use std::time::Duration;
|
||||
use std::sync::Arc;
|
||||
use std::{sync::Arc, time::Duration};
|
||||
|
||||
use assert_matches::assert_matches;
|
||||
use futures::{executor, future};
|
||||
use futures_timer::Delay;
|
||||
use assert_matches::assert_matches;
|
||||
|
||||
use parity_scale_codec::Encode;
|
||||
|
||||
use super::*;
|
||||
|
||||
use polkadot_primitives::v1::{
|
||||
AuthorityDiscoveryId, PersistedValidationData, HeadData,
|
||||
};
|
||||
use polkadot_node_primitives::{PoV, BlockData};
|
||||
use polkadot_erasure_coding::{branches, obtain_chunks_v1 as obtain_chunks};
|
||||
use polkadot_node_primitives::{BlockData, PoV};
|
||||
use polkadot_node_subsystem_util::TimeoutExt;
|
||||
use polkadot_subsystem_testhelpers as test_helpers;
|
||||
use polkadot_primitives::v1::{AuthorityDiscoveryId, HeadData, PersistedValidationData};
|
||||
use polkadot_subsystem::{
|
||||
messages::{AllMessages, RuntimeApiMessage, RuntimeApiRequest}, jaeger, ActivatedLeaf, LeafStatus,
|
||||
jaeger,
|
||||
messages::{AllMessages, RuntimeApiMessage, RuntimeApiRequest},
|
||||
ActivatedLeaf, LeafStatus,
|
||||
};
|
||||
use polkadot_subsystem_testhelpers as test_helpers;
|
||||
|
||||
type VirtualOverseer = test_helpers::TestSubsystemContextHandle<AvailabilityRecoveryMessage>;
|
||||
|
||||
@@ -43,10 +42,7 @@ fn test_harness_fast_path<T: Future<Output = VirtualOverseer>>(
|
||||
) {
|
||||
let _ = env_logger::builder()
|
||||
.is_test(true)
|
||||
.filter(
|
||||
Some("polkadot_availability_recovery"),
|
||||
log::LevelFilter::Trace,
|
||||
)
|
||||
.filter(Some("polkadot_availability_recovery"), log::LevelFilter::Trace)
|
||||
.try_init();
|
||||
|
||||
let pool = sp_core::testing::TaskExecutor::new();
|
||||
@@ -61,10 +57,15 @@ fn test_harness_fast_path<T: Future<Output = VirtualOverseer>>(
|
||||
futures::pin_mut!(test_fut);
|
||||
futures::pin_mut!(subsystem);
|
||||
|
||||
executor::block_on(future::join(async move {
|
||||
let mut overseer = test_fut.await;
|
||||
overseer_signal(&mut overseer, OverseerSignal::Conclude).await;
|
||||
}, subsystem)).1.unwrap();
|
||||
executor::block_on(future::join(
|
||||
async move {
|
||||
let mut overseer = test_fut.await;
|
||||
overseer_signal(&mut overseer, OverseerSignal::Conclude).await;
|
||||
},
|
||||
subsystem,
|
||||
))
|
||||
.1
|
||||
.unwrap();
|
||||
}
|
||||
|
||||
fn test_harness_chunks_only<T: Future<Output = VirtualOverseer>>(
|
||||
@@ -72,10 +73,7 @@ fn test_harness_chunks_only<T: Future<Output = VirtualOverseer>>(
|
||||
) {
|
||||
let _ = env_logger::builder()
|
||||
.is_test(true)
|
||||
.filter(
|
||||
Some("polkadot_availability_recovery"),
|
||||
log::LevelFilter::Trace,
|
||||
)
|
||||
.filter(Some("polkadot_availability_recovery"), log::LevelFilter::Trace)
|
||||
.try_init();
|
||||
|
||||
let pool = sp_core::testing::TaskExecutor::new();
|
||||
@@ -90,10 +88,15 @@ fn test_harness_chunks_only<T: Future<Output = VirtualOverseer>>(
|
||||
futures::pin_mut!(test_fut);
|
||||
futures::pin_mut!(subsystem);
|
||||
|
||||
executor::block_on(future::join(async move {
|
||||
let mut overseer = test_fut.await;
|
||||
overseer_signal(&mut overseer, OverseerSignal::Conclude).await;
|
||||
}, subsystem)).1.unwrap();
|
||||
executor::block_on(future::join(
|
||||
async move {
|
||||
let mut overseer = test_fut.await;
|
||||
overseer_signal(&mut overseer, OverseerSignal::Conclude).await;
|
||||
},
|
||||
subsystem,
|
||||
))
|
||||
.1
|
||||
.unwrap();
|
||||
}
|
||||
|
||||
const TIMEOUT: Duration = Duration::from_millis(100);
|
||||
@@ -132,16 +135,11 @@ async fn overseer_recv(
|
||||
overseer: &mut test_helpers::TestSubsystemContextHandle<AvailabilityRecoveryMessage>,
|
||||
) -> AllMessages {
|
||||
tracing::trace!("waiting for message ...");
|
||||
let msg = overseer
|
||||
.recv()
|
||||
.timeout(TIMEOUT)
|
||||
.await
|
||||
.expect("TIMEOUT is enough to recv.");
|
||||
let msg = overseer.recv().timeout(TIMEOUT).await.expect("TIMEOUT is enough to recv.");
|
||||
tracing::trace!(msg = ?msg, "received message");
|
||||
msg
|
||||
}
|
||||
|
||||
|
||||
use sp_keyring::Sr25519Keyring;
|
||||
|
||||
#[derive(Debug)]
|
||||
@@ -153,9 +151,7 @@ enum Has {
|
||||
|
||||
impl Has {
|
||||
fn timeout() -> Self {
|
||||
Has::NetworkError(sc_network::RequestFailure::Network(
|
||||
sc_network::OutboundFailure::Timeout
|
||||
))
|
||||
Has::NetworkError(sc_network::RequestFailure::Network(sc_network::OutboundFailure::Timeout))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -183,10 +179,7 @@ impl TestState {
|
||||
self.validators.len() - self.threshold() + 1
|
||||
}
|
||||
|
||||
async fn test_runtime_api(
|
||||
&self,
|
||||
virtual_overseer: &mut VirtualOverseer,
|
||||
) {
|
||||
async fn test_runtime_api(&self, virtual_overseer: &mut VirtualOverseer) {
|
||||
assert_matches!(
|
||||
overseer_recv(virtual_overseer).await,
|
||||
AllMessages::RuntimeApi(RuntimeApiMessage::Request(
|
||||
@@ -233,7 +226,7 @@ impl TestState {
|
||||
async fn respond_to_query_all_request(
|
||||
&self,
|
||||
virtual_overseer: &mut VirtualOverseer,
|
||||
send_chunk: impl Fn(usize) -> bool
|
||||
send_chunk: impl Fn(usize) -> bool,
|
||||
) {
|
||||
assert_matches!(
|
||||
overseer_recv(virtual_overseer).await,
|
||||
@@ -344,7 +337,6 @@ impl TestState {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
fn validator_pubkeys(val_ids: &[Sr25519Keyring]) -> Vec<ValidatorId> {
|
||||
val_ids.iter().map(|v| v.public().into()).collect()
|
||||
}
|
||||
@@ -406,9 +398,7 @@ impl Default for TestState {
|
||||
relay_parent_storage_root: Default::default(),
|
||||
};
|
||||
|
||||
let pov = PoV {
|
||||
block_data: BlockData(vec![42; 64]),
|
||||
};
|
||||
let pov = PoV { block_data: BlockData(vec![42; 64]) };
|
||||
|
||||
let available_data = AvailableData {
|
||||
validation_data: persisted_validation_data.clone(),
|
||||
@@ -451,7 +441,8 @@ fn availability_is_recovered_from_chunks_if_no_group_provided() {
|
||||
status: LeafStatus::Fresh,
|
||||
span: Arc::new(jaeger::Span::Disabled),
|
||||
})),
|
||||
).await;
|
||||
)
|
||||
.await;
|
||||
|
||||
let (tx, rx) = oneshot::channel();
|
||||
|
||||
@@ -462,8 +453,9 @@ fn availability_is_recovered_from_chunks_if_no_group_provided() {
|
||||
test_state.session_index,
|
||||
None,
|
||||
tx,
|
||||
)
|
||||
).await;
|
||||
),
|
||||
)
|
||||
.await;
|
||||
|
||||
test_state.test_runtime_api(&mut virtual_overseer).await;
|
||||
|
||||
@@ -472,12 +464,14 @@ fn availability_is_recovered_from_chunks_if_no_group_provided() {
|
||||
test_state.respond_to_available_data_query(&mut virtual_overseer, false).await;
|
||||
test_state.respond_to_query_all_request(&mut virtual_overseer, |_| false).await;
|
||||
|
||||
test_state.test_chunk_requests(
|
||||
candidate_hash,
|
||||
&mut virtual_overseer,
|
||||
test_state.threshold(),
|
||||
|_| Has::Yes,
|
||||
).await;
|
||||
test_state
|
||||
.test_chunk_requests(
|
||||
candidate_hash,
|
||||
&mut virtual_overseer,
|
||||
test_state.threshold(),
|
||||
|_| Has::Yes,
|
||||
)
|
||||
.await;
|
||||
|
||||
// Recovered data should match the original one.
|
||||
assert_eq!(rx.await.unwrap().unwrap(), test_state.available_data);
|
||||
@@ -496,20 +490,23 @@ fn availability_is_recovered_from_chunks_if_no_group_provided() {
|
||||
test_state.session_index,
|
||||
None,
|
||||
tx,
|
||||
)
|
||||
).await;
|
||||
),
|
||||
)
|
||||
.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(&mut virtual_overseer, |_| false).await;
|
||||
|
||||
test_state.test_chunk_requests(
|
||||
new_candidate.hash(),
|
||||
&mut virtual_overseer,
|
||||
test_state.impossibility_threshold(),
|
||||
|_| Has::No,
|
||||
).await;
|
||||
test_state
|
||||
.test_chunk_requests(
|
||||
new_candidate.hash(),
|
||||
&mut virtual_overseer,
|
||||
test_state.impossibility_threshold(),
|
||||
|_| Has::No,
|
||||
)
|
||||
.await;
|
||||
|
||||
// A request times out with `Unavailable` error.
|
||||
assert_eq!(rx.await.unwrap().unwrap_err(), RecoveryError::Unavailable);
|
||||
@@ -530,7 +527,8 @@ fn availability_is_recovered_from_chunks_even_if_backing_group_supplied_if_chunk
|
||||
status: LeafStatus::Fresh,
|
||||
span: Arc::new(jaeger::Span::Disabled),
|
||||
})),
|
||||
).await;
|
||||
)
|
||||
.await;
|
||||
|
||||
let (tx, rx) = oneshot::channel();
|
||||
|
||||
@@ -541,8 +539,9 @@ fn availability_is_recovered_from_chunks_even_if_backing_group_supplied_if_chunk
|
||||
test_state.session_index,
|
||||
Some(GroupIndex(0)),
|
||||
tx,
|
||||
)
|
||||
).await;
|
||||
),
|
||||
)
|
||||
.await;
|
||||
|
||||
test_state.test_runtime_api(&mut virtual_overseer).await;
|
||||
|
||||
@@ -551,12 +550,14 @@ fn availability_is_recovered_from_chunks_even_if_backing_group_supplied_if_chunk
|
||||
test_state.respond_to_available_data_query(&mut virtual_overseer, false).await;
|
||||
test_state.respond_to_query_all_request(&mut virtual_overseer, |_| false).await;
|
||||
|
||||
test_state.test_chunk_requests(
|
||||
candidate_hash,
|
||||
&mut virtual_overseer,
|
||||
test_state.threshold(),
|
||||
|_| Has::Yes,
|
||||
).await;
|
||||
test_state
|
||||
.test_chunk_requests(
|
||||
candidate_hash,
|
||||
&mut virtual_overseer,
|
||||
test_state.threshold(),
|
||||
|_| Has::Yes,
|
||||
)
|
||||
.await;
|
||||
|
||||
// Recovered data should match the original one.
|
||||
assert_eq!(rx.await.unwrap().unwrap(), test_state.available_data);
|
||||
@@ -575,20 +576,23 @@ fn availability_is_recovered_from_chunks_even_if_backing_group_supplied_if_chunk
|
||||
test_state.session_index,
|
||||
None,
|
||||
tx,
|
||||
)
|
||||
).await;
|
||||
),
|
||||
)
|
||||
.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(&mut virtual_overseer, |_| false).await;
|
||||
|
||||
test_state.test_chunk_requests(
|
||||
new_candidate.hash(),
|
||||
&mut virtual_overseer,
|
||||
test_state.impossibility_threshold(),
|
||||
|_| Has::No,
|
||||
).await;
|
||||
test_state
|
||||
.test_chunk_requests(
|
||||
new_candidate.hash(),
|
||||
&mut virtual_overseer,
|
||||
test_state.impossibility_threshold(),
|
||||
|_| Has::No,
|
||||
)
|
||||
.await;
|
||||
|
||||
// A request times out with `Unavailable` error.
|
||||
assert_eq!(rx.await.unwrap().unwrap_err(), RecoveryError::Unavailable);
|
||||
@@ -609,7 +613,8 @@ fn bad_merkle_path_leads_to_recovery_error() {
|
||||
status: LeafStatus::Fresh,
|
||||
span: Arc::new(jaeger::Span::Disabled),
|
||||
})),
|
||||
).await;
|
||||
)
|
||||
.await;
|
||||
|
||||
let (tx, rx) = oneshot::channel();
|
||||
|
||||
@@ -620,8 +625,9 @@ fn bad_merkle_path_leads_to_recovery_error() {
|
||||
test_state.session_index,
|
||||
None,
|
||||
tx,
|
||||
)
|
||||
).await;
|
||||
),
|
||||
)
|
||||
.await;
|
||||
|
||||
test_state.test_runtime_api(&mut virtual_overseer).await;
|
||||
|
||||
@@ -637,12 +643,14 @@ fn bad_merkle_path_leads_to_recovery_error() {
|
||||
test_state.respond_to_available_data_query(&mut virtual_overseer, false).await;
|
||||
test_state.respond_to_query_all_request(&mut virtual_overseer, |_| false).await;
|
||||
|
||||
test_state.test_chunk_requests(
|
||||
candidate_hash,
|
||||
&mut virtual_overseer,
|
||||
test_state.impossibility_threshold(),
|
||||
|_| Has::Yes,
|
||||
).await;
|
||||
test_state
|
||||
.test_chunk_requests(
|
||||
candidate_hash,
|
||||
&mut virtual_overseer,
|
||||
test_state.impossibility_threshold(),
|
||||
|_| Has::Yes,
|
||||
)
|
||||
.await;
|
||||
|
||||
// A request times out with `Unavailable` error.
|
||||
assert_eq!(rx.await.unwrap().unwrap_err(), RecoveryError::Unavailable);
|
||||
@@ -663,7 +671,8 @@ fn wrong_chunk_index_leads_to_recovery_error() {
|
||||
status: LeafStatus::Fresh,
|
||||
span: Arc::new(jaeger::Span::Disabled),
|
||||
})),
|
||||
).await;
|
||||
)
|
||||
.await;
|
||||
|
||||
let (tx, rx) = oneshot::channel();
|
||||
|
||||
@@ -674,8 +683,9 @@ fn wrong_chunk_index_leads_to_recovery_error() {
|
||||
test_state.session_index,
|
||||
None,
|
||||
tx,
|
||||
)
|
||||
).await;
|
||||
),
|
||||
)
|
||||
.await;
|
||||
|
||||
test_state.test_runtime_api(&mut virtual_overseer).await;
|
||||
|
||||
@@ -690,12 +700,14 @@ fn wrong_chunk_index_leads_to_recovery_error() {
|
||||
test_state.respond_to_available_data_query(&mut virtual_overseer, false).await;
|
||||
test_state.respond_to_query_all_request(&mut virtual_overseer, |_| false).await;
|
||||
|
||||
test_state.test_chunk_requests(
|
||||
candidate_hash,
|
||||
&mut virtual_overseer,
|
||||
test_state.impossibility_threshold(),
|
||||
|_| Has::No,
|
||||
).await;
|
||||
test_state
|
||||
.test_chunk_requests(
|
||||
candidate_hash,
|
||||
&mut virtual_overseer,
|
||||
test_state.impossibility_threshold(),
|
||||
|_| Has::No,
|
||||
)
|
||||
.await;
|
||||
|
||||
// A request times out with `Unavailable` error as there are no good peers.
|
||||
assert_eq!(rx.await.unwrap().unwrap_err(), RecoveryError::Unavailable);
|
||||
@@ -708,9 +720,7 @@ fn invalid_erasure_coding_leads_to_invalid_error() {
|
||||
let mut test_state = TestState::default();
|
||||
|
||||
test_harness_fast_path(|mut virtual_overseer| async move {
|
||||
let pov = PoV {
|
||||
block_data: BlockData(vec![69; 64]),
|
||||
};
|
||||
let pov = PoV { block_data: BlockData(vec![69; 64]) };
|
||||
|
||||
let (bad_chunks, bad_erasure_root) = derive_erasure_chunks_with_proofs_and_root(
|
||||
test_state.chunks.len(),
|
||||
@@ -734,7 +744,8 @@ fn invalid_erasure_coding_leads_to_invalid_error() {
|
||||
status: LeafStatus::Fresh,
|
||||
span: Arc::new(jaeger::Span::Disabled),
|
||||
})),
|
||||
).await;
|
||||
)
|
||||
.await;
|
||||
|
||||
let (tx, rx) = oneshot::channel();
|
||||
|
||||
@@ -745,20 +756,23 @@ fn invalid_erasure_coding_leads_to_invalid_error() {
|
||||
test_state.session_index,
|
||||
None,
|
||||
tx,
|
||||
)
|
||||
).await;
|
||||
),
|
||||
)
|
||||
.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(&mut virtual_overseer, |_| false).await;
|
||||
|
||||
test_state.test_chunk_requests(
|
||||
candidate_hash,
|
||||
&mut virtual_overseer,
|
||||
test_state.threshold(),
|
||||
|_| Has::Yes,
|
||||
).await;
|
||||
test_state
|
||||
.test_chunk_requests(
|
||||
candidate_hash,
|
||||
&mut virtual_overseer,
|
||||
test_state.threshold(),
|
||||
|_| Has::Yes,
|
||||
)
|
||||
.await;
|
||||
|
||||
// f+1 'valid' chunks can't produce correct data.
|
||||
assert_eq!(rx.await.unwrap().unwrap_err(), RecoveryError::Invalid);
|
||||
@@ -779,7 +793,8 @@ fn fast_path_backing_group_recovers() {
|
||||
status: LeafStatus::Fresh,
|
||||
span: Arc::new(jaeger::Span::Disabled),
|
||||
})),
|
||||
).await;
|
||||
)
|
||||
.await;
|
||||
|
||||
let (tx, rx) = oneshot::channel();
|
||||
|
||||
@@ -790,8 +805,9 @@ fn fast_path_backing_group_recovers() {
|
||||
test_state.session_index,
|
||||
Some(GroupIndex(0)),
|
||||
tx,
|
||||
)
|
||||
).await;
|
||||
),
|
||||
)
|
||||
.await;
|
||||
|
||||
test_state.test_runtime_api(&mut virtual_overseer).await;
|
||||
|
||||
@@ -804,11 +820,9 @@ fn fast_path_backing_group_recovers() {
|
||||
|
||||
test_state.respond_to_available_data_query(&mut virtual_overseer, false).await;
|
||||
|
||||
test_state.test_full_data_requests(
|
||||
candidate_hash,
|
||||
&mut virtual_overseer,
|
||||
who_has,
|
||||
).await;
|
||||
test_state
|
||||
.test_full_data_requests(candidate_hash, &mut virtual_overseer, who_has)
|
||||
.await;
|
||||
|
||||
// Recovered data should match the original one.
|
||||
assert_eq!(rx.await.unwrap().unwrap(), test_state.available_data);
|
||||
@@ -829,7 +843,8 @@ fn no_answers_in_fast_path_causes_chunk_requests() {
|
||||
status: LeafStatus::Fresh,
|
||||
span: Arc::new(jaeger::Span::Disabled),
|
||||
})),
|
||||
).await;
|
||||
)
|
||||
.await;
|
||||
|
||||
let (tx, rx) = oneshot::channel();
|
||||
|
||||
@@ -840,8 +855,9 @@ fn no_answers_in_fast_path_causes_chunk_requests() {
|
||||
test_state.session_index,
|
||||
Some(GroupIndex(0)),
|
||||
tx,
|
||||
)
|
||||
).await;
|
||||
),
|
||||
)
|
||||
.await;
|
||||
|
||||
test_state.test_runtime_api(&mut virtual_overseer).await;
|
||||
|
||||
@@ -855,20 +871,20 @@ fn no_answers_in_fast_path_causes_chunk_requests() {
|
||||
|
||||
test_state.respond_to_available_data_query(&mut virtual_overseer, false).await;
|
||||
|
||||
test_state.test_full_data_requests(
|
||||
candidate_hash,
|
||||
&mut virtual_overseer,
|
||||
who_has,
|
||||
).await;
|
||||
test_state
|
||||
.test_full_data_requests(candidate_hash, &mut virtual_overseer, who_has)
|
||||
.await;
|
||||
|
||||
test_state.respond_to_query_all_request(&mut virtual_overseer, |_| false).await;
|
||||
|
||||
test_state.test_chunk_requests(
|
||||
candidate_hash,
|
||||
&mut virtual_overseer,
|
||||
test_state.threshold(),
|
||||
|_| Has::Yes,
|
||||
).await;
|
||||
test_state
|
||||
.test_chunk_requests(
|
||||
candidate_hash,
|
||||
&mut virtual_overseer,
|
||||
test_state.threshold(),
|
||||
|_| Has::Yes,
|
||||
)
|
||||
.await;
|
||||
|
||||
// Recovered data should match the original one.
|
||||
assert_eq!(rx.await.unwrap().unwrap(), test_state.available_data);
|
||||
@@ -889,7 +905,8 @@ fn task_canceled_when_receivers_dropped() {
|
||||
status: LeafStatus::Fresh,
|
||||
span: Arc::new(jaeger::Span::Disabled),
|
||||
})),
|
||||
).await;
|
||||
)
|
||||
.await;
|
||||
|
||||
let (tx, _) = oneshot::channel();
|
||||
|
||||
@@ -900,8 +917,9 @@ fn task_canceled_when_receivers_dropped() {
|
||||
test_state.session_index,
|
||||
None,
|
||||
tx,
|
||||
)
|
||||
).await;
|
||||
),
|
||||
)
|
||||
.await;
|
||||
|
||||
test_state.test_runtime_api(&mut virtual_overseer).await;
|
||||
|
||||
@@ -929,7 +947,8 @@ fn chunks_retry_until_all_nodes_respond() {
|
||||
status: LeafStatus::Fresh,
|
||||
span: Arc::new(jaeger::Span::Disabled),
|
||||
})),
|
||||
).await;
|
||||
)
|
||||
.await;
|
||||
|
||||
let (tx, rx) = oneshot::channel();
|
||||
|
||||
@@ -940,8 +959,9 @@ fn chunks_retry_until_all_nodes_respond() {
|
||||
test_state.session_index,
|
||||
Some(GroupIndex(0)),
|
||||
tx,
|
||||
)
|
||||
).await;
|
||||
),
|
||||
)
|
||||
.await;
|
||||
|
||||
test_state.test_runtime_api(&mut virtual_overseer).await;
|
||||
|
||||
@@ -950,21 +970,25 @@ fn chunks_retry_until_all_nodes_respond() {
|
||||
test_state.respond_to_available_data_query(&mut virtual_overseer, false).await;
|
||||
test_state.respond_to_query_all_request(&mut virtual_overseer, |_| false).await;
|
||||
|
||||
test_state.test_chunk_requests(
|
||||
candidate_hash,
|
||||
&mut virtual_overseer,
|
||||
test_state.validators.len(),
|
||||
|_| Has::timeout(),
|
||||
).await;
|
||||
test_state
|
||||
.test_chunk_requests(
|
||||
candidate_hash,
|
||||
&mut virtual_overseer,
|
||||
test_state.validators.len(),
|
||||
|_| Has::timeout(),
|
||||
)
|
||||
.await;
|
||||
|
||||
// we get to go another round!
|
||||
|
||||
test_state.test_chunk_requests(
|
||||
candidate_hash,
|
||||
&mut virtual_overseer,
|
||||
test_state.impossibility_threshold(),
|
||||
|_| Has::No,
|
||||
).await;
|
||||
test_state
|
||||
.test_chunk_requests(
|
||||
candidate_hash,
|
||||
&mut virtual_overseer,
|
||||
test_state.impossibility_threshold(),
|
||||
|_| Has::No,
|
||||
)
|
||||
.await;
|
||||
|
||||
// Recovered data should match the original one.
|
||||
assert_eq!(rx.await.unwrap().unwrap_err(), RecoveryError::Unavailable);
|
||||
@@ -985,7 +1009,8 @@ fn returns_early_if_we_have_the_data() {
|
||||
status: LeafStatus::Fresh,
|
||||
span: Arc::new(jaeger::Span::Disabled),
|
||||
})),
|
||||
).await;
|
||||
)
|
||||
.await;
|
||||
|
||||
let (tx, rx) = oneshot::channel();
|
||||
|
||||
@@ -996,8 +1021,9 @@ fn returns_early_if_we_have_the_data() {
|
||||
test_state.session_index,
|
||||
None,
|
||||
tx,
|
||||
)
|
||||
).await;
|
||||
),
|
||||
)
|
||||
.await;
|
||||
|
||||
test_state.test_runtime_api(&mut virtual_overseer).await;
|
||||
test_state.respond_to_available_data_query(&mut virtual_overseer, true).await;
|
||||
@@ -1020,7 +1046,8 @@ fn does_not_query_local_validator() {
|
||||
status: LeafStatus::Fresh,
|
||||
span: Arc::new(jaeger::Span::Disabled),
|
||||
})),
|
||||
).await;
|
||||
)
|
||||
.await;
|
||||
|
||||
let (tx, rx) = oneshot::channel();
|
||||
|
||||
@@ -1031,8 +1058,9 @@ fn does_not_query_local_validator() {
|
||||
test_state.session_index,
|
||||
None,
|
||||
tx,
|
||||
)
|
||||
).await;
|
||||
),
|
||||
)
|
||||
.await;
|
||||
|
||||
test_state.test_runtime_api(&mut virtual_overseer).await;
|
||||
test_state.respond_to_available_data_query(&mut virtual_overseer, false).await;
|
||||
@@ -1040,28 +1068,24 @@ fn does_not_query_local_validator() {
|
||||
|
||||
let candidate_hash = test_state.candidate.hash();
|
||||
|
||||
test_state.test_chunk_requests(
|
||||
candidate_hash,
|
||||
&mut virtual_overseer,
|
||||
test_state.validators.len(),
|
||||
|i| if i == 0 {
|
||||
panic!("requested from local validator")
|
||||
} else {
|
||||
Has::timeout()
|
||||
},
|
||||
).await;
|
||||
test_state
|
||||
.test_chunk_requests(
|
||||
candidate_hash,
|
||||
&mut virtual_overseer,
|
||||
test_state.validators.len(),
|
||||
|i| if i == 0 { panic!("requested from local validator") } else { Has::timeout() },
|
||||
)
|
||||
.await;
|
||||
|
||||
// second round, make sure it uses the local chunk.
|
||||
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;
|
||||
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
|
||||
|
||||
Reference in New Issue
Block a user