Split the Roles in three types (#5520)

* Split the Roles bitfield in three

* Forgot to include some changes

* Fix cli test

* More test fixes

* Oh God, merging master broke other tests

* Didn't run the doctests

* Address review

* I'm trying to fix the build blindly because it's taking a good hour to compile on my machine

* Address some review

* Also update the peerset's API to make sense

* Fix peerset tests

* Fix browser node

* client: distinguish between local and network authority

Co-authored-by: André Silva <andre.beat@gmail.com>
This commit is contained in:
Pierre Krieger
2020-04-03 19:08:14 +02:00
committed by GitHub
parent 9dbcb11f66
commit 8c03a4fcef
44 changed files with 591 additions and 432 deletions
+60 -8
View File
@@ -15,18 +15,19 @@
// along with Substrate. If not, see <http://www.gnu.org/licenses/>.
use crate::{
config::Role,
debug_info, discovery::DiscoveryBehaviour, discovery::DiscoveryOut,
Event, protocol::event::DhtEvent, ExHashT,
Event, ObservedRole, DhtEvent, ExHashT,
};
use crate::protocol::{self, light_client_handler, CustomMessageOutcome, Protocol};
use crate::protocol::{self, light_client_handler, message::Roles, CustomMessageOutcome, Protocol};
use libp2p::NetworkBehaviour;
use libp2p::core::{Multiaddr, PeerId, PublicKey};
use libp2p::kad::record;
use libp2p::swarm::{NetworkBehaviourAction, NetworkBehaviourEventProcess, PollParameters};
use log::debug;
use sp_consensus::{BlockOrigin, import_queue::{IncomingBlock, Origin}};
use sp_runtime::{traits::{Block as BlockT, NumberFor}, Justification};
use std::{iter, task::Context, task::Poll};
use sp_runtime::{traits::{Block as BlockT, NumberFor}, ConsensusEngineId, Justification};
use std::{borrow::Cow, iter, task::Context, task::Poll};
use void;
/// General behaviour of the network. Combines all protocols together.
@@ -44,9 +45,14 @@ pub struct Behaviour<B: BlockT, H: ExHashT> {
block_requests: protocol::BlockRequests<B>,
/// Light client request handling.
light_client_handler: protocol::LightClientHandler<B>,
/// Queue of events to produce for the outside.
#[behaviour(ignore)]
events: Vec<BehaviourOut<B>>,
/// Role of our local node, as originally passed from the configuration.
#[behaviour(ignore)]
role: Role,
}
/// Event generated by `Behaviour`.
@@ -63,6 +69,7 @@ impl<B: BlockT, H: ExHashT> Behaviour<B, H> {
/// Builds a new `Behaviour`.
pub async fn new(
substrate: Protocol<B, H>,
role: Role,
user_agent: String,
local_public_key: PublicKey,
known_addresses: Vec<(PeerId, Multiaddr)>,
@@ -84,7 +91,8 @@ impl<B: BlockT, H: ExHashT> Behaviour<B, H> {
).await,
block_requests,
light_client_handler,
events: Vec::new()
events: Vec::new(),
role,
}
}
@@ -112,6 +120,32 @@ impl<B: BlockT, H: ExHashT> Behaviour<B, H> {
self.debug_info.node(peer_id)
}
/// Registers a new notifications protocol.
///
/// After that, you can call `write_notifications`.
///
/// Please call `event_stream` before registering a protocol, otherwise you may miss events
/// about the protocol that you have registered.
///
/// You are very strongly encouraged to call this method very early on. Any connection open
/// will retain the protocols that were registered then, and not any new one.
pub fn register_notifications_protocol(
&mut self,
engine_id: ConsensusEngineId,
protocol_name: impl Into<Cow<'static, [u8]>>,
) {
let list = self.substrate.register_notifications_protocol(engine_id, protocol_name);
for (remote, roles) in list {
let role = reported_roles_to_observed_role(&self.role, remote, roles);
let ev = Event::NotificationStreamOpened {
remote: remote.clone(),
engine_id,
role,
};
self.events.push(BehaviourOut::Event(ev));
}
}
/// Returns a shared reference to the user protocol.
pub fn user_protocol(&self) -> &Protocol<B, H> {
&self.substrate
@@ -138,6 +172,22 @@ impl<B: BlockT, H: ExHashT> Behaviour<B, H> {
}
}
fn reported_roles_to_observed_role(local_role: &Role, remote: &PeerId, roles: Roles) -> ObservedRole {
if roles.is_authority() {
match local_role {
Role::Authority { sentry_nodes }
if sentry_nodes.iter().any(|s| s.peer_id == *remote) => ObservedRole::OurSentry,
Role::Sentry { validators }
if validators.iter().any(|s| s.peer_id == *remote) => ObservedRole::OurGuardedAuthority,
_ => ObservedRole::Authority
}
} else if roles.is_full() {
ObservedRole::Full
} else {
ObservedRole::Light
}
}
impl<B: BlockT, H: ExHashT> NetworkBehaviourEventProcess<void::Void> for
Behaviour<B, H> {
fn inject_event(&mut self, event: void::Void) {
@@ -155,14 +205,16 @@ Behaviour<B, H> {
self.events.push(BehaviourOut::JustificationImport(origin, hash, nb, justification)),
CustomMessageOutcome::FinalityProofImport(origin, hash, nb, proof) =>
self.events.push(BehaviourOut::FinalityProofImport(origin, hash, nb, proof)),
CustomMessageOutcome::NotificationStreamOpened { remote, protocols, roles } =>
CustomMessageOutcome::NotificationStreamOpened { remote, protocols, roles } => {
let role = reported_roles_to_observed_role(&self.role, &remote, roles);
for engine_id in protocols {
self.events.push(BehaviourOut::Event(Event::NotificationStreamOpened {
remote: remote.clone(),
engine_id,
roles,
role: role.clone(),
}));
},
}
},
CustomMessageOutcome::NotificationStreamClosed { remote, protocols } =>
for engine_id in protocols {
self.events.push(BehaviourOut::Event(Event::NotificationStreamClosed {