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

Commit

Permalink
extract provisioner data fetch
Browse files Browse the repository at this point in the history
This satisfies two requirements:

- only applies the timeout to actually fetching the provisioner data,
  not to constructing the block after
- simplifies the problem of injecting default data if we could not
  get the real provisioner data in time.
  • Loading branch information
coriolinus committed Jul 3, 2020
1 parent b91be19 commit 9bae56e
Show file tree
Hide file tree
Showing 2 changed files with 64 additions and 29 deletions.
91 changes: 63 additions & 28 deletions node/core/proposer/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use futures::prelude::*;
use futures::select;
use polkadot_node_subsystem::{messages::{AllMessages, ProvisionerMessage}, SubsystemError};
use polkadot_node_subsystem::{messages::{AllMessages, ProvisionerInherentData, ProvisionerMessage}, SubsystemError};
use polkadot_overseer::OverseerHandler;
use polkadot_primitives::{
inclusion_inherent,
Expand Down Expand Up @@ -93,7 +93,8 @@ pub struct Proposer<TxPool: TransactionPool<Block = Block>, Backend, Client> {
parent_header_hash: Hash,
}

impl<TxPool, Backend, Client> sp_consensus::Proposer<Block> for Proposer<TxPool, Backend, Client>
// This impl has the same generic bounds as the Proposer impl.
impl<TxPool, Backend, Client> Proposer<TxPool, Backend, Client>
where
TxPool: 'static + TransactionPool<Block = Block>,
Client: 'static
Expand All @@ -109,24 +110,15 @@ where
// Rust bug: https://github.com/rust-lang/rust/issues/24159
sp_api::StateBackendFor<Client, Block>: sp_api::StateBackend<HashFor<Block>> + Send,
{
type Transaction = sc_client_api::TransactionFor<Backend, Block>;
type Proposal = Pin<Box<
dyn Future<Output = Result<Proposal<Block, sp_api::TransactionFor<Client, Block>>, Error>> + Send,
>>;
type Error = Error;

fn propose(
self,
mut inherent_data: InherentData,
inherent_digests: DigestFor<Block>,
max_duration: time::Duration,
record_proof: RecordProof,
) -> Self::Proposal {
/// Get provisioner inherent data
///
/// This function has a constant timeout: `PROPOSE_TIMEOUT`.
fn get_provisioner_data(&self) -> impl Future<Output = Result<ProvisionerInherentData, Error>> {
// clone this (lightweight) data because we're going to move it into the future
let mut overseer = self.overseer.clone();
let parent_header_hash = self.parent_header_hash.clone();

let mut proposal = async move {
let mut provisioner_inherent_data = async move {
let (sender, receiver) = futures::channel::oneshot::channel();

// strictly speaking, we don't _have_ to .await this send_msg before opening the
Expand All @@ -137,17 +129,7 @@ where
ProvisionerMessage::RequestInherentData(parent_header_hash, sender),
)).await?;

let provisioner_inherent_data = receiver.await.map_err(Error::ClosedChannelFromProvisioner)?;

inherent_data.put_data(
inclusion_inherent::INHERENT_IDENTIFIER,
&provisioner_inherent_data,
)?;

self.inner
.propose(inherent_data, inherent_digests, max_duration, record_proof)
.await
.map_err(Into::into)
receiver.await.map_err(Error::ClosedChannelFromProvisioner)
}
.boxed()
.fuse();
Expand All @@ -156,10 +138,63 @@ where

async move {
select! {
proposal_result = proposal => proposal_result,
pid = provisioner_inherent_data => pid,
_ = timeout => Err(Error::Timeout),
}
}
}
}

impl<TxPool, Backend, Client> sp_consensus::Proposer<Block> for Proposer<TxPool, Backend, Client>
where
TxPool: 'static + TransactionPool<Block = Block>,
Client: 'static
+ BlockBuilderProvider<Backend, Block, Client>
+ ProvideRuntimeApi<Block>
+ HeaderBackend<Block>
+ Send
+ Sync,
Client::Api:
ParachainHost<Block> + BlockBuilderApi<Block> + ApiExt<Block, Error = sp_blockchain::Error>,
Backend:
'static + sc_client_api::Backend<Block, State = sp_api::StateBackendFor<Client, Block>>,
// Rust bug: https://github.com/rust-lang/rust/issues/24159
sp_api::StateBackendFor<Client, Block>: sp_api::StateBackend<HashFor<Block>> + Send,
{
type Transaction = sc_client_api::TransactionFor<Backend, Block>;
type Proposal = Pin<Box<
dyn Future<Output = Result<Proposal<Block, sp_api::TransactionFor<Client, Block>>, Error>> + Send,
>>;
type Error = Error;

fn propose(
self,
mut inherent_data: InherentData,
inherent_digests: DigestFor<Block>,
max_duration: time::Duration,
record_proof: RecordProof,
) -> Self::Proposal {
let provisioner_data = self.get_provisioner_data();

async move {
let provisioner_data = match provisioner_data.await {
Ok(pd) => pd,
Err(err) => {
log::warn!("could not get provisioner inherent data; injecting default data: {}", err);
Default::default()

This comment has been minimized.

Copy link
@rphmeier

rphmeier Jul 3, 2020

Contributor

Yes, 👍 this is exactly what I was thinking.

}
};

inherent_data.put_data(
inclusion_inherent::INHERENT_IDENTIFIER,
&provisioner_data,
)?;

self.inner
.propose(inherent_data, inherent_digests, max_duration, record_proof)
.await
.map_err(Into::into)
}
.boxed()
}
}
Expand Down
2 changes: 1 addition & 1 deletion primitives/src/parachain.rs
Original file line number Diff line number Diff line change
Expand Up @@ -724,7 +724,7 @@ impl From<BitVec<bitvec::order::Lsb0, u8>> for AvailabilityBitfield {
pub type SignedAvailabilityBitfield = Signed<AvailabilityBitfield>;

/// A set of signed availability bitfields. Should be sorted by validator index, ascending.
#[derive(Encode, Decode, Clone, PartialEq, Eq, RuntimeDebug)]
#[derive(Encode, Decode, Clone, PartialEq, Eq, RuntimeDebug, Default)]
pub struct SignedAvailabilityBitfields(pub Vec<SignedAvailabilityBitfield>);

impl From<Vec<SignedAvailabilityBitfield>> for SignedAvailabilityBitfields {
Expand Down

0 comments on commit 9bae56e

Please sign in to comment.