Skip to content
This repository has been archived by the owner on Nov 15, 2023. It is now read-only.

Commit

Permalink
core/authority-discovery: Enable authorities to discover each other (#…
Browse files Browse the repository at this point in the history
…3452)

With the *authority-discovery* module an authoritative node makes itself
discoverable and is able to discover other authorities. Once discovered, a node
can directly connect to other authorities instead of multi-hop gossiping
information.

1. **Making itself discoverable**

    1. Retrieve its external addresses

    2. Adds its network peer id to the addresses

    3. Sign the above

    4. Put the signature and the addresses on the libp2p Kademlia DHT

2. **Discovering other authorities**

    1. Retrieve the current set of authorities

    2. Start DHT queries for the ids of the authorities

    3. Validate the signatures of the retrieved key value pairs

    4. Add the retrieved external addresses as ~reserved~ priority nodes to the
       peerset


* node/runtime: Add authority-discovery as session handler

The srml/authority-discovery module implements the OneSessionHandler in
order to keep its authority set in sync. This commit adds the module to
the set of session handlers.

* core/network: Make network worker return Dht events on poll

Instead of network worker implement the Future trait, have it implement
the Stream interface returning Dht events.

For now these events are ignored in build_network_future but will be
used by the core/authority-discovery module in subsequent commits.

* *: Add scaffolding and integration for core/authority-discovery module

* core/authority-discovery: Implement module logic itself
  • Loading branch information
mxinden authored and andresilva committed Sep 17, 2019
1 parent 9ad3dc9 commit f85e797
Show file tree
Hide file tree
Showing 19 changed files with 1,041 additions and 62 deletions.
102 changes: 102 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,7 @@ members = [
"core/utils/fork-tree",
"core/utils/wasm-builder",
"core/utils/wasm-builder-runner",
"core/authority-discovery",
"srml/support",
"srml/support/procedural",
"srml/support/procedural/tools",
Expand Down
32 changes: 32 additions & 0 deletions core/authority-discovery/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
[package]
name = "substrate-authority-discovery"
version = "2.0.0"
authors = ["Parity Technologies <admin@parity.io>"]
edition = "2018"
build = "build.rs"

[build-dependencies]
prost-build = "0.5"

[dependencies]
authority-discovery-primitives = { package = "substrate-authority-discovery-primitives", path = "./primitives", default-features = false }
bytes = "0.4"
client = { package = "substrate-client", path = "../../core/client" }
codec = { package = "parity-scale-codec", default-features = false, version = "1.0.3" }
derive_more = "0.14.0"
futures = "0.1"
keystore = { package = "substrate-keystore", path = "../../core/keystore" }
libp2p = { version = "0.12.0", default-features = false, features = ["secp256k1", "libp2p-websocket"] }
log = "0.4"
network = { package = "substrate-network", path = "../../core/network" }
primitives = { package = "substrate-primitives", path = "../primitives" }
prost = "0.5"
serde_json = "1.0"
sr-primitives = { path = "../../core/sr-primitives" }
tokio-timer = "0.2"

[dev-dependencies]
parking_lot = { version = "0.9.0" }
peerset = { package = "substrate-peerset", path = "../../core/peerset" }
test-client = { package = "substrate-test-runtime-client", path = "../../core/test-runtime/client" }
tokio = { version = "0.1"}
3 changes: 3 additions & 0 deletions core/authority-discovery/build.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
fn main() {
prost_build::compile_protos(&["src/schema/dht.proto"], &["src/schema"]).unwrap();
}
20 changes: 10 additions & 10 deletions core/authority-discovery/primitives/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,31 +19,31 @@
#![cfg_attr(not(feature = "std"), no_std)]

use client::decl_runtime_apis;
use codec::Codec;
use rstd::vec::Vec;

#[derive(codec::Encode, codec::Decode, Eq, PartialEq, Clone)]
#[cfg_attr(feature = "std", derive(Debug, Hash))]
pub struct Signature(pub Vec<u8>);
#[derive(codec::Encode, codec::Decode, Eq, PartialEq, Clone)]
#[cfg_attr(feature = "std", derive(Debug, Hash))]
pub struct AuthorityId(pub Vec<u8>);

decl_runtime_apis! {
/// The authority discovery api.
///
/// This api is used by the `core/authority-discovery` module to retrieve our
/// own authority identifier, to retrieve identifiers of the current authority
/// set, as well as sign and verify Kademlia Dht external address payloads
/// from and to other authorities.
pub trait AuthorityDiscoveryApi<AuthorityId: Codec> {
/// Returns own authority identifier iff it is part of the current authority
/// set, otherwise this function returns None. The restriction might be
/// softened in the future in case a consumer needs to learn own authority
/// identifier.
fn authority_id() -> Option<AuthorityId>;

pub trait AuthorityDiscoveryApi {
/// Retrieve authority identifiers of the current authority set.
fn authorities() -> Vec<AuthorityId>;

/// Sign the given payload with the private key corresponding to the given authority id.
fn sign(payload: Vec<u8>, authority_id: AuthorityId) -> Option<Vec<u8>>;
fn sign(payload: &Vec<u8>) -> Option<(Signature, AuthorityId)>;

/// Verify the given signature for the given payload with the given
/// authority identifier.
fn verify(payload: Vec<u8>, signature: Vec<u8>, authority_id: AuthorityId) -> bool;
fn verify(payload: &Vec<u8>, signature: &Signature, authority_id: &AuthorityId) -> bool;
}
}
47 changes: 47 additions & 0 deletions core/authority-discovery/src/error.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
// Copyright 2019 Parity Technologies (UK) Ltd.
// This file is part of Substrate.

// Substrate 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.

// Substrate 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 Substrate. If not, see <http://www.gnu.org/licenses/>.

//! Authority discovery errors.

/// AuthorityDiscovery Result.
pub type Result<T> = std::result::Result<T, Error>;

/// Error type for the authority discovery module.
#[derive(Debug, derive_more::Display, derive_more::From)]
pub enum Error {
/// Failed to verify a dht payload with the given signature.
VerifyingDhtPayload,
/// Failed to hash the authority id to be used as a dht key.
HashingAuthorityId(libp2p::core::multiaddr::multihash::EncodeError),
/// Failed calling into the Substrate runtime.
CallingRuntime(client::error::Error),
/// Failed signing the dht payload via the Substrate runtime.
SigningDhtPayload,
/// From the Dht we only get the hashed authority id. In order to retrieve the actual authority id and to ensure it
/// is actually an authority, we match the hash against the hash of the authority id of all other authorities. This
/// error is the result of the above failing.
MatchingHashedAuthorityIdWithAuthorityId,
/// Failed to set the authority discovery peerset priority group in the peerset module.
SettingPeersetPriorityGroup(String),
/// Failed to encode a dht payload.
Encoding(prost::EncodeError),
/// Failed to decode a dht payload.
Decoding(prost::DecodeError),
/// Failed to parse a libp2p multi address.
ParsingMultiaddress(libp2p::core::multiaddr::Error),
/// Tokio timer error.
PollingTokioTimer(tokio_timer::Error)
}
Loading

0 comments on commit f85e797

Please sign in to comment.