Skip to content

Commit

Permalink
try-runtime::fast-forward (paritytech#12896)
Browse files Browse the repository at this point in the history
* try-runtime::fast-forward

* Revert un`pub`ing command's fields

* Handle storage change failure

* Adjust Substrate node

* Feature-gated imports

* doc link

* Feature-gated imports in node-template

* Move trait, blanket implementation and auxiliary functions to a new module

* Distinguish between plain babe+timestamp and substrate enhanced info

* Remove uncles inherents

* Missing argument

* Add doc comment about `blocktime_millis`

* Add licenses
  • Loading branch information
pmikolajczyk41 authored and ark0f committed Feb 27, 2023
1 parent c9e7dba commit 10f2a2a
Show file tree
Hide file tree
Showing 8 changed files with 473 additions and 4 deletions.
6 changes: 6 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

7 changes: 6 additions & 1 deletion bin/node-template/node/src/command.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,9 @@ use sc_cli::{ChainSpec, RuntimeVersion, SubstrateCli};
use sc_service::PartialComponents;
use sp_keyring::Sr25519Keyring;

#[cfg(feature = "try-runtime")]
use try_runtime_cli::block_building_info::timestamp_with_aura_info;

impl SubstrateCli for Cli {
fn impl_name() -> String {
"Substrate Node".into()
Expand Down Expand Up @@ -184,11 +187,13 @@ pub fn run() -> sc_cli::Result<()> {
let task_manager =
sc_service::TaskManager::new(config.tokio_handle.clone(), registry)
.map_err(|e| sc_cli::Error::Service(sc_service::Error::Prometheus(e)))?;
let info_provider = timestamp_with_aura_info(6000);

Ok((
cmd.run::<Block, ExtendedHostFunctions<
sp_io::SubstrateHostFunctions,
<ExecutorDispatch as NativeExecutionDispatch>::ExtendHostFunctions,
>>(),
>, _>(Some(info_provider)),
task_manager,
))
})
Expand Down
10 changes: 9 additions & 1 deletion bin/node/cli/src/command.rs
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,12 @@ use sp_keyring::Sr25519Keyring;

use std::sync::Arc;

#[cfg(feature = "try-runtime")]
use {
kitchensink_runtime::constants::time::SLOT_DURATION,
try_runtime_cli::block_building_info::substrate_info,
};

impl SubstrateCli for Cli {
fn impl_name() -> String {
"Substrate Node".into()
Expand Down Expand Up @@ -236,11 +242,13 @@ pub fn run() -> Result<()> {
sc_service::TaskManager::new(config.tokio_handle.clone(), registry)
.map_err(|e| sc_cli::Error::Service(sc_service::Error::Prometheus(e)))?;

let info_provider = substrate_info(SLOT_DURATION);

Ok((
cmd.run::<Block, ExtendedHostFunctions<
sp_io::SubstrateHostFunctions,
<ExecutorDispatch as NativeExecutionDispatch>::ExtendHostFunctions,
>>(),
>, _>(Some(info_provider)),
task_manager,
))
})
Expand Down
6 changes: 6 additions & 0 deletions utils/frame/try-runtime/cli/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -16,20 +16,26 @@ remote-externalities = { version = "0.10.0-dev", path = "../../remote-externalit
sc-cli = { version = "0.10.0-dev", path = "../../../../client/cli" }
sc-executor = { version = "0.10.0-dev", path = "../../../../client/executor" }
sc-service = { version = "0.10.0-dev", default-features = false, path = "../../../../client/service" }
sp-consensus-aura = { path = "../../../../primitives/consensus/aura" }
sp-consensus-babe = { path = "../../../../primitives/consensus/babe" }
sp-core = { version = "7.0.0", path = "../../../../primitives/core" }
sp-externalities = { version = "0.13.0", path = "../../../../primitives/externalities" }
sp-inherents = { path = "../../../../primitives/inherents" }
sp-io = { version = "7.0.0", path = "../../../../primitives/io" }
sp-keystore = { version = "0.13.0", path = "../../../../primitives/keystore" }
sp-runtime = { version = "7.0.0", path = "../../../../primitives/runtime" }
sp-rpc = { version = "6.0.0", path = "../../../../primitives/rpc" }
sp-state-machine = { version = "0.13.0", path = "../../../../primitives/state-machine" }
sp-timestamp = { path = "../../../../primitives/timestamp" }
sp-transaction-storage-proof = { path = "../../../../primitives/transaction-storage-proof" }
sp-version = { version = "5.0.0", path = "../../../../primitives/version" }
sp-debug-derive = { path = "../../../../primitives/debug-derive" }
sp-api = { path = "../../../../primitives/api" }
sp-weights = { version = "4.0.0", path = "../../../../primitives/weights" }
frame-try-runtime = { optional = true, path = "../../../../frame/try-runtime" }
substrate-rpc-client = { path = "../../rpc/client" }

async-trait = "0.1.57"
clap = { version = "4.0.9", features = ["derive"] }
hex = { version = "0.4.3", default-features = false }
log = "0.4.17"
Expand Down
152 changes: 152 additions & 0 deletions utils/frame/try-runtime/cli/src/block_building_info.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,152 @@
// This file is part of Substrate.

// Copyright (C) 2021-2022 Parity Technologies (UK) Ltd.
// SPDX-License-Identifier: Apache-2.0

// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

use crate::BlockT;
use parity_scale_codec::Encode;
use sc_cli::Result;
use sp_consensus_aura::{Slot, SlotDuration, AURA_ENGINE_ID};
use sp_consensus_babe::{
digests::{PreDigest, SecondaryPlainPreDigest},
BABE_ENGINE_ID,
};
use sp_inherents::{InherentData, InherentDataProvider};
use sp_runtime::{Digest, DigestItem};
use sp_timestamp::TimestampInherentData;

/// Something that can create inherent data providers and pre-runtime digest.
///
/// It is possible for the caller to provide custom arguments to the callee by setting the
/// `ExtraArgs` generic parameter.
///
/// This module already provides some convenience implementation of this trait for closures. So, it
/// should not be required to implement it directly.
#[async_trait::async_trait]
pub trait BlockBuildingInfoProvider<Block: BlockT, ExtraArgs = ()> {
type InherentDataProviders: InherentDataProvider;

async fn get_inherent_providers_and_pre_digest(
&self,
parent_hash: Block::Hash,
extra_args: ExtraArgs,
) -> Result<(Self::InherentDataProviders, Vec<DigestItem>)>;
}

#[async_trait::async_trait]
impl<F, Block, IDP, ExtraArgs, Fut> BlockBuildingInfoProvider<Block, ExtraArgs> for F
where
Block: BlockT,
F: Fn(Block::Hash, ExtraArgs) -> Fut + Sync + Send,
Fut: std::future::Future<Output = Result<(IDP, Vec<DigestItem>)>> + Send + 'static,
IDP: InherentDataProvider + 'static,
ExtraArgs: Send + 'static,
{
type InherentDataProviders = IDP;

async fn get_inherent_providers_and_pre_digest(
&self,
parent: Block::Hash,
extra_args: ExtraArgs,
) -> Result<(Self::InherentDataProviders, Vec<DigestItem>)> {
(*self)(parent, extra_args).await
}
}

/// Provides [`BlockBuildingInfoProvider`] implementation for chains that include timestamp inherent
/// and use Aura for a block production.
///
/// It depends only on the expected block production frequency, i.e. `blocktime_millis`.
pub fn timestamp_with_aura_info<Block: BlockT>(
blocktime_millis: u64,
) -> impl BlockBuildingInfoProvider<Block, Option<(InherentData, Digest)>> {
move |_, maybe_prev_info: Option<(InherentData, Digest)>| async move {
let timestamp_idp = match maybe_prev_info {
Some((inherent_data, _)) => sp_timestamp::InherentDataProvider::new(
inherent_data.timestamp_inherent_data().unwrap().unwrap() + blocktime_millis,
),
None => sp_timestamp::InherentDataProvider::from_system_time(),
};

let slot =
Slot::from_timestamp(*timestamp_idp, SlotDuration::from_millis(blocktime_millis));
let digest = vec![DigestItem::PreRuntime(AURA_ENGINE_ID, slot.encode())];

Ok((timestamp_idp, digest))
}
}

/// Provides [`BlockBuildingInfoProvider`] implementation for chains that include timestamp inherent
/// and use Babe for a block production.
///
/// It depends only on the expected block production frequency, i.e. `blocktime_millis`.
pub fn timestamp_with_babe_info<Block: BlockT>(
blocktime_millis: u64,
) -> impl BlockBuildingInfoProvider<Block, Option<(InherentData, Digest)>> {
move |_, maybe_prev_info: Option<(InherentData, Digest)>| async move {
let timestamp_idp = match maybe_prev_info {
Some((inherent_data, _)) => sp_timestamp::InherentDataProvider::new(
inherent_data.timestamp_inherent_data().unwrap().unwrap() + blocktime_millis,
),
None => sp_timestamp::InherentDataProvider::from_system_time(),
};

let slot =
Slot::from_timestamp(*timestamp_idp, SlotDuration::from_millis(blocktime_millis));
let slot_idp = sp_consensus_babe::inherents::InherentDataProvider::new(slot);

let digest = vec![DigestItem::PreRuntime(
BABE_ENGINE_ID,
PreDigest::SecondaryPlain(SecondaryPlainPreDigest { slot, authority_index: 0 })
.encode(),
)];

Ok(((slot_idp, timestamp_idp), digest))
}
}

/// Provides [`BlockBuildingInfoProvider`] implementation for chains that use:
/// - timestamp inherent,
/// - Babe for a block production (inherent + digest),
/// - uncles inherent,
/// - storage proof inherent
///
/// It depends only on the expected block production frequency, i.e. `blocktime_millis`.
pub fn substrate_info<Block: BlockT>(
blocktime_millis: u64,
) -> impl BlockBuildingInfoProvider<Block, Option<(InherentData, Digest)>> {
move |_, maybe_prev_info: Option<(InherentData, Digest)>| async move {
let timestamp_idp = match maybe_prev_info {
Some((inherent_data, _)) => sp_timestamp::InherentDataProvider::new(
inherent_data.timestamp_inherent_data().unwrap().unwrap() + blocktime_millis,
),
None => sp_timestamp::InherentDataProvider::from_system_time(),
};

let slot =
Slot::from_timestamp(*timestamp_idp, SlotDuration::from_millis(blocktime_millis));
let slot_idp = sp_consensus_babe::inherents::InherentDataProvider::new(slot);

let storage_proof_idp = sp_transaction_storage_proof::InherentDataProvider::new(None);

let digest = vec![DigestItem::PreRuntime(
BABE_ENGINE_ID,
PreDigest::SecondaryPlain(SecondaryPlainPreDigest { slot, authority_index: 0 })
.encode(),
)];

Ok(((slot_idp, timestamp_idp, storage_proof_idp), digest))
}
}
Loading

0 comments on commit 10f2a2a

Please sign in to comment.