Penalise bad peer behaviour (#1602)

## Issue Addressed

#1386 

## Proposed Changes

Penalises peers in our scoring system that produce invalid attestations or blocks.
This commit is contained in:
Age Manning 2020-09-10 03:51:06 +00:00
parent dfe507715d
commit b19cf02d2d

View File

@ -7,7 +7,7 @@ use beacon_chain::{
attestation_verification::Error as AttnError, observed_operations::ObservationOutcome, attestation_verification::Error as AttnError, observed_operations::ObservationOutcome,
BeaconChain, BeaconChainError, BeaconChainTypes, BlockError, ForkChoiceError, BeaconChain, BeaconChainError, BeaconChainTypes, BlockError, ForkChoiceError,
}; };
use eth2_libp2p::{MessageAcceptance, MessageId, PeerId}; use eth2_libp2p::{MessageAcceptance, MessageId, PeerAction, PeerId};
use slog::{crit, debug, error, info, trace, warn, Logger}; use slog::{crit, debug, error, info, trace, warn, Logger};
use ssz::Encode; use ssz::Encode;
use std::sync::Arc; use std::sync::Arc;
@ -234,7 +234,12 @@ impl<T: BeaconChainTypes> Worker<T> {
| Err(e @ BlockError::GenesisBlock) => { | Err(e @ BlockError::GenesisBlock) => {
warn!(self.log, "Could not verify block for gossip, rejecting the block"; warn!(self.log, "Could not verify block for gossip, rejecting the block";
"error" => e.to_string()); "error" => e.to_string());
self.propagate_validation_result(message_id, peer_id, MessageAcceptance::Reject); self.propagate_validation_result(
message_id,
peer_id.clone(),
MessageAcceptance::Reject,
);
self.penalize_peer(peer_id, PeerAction::LowToleranceError);
return; return;
} }
}; };
@ -252,9 +257,6 @@ impl<T: BeaconChainTypes> Worker<T> {
"peer_id" => peer_id.to_string() "peer_id" => peer_id.to_string()
); );
// TODO: It would be better if we can run this _after_ we publish the block to
// reduce block propagation latency.
//
// The `MessageHandler` would be the place to put this, however it doesn't seem // The `MessageHandler` would be the place to put this, however it doesn't seem
// to have a reference to the `BeaconChain`. I will leave this for future // to have a reference to the `BeaconChain`. I will leave this for future
// works. // works.
@ -290,6 +292,7 @@ impl<T: BeaconChainTypes> Worker<T> {
"block root" => format!("{}", block.canonical_root()), "block root" => format!("{}", block.canonical_root()),
"block slot" => block.slot() "block slot" => block.slot()
); );
self.penalize_peer(peer_id, PeerAction::MidToleranceError);
trace!( trace!(
self.log, self.log,
"Invalid gossip beacon block ssz"; "Invalid gossip beacon block ssz";
@ -333,7 +336,13 @@ impl<T: BeaconChainTypes> Worker<T> {
); );
// These errors occur due to a fault in the beacon chain. It is not necessarily // These errors occur due to a fault in the beacon chain. It is not necessarily
// the fault on the peer. // the fault on the peer.
self.propagate_validation_result(message_id, peer_id, MessageAcceptance::Ignore); self.propagate_validation_result(
message_id,
peer_id.clone(),
MessageAcceptance::Ignore,
);
// We still penalize a peer slightly to prevent overuse of invalids.
self.penalize_peer(peer_id, PeerAction::HighToleranceError);
return; return;
} }
}; };
@ -382,7 +391,14 @@ impl<T: BeaconChainTypes> Worker<T> {
"peer" => peer_id.to_string(), "peer" => peer_id.to_string(),
"error" => format!("{:?}", e) "error" => format!("{:?}", e)
); );
self.propagate_validation_result(message_id, peer_id, MessageAcceptance::Ignore); self.propagate_validation_result(
message_id,
peer_id.clone(),
MessageAcceptance::Ignore,
);
// Penalize peer slightly for invalids.
self.penalize_peer(peer_id, PeerAction::HighToleranceError);
return; return;
} }
}; };
@ -425,7 +441,13 @@ impl<T: BeaconChainTypes> Worker<T> {
"peer" => peer_id.to_string(), "peer" => peer_id.to_string(),
"error" => format!("{:?}", e) "error" => format!("{:?}", e)
); );
self.propagate_validation_result(message_id, peer_id, MessageAcceptance::Ignore); self.propagate_validation_result(
message_id,
peer_id.clone(),
MessageAcceptance::Ignore,
);
// Penalize peer slightly for invalids.
self.penalize_peer(peer_id, PeerAction::HighToleranceError);
return; return;
} }
}; };
@ -497,6 +519,18 @@ impl<T: BeaconChainTypes> Worker<T> {
}); });
} }
/// Penalizes a peer for misbehaviour.
fn penalize_peer(&self, peer_id: PeerId, action: PeerAction) {
self.network_tx
.send(NetworkMessage::ReportPeer { peer_id, action })
.unwrap_or_else(|_| {
warn!(
self.log,
"Could not send peer action to the network service"
)
});
}
/// Send a message to `sync_tx`. /// Send a message to `sync_tx`.
/// ///
/// Creates a log if there is an interal error. /// Creates a log if there is an interal error.
@ -533,6 +567,7 @@ impl<T: BeaconChainTypes> Worker<T> {
peer_id.clone(), peer_id.clone(),
MessageAcceptance::Reject, MessageAcceptance::Reject,
); );
self.penalize_peer(peer_id.clone(), PeerAction::LowToleranceError);
} }
AttnError::InvalidSelectionProof { .. } | AttnError::InvalidSignature => { AttnError::InvalidSelectionProof { .. } | AttnError::InvalidSignature => {
/* /*
@ -545,6 +580,7 @@ impl<T: BeaconChainTypes> Worker<T> {
peer_id.clone(), peer_id.clone(),
MessageAcceptance::Reject, MessageAcceptance::Reject,
); );
self.penalize_peer(peer_id.clone(), PeerAction::LowToleranceError);
} }
AttnError::EmptyAggregationBitfield => { AttnError::EmptyAggregationBitfield => {
/* /*
@ -559,6 +595,7 @@ impl<T: BeaconChainTypes> Worker<T> {
peer_id.clone(), peer_id.clone(),
MessageAcceptance::Reject, MessageAcceptance::Reject,
); );
self.penalize_peer(peer_id.clone(), PeerAction::LowToleranceError);
} }
AttnError::AggregatorPubkeyUnknown(_) => { AttnError::AggregatorPubkeyUnknown(_) => {
/* /*
@ -579,6 +616,7 @@ impl<T: BeaconChainTypes> Worker<T> {
peer_id.clone(), peer_id.clone(),
MessageAcceptance::Reject, MessageAcceptance::Reject,
); );
self.penalize_peer(peer_id.clone(), PeerAction::LowToleranceError);
} }
AttnError::AggregatorNotInCommittee { .. } => { AttnError::AggregatorNotInCommittee { .. } => {
/* /*
@ -599,6 +637,7 @@ impl<T: BeaconChainTypes> Worker<T> {
peer_id.clone(), peer_id.clone(),
MessageAcceptance::Reject, MessageAcceptance::Reject,
); );
self.penalize_peer(peer_id.clone(), PeerAction::LowToleranceError);
} }
AttnError::AttestationAlreadyKnown { .. } => { AttnError::AttestationAlreadyKnown { .. } => {
/* /*
@ -662,6 +701,7 @@ impl<T: BeaconChainTypes> Worker<T> {
peer_id.clone(), peer_id.clone(),
MessageAcceptance::Reject, MessageAcceptance::Reject,
); );
self.penalize_peer(peer_id.clone(), PeerAction::LowToleranceError);
} }
AttnError::UnknownHeadBlock { beacon_block_root } => { AttnError::UnknownHeadBlock { beacon_block_root } => {
// Note: its a little bit unclear as to whether or not this block is unknown or // Note: its a little bit unclear as to whether or not this block is unknown or
@ -714,6 +754,7 @@ impl<T: BeaconChainTypes> Worker<T> {
peer_id.clone(), peer_id.clone(),
MessageAcceptance::Reject, MessageAcceptance::Reject,
); );
self.penalize_peer(peer_id.clone(), PeerAction::LowToleranceError);
} }
AttnError::BadTargetEpoch => { AttnError::BadTargetEpoch => {
/* /*
@ -727,6 +768,7 @@ impl<T: BeaconChainTypes> Worker<T> {
peer_id.clone(), peer_id.clone(),
MessageAcceptance::Reject, MessageAcceptance::Reject,
); );
self.penalize_peer(peer_id.clone(), PeerAction::LowToleranceError);
} }
AttnError::NoCommitteeForSlotAndIndex { .. } => { AttnError::NoCommitteeForSlotAndIndex { .. } => {
/* /*
@ -739,6 +781,7 @@ impl<T: BeaconChainTypes> Worker<T> {
peer_id.clone(), peer_id.clone(),
MessageAcceptance::Reject, MessageAcceptance::Reject,
); );
self.penalize_peer(peer_id.clone(), PeerAction::LowToleranceError);
} }
AttnError::NotExactlyOneAggregationBitSet(_) => { AttnError::NotExactlyOneAggregationBitSet(_) => {
/* /*
@ -751,6 +794,7 @@ impl<T: BeaconChainTypes> Worker<T> {
peer_id.clone(), peer_id.clone(),
MessageAcceptance::Reject, MessageAcceptance::Reject,
); );
self.penalize_peer(peer_id.clone(), PeerAction::LowToleranceError);
} }
AttnError::AttestsToFutureBlock { .. } => { AttnError::AttestsToFutureBlock { .. } => {
/* /*
@ -763,6 +807,7 @@ impl<T: BeaconChainTypes> Worker<T> {
peer_id.clone(), peer_id.clone(),
MessageAcceptance::Reject, MessageAcceptance::Reject,
); );
self.penalize_peer(peer_id.clone(), PeerAction::LowToleranceError);
} }
AttnError::InvalidSubnetId { received, expected } => { AttnError::InvalidSubnetId { received, expected } => {
@ -780,6 +825,7 @@ impl<T: BeaconChainTypes> Worker<T> {
peer_id.clone(), peer_id.clone(),
MessageAcceptance::Reject, MessageAcceptance::Reject,
); );
self.penalize_peer(peer_id.clone(), PeerAction::LowToleranceError);
} }
AttnError::Invalid(_) => { AttnError::Invalid(_) => {
/* /*
@ -792,6 +838,7 @@ impl<T: BeaconChainTypes> Worker<T> {
peer_id.clone(), peer_id.clone(),
MessageAcceptance::Reject, MessageAcceptance::Reject,
); );
self.penalize_peer(peer_id.clone(), PeerAction::LowToleranceError);
} }
AttnError::TooManySkippedSlots { AttnError::TooManySkippedSlots {
head_block_slot, head_block_slot,
@ -815,6 +862,7 @@ impl<T: BeaconChainTypes> Worker<T> {
peer_id.clone(), peer_id.clone(),
MessageAcceptance::Reject, MessageAcceptance::Reject,
); );
self.penalize_peer(peer_id.clone(), PeerAction::MidToleranceError);
} }
AttnError::BeaconChainError(e) => { AttnError::BeaconChainError(e) => {
/* /*
@ -835,6 +883,8 @@ impl<T: BeaconChainTypes> Worker<T> {
peer_id.clone(), peer_id.clone(),
MessageAcceptance::Ignore, MessageAcceptance::Ignore,
); );
// Penalize the peer slightly
self.penalize_peer(peer_id.clone(), PeerAction::HighToleranceError);
} }
} }