soil_network/gossip/mod.rs
1// This file is part of Soil.
2
3// Copyright (C) Soil contributors.
4// Copyright (C) Parity Technologies (UK) Ltd.
5// SPDX-License-Identifier: GPL-3.0-or-later WITH Classpath-exception-2.0
6
7//! Polite gossiping.
8//!
9//! This crate provides gossiping capabilities on top of a network.
10//!
11//! Gossip messages are separated by two categories: "topics" and consensus engine ID.
12//! The consensus engine ID is sent over the wire with the message, while the topic is not,
13//! with the expectation that the topic can be derived implicitly from the content of the
14//! message, assuming it is valid.
15//!
16//! Topics are a single 32-byte tag associated with a message, used to group those messages
17//! in an opaque way. Consensus code can invoke [`ValidatorContext::broadcast_topic`] to
18//! attempt to send all messages under a single topic to all peers who don't have them yet, and
19//! [`ValidatorContext::send_topic`] to send all messages under a single topic to a specific peer.
20//!
21//! # Usage
22//!
23//! - Implement the [`Network`] trait, representing the low-level networking primitives. It is
24//! already implemented on `soil_network::NetworkService`.
25//! - Implement the [`Validator`] trait. See the section below.
26//! - Decide on a protocol name. Each gossiping protocol should have a different one.
27//! - Build a [`GossipEngine`] using these three elements.
28//! - Use the methods of the [`GossipEngine`] in order to send out messages and receive incoming
29//! messages.
30//!
31//! The [`GossipEngine`] will automatically use [`Network::add_set_reserved`] and
32//! [`NetworkPeers::remove_peers_from_reserved_set`] to maintain a set of peers equal to the set of
33//! peers the node is syncing from. See the documentation of `soil-network` for more explanations
34//! about the concepts of peer sets.
35//!
36//! # What is a validator?
37//!
38//! The primary role of a [`Validator`] is to process incoming messages from peers, and decide
39//! whether to discard them or process them. It also decides whether to re-broadcast the message.
40//!
41//! The secondary role of the [`Validator`] is to check if a message is allowed to be sent to a
42//! given peer. All messages, before being sent, will be checked against this filter.
43//! This enables the validator to use information it's aware of about connected peers to decide
44//! whether to send messages to them at any given moment in time - In particular, to wait until
45//! peers can accept and process the message before sending it.
46//!
47//! Lastly, the fact that gossip validators can decide not to rebroadcast messages
48//! opens the door for neighbor status packets to be baked into the gossip protocol.
49//! These status packets will typically contain light pieces of information
50//! used to inform peers of a current view of protocol state.
51
52pub use self::{
53 bridge::GossipEngine,
54 state_machine::TopicNotification,
55 validator::{DiscardAll, MessageIntent, ValidationResult, Validator, ValidatorContext},
56};
57
58use soil_network::sync::SyncEventStream;
59use soil_network::types::{
60 multiaddr::{Multiaddr, Protocol},
61 PeerId,
62};
63use soil_network::{types::ProtocolName, NetworkBlock, NetworkEventStream, NetworkPeers};
64use std::iter;
65use subsoil::runtime::traits::{Block as BlockT, NumberFor};
66
67mod bridge;
68mod state_machine;
69mod validator;
70
71/// Abstraction over a network.
72pub trait Network<B: BlockT>: NetworkPeers + NetworkEventStream {
73 fn add_set_reserved(&self, who: PeerId, protocol: ProtocolName) {
74 let addr = Multiaddr::empty().with(Protocol::P2p(*who.as_ref()));
75 let result = self.add_peers_to_reserved_set(protocol, iter::once(addr).collect());
76 if let Err(err) = result {
77 log::error!(target: "gossip", "add_set_reserved failed: {}", err);
78 }
79 }
80 fn remove_set_reserved(&self, who: PeerId, protocol: ProtocolName) {
81 let result = self.remove_peers_from_reserved_set(protocol, iter::once(who).collect());
82 if let Err(err) = result {
83 log::error!(target: "gossip", "remove_set_reserved failed: {}", err);
84 }
85 }
86}
87
88impl<T, B: BlockT> Network<B> for T where T: NetworkPeers + NetworkEventStream {}
89
90/// Abstraction over the syncing subsystem.
91pub trait Syncing<B: BlockT>: SyncEventStream + NetworkBlock<B::Hash, NumberFor<B>> {}
92
93impl<T, B: BlockT> Syncing<B> for T where T: SyncEventStream + NetworkBlock<B::Hash, NumberFor<B>> {}