try_runtime_core/commands/
fast_forward.rs1use std::{fmt::Debug, str::FromStr, sync::Arc, time::Duration};
19
20use parity_scale_codec::Encode;
21use sc_cli::Result;
22use sc_executor::sp_wasm_interface::HostFunctions;
23use serde::de::DeserializeOwned;
24use sp_core::H256;
25use sp_runtime::traits::NumberFor;
26use tokio::sync::Mutex;
27
28use crate::{
29 common::{
30 empty_block::{inherents::providers::ProviderVariant, production::mine_block},
31 state::{build_executor, state_machine_call_with_proof, RuntimeChecks, State},
32 },
33 BlockT, SharedParams,
34};
35
36#[derive(Debug, Clone, clap::Parser)]
38pub struct Command {
39 #[arg(long)]
41 pub n_blocks: u64,
42
43 #[arg(long)]
45 pub blocktime: u64,
46
47 #[arg(long, default_value = "all")]
57 pub try_state: frame_try_runtime::TryStateSelect,
58
59 #[arg(long, default_value = "true")]
61 pub run_migrations: bool,
62
63 #[command(subcommand)]
65 pub state: State,
66}
67
68pub async fn run<Block, HostFns>(shared: SharedParams, command: Command) -> Result<()>
69where
70 Block: BlockT<Hash = H256> + DeserializeOwned,
71 Block::Header: DeserializeOwned,
72 <Block::Hash as FromStr>::Err: Debug,
73 NumberFor<Block>: FromStr,
74 <NumberFor<Block> as FromStr>::Err: Debug,
75 HostFns: HostFunctions,
76{
77 let executor = build_executor::<HostFns>(&shared);
78 let runtime_checks = RuntimeChecks {
79 name_matches: !shared.disable_spec_name_check,
80 version_increases: false,
81 try_runtime_feature_enabled: true,
82 };
83 let ext = command
84 .state
85 .to_ext::<Block, HostFns>(&shared, &executor, None, runtime_checks)
86 .await?;
87
88 if command.run_migrations {
89 log::info!("Running migrations...");
90 state_machine_call_with_proof::<Block, HostFns>(
91 &ext,
92 &mut Default::default(),
93 &executor,
94 "TryRuntime_on_runtime_upgrade",
95 command.try_state.encode().as_ref(),
96 Default::default(), None,
98 )?;
99 }
100
101 log::info!("Fast forwarding {} blocks...", command.n_blocks);
102
103 let inner_ext = Arc::new(Mutex::new(ext.inner_ext));
104 let mut parent_header = ext.header.clone();
105 let mut parent_block_building_info = None;
106 let provider_variant = ProviderVariant::Smart(Duration::from_millis(command.blocktime));
107
108 for _ in 1..=command.n_blocks {
109 let (next_block_building_info, next_header, _) = mine_block::<Block, HostFns>(
110 inner_ext.clone(),
111 &executor,
112 parent_block_building_info,
113 parent_header.clone(),
114 provider_variant,
115 command.try_state.clone(),
116 )
117 .await?;
118
119 parent_block_building_info = Some(next_block_building_info);
120 parent_header = next_header;
121 }
122
123 Ok(())
124}