diff --git a/cumulus/Cargo.lock b/cumulus/Cargo.lock
index 477dcdb91d..eeef7e2ec8 100644
--- a/cumulus/Cargo.lock
+++ b/cumulus/Cargo.lock
@@ -1785,6 +1785,7 @@ version = "0.1.0"
dependencies = [
"async-trait",
"cumulus-primitives-core",
+ "cumulus-test-relay-sproof-builder",
"parity-scale-codec",
"polkadot-client",
"sc-client-api",
diff --git a/cumulus/primitives/parachain-inherent/Cargo.toml b/cumulus/primitives/parachain-inherent/Cargo.toml
index eccb234143..041d7f974f 100644
--- a/cumulus/primitives/parachain-inherent/Cargo.toml
+++ b/cumulus/primitives/parachain-inherent/Cargo.toml
@@ -20,6 +20,7 @@ polkadot-client = { git = "https://github.com/paritytech/polkadot", optional = t
# Cumulus dependencies
cumulus-primitives-core = { path = "../core", default-features = false }
+cumulus-test-relay-sproof-builder = { path = "../../test/relay-sproof-builder", optional = true }
# Other dependencies
codec = { package = "parity-scale-codec", version = "2.0.0", default-features = false, features = [ "derive" ] }
@@ -42,4 +43,5 @@ std = [
"sc-client-api",
"sp-api",
"polkadot-client",
+ "cumulus-test-relay-sproof-builder"
]
diff --git a/cumulus/primitives/parachain-inherent/src/lib.rs b/cumulus/primitives/parachain-inherent/src/lib.rs
index fd678af13e..52f4b0e9b2 100644
--- a/cumulus/primitives/parachain-inherent/src/lib.rs
+++ b/cumulus/primitives/parachain-inherent/src/lib.rs
@@ -38,6 +38,10 @@ use sp_std::{collections::btree_map::BTreeMap, vec::Vec};
mod client_side;
#[cfg(feature = "std")]
pub use client_side::*;
+#[cfg(feature = "std")]
+mod mock;
+#[cfg(feature = "std")]
+pub use mock::MockValidationDataInherentDataProvider;
/// The identifier for the parachain inherent.
pub const INHERENT_IDENTIFIER: InherentIdentifier = *b"sysi1337";
diff --git a/cumulus/primitives/parachain-inherent/src/mock.rs b/cumulus/primitives/parachain-inherent/src/mock.rs
new file mode 100644
index 0000000000..a6be560f30
--- /dev/null
+++ b/cumulus/primitives/parachain-inherent/src/mock.rs
@@ -0,0 +1,80 @@
+// Copyright 2021 Parity Technologies (UK) Ltd.
+// This file is part of Cumulus.
+
+// Cumulus 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 Cumulus. If not, see .
+
+use cumulus_primitives_core::PersistedValidationData;
+use crate::{ParachainInherentData, INHERENT_IDENTIFIER};
+use sp_inherents::{InherentData, InherentDataProvider};
+
+use cumulus_test_relay_sproof_builder::RelayStateSproofBuilder;
+
+/// Inherent data provider that supplies mocked validation data.
+///
+/// This is useful when running a node that is not actually backed by any relay chain.
+/// For example when running a local node, or running integration tests.
+///
+/// We mock a relay chain block number as follows:
+/// relay_block_number = offset + relay_blocks_per_para_block * current_para_block
+/// To simulate a parachain that starts in relay block 1000 and gets a block in every other relay
+/// block, use 1000 and 2
+pub struct MockValidationDataInherentDataProvider {
+ /// The current block number of the local block chain (the parachain)
+ pub current_para_block: u32,
+ /// The relay block in which this parachain appeared to start. This will be the relay block
+ /// number in para block #P1
+ pub relay_offset: u32,
+ /// The number of relay blocks that elapses between each parablock. Probably set this to 1 or 2
+ /// to simulate optimistic or realistic relay chain behavior.
+ pub relay_blocks_per_para_block: u32,
+}
+
+#[async_trait::async_trait]
+impl InherentDataProvider for MockValidationDataInherentDataProvider {
+ fn provide_inherent_data(
+ &self,
+ inherent_data: &mut InherentData,
+ ) -> Result<(), sp_inherents::Error> {
+ // Use the "sproof" (spoof proof) builder to build valid mock state root and proof.
+ let (relay_storage_root, proof) =
+ RelayStateSproofBuilder::default().into_state_root_and_proof();
+
+ // Calculate the mocked relay block based on the current para block
+ let relay_parent_number =
+ self.relay_offset + self.relay_blocks_per_para_block * self.current_para_block;
+
+ let data = ParachainInherentData {
+ validation_data: PersistedValidationData {
+ parent_head: Default::default(),
+ relay_parent_storage_root: relay_storage_root,
+ relay_parent_number,
+ max_pov_size: Default::default(),
+ },
+ downward_messages: Default::default(),
+ horizontal_messages: Default::default(),
+ relay_chain_state: proof,
+ };
+
+ inherent_data.put_data(INHERENT_IDENTIFIER, &data)
+ }
+
+ // Copied from the real implementation
+ async fn try_handle_error(
+ &self,
+ _: &sp_inherents::InherentIdentifier,
+ _: &[u8],
+ ) -> Option> {
+ None
+ }
+}