Commit 1d973455 authored by Fedor Sakharov's avatar Fedor Sakharov Committed by Gavin Wood
Browse files

positive updates to reputations when good things happen (#258)

* positive updates to reputations when good things happen

* address review

* branch on good or bad pov blocks

* add a new constant for bad pov blocks
parent 41f62652
Pipeline #37731 passed with stages
in 23 minutes and 39 seconds
......@@ -80,6 +80,17 @@ mod cost {
pub(super) const UNKNOWN_PEER: i32 = -50;
pub(super) const COLLATOR_ALREADY_KNOWN: i32 = -100;
pub(super) const BAD_COLLATION: i32 = -1000;
pub(super) const BAD_POV_BLOCK: i32 = -1000;
}
mod benefit {
pub(super) const EXPECTED_MESSAGE: i32 = 20;
pub(super) const VALID_FORMAT: i32 = 20;
pub(super) const KNOWN_PEER: i32 = 5;
pub(super) const NEW_COLLATOR: i32 = 10;
pub(super) const GOOD_COLLATION: i32 = 100;
pub(super) const GOOD_POV_BLOCK: i32 = 100;
}
type FullStatus = GenericFullStatus<Block>;
......@@ -382,6 +393,7 @@ impl PolkadotProtocol {
ctx.report_peer(who, cost::UNEXPECTED_MESSAGE);
return;
}
ctx.report_peer(who.clone(), benefit::EXPECTED_MESSAGE);
let local_collations = &mut self.local_collations;
let new_collations = match info.validator_keys.insert(key.clone()) {
......@@ -418,10 +430,21 @@ impl PolkadotProtocol {
) {
match self.in_flight.remove(&(req_id, who.clone())) {
Some(mut req) => {
if let Some(pov_block) = pov_block {
match req.process_response(pov_block) {
Ok(()) => return,
Err(r) => { req = r; }
match pov_block {
Some(pov_block) => {
match req.process_response(pov_block) {
Ok(()) => {
ctx.report_peer(who, benefit::GOOD_POV_BLOCK);
return;
}
Err(r) => {
ctx.report_peer(who, cost::BAD_POV_BLOCK);
req = r;
}
}
},
None => {
ctx.report_peer(who, benefit::EXPECTED_MESSAGE);
}
}
......@@ -493,6 +516,7 @@ impl Specialization<Block> for PolkadotProtocol {
ctx.report_peer(who, cost::COLLATOR_ALREADY_KNOWN);
return
}
ctx.report_peer(who.clone(), benefit::NEW_COLLATOR);
let collator_role = self.collators.on_new_collator(acc_id.clone(), para_id.clone());
......@@ -566,7 +590,10 @@ impl Specialization<Block> for PolkadotProtocol {
match message.take() {
Some(generic_message::Message::ChainSpecific(raw)) => {
match Message::decode(&mut raw.as_slice()) {
Some(msg) => self.on_polkadot_message(ctx, who, msg),
Some(msg) => {
ctx.report_peer(who.clone(), benefit::VALID_FORMAT);
self.on_polkadot_message(ctx, who, msg)
},
None => {
trace!(target: "p_net", "Bad message from {}", who);
ctx.report_peer(who, cost::INVALID_FORMAT);
......@@ -614,16 +641,21 @@ impl PolkadotProtocol {
match self.peers.get(&from) {
None => ctx.report_peer(from, cost::UNKNOWN_PEER),
Some(peer_info) => match peer_info.collating_for {
None => ctx.report_peer(from, cost::UNEXPECTED_MESSAGE),
Some((ref acc_id, ref para_id)) => {
let structurally_valid = para_id == &collation_para && acc_id == &collated_acc;
if structurally_valid && collation.receipt.check_signature().is_ok() {
debug!(target: "p_net", "Received collation for parachain {:?} from peer {}", para_id, from);
self.collators.on_collation(acc_id.clone(), relay_parent, collation)
} else {
ctx.report_peer(from, cost::INVALID_FORMAT)
};
Some(peer_info) => {
ctx.report_peer(from.clone(), benefit::KNOWN_PEER);
match peer_info.collating_for {
None => ctx.report_peer(from, cost::UNEXPECTED_MESSAGE),
Some((ref acc_id, ref para_id)) => {
ctx.report_peer(from.clone(), benefit::EXPECTED_MESSAGE);
let structurally_valid = para_id == &collation_para && acc_id == &collated_acc;
if structurally_valid && collation.receipt.check_signature().is_ok() {
debug!(target: "p_net", "Received collation for parachain {:?} from peer {}", para_id, from);
ctx.report_peer(from, benefit::GOOD_COLLATION);
self.collators.on_collation(acc_id.clone(), relay_parent, collation)
} else {
ctx.report_peer(from, cost::INVALID_FORMAT)
};
}
}
},
}
......
......@@ -16,6 +16,7 @@
//! Tests for polkadot and validation network.
use std::collections::HashMap;
use super::{PolkadotProtocol, Status, Message, FullStatus};
use validation::SessionParams;
......@@ -41,6 +42,7 @@ mod validation;
struct TestContext {
disabled: Vec<PeerId>,
disconnected: Vec<PeerId>,
reputations: HashMap<PeerId, i32>,
messages: Vec<(PeerId, Vec<u8>)>,
}
......@@ -50,6 +52,9 @@ impl Context<Block> for TestContext {
}
fn report_peer(&mut self, peer: PeerId, reputation: i32) {
let reputation = self.reputations.get(&peer).map_or(reputation, |v| v + reputation);
self.reputations.insert(peer.clone(), reputation);
match reputation {
i if i < -100 => self.disabled.push(peer),
i if i < 0 => self.disconnected.push(peer),
......@@ -306,6 +311,22 @@ fn remove_bad_collator() {
}
}
#[test]
fn kick_collator() {
let mut protocol = PolkadotProtocol::new(None);
let who = PeerId::random();
let collator_id: CollatorId = [2; 32].unchecked_into();
let mut ctx = TestContext::default();
let status = Status { collating_for: Some((collator_id.clone(), 5.into())) };
protocol.on_connect(&mut ctx, who.clone(), make_status(&status, Roles::NONE));
assert!(!ctx.disconnected.contains(&who));
protocol.on_connect(&mut ctx, who.clone(), make_status(&status, Roles::NONE));
assert!(ctx.disconnected.contains(&who));
}
#[test]
fn many_session_keys() {
let mut protocol = PolkadotProtocol::new(None);
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment