Skip to main content

soil_network/gossip/
validator.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
7use soil_network::common::role::ObservedRole;
8use soil_network::types::PeerId;
9use subsoil::runtime::traits::Block as BlockT;
10
11/// Validates consensus messages.
12pub trait Validator<B: BlockT>: Send + Sync {
13	/// New peer is connected.
14	fn new_peer(&self, _context: &mut dyn ValidatorContext<B>, _who: &PeerId, _role: ObservedRole) {
15	}
16
17	/// New connection is dropped.
18	fn peer_disconnected(&self, _context: &mut dyn ValidatorContext<B>, _who: &PeerId) {}
19
20	/// Validate consensus message.
21	fn validate(
22		&self,
23		context: &mut dyn ValidatorContext<B>,
24		sender: &PeerId,
25		data: &[u8],
26	) -> ValidationResult<B::Hash>;
27
28	/// Produce a closure for validating messages on a given topic.
29	fn message_expired<'a>(&'a self) -> Box<dyn FnMut(B::Hash, &[u8]) -> bool + 'a> {
30		Box::new(move |_topic, _data| false)
31	}
32
33	/// Produce a closure for filtering egress messages.
34	fn message_allowed<'a>(
35		&'a self,
36	) -> Box<dyn FnMut(&PeerId, MessageIntent, &B::Hash, &[u8]) -> bool + 'a> {
37		Box::new(move |_who, _intent, _topic, _data| true)
38	}
39}
40
41/// Validation context. Allows reacting to incoming messages by sending out further messages.
42pub trait ValidatorContext<B: BlockT> {
43	/// Broadcast all messages with given topic to peers that do not have it yet.
44	fn broadcast_topic(&mut self, topic: B::Hash, force: bool);
45	/// Broadcast a message to all peers that have not received it previously.
46	fn broadcast_message(&mut self, topic: B::Hash, message: Vec<u8>, force: bool);
47	/// Send addressed message to a peer.
48	fn send_message(&mut self, who: &PeerId, message: Vec<u8>);
49	/// Send all messages with given topic to a peer.
50	fn send_topic(&mut self, who: &PeerId, topic: B::Hash, force: bool);
51}
52
53/// The reason for sending out the message.
54#[derive(Eq, PartialEq, Copy, Clone)]
55#[cfg_attr(test, derive(Debug))]
56pub enum MessageIntent {
57	/// Requested broadcast.
58	Broadcast,
59	/// Requested broadcast to all peers.
60	ForcedBroadcast,
61	/// Periodic rebroadcast of all messages to all peers.
62	PeriodicRebroadcast,
63}
64
65/// Message validation result.
66pub enum ValidationResult<H> {
67	/// Message should be stored and propagated under given topic.
68	ProcessAndKeep(H),
69	/// Message should be processed, but not propagated.
70	ProcessAndDiscard(H),
71	/// Message should be ignored.
72	Discard,
73}
74
75/// A gossip message validator that discards all messages.
76pub struct DiscardAll;
77
78impl<B: BlockT> Validator<B> for DiscardAll {
79	fn validate(
80		&self,
81		_context: &mut dyn ValidatorContext<B>,
82		_sender: &PeerId,
83		_data: &[u8],
84	) -> ValidationResult<B::Hash> {
85		ValidationResult::Discard
86	}
87
88	fn message_expired<'a>(&'a self) -> Box<dyn FnMut(B::Hash, &[u8]) -> bool + 'a> {
89		Box::new(move |_topic, _data| true)
90	}
91
92	fn message_allowed<'a>(
93		&'a self,
94	) -> Box<dyn FnMut(&PeerId, MessageIntent, &B::Hash, &[u8]) -> bool + 'a> {
95		Box::new(move |_who, _intent, _topic, _data| false)
96	}
97}