diff --git a/polkadot/Cargo.lock b/polkadot/Cargo.lock index 4e8060f576..1e9308eae5 100644 --- a/polkadot/Cargo.lock +++ b/polkadot/Cargo.lock @@ -188,9 +188,9 @@ dependencies = [ [[package]] name = "assert_matches" -version = "1.4.0" +version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "695579f0f2520f3774bb40461e5adb066459d4e0af4d59d20175484fb8e9edf1" +checksum = "9b34d609dfbaf33d6889b2b7106d3ca345eacad44200913df5ba02bfd31d2ba9" [[package]] name = "async-channel" @@ -5526,6 +5526,7 @@ dependencies = [ "polkadot-node-primitives", "polkadot-node-subsystem-test-helpers", "polkadot-primitives", + "polkadot-procmacro-subsystem-dispatch-gen", "polkadot-statement-table", "sc-network", "smallvec 1.6.1", @@ -5686,6 +5687,17 @@ dependencies = [ "sp-version", ] +[[package]] +name = "polkadot-procmacro-subsystem-dispatch-gen" +version = "0.1.0" +dependencies = [ + "assert_matches", + "proc-macro2", + "quote", + "syn", + "trybuild", +] + [[package]] name = "polkadot-rpc" version = "0.8.29" @@ -6402,9 +6414,9 @@ dependencies = [ [[package]] name = "quote" -version = "1.0.7" +version = "1.0.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "aa563d17ecb180e500da1cfd2b028310ac758de548efdd203e18f283af693f37" +checksum = "c3d0b9745dc2debf507c8422de05d7226cc1f0644216dfdfead988f9b1ab32a7" dependencies = [ "proc-macro2", ] @@ -9893,6 +9905,20 @@ dependencies = [ "structopt", ] +[[package]] +name = "trybuild" +version = "1.0.41" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "99471a206425fba51842a9186315f32d91c56eadc21ea4c21f847b59cf778f8b" +dependencies = [ + "glob", + "lazy_static", + "serde", + "serde_json", + "termcolor", + "toml", +] + [[package]] name = "twox-hash" version = "1.5.0" diff --git a/polkadot/Cargo.toml b/polkadot/Cargo.toml index 5e2e6350cc..44f464812a 100644 --- a/polkadot/Cargo.toml +++ b/polkadot/Cargo.toml @@ -65,6 +65,7 @@ members = [ "node/primitives", "node/service", "node/subsystem", + "node/subsystem/dispatch-gen", "node/subsystem-test-helpers", "node/subsystem-util", "node/jaeger", diff --git a/polkadot/cli/src/browser.rs b/polkadot/cli/src/browser.rs index f4645b64b7..9efea40f8b 100644 --- a/polkadot/cli/src/browser.rs +++ b/polkadot/cli/src/browser.rs @@ -14,27 +14,22 @@ // You should have received a copy of the GNU General Public License // along with Substrate. If not, see . +use browser_utils::{browser_configuration, init_logging_and_telemetry, set_console_error_panic_hook, Client}; use log::info; use wasm_bindgen::prelude::*; -use browser_utils::{ - Client, - browser_configuration, init_logging_and_telemetry, set_console_error_panic_hook, -}; /// Starts the client. #[wasm_bindgen] pub async fn start_client(chain_spec: String, log_level: String) -> Result { - start_inner(chain_spec, log_level) - .await - .map_err(|err| JsValue::from_str(&err.to_string())) + start_inner(chain_spec, log_level).await.map_err(|err| JsValue::from_str(&err.to_string())) } async fn start_inner(chain_spec: String, log_directives: String) -> Result> { set_console_error_panic_hook(); let telemetry_worker = init_logging_and_telemetry(&log_directives)?; - let chain_spec = service::PolkadotChainSpec::from_json_bytes(chain_spec.as_bytes().to_vec()) - .map_err(|e| format!("{:?}", e))?; + let chain_spec = + service::PolkadotChainSpec::from_json_bytes(chain_spec.as_bytes().to_vec()).map_err(|e| format!("{:?}", e))?; let telemetry_handle = telemetry_worker.handle(); let config = browser_configuration(chain_spec, Some(telemetry_handle)).await?; diff --git a/polkadot/node/network/bridge/src/lib.rs b/polkadot/node/network/bridge/src/lib.rs index 794721a70b..d63796d734 100644 --- a/polkadot/node/network/bridge/src/lib.rs +++ b/polkadot/node/network/bridge/src/lib.rs @@ -28,10 +28,8 @@ use polkadot_subsystem::{ SubsystemResult, jaeger, }; use polkadot_subsystem::messages::{ - NetworkBridgeMessage, AllMessages, AvailabilityDistributionMessage, - BitfieldDistributionMessage, PoVDistributionMessage, StatementDistributionMessage, - CollatorProtocolMessage, ApprovalDistributionMessage, NetworkBridgeEvent, - AvailabilityRecoveryMessage, + NetworkBridgeMessage, AllMessages, + CollatorProtocolMessage, NetworkBridgeEvent, }; use polkadot_primitives::v1::{Hash, BlockNumber}; use polkadot_node_network_protocol::{ @@ -565,35 +563,7 @@ async fn dispatch_validation_events_to_all( I: IntoIterator>, I::IntoIter: Send, { - let messages_for = |event: NetworkBridgeEvent| { - let av_d = std::iter::once(event.focus().ok().map(|m| AllMessages::AvailabilityDistribution( - AvailabilityDistributionMessage::NetworkBridgeUpdateV1(m) - ))); - - let b = std::iter::once(event.focus().ok().map(|m| AllMessages::BitfieldDistribution( - BitfieldDistributionMessage::NetworkBridgeUpdateV1(m) - ))); - - let p = std::iter::once(event.focus().ok().map(|m| AllMessages::PoVDistribution( - PoVDistributionMessage::NetworkBridgeUpdateV1(m) - ))); - - let s = std::iter::once(event.focus().ok().map(|m| AllMessages::StatementDistribution( - StatementDistributionMessage::NetworkBridgeUpdateV1(m) - ))); - - let ap = std::iter::once(event.focus().ok().map(|m| AllMessages::ApprovalDistribution( - ApprovalDistributionMessage::NetworkBridgeUpdateV1(m) - ))); - - let av_r = std::iter::once(event.focus().ok().map(|m| AllMessages::AvailabilityRecovery( - AvailabilityRecoveryMessage::NetworkBridgeUpdateV1(m) - ))); - - av_d.chain(b).chain(p).chain(s).chain(ap).chain(av_r).filter_map(|x| x) - }; - - ctx.send_messages(events.into_iter().flat_map(messages_for)).await + ctx.send_messages(events.into_iter().flat_map(AllMessages::dispatch_iter)).await } #[tracing::instrument(level = "trace", skip(events, ctx), fields(subsystem = LOG_TARGET))] @@ -635,8 +605,12 @@ mod tests { use polkadot_subsystem::{ActiveLeavesUpdate, FromOverseer, OverseerSignal}; use polkadot_subsystem::messages::{ - StatementDistributionMessage, BitfieldDistributionMessage, + AvailabilityDistributionMessage, + AvailabilityRecoveryMessage, ApprovalDistributionMessage, + BitfieldDistributionMessage, + PoVDistributionMessage, + StatementDistributionMessage }; use polkadot_node_subsystem_test_helpers::{ SingleItemSink, SingleItemStream, TestSubsystemContextHandle, @@ -818,6 +792,15 @@ mod tests { event: NetworkBridgeEvent, virtual_overseer: &mut TestSubsystemContextHandle, ) { + // Ordering must match the enum variant order + // in `AllMessages`. + assert_matches!( + virtual_overseer.recv().await, + AllMessages::StatementDistribution( + StatementDistributionMessage::NetworkBridgeUpdateV1(e) + ) if e == event.focus().expect("could not focus message") + ); + assert_matches!( virtual_overseer.recv().await, AllMessages::AvailabilityDistribution( @@ -825,6 +808,13 @@ mod tests { ) if e == event.focus().expect("could not focus message") ); + assert_matches!( + virtual_overseer.recv().await, + AllMessages::AvailabilityRecovery( + AvailabilityRecoveryMessage::NetworkBridgeUpdateV1(e) + ) if e == event.focus().expect("could not focus message") + ); + assert_matches!( virtual_overseer.recv().await, AllMessages::BitfieldDistribution( @@ -839,26 +829,12 @@ mod tests { ) if e == event.focus().expect("could not focus message") ); - assert_matches!( - virtual_overseer.recv().await, - AllMessages::StatementDistribution( - StatementDistributionMessage::NetworkBridgeUpdateV1(e) - ) if e == event.focus().expect("could not focus message") - ); - assert_matches!( virtual_overseer.recv().await, AllMessages::ApprovalDistribution( ApprovalDistributionMessage::NetworkBridgeUpdateV1(e) ) if e == event.focus().expect("could not focus message") ); - - assert_matches!( - virtual_overseer.recv().await, - AllMessages::AvailabilityRecovery( - AvailabilityRecoveryMessage::NetworkBridgeUpdateV1(e) - ) if e == event.focus().expect("could not focus message") - ); } async fn assert_sends_collation_event_to_all( @@ -1546,4 +1522,38 @@ mod tests { } }); } + + #[test] + fn spread_event_to_subsystems_is_up_to_date() { + // Number of subsystems expected to be interested in a network event, + // and hence the network event broadcasted to. + const EXPECTED_COUNT: usize = 6; + + let mut cnt = 0_usize; + for msg in AllMessages::dispatch_iter(NetworkBridgeEvent::PeerDisconnected(PeerId::random())) { + match msg { + AllMessages::CandidateValidation(_) => unreachable!("Not interested in network events"), + AllMessages::CandidateBacking(_) => unreachable!("Not interested in network events"), + AllMessages::CandidateSelection(_) => unreachable!("Not interested in network events"), + AllMessages::ChainApi(_) => unreachable!("Not interested in network events"), + AllMessages::CollatorProtocol(_) => unreachable!("Not interested in network events"), + AllMessages::StatementDistribution(_) => { cnt += 1; } + AllMessages::AvailabilityDistribution(_) => { cnt += 1; } + AllMessages::AvailabilityRecovery(_) => { cnt += 1; } + AllMessages::BitfieldDistribution(_) => { cnt += 1; } + AllMessages::BitfieldSigning(_) => unreachable!("Not interested in network events"), + AllMessages::Provisioner(_) => unreachable!("Not interested in network events"), + AllMessages::PoVDistribution(_) => { cnt += 1; } + AllMessages::RuntimeApi(_) => unreachable!("Not interested in network events"), + AllMessages::AvailabilityStore(_) => unreachable!("Not interested in network events"), + AllMessages::NetworkBridge(_) => unreachable!("Not interested in network events"), + AllMessages::CollationGeneration(_) => unreachable!("Not interested in network events"), + AllMessages::ApprovalVoting(_) => unreachable!("Not interested in network events"), + AllMessages::ApprovalDistribution(_) => { cnt += 1; } + // Add variants here as needed, `{ cnt += 1; }` for those that need to be + // notified, `unreachable!()` for those that should not. + } + } + assert_eq!(cnt, EXPECTED_COUNT); + } } diff --git a/polkadot/node/subsystem/Cargo.toml b/polkadot/node/subsystem/Cargo.toml index 3fa2061f04..9dd4e9b80e 100644 --- a/polkadot/node/subsystem/Cargo.toml +++ b/polkadot/node/subsystem/Cargo.toml @@ -23,6 +23,7 @@ polkadot-node-network-protocol = { path = "../network/protocol" } polkadot-primitives = { path = "../../primitives" } polkadot-statement-table = { path = "../../statement-table" } polkadot-node-jaeger = { path = "../jaeger" } +polkadot-procmacro-subsystem-dispatch-gen = { path = "dispatch-gen" } sc-network = { git = "https://github.com/paritytech/substrate", branch = "master" } smallvec = "1.6.1" sp-core = { git = "https://github.com/paritytech/substrate", branch = "master" } diff --git a/polkadot/node/subsystem/dispatch-gen/Cargo.toml b/polkadot/node/subsystem/dispatch-gen/Cargo.toml new file mode 100644 index 0000000000..09de1362c9 --- /dev/null +++ b/polkadot/node/subsystem/dispatch-gen/Cargo.toml @@ -0,0 +1,18 @@ +[package] +name = "polkadot-procmacro-subsystem-dispatch-gen" +version = "0.1.0" +authors = ["Parity Technologies "] +edition = "2018" +description = "Small proc macro to create the distribution code for network events" + +[lib] +proc-macro = true + +[dependencies] +syn = { version = "1.0.60", features = ["full"] } +quote = "1.0.9" +proc-macro2 = "1.0.24" +assert_matches = "1.5.0" + +[dev-dependencies] +trybuild = "1.0.41" diff --git a/polkadot/node/subsystem/dispatch-gen/src/lib.rs b/polkadot/node/subsystem/dispatch-gen/src/lib.rs new file mode 100644 index 0000000000..737712639c --- /dev/null +++ b/polkadot/node/subsystem/dispatch-gen/src/lib.rs @@ -0,0 +1,208 @@ +// Copyright 2021 Parity Technologies (UK) Ltd. +// This file is part of Polkadot. + +// Polkadot 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 Polkadot. If not, see . + +use proc_macro2::TokenStream; +use quote::{quote, ToTokens}; +use std::fmt; +use syn::{parse2, Error, Fields, FieldsNamed, FieldsUnnamed, Ident, ItemEnum, Path, Result, Type, Variant}; + +#[proc_macro_attribute] +pub fn subsystem_dispatch_gen(attr: proc_macro::TokenStream, item: proc_macro::TokenStream) -> proc_macro::TokenStream { + let attr: TokenStream = attr.into(); + let item: TokenStream = item.into(); + let mut backup = item.clone(); + impl_subsystem_dispatch_gen(attr.into(), item).unwrap_or_else(|err| { + backup.extend(err.to_compile_error()); + backup + }).into() +} + +/// An enum variant without base type. +#[derive(Clone)] +struct EnumVariantDispatchWithTy { + // enum ty name + ty: Ident, + // variant + variant: EnumVariantDispatch, +} + +impl fmt::Debug for EnumVariantDispatchWithTy { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + write!(f, "{}::{:?}", self.ty, self.variant) + } +} + +impl ToTokens for EnumVariantDispatchWithTy { + fn to_tokens(&self, tokens: &mut proc_macro2::TokenStream) { + if let Some(inner) = &self.variant.inner { + let enum_name = &self.ty; + let variant_name = &self.variant.name; + + let quoted = quote! { + #enum_name::#variant_name(#inner::from(event)) + }; + quoted.to_tokens(tokens); + } + } +} + +/// An enum variant without the base type, contains the relevant inner type. +#[derive(Clone)] +struct EnumVariantDispatch { + /// variant name + name: Ident, + /// The inner type for which a `From::from` impl is anticipated from the input type. + /// No code will be generated for this enum variant if `inner` is `None`. + inner: Option, +} + +impl fmt::Debug for EnumVariantDispatch { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + write!(f, "{}(..)", self.name) + } +} + +fn prepare_enum_variant(variant: &mut Variant) -> Result { + let skip = variant.attrs.iter().find(|attr| attr.path.is_ident("skip")).is_some(); + variant.attrs = variant.attrs.iter().filter(|attr| !attr.path.is_ident("skip")).cloned().collect::>(); + + let variant = variant.clone(); + let span = variant.ident.span(); + let inner = match variant.fields.clone() { + // look for one called inner + Fields::Named(FieldsNamed { brace_token: _, named }) if !skip => named + .iter() + .find_map( + |field| { + if let Some(ident) = &field.ident { + if ident == "inner" { + return Some(Some(field.ty.clone())) + } + } + None + }, + ) + .ok_or_else(|| { + Error::new(span, "To dispatch with struct enum variant, one element must named `inner`") + })?, + + // technically, if it has no inner types we cound not require the #[skip] annotation, but better make it consistent + Fields::Unnamed(FieldsUnnamed { paren_token: _, unnamed }) if !skip => unnamed + .first() + .map(|field| Some(field.ty.clone())) + .ok_or_else(|| Error::new(span, "Must be annotated with skip, even if no inner types exist."))?, + _ if skip => None, + Fields::Unit => { + return Err(Error::new( + span, + "Must be annotated with #[skip].", + )) + } + Fields::Unnamed(_) => { + return Err(Error::new( + span, + "Must be annotated with #[skip] or have in `inner` element which impls `From<_>`.", + )) + } + Fields::Named(_) => { + return Err(Error::new( + span, + "Must be annotated with #[skip] or the first wrapped type must impl `From<_>`.", + )) + } + }; + + Ok(EnumVariantDispatch { name: variant.ident, inner }) +} + +fn impl_subsystem_dispatch_gen(attr: TokenStream, item: TokenStream) -> Result { + let event_ty = parse2::(attr)?; + + let mut ie = parse2::(item)?; + + let message_enum = ie.ident.clone(); + let variants = ie.variants.iter_mut().try_fold(Vec::::new(), |mut acc, variant| { + let variant = prepare_enum_variant(variant)?; + if variant.inner.is_some() { + acc.push(EnumVariantDispatchWithTy { ty: message_enum.clone(), variant }) + } + Ok::<_, syn::Error>(acc) + })?; + + let mut orig = ie.to_token_stream(); + + let msg = "Generated by #[subsystem_dispatch_gen] proc-macro."; + + orig.extend(quote! { + impl #message_enum { + #[doc = #msg] + pub fn dispatch_iter(event: #event_ty) -> impl Iterator + Send { + let mut iter = None.into_iter(); + + #( + let mut iter = iter.chain(std::iter::once(event.focus().ok().map(|event| { + #variants + }))); + )* + iter.filter_map(|x| x) + } + } + }); + Ok(orig) +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn basic() { + let attr = quote! { + NetEvent + }; + + let item = quote! { + /// Documentation. + #[derive(Clone)] + enum AllMessages { + + Sub1(Inner1), + + #[skip] + /// D3 + Sub3, + + /// D4 + #[skip] + Sub4(Inner2), + + /// D2 + Sub2(Inner2), + } + }; + + let output = impl_subsystem_dispatch_gen(attr, item).expect("Simple example always works. qed"); + println!("//generated:"); + println!("{}", output); + } + + #[test] + fn ui() { + let t = trybuild::TestCases::new(); + t.compile_fail("tests/ui/err-*.rs"); + t.pass("tests/ui/ok-*.rs"); + } +} diff --git a/polkadot/node/subsystem/dispatch-gen/tests/ui/err-01-missing-skip.rs b/polkadot/node/subsystem/dispatch-gen/tests/ui/err-01-missing-skip.rs new file mode 100644 index 0000000000..7248a7181e --- /dev/null +++ b/polkadot/node/subsystem/dispatch-gen/tests/ui/err-01-missing-skip.rs @@ -0,0 +1,37 @@ +#![allow(dead_code)] + +use polkadot_procmacro_subsystem_dispatch_gen::subsystem_dispatch_gen; + +/// The event type in question. +#[derive(Clone, Copy)] +enum Event { + Smth, + Else, +} + +impl Event { + fn focus(&self) -> std::result::Result { + unimplemented!("foo") + } +} + +/// This should have a `From` impl but does not. +#[derive(Clone)] +enum Inner { + Foo, + Bar(Event), +} + +#[subsystem_dispatch_gen(Event)] +#[derive(Clone)] +enum AllMessages { + /// Foo + Vvvvvv(Inner), + + /// Missing a `#[skip]` annotation + Uuuuu, +} + +fn main() { + let _x = AllMessages::dispatch_iter(Event::Else); +} diff --git a/polkadot/node/subsystem/dispatch-gen/tests/ui/err-01-missing-skip.stderr b/polkadot/node/subsystem/dispatch-gen/tests/ui/err-01-missing-skip.stderr new file mode 100644 index 0000000000..855521d2c4 --- /dev/null +++ b/polkadot/node/subsystem/dispatch-gen/tests/ui/err-01-missing-skip.stderr @@ -0,0 +1,14 @@ +error: Must be annotated with #[skip]. + --> $DIR/err-01-missing-skip.rs:32:5 + | +32 | Uuuuu, + | ^^^^^ + +error[E0599]: no variant or associated item named `dispatch_iter` found for enum `AllMessages` in the current scope + --> $DIR/err-01-missing-skip.rs:36:27 + | +27 | enum AllMessages { + | ---------------- variant or associated item `dispatch_iter` not found here +... +36 | let _x = AllMessages::dispatch_iter(Event::Else); + | ^^^^^^^^^^^^^ variant or associated item not found in `AllMessages` diff --git a/polkadot/node/subsystem/dispatch-gen/tests/ui/err-02-missing-from.rs b/polkadot/node/subsystem/dispatch-gen/tests/ui/err-02-missing-from.rs new file mode 100644 index 0000000000..a7abef2c87 --- /dev/null +++ b/polkadot/node/subsystem/dispatch-gen/tests/ui/err-02-missing-from.rs @@ -0,0 +1,41 @@ +#![allow(dead_code)] + +use polkadot_procmacro_subsystem_dispatch_gen::subsystem_dispatch_gen; + +/// The event type in question. +#[derive(Clone, Copy, Debug)] +enum Event { + Smth, + Else, +} + +impl Event { + fn focus(&self) -> std::result::Result { + Ok(Intermediate(self.clone())) + } +} + +#[derive(Debug, Clone)] +struct Intermediate(Event); + + +/// This should have a `From` impl but does not. +#[derive(Debug, Clone)] +enum Inner { + Foo, + Bar(Intermediate), +} + +#[subsystem_dispatch_gen(Event)] +#[derive(Clone)] +enum AllMessages { + /// Foo + Vvvvvv(Inner), + + #[skip] + Uuuuu, +} + +fn main() { + let _x = AllMessages::dispatch_iter(Event::Else); +} diff --git a/polkadot/node/subsystem/dispatch-gen/tests/ui/err-02-missing-from.stderr b/polkadot/node/subsystem/dispatch-gen/tests/ui/err-02-missing-from.stderr new file mode 100644 index 0000000000..bf82201a7e --- /dev/null +++ b/polkadot/node/subsystem/dispatch-gen/tests/ui/err-02-missing-from.stderr @@ -0,0 +1,10 @@ +error[E0308]: mismatched types + --> $DIR/err-02-missing-from.rs:29:1 + | +29 | #[subsystem_dispatch_gen(Event)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | | + | expected enum `Inner`, found struct `Intermediate` + | help: try using a variant of the expected enum: `Inner::Bar(#[subsystem_dispatch_gen(Event)])` + | + = note: this error originates in an attribute macro (in Nightly builds, run with -Z macro-backtrace for more info) diff --git a/polkadot/node/subsystem/dispatch-gen/tests/ui/ok-01-with-intermediate.rs b/polkadot/node/subsystem/dispatch-gen/tests/ui/ok-01-with-intermediate.rs new file mode 100644 index 0000000000..b160bf9ce1 --- /dev/null +++ b/polkadot/node/subsystem/dispatch-gen/tests/ui/ok-01-with-intermediate.rs @@ -0,0 +1,48 @@ +#![allow(dead_code)] + +use polkadot_procmacro_subsystem_dispatch_gen::subsystem_dispatch_gen; + +/// The event type in question. +#[derive(Clone, Copy, Debug)] +enum Event { + Smth, + Else, +} + +impl Event { + fn focus(&self) -> std::result::Result { + Ok(Intermediate(self.clone())) + } +} + + +#[derive(Debug, Clone)] +struct Intermediate(Event); + + +/// This should have a `From` impl but does not. +#[derive(Clone, Debug)] +enum Inner { + Foo, + Bar(Intermediate), +} + +impl From for Inner { + fn from(src: Intermediate) -> Self { + Inner::Bar(src) + } +} + +#[subsystem_dispatch_gen(Event)] +#[derive(Clone)] +enum AllMessages { + /// Foo + Vvvvvv(Inner), + + #[skip] + Uuuuu, +} + +fn main() { + let _x = AllMessages::dispatch_iter(Event::Else); +} diff --git a/polkadot/node/subsystem/src/lib.rs b/polkadot/node/subsystem/src/lib.rs index a48eaee028..825614e3b1 100644 --- a/polkadot/node/subsystem/src/lib.rs +++ b/polkadot/node/subsystem/src/lib.rs @@ -32,14 +32,14 @@ use polkadot_primitives::v1::{Hash, BlockNumber}; use async_trait::async_trait; use smallvec::SmallVec; -use crate::messages::AllMessages; - pub mod errors; pub mod messages; pub use polkadot_node_jaeger as jaeger; pub use jaeger::*; +use self::messages::AllMessages; + /// How many slots are stack-reserved for active leaves updates /// /// If there are fewer than this number of slots, then we've wasted some stack space. diff --git a/polkadot/node/subsystem/src/messages.rs b/polkadot/node/subsystem/src/messages.rs index 857b1e90ae..4415da3257 100644 --- a/polkadot/node/subsystem/src/messages.rs +++ b/polkadot/node/subsystem/src/messages.rs @@ -44,6 +44,7 @@ use polkadot_primitives::v1::{ CandidateIndex, GroupIndex, }; use polkadot_statement_table::v1::Misbehavior; +use polkadot_procmacro_subsystem_dispatch_gen::subsystem_dispatch_gen; use std::{sync::Arc, collections::btree_map::BTreeMap}; @@ -171,7 +172,7 @@ impl CandidateValidationMessage { /// Messages received by the Collator Protocol subsystem. -#[derive(Debug)] +#[derive(Debug, derive_more::From)] pub enum CollatorProtocolMessage { /// Signal to the collator protocol that it should connect to validators with the expectation /// of collating on the given para. This is only expected to be called once, early on, if at all, @@ -195,6 +196,7 @@ pub enum CollatorProtocolMessage { /// Notify a collator that its collation was seconded. NotifyCollationSeconded(CollatorId, SignedFullStatement), /// Get a network bridge update. + #[from] NetworkBridgeUpdateV1(NetworkBridgeEvent), } @@ -270,13 +272,15 @@ impl NetworkBridgeMessage { #[derive(Debug, derive_more::From)] pub enum AvailabilityDistributionMessage { /// Event from the network bridge. + #[from] NetworkBridgeUpdateV1(NetworkBridgeEvent), /// Incoming request for an availability chunk. + #[from] AvailabilityFetchingRequest(IncomingRequest) } /// Availability Recovery Message. -#[derive(Debug)] +#[derive(Debug, derive_more::From)] pub enum AvailabilityRecoveryMessage { /// Recover available data from validators on the network. RecoverAvailableData( @@ -286,6 +290,7 @@ pub enum AvailabilityRecoveryMessage { oneshot::Sender>, ), /// Event from the network bridge. + #[from] NetworkBridgeUpdateV1(NetworkBridgeEvent), } @@ -300,12 +305,13 @@ impl AvailabilityDistributionMessage { } /// Bitfield distribution message. -#[derive(Debug)] +#[derive(Debug, derive_more::From)] pub enum BitfieldDistributionMessage { /// Distribute a bitfield via gossip to other validators. DistributeBitfield(Hash, SignedAvailabilityBitfield), /// Event from the network bridge. + #[from] NetworkBridgeUpdateV1(NetworkBridgeEvent), } @@ -509,12 +515,13 @@ impl RuntimeApiMessage { } /// Statement distribution message. -#[derive(Debug)] +#[derive(Debug, derive_more::From)] pub enum StatementDistributionMessage { /// We have originated a signed statement in the context of /// given relay-parent hash and it should be distributed to other validators. Share(Hash, SignedFullStatement), /// Event from the network bridge. + #[from] NetworkBridgeUpdateV1(NetworkBridgeEvent), } @@ -572,7 +579,7 @@ impl BoundToRelayParent for ProvisionerMessage { } /// Message to the PoV Distribution subsystem. -#[derive(Debug)] +#[derive(Debug, derive_more::From)] pub enum PoVDistributionMessage { /// Fetch a PoV from the network. /// @@ -583,6 +590,7 @@ pub enum PoVDistributionMessage { /// The PoV should correctly hash to the PoV hash mentioned in the CandidateDescriptor DistributePoV(Hash, CandidateDescriptor, Arc), /// An update from the network bridge. + #[from] NetworkBridgeUpdateV1(NetworkBridgeEvent), } @@ -662,7 +670,7 @@ pub enum ApprovalVotingMessage { } /// Message to the Approval Distribution subsystem. -#[derive(Debug)] +#[derive(Debug, derive_more::From)] pub enum ApprovalDistributionMessage { /// Notify the `ApprovalDistribution` subsystem about new blocks /// and the candidates contained within them. @@ -675,21 +683,28 @@ pub enum ApprovalDistributionMessage { /// If not, the subsystem is free to drop the message. DistributeApproval(IndirectSignedApprovalVote), /// An update from the network bridge. + #[from] NetworkBridgeUpdateV1(NetworkBridgeEvent), } /// A message type tying together all message types that are used across Subsystems. +#[subsystem_dispatch_gen(NetworkBridgeEvent)] #[derive(Debug, derive_more::From)] pub enum AllMessages { /// Message for the validation subsystem. + #[skip] CandidateValidation(CandidateValidationMessage), /// Message for the candidate backing subsystem. + #[skip] CandidateBacking(CandidateBackingMessage), /// Message for the candidate selection subsystem. + #[skip] CandidateSelection(CandidateSelectionMessage), /// Message for the Chain API subsystem. + #[skip] ChainApi(ChainApiMessage), /// Message for the Collator Protocol subsystem. + #[skip] CollatorProtocol(CollatorProtocolMessage), /// Message for the statement distribution subsystem. StatementDistribution(StatementDistributionMessage), @@ -700,20 +715,27 @@ pub enum AllMessages { /// Message for the bitfield distribution subsystem. BitfieldDistribution(BitfieldDistributionMessage), /// Message for the bitfield signing subsystem. + #[skip] BitfieldSigning(BitfieldSigningMessage), /// Message for the Provisioner subsystem. + #[skip] Provisioner(ProvisionerMessage), /// Message for the PoV Distribution subsystem. PoVDistribution(PoVDistributionMessage), /// Message for the Runtime API subsystem. + #[skip] RuntimeApi(RuntimeApiMessage), /// Message for the availability store subsystem. + #[skip] AvailabilityStore(AvailabilityStoreMessage), /// Message for the network bridge subsystem. + #[skip] NetworkBridge(NetworkBridgeMessage), /// Message for the Collation Generation subsystem. + #[skip] CollationGeneration(CollationGenerationMessage), /// Message for the Approval Voting subsystem. + #[skip] ApprovalVoting(ApprovalVotingMessage), /// Message for the Approval Distribution subsystem. ApprovalDistribution(ApprovalDistributionMessage),