Punish peers for duplicate GRANDPA neighbor messages (#12462)

* Decrease peer reputation for duplicate GRANDPA neighbor messages.

* Fix comparison

* Fix update_peer_state() validity condition

* Add negative test

* Rework update_peer_state() validity condition, add tests

* update_peer_state() validity condition: invert comparison

* Split InvalidViewChange and DuplicateNeighborMessage misbehaviors

* Enforce rate-limiting of duplicate GRANDPA neighbor packets

* Update client/finality-grandpa/src/communication/gossip.rs

Co-authored-by: André Silva <123550+andresilva@users.noreply.github.com>

* Make rolling clock back in a test safer

Co-authored-by: André Silva <123550+andresilva@users.noreply.github.com>
This commit is contained in:
Dmitrii Markin
2022-10-13 12:24:31 +03:00
committed by GitHub
parent b38c4165a4
commit b0b2b6799c
3 changed files with 124 additions and 52 deletions
@@ -32,9 +32,6 @@ use super::gossip::{GossipMessage, NeighborPacket};
use sc_network::PeerId;
use sp_runtime::traits::{Block as BlockT, NumberFor};
// How often to rebroadcast, in cases where no new packets are created.
const REBROADCAST_AFTER: Duration = Duration::from_secs(2 * 60);
/// A sender used to send neighbor packets to a background job.
#[derive(Clone)]
pub(super) struct NeighborPacketSender<B: BlockT>(
@@ -60,6 +57,7 @@ impl<B: BlockT> NeighborPacketSender<B> {
/// implementation). Periodically it sends out the last packet in cases where no new ones arrive.
pub(super) struct NeighborPacketWorker<B: BlockT> {
last: Option<(Vec<PeerId>, NeighborPacket<NumberFor<B>>)>,
rebroadcast_period: Duration,
delay: Delay,
rx: TracingUnboundedReceiver<(Vec<PeerId>, NeighborPacket<NumberFor<B>>)>,
}
@@ -67,13 +65,16 @@ pub(super) struct NeighborPacketWorker<B: BlockT> {
impl<B: BlockT> Unpin for NeighborPacketWorker<B> {}
impl<B: BlockT> NeighborPacketWorker<B> {
pub(super) fn new() -> (Self, NeighborPacketSender<B>) {
pub(super) fn new(rebroadcast_period: Duration) -> (Self, NeighborPacketSender<B>) {
let (tx, rx) = tracing_unbounded::<(Vec<PeerId>, NeighborPacket<NumberFor<B>>)>(
"mpsc_grandpa_neighbor_packet_worker",
);
let delay = Delay::new(REBROADCAST_AFTER);
let delay = Delay::new(rebroadcast_period);
(NeighborPacketWorker { last: None, delay, rx }, NeighborPacketSender(tx))
(
NeighborPacketWorker { last: None, rebroadcast_period, delay, rx },
NeighborPacketSender(tx),
)
}
}
@@ -85,7 +86,7 @@ impl<B: BlockT> Stream for NeighborPacketWorker<B> {
match this.rx.poll_next_unpin(cx) {
Poll::Ready(None) => return Poll::Ready(None),
Poll::Ready(Some((to, packet))) => {
this.delay.reset(REBROADCAST_AFTER);
this.delay.reset(this.rebroadcast_period);
this.last = Some((to.clone(), packet.clone()));
return Poll::Ready(Some((to, GossipMessage::<B>::from(packet))))
@@ -98,7 +99,7 @@ impl<B: BlockT> Stream for NeighborPacketWorker<B> {
// Getting this far here implies that the timer fired.
this.delay.reset(REBROADCAST_AFTER);
this.delay.reset(this.rebroadcast_period);
// Make sure the underlying task is scheduled for wake-up.
//