mirror of
https://github.com/fluencelabs/rust-libp2p
synced 2025-06-14 02:21:21 +00:00
protocols/gossipsub: Add message signing and verification configuration (#1583)
This adds optional message signing and verification to the gossipsub protocol as per the libp2p specifications. In addition this commit: - Removes the LruCache received cache and simply uses the memcache in it's place. - Send subscriptions to all peers - Prevent invalid messages from being gossiped - Send grafts when subscriptions are added to the mesh Co-authored-by: Max Inden <mail@max-inden.de> Co-authored-by: Rüdiger Klaehn <rklaehn@protonmail.com> Co-authored-by: Rüdiger Klaehn <rklaehn@gmail.com>
This commit is contained in:
@ -19,6 +19,7 @@
|
||||
// DEALINGS IN THE SOFTWARE.
|
||||
|
||||
use crate::behaviour::GossipsubRpc;
|
||||
use crate::config::ValidationMode;
|
||||
use crate::protocol::{GossipsubCodec, ProtocolConfig};
|
||||
use futures::prelude::*;
|
||||
use futures_codec::Framed;
|
||||
@ -50,6 +51,10 @@ pub struct GossipsubHandler {
|
||||
/// Queue of values that we want to send to the remote.
|
||||
send_queue: SmallVec<[GossipsubRpc; 16]>,
|
||||
|
||||
/// Flag indicating that an outbound substream is being established to prevent duplicate
|
||||
/// requests.
|
||||
outbound_substream_establishing: bool,
|
||||
|
||||
/// Flag determining whether to maintain the connection to the peer.
|
||||
keep_alive: KeepAlive,
|
||||
}
|
||||
@ -80,26 +85,20 @@ enum OutboundSubstreamState {
|
||||
|
||||
impl GossipsubHandler {
|
||||
/// Builds a new `GossipsubHandler`.
|
||||
pub fn new(protocol_id: impl Into<Cow<'static, [u8]>>, max_transmit_size: usize) -> Self {
|
||||
pub fn new(
|
||||
protocol_id: impl Into<Cow<'static, [u8]>>,
|
||||
max_transmit_size: usize,
|
||||
validation_mode: ValidationMode,
|
||||
) -> Self {
|
||||
GossipsubHandler {
|
||||
listen_protocol: SubstreamProtocol::new(ProtocolConfig::new(
|
||||
protocol_id,
|
||||
max_transmit_size,
|
||||
validation_mode,
|
||||
)),
|
||||
inbound_substream: None,
|
||||
outbound_substream: None,
|
||||
send_queue: SmallVec::new(),
|
||||
keep_alive: KeepAlive::Yes,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Default for GossipsubHandler {
|
||||
fn default() -> Self {
|
||||
GossipsubHandler {
|
||||
listen_protocol: SubstreamProtocol::new(ProtocolConfig::default()),
|
||||
inbound_substream: None,
|
||||
outbound_substream: None,
|
||||
outbound_substream_establishing: false,
|
||||
send_queue: SmallVec::new(),
|
||||
keep_alive: KeepAlive::Yes,
|
||||
}
|
||||
@ -132,6 +131,7 @@ impl ProtocolsHandler for GossipsubHandler {
|
||||
substream: <Self::OutboundProtocol as OutboundUpgrade<NegotiatedSubstream>>::Output,
|
||||
message: Self::OutboundOpenInfo,
|
||||
) {
|
||||
self.outbound_substream_establishing = false;
|
||||
// Should never establish a new outbound substream if one already exists.
|
||||
// If this happens, an outbound message is not sent.
|
||||
if self.outbound_substream.is_some() {
|
||||
@ -154,6 +154,7 @@ impl ProtocolsHandler for GossipsubHandler {
|
||||
<Self::OutboundProtocol as OutboundUpgrade<NegotiatedSubstream>>::Error,
|
||||
>,
|
||||
) {
|
||||
self.outbound_substream_establishing = false;
|
||||
// Ignore upgrade errors for now.
|
||||
// If a peer doesn't support this protocol, this will just ignore them, but not disconnect
|
||||
// them.
|
||||
@ -175,9 +176,13 @@ impl ProtocolsHandler for GossipsubHandler {
|
||||
>,
|
||||
> {
|
||||
// determine if we need to create the stream
|
||||
if !self.send_queue.is_empty() && self.outbound_substream.is_none() {
|
||||
if !self.send_queue.is_empty()
|
||||
&& self.outbound_substream.is_none()
|
||||
&& !self.outbound_substream_establishing
|
||||
{
|
||||
let message = self.send_queue.remove(0);
|
||||
self.send_queue.shrink_to_fit();
|
||||
self.outbound_substream_establishing = true;
|
||||
return Poll::Ready(ProtocolsHandlerEvent::OutboundSubstreamRequest {
|
||||
protocol: self.listen_protocol.clone(),
|
||||
info: message,
|
||||
@ -198,9 +203,21 @@ impl ProtocolsHandler for GossipsubHandler {
|
||||
return Poll::Ready(ProtocolsHandlerEvent::Custom(message));
|
||||
}
|
||||
Poll::Ready(Some(Err(e))) => {
|
||||
debug!("Inbound substream error while awaiting input: {:?}", e);
|
||||
self.inbound_substream =
|
||||
Some(InboundSubstreamState::Closing(substream));
|
||||
match e.kind() {
|
||||
std::io::ErrorKind::InvalidData => {
|
||||
// Invalid message, ignore it and reset to waiting
|
||||
warn!("Invalid message received. Error: {}", e);
|
||||
self.inbound_substream =
|
||||
Some(InboundSubstreamState::WaitingInput(substream));
|
||||
}
|
||||
_ => {
|
||||
// More serious errors, close this side of the stream. If the
|
||||
// peer is still around, they will re-establish their
|
||||
// connection
|
||||
self.inbound_substream =
|
||||
Some(InboundSubstreamState::Closing(substream));
|
||||
}
|
||||
}
|
||||
}
|
||||
// peer closed the stream
|
||||
Poll::Ready(None) => {
|
||||
@ -242,7 +259,7 @@ impl ProtocolsHandler for GossipsubHandler {
|
||||
break;
|
||||
}
|
||||
Some(InboundSubstreamState::Poisoned) => {
|
||||
panic!("Error occurred during inbound stream processing")
|
||||
unreachable!("Error occurred during inbound stream processing")
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -338,7 +355,7 @@ impl ProtocolsHandler for GossipsubHandler {
|
||||
break;
|
||||
}
|
||||
Some(OutboundSubstreamState::Poisoned) => {
|
||||
panic!("Error occurred during outbound stream processing")
|
||||
unreachable!("Error occurred during outbound stream processing")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user