mirror of
https://github.com/pezkuwichain/pezkuwi-subxt.git
synced 2026-06-19 00:41:03 +00:00
refactor overseer into proc-macro based pattern (#2962)
This commit is contained in:
committed by
GitHub
parent
2510bfc5d7
commit
3c9104daff
@@ -29,6 +29,7 @@
|
||||
//! We maintain a rolling window of session indices. This starts as empty
|
||||
|
||||
use polkadot_node_subsystem::{
|
||||
overseer,
|
||||
messages::{
|
||||
RuntimeApiMessage, RuntimeApiRequest, ChainApiMessage, ApprovalDistributionMessage,
|
||||
ChainSelectionMessage,
|
||||
@@ -84,7 +85,7 @@ struct ImportedBlockInfoEnv<'a> {
|
||||
// Computes information about the imported block. Returns `None` if the info couldn't be extracted -
|
||||
// failure to communicate with overseer,
|
||||
async fn imported_block_info(
|
||||
ctx: &mut impl SubsystemContext,
|
||||
ctx: &mut (impl SubsystemContext + overseer::SubsystemContext),
|
||||
env: ImportedBlockInfoEnv<'_>,
|
||||
block_hash: Hash,
|
||||
block_header: &Header,
|
||||
@@ -98,7 +99,7 @@ async fn imported_block_info(
|
||||
ctx.send_message(RuntimeApiMessage::Request(
|
||||
block_hash,
|
||||
RuntimeApiRequest::CandidateEvents(c_tx),
|
||||
).into()).await;
|
||||
)).await;
|
||||
|
||||
let events: Vec<CandidateEvent> = match c_rx.await {
|
||||
Ok(Ok(events)) => events,
|
||||
@@ -120,7 +121,7 @@ async fn imported_block_info(
|
||||
ctx.send_message(RuntimeApiMessage::Request(
|
||||
block_header.parent_hash,
|
||||
RuntimeApiRequest::SessionIndexForChild(s_tx),
|
||||
).into()).await;
|
||||
)).await;
|
||||
|
||||
let session_index = match s_rx.await {
|
||||
Ok(Ok(s)) => s,
|
||||
@@ -161,7 +162,7 @@ async fn imported_block_info(
|
||||
ctx.send_message(RuntimeApiMessage::Request(
|
||||
block_hash,
|
||||
RuntimeApiRequest::CurrentBabeEpoch(s_tx),
|
||||
).into()).await;
|
||||
)).await;
|
||||
|
||||
match s_rx.await {
|
||||
Ok(Ok(s)) => s,
|
||||
@@ -284,20 +285,21 @@ pub struct BlockImportedCandidates {
|
||||
/// * and return information about all candidates imported under each block.
|
||||
///
|
||||
/// It is the responsibility of the caller to schedule wakeups for each block.
|
||||
pub(crate) async fn handle_new_head<'a>(
|
||||
ctx: &mut impl SubsystemContext,
|
||||
pub(crate) async fn handle_new_head(
|
||||
ctx: &mut (impl SubsystemContext + overseer::SubsystemContext),
|
||||
state: &mut State,
|
||||
db: &mut OverlayedBackend<'a, impl Backend>,
|
||||
db: &mut OverlayedBackend<'_, impl Backend>,
|
||||
head: Hash,
|
||||
finalized_number: &Option<BlockNumber>,
|
||||
) -> SubsystemResult<Vec<BlockImportedCandidates>> {
|
||||
) -> SubsystemResult<Vec<BlockImportedCandidates>>
|
||||
{
|
||||
// Update session info based on most recent head.
|
||||
|
||||
let mut span = jaeger::Span::new(head, "approval-checking-import");
|
||||
|
||||
let header = {
|
||||
let (h_tx, h_rx) = oneshot::channel();
|
||||
ctx.send_message(ChainApiMessage::BlockHeader(head, h_tx).into()).await;
|
||||
ctx.send_message(ChainApiMessage::BlockHeader(head, h_tx)).await;
|
||||
|
||||
match h_rx.await? {
|
||||
Err(e) => {
|
||||
@@ -375,7 +377,7 @@ pub(crate) async fn handle_new_head<'a>(
|
||||
// It's possible that we've lost a race with finality.
|
||||
let (tx, rx) = oneshot::channel();
|
||||
ctx.send_message(
|
||||
ChainApiMessage::FinalizedBlockHash(block_header.number.clone(), tx).into()
|
||||
ChainApiMessage::FinalizedBlockHash(block_header.number.clone(), tx)
|
||||
).await;
|
||||
|
||||
let lost_to_finality = match rx.await {
|
||||
@@ -469,7 +471,7 @@ pub(crate) async fn handle_new_head<'a>(
|
||||
|
||||
// If all bits are already set, then send an approve message.
|
||||
if approved_bitfield.count_ones() == approved_bitfield.len() {
|
||||
ctx.send_message(ChainSelectionMessage::Approved(block_hash).into()).await;
|
||||
ctx.send_message(ChainSelectionMessage::Approved(block_hash)).await;
|
||||
}
|
||||
|
||||
let block_entry = v1::BlockEntry {
|
||||
@@ -498,7 +500,7 @@ pub(crate) async fn handle_new_head<'a>(
|
||||
|
||||
// Notify chain-selection of all approved hashes.
|
||||
for hash in approved_hashes {
|
||||
ctx.send_message(ChainSelectionMessage::Approved(hash).into()).await;
|
||||
ctx.send_message(ChainSelectionMessage::Approved(hash)).await;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -551,7 +553,7 @@ pub(crate) async fn handle_new_head<'a>(
|
||||
"Informing distribution of newly imported chain",
|
||||
);
|
||||
|
||||
ctx.send_unbounded_message(ApprovalDistributionMessage::NewBlocks(approval_meta).into());
|
||||
ctx.send_unbounded_message(ApprovalDistributionMessage::NewBlocks(approval_meta));
|
||||
|
||||
Ok(imported_candidates)
|
||||
}
|
||||
|
||||
@@ -29,7 +29,7 @@ use polkadot_node_subsystem::{
|
||||
AvailabilityRecoveryMessage, ChainSelectionMessage,
|
||||
},
|
||||
errors::RecoveryError,
|
||||
Subsystem, SubsystemContext, SubsystemError, SubsystemResult, SpawnedSubsystem,
|
||||
overseer::{self, SubsystemSender as _}, SubsystemContext, SubsystemError, SubsystemResult, SpawnedSubsystem,
|
||||
FromOverseer, OverseerSignal, SubsystemSender,
|
||||
};
|
||||
use polkadot_node_subsystem_util::{
|
||||
@@ -333,12 +333,15 @@ impl ApprovalVotingSubsystem {
|
||||
}
|
||||
}
|
||||
|
||||
impl<C> Subsystem<C> for ApprovalVotingSubsystem
|
||||
where C: SubsystemContext<Message = ApprovalVotingMessage>
|
||||
impl<Context> overseer::Subsystem<Context, SubsystemError> for ApprovalVotingSubsystem
|
||||
where
|
||||
Context: SubsystemContext<Message = ApprovalVotingMessage>,
|
||||
Context: overseer::SubsystemContext<Message = ApprovalVotingMessage>,
|
||||
{
|
||||
fn start(self, ctx: C) -> SpawnedSubsystem {
|
||||
|
||||
fn start(self, ctx: Context) -> SpawnedSubsystem {
|
||||
let backend = DbBackend::new(self.db.clone(), self.db_config);
|
||||
let future = run::<DbBackend, C>(
|
||||
let future = run::<DbBackend, Context>(
|
||||
ctx,
|
||||
self,
|
||||
Box::new(SystemClock),
|
||||
@@ -663,15 +666,16 @@ enum Action {
|
||||
Conclude,
|
||||
}
|
||||
|
||||
async fn run<B, C>(
|
||||
mut ctx: C,
|
||||
async fn run<B, Context>(
|
||||
mut ctx: Context,
|
||||
mut subsystem: ApprovalVotingSubsystem,
|
||||
clock: Box<dyn Clock + Send + Sync>,
|
||||
assignment_criteria: Box<dyn AssignmentCriteria + Send + Sync>,
|
||||
mut backend: B,
|
||||
) -> SubsystemResult<()>
|
||||
where
|
||||
C: SubsystemContext<Message = ApprovalVotingMessage>,
|
||||
Context: SubsystemContext<Message = ApprovalVotingMessage>,
|
||||
Context: overseer::SubsystemContext<Message = ApprovalVotingMessage>,
|
||||
B: Backend,
|
||||
{
|
||||
let mut state = State {
|
||||
@@ -797,7 +801,7 @@ async fn run<B, C>(
|
||||
//
|
||||
// returns `true` if any of the actions was a `Conclude` command.
|
||||
async fn handle_actions(
|
||||
ctx: &mut impl SubsystemContext,
|
||||
ctx: &mut (impl SubsystemContext<Message = ApprovalVotingMessage> + overseer::SubsystemContext<Message = ApprovalVotingMessage>),
|
||||
state: &mut State,
|
||||
overlayed_db: &mut OverlayedBackend<'_, impl Backend>,
|
||||
metrics: &Metrics,
|
||||
@@ -861,7 +865,7 @@ async fn handle_actions(
|
||||
ctx.send_unbounded_message(ApprovalDistributionMessage::DistributeAssignment(
|
||||
indirect_cert,
|
||||
candidate_index,
|
||||
).into());
|
||||
));
|
||||
|
||||
match approvals_cache.get(&candidate_hash) {
|
||||
Some(ApprovalOutcome::Approved) => {
|
||||
@@ -902,14 +906,14 @@ async fn handle_actions(
|
||||
}
|
||||
}
|
||||
Action::NoteApprovedInChainSelection(block_hash) => {
|
||||
ctx.send_message(ChainSelectionMessage::Approved(block_hash).into()).await;
|
||||
ctx.send_message(ChainSelectionMessage::Approved(block_hash)).await;
|
||||
}
|
||||
Action::BecomeActive => {
|
||||
*mode = Mode::Active;
|
||||
|
||||
let messages = distribution_messages_for_activation(overlayed_db)?;
|
||||
|
||||
ctx.send_messages(messages.into_iter().map(Into::into)).await;
|
||||
ctx.send_messages(messages.into_iter()).await;
|
||||
}
|
||||
Action::Conclude => { conclude = true; }
|
||||
}
|
||||
@@ -1017,7 +1021,7 @@ fn distribution_messages_for_activation(
|
||||
|
||||
// Handle an incoming signal from the overseer. Returns true if execution should conclude.
|
||||
async fn handle_from_overseer(
|
||||
ctx: &mut impl SubsystemContext,
|
||||
ctx: &mut (impl SubsystemContext<Message = ApprovalVotingMessage> + overseer::SubsystemContext<Message = ApprovalVotingMessage>),
|
||||
state: &mut State,
|
||||
db: &mut OverlayedBackend<'_, impl Backend>,
|
||||
metrics: &Metrics,
|
||||
@@ -1130,7 +1134,7 @@ async fn handle_from_overseer(
|
||||
}
|
||||
|
||||
async fn handle_approved_ancestor(
|
||||
ctx: &mut impl SubsystemContext,
|
||||
ctx: &mut (impl SubsystemContext + overseer::SubsystemContext),
|
||||
db: &OverlayedBackend<'_, impl Backend>,
|
||||
target: Hash,
|
||||
lower_bound: BlockNumber,
|
||||
@@ -1149,7 +1153,7 @@ async fn handle_approved_ancestor(
|
||||
let target_number = {
|
||||
let (tx, rx) = oneshot::channel();
|
||||
|
||||
ctx.send_message(ChainApiMessage::BlockNumber(target, tx).into()).await;
|
||||
ctx.send_message(ChainApiMessage::BlockNumber(target, tx)).await;
|
||||
|
||||
match rx.await {
|
||||
Ok(Ok(Some(n))) => n,
|
||||
@@ -1173,7 +1177,7 @@ async fn handle_approved_ancestor(
|
||||
hash: target,
|
||||
k: (target_number - (lower_bound + 1)) as usize,
|
||||
response_channel: tx,
|
||||
}.into()).await;
|
||||
}).await;
|
||||
|
||||
match rx.await {
|
||||
Ok(Ok(a)) => a,
|
||||
@@ -1994,7 +1998,7 @@ fn process_wakeup(
|
||||
// spawned. When the background work is no longer needed, the `AbortHandle` should be dropped
|
||||
// to cancel the background work and any requests it has spawned.
|
||||
async fn launch_approval(
|
||||
ctx: &mut impl SubsystemContext,
|
||||
ctx: &mut (impl SubsystemContext<Message = ApprovalVotingMessage> + overseer::SubsystemContext<Message = ApprovalVotingMessage>),
|
||||
metrics: Metrics,
|
||||
session_index: SessionIndex,
|
||||
candidate: CandidateReceipt,
|
||||
@@ -2043,7 +2047,7 @@ async fn launch_approval(
|
||||
session_index,
|
||||
Some(backing_group),
|
||||
a_tx,
|
||||
).into()).await;
|
||||
)).await;
|
||||
|
||||
ctx.send_message(
|
||||
RuntimeApiMessage::Request(
|
||||
@@ -2052,7 +2056,7 @@ async fn launch_approval(
|
||||
candidate.descriptor.validation_code_hash,
|
||||
code_tx,
|
||||
),
|
||||
).into()
|
||||
)
|
||||
).await;
|
||||
|
||||
let candidate = candidate.clone();
|
||||
|
||||
@@ -37,7 +37,9 @@ use polkadot_node_primitives::{
|
||||
ErasureChunk, AvailableData,
|
||||
};
|
||||
use polkadot_subsystem::{
|
||||
FromOverseer, OverseerSignal, SubsystemError, Subsystem, SubsystemContext, SpawnedSubsystem,
|
||||
FromOverseer, OverseerSignal, SubsystemError,
|
||||
SubsystemContext, SpawnedSubsystem,
|
||||
overseer,
|
||||
ActiveLeavesUpdate,
|
||||
errors::{ChainApiError, RuntimeApiError},
|
||||
};
|
||||
@@ -522,9 +524,10 @@ impl KnownUnfinalizedBlocks {
|
||||
}
|
||||
}
|
||||
|
||||
impl<Context> Subsystem<Context> for AvailabilityStoreSubsystem
|
||||
impl<Context> overseer::Subsystem<Context, SubsystemError> for AvailabilityStoreSubsystem
|
||||
where
|
||||
Context: SubsystemContext<Message = AvailabilityStoreMessage>,
|
||||
Context: overseer::SubsystemContext<Message = AvailabilityStoreMessage>,
|
||||
{
|
||||
fn start(self, ctx: Context) -> SpawnedSubsystem {
|
||||
let future = run(self, ctx)
|
||||
@@ -540,7 +543,8 @@ where
|
||||
|
||||
async fn run<Context>(mut subsystem: AvailabilityStoreSubsystem, mut ctx: Context)
|
||||
where
|
||||
Context: SubsystemContext<Message=AvailabilityStoreMessage>,
|
||||
Context: SubsystemContext<Message = AvailabilityStoreMessage>,
|
||||
Context: overseer::SubsystemContext<Message = AvailabilityStoreMessage>,
|
||||
{
|
||||
let mut next_pruning = Delay::new(subsystem.pruning_config.pruning_interval).fuse();
|
||||
|
||||
@@ -570,7 +574,8 @@ async fn run_iteration<Context>(
|
||||
)
|
||||
-> Result<bool, Error>
|
||||
where
|
||||
Context: SubsystemContext<Message=AvailabilityStoreMessage>,
|
||||
Context: SubsystemContext<Message = AvailabilityStoreMessage>,
|
||||
Context: overseer::SubsystemContext<Message = AvailabilityStoreMessage>,
|
||||
{
|
||||
select! {
|
||||
incoming = ctx.recv().fuse() => {
|
||||
@@ -615,18 +620,22 @@ where
|
||||
Ok(false)
|
||||
}
|
||||
|
||||
async fn process_block_activated(
|
||||
ctx: &mut impl SubsystemContext,
|
||||
async fn process_block_activated<Context>(
|
||||
ctx: &mut Context,
|
||||
subsystem: &mut AvailabilityStoreSubsystem,
|
||||
activated: Hash,
|
||||
) -> Result<(), Error> {
|
||||
) -> Result<(), Error>
|
||||
where
|
||||
Context: SubsystemContext<Message = AvailabilityStoreMessage>,
|
||||
Context: overseer::SubsystemContext<Message = AvailabilityStoreMessage>,
|
||||
{
|
||||
let now = subsystem.clock.now()?;
|
||||
|
||||
let block_header = {
|
||||
let (tx, rx) = oneshot::channel();
|
||||
|
||||
ctx.send_message(
|
||||
ChainApiMessage::BlockHeader(activated, tx).into()
|
||||
ChainApiMessage::BlockHeader(activated, tx)
|
||||
).await;
|
||||
|
||||
match rx.await?? {
|
||||
@@ -666,8 +675,8 @@ async fn process_block_activated(
|
||||
Ok(())
|
||||
}
|
||||
|
||||
async fn process_new_head(
|
||||
ctx: &mut impl SubsystemContext,
|
||||
async fn process_new_head<Context>(
|
||||
ctx: &mut Context,
|
||||
db: &Arc<dyn KeyValueDB>,
|
||||
db_transaction: &mut DBTransaction,
|
||||
config: &Config,
|
||||
@@ -675,12 +684,16 @@ async fn process_new_head(
|
||||
now: Duration,
|
||||
hash: Hash,
|
||||
header: Header,
|
||||
) -> Result<(), Error> {
|
||||
) -> Result<(), Error>
|
||||
where
|
||||
Context: SubsystemContext<Message = AvailabilityStoreMessage>,
|
||||
Context: overseer::SubsystemContext<Message = AvailabilityStoreMessage>,
|
||||
{
|
||||
|
||||
let candidate_events = {
|
||||
let (tx, rx) = oneshot::channel();
|
||||
ctx.send_message(
|
||||
RuntimeApiMessage::Request(hash, RuntimeApiRequest::CandidateEvents(tx)).into()
|
||||
RuntimeApiMessage::Request(hash, RuntimeApiRequest::CandidateEvents(tx))
|
||||
).await;
|
||||
|
||||
rx.await??
|
||||
@@ -691,7 +704,7 @@ async fn process_new_head(
|
||||
let n_validators = {
|
||||
let (tx, rx) = oneshot::channel();
|
||||
ctx.send_message(
|
||||
RuntimeApiMessage::Request(header.parent_hash, RuntimeApiRequest::Validators(tx)).into()
|
||||
RuntimeApiMessage::Request(header.parent_hash, RuntimeApiRequest::Validators(tx))
|
||||
).await;
|
||||
|
||||
rx.await??.len()
|
||||
@@ -835,12 +848,16 @@ macro_rules! peek_num {
|
||||
}
|
||||
}
|
||||
|
||||
async fn process_block_finalized(
|
||||
ctx: &mut impl SubsystemContext,
|
||||
async fn process_block_finalized<Context>(
|
||||
ctx: &mut Context,
|
||||
subsystem: &AvailabilityStoreSubsystem,
|
||||
finalized_hash: Hash,
|
||||
finalized_number: BlockNumber,
|
||||
) -> Result<(), Error> {
|
||||
) -> Result<(), Error>
|
||||
where
|
||||
Context: SubsystemContext<Message = AvailabilityStoreMessage>,
|
||||
Context: overseer::SubsystemContext<Message = AvailabilityStoreMessage>,
|
||||
{
|
||||
let now = subsystem.clock.now()?;
|
||||
|
||||
let mut next_possible_batch = 0;
|
||||
@@ -869,7 +886,7 @@ async fn process_block_finalized(
|
||||
finalized_hash
|
||||
} else {
|
||||
let (tx, rx) = oneshot::channel();
|
||||
ctx.send_message(ChainApiMessage::FinalizedBlockHash(batch_num, tx).into()).await;
|
||||
ctx.send_message(ChainApiMessage::FinalizedBlockHash(batch_num, tx)).await;
|
||||
|
||||
match rx.await?? {
|
||||
None => {
|
||||
|
||||
@@ -37,6 +37,7 @@ use polkadot_node_primitives::{
|
||||
use polkadot_subsystem::{
|
||||
PerLeafSpan, Stage, SubsystemSender,
|
||||
jaeger,
|
||||
overseer,
|
||||
messages::{
|
||||
AllMessages, AvailabilityDistributionMessage, AvailabilityStoreMessage,
|
||||
CandidateBackingMessage, CandidateValidationMessage, CollatorProtocolMessage,
|
||||
@@ -308,7 +309,7 @@ async fn store_available_data(
|
||||
n_validators,
|
||||
available_data,
|
||||
tx,
|
||||
).into()).await;
|
||||
)).await;
|
||||
|
||||
let _ = rx.await.map_err(Error::StoreAvailableData)?;
|
||||
|
||||
@@ -384,7 +385,7 @@ async fn request_pov(
|
||||
candidate_hash,
|
||||
pov_hash,
|
||||
tx,
|
||||
}.into()).await;
|
||||
}).await;
|
||||
|
||||
let pov = rx.await.map_err(|_| Error::FetchPoV)?;
|
||||
Ok(Arc::new(pov))
|
||||
@@ -397,13 +398,12 @@ async fn request_candidate_validation(
|
||||
) -> Result<ValidationResult, Error> {
|
||||
let (tx, rx) = oneshot::channel();
|
||||
|
||||
sender.send_message(AllMessages::CandidateValidation(
|
||||
CandidateValidationMessage::ValidateFromChainState(
|
||||
candidate,
|
||||
pov,
|
||||
tx,
|
||||
)
|
||||
).into()
|
||||
sender.send_message(
|
||||
CandidateValidationMessage::ValidateFromChainState(
|
||||
candidate,
|
||||
pov,
|
||||
tx,
|
||||
)
|
||||
).await;
|
||||
|
||||
match rx.await {
|
||||
@@ -415,7 +415,7 @@ async fn request_candidate_validation(
|
||||
|
||||
type BackgroundValidationResult = Result<(CandidateReceipt, CandidateCommitments, Arc<PoV>), CandidateReceipt>;
|
||||
|
||||
struct BackgroundValidationParams<S, F> {
|
||||
struct BackgroundValidationParams<S: overseer::SubsystemSender<AllMessages>, F> {
|
||||
sender: JobSender<S>,
|
||||
tx_command: mpsc::Sender<ValidatedCandidateCommand>,
|
||||
candidate: CandidateReceipt,
|
||||
@@ -600,14 +600,14 @@ impl CandidateBackingJob {
|
||||
root_span,
|
||||
).await? {
|
||||
sender.send_message(
|
||||
CollatorProtocolMessage::Seconded(self.parent, stmt).into()
|
||||
CollatorProtocolMessage::Seconded(self.parent, stmt)
|
||||
).await;
|
||||
}
|
||||
}
|
||||
}
|
||||
Err(candidate) => {
|
||||
sender.send_message(
|
||||
CollatorProtocolMessage::Invalid(self.parent, candidate).into()
|
||||
CollatorProtocolMessage::Invalid(self.parent, candidate)
|
||||
).await;
|
||||
}
|
||||
}
|
||||
@@ -683,7 +683,7 @@ impl CandidateBackingJob {
|
||||
.map_or(false, |c| c != &candidate.descriptor().collator)
|
||||
{
|
||||
sender.send_message(
|
||||
CollatorProtocolMessage::Invalid(self.parent, candidate.clone()).into()
|
||||
CollatorProtocolMessage::Invalid(self.parent, candidate.clone())
|
||||
).await;
|
||||
return Ok(());
|
||||
}
|
||||
@@ -732,7 +732,7 @@ impl CandidateBackingJob {
|
||||
if let Some(signed_statement) = self.sign_statement(statement).await {
|
||||
self.import_statement(sender, &signed_statement, root_span).await?;
|
||||
let smsg = StatementDistributionMessage::Share(self.parent, signed_statement.clone());
|
||||
sender.send_unbounded_message(smsg.into());
|
||||
sender.send_unbounded_message(smsg);
|
||||
|
||||
Ok(Some(signed_statement))
|
||||
} else {
|
||||
@@ -749,7 +749,7 @@ impl CandidateBackingJob {
|
||||
ProvisionerMessage::ProvisionableData(
|
||||
self.parent,
|
||||
ProvisionableData::MisbehaviorReport(self.parent, validator_id, report)
|
||||
).into()
|
||||
)
|
||||
).await;
|
||||
}
|
||||
}
|
||||
@@ -801,7 +801,7 @@ impl CandidateBackingJob {
|
||||
self.parent,
|
||||
ProvisionableData::BackedCandidate(backed.receipt()),
|
||||
);
|
||||
sender.send_message(message.into()).await;
|
||||
sender.send_message(message).await;
|
||||
|
||||
span.as_ref().map(|s| s.child("backed"));
|
||||
span
|
||||
|
||||
@@ -38,10 +38,14 @@ use polkadot_primitives::v1::{AvailabilityBitfield, CoreState, Hash, ValidatorIn
|
||||
use std::{pin::Pin, time::Duration, iter::FromIterator, sync::Arc};
|
||||
use wasm_timer::{Delay, Instant};
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests;
|
||||
|
||||
/// Delay between starting a bitfield signing job and its attempting to create a bitfield.
|
||||
const JOB_DELAY: Duration = Duration::from_millis(1500);
|
||||
const LOG_TARGET: &str = "parachain::bitfield-signing";
|
||||
|
||||
|
||||
/// Each `BitfieldSigningJob` prepares a signed bitfield for a single relay parent.
|
||||
pub struct BitfieldSigningJob;
|
||||
|
||||
@@ -299,7 +303,7 @@ impl JobTrait for BitfieldSigningJob {
|
||||
.send_message(BitfieldDistributionMessage::DistributeBitfield(
|
||||
relay_parent,
|
||||
signed_bitfield,
|
||||
).into())
|
||||
))
|
||||
.await;
|
||||
|
||||
Ok(())
|
||||
@@ -310,74 +314,3 @@ impl JobTrait for BitfieldSigningJob {
|
||||
|
||||
/// BitfieldSigningSubsystem manages a number of bitfield signing jobs.
|
||||
pub type BitfieldSigningSubsystem<Spawner> = JobSubsystem<BitfieldSigningJob, Spawner>;
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
use futures::{pin_mut, executor::block_on};
|
||||
use polkadot_primitives::v1::{CandidateHash, OccupiedCore};
|
||||
use polkadot_node_subsystem::messages::AllMessages;
|
||||
|
||||
fn occupied_core(para_id: u32, candidate_hash: CandidateHash) -> CoreState {
|
||||
CoreState::Occupied(OccupiedCore {
|
||||
group_responsible: para_id.into(),
|
||||
next_up_on_available: None,
|
||||
occupied_since: 100_u32,
|
||||
time_out_at: 200_u32,
|
||||
next_up_on_time_out: None,
|
||||
availability: Default::default(),
|
||||
candidate_hash,
|
||||
candidate_descriptor: Default::default(),
|
||||
})
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn construct_availability_bitfield_works() {
|
||||
block_on(async move {
|
||||
let relay_parent = Hash::default();
|
||||
let validator_index = ValidatorIndex(1u32);
|
||||
|
||||
let (mut sender, mut receiver) = polkadot_node_subsystem_test_helpers::sender_receiver();
|
||||
let future = construct_availability_bitfield(
|
||||
relay_parent,
|
||||
&jaeger::Span::Disabled,
|
||||
validator_index,
|
||||
&mut sender,
|
||||
).fuse();
|
||||
pin_mut!(future);
|
||||
|
||||
let hash_a = CandidateHash(Hash::repeat_byte(1));
|
||||
let hash_b = CandidateHash(Hash::repeat_byte(2));
|
||||
|
||||
loop {
|
||||
futures::select! {
|
||||
m = receiver.next() => match m.unwrap() {
|
||||
AllMessages::RuntimeApi(
|
||||
RuntimeApiMessage::Request(rp, RuntimeApiRequest::AvailabilityCores(tx)),
|
||||
) => {
|
||||
assert_eq!(relay_parent, rp);
|
||||
tx.send(Ok(vec![CoreState::Free, occupied_core(1, hash_a), occupied_core(2, hash_b)])).unwrap();
|
||||
}
|
||||
AllMessages::AvailabilityStore(
|
||||
AvailabilityStoreMessage::QueryChunkAvailability(c_hash, vidx, tx),
|
||||
) => {
|
||||
assert_eq!(validator_index, vidx);
|
||||
|
||||
tx.send(c_hash == hash_a).unwrap();
|
||||
},
|
||||
o => panic!("Unknown message: {:?}", o),
|
||||
},
|
||||
r = future => match r {
|
||||
Ok(r) => {
|
||||
assert!(!r.0.get(0).unwrap());
|
||||
assert!(r.0.get(1).unwrap());
|
||||
assert!(!r.0.get(2).unwrap());
|
||||
break
|
||||
},
|
||||
Err(e) => panic!("Failed: {:?}", e),
|
||||
},
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,83 @@
|
||||
// Copyright 2020 Parity Technologies (UK) Ltd.
|
||||
// This file is part of Polkadot.
|
||||
|
||||
// Polkadot is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
|
||||
// Polkadot is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
|
||||
// You should have received a copy of the GNU General Public License
|
||||
// along with Polkadot. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
use super::*;
|
||||
use futures::{pin_mut, executor::block_on};
|
||||
use polkadot_primitives::v1::{CandidateHash, OccupiedCore};
|
||||
use polkadot_node_subsystem::messages::AllMessages;
|
||||
|
||||
fn occupied_core(para_id: u32, candidate_hash: CandidateHash) -> CoreState {
|
||||
CoreState::Occupied(OccupiedCore {
|
||||
group_responsible: para_id.into(),
|
||||
next_up_on_available: None,
|
||||
occupied_since: 100_u32,
|
||||
time_out_at: 200_u32,
|
||||
next_up_on_time_out: None,
|
||||
availability: Default::default(),
|
||||
candidate_hash,
|
||||
candidate_descriptor: Default::default(),
|
||||
})
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn construct_availability_bitfield_works() {
|
||||
block_on(async move {
|
||||
let relay_parent = Hash::default();
|
||||
let validator_index = ValidatorIndex(1u32);
|
||||
|
||||
let (mut sender, mut receiver) = polkadot_node_subsystem_test_helpers::sender_receiver();
|
||||
let future = construct_availability_bitfield(
|
||||
relay_parent,
|
||||
&jaeger::Span::Disabled,
|
||||
validator_index,
|
||||
&mut sender,
|
||||
).fuse();
|
||||
pin_mut!(future);
|
||||
|
||||
let hash_a = CandidateHash(Hash::repeat_byte(1));
|
||||
let hash_b = CandidateHash(Hash::repeat_byte(2));
|
||||
|
||||
loop {
|
||||
futures::select! {
|
||||
m = receiver.next() => match m.unwrap() {
|
||||
AllMessages::RuntimeApi(
|
||||
RuntimeApiMessage::Request(rp, RuntimeApiRequest::AvailabilityCores(tx)),
|
||||
) => {
|
||||
assert_eq!(relay_parent, rp);
|
||||
tx.send(Ok(vec![CoreState::Free, occupied_core(1, hash_a), occupied_core(2, hash_b)])).unwrap();
|
||||
}
|
||||
AllMessages::AvailabilityStore(
|
||||
AvailabilityStoreMessage::QueryChunkAvailability(c_hash, vidx, tx),
|
||||
) => {
|
||||
assert_eq!(validator_index, vidx);
|
||||
|
||||
tx.send(c_hash == hash_a).unwrap();
|
||||
},
|
||||
o => panic!("Unknown message: {:?}", o),
|
||||
},
|
||||
r = future => match r {
|
||||
Ok(r) => {
|
||||
assert!(!r.0.get(0).unwrap());
|
||||
assert!(r.0.get(1).unwrap());
|
||||
assert!(!r.0.get(2).unwrap());
|
||||
break
|
||||
},
|
||||
Err(e) => panic!("Failed: {:?}", e),
|
||||
},
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
@@ -15,7 +15,7 @@ parity-scale-codec = { version = "2.0.0", default-features = false, features = [
|
||||
polkadot-primitives = { path = "../../../primitives" }
|
||||
polkadot-parachain = { path = "../../../parachain" }
|
||||
polkadot-node-primitives = { path = "../../primitives" }
|
||||
polkadot-subsystem = { package = "polkadot-node-subsystem", path = "../../subsystem" }
|
||||
polkadot-node-subsystem = { package = "polkadot-node-subsystem", path = "../../subsystem" }
|
||||
polkadot-node-subsystem-util = { path = "../../subsystem-util" }
|
||||
|
||||
[target.'cfg(not(any(target_os = "android", target_os = "unknown")))'.dependencies]
|
||||
|
||||
@@ -23,16 +23,17 @@
|
||||
#![deny(unused_crate_dependencies, unused_results)]
|
||||
#![warn(missing_docs)]
|
||||
|
||||
use polkadot_subsystem::{
|
||||
Subsystem, SubsystemContext, SpawnedSubsystem, SubsystemResult, SubsystemError,
|
||||
use polkadot_node_subsystem::{
|
||||
overseer,
|
||||
SubsystemContext, SpawnedSubsystem, SubsystemResult, SubsystemError,
|
||||
FromOverseer, OverseerSignal,
|
||||
messages::{
|
||||
AllMessages, CandidateValidationMessage, RuntimeApiMessage,
|
||||
CandidateValidationMessage, RuntimeApiMessage,
|
||||
ValidationFailed, RuntimeApiRequest,
|
||||
},
|
||||
errors::RuntimeApiError,
|
||||
};
|
||||
use polkadot_node_subsystem_util::metrics::{self, prometheus};
|
||||
use polkadot_subsystem::errors::RuntimeApiError;
|
||||
use polkadot_node_primitives::{
|
||||
VALIDATION_CODE_BOMB_LIMIT, POV_BOMB_LIMIT, ValidationResult, InvalidCandidate, PoV, BlockData,
|
||||
};
|
||||
@@ -84,10 +85,12 @@ impl CandidateValidationSubsystem {
|
||||
}
|
||||
}
|
||||
|
||||
impl<C> Subsystem<C> for CandidateValidationSubsystem where
|
||||
C: SubsystemContext<Message = CandidateValidationMessage>,
|
||||
impl<Context> overseer::Subsystem<Context, SubsystemError> for CandidateValidationSubsystem
|
||||
where
|
||||
Context: SubsystemContext<Message = CandidateValidationMessage>,
|
||||
Context: overseer::SubsystemContext<Message = CandidateValidationMessage>,
|
||||
{
|
||||
fn start(self, ctx: C) -> SpawnedSubsystem {
|
||||
fn start(self, ctx: Context) -> SpawnedSubsystem {
|
||||
let future = run(ctx, self.metrics, self.config.artifacts_cache_path, self.config.program_path)
|
||||
.map_err(|e| SubsystemError::with_origin("candidate-validation", e))
|
||||
.boxed();
|
||||
@@ -98,12 +101,16 @@ impl<C> Subsystem<C> for CandidateValidationSubsystem where
|
||||
}
|
||||
}
|
||||
|
||||
async fn run(
|
||||
mut ctx: impl SubsystemContext<Message = CandidateValidationMessage>,
|
||||
async fn run<Context>(
|
||||
mut ctx: Context,
|
||||
metrics: Metrics,
|
||||
cache_path: PathBuf,
|
||||
program_path: PathBuf,
|
||||
) -> SubsystemResult<()> {
|
||||
) -> SubsystemResult<()>
|
||||
where
|
||||
Context: SubsystemContext<Message = CandidateValidationMessage>,
|
||||
Context: overseer::SubsystemContext<Message = CandidateValidationMessage>,
|
||||
{
|
||||
let (mut validation_host, task) = polkadot_node_core_pvf::start(
|
||||
polkadot_node_core_pvf::Config::new(cache_path, program_path),
|
||||
);
|
||||
@@ -174,17 +181,21 @@ async fn run(
|
||||
}
|
||||
}
|
||||
|
||||
async fn runtime_api_request<T>(
|
||||
ctx: &mut impl SubsystemContext<Message = CandidateValidationMessage>,
|
||||
async fn runtime_api_request<T, Context>(
|
||||
ctx: &mut Context,
|
||||
relay_parent: Hash,
|
||||
request: RuntimeApiRequest,
|
||||
receiver: oneshot::Receiver<Result<T, RuntimeApiError>>,
|
||||
) -> SubsystemResult<Result<T, RuntimeApiError>> {
|
||||
) -> SubsystemResult<Result<T, RuntimeApiError>>
|
||||
where
|
||||
Context: SubsystemContext<Message = CandidateValidationMessage>,
|
||||
Context: overseer::SubsystemContext<Message = CandidateValidationMessage>,
|
||||
{
|
||||
ctx.send_message(
|
||||
AllMessages::RuntimeApi(RuntimeApiMessage::Request(
|
||||
RuntimeApiMessage::Request(
|
||||
relay_parent,
|
||||
request,
|
||||
))
|
||||
)
|
||||
).await;
|
||||
|
||||
receiver.await.map_err(Into::into)
|
||||
@@ -197,11 +208,15 @@ enum AssumptionCheckOutcome {
|
||||
BadRequest,
|
||||
}
|
||||
|
||||
async fn check_assumption_validation_data(
|
||||
ctx: &mut impl SubsystemContext<Message = CandidateValidationMessage>,
|
||||
async fn check_assumption_validation_data<Context>(
|
||||
ctx: &mut Context,
|
||||
descriptor: &CandidateDescriptor,
|
||||
assumption: OccupiedCoreAssumption,
|
||||
) -> SubsystemResult<AssumptionCheckOutcome> {
|
||||
) -> SubsystemResult<AssumptionCheckOutcome>
|
||||
where
|
||||
Context: SubsystemContext<Message = CandidateValidationMessage>,
|
||||
Context: overseer::SubsystemContext<Message = CandidateValidationMessage>,
|
||||
{
|
||||
let validation_data = {
|
||||
let (tx, rx) = oneshot::channel();
|
||||
let d = runtime_api_request(
|
||||
@@ -247,10 +262,14 @@ async fn check_assumption_validation_data(
|
||||
})
|
||||
}
|
||||
|
||||
async fn find_assumed_validation_data(
|
||||
ctx: &mut impl SubsystemContext<Message = CandidateValidationMessage>,
|
||||
async fn find_assumed_validation_data<Context>(
|
||||
ctx: &mut Context,
|
||||
descriptor: &CandidateDescriptor,
|
||||
) -> SubsystemResult<AssumptionCheckOutcome> {
|
||||
) -> SubsystemResult<AssumptionCheckOutcome>
|
||||
where
|
||||
Context: SubsystemContext<Message = CandidateValidationMessage>,
|
||||
Context: overseer::SubsystemContext<Message = CandidateValidationMessage>,
|
||||
{
|
||||
// The candidate descriptor has a `persisted_validation_data_hash` which corresponds to
|
||||
// one of up to two possible values that we can derive from the state of the
|
||||
// relay-parent. We can fetch these values by getting the persisted validation data
|
||||
@@ -278,13 +297,17 @@ async fn find_assumed_validation_data(
|
||||
Ok(AssumptionCheckOutcome::DoesNotMatch)
|
||||
}
|
||||
|
||||
async fn spawn_validate_from_chain_state(
|
||||
ctx: &mut impl SubsystemContext<Message = CandidateValidationMessage>,
|
||||
async fn spawn_validate_from_chain_state<Context>(
|
||||
ctx: &mut Context,
|
||||
validation_host: &mut ValidationHost,
|
||||
descriptor: CandidateDescriptor,
|
||||
pov: Arc<PoV>,
|
||||
metrics: &Metrics,
|
||||
) -> SubsystemResult<Result<ValidationResult, ValidationFailed>> {
|
||||
) -> SubsystemResult<Result<ValidationResult, ValidationFailed>>
|
||||
where
|
||||
Context: SubsystemContext<Message = CandidateValidationMessage>,
|
||||
Context: overseer::SubsystemContext<Message = CandidateValidationMessage>,
|
||||
{
|
||||
let (validation_data, validation_code) =
|
||||
match find_assumed_validation_data(ctx, &descriptor).await? {
|
||||
AssumptionCheckOutcome::Matches(validation_data, validation_code) => {
|
||||
|
||||
@@ -15,6 +15,7 @@
|
||||
// along with Polkadot. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
use super::*;
|
||||
use polkadot_node_subsystem::messages::AllMessages;
|
||||
use polkadot_node_subsystem_test_helpers as test_helpers;
|
||||
use polkadot_primitives::v1::{HeadData, UpwardMessage};
|
||||
use sp_core::testing::TaskExecutor;
|
||||
|
||||
@@ -40,10 +40,15 @@ use sp_blockchain::HeaderBackend;
|
||||
use polkadot_node_subsystem_util::metrics::{self, prometheus};
|
||||
use polkadot_primitives::v1::{Block, BlockId};
|
||||
use polkadot_subsystem::{
|
||||
messages::ChainApiMessage, FromOverseer, OverseerSignal, SpawnedSubsystem, Subsystem,
|
||||
overseer,
|
||||
messages::ChainApiMessage,
|
||||
FromOverseer, OverseerSignal, SpawnedSubsystem,
|
||||
SubsystemContext, SubsystemError, SubsystemResult,
|
||||
};
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests;
|
||||
|
||||
const LOG_TARGET: &str = "parachain::chain-api";
|
||||
|
||||
/// The Chain API Subsystem implementation.
|
||||
@@ -62,13 +67,14 @@ impl<Client> ChainApiSubsystem<Client> {
|
||||
}
|
||||
}
|
||||
|
||||
impl<Client, Context> Subsystem<Context> for ChainApiSubsystem<Client>
|
||||
impl<Client, Context> overseer::Subsystem<Context, SubsystemError> for ChainApiSubsystem<Client>
|
||||
where
|
||||
Client: HeaderBackend<Block> + AuxStore + 'static,
|
||||
Context: SubsystemContext<Message = ChainApiMessage>,
|
||||
Context: overseer::SubsystemContext<Message = ChainApiMessage>,
|
||||
{
|
||||
fn start(self, ctx: Context) -> SpawnedSubsystem {
|
||||
let future = run(ctx, self)
|
||||
let future = run::<Client, Context>(ctx, self)
|
||||
.map_err(|e| SubsystemError::with_origin("chain-api", e))
|
||||
.boxed();
|
||||
SpawnedSubsystem {
|
||||
@@ -78,12 +84,14 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
async fn run<Client>(
|
||||
mut ctx: impl SubsystemContext<Message = ChainApiMessage>,
|
||||
async fn run<Client, Context>(
|
||||
mut ctx: Context,
|
||||
subsystem: ChainApiSubsystem<Client>,
|
||||
) -> SubsystemResult<()>
|
||||
where
|
||||
Client: HeaderBackend<Block> + AuxStore,
|
||||
Context: SubsystemContext<Message = ChainApiMessage>,
|
||||
Context: overseer::SubsystemContext<Message = ChainApiMessage>,
|
||||
{
|
||||
loop {
|
||||
match ctx.recv().await? {
|
||||
@@ -291,311 +299,3 @@ impl metrics::Metrics for Metrics {
|
||||
Ok(Metrics(Some(metrics)))
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
||||
use std::collections::BTreeMap;
|
||||
use futures::{future::BoxFuture, channel::oneshot};
|
||||
use parity_scale_codec::Encode;
|
||||
|
||||
use polkadot_primitives::v1::{Hash, BlockNumber, BlockId, Header};
|
||||
use polkadot_node_primitives::BlockWeight;
|
||||
use polkadot_node_subsystem_test_helpers::{make_subsystem_context, TestSubsystemContextHandle};
|
||||
use sp_blockchain::Info as BlockInfo;
|
||||
use sp_core::testing::TaskExecutor;
|
||||
|
||||
#[derive(Clone)]
|
||||
struct TestClient {
|
||||
blocks: BTreeMap<Hash, BlockNumber>,
|
||||
block_weights: BTreeMap<Hash, BlockWeight>,
|
||||
finalized_blocks: BTreeMap<BlockNumber, Hash>,
|
||||
headers: BTreeMap<Hash, Header>,
|
||||
}
|
||||
|
||||
const ONE: Hash = Hash::repeat_byte(0x01);
|
||||
const TWO: Hash = Hash::repeat_byte(0x02);
|
||||
const THREE: Hash = Hash::repeat_byte(0x03);
|
||||
const FOUR: Hash = Hash::repeat_byte(0x04);
|
||||
const ERROR_PATH: Hash = Hash::repeat_byte(0xFF);
|
||||
|
||||
fn default_header() -> Header {
|
||||
Header {
|
||||
parent_hash: Hash::zero(),
|
||||
number: 100500,
|
||||
state_root: Hash::zero(),
|
||||
extrinsics_root: Hash::zero(),
|
||||
digest: Default::default(),
|
||||
}
|
||||
}
|
||||
|
||||
impl Default for TestClient {
|
||||
fn default() -> Self {
|
||||
Self {
|
||||
blocks: maplit::btreemap! {
|
||||
ONE => 1,
|
||||
TWO => 2,
|
||||
THREE => 3,
|
||||
FOUR => 4,
|
||||
},
|
||||
block_weights: maplit::btreemap! {
|
||||
ONE => 0,
|
||||
TWO => 1,
|
||||
THREE => 1,
|
||||
FOUR => 2,
|
||||
},
|
||||
finalized_blocks: maplit::btreemap! {
|
||||
1 => ONE,
|
||||
3 => THREE,
|
||||
},
|
||||
headers: maplit::btreemap! {
|
||||
TWO => Header {
|
||||
parent_hash: ONE,
|
||||
number: 2,
|
||||
..default_header()
|
||||
},
|
||||
THREE => Header {
|
||||
parent_hash: TWO,
|
||||
number: 3,
|
||||
..default_header()
|
||||
},
|
||||
FOUR => Header {
|
||||
parent_hash: THREE,
|
||||
number: 4,
|
||||
..default_header()
|
||||
},
|
||||
ERROR_PATH => Header {
|
||||
..default_header()
|
||||
}
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn last_key_value<K: Clone, V: Clone>(map: &BTreeMap<K, V>) -> (K, V) {
|
||||
assert!(!map.is_empty());
|
||||
map.iter()
|
||||
.last()
|
||||
.map(|(k, v)| (k.clone(), v.clone()))
|
||||
.unwrap()
|
||||
}
|
||||
|
||||
impl HeaderBackend<Block> for TestClient {
|
||||
fn info(&self) -> BlockInfo<Block> {
|
||||
let genesis_hash = self.blocks.iter().next().map(|(h, _)| *h).unwrap();
|
||||
let (best_hash, best_number) = last_key_value(&self.blocks);
|
||||
let (finalized_number, finalized_hash) = last_key_value(&self.finalized_blocks);
|
||||
|
||||
BlockInfo {
|
||||
best_hash,
|
||||
best_number,
|
||||
genesis_hash,
|
||||
finalized_hash,
|
||||
finalized_number,
|
||||
number_leaves: 0,
|
||||
finalized_state: None,
|
||||
}
|
||||
}
|
||||
fn number(&self, hash: Hash) -> sp_blockchain::Result<Option<BlockNumber>> {
|
||||
Ok(self.blocks.get(&hash).copied())
|
||||
}
|
||||
fn hash(&self, number: BlockNumber) -> sp_blockchain::Result<Option<Hash>> {
|
||||
Ok(self.finalized_blocks.get(&number).copied())
|
||||
}
|
||||
fn header(&self, id: BlockId) -> sp_blockchain::Result<Option<Header>> {
|
||||
match id {
|
||||
// for error path testing
|
||||
BlockId::Hash(hash) if hash.is_zero() => {
|
||||
Err(sp_blockchain::Error::Backend("Zero hashes are illegal!".into()))
|
||||
}
|
||||
BlockId::Hash(hash) => {
|
||||
Ok(self.headers.get(&hash).cloned())
|
||||
}
|
||||
_ => unreachable!(),
|
||||
}
|
||||
}
|
||||
fn status(&self, _id: BlockId) -> sp_blockchain::Result<sp_blockchain::BlockStatus> {
|
||||
unimplemented!()
|
||||
}
|
||||
}
|
||||
|
||||
fn test_harness(
|
||||
test: impl FnOnce(Arc<TestClient>, TestSubsystemContextHandle<ChainApiMessage>)
|
||||
-> BoxFuture<'static, ()>,
|
||||
) {
|
||||
let (ctx, ctx_handle) = make_subsystem_context(TaskExecutor::new());
|
||||
let client = Arc::new(TestClient::default());
|
||||
|
||||
let subsystem = ChainApiSubsystem::new(client.clone(), Metrics(None));
|
||||
let chain_api_task = run(ctx, subsystem).map(|x| x.unwrap());
|
||||
let test_task = test(client, ctx_handle);
|
||||
|
||||
futures::executor::block_on(future::join(chain_api_task, test_task));
|
||||
}
|
||||
|
||||
impl AuxStore for TestClient {
|
||||
fn insert_aux<
|
||||
'a,
|
||||
'b: 'a,
|
||||
'c: 'a,
|
||||
I: IntoIterator<Item = &'a (&'c [u8], &'c [u8])>,
|
||||
D: IntoIterator<Item = &'a &'b [u8]>,
|
||||
>(
|
||||
&self,
|
||||
_insert: I,
|
||||
_delete: D,
|
||||
) -> sp_blockchain::Result<()> {
|
||||
unimplemented!()
|
||||
}
|
||||
|
||||
fn get_aux(&self, key: &[u8]) -> sp_blockchain::Result<Option<Vec<u8>>> {
|
||||
Ok(self
|
||||
.block_weights
|
||||
.iter()
|
||||
.find(|(hash, _)| sc_consensus_babe::aux_schema::block_weight_key(hash) == key)
|
||||
.map(|(_, weight)| weight.encode()))
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn request_block_number() {
|
||||
test_harness(|client, mut sender| {
|
||||
async move {
|
||||
let zero = Hash::zero();
|
||||
let test_cases = [
|
||||
(TWO, client.number(TWO).unwrap()),
|
||||
(zero, client.number(zero).unwrap()), // not here
|
||||
];
|
||||
for (hash, expected) in &test_cases {
|
||||
let (tx, rx) = oneshot::channel();
|
||||
|
||||
sender.send(FromOverseer::Communication {
|
||||
msg: ChainApiMessage::BlockNumber(*hash, tx),
|
||||
}).await;
|
||||
|
||||
assert_eq!(rx.await.unwrap().unwrap(), *expected);
|
||||
}
|
||||
|
||||
sender.send(FromOverseer::Signal(OverseerSignal::Conclude)).await;
|
||||
}.boxed()
|
||||
})
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn request_block_header() {
|
||||
test_harness(|client, mut sender| {
|
||||
async move {
|
||||
const NOT_HERE: Hash = Hash::repeat_byte(0x5);
|
||||
let test_cases = [
|
||||
(TWO, client.header(BlockId::Hash(TWO)).unwrap()),
|
||||
(NOT_HERE, client.header(BlockId::Hash(NOT_HERE)).unwrap()),
|
||||
];
|
||||
for (hash, expected) in &test_cases {
|
||||
let (tx, rx) = oneshot::channel();
|
||||
|
||||
sender.send(FromOverseer::Communication {
|
||||
msg: ChainApiMessage::BlockHeader(*hash, tx),
|
||||
}).await;
|
||||
|
||||
assert_eq!(rx.await.unwrap().unwrap(), *expected);
|
||||
}
|
||||
|
||||
sender.send(FromOverseer::Signal(OverseerSignal::Conclude)).await;
|
||||
}.boxed()
|
||||
})
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn request_block_weight() {
|
||||
test_harness(|client, mut sender| {
|
||||
async move {
|
||||
const NOT_HERE: Hash = Hash::repeat_byte(0x5);
|
||||
let test_cases = [
|
||||
(TWO, sc_consensus_babe::block_weight(&*client, TWO).unwrap()),
|
||||
(FOUR, sc_consensus_babe::block_weight(&*client, FOUR).unwrap()),
|
||||
(NOT_HERE, sc_consensus_babe::block_weight(&*client, NOT_HERE).unwrap()),
|
||||
];
|
||||
for (hash, expected) in &test_cases {
|
||||
let (tx, rx) = oneshot::channel();
|
||||
|
||||
sender.send(FromOverseer::Communication {
|
||||
msg: ChainApiMessage::BlockWeight(*hash, tx),
|
||||
}).await;
|
||||
|
||||
assert_eq!(rx.await.unwrap().unwrap(), *expected);
|
||||
}
|
||||
|
||||
sender.send(FromOverseer::Signal(OverseerSignal::Conclude)).await;
|
||||
}.boxed()
|
||||
})
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn request_finalized_hash() {
|
||||
test_harness(|client, mut sender| {
|
||||
async move {
|
||||
let test_cases = [
|
||||
(1, client.hash(1).unwrap()), // not here
|
||||
(2, client.hash(2).unwrap()),
|
||||
];
|
||||
for (number, expected) in &test_cases {
|
||||
let (tx, rx) = oneshot::channel();
|
||||
|
||||
sender.send(FromOverseer::Communication {
|
||||
msg: ChainApiMessage::FinalizedBlockHash(*number, tx),
|
||||
}).await;
|
||||
|
||||
assert_eq!(rx.await.unwrap().unwrap(), *expected);
|
||||
}
|
||||
|
||||
sender.send(FromOverseer::Signal(OverseerSignal::Conclude)).await;
|
||||
}.boxed()
|
||||
})
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn request_last_finalized_number() {
|
||||
test_harness(|client, mut sender| {
|
||||
async move {
|
||||
let (tx, rx) = oneshot::channel();
|
||||
|
||||
let expected = client.info().finalized_number;
|
||||
sender.send(FromOverseer::Communication {
|
||||
msg: ChainApiMessage::FinalizedBlockNumber(tx),
|
||||
}).await;
|
||||
|
||||
assert_eq!(rx.await.unwrap().unwrap(), expected);
|
||||
|
||||
sender.send(FromOverseer::Signal(OverseerSignal::Conclude)).await;
|
||||
}.boxed()
|
||||
})
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn request_ancestors() {
|
||||
test_harness(|_client, mut sender| {
|
||||
async move {
|
||||
let (tx, rx) = oneshot::channel();
|
||||
sender.send(FromOverseer::Communication {
|
||||
msg: ChainApiMessage::Ancestors { hash: THREE, k: 4, response_channel: tx },
|
||||
}).await;
|
||||
assert_eq!(rx.await.unwrap().unwrap(), vec![TWO, ONE]);
|
||||
|
||||
let (tx, rx) = oneshot::channel();
|
||||
sender.send(FromOverseer::Communication {
|
||||
msg: ChainApiMessage::Ancestors { hash: TWO, k: 1, response_channel: tx },
|
||||
}).await;
|
||||
assert_eq!(rx.await.unwrap().unwrap(), vec![ONE]);
|
||||
|
||||
let (tx, rx) = oneshot::channel();
|
||||
sender.send(FromOverseer::Communication {
|
||||
msg: ChainApiMessage::Ancestors { hash: ERROR_PATH, k: 2, response_channel: tx },
|
||||
}).await;
|
||||
assert!(rx.await.unwrap().is_err());
|
||||
|
||||
sender.send(FromOverseer::Signal(OverseerSignal::Conclude)).await;
|
||||
}.boxed()
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,304 @@
|
||||
use super::*;
|
||||
|
||||
use std::collections::BTreeMap;
|
||||
use futures::{future::BoxFuture, channel::oneshot};
|
||||
use parity_scale_codec::Encode;
|
||||
|
||||
use polkadot_primitives::v1::{Hash, BlockNumber, BlockId, Header};
|
||||
use polkadot_node_primitives::BlockWeight;
|
||||
use polkadot_node_subsystem_test_helpers::{make_subsystem_context, TestSubsystemContextHandle};
|
||||
use sp_blockchain::Info as BlockInfo;
|
||||
use sp_core::testing::TaskExecutor;
|
||||
|
||||
#[derive(Clone)]
|
||||
struct TestClient {
|
||||
blocks: BTreeMap<Hash, BlockNumber>,
|
||||
block_weights: BTreeMap<Hash, BlockWeight>,
|
||||
finalized_blocks: BTreeMap<BlockNumber, Hash>,
|
||||
headers: BTreeMap<Hash, Header>,
|
||||
}
|
||||
|
||||
const ONE: Hash = Hash::repeat_byte(0x01);
|
||||
const TWO: Hash = Hash::repeat_byte(0x02);
|
||||
const THREE: Hash = Hash::repeat_byte(0x03);
|
||||
const FOUR: Hash = Hash::repeat_byte(0x04);
|
||||
const ERROR_PATH: Hash = Hash::repeat_byte(0xFF);
|
||||
|
||||
fn default_header() -> Header {
|
||||
Header {
|
||||
parent_hash: Hash::zero(),
|
||||
number: 100500,
|
||||
state_root: Hash::zero(),
|
||||
extrinsics_root: Hash::zero(),
|
||||
digest: Default::default(),
|
||||
}
|
||||
}
|
||||
|
||||
impl Default for TestClient {
|
||||
fn default() -> Self {
|
||||
Self {
|
||||
blocks: maplit::btreemap! {
|
||||
ONE => 1,
|
||||
TWO => 2,
|
||||
THREE => 3,
|
||||
FOUR => 4,
|
||||
},
|
||||
block_weights: maplit::btreemap! {
|
||||
ONE => 0,
|
||||
TWO => 1,
|
||||
THREE => 1,
|
||||
FOUR => 2,
|
||||
},
|
||||
finalized_blocks: maplit::btreemap! {
|
||||
1 => ONE,
|
||||
3 => THREE,
|
||||
},
|
||||
headers: maplit::btreemap! {
|
||||
TWO => Header {
|
||||
parent_hash: ONE,
|
||||
number: 2,
|
||||
..default_header()
|
||||
},
|
||||
THREE => Header {
|
||||
parent_hash: TWO,
|
||||
number: 3,
|
||||
..default_header()
|
||||
},
|
||||
FOUR => Header {
|
||||
parent_hash: THREE,
|
||||
number: 4,
|
||||
..default_header()
|
||||
},
|
||||
ERROR_PATH => Header {
|
||||
..default_header()
|
||||
}
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn last_key_value<K: Clone, V: Clone>(map: &BTreeMap<K, V>) -> (K, V) {
|
||||
assert!(!map.is_empty());
|
||||
map.iter()
|
||||
.last()
|
||||
.map(|(k, v)| (k.clone(), v.clone()))
|
||||
.unwrap()
|
||||
}
|
||||
|
||||
impl HeaderBackend<Block> for TestClient {
|
||||
fn info(&self) -> BlockInfo<Block> {
|
||||
let genesis_hash = self.blocks.iter().next().map(|(h, _)| *h).unwrap();
|
||||
let (best_hash, best_number) = last_key_value(&self.blocks);
|
||||
let (finalized_number, finalized_hash) = last_key_value(&self.finalized_blocks);
|
||||
|
||||
BlockInfo {
|
||||
best_hash,
|
||||
best_number,
|
||||
genesis_hash,
|
||||
finalized_hash,
|
||||
finalized_number,
|
||||
number_leaves: 0,
|
||||
finalized_state: None,
|
||||
}
|
||||
}
|
||||
fn number(&self, hash: Hash) -> sp_blockchain::Result<Option<BlockNumber>> {
|
||||
Ok(self.blocks.get(&hash).copied())
|
||||
}
|
||||
fn hash(&self, number: BlockNumber) -> sp_blockchain::Result<Option<Hash>> {
|
||||
Ok(self.finalized_blocks.get(&number).copied())
|
||||
}
|
||||
fn header(&self, id: BlockId) -> sp_blockchain::Result<Option<Header>> {
|
||||
match id {
|
||||
// for error path testing
|
||||
BlockId::Hash(hash) if hash.is_zero() => {
|
||||
Err(sp_blockchain::Error::Backend("Zero hashes are illegal!".into()))
|
||||
}
|
||||
BlockId::Hash(hash) => {
|
||||
Ok(self.headers.get(&hash).cloned())
|
||||
}
|
||||
_ => unreachable!(),
|
||||
}
|
||||
}
|
||||
fn status(&self, _id: BlockId) -> sp_blockchain::Result<sp_blockchain::BlockStatus> {
|
||||
unimplemented!()
|
||||
}
|
||||
}
|
||||
|
||||
fn test_harness(
|
||||
test: impl FnOnce(Arc<TestClient>, TestSubsystemContextHandle<ChainApiMessage>)
|
||||
-> BoxFuture<'static, ()>,
|
||||
) {
|
||||
let (ctx, ctx_handle) = make_subsystem_context(TaskExecutor::new());
|
||||
let client = Arc::new(TestClient::default());
|
||||
|
||||
let subsystem = ChainApiSubsystem::new(client.clone(), Metrics(None));
|
||||
let chain_api_task = run(ctx, subsystem).map(|x| x.unwrap());
|
||||
let test_task = test(client, ctx_handle);
|
||||
|
||||
futures::executor::block_on(future::join(chain_api_task, test_task));
|
||||
}
|
||||
|
||||
impl AuxStore for TestClient {
|
||||
fn insert_aux<
|
||||
'a,
|
||||
'b: 'a,
|
||||
'c: 'a,
|
||||
I: IntoIterator<Item = &'a (&'c [u8], &'c [u8])>,
|
||||
D: IntoIterator<Item = &'a &'b [u8]>,
|
||||
>(
|
||||
&self,
|
||||
_insert: I,
|
||||
_delete: D,
|
||||
) -> sp_blockchain::Result<()> {
|
||||
unimplemented!()
|
||||
}
|
||||
|
||||
fn get_aux(&self, key: &[u8]) -> sp_blockchain::Result<Option<Vec<u8>>> {
|
||||
Ok(self
|
||||
.block_weights
|
||||
.iter()
|
||||
.find(|(hash, _)| sc_consensus_babe::aux_schema::block_weight_key(hash) == key)
|
||||
.map(|(_, weight)| weight.encode()))
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn request_block_number() {
|
||||
test_harness(|client, mut sender| {
|
||||
async move {
|
||||
let zero = Hash::zero();
|
||||
let test_cases = [
|
||||
(TWO, client.number(TWO).unwrap()),
|
||||
(zero, client.number(zero).unwrap()), // not here
|
||||
];
|
||||
for (hash, expected) in &test_cases {
|
||||
let (tx, rx) = oneshot::channel();
|
||||
|
||||
sender.send(FromOverseer::Communication {
|
||||
msg: ChainApiMessage::BlockNumber(*hash, tx),
|
||||
}).await;
|
||||
|
||||
assert_eq!(rx.await.unwrap().unwrap(), *expected);
|
||||
}
|
||||
|
||||
sender.send(FromOverseer::Signal(OverseerSignal::Conclude)).await;
|
||||
}.boxed()
|
||||
})
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn request_block_header() {
|
||||
test_harness(|client, mut sender| {
|
||||
async move {
|
||||
const NOT_HERE: Hash = Hash::repeat_byte(0x5);
|
||||
let test_cases = [
|
||||
(TWO, client.header(BlockId::Hash(TWO)).unwrap()),
|
||||
(NOT_HERE, client.header(BlockId::Hash(NOT_HERE)).unwrap()),
|
||||
];
|
||||
for (hash, expected) in &test_cases {
|
||||
let (tx, rx) = oneshot::channel();
|
||||
|
||||
sender.send(FromOverseer::Communication {
|
||||
msg: ChainApiMessage::BlockHeader(*hash, tx),
|
||||
}).await;
|
||||
|
||||
assert_eq!(rx.await.unwrap().unwrap(), *expected);
|
||||
}
|
||||
|
||||
sender.send(FromOverseer::Signal(OverseerSignal::Conclude)).await;
|
||||
}.boxed()
|
||||
})
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn request_block_weight() {
|
||||
test_harness(|client, mut sender| {
|
||||
async move {
|
||||
const NOT_HERE: Hash = Hash::repeat_byte(0x5);
|
||||
let test_cases = [
|
||||
(TWO, sc_consensus_babe::block_weight(&*client, TWO).unwrap()),
|
||||
(FOUR, sc_consensus_babe::block_weight(&*client, FOUR).unwrap()),
|
||||
(NOT_HERE, sc_consensus_babe::block_weight(&*client, NOT_HERE).unwrap()),
|
||||
];
|
||||
for (hash, expected) in &test_cases {
|
||||
let (tx, rx) = oneshot::channel();
|
||||
|
||||
sender.send(FromOverseer::Communication {
|
||||
msg: ChainApiMessage::BlockWeight(*hash, tx),
|
||||
}).await;
|
||||
|
||||
assert_eq!(rx.await.unwrap().unwrap(), *expected);
|
||||
}
|
||||
|
||||
sender.send(FromOverseer::Signal(OverseerSignal::Conclude)).await;
|
||||
}.boxed()
|
||||
})
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn request_finalized_hash() {
|
||||
test_harness(|client, mut sender| {
|
||||
async move {
|
||||
let test_cases = [
|
||||
(1, client.hash(1).unwrap()), // not here
|
||||
(2, client.hash(2).unwrap()),
|
||||
];
|
||||
for (number, expected) in &test_cases {
|
||||
let (tx, rx) = oneshot::channel();
|
||||
|
||||
sender.send(FromOverseer::Communication {
|
||||
msg: ChainApiMessage::FinalizedBlockHash(*number, tx),
|
||||
}).await;
|
||||
|
||||
assert_eq!(rx.await.unwrap().unwrap(), *expected);
|
||||
}
|
||||
|
||||
sender.send(FromOverseer::Signal(OverseerSignal::Conclude)).await;
|
||||
}.boxed()
|
||||
})
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn request_last_finalized_number() {
|
||||
test_harness(|client, mut sender| {
|
||||
async move {
|
||||
let (tx, rx) = oneshot::channel();
|
||||
|
||||
let expected = client.info().finalized_number;
|
||||
sender.send(FromOverseer::Communication {
|
||||
msg: ChainApiMessage::FinalizedBlockNumber(tx),
|
||||
}).await;
|
||||
|
||||
assert_eq!(rx.await.unwrap().unwrap(), expected);
|
||||
|
||||
sender.send(FromOverseer::Signal(OverseerSignal::Conclude)).await;
|
||||
}.boxed()
|
||||
})
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn request_ancestors() {
|
||||
test_harness(|_client, mut sender| {
|
||||
async move {
|
||||
let (tx, rx) = oneshot::channel();
|
||||
sender.send(FromOverseer::Communication {
|
||||
msg: ChainApiMessage::Ancestors { hash: THREE, k: 4, response_channel: tx },
|
||||
}).await;
|
||||
assert_eq!(rx.await.unwrap().unwrap(), vec![TWO, ONE]);
|
||||
|
||||
let (tx, rx) = oneshot::channel();
|
||||
sender.send(FromOverseer::Communication {
|
||||
msg: ChainApiMessage::Ancestors { hash: TWO, k: 1, response_channel: tx },
|
||||
}).await;
|
||||
assert_eq!(rx.await.unwrap().unwrap(), vec![ONE]);
|
||||
|
||||
let (tx, rx) = oneshot::channel();
|
||||
sender.send(FromOverseer::Communication {
|
||||
msg: ChainApiMessage::Ancestors { hash: ERROR_PATH, k: 2, response_channel: tx },
|
||||
}).await;
|
||||
assert!(rx.await.unwrap().is_err());
|
||||
|
||||
sender.send(FromOverseer::Signal(OverseerSignal::Conclude)).await;
|
||||
}.boxed()
|
||||
})
|
||||
}
|
||||
@@ -11,7 +11,7 @@ futures-timer = "3"
|
||||
tracing = "0.1.26"
|
||||
polkadot-primitives = { path = "../../../primitives" }
|
||||
polkadot-node-primitives = { path = "../../primitives" }
|
||||
polkadot-subsystem = { package = "polkadot-node-subsystem", path = "../../subsystem" }
|
||||
polkadot-node-subsystem = { path = "../../subsystem" }
|
||||
polkadot-node-subsystem-util = { path = "../../subsystem-util" }
|
||||
kvdb = "0.10.0"
|
||||
thiserror = "1.0.23"
|
||||
|
||||
@@ -18,8 +18,8 @@
|
||||
|
||||
use polkadot_primitives::v1::{BlockNumber, Hash, Header, ConsensusLog};
|
||||
use polkadot_node_primitives::BlockWeight;
|
||||
use polkadot_subsystem::{
|
||||
Subsystem, SubsystemContext, SubsystemError, SpawnedSubsystem,
|
||||
use polkadot_node_subsystem::{
|
||||
overseer, SubsystemContext, SubsystemError, SpawnedSubsystem,
|
||||
OverseerSignal, FromOverseer,
|
||||
messages::{ChainSelectionMessage, ChainApiMessage},
|
||||
errors::ChainApiError,
|
||||
@@ -306,8 +306,10 @@ impl ChainSelectionSubsystem {
|
||||
}
|
||||
}
|
||||
|
||||
impl<Context> Subsystem<Context> for ChainSelectionSubsystem
|
||||
where Context: SubsystemContext<Message = ChainSelectionMessage>
|
||||
impl<Context> overseer::Subsystem<Context, SubsystemError> for ChainSelectionSubsystem
|
||||
where
|
||||
Context: SubsystemContext<Message = ChainSelectionMessage>,
|
||||
Context: overseer::SubsystemContext<Message = ChainSelectionMessage>,
|
||||
{
|
||||
fn start(self, ctx: Context) -> SpawnedSubsystem {
|
||||
let backend = crate::db_backend::v1::DbBackend::new(
|
||||
@@ -337,6 +339,7 @@ async fn run<Context, B>(
|
||||
)
|
||||
where
|
||||
Context: SubsystemContext<Message = ChainSelectionMessage>,
|
||||
Context: overseer::SubsystemContext<Message = ChainSelectionMessage>,
|
||||
B: Backend,
|
||||
{
|
||||
loop {
|
||||
@@ -376,6 +379,7 @@ async fn run_iteration<Context, B>(
|
||||
-> Result<(), Error>
|
||||
where
|
||||
Context: SubsystemContext<Message = ChainSelectionMessage>,
|
||||
Context: overseer::SubsystemContext<Message = ChainSelectionMessage>,
|
||||
B: Backend,
|
||||
{
|
||||
let mut stagnant_check_stream = stagnant_check_interval.timeout_stream();
|
||||
@@ -439,11 +443,11 @@ async fn fetch_finalized(
|
||||
let (number_tx, number_rx) = oneshot::channel();
|
||||
let (hash_tx, hash_rx) = oneshot::channel();
|
||||
|
||||
ctx.send_message(ChainApiMessage::FinalizedBlockNumber(number_tx).into()).await;
|
||||
ctx.send_message(ChainApiMessage::FinalizedBlockNumber(number_tx)).await;
|
||||
|
||||
let number = number_rx.await??;
|
||||
|
||||
ctx.send_message(ChainApiMessage::FinalizedBlockHash(number, hash_tx).into()).await;
|
||||
ctx.send_message(ChainApiMessage::FinalizedBlockHash(number, hash_tx)).await;
|
||||
|
||||
match hash_rx.await?? {
|
||||
None => {
|
||||
@@ -464,7 +468,7 @@ async fn fetch_header(
|
||||
hash: Hash,
|
||||
) -> Result<Option<Header>, Error> {
|
||||
let (h_tx, h_rx) = oneshot::channel();
|
||||
ctx.send_message(ChainApiMessage::BlockHeader(hash, h_tx).into()).await;
|
||||
ctx.send_message(ChainApiMessage::BlockHeader(hash, h_tx)).await;
|
||||
|
||||
h_rx.await?.map_err(Into::into)
|
||||
}
|
||||
@@ -474,7 +478,7 @@ async fn fetch_block_weight(
|
||||
hash: Hash,
|
||||
) -> Result<Option<BlockWeight>, Error> {
|
||||
let (tx, rx) = oneshot::channel();
|
||||
ctx.send_message(ChainApiMessage::BlockWeight(hash, tx).into()).await;
|
||||
ctx.send_message(ChainApiMessage::BlockWeight(hash, tx)).await;
|
||||
|
||||
rx.await?.map_err(Into::into)
|
||||
}
|
||||
|
||||
@@ -31,8 +31,11 @@ use sp_core::testing::TaskExecutor;
|
||||
use assert_matches::assert_matches;
|
||||
|
||||
use polkadot_primitives::v1::{BlakeTwo256, HashT, ConsensusLog};
|
||||
use polkadot_subsystem::{jaeger, ActiveLeavesUpdate, ActivatedLeaf, LeafStatus};
|
||||
use polkadot_subsystem::messages::AllMessages;
|
||||
use polkadot_node_subsystem::{
|
||||
messages::AllMessages,
|
||||
jaeger,
|
||||
ActiveLeavesUpdate, ActivatedLeaf, LeafStatus,
|
||||
};
|
||||
use polkadot_node_subsystem_test_helpers as test_helpers;
|
||||
|
||||
#[derive(Default)]
|
||||
|
||||
@@ -30,10 +30,11 @@ use std::sync::Arc;
|
||||
|
||||
use polkadot_node_primitives::{CandidateVotes, SignedDisputeStatement};
|
||||
use polkadot_node_subsystem::{
|
||||
overseer,
|
||||
messages::{
|
||||
DisputeCoordinatorMessage, ChainApiMessage, DisputeParticipationMessage,
|
||||
},
|
||||
Subsystem, SubsystemContext, FromOverseer, OverseerSignal, SpawnedSubsystem,
|
||||
SubsystemContext, FromOverseer, OverseerSignal, SpawnedSubsystem,
|
||||
SubsystemError,
|
||||
errors::{ChainApiError, RuntimeApiError},
|
||||
};
|
||||
@@ -101,8 +102,10 @@ impl DisputeCoordinatorSubsystem {
|
||||
}
|
||||
}
|
||||
|
||||
impl<Context> Subsystem<Context> for DisputeCoordinatorSubsystem
|
||||
where Context: SubsystemContext<Message = DisputeCoordinatorMessage>
|
||||
impl<Context> overseer::Subsystem<Context, SubsystemError> for DisputeCoordinatorSubsystem
|
||||
where
|
||||
Context: SubsystemContext<Message = DisputeCoordinatorMessage>,
|
||||
Context: overseer::SubsystemContext<Message = DisputeCoordinatorMessage>,
|
||||
{
|
||||
fn start(self, ctx: Context) -> SpawnedSubsystem {
|
||||
let future = run(self, ctx)
|
||||
@@ -160,7 +163,9 @@ impl Error {
|
||||
}
|
||||
|
||||
async fn run<Context>(subsystem: DisputeCoordinatorSubsystem, mut ctx: Context)
|
||||
where Context: SubsystemContext<Message = DisputeCoordinatorMessage>
|
||||
where
|
||||
Context: overseer::SubsystemContext<Message = DisputeCoordinatorMessage>,
|
||||
Context: SubsystemContext<Message = DisputeCoordinatorMessage>
|
||||
{
|
||||
loop {
|
||||
let res = run_iteration(&mut ctx, &subsystem).await;
|
||||
@@ -187,7 +192,9 @@ async fn run<Context>(subsystem: DisputeCoordinatorSubsystem, mut ctx: Context)
|
||||
// lead to another call to this function.
|
||||
async fn run_iteration<Context>(ctx: &mut Context, subsystem: &DisputeCoordinatorSubsystem)
|
||||
-> Result<(), Error>
|
||||
where Context: SubsystemContext<Message = DisputeCoordinatorMessage>
|
||||
where
|
||||
Context: overseer::SubsystemContext<Message = DisputeCoordinatorMessage>,
|
||||
Context: SubsystemContext<Message = DisputeCoordinatorMessage>
|
||||
{
|
||||
let DisputeCoordinatorSubsystem { ref store, ref keystore, ref config } = *subsystem;
|
||||
let mut state = State {
|
||||
@@ -225,7 +232,7 @@ async fn run_iteration<Context>(ctx: &mut Context, subsystem: &DisputeCoordinato
|
||||
}
|
||||
|
||||
async fn handle_new_activations(
|
||||
ctx: &mut impl SubsystemContext,
|
||||
ctx: &mut (impl SubsystemContext<Message = DisputeCoordinatorMessage> + overseer::SubsystemContext<Message = DisputeCoordinatorMessage>),
|
||||
store: &dyn KeyValueDB,
|
||||
state: &mut State,
|
||||
config: &Config,
|
||||
@@ -236,7 +243,7 @@ async fn handle_new_activations(
|
||||
let (tx, rx) = oneshot::channel();
|
||||
|
||||
ctx.send_message(
|
||||
ChainApiMessage::BlockHeader(new_leaf, tx).into()
|
||||
ChainApiMessage::BlockHeader(new_leaf, tx)
|
||||
).await;
|
||||
|
||||
match rx.await?? {
|
||||
@@ -488,7 +495,7 @@ async fn handle_import_statements(
|
||||
candidate_receipt,
|
||||
session,
|
||||
n_validators: n_validators as u32,
|
||||
}.into()).await;
|
||||
}).await;
|
||||
}
|
||||
|
||||
if concluded_valid && already_disputed {
|
||||
|
||||
@@ -26,12 +26,13 @@ use futures::prelude::*;
|
||||
use polkadot_node_primitives::ValidationResult;
|
||||
use polkadot_node_subsystem::{
|
||||
errors::{RecoveryError, RuntimeApiError},
|
||||
overseer,
|
||||
messages::{
|
||||
AllMessages, AvailabilityRecoveryMessage, AvailabilityStoreMessage,
|
||||
AvailabilityRecoveryMessage, AvailabilityStoreMessage,
|
||||
CandidateValidationMessage, DisputeCoordinatorMessage, DisputeParticipationMessage,
|
||||
RuntimeApiMessage, RuntimeApiRequest,
|
||||
},
|
||||
ActiveLeavesUpdate, FromOverseer, OverseerSignal, SpawnedSubsystem, Subsystem,
|
||||
ActiveLeavesUpdate, FromOverseer, OverseerSignal, SpawnedSubsystem,
|
||||
SubsystemContext, SubsystemError,
|
||||
};
|
||||
use polkadot_primitives::v1::{BlockNumber, CandidateHash, CandidateReceipt, Hash, SessionIndex};
|
||||
@@ -55,9 +56,10 @@ impl DisputeParticipationSubsystem {
|
||||
}
|
||||
}
|
||||
|
||||
impl<Context> Subsystem<Context> for DisputeParticipationSubsystem
|
||||
impl<Context> overseer::Subsystem<Context, SubsystemError> for DisputeParticipationSubsystem
|
||||
where
|
||||
Context: SubsystemContext<Message = DisputeParticipationMessage>,
|
||||
Context: overseer::SubsystemContext<Message = DisputeParticipationMessage>,
|
||||
{
|
||||
fn start(self, ctx: Context) -> SpawnedSubsystem {
|
||||
let future = run(ctx).map(|_| Ok(())).boxed();
|
||||
@@ -111,6 +113,7 @@ impl Error {
|
||||
async fn run<Context>(mut ctx: Context)
|
||||
where
|
||||
Context: SubsystemContext<Message = DisputeParticipationMessage>,
|
||||
Context: overseer::SubsystemContext<Message = DisputeParticipationMessage>,
|
||||
{
|
||||
let mut state = State { recent_block: None };
|
||||
|
||||
@@ -196,7 +199,6 @@ async fn participate(
|
||||
None,
|
||||
recover_available_data_tx,
|
||||
)
|
||||
.into(),
|
||||
)
|
||||
.await;
|
||||
|
||||
@@ -223,7 +225,6 @@ async fn participate(
|
||||
code_tx,
|
||||
),
|
||||
)
|
||||
.into(),
|
||||
)
|
||||
.await;
|
||||
|
||||
@@ -252,7 +253,6 @@ async fn participate(
|
||||
available_data.clone(),
|
||||
store_available_data_tx,
|
||||
)
|
||||
.into(),
|
||||
)
|
||||
.await;
|
||||
|
||||
@@ -277,7 +277,6 @@ async fn participate(
|
||||
available_data.pov,
|
||||
validation_tx,
|
||||
)
|
||||
.into(),
|
||||
)
|
||||
.await;
|
||||
|
||||
@@ -360,13 +359,13 @@ async fn issue_local_statement(
|
||||
session: SessionIndex,
|
||||
valid: bool,
|
||||
) {
|
||||
ctx.send_message(AllMessages::DisputeCoordinator(
|
||||
ctx.send_message(
|
||||
DisputeCoordinatorMessage::IssueLocalStatement(
|
||||
session,
|
||||
candidate_hash,
|
||||
candidate_receipt,
|
||||
valid,
|
||||
),
|
||||
))
|
||||
)
|
||||
.await
|
||||
}
|
||||
|
||||
@@ -24,7 +24,8 @@ use super::*;
|
||||
use parity_scale_codec::Encode;
|
||||
use polkadot_node_primitives::{AvailableData, BlockData, InvalidCandidate, PoV};
|
||||
use polkadot_node_subsystem::{
|
||||
jaeger, messages::ValidationFailed, ActivatedLeaf, ActiveLeavesUpdate, LeafStatus,
|
||||
overseer::Subsystem,
|
||||
jaeger, messages::{AllMessages, ValidationFailed}, ActivatedLeaf, ActiveLeavesUpdate, LeafStatus,
|
||||
};
|
||||
use polkadot_node_subsystem_test_helpers::{make_subsystem_context, TestSubsystemContextHandle};
|
||||
use polkadot_primitives::v1::{BlakeTwo256, CandidateCommitments, HashT, Header, ValidationCode};
|
||||
|
||||
@@ -11,7 +11,6 @@ tracing = "0.1.26"
|
||||
thiserror = "1.0.23"
|
||||
async-trait = "0.1.47"
|
||||
polkadot-node-subsystem = { path = "../../subsystem" }
|
||||
polkadot-overseer = { path = "../../overseer" }
|
||||
polkadot-primitives = { path = "../../../primitives" }
|
||||
sp-blockchain = { git = "https://github.com/paritytech/substrate", branch = "master" }
|
||||
sp-inherents = { git = "https://github.com/paritytech/substrate", branch = "master" }
|
||||
|
||||
@@ -26,9 +26,9 @@
|
||||
|
||||
use futures::{select, FutureExt};
|
||||
use polkadot_node_subsystem::{
|
||||
messages::{AllMessages, ProvisionerMessage}, SubsystemError,
|
||||
overseer::Handle,
|
||||
messages::ProvisionerMessage, errors::SubsystemError,
|
||||
};
|
||||
use polkadot_overseer::OverseerHandler;
|
||||
use polkadot_primitives::v1::{
|
||||
Block, Hash, InherentData as ParachainsInherentData,
|
||||
};
|
||||
@@ -48,19 +48,17 @@ impl ParachainsInherentDataProvider {
|
||||
/// Create a new instance of the [`ParachainsInherentDataProvider`].
|
||||
pub async fn create<C: HeaderBackend<Block>>(
|
||||
client: &C,
|
||||
mut overseer: OverseerHandler,
|
||||
mut overseer: Handle,
|
||||
parent: Hash,
|
||||
) -> Result<Self, Error> {
|
||||
let pid = async {
|
||||
let (sender, receiver) = futures::channel::oneshot::channel();
|
||||
overseer.wait_for_activation(parent, sender).await;
|
||||
receiver.await.map_err(|_| Error::ClosedChannelAwaitingActivation)?.map_err(Error::Subsystem)?;
|
||||
receiver.await.map_err(|_| Error::ClosedChannelAwaitingActivation)?.map_err(|e| Error::Subsystem(e))?;
|
||||
|
||||
let (sender, receiver) = futures::channel::oneshot::channel();
|
||||
overseer.send_msg(
|
||||
AllMessages::Provisioner(
|
||||
ProvisionerMessage::RequestInherentData(parent, sender),
|
||||
),
|
||||
ProvisionerMessage::RequestInherentData(parent, sender),
|
||||
std::any::type_name::<Self>(),
|
||||
).await;
|
||||
|
||||
@@ -127,7 +125,7 @@ impl sp_inherents::InherentDataProvider for ParachainsInherentDataProvider {
|
||||
#[derive(thiserror::Error, Debug)]
|
||||
pub enum Error {
|
||||
#[error("Blockchain error")]
|
||||
Blockchain(sp_blockchain::Error),
|
||||
Blockchain(#[from] sp_blockchain::Error),
|
||||
#[error("Timeout: provisioner did not return inherent data after {:?}", PROVISIONER_TIMEOUT)]
|
||||
Timeout,
|
||||
#[error("Could not find the parent header in the blockchain: {:?}", _0)]
|
||||
@@ -137,5 +135,5 @@ pub enum Error {
|
||||
#[error("Closed channel from provisioner when awaiting inherent data")]
|
||||
ClosedChannelAwaitingInherentData,
|
||||
#[error("Subsystem failed")]
|
||||
Subsystem(SubsystemError),
|
||||
Subsystem(#[from] SubsystemError),
|
||||
}
|
||||
|
||||
@@ -23,12 +23,14 @@
|
||||
#![warn(missing_docs)]
|
||||
|
||||
use polkadot_subsystem::{
|
||||
Subsystem, SpawnedSubsystem, SubsystemResult, SubsystemContext,
|
||||
FromOverseer, OverseerSignal,
|
||||
SubsystemError, SubsystemResult,
|
||||
FromOverseer, OverseerSignal, SpawnedSubsystem,
|
||||
SubsystemContext,
|
||||
errors::RuntimeApiError,
|
||||
messages::{
|
||||
RuntimeApiMessage, RuntimeApiRequest as Request,
|
||||
},
|
||||
errors::RuntimeApiError,
|
||||
overseer,
|
||||
};
|
||||
use polkadot_node_subsystem_util::metrics::{self, prometheus};
|
||||
use polkadot_primitives::v1::{Block, BlockId, Hash, ParachainHost};
|
||||
@@ -85,10 +87,11 @@ impl<Client> RuntimeApiSubsystem<Client> {
|
||||
}
|
||||
}
|
||||
|
||||
impl<Client, Context> Subsystem<Context> for RuntimeApiSubsystem<Client> where
|
||||
impl<Client, Context> overseer::Subsystem<Context, SubsystemError> for RuntimeApiSubsystem<Client> where
|
||||
Client: ProvideRuntimeApi<Block> + Send + 'static + Sync,
|
||||
Client::Api: ParachainHost<Block> + BabeApi<Block> + AuthorityDiscoveryApi<Block>,
|
||||
Context: SubsystemContext<Message = RuntimeApiMessage>
|
||||
Context: SubsystemContext<Message = RuntimeApiMessage>,
|
||||
Context: overseer::SubsystemContext<Message = RuntimeApiMessage>,
|
||||
{
|
||||
fn start(self, ctx: Context) -> SpawnedSubsystem {
|
||||
SpawnedSubsystem {
|
||||
@@ -265,12 +268,14 @@ impl<Client> RuntimeApiSubsystem<Client> where
|
||||
}
|
||||
}
|
||||
|
||||
async fn run<Client>(
|
||||
mut ctx: impl SubsystemContext<Message = RuntimeApiMessage>,
|
||||
async fn run<Client, Context>(
|
||||
mut ctx: Context,
|
||||
mut subsystem: RuntimeApiSubsystem<Client>,
|
||||
) -> SubsystemResult<()> where
|
||||
Client: ProvideRuntimeApi<Block> + Send + Sync + 'static,
|
||||
Client::Api: ParachainHost<Block> + BabeApi<Block> + AuthorityDiscoveryApi<Block>,
|
||||
Context: SubsystemContext<Message = RuntimeApiMessage>,
|
||||
Context: overseer::SubsystemContext<Message = RuntimeApiMessage>,
|
||||
{
|
||||
loop {
|
||||
select! {
|
||||
|
||||
Reference in New Issue
Block a user