Unverified Commit 07426539 authored by asynchronous rob's avatar asynchronous rob Committed by GitHub
Browse files

rewrite network code to use notifications_protocol APIs from Substrate (#788)

* extract all network code to legacy submodule

* update references to legacy proto

* skeleton of futures-based protocol

* refactor skeleton to use background task

* rename communication_for to build_table_router

* implement internal message types for validation network

* basic ParachainNetwork and TableRouter implementations

* add some module docs

* remove exit-future from validation

* hack: adapt legacy protocol to lack of exit-future

* generalize RegisteredMessageValidator somewhat

* instantiate and teardown table routers

* clean up RouterInner drop logic

* implement most of the statement import loop

* implement statement loop in async/await

* remove unneeded TODO

* most of the collation skeleton

* send session keys and validator roles

* also send role after status

* use config in startup

* point TODO to issue

* fix test compilation
parent 1d21f773
Pipeline #78342 passed with stages
in 20 minutes and 49 seconds
......@@ -3809,8 +3809,11 @@ name = "polkadot-network"
version = "0.7.20"
dependencies = [
"arrayvec 0.4.12 (registry+https://github.com/rust-lang/crates.io-index)",
"bytes 0.5.4 (registry+https://github.com/rust-lang/crates.io-index)",
"derive_more 0.14.1 (registry+https://github.com/rust-lang/crates.io-index)",
"exit-future 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
"futures 0.3.4 (registry+https://github.com/rust-lang/crates.io-index)",
"futures-timer 2.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
"log 0.4.8 (registry+https://github.com/rust-lang/crates.io-index)",
"parity-scale-codec 1.1.2 (registry+https://github.com/rust-lang/crates.io-index)",
"parking_lot 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)",
......
......@@ -65,10 +65,10 @@ use polkadot_cli::{
ProvideRuntimeApi, AbstractService, ParachainHost, IsKusama,
service::{self, Roles, SelectChain}
};
use polkadot_network::validation::{LeafWorkParams, ValidationNetwork};
use polkadot_network::legacy::validation::{LeafWorkParams, ValidationNetwork};
pub use polkadot_cli::{VersionInfo, load_spec, service::Configuration};
pub use polkadot_network::validation::Incoming;
pub use polkadot_network::legacy::validation::Incoming;
pub use polkadot_validation::SignedStatement;
pub use polkadot_primitives::parachain::CollatorId;
pub use sc_network::PeerId;
......@@ -316,7 +316,7 @@ fn run_collator_node<S, P, Extrinsic>(
let is_known = move |block_hash: &Hash| {
use consensus_common::BlockStatus;
use polkadot_network::gossip::Known;
use polkadot_network::legacy::gossip::Known;
match known_oracle.block_status(&BlockId::hash(*block_hash)) {
Err(_) | Ok(BlockStatus::Unknown) | Ok(BlockStatus::Queued) => None,
......@@ -333,7 +333,7 @@ fn run_collator_node<S, P, Extrinsic>(
}
};
let message_validator = polkadot_network::gossip::register_validator(
let message_validator = polkadot_network::legacy::gossip::register_validator(
network.clone(),
(is_known, client.clone()),
&spawner,
......
......@@ -7,7 +7,9 @@ edition = "2018"
[dependencies]
arrayvec = "0.4.12"
bytes = "0.5"
parking_lot = "0.9.0"
derive_more = "0.14.1"
av_store = { package = "polkadot-availability-store", path = "../availability-store" }
polkadot-validation = { path = "../validation" }
polkadot-primitives = { path = "../primitives" }
......@@ -20,6 +22,7 @@ sp-runtime = { git = "https://github.com/paritytech/substrate", branch = "polkad
futures = "0.3.4"
log = "0.4.8"
exit-future = "0.2.0"
futures-timer = "2.0"
sc-client = { git = "https://github.com/paritytech/substrate", branch = "polkadot-master" }
sp-blockchain = { git = "https://github.com/paritytech/substrate", branch = "polkadot-master" }
sp-api = { git = "https://github.com/paritytech/substrate", branch = "polkadot-master" }
......
......@@ -118,6 +118,7 @@ struct ParachainCollators {
}
/// Manages connected collators and role assignments from the perspective of a validator.
#[derive(Default)]
pub struct CollatorPool {
collators: HashMap<CollatorId, (ParaId, PeerId)>,
parachain_collators: HashMap<ParaId, ParachainCollators>,
......
......@@ -38,7 +38,7 @@ use polkadot_primitives::Hash;
use std::collections::{HashMap, HashSet};
use log::warn;
use crate::router::attestation_topic;
use crate::legacy::router::attestation_topic;
use super::{cost, benefit, MAX_CHAIN_HEADS, LeavesVec,
ChainContext, Known, MessageValidationData, GossipStatement
......
......@@ -210,8 +210,8 @@ impl View {
#[cfg(test)]
mod tests {
use super::*;
use crate::tests::TestChainContext;
use crate::gossip::{Known, GossipParachainMessages};
use crate::legacy::tests::TestChainContext;
use crate::legacy::gossip::{Known, GossipParachainMessages};
use polkadot_primitives::parachain::Message as ParachainMessage;
fn hash(x: u8) -> Hash {
......
......@@ -52,6 +52,7 @@
use sp_runtime::{generic::BlockId, traits::{BlakeTwo256, Hash as HashT}};
use sp_blockchain::Error as ClientError;
use sc_network::{config::Roles, Context, PeerId, ReputationChange};
use sc_network::{NetworkService as SubstrateNetworkService, specialization::NetworkSpecialization};
use sc_network_gossip::{
ValidationResult as GossipValidationResult,
ValidatorContext, MessageIntent,
......@@ -73,8 +74,7 @@ use futures::prelude::*;
use parking_lot::RwLock;
use log::warn;
use super::PolkadotNetworkService;
use crate::{GossipMessageStream, NetworkService, PolkadotProtocol, router::attestation_topic};
use crate::legacy::{GossipMessageStream, NetworkService, GossipService, PolkadotProtocol, router::attestation_topic};
use attestation::{View as AttestationView, PeerData as AttestationPeerData};
use message_routing::{View as MessageRoutingView};
......@@ -308,11 +308,11 @@ impl<F, P> ChainContext for (F, P) where
// NOTE: since RegisteredMessageValidator is meant to be a type-safe proof
// that we've actually done the registration, this should be the only way
// to construct it outside of tests.
pub fn register_validator<C: ChainContext + 'static>(
service: Arc<PolkadotNetworkService>,
pub fn register_validator<C: ChainContext + 'static, S: NetworkSpecialization<Block>>(
service: Arc<SubstrateNetworkService<Block, S, Hash>>,
chain: C,
executor: &impl futures::task::Spawn,
) -> RegisteredMessageValidator
) -> RegisteredMessageValidator<S>
{
let s = service.clone();
let report_handle = Box::new(move |peer: &PeerId, cost_benefit: ReputationChange| {
......@@ -366,7 +366,7 @@ impl NewLeafActions {
/// Perform the queued actions, feeding into gossip.
pub fn perform(
self,
gossip: &dyn crate::NetworkService,
gossip: &dyn crate::legacy::GossipService,
) {
for action in self.actions {
match action {
......@@ -382,16 +382,25 @@ impl NewLeafActions {
/// A registered message validator.
///
/// Create this using `register_validator`.
#[derive(Clone)]
pub struct RegisteredMessageValidator {
pub struct RegisteredMessageValidator<S: NetworkSpecialization<Block>> {
inner: Arc<MessageValidator<dyn ChainContext>>,
// Note: this is always `Some` in real code and `None` in tests.
service: Option<Arc<PolkadotNetworkService>>,
service: Option<Arc<SubstrateNetworkService<Block, S, Hash>>>,
// Note: this is always `Some` in real code and `None` in tests.
gossip_engine: Option<sc_network_gossip::GossipEngine<Block>>,
}
impl RegisteredMessageValidator {
impl<S: NetworkSpecialization<Block>> Clone for RegisteredMessageValidator<S> {
fn clone(&self) -> Self {
RegisteredMessageValidator {
inner: self.inner.clone(),
service: self.service.clone(),
gossip_engine: self.gossip_engine.clone(),
}
}
}
impl RegisteredMessageValidator<crate::legacy::PolkadotProtocol> {
#[cfg(test)]
pub(crate) fn new_test<C: ChainContext + 'static>(
chain: C,
......@@ -405,7 +414,9 @@ impl RegisteredMessageValidator {
gossip_engine: None,
}
}
}
impl<S: NetworkSpecialization<Block>> RegisteredMessageValidator<S> {
pub fn register_availability_store(&mut self, availability_store: av_store::Store) {
self.inner.inner.write().availability_store = Some(availability_store);
}
......@@ -469,10 +480,8 @@ impl RegisteredMessageValidator {
NewLeafActions { actions }
}
}
impl NetworkService for RegisteredMessageValidator {
fn gossip_messages_for(&self, topic: Hash) -> GossipMessageStream {
pub(crate) fn gossip_messages_for(&self, topic: Hash) -> GossipMessageStream {
let topic_stream = if let Some(gossip_engine) = self.gossip_engine.as_ref() {
gossip_engine.messages_for(topic)
} else {
......@@ -483,7 +492,7 @@ impl NetworkService for RegisteredMessageValidator {
GossipMessageStream::new(topic_stream.boxed())
}
fn gossip_message(&self, topic: Hash, message: GossipMessage) {
pub(crate) fn gossip_message(&self, topic: Hash, message: GossipMessage) {
if let Some(gossip_engine) = self.gossip_engine.as_ref() {
gossip_engine.gossip_message(
topic,
......@@ -495,14 +504,30 @@ impl NetworkService for RegisteredMessageValidator {
}
}
fn send_message(&self, who: PeerId, message: GossipMessage) {
pub(crate) fn send_message(&self, who: PeerId, message: GossipMessage) {
if let Some(gossip_engine) = self.gossip_engine.as_ref() {
gossip_engine.send_message(vec![who], message.encode());
} else {
log::error!("Called send_message on a test engine");
}
}
}
impl<S: NetworkSpecialization<Block>> GossipService for RegisteredMessageValidator<S> {
fn gossip_messages_for(&self, topic: Hash) -> GossipMessageStream {
RegisteredMessageValidator::gossip_messages_for(self, topic)
}
fn gossip_message(&self, topic: Hash, message: GossipMessage) {
RegisteredMessageValidator::gossip_message(self, topic, message)
}
fn send_message(&self, who: PeerId, message: GossipMessage) {
RegisteredMessageValidator::send_message(self, who, message)
}
}
impl NetworkService for RegisteredMessageValidator<crate::legacy::PolkadotProtocol> {
fn with_spec<F: Send + 'static>(&self, with: F)
where F: FnOnce(&mut PolkadotProtocol, &mut dyn Context<Block>)
{
......@@ -806,7 +831,7 @@ mod tests {
use polkadot_validation::GenericStatement;
use super::message_routing::queue_topic;
use crate::tests::TestChainContext;
use crate::legacy::tests::TestChainContext;
#[derive(PartialEq, Clone, Debug)]
enum ContextEvent {
......
......@@ -20,7 +20,7 @@
//! a validator changes his session key, or when they are generated.
use polkadot_primitives::{Hash, parachain::{ValidatorId}};
use crate::collator_pool::Role;
use crate::legacy::collator_pool::Role;
use std::collections::{HashMap, HashSet};
use std::time::Duration;
use wasm_timer::Instant;
......@@ -39,6 +39,12 @@ pub struct LocalCollations<C> {
local_collations: HashMap<Hash, LocalCollation<C>>,
}
impl<C: Clone> Default for LocalCollations<C> {
fn default() -> Self {
Self::new()
}
}
impl<C: Clone> LocalCollations<C> {
/// Create a new `LocalCollations` tracker.
pub fn new() -> Self {
......
This diff is collapsed.
......@@ -31,7 +31,6 @@ use polkadot_primitives::{Block, Hash};
use polkadot_primitives::parachain::{
OutgoingMessages, CandidateReceipt, ParachainHost, ValidatorIndex, Collation, PoVBlock, ErasureChunk,
};
use crate::gossip::{RegisteredMessageValidator, GossipMessage, GossipStatement, ErasureChunkMessage};
use sp_api::ProvideRuntimeApi;
use futures::prelude::*;
......@@ -44,8 +43,9 @@ use std::io;
use std::sync::Arc;
use std::pin::Pin;
use crate::validation::{LeafWorkDataFetcher, Executor};
use crate::NetworkService;
use crate::legacy::gossip::{RegisteredMessageValidator, GossipMessage, GossipStatement, ErasureChunkMessage};
use crate::legacy::validation::{LeafWorkDataFetcher, Executor};
use crate::legacy::{NetworkService, PolkadotProtocol};
/// Compute the gossip topic for attestations on the given parent hash.
pub(crate) fn attestation_topic(parent_hash: Hash) -> Hash {
......@@ -78,14 +78,16 @@ pub struct Router<P, T> {
attestation_topic: Hash,
fetcher: LeafWorkDataFetcher<P, T>,
deferred_statements: Arc<Mutex<DeferredStatements>>,
message_validator: RegisteredMessageValidator,
message_validator: RegisteredMessageValidator<PolkadotProtocol>,
drop_signal: Arc<exit_future::Signal>,
}
impl<P, T> Router<P, T> {
pub(crate) fn new(
table: Arc<SharedTable>,
fetcher: LeafWorkDataFetcher<P, T>,
message_validator: RegisteredMessageValidator,
message_validator: RegisteredMessageValidator<PolkadotProtocol>,
drop_signal: exit_future::Signal,
) -> Self {
let parent_hash = fetcher.parent_hash();
Router {
......@@ -94,6 +96,7 @@ impl<P, T> Router<P, T> {
attestation_topic: attestation_topic(parent_hash),
deferred_statements: Arc::new(Mutex::new(DeferredStatements::new())),
message_validator,
drop_signal: Arc::new(drop_signal),
}
}
......@@ -111,7 +114,7 @@ impl<P, T> Router<P, T> {
self.fetcher.parent_hash()
}
fn network(&self) -> &RegisteredMessageValidator {
fn network(&self) -> &RegisteredMessageValidator<PolkadotProtocol> {
self.fetcher.network()
}
}
......@@ -124,6 +127,7 @@ impl<P, T: Clone> Clone for Router<P, T> {
attestation_topic: self.attestation_topic,
deferred_statements: self.deferred_statements.clone(),
message_validator: self.message_validator.clone(),
drop_signal: self.drop_signal.clone(),
}
}
}
......@@ -155,7 +159,7 @@ impl<P: ProvideRuntimeApi<Block> + Send + Sync + 'static, T> Router<P, T> where
// import all statements pending on this candidate
let (mut statements, _traces) = if let GenericStatement::Candidate(_) = statement.statement {
self.deferred_statements.lock().get_deferred(&c_hash)
self.deferred_statements.lock().take_deferred(&c_hash)
} else {
(Vec::new(), Vec::new())
};
......@@ -229,6 +233,7 @@ impl<P: ProvideRuntimeApi<Block> + Send, T> TableRouter for Router<P, T> where
T: Clone + Executor + Send + 'static,
{
type Error = io::Error;
type SendLocalCollation = future::Ready<Result<(), Self::Error>>;
type FetchValidationProof = Pin<Box<dyn Future<Output = Result<PoVBlock, io::Error>> + Send>>;
// We have fetched from a collator and here the receipt should have been already formed.
......@@ -238,7 +243,7 @@ impl<P: ProvideRuntimeApi<Block> + Send, T> TableRouter for Router<P, T> where
receipt: CandidateReceipt,
outgoing: OutgoingMessages,
chunks: (ValidatorIndex, &[ErasureChunk])
) {
) -> Self::SendLocalCollation {
// produce a signed statement
let hash = receipt.hash();
let erasure_root = receipt.erasure_root;
......@@ -251,7 +256,7 @@ impl<P: ProvideRuntimeApi<Block> + Send, T> TableRouter for Router<P, T> where
let statement = GossipStatement::new(
self.parent_hash(),
match self.table.import_validated(validated) {
None => return,
None => return future::ready(Ok(())),
Some(s) => s,
},
);
......@@ -273,6 +278,8 @@ impl<P: ProvideRuntimeApi<Block> + Send, T> TableRouter for Router<P, T> where
message.into()
);
}
future::ready(Ok(()))
}
fn fetch_pov_block(&self, candidate: &CandidateReceipt) -> Self::FetchValidationProof {
......@@ -289,26 +296,29 @@ impl<P, T> Drop for Router<P, T> {
// A unique trace for valid statements issued by a validator.
#[derive(Hash, PartialEq, Eq, Clone, Debug)]
enum StatementTrace {
pub(crate) enum StatementTrace {
Valid(ValidatorIndex, Hash),
Invalid(ValidatorIndex, Hash),
}
// helper for deferring statements whose associated candidate is unknown.
struct DeferredStatements {
/// Helper for deferring statements whose associated candidate is unknown.
pub(crate) struct DeferredStatements {
deferred: HashMap<Hash, Vec<SignedStatement>>,
known_traces: HashSet<StatementTrace>,
}
impl DeferredStatements {
fn new() -> Self {
/// Create a new `DeferredStatements`.
pub(crate) fn new() -> Self {
DeferredStatements {
deferred: HashMap::new(),
known_traces: HashSet::new(),
}
}
fn push(&mut self, statement: SignedStatement) {
/// Push a new statement onto the deferred pile. `Candidate` statements
/// cannot be deferred and are ignored.
pub(crate) fn push(&mut self, statement: SignedStatement) {
let (hash, trace) = match statement.statement {
GenericStatement::Candidate(_) => return,
GenericStatement::Valid(hash) => (hash, StatementTrace::Valid(statement.sender.clone(), hash)),
......@@ -320,7 +330,8 @@ impl DeferredStatements {
}
}
fn get_deferred(&mut self, hash: &Hash) -> (Vec<SignedStatement>, Vec<StatementTrace>) {
/// Take all deferred statements referencing the given candidate hash out.
pub(crate) fn take_deferred(&mut self, hash: &Hash) -> (Vec<SignedStatement>, Vec<StatementTrace>) {
match self.deferred.remove(hash) {
None => (Vec::new(), Vec::new()),
Some(deferred) => {
......@@ -361,7 +372,7 @@ mod tests {
// pre-push.
{
let (signed, traces) = deferred.get_deferred(&hash);
let (signed, traces) = deferred.take_deferred(&hash);
assert!(signed.is_empty());
assert!(traces.is_empty());
}
......@@ -371,7 +382,7 @@ mod tests {
// draining: second push should have been ignored.
{
let (signed, traces) = deferred.get_deferred(&hash);
let (signed, traces) = deferred.take_deferred(&hash);
assert_eq!(signed.len(), 1);
assert_eq!(traces.len(), 1);
......@@ -381,7 +392,7 @@ mod tests {
// after draining
{
let (signed, traces) = deferred.get_deferred(&hash);
let (signed, traces) = deferred.take_deferred(&hash);
assert!(signed.is_empty());
assert!(traces.is_empty());
}
......
......@@ -18,7 +18,7 @@
use std::collections::HashMap;
use super::{PolkadotProtocol, Status, Message, FullStatus};
use crate::validation::LeafWorkParams;
use crate::legacy::validation::LeafWorkParams;
use polkadot_validation::GenericStatement;
use polkadot_primitives::{Block, Hash};
......@@ -74,12 +74,12 @@ impl TestContext {
#[derive(Default)]
pub struct TestChainContext {
pub known_map: HashMap<Hash, crate::gossip::Known>,
pub known_map: HashMap<Hash, crate::legacy::gossip::Known>,
pub ingress_roots: HashMap<Hash, Vec<Hash>>,
}
impl crate::gossip::ChainContext for TestChainContext {
fn is_known(&self, block_hash: &Hash) -> Option<crate::gossip::Known> {
impl crate::legacy::gossip::ChainContext for TestChainContext {
fn is_known(&self, block_hash: &Hash) -> Option<crate::legacy::gossip::Known> {
self.known_map.get(block_hash).map(|x| x.clone())
}
......
......@@ -18,12 +18,12 @@
#![allow(unused)]
use crate::gossip::GossipMessage;
use crate::legacy::gossip::GossipMessage;
use sc_network::{Context as NetContext, PeerId};
use sc_network_gossip::TopicNotification;
use sp_core::{NativeOrEncoded, ExecutionContext};
use sp_keyring::Sr25519Keyring;
use crate::{PolkadotProtocol, NetworkService, GossipMessageStream};
use crate::legacy::{PolkadotProtocol, NetworkService, GossipService, GossipMessageStream};
use polkadot_validation::{SharedTable, Network};
use polkadot_primitives::{Block, BlockNumber, Hash, Header, BlockId};
......@@ -117,6 +117,18 @@ struct TestNetwork {
}
impl NetworkService for TestNetwork {
fn with_spec<F: Send + 'static>(&self, with: F)
where F: FnOnce(&mut PolkadotProtocol, &mut dyn NetContext<Block>)
{
let mut context = TestContext::default();
let res = with(&mut *self.proto.lock(), &mut context);
// TODO: send context to worker for message routing.
// https://github.com/paritytech/polkadot/issues/215
res
}
}
impl GossipService for TestNetwork {
fn gossip_messages_for(&self, topic: Hash) -> GossipMessageStream {
let (tx, rx) = mpsc::unbounded();
let _ = self.gossip.send_listener.unbounded_send((topic, tx));
......@@ -131,16 +143,6 @@ impl NetworkService for TestNetwork {
let notification = TopicNotification { message: message.encode(), sender: None };
let _ = self.gossip.send_message.unbounded_send((topic, notification));
}
fn with_spec<F: Send + 'static>(&self, with: F)
where F: FnOnce(&mut PolkadotProtocol, &mut dyn NetContext<Block>)
{
let mut context = TestContext::default();
let res = with(&mut *self.proto.lock(), &mut context);
// TODO: send context to worker for message routing.
// https://github.com/paritytech/polkadot/issues/215
res
}
}
#[derive(Default)]
......@@ -319,7 +321,7 @@ impl ParachainHost<Block> for RuntimeApi {
}
}
type TestValidationNetwork<SP> = crate::validation::ValidationNetwork<TestApi, SP>;
type TestValidationNetwork<SP> = crate::legacy::validation::ValidationNetwork<TestApi, SP>;
struct Built<SP> {
gossip: Pin<Box<dyn Future<Output = ()>>>,
......@@ -327,7 +329,8 @@ struct Built<SP> {
networks: Vec<TestValidationNetwork<SP>>,
}
fn build_network<SP: Spawn + Clone>(n: usize, spawner: SP) -> Built<SP> {
fn build_network<SP: Spawn + Clone>(n: usize, spawner: SP)-> Built<SP> {
use crate::legacy::gossip::RegisteredMessageValidator;
let (gossip_router, gossip_handle) = make_gossip();
let api_handle = Arc::new(Mutex::new(Default::default()));
let runtime_api = Arc::new(TestApi { data: api_handle.clone() });
......@@ -338,7 +341,7 @@ fn build_network<SP: Spawn + Clone>(n: usize, spawner: SP) -> Built<SP> {
gossip: gossip_handle.clone(),
});
let message_val = crate::gossip::RegisteredMessageValidator::new_test(
let message_val = RegisteredMessageValidator::<PolkadotProtocol>::new_test(
TestChainContext::default(),
Box::new(|_, _| {}),
);
......
......@@ -44,10 +44,10 @@ use std::pin::Pin;
use arrayvec::ArrayVec;
use parking_lot::Mutex;
use crate::router::Router;
use crate::gossip::{RegisteredMessageValidator, MessageValidationData};
use crate::legacy::router::Router;
use crate::legacy::gossip::{RegisteredMessageValidator, MessageValidationData};
use super::NetworkService;
use super::{NetworkService, PolkadotProtocol};
pub use polkadot_validation::Incoming;
......@@ -65,13 +65,13 @@ pub struct LeafWorkParams {
pub struct ValidationNetwork<P, T> {
api: Arc<P>,
executor: T,
network: RegisteredMessageValidator,
network: RegisteredMessageValidator<PolkadotProtocol>,
}
impl<P, T> ValidationNetwork<P, T> {
/// Create a new consensus networking object.
pub fn new(
network: RegisteredMessageValidator,
network: RegisteredMessageValidator<PolkadotProtocol>,
api: Arc<P>,
executor: T,
) -> Self {
......@@ -165,7 +165,7 @@ impl<P, T> ValidationNetwork<P, T> {
/// dropped when it is not required anymore. Otherwise, it will stick around in memory
/// infinitely.
pub fn checked_statements(&self, relay_parent: Hash) -> impl Stream<Item=SignedStatement> {
crate::router::checked_statements(&self.network, crate::router::attestation_topic(relay_parent))
crate::legacy::router::checked_statements(&self.network, crate::legacy::router::attestation_topic(relay_parent))
}
}
......@@ -179,12 +179,12 @@ impl<P, T> ParachainNetwork for ValidationNetwork<P, T> where
type TableRouter = Router<P, T>;
type BuildTableRouter = Box<dyn Future<Output=Result<Self::TableRouter, String>> + Send + Unpin>;
fn communication_for(
fn build_table_router(
&self,
table: Arc<SharedTable>,
authorities: &[ValidatorId],
exit: exit_future::Exit,
) -> Self::BuildTableRouter {
let (signal, exit) = exit_future::signal();
let parent_hash = *table.consensus_parent_hash();
let local_session_key = table.session_key();
......@@ -203,6 +203,7 @@ impl<P, T> ParachainNetwork for ValidationNetwork<P, T> where
table,
fetcher,
network,
signal,
);
let table_router_clone = table_router.clone();
......@@ -390,7 +391,7 @@ impl RecentValidatorIds {
InsertedRecentKey::New(old)
}
/// As a slice.
/// As a slice. Most recent is last.
pub(crate) fn as_slice(&self) -> &[ValidatorId] {
&*self.inner
}
......@@ -512,7 +513,7 @@ impl LiveValidationLeaves {
/// Can fetch data for a given validation leaf-work instance.