Collators get incoming parachain messages (#149)

* refactor out a consensus data fetcher from table router

* move statement checking logic into router

* refuse to start authority if collator

* support building the table router asynchronously

* instantiate_consensus does not overwrite old

* update key in new consensus if there was none before

* collator collects ingress from network

* test produced egress roots

* fix adder-collator compilation

* address first grumbles

* integrate new gossip with collator network launch

* address review
This commit is contained in:
Robert Habermeier
2019-03-22 00:48:36 +01:00
committed by GitHub
parent 67275abe30
commit 454ddf8921
16 changed files with 960 additions and 657 deletions
@@ -118,6 +118,7 @@ pub(crate) fn start<C, N, P>(
N: Network + Send + Sync + 'static,
N::TableRouter: Send + 'static,
<<N::TableRouter as TableRouter>::FetchIncoming as IntoFuture>::Future: Send + 'static,
<N::BuildTableRouter as IntoFuture>::Future: Send + 'static,
{
const TIMER_DELAY: Duration = Duration::from_secs(5);
const TIMER_INTERVAL: Duration = Duration::from_secs(30);
+2 -2
View File
@@ -170,7 +170,7 @@ pub fn message_queue_root<A, I: IntoIterator<Item=A>>(messages: I) -> Hash
}
/// Compute the set of egress roots for all given outgoing messages.
pub fn egress_roots(mut outgoing: Vec<OutgoingMessage>) -> Vec<(ParaId, Hash)> {
pub fn egress_roots(outgoing: &mut [OutgoingMessage]) -> Vec<(ParaId, Hash)> {
// stable sort messages by parachain ID.
outgoing.sort_by_key(|msg| ParaId::from(msg.target));
@@ -357,7 +357,7 @@ mod tests {
&[(1.into(), root_1), (2.into(), root_2), (3.into(), root_3)],
).is_ok());
let egress_roots = egress_roots(messages.clone());
let egress_roots = egress_roots(&mut messages.clone()[..]);
assert!(check_extrinsic(
messages.clone(),
+71 -48
View File
@@ -167,10 +167,17 @@ pub trait TableRouter: Clone {
/// A long-lived network which can create parachain statement and BFT message routing processes on demand.
pub trait Network {
/// The error type of asynchronously building the table router.
type Error: std::fmt::Debug;
/// The table router type. This should handle importing of any statements,
/// routing statements to peers, and driving completion of any `StatementProducers`.
type TableRouter: TableRouter;
/// The future used for asynchronously building the table router.
/// This should not fail.
type BuildTableRouter: IntoFuture<Item=Self::TableRouter,Error=Self::Error>;
/// Instantiate a table router using the given shared table.
/// Also pass through any outgoing messages to be broadcast to peers.
fn communication_for(
@@ -178,7 +185,7 @@ pub trait Network {
table: Arc<SharedTable>,
outgoing: Outgoing,
authorities: &[SessionKey],
) -> Self::TableRouter;
) -> Self::BuildTableRouter;
}
/// Information about a specific group.
@@ -284,6 +291,7 @@ impl<C, N, P> ParachainValidation<C, N, P> where
<C::Collation as IntoFuture>::Future: Send + 'static,
N::TableRouter: Send + 'static,
<<N::TableRouter as TableRouter>::FetchIncoming as IntoFuture>::Future: Send + 'static,
<N::BuildTableRouter as IntoFuture>::Future: Send + 'static,
{
/// Get an attestation table for given parent hash.
///
@@ -382,64 +390,77 @@ impl<C, N, P> ParachainValidation<C, N, P> where
&self,
relay_parent: Hash,
validation_para: ParaId,
router: N::TableRouter,
build_router: N::BuildTableRouter
) -> exit_future::Signal {
use extrinsic_store::Data;
let (signal, exit) = exit_future::signal();
let fetch_incoming = router.fetch_incoming(validation_para)
.into_future()
.map_err(|e| format!("{:?}", e));
// fetch incoming messages to our parachain from network and
// then fetch a local collation.
let (collators, client) = (self.collators.clone(), self.client.clone());
let collation_work = fetch_incoming
.map_err(|e| String::clone(&e))
.and_then(move |incoming| {
CollationFetch::new(
validation_para,
relay_parent,
collators,
client,
incoming,
).map_err(|e| format!("{:?}", e))
});
let extrinsic_store = self.extrinsic_store.clone();
let handled_work = collation_work.then(move |result| match result {
Ok((collation, extrinsic)) => {
let res = extrinsic_store.make_available(Data {
relay_parent,
parachain_id: collation.receipt.parachain_index,
candidate_hash: collation.receipt.hash(),
block_data: collation.block_data.clone(),
extrinsic: Some(extrinsic.clone()),
let with_router = move |router: N::TableRouter| {
let fetch_incoming = router.fetch_incoming(validation_para)
.into_future()
.map_err(|e| format!("{:?}", e));
// fetch incoming messages to our parachain from network and
// then fetch a local collation.
let collation_work = fetch_incoming
.map_err(|e| String::clone(&e))
.and_then(move |incoming| {
CollationFetch::new(
validation_para,
relay_parent,
collators,
client,
incoming,
).map_err(|e| format!("{:?}", e))
});
match res {
Ok(()) => {
// TODO: https://github.com/paritytech/polkadot/issues/51
// Erasure-code and provide merkle branches.
router.local_candidate(collation.receipt, collation.block_data, extrinsic)
collation_work.then(move |result| match result {
Ok((collation, extrinsic)) => {
let res = extrinsic_store.make_available(Data {
relay_parent,
parachain_id: collation.receipt.parachain_index,
candidate_hash: collation.receipt.hash(),
block_data: collation.block_data.clone(),
extrinsic: Some(extrinsic.clone()),
});
match res {
Ok(()) => {
// TODO: https://github.com/paritytech/polkadot/issues/51
// Erasure-code and provide merkle branches.
router.local_candidate(
collation.receipt,
collation.block_data,
extrinsic,
)
}
Err(e) => warn!(
target: "validation",
"Failed to make collation data available: {:?}",
e,
),
}
Err(e) => warn!(
target: "validation",
"Failed to make collation data available: {:?}",
e,
),
Ok(())
}
Err(e) => {
warn!(target: "validation", "Failed to collate candidate: {}", e);
Ok(())
}
})
};
Ok(())
}
Err(e) => {
warn!(target: "validation", "Failed to collate candidate: {}", e);
Ok(())
}
});
let cancellable_work = handled_work.select(exit).then(|_| Ok(()));
let cancellable_work = build_router
.into_future()
.map_err(|e| {
warn!(target: "validation" , "Failed to build table router: {:?}", e);
})
.and_then(with_router)
.select(exit)
.then(|_| Ok(()));
// spawn onto thread pool.
self.handle.spawn(cancellable_work);
@@ -472,6 +493,7 @@ impl<C, N, P, TxApi> ProposerFactory<C, N, P, TxApi> where
N: Network + Send + Sync + 'static,
N::TableRouter: Send + 'static,
<<N::TableRouter as TableRouter>::FetchIncoming as IntoFuture>::Future: Send + 'static,
<N::BuildTableRouter as IntoFuture>::Future: Send + 'static,
TxApi: PoolChainApi,
{
/// Create a new proposer factory.
@@ -521,6 +543,7 @@ impl<C, N, P, TxApi> consensus::Environment<Block> for ProposerFactory<C, N, P,
<C::Collation as IntoFuture>::Future: Send + 'static,
N::TableRouter: Send + 'static,
<<N::TableRouter as TableRouter>::FetchIncoming as IntoFuture>::Future: Send + 'static,
<N::BuildTableRouter as IntoFuture>::Future: Send + 'static,
{
type Proposer = Proposer<P, TxApi>;
type Error = Error;