diff --git a/Cargo.lock b/Cargo.lock index 60fb76112f..f026a0ec8f 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1140,6 +1140,7 @@ dependencies = [ "sp-inherents", "sp-io", "sp-runtime", + "sp-state-machine", "sp-std", "sp-version", "substrate-test-runtime-client", @@ -1159,6 +1160,7 @@ dependencies = [ "sp-inherents", "sp-runtime", "sp-std", + "sp-trie", ] [[package]] @@ -1232,6 +1234,7 @@ dependencies = [ "sp-inherents", "sp-keyring", "sp-runtime", + "sp-state-machine", "sp-test-primitives", "sp-timestamp", "substrate-test-client", diff --git a/collator/src/lib.rs b/collator/src/lib.rs index ec0e2e7ece..9130c4f730 100644 --- a/collator/src/lib.rs +++ b/collator/src/lib.rs @@ -61,7 +61,7 @@ type TransactionFor = <>::Proposer as Proposer>::Transaction; /// The implementation of the Cumulus `Collator`. -pub struct Collator { +pub struct Collator { para_id: ParaId, proposer_factory: Arc>, _phantom: PhantomData<(Block, PBackend)>, @@ -71,10 +71,11 @@ pub struct Collator { wait_to_announce: Arc>>, backend: Arc, polkadot_client: Arc, + polkadot_backend: Arc, } -impl Clone - for Collator +impl Clone + for Collator { fn clone(&self) -> Self { Self { @@ -87,12 +88,13 @@ impl Clone wait_to_announce: self.wait_to_announce.clone(), backend: self.backend.clone(), polkadot_client: self.polkadot_client.clone(), + polkadot_backend: self.polkadot_backend.clone(), } } } -impl - Collator +impl + Collator where Block: BlockT, PF: Environment + 'static + Send, @@ -110,6 +112,8 @@ where PBackend::State: StateBackend, PApi: RuntimeApiCollection, PClient: polkadot_service::AbstractClient + 'static, + PBackend2: sc_client_api::Backend + 'static, + PBackend2::State: StateBackend, { /// Create a new instance. fn new( @@ -123,6 +127,7 @@ where announce_block: Arc) + Send + Sync>, backend: Arc, polkadot_client: Arc, + polkadot_backend: Arc, ) -> Self { let wait_to_announce = Arc::new(Mutex::new(WaitToAnnounce::new( spawner, @@ -140,6 +145,7 @@ where wait_to_announce, backend, polkadot_client, + polkadot_backend, } } @@ -208,8 +214,17 @@ where }) .ok()?; + let validation_data = { + // TODO: Actual proof is to be created in the upcoming PRs. + let relay_chain_state = sp_state_machine::StorageProof::empty(); + inherents::ValidationDataType { + validation_data: validation_data.clone(), + relay_chain_state, + } + }; + inherent_data - .put_data(VALIDATION_DATA_IDENTIFIER, validation_data) + .put_data(VALIDATION_DATA_IDENTIFIER, &validation_data) .map_err(|e| { error!( target: "cumulus-collator", @@ -507,7 +522,7 @@ where } /// Parameters for [`start_collator`]. -pub struct StartCollatorParams { +pub struct StartCollatorParams { pub proposer_factory: PF, pub inherent_data_providers: InherentDataProviders, pub backend: Arc, @@ -520,6 +535,7 @@ pub struct StartCollatorParams, + pub polkadot_backend: Arc, } pub async fn start_collator< @@ -532,6 +548,7 @@ pub async fn start_collator< Spawner, PClient, PBackend, + PBackend2, PApi, >( StartCollatorParams { @@ -547,7 +564,8 @@ pub async fn start_collator< para_id, key, polkadot_client, - }: StartCollatorParams, + polkadot_backend, + }: StartCollatorParams, ) -> Result<(), String> where PF: Environment + Send + 'static, @@ -570,6 +588,8 @@ where PBackend::State: StateBackend, PApi: RuntimeApiCollection, PClient: polkadot_service::AbstractClient + 'static, + PBackend2: sc_client_api::Backend + 'static, + PBackend2::State: StateBackend, { let follow = match cumulus_consensus::follow_polkadot( para_id, @@ -594,6 +614,7 @@ where announce_block, backend, polkadot_client, + polkadot_backend, ); let config = CollationGenerationConfig { @@ -725,24 +746,27 @@ mod tests { spawner.spawn("overseer", overseer.run().then(|_| async { () }).boxed()); - let (polkadot_client, relay_parent) = { + let (polkadot_client, polkadot_backend, relay_parent) = { // Create a polkadot client with a block imported. use polkadot_test_client::{ ClientBlockImportExt as _, DefaultTestClientBuilderExt as _, InitPolkadotBlockBuilder as _, TestClientBuilderExt as _, }; - let mut client = polkadot_test_client::TestClientBuilder::new().build(); + + let client_builder = polkadot_test_client::TestClientBuilder::new(); + let polkadot_backend = client_builder.backend(); + let mut client = client_builder.build(); let block_builder = client.init_polkadot_block_builder(); let block = block_builder.build().expect("Finalizes the block").block; let hash = block.header().hash(); client .import_as_best(BlockOrigin::Own, block) .expect("Imports the block"); - (client, hash) + (client, polkadot_backend, hash) }; let collator_start = - start_collator::<_, _, _, _, _, _, _, _, polkadot_service::FullBackend, _>( + start_collator::<_, _, _, _, _, _, _, _, polkadot_service::FullBackend, _, _>( StartCollatorParams { proposer_factory: DummyFactory(client.clone()), inherent_data_providers: Default::default(), @@ -756,6 +780,7 @@ mod tests { para_id, key: CollatorPair::generate().0, polkadot_client: Arc::new(polkadot_client), + polkadot_backend, }, ); block_on(collator_start).expect("Should start collator"); diff --git a/parachain-upgrade/Cargo.toml b/parachain-upgrade/Cargo.toml index dd0b34fce4..5f979cbaa2 100644 --- a/parachain-upgrade/Cargo.toml +++ b/parachain-upgrade/Cargo.toml @@ -23,6 +23,7 @@ sp-std = { git = "https://github.com/paritytech/substrate", default-features = f sp-runtime = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "master" } sp-version = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "master" } frame-system = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "master" } +sp-state-machine = { git = "https://github.com/paritytech/substrate", default-features = false , branch = "master" } # Other Dependencies codec = { package = "parity-scale-codec", version = "1.0.0", default-features = false, features = ["derive"]} @@ -45,6 +46,7 @@ std = [ 'sp-runtime/std', 'sp-io/std', 'sp-std/std', + 'sp-state-machine/std', 'frame-system/std', 'cumulus-primitives/std', ] diff --git a/parachain-upgrade/src/lib.rs b/parachain-upgrade/src/lib.rs index 447a912ab0..726b4688b5 100644 --- a/parachain-upgrade/src/lib.rs +++ b/parachain-upgrade/src/lib.rs @@ -30,7 +30,7 @@ //! Users must ensure that they register this pallet as an inherent provider. use cumulus_primitives::{ - inherents::VALIDATION_DATA_IDENTIFIER as INHERENT_IDENTIFIER, + inherents::{ValidationDataType, VALIDATION_DATA_IDENTIFIER as INHERENT_IDENTIFIER}, well_known_keys::{NEW_VALIDATION_CODE, VALIDATION_DATA}, OnValidationData, ValidationData, }; @@ -106,10 +106,15 @@ decl_module! { /// As a side effect, this function upgrades the current validation function /// if the appropriate time has come. #[weight = (0, DispatchClass::Mandatory)] - fn set_validation_data(origin, vfp: ValidationData) { + fn set_validation_data(origin, data: ValidationDataType) { ensure_none(origin)?; assert!(!DidUpdateValidationData::exists(), "ValidationData must be updated only once in a block"); + let ValidationDataType { + validation_data: vfp, + relay_chain_state, + } = data; + // initialization logic: we know that this runs exactly once every block, // which means we can put the initialization logic here to remove the // sequencing problem. @@ -123,6 +128,10 @@ decl_module! { storage::unhashed::put(VALIDATION_DATA, &vfp); DidUpdateValidationData::put(true); + + // TODO: here we should extract the key value pairs out of the storage proof. + drop(relay_chain_state); + ::on_validation_data(vfp); } @@ -219,7 +228,7 @@ impl ProvideInherent for Module { const INHERENT_IDENTIFIER: InherentIdentifier = INHERENT_IDENTIFIER; fn create_inherent(data: &InherentData) -> Option { - let data: ValidationData = data + let data: ValidationDataType = data .get_data(&INHERENT_IDENTIFIER) .ok() .flatten() @@ -489,7 +498,10 @@ mod tests { let inherent_data = { let mut inherent_data = InherentData::default(); inherent_data - .put_data(INHERENT_IDENTIFIER, &vfp) + .put_data(INHERENT_IDENTIFIER, &ValidationDataType { + validation_data: vfp.clone(), + relay_chain_state: sp_state_machine::StorageProof::empty(), + }) .expect("failed to put VFP inherent"); inherent_data }; diff --git a/primitives/Cargo.toml b/primitives/Cargo.toml index 0d26e9bfdf..3303399714 100644 --- a/primitives/Cargo.toml +++ b/primitives/Cargo.toml @@ -11,6 +11,7 @@ sp-std = { git = "https://github.com/paritytech/substrate", default-features = f sp-runtime = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "master" } sc-chain-spec = { git = "https://github.com/paritytech/substrate", optional = true, branch = "master" } sp-core = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "master" } +sp-trie = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "master" } # Polkadot dependencies polkadot-parachain = { git = "https://github.com/paritytech/polkadot", default-features = false, branch = "master" } @@ -35,4 +36,5 @@ std = [ "polkadot-core-primitives/std", "sp-runtime/std", "sp-core/std", + "sp-trie/std", ] diff --git a/primitives/src/lib.rs b/primitives/src/lib.rs index 645e622644..5b21288667 100644 --- a/primitives/src/lib.rs +++ b/primitives/src/lib.rs @@ -57,7 +57,14 @@ pub mod inherents { /// The identifier for the `set_validation_data` inherent. pub const VALIDATION_DATA_IDENTIFIER: InherentIdentifier = *b"valfunp0"; /// The type of the inherent. - pub type ValidationDataType = crate::ValidationData; + #[derive(codec::Encode, codec::Decode, sp_core::RuntimeDebug, Clone, PartialEq)] + pub struct ValidationDataType { + pub validation_data: crate::ValidationData, + /// A storage proof of a predefined set of keys from the relay-chain. + /// + /// The set of keys is TBD + pub relay_chain_state: sp_trie::StorageProof, + } } /// Well known keys for values in the storage. diff --git a/rococo-parachains/src/service.rs b/rococo-parachains/src/service.rs index d2a1aae68d..4b829142e7 100644 --- a/rococo-parachains/src/service.rs +++ b/rococo-parachains/src/service.rs @@ -187,6 +187,8 @@ where ); let spawner = task_manager.spawn_handle(); + let polkadot_backend = polkadot_full_node.backend.clone(); + let params = StartCollatorParams { para_id: id, block_import: client.clone(), @@ -200,6 +202,7 @@ where polkadot_full_node, spawner, backend, + polkadot_backend, }; start_collator(params).await?; diff --git a/service/src/lib.rs b/service/src/lib.rs index dc945576ba..f7bb1ca78a 100644 --- a/service/src/lib.rs +++ b/service/src/lib.rs @@ -23,7 +23,7 @@ use futures::{Future, FutureExt}; use polkadot_overseer::OverseerHandler; use polkadot_primitives::v1::{Block as PBlock, CollatorId, CollatorPair}; use polkadot_service::{AbstractClient, Client as PClient, ClientHandle, RuntimeApiCollection}; -use sc_client_api::{Backend as BackendT, BlockBackend, Finalizer, UsageProvider}; +use sc_client_api::{Backend as BackendT, BlockBackend, Finalizer, UsageProvider, StateBackend}; use sc_service::{error::Result as ServiceResult, Configuration, Role, TaskManager}; use sp_blockchain::HeaderBackend; use sp_consensus::{BlockImport, Environment, Error as ConsensusError, Proposer}; @@ -36,7 +36,7 @@ use std::{marker::PhantomData, sync::Arc}; type PFullNode = polkadot_service::NewFull; /// Parameters given to [`start_collator`]. -pub struct StartCollatorParams<'a, Block: BlockT, PF, BI, BS, Client, Backend, Spawner, PClient> { +pub struct StartCollatorParams<'a, Block: BlockT, PF, BI, BS, Client, Backend, Spawner, PClient, PBackend> { pub proposer_factory: PF, pub inherent_data_providers: InherentDataProviders, pub backend: Arc, @@ -49,6 +49,7 @@ pub struct StartCollatorParams<'a, Block: BlockT, PF, BI, BS, Client, Backend, S pub collator_key: CollatorPair, pub polkadot_full_node: PFullNode, pub task_manager: &'a mut TaskManager, + pub polkadot_backend: Arc, } /// Start a collator node for a parachain. @@ -56,7 +57,7 @@ pub struct StartCollatorParams<'a, Block: BlockT, PF, BI, BS, Client, Backend, S /// A collator is similar to a validator in a normal blockchain. /// It is responsible for producing blocks and sending the blocks to a /// parachain validator for validation and inclusion into the relay chain. -pub async fn start_collator<'a, Block, PF, BI, BS, Client, Backend, Spawner, PClient>( +pub async fn start_collator<'a, Block, PF, BI, BS, Client, Backend, Spawner, PClient, PBackend>( StartCollatorParams { proposer_factory, inherent_data_providers, @@ -70,7 +71,8 @@ pub async fn start_collator<'a, Block, PF, BI, BS, Client, Backend, Spawner, PCl collator_key, polkadot_full_node, task_manager, - }: StartCollatorParams<'a, Block, PF, BI, BS, Client, Backend, Spawner, PClient>, + polkadot_backend, + }: StartCollatorParams<'a, Block, PF, BI, BS, Client, Backend, Spawner, PClient, PBackend>, ) -> sc_service::error::Result<()> where Block: BlockT, @@ -94,6 +96,8 @@ where Backend: BackendT + 'static, Spawner: SpawnNamed + Clone + Send + Sync + 'static, PClient: ClientHandle, + PBackend: BackendT + 'static, + PBackend::State: StateBackend, { polkadot_full_node .client @@ -111,6 +115,7 @@ where collator_key, block_import, block_status, + polkadot_backend, }) .await?; @@ -119,7 +124,7 @@ where Ok(()) } -struct StartCollator { +struct StartCollator { proposer_factory: PF, inherent_data_providers: InherentDataProviders, backend: Arc, @@ -131,10 +136,11 @@ struct StartCollator { spawner: Spawner, para_id: ParaId, collator_key: CollatorPair, + polkadot_backend: Arc, } -impl polkadot_service::ExecuteWithClient - for StartCollator +impl polkadot_service::ExecuteWithClient + for StartCollator where Block: BlockT, PF: Environment + Send + 'static, @@ -156,6 +162,8 @@ where for<'b> &'b Client: BlockImport, Backend: BackendT + 'static, Spawner: SpawnNamed + Clone + Send + Sync + 'static, + PBackend2: sc_client_api::Backend + 'static, + PBackend2::State: sp_api::StateBackend, { type Output = std::pin::Pin>>>; @@ -181,6 +189,7 @@ where para_id: self.para_id, key: self.collator_key, polkadot_client: client, + polkadot_backend: self.polkadot_backend, }) .await .map_err(Into::into) diff --git a/test/client/Cargo.toml b/test/client/Cargo.toml index a89cec1078..bf9b7d74c1 100644 --- a/test/client/Cargo.toml +++ b/test/client/Cargo.toml @@ -17,6 +17,7 @@ sp-test-primitives = { git = "https://github.com/paritytech/substrate", branch = sp-blockchain = { git = "https://github.com/paritytech/substrate", branch = "master" } sp-inherents = { git = "https://github.com/paritytech/substrate", branch = "master" } sp-timestamp = { git = "https://github.com/paritytech/substrate", branch = "master" } +sp-state-machine = { git = "https://github.com/paritytech/substrate", branch = "master" } frame-system = { git = "https://github.com/paritytech/substrate", branch = "master" } pallet-transaction-payment = { git = "https://github.com/paritytech/substrate", branch = "master" } pallet-balances = { git = "https://github.com/paritytech/substrate", branch = "master" } diff --git a/test/client/src/block_builder.rs b/test/client/src/block_builder.rs index 841358aaec..a2ff162afa 100644 --- a/test/client/src/block_builder.rs +++ b/test/client/src/block_builder.rs @@ -15,7 +15,7 @@ // along with Cumulus. If not, see . use crate::Client; -use cumulus_primitives::{inherents::VALIDATION_DATA_IDENTIFIER, ValidationData}; +use cumulus_primitives::{inherents::{VALIDATION_DATA_IDENTIFIER, ValidationDataType}, ValidationData}; use cumulus_test_runtime::GetLastTimestamp; use polkadot_primitives::v1::BlockNumber as PBlockNumber; use sc_block_builder::BlockBuilderApi; @@ -47,7 +47,10 @@ pub fn generate_block_inherents( inherent_data .put_data( VALIDATION_DATA_IDENTIFIER, - &validation_data.unwrap_or_default(), + &ValidationDataType { + validation_data: validation_data.unwrap_or_default(), + relay_chain_state: sp_state_machine::StorageProof::empty(), + }, ) .expect("Put validation function params failed"); diff --git a/test/service/src/lib.rs b/test/service/src/lib.rs index 7a170ce671..6b49f8b0a4 100644 --- a/test/service/src/lib.rs +++ b/test/service/src/lib.rs @@ -223,6 +223,7 @@ where prometheus_registry.as_ref(), ); + let polkadot_backend = polkadot_full_node.backend.clone(); let params = StartCollatorParams { proposer_factory, inherent_data_providers: params.inherent_data_providers, @@ -236,6 +237,7 @@ where para_id, collator_key, polkadot_full_node, + polkadot_backend, }; start_collator(params).await?;