diff --git a/Cargo.lock b/Cargo.lock index 0ec7048d6338..687033f178e1 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2790,6 +2790,7 @@ dependencies = [ "sr-staking-primitives 2.0.0 (git+https://github.com/paritytech/substrate?branch=polkadot-master)", "sr-std 2.0.0 (git+https://github.com/paritytech/substrate?branch=polkadot-master)", "sr-version 2.0.0 (git+https://github.com/paritytech/substrate?branch=polkadot-master)", + "srml-authority-discovery 0.1.0 (git+https://github.com/paritytech/substrate?branch=polkadot-master)", "srml-authorship 0.1.0 (git+https://github.com/paritytech/substrate?branch=polkadot-master)", "srml-babe 2.0.0 (git+https://github.com/paritytech/substrate?branch=polkadot-master)", "srml-balances 2.0.0 (git+https://github.com/paritytech/substrate?branch=polkadot-master)", @@ -2811,6 +2812,7 @@ dependencies = [ "srml-system 2.0.0 (git+https://github.com/paritytech/substrate?branch=polkadot-master)", "srml-timestamp 2.0.0 (git+https://github.com/paritytech/substrate?branch=polkadot-master)", "srml-treasury 2.0.0 (git+https://github.com/paritytech/substrate?branch=polkadot-master)", + "substrate-authority-discovery-primitives 2.0.0 (git+https://github.com/paritytech/substrate?branch=polkadot-master)", "substrate-client 2.0.0 (git+https://github.com/paritytech/substrate?branch=polkadot-master)", "substrate-consensus-babe-primitives 2.0.0 (git+https://github.com/paritytech/substrate?branch=polkadot-master)", "substrate-inherents 2.0.0 (git+https://github.com/paritytech/substrate?branch=polkadot-master)", @@ -2847,6 +2849,7 @@ dependencies = [ "srml-babe 2.0.0 (git+https://github.com/paritytech/substrate?branch=polkadot-master)", "srml-im-online 0.1.0 (git+https://github.com/paritytech/substrate?branch=polkadot-master)", "srml-staking 2.0.0 (git+https://github.com/paritytech/substrate?branch=polkadot-master)", + "substrate-authority-discovery 2.0.0 (git+https://github.com/paritytech/substrate?branch=polkadot-master)", "substrate-client 2.0.0 (git+https://github.com/paritytech/substrate?branch=polkadot-master)", "substrate-client-db 2.0.0 (git+https://github.com/paritytech/substrate?branch=polkadot-master)", "substrate-consensus-babe 2.0.0 (git+https://github.com/paritytech/substrate?branch=polkadot-master)", @@ -3746,6 +3749,24 @@ dependencies = [ "sr-std 2.0.0 (git+https://github.com/paritytech/substrate?branch=polkadot-master)", ] +[[package]] +name = "srml-authority-discovery" +version = "0.1.0" +source = "git+https://github.com/paritytech/substrate?branch=polkadot-master#7a7d641b40b9f9791406d04bd4fc7be2d190fa7b" +dependencies = [ + "parity-scale-codec 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.101 (registry+https://github.com/rust-lang/crates.io-index)", + "sr-io 2.0.0 (git+https://github.com/paritytech/substrate?branch=polkadot-master)", + "sr-primitives 2.0.0 (git+https://github.com/paritytech/substrate?branch=polkadot-master)", + "sr-std 2.0.0 (git+https://github.com/paritytech/substrate?branch=polkadot-master)", + "srml-im-online 0.1.0 (git+https://github.com/paritytech/substrate?branch=polkadot-master)", + "srml-session 2.0.0 (git+https://github.com/paritytech/substrate?branch=polkadot-master)", + "srml-support 2.0.0 (git+https://github.com/paritytech/substrate?branch=polkadot-master)", + "srml-system 2.0.0 (git+https://github.com/paritytech/substrate?branch=polkadot-master)", + "substrate-application-crypto 2.0.0 (git+https://github.com/paritytech/substrate?branch=polkadot-master)", + "substrate-primitives 2.0.0 (git+https://github.com/paritytech/substrate?branch=polkadot-master)", +] + [[package]] name = "srml-authorship" version = "0.1.0" @@ -6122,6 +6143,7 @@ dependencies = [ "checksum sr-staking-primitives 2.0.0 (git+https://github.com/paritytech/substrate?branch=polkadot-master)" = "" "checksum sr-std 2.0.0 (git+https://github.com/paritytech/substrate?branch=polkadot-master)" = "" "checksum sr-version 2.0.0 (git+https://github.com/paritytech/substrate?branch=polkadot-master)" = "" +"checksum srml-authority-discovery 0.1.0 (git+https://github.com/paritytech/substrate?branch=polkadot-master)" = "" "checksum srml-authorship 0.1.0 (git+https://github.com/paritytech/substrate?branch=polkadot-master)" = "" "checksum srml-babe 2.0.0 (git+https://github.com/paritytech/substrate?branch=polkadot-master)" = "" "checksum srml-balances 2.0.0 (git+https://github.com/paritytech/substrate?branch=polkadot-master)" = "" diff --git a/runtime/Cargo.toml b/runtime/Cargo.toml index c34825fb0659..23ce79884f46 100644 --- a/runtime/Cargo.toml +++ b/runtime/Cargo.toml @@ -14,6 +14,7 @@ safe-mix = { version = "1.0", default-features = false} serde = { version = "1.0", default-features = false } serde_derive = { version = "1.0", optional = true } +authority-discovery-primitives = { package = "substrate-authority-discovery-primitives", git = "https://github.com/paritytech/substrate", default-features = false, branch = "polkadot-master" } babe-primitives = { package = "substrate-consensus-babe-primitives", git = "https://github.com/paritytech/substrate", default-features = false, branch = "polkadot-master" } client = { package = "substrate-client", git = "https://github.com/paritytech/substrate", default-features = false, branch = "polkadot-master" } inherents = { package = "substrate-inherents", git = "https://github.com/paritytech/substrate", default-features = false, branch = "polkadot-master" } @@ -27,6 +28,7 @@ substrate-serializer = { git = "https://github.com/paritytech/substrate", defaul substrate-session = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "polkadot-master" } version = { package = "sr-version", git = "https://github.com/paritytech/substrate", default-features = false, branch = "polkadot-master" } +authority-discovery = { package = "srml-authority-discovery", git = "https://github.com/paritytech/substrate", default-features = false, branch = "polkadot-master" } authorship = { package = "srml-authorship", git = "https://github.com/paritytech/substrate", default-features = false, branch = "polkadot-master" } babe = { package = "srml-babe", git = "https://github.com/paritytech/substrate", default-features = false, branch = "polkadot-master" } balances = { package = "srml-balances", git = "https://github.com/paritytech/substrate", default-features = false, branch = "polkadot-master" } @@ -68,6 +70,8 @@ default = ["std"] no_std = [] only-staking = [] std = [ + "authority-discovery-primitives/std", + "authority-discovery/std", "bitvec/std", "primitives/std", "rustc-hex/std", diff --git a/runtime/src/lib.rs b/runtime/src/lib.rs index 703e02102904..b0cd30c68c82 100644 --- a/runtime/src/lib.rs +++ b/runtime/src/lib.rs @@ -55,7 +55,8 @@ use sr_staking_primitives::SessionIndex; use srml_support::{ parameter_types, construct_runtime, traits::{SplitTwoWays, Currency} }; -use im_online::sr25519::{AuthorityId as ImOnlineId}; +use authority_discovery_primitives::{AuthorityId as EncodedAuthorityId, Signature as EncodedSignature}; +use im_online::sr25519::{AuthorityId as ImOnlineId, AuthoritySignature as ImOnlineSignature}; use system::offchain::TransactionSubmitter; #[cfg(feature = "std")] @@ -242,7 +243,7 @@ parameter_types! { pub const Offset: BlockNumber = 0; } -type SessionHandlers = (Grandpa, Babe, ImOnline, Parachains); +type SessionHandlers = (Grandpa, Babe, ImOnline, AuthorityDiscovery, Parachains); impl_opaque_keys! { pub struct SessionKeys { #[id(key_types::GRANDPA)] @@ -444,6 +445,8 @@ impl im_online::Trait for Runtime { type ReportUnresponsiveness = (); } +impl authority_discovery::Trait for Runtime {} + impl grandpa::Trait for Runtime { type Event = Event; } @@ -530,6 +533,7 @@ construct_runtime!( FinalityTracker: finality_tracker::{Module, Call, Inherent}, Grandpa: grandpa::{Module, Call, Storage, Config, Event}, ImOnline: im_online::{Module, Call, Storage, Event, ValidateUnsigned, Config}, + AuthorityDiscovery: authority_discovery::{Module, Call, Config}, // Governance stuff; uncallable initially. Democracy: democracy::{Module, Call, Storage, Config, Event}, @@ -684,6 +688,35 @@ impl_runtime_apis! { } } + impl authority_discovery_primitives::AuthorityDiscoveryApi for Runtime { + fn authorities() -> Vec { + AuthorityDiscovery::authorities().into_iter() + .map(|id| id.encode()) + .map(EncodedAuthorityId) + .collect() + } + + fn sign(payload: &Vec) -> Option<(EncodedSignature, EncodedAuthorityId)> { + AuthorityDiscovery::sign(payload).map(|(sig, id)| { + (EncodedSignature(sig.encode()), EncodedAuthorityId(id.encode())) + }) + } + + fn verify(payload: &Vec, signature: &EncodedSignature, authority_id: &EncodedAuthorityId) -> bool { + let signature = match ImOnlineSignature::decode(&mut &signature.0[..]) { + Ok(s) => s, + _ => return false, + }; + + let authority_id = match ImOnlineId::decode(&mut &authority_id.0[..]) { + Ok(id) => id, + _ => return false, + }; + + AuthorityDiscovery::verify(payload, signature, authority_id) + } + } + impl substrate_session::SessionKeys for Runtime { fn generate_session_keys(seed: Option>) -> Vec { let seed = seed.as_ref().map(|s| rstd::str::from_utf8(&s).expect("Seed is an utf8 string")); diff --git a/service/Cargo.toml b/service/Cargo.toml index 0638b7027675..3059af36be91 100644 --- a/service/Cargo.toml +++ b/service/Cargo.toml @@ -36,5 +36,6 @@ substrate-keystore = { git = "https://github.com/paritytech/substrate", branch = srml-babe = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "polkadot-master" } srml-staking = { git = "https://github.com/paritytech/substrate", default-features = false, branch = "polkadot-master" } im-online = { package = "srml-im-online", git = "https://github.com/paritytech/substrate", default-features = false, branch = "polkadot-master" } +authority-discovery = { package = "substrate-authority-discovery", git = "https://github.com/paritytech/substrate", branch = "polkadot-master" } babe = { package = "substrate-consensus-babe", git = "https://github.com/paritytech/substrate", branch = "polkadot-master" } babe-primitives = { package = "substrate-consensus-babe-primitives", git = "https://github.com/paritytech/substrate", default-features = false, branch = "polkadot-master" } diff --git a/service/src/chain_spec.rs b/service/src/chain_spec.rs index b1dee37ea82b..25943a2b1ad6 100644 --- a/service/src/chain_spec.rs +++ b/service/src/chain_spec.rs @@ -148,6 +148,7 @@ fn staging_testnet_config_genesis() -> GenesisConfig { babe: Some(Default::default()), grandpa: Some(Default::default()), im_online: Some(Default::default()), + authority_discovery: Some(Default::default()), parachains: Some(ParachainsConfig { authorities: vec![], parachains: vec![], @@ -285,6 +286,7 @@ pub fn testnet_genesis( babe: Some(Default::default()), grandpa: Some(Default::default()), im_online: Some(Default::default()), + authority_discovery: Some(Default::default()), parachains: Some(ParachainsConfig { authorities: vec![], parachains: vec![], diff --git a/service/src/lib.rs b/service/src/lib.rs index 6bade1429363..31f8d840743a 100644 --- a/service/src/lib.rs +++ b/service/src/lib.rs @@ -19,6 +19,7 @@ pub mod chain_spec; use futures::prelude::*; +use futures::sync::mpsc; use client::LongestChain; use std::sync::Arc; use std::time::Duration; @@ -138,6 +139,8 @@ pub fn new_full(config: Configuration) CallExecutor = impl CallExecutor + Clone + Send + Sync + 'static, >, ServiceError> { + use substrate_network::DhtEvent; + let is_authority = config.roles.is_authority(); let is_collator = config.custom.collating_for.is_some(); let force_authoring = config.force_authoring; @@ -148,11 +151,19 @@ pub fn new_full(config: Configuration) let (builder, mut import_setup, inherent_data_providers) = new_full_start!(config); + // Dht event channel from the network to the authority discovery module. Use + // bounded channel to ensure back-pressure. Authority discovery is triggering one + // event per authority within the current authority set. This estimates the + // authority set size to be somewhere below 10 000 thereby setting the channel + // buffer size to 10 000. + let (dht_event_tx, dht_event_rx) = mpsc::channel::(10000); + let service = builder .with_network_protocol(|config| Ok(PolkadotProtocol::new(config.custom.collating_for.clone())))? .with_finality_proof_provider(|client, backend| Ok(Arc::new(GrandpaFinalityProofProvider::new(backend, client)) as _) )? + .with_dht_event_tx(dht_event_tx)? .build()?; let (block_import, link_half, babe_link) = import_setup.take() @@ -258,6 +269,13 @@ pub fn new_full(config: Configuration) let babe = start_babe(babe_config)?; let select = babe.select(service.on_exit()).then(|_| Ok(())); service.spawn_essential_task(Box::new(select)); + + let authority_discovery = authority_discovery::AuthorityDiscovery::new( + service.client(), + service.network(), + dht_event_rx, + ); + service.spawn_task(authority_discovery); } else { network_gossip::register_non_authority_validator(service.network()); }