Implement basic upward & downward messages (#118)

* Start by replacing branch names and set `DownwardMessage`

* Add the upward-message crate

* Add Kusama & Polkadot

* More work on getting the upward messages working

* Fix build

* Begin to integrate it into the test Parachain

* Update

* Make everything compile again

* Switch to westend and print parachain account on startup

* Use MultiSignature etc

* Fix validate block

* Some downward messages work

* Update git reference

* More downward messages integration

* Update test runtime for downward messages

* Enable downward message handler and withdraw send tokens

* Add some docs

* Begin to implement simple XCMP

* More work

* Fixes and make parachain id configurable

* Make parachain ID be part of the genesis

* Finishing the XCMP message demo

* Update and fixes tests

* Update branch
This commit is contained in:
Bastian Köcher
2020-06-18 12:10:20 +02:00
committed by GitHub
parent 071d7a11c4
commit c9aaddf667
30 changed files with 1037 additions and 391 deletions
+100 -92
View File
@@ -20,39 +20,39 @@ use cumulus_network::{
DelayedBlockAnnounceValidator, JustifiedBlockAnnounceValidator, WaitToAnnounce,
};
use cumulus_primitives::{
HeadData, inherents::VALIDATION_FUNCTION_PARAMS_IDENTIFIER as VFP_IDENT,
validation_function_params::ValidationFunctionParams,
inherents::{VALIDATION_FUNCTION_PARAMS_IDENTIFIER as VFP_IDENT, DOWNWARD_MESSAGES_IDENTIFIER, DownwardMessagesType},
validation_function_params::ValidationFunctionParams, HeadData,
};
use cumulus_runtime::ParachainBlockData;
use sc_client_api::{BlockchainEvents, Finalizer, StateBackend, UsageProvider};
use sc_service::Configuration;
use sp_api::{ApiExt, ProvideRuntimeApi};
use sp_blockchain::HeaderBackend;
use sp_consensus::{
BlockImport, BlockImportParams, BlockOrigin, Environment, Error as ConsensusError,
ForkChoiceStrategy, Proposal, Proposer, RecordProof,
};
use sp_inherents::{InherentData, InherentDataProviders};
use sp_runtime::traits::{Block as BlockT, Header as HeaderT, HashFor};
use sp_api::{ApiExt, ProvideRuntimeApi};
use sc_client_api::{StateBackend, UsageProvider, Finalizer, BlockchainEvents};
use sc_service::Configuration;
use sp_runtime::traits::{Block as BlockT, HashFor, Header as HeaderT};
use polkadot_collator::{
BuildParachainContext, InvalidHead, Network as CollatorNetwork, ParachainContext,
RuntimeApiCollection,
};
use polkadot_primitives::{
parachain::{self, BlockData, GlobalValidationSchedule, LocalValidationData, Id as ParaId},
Block as PBlock, Hash as PHash,
parachain::{self, BlockData, GlobalValidationSchedule, Id as ParaId, LocalValidationData},
Block as PBlock, DownwardMessage, Hash as PHash,
};
use codec::{Decode, Encode};
use log::{error, trace};
use futures::task::Spawn;
use futures::prelude::*;
use futures::task::Spawn;
use std::{marker::PhantomData, sync::Arc, time::Duration, pin::Pin};
use std::{marker::PhantomData, pin::Pin, sync::Arc, time::Duration};
use parking_lot::Mutex;
@@ -98,29 +98,44 @@ impl<Block: BlockT, PF, BI> Collator<Block, PF, BI> {
inherent_providers: InherentDataProviders,
global_validation: GlobalValidationSchedule,
local_validation: LocalValidationData,
downward_messages: DownwardMessagesType,
) -> Result<InherentData, InvalidHead> {
let mut inherent_data = inherent_providers
.create_inherent_data()
let mut inherent_data = inherent_providers.create_inherent_data().map_err(|e| {
error!(
target: "cumulus-collator",
"Failed to create inherent data: {:?}",
e,
);
InvalidHead
})?;
inherent_data
.put_data(
VFP_IDENT,
&ValidationFunctionParams::from((global_validation, local_validation)),
)
.map_err(|e| {
error!(
target: "cumulus-collator",
"Failed to create inherent data: {:?}",
"Failed to put validation function params into inherent data: {:?}",
e,
);
InvalidHead
})?;
inherent_data.put_data(
VFP_IDENT,
&ValidationFunctionParams::from((global_validation, local_validation))
).map_err(|e| {
error!(
target: "cumulus-collator",
"Failed to inject validation function params into inherents: {:?}",
e,
);
InvalidHead
})?;
inherent_data
.put_data(
DOWNWARD_MESSAGES_IDENTIFIER,
&downward_messages,
)
.map_err(|e| {
error!(
target: "cumulus-collator",
"Failed to put downward messages into inherent data: {:?}",
e,
);
InvalidHead
})?;
Ok(inherent_data)
}
@@ -152,16 +167,15 @@ where
+ Sync
+ 'static,
{
type ProduceCandidate = Pin<Box<
dyn Future<Output=Result<(BlockData, parachain::HeadData), InvalidHead>>
+ Send,
>>;
type ProduceCandidate =
Pin<Box<dyn Future<Output = Result<(BlockData, parachain::HeadData), InvalidHead>> + Send>>;
fn produce_candidate(
&mut self,
relay_chain_parent: PHash,
global_validation: GlobalValidationSchedule,
local_validation: LocalValidationData,
downward_messages: Vec<DownwardMessage>,
) -> Self::ProduceCandidate {
let factory = self.proposer_factory.clone();
let inherent_providers = self.inherent_data_providers.clone();
@@ -177,27 +191,28 @@ where
}
};
let proposer_future = factory
.lock()
.init(&last_head.header);
let proposer_future = factory.lock().init(&last_head.header);
let wait_to_announce = self.wait_to_announce.clone();
Box::pin(async move {
let parent_state_root = *last_head.header.state_root();
let proposer = proposer_future
.await
.map_err(|e| {
error!(
target: "cumulus-collator",
"Could not create proposer: {:?}",
e,
);
InvalidHead
})?;
let proposer = proposer_future.await.map_err(|e| {
error!(
target: "cumulus-collator",
"Could not create proposer: {:?}",
e,
);
InvalidHead
})?;
let inherent_data = Self::inherent_data(inherent_providers, global_validation, local_validation)?;
let inherent_data = Self::inherent_data(
inherent_providers,
global_validation,
local_validation,
downward_messages,
)?;
let Proposal {
block,
@@ -221,14 +236,13 @@ where
InvalidHead
})?;
let proof = proof
.ok_or_else(|| {
error!(
target: "cumulus-collator",
"Proposer did not return the requested proof.",
);
InvalidHead
})?;
let proof = proof.ok_or_else(|| {
error!(
target: "cumulus-collator",
"Proposer did not return the requested proof.",
);
InvalidHead
})?;
let (header, extrinsics) = block.deconstruct();
@@ -262,20 +276,13 @@ where
let header = b.into_header();
let encoded_header = header.encode();
let hash = header.hash();
let head_data = HeadData::<Block> {
header,
};
let head_data = HeadData::<Block> { header };
let candidate = (
block_data,
parachain::HeadData(head_data.encode()),
);
let candidate = (block_data, parachain::HeadData(head_data.encode()));
wait_to_announce.lock().wait_to_announce(
hash,
relay_chain_parent,
encoded_header,
);
wait_to_announce
.lock()
.wait_to_announce(hash, relay_chain_parent, encoded_header);
trace!(target: "cumulus-collator", "Produced candidate: {:?}", candidate);
@@ -296,9 +303,7 @@ pub struct CollatorBuilder<Block: BlockT, PF, BI, Backend, Client> {
_marker: PhantomData<(Block, Backend)>,
}
impl<Block: BlockT, PF, BI, Backend, Client>
CollatorBuilder<Block, PF, BI, Backend, Client>
{
impl<Block: BlockT, PF, BI, Backend, Client> CollatorBuilder<Block, PF, BI, Backend, Client> {
/// Create a new instance of self.
pub fn new(
proposer_factory: PF,
@@ -334,7 +339,9 @@ where
+ Sync
+ 'static,
Backend: sc_client_api::Backend<Block> + 'static,
Client: Finalizer<Block, Backend> + UsageProvider<Block> + HeaderBackend<Block>
Client: Finalizer<Block, Backend>
+ UsageProvider<Block>
+ HeaderBackend<Block>
+ Send
+ Sync
+ 'static,
@@ -348,16 +355,22 @@ where
polkadot_network: impl CollatorNetwork + Clone + 'static,
) -> Result<Self::ParachainContext, ()>
where
PClient: ProvideRuntimeApi<PBlock> + BlockchainEvents<PBlock> + HeaderBackend<PBlock>
+ Send + Sync + 'static,
PClient: ProvideRuntimeApi<PBlock>
+ BlockchainEvents<PBlock>
+ HeaderBackend<PBlock>
+ Send
+ Sync
+ 'static,
PClient::Api: RuntimeApiCollection<Extrinsic>,
<PClient::Api as ApiExt<PBlock>>::StateBackend: StateBackend<HashFor<PBlock>>,
Spawner: Spawn + Clone + Send + Sync + 'static,
Extrinsic: codec::Codec + Send + Sync + 'static,
{
self.delayed_block_announce_validator.set(
Box::new(JustifiedBlockAnnounceValidator::new(polkadot_client.clone(), self.para_id)),
);
self.delayed_block_announce_validator
.set(Box::new(JustifiedBlockAnnounceValidator::new(
polkadot_client.clone(),
self.para_id,
)));
let follow =
match cumulus_consensus::follow_polkadot(self.para_id, self.client, polkadot_client) {
@@ -368,12 +381,7 @@ where
};
spawner
.spawn_obj(
Box::new(
follow.map(|_| ()),
)
.into(),
)
.spawn_obj(Box::new(follow.map(|_| ())).into())
.map_err(|_| error!("Could not spawn parachain server!"))?;
Ok(Collator::new(
@@ -415,12 +423,10 @@ mod tests {
use sp_state_machine::StorageProof;
use substrate_test_client::{NativeExecutor, WasmExecutionMethod::Interpreted};
use test_client::{
DefaultTestClientBuilderExt, TestClientBuilder, TestClientBuilderExt,
};
use test_client::{DefaultTestClientBuilderExt, TestClientBuilder, TestClientBuilderExt};
use test_runtime::{Block, Header};
use futures::{Stream, future};
use futures::{future, Stream};
#[derive(Debug)]
struct Error;
@@ -436,9 +442,9 @@ mod tests {
impl Environment<Block> for DummyFactory {
type Proposer = DummyProposer;
type Error = Error;
type CreateProposer = Pin<Box<
dyn Future<Output = Result<Self::Proposer, Self::Error>> + Send + Unpin + 'static
>>;
type CreateProposer = Pin<
Box<dyn Future<Output = Result<Self::Proposer, Self::Error>> + Send + Unpin + 'static>,
>;
fn init(&mut self, _: &Header) -> Self::CreateProposer {
Box::pin(future::ready(Ok(DummyProposer)))
@@ -479,7 +485,10 @@ mod tests {
struct DummyCollatorNetwork;
impl CollatorNetwork for DummyCollatorNetwork {
fn checked_statements(&self, _: PHash) -> Pin<Box<dyn Stream<Item = SignedStatement> + Send>> {
fn checked_statements(
&self,
_: PHash,
) -> Pin<Box<dyn Stream<Item = SignedStatement> + Send>> {
unimplemented!("Not required in tests")
}
}
@@ -526,13 +535,11 @@ mod tests {
Arc::new(
substrate_test_client::TestClientBuilder::<_, _, _, ()>::default()
.build_with_native_executor::<polkadot_service::polkadot_runtime::RuntimeApi, _>(
Some(
NativeExecutor::<polkadot_service::PolkadotExecutor>::new(
Interpreted,
None,
1,
)
)
Some(NativeExecutor::<polkadot_service::PolkadotExecutor>::new(
Interpreted,
None,
1,
)),
)
.0,
),
@@ -562,6 +569,7 @@ mod tests {
balance: 10,
code_upgrade_allowed: None,
},
Vec::new(),
context,
Arc::new(Sr25519Keyring::Alice.pair().into()),
);