Companion for Substrate#8526 (#2845)

* Update branch

* Make it compile

* Compile

* gate approval-checking logic (#2470)

* Fix build

* Updates

* Fix merge

* Adds missing crate

* Companion for Substrate#8386

https://github.com/paritytech/substrate/pull/8386

* Fix fix fix

* Fix

* Fix compilation

* Rewrite to `ParachainsInherentDataProvider`

* Make it compile

* Renamings

* Revert stuff

* Remove stale file

* Guide updates

* Update node/core/parachains-inherent/src/lib.rs

Co-authored-by: Andronik Ordian <write@reusable.software>

* Update node/core/parachains-inherent/src/lib.rs

Co-authored-by: Andronik Ordian <write@reusable.software>

* Apply suggestions from code review

* Reset accidental changes

* More

* Remove stale file

* update Substrate

Co-authored-by: Robert Habermeier <rphmeier@gmail.com>
Co-authored-by: Andronik Ordian <write@reusable.software>
Co-authored-by: parity-processbot <>
This commit is contained in:
Bastian Köcher
2021-05-03 17:21:13 +02:00
committed by GitHub
parent 774d612eef
commit 7830bae524
16 changed files with 402 additions and 549 deletions
@@ -0,0 +1,138 @@
// Copyright 2021 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/>.
//! The parachain inherent data provider
//!
//! Parachain backing and approval is an off-chain process, but the parachain needs to progress on chain as well. To
//! make it progress on chain a block producer needs to forward information about the state of a parachain to the
//! runtime. This information is forwarded through an inherent to the runtime. Here we provide the
//! [`ParachainInherentDataProvider`] that requests the relevant data from the provisioner subsystem and creates the
//! the inherent data that the runtime will use to create an inherent.
#![deny(unused_crate_dependencies, unused_results)]
use futures::{select, FutureExt};
use polkadot_node_subsystem::{
messages::{AllMessages, ProvisionerMessage}, SubsystemError,
};
use polkadot_overseer::OverseerHandler;
use polkadot_primitives::v1::{
Block, Hash, InherentData as ParachainsInherentData,
};
use sp_blockchain::HeaderBackend;
use sp_runtime::generic::BlockId;
use std::time;
/// How long to wait for the provisioner, before giving up.
const PROVISIONER_TIMEOUT: time::Duration = core::time::Duration::from_millis(2500);
/// Provides the parachains inherent data.
pub struct ParachainsInherentDataProvider {
inherent_data: ParachainsInherentData,
}
impl ParachainsInherentDataProvider {
/// Create a new instance of the [`ParachainsInherentDataProvider`].
pub async fn create<C: HeaderBackend<Block>>(
client: &C,
mut overseer: OverseerHandler,
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)?;
let (sender, receiver) = futures::channel::oneshot::channel();
overseer.send_msg(AllMessages::Provisioner(
ProvisionerMessage::RequestInherentData(parent, sender),
)).await;
receiver.await.map_err(|_| Error::ClosedChannelAwaitingInherentData)
};
let mut timeout = futures_timer::Delay::new(PROVISIONER_TIMEOUT).fuse();
let parent_header = match client.header(BlockId::Hash(parent)) {
Ok(Some(h)) => h,
Ok(None) => return Err(Error::ParentHeaderNotFound(parent)),
Err(err) => return Err(Error::Blockchain(err)),
};
let res = select! {
pid = pid.fuse() => pid,
_ = timeout => Err(Error::Timeout),
};
let inherent_data = match res {
Ok(pd) => ParachainsInherentData {
bitfields: pd.bitfields,
backed_candidates: pd.backed_candidates,
disputes: pd.disputes,
parent_header,
},
Err(err) => {
tracing::debug!(
?err,
"Could not get provisioner inherent data; injecting default data",
);
ParachainsInherentData {
bitfields: Vec::new(),
backed_candidates: Vec::new(),
disputes: Vec::new(),
parent_header,
}
}
};
Ok(Self { inherent_data })
}
}
#[async_trait::async_trait]
impl sp_inherents::InherentDataProvider for ParachainsInherentDataProvider {
fn provide_inherent_data(&self, inherent_data: &mut sp_inherents::InherentData) -> Result<(), sp_inherents::Error> {
inherent_data.put_data(
polkadot_primitives::v1::PARACHAINS_INHERENT_IDENTIFIER,
&self.inherent_data,
)
}
async fn try_handle_error(
&self,
_: &sp_inherents::InherentIdentifier,
_: &[u8],
) -> Option<Result<(), sp_inherents::Error>> {
// Inherent isn't checked and can not return any error
None
}
}
#[derive(thiserror::Error, Debug)]
pub enum Error {
#[error("Blockchain error")]
Blockchain(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)]
ParentHeaderNotFound(Hash),
#[error("Closed channel from overseer when awaiting activation")]
ClosedChannelAwaitingActivation,
#[error("Closed channel from provisioner when awaiting inherent data")]
ClosedChannelAwaitingInherentData,
#[error("Subsystem failed")]
Subsystem(SubsystemError),
}