From e73436d81844af24b291e29d04ff09330fd4b043 Mon Sep 17 00:00:00 2001
From: Arkadiy Paronyan <arkady.paronyan@gmail.com>
Date: Thu, 7 Nov 2019 12:00:14 +0100
Subject: [PATCH] Decrease peer reputation on bad transactions (#4035)

* Decrease reputation on bad transactions

* Don't punish on duplicate transactions
---
 substrate/core/network/src/protocol.rs |  7 +++++--
 substrate/core/network/src/service.rs  |  3 ++-
 substrate/core/network/src/test/mod.rs |  9 ++++++++-
 substrate/core/service/src/lib.rs      | 16 +++++++++++++---
 4 files changed, 28 insertions(+), 7 deletions(-)

diff --git a/substrate/core/network/src/protocol.rs b/substrate/core/network/src/protocol.rs
index 8b3b5a49e40..35de679489e 100644
--- a/substrate/core/network/src/protocol.rs
+++ b/substrate/core/network/src/protocol.rs
@@ -90,7 +90,9 @@ const UNEXPECTED_STATUS_REPUTATION_CHANGE: i32 = -(1 << 20);
 /// Reputation change when we are a light client and a peer is behind us.
 const PEER_BEHIND_US_LIGHT_REPUTATION_CHANGE: i32 = -(1 << 8);
 /// Reputation change when a peer sends us an extrinsic that we didn't know about.
-const NEW_EXTRINSIC_REPUTATION_CHANGE: i32 = 1 << 7;
+const GOOD_EXTRINSIC_REPUTATION_CHANGE: i32 = 1 << 7;
+/// Reputation change when a peer sends us a bad extrinsic.
+const BAD_EXTRINSIC_REPUTATION_CHANGE: i32 = -(1 << 12);
 /// We sent an RPC query to the given node, but it failed.
 const RPC_FAILED_REPUTATION_CHANGE: i32 = -(1 << 12);
 /// We received a message that failed to decode.
@@ -1019,7 +1021,8 @@ impl<B: BlockT, S: NetworkSpecialization<B>, H: ExHashT> Protocol<B, S, H> {
 				self.transaction_pool.import(
 					self.peerset_handle.clone().into(),
 					who.clone(),
-					NEW_EXTRINSIC_REPUTATION_CHANGE,
+					GOOD_EXTRINSIC_REPUTATION_CHANGE,
+					BAD_EXTRINSIC_REPUTATION_CHANGE,
 					t,
 				);
 			}
diff --git a/substrate/core/network/src/service.rs b/substrate/core/network/src/service.rs
index a88c163a691..e73bff9b1cd 100644
--- a/substrate/core/network/src/service.rs
+++ b/substrate/core/network/src/service.rs
@@ -71,7 +71,8 @@ pub trait TransactionPool<H: ExHashT, B: BlockT>: Send + Sync {
 		&self,
 		report_handle: ReportHandle,
 		who: PeerId,
-		reputation_change: i32,
+		reputation_change_good: i32,
+		reputation_change_bad: i32,
 		transaction: B::Extrinsic,
 	);
 	/// Notify the pool about transactions broadcast.
diff --git a/substrate/core/network/src/test/mod.rs b/substrate/core/network/src/test/mod.rs
index 0c50179f10a..330988169db 100644
--- a/substrate/core/network/src/test/mod.rs
+++ b/substrate/core/network/src/test/mod.rs
@@ -399,7 +399,14 @@ impl TransactionPool<Hash, Block> for EmptyTransactionPool {
 		Hash::default()
 	}
 
-	fn import(&self, _report_handle: ReportHandle, _who: PeerId, _rep_change: i32, _transaction: Extrinsic) {}
+	fn import(
+		&self,
+		_report_handle: ReportHandle,
+		_who: PeerId,
+		_rep_change_good: i32,
+		_rep_change_bad: i32,
+		_transaction: Extrinsic
+	) {}
 
 	fn on_broadcasted(&self, _: HashMap<Hash, Vec<String>>) {}
 }
diff --git a/substrate/core/service/src/lib.rs b/substrate/core/service/src/lib.rs
index d09fcb093b2..b267e0a635b 100644
--- a/substrate/core/service/src/lib.rs
+++ b/substrate/core/service/src/lib.rs
@@ -615,7 +615,14 @@ where
 		self.pool.hash_of(transaction)
 	}
 
-	fn import(&self, report_handle: ReportHandle, who: PeerId, reputation_change: i32, transaction: B::Extrinsic) {
+	fn import(
+		&self,
+		report_handle: ReportHandle,
+		who: PeerId,
+		reputation_change_good: i32,
+		reputation_change_bad: i32,
+		transaction: B::Extrinsic
+	) {
 		if !self.imports_external_transactions {
 			debug!("Transaction rejected");
 			return;
@@ -629,10 +636,13 @@ where
 				let import_future = import_future
 					.then(move |import_result| {
 						match import_result {
-							Ok(_) => report_handle.report_peer(who, reputation_change),
+							Ok(_) => report_handle.report_peer(who, reputation_change_good),
 							Err(e) => match e.into_pool_error() {
 								Ok(txpool::error::Error::AlreadyImported(_)) => (),
-								Ok(e) => debug!("Error adding transaction to the pool: {:?}", e),
+								Ok(e) => {
+									report_handle.report_peer(who, reputation_change_bad);
+									debug!("Error adding transaction to the pool: {:?}", e)
+								}
 								Err(e) => debug!("Error converting pool error: {:?}", e),
 							}
 						}
-- 
GitLab