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

Commit

Permalink
follow-chain testing mode for try-runtime (and revamp CLI configs). (
Browse files Browse the repository at this point in the history
…#9788)

* deadlock, need to ask someone to help now

* Finally it seems to be working.. at least for a few blocks

* self-review

* major mega revamp

* some small fixes

* another mega refactor

* add license

* Apply suggestions from code review

* hack around signature verification

* Some fixes

* Update utils/frame/try-runtime/cli/src/lib.rs

Co-authored-by: Zeke Mostov <32168567+emostov@users.noreply.github.com>

* Update utils/frame/try-runtime/cli/src/lib.rs

Co-authored-by: Zeke Mostov <32168567+emostov@users.noreply.github.com>

* Update utils/frame/try-runtime/cli/src/lib.rs

Co-authored-by: Zeke Mostov <32168567+emostov@users.noreply.github.com>

* final tweaks, hopefully.

* a little self-review

* Add the ext root check

Co-authored-by: Zeke Mostov <32168567+emostov@users.noreply.github.com>
  • Loading branch information
kianenigma and emostov authored Sep 21, 2021
1 parent 700c9e2 commit 04bb4e0
Show file tree
Hide file tree
Showing 14 changed files with 1,238 additions and 380 deletions.
4 changes: 4 additions & 0 deletions Cargo.lock

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

13 changes: 10 additions & 3 deletions bin/node/runtime/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1585,9 +1585,16 @@ impl_runtime_apis! {

#[cfg(feature = "try-runtime")]
impl frame_try_runtime::TryRuntime<Block> for Runtime {
fn on_runtime_upgrade() -> Result<(Weight, Weight), sp_runtime::RuntimeString> {
let weight = Executive::try_runtime_upgrade()?;
Ok((weight, RuntimeBlockWeights::get().max_block))
fn on_runtime_upgrade() -> (Weight, Weight) {
// NOTE: intentional unwrap: we don't want to propagate the error backwards, and want to
// have a backtrace here. If any of the pre/post migration checks fail, we shall stop
// right here and right now.
let weight = Executive::try_runtime_upgrade().unwrap();
(weight, RuntimeBlockWeights::get().max_block)
}

fn execute_block_no_check(block: Block) -> Weight {
Executive::execute_block_no_check(block)
}
}

Expand Down
31 changes: 31 additions & 0 deletions frame/executive/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -220,6 +220,37 @@ where
weight
}

/// Execute given block, but don't do any of the [`final_checks`].
///
/// Should only be used for testing.
#[cfg(feature = "try-runtime")]
pub fn execute_block_no_check(block: Block) -> frame_support::weights::Weight {
Self::initialize_block(block.header());
Self::initial_checks(&block);

let (header, extrinsics) = block.deconstruct();

Self::execute_extrinsics_with_book_keeping(extrinsics, *header.number());

// do some of the checks that would normally happen in `final_checks`, but definitely skip
// the state root check.
{
let new_header = <frame_system::Pallet<System>>::finalize();
let items_zip = header.digest().logs().iter().zip(new_header.digest().logs().iter());
for (header_item, computed_item) in items_zip {
header_item.check_equal(&computed_item);
assert!(header_item == computed_item, "Digest item must match that calculated.");
}

assert!(
header.extrinsics_root() == new_header.extrinsics_root(),
"Transaction trie root must be valid.",
);
}

frame_system::Pallet::<System>::block_weight().total()
}

/// Execute all `OnRuntimeUpgrade` of this runtime, including the pre and post migration checks.
///
/// This should only be used for testing.
Expand Down
8 changes: 7 additions & 1 deletion frame/try-runtime/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,12 @@ sp_api::decl_runtime_apis! {
///
/// Returns the consumed weight of the migration in case of a successful one, combined with
/// the total allowed block weight of the runtime.
fn on_runtime_upgrade() -> Result<(Weight, Weight), sp_runtime::RuntimeString>;
fn on_runtime_upgrade() -> (Weight, Weight);

/// Execute the given block, but don't check that its state root matches that of yours.
///
/// This is only sensible where the incoming block is from a different network, yet it has
/// the same block format as the runtime implementing this API.
fn execute_block_no_check(block: Block) -> Weight;
}
}
2 changes: 1 addition & 1 deletion primitives/state-machine/src/testing.rs
Original file line number Diff line number Diff line change
Expand Up @@ -159,7 +159,7 @@ where
///
/// In contrast to [`commit_all`](Self::commit_all) this will not panic if there are open
/// transactions.
fn as_backend(&self) -> InMemoryBackend<H> {
pub fn as_backend(&self) -> InMemoryBackend<H> {
let top: Vec<_> =
self.overlay.changes().map(|(k, v)| (k.clone(), v.value().cloned())).collect();
let mut transaction = vec![(None, top)];
Expand Down
2 changes: 1 addition & 1 deletion utils/frame/remote-externalities/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ targets = ["x86_64-unknown-linux-gnu"]
[dependencies]
jsonrpsee-ws-client = { version = "0.3.0", default-features = false, features = [
"tokio1",
] }
]}
jsonrpsee-proc-macros = "0.3.0"

env_logger = "0.9"
Expand Down
33 changes: 22 additions & 11 deletions utils/frame/remote-externalities/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -112,8 +112,8 @@ pub struct OnlineConfig<B: BlockT> {
pub at: Option<B::Hash>,
/// An optional state snapshot file to WRITE to, not for reading. Not written if set to `None`.
pub state_snapshot: Option<SnapshotConfig>,
/// The modules to scrape. If empty, entire chain state will be scraped.
pub modules: Vec<String>,
/// The pallets to scrape. If empty, entire chain state will be scraped.
pub pallets: Vec<String>,
/// Transport config.
pub transport: Transport,
}
Expand All @@ -134,7 +134,7 @@ impl<B: BlockT> Default for OnlineConfig<B> {
transport: Transport { uri: DEFAULT_TARGET.to_owned(), client: None },
at: None,
state_snapshot: None,
modules: vec![],
pallets: vec![],
}
}
}
Expand Down Expand Up @@ -360,9 +360,9 @@ impl<B: BlockT> Builder<B> {
.clone();
info!(target: LOG_TARGET, "scraping key-pairs from remote @ {:?}", at);

let mut keys_and_values = if config.modules.len() > 0 {
let mut keys_and_values = if config.pallets.len() > 0 {
let mut filtered_kv = vec![];
for f in config.modules.iter() {
for f in config.pallets.iter() {
let hashed_prefix = StorageKey(twox_128(f.as_bytes()).to_vec());
let module_kv = self.rpc_get_pairs_paged(hashed_prefix.clone(), at).await?;
info!(
Expand All @@ -376,7 +376,7 @@ impl<B: BlockT> Builder<B> {
}
filtered_kv
} else {
info!(target: LOG_TARGET, "downloading data for all modules.");
info!(target: LOG_TARGET, "downloading data for all pallets.");
self.rpc_get_pairs_paged(StorageKey(vec![]), at).await?
};

Expand Down Expand Up @@ -482,12 +482,23 @@ impl<B: BlockT> Builder<B> {
self
}

/// overwrite the `at` value, if `mode` is set to [`Mode::Online`].
///
/// noop if `mode` is [`Mode::Offline`]
pub fn overwrite_online_at(mut self, at: B::Hash) -> Self {
if let Mode::Online(mut online) = self.mode.clone() {
online.at = Some(at);
self.mode = Mode::Online(online);
}
self
}

/// Build the test externalities.
pub async fn build(self) -> Result<TestExternalities, &'static str> {
let kv = self.pre_build().await?;
let mut ext = TestExternalities::new_empty();

debug!(target: LOG_TARGET, "injecting a total of {} keys", kv.len());
info!(target: LOG_TARGET, "injecting a total of {} keys", kv.len());
for (k, v) in kv {
let (k, v) = (k.0, v.0);
// Insert the key,value pair into the test trie backend
Expand Down Expand Up @@ -541,7 +552,7 @@ mod remote_tests {
init_logger();
Builder::<Block>::new()
.mode(Mode::Online(OnlineConfig {
modules: vec!["System".to_owned()],
pallets: vec!["System".to_owned()],
..Default::default()
}))
.build()
Expand All @@ -555,7 +566,7 @@ mod remote_tests {
init_logger();
Builder::<Block>::new()
.mode(Mode::Online(OnlineConfig {
modules: vec![
pallets: vec![
"Proxy".to_owned(),
"Multisig".to_owned(),
"PhragmenElection".to_owned(),
Expand Down Expand Up @@ -583,7 +594,7 @@ mod remote_tests {
init_logger();
Builder::<Block>::new()
.mode(Mode::Online(OnlineConfig {
modules: vec!["PhragmenElection".to_owned()],
pallets: vec!["PhragmenElection".to_owned()],
..Default::default()
}))
.build()
Expand All @@ -609,7 +620,7 @@ mod remote_tests {
Builder::<Block>::new()
.mode(Mode::Online(OnlineConfig {
state_snapshot: Some(SnapshotConfig::new("test_snapshot_to_remove.bin")),
modules: vec!["Balances".to_owned()],
pallets: vec!["Balances".to_owned()],
..Default::default()
}))
.build()
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 @@ -25,6 +25,12 @@ sc-chain-spec = { version = "4.0.0-dev", path = "../../../../client/chain-spec"
sp-state-machine = { version = "0.10.0-dev", path = "../../../../primitives/state-machine" }
sp-runtime = { version = "4.0.0-dev", path = "../../../../primitives/runtime" }
sp-core = { version = "4.0.0-dev", path = "../../../../primitives/core" }
sp-io = { version = "4.0.0-dev", path = "../../../../primitives/io" }
sp-keystore = { version = "0.10.0-dev", path = "../../../../primitives/keystore" }
sp-externalities = { version = "0.10.0-dev", path = "../../../../primitives/externalities" }
sp-version = { version = "4.0.0-dev", path = "../../../../primitives/version" }

remote-externalities = { version = "0.10.0-dev", path = "../../remote-externalities" }
jsonrpsee-ws-client = { version = "0.3.0", default-features = false, features = [
"tokio1",
]}
Loading

0 comments on commit 04bb4e0

Please sign in to comment.