From 9973432342c039041daecbd294fd72b601b5f5d9 Mon Sep 17 00:00:00 2001
From: Robert Habermeier <rphmeier@gmail.com>
Date: Wed, 27 Nov 2019 22:53:34 +0100
Subject: [PATCH] back-off block proposal (#4235)

---
 substrate/client/consensus/babe/src/lib.rs | 26 ++++++++++++++++++++++
 1 file changed, 26 insertions(+)

diff --git a/substrate/client/consensus/babe/src/lib.rs b/substrate/client/consensus/babe/src/lib.rs
index 3fd1e526d46..2c81367039a 100644
--- a/substrate/client/consensus/babe/src/lib.rs
+++ b/substrate/client/consensus/babe/src/lib.rs
@@ -453,6 +453,32 @@ impl<B, C, E, I, Error, SO> slots::SimpleSlotWorker<B> for BabeWorker<B, C, E, I
 			consensus_common::Error::ClientImport(format!("{:?}", e))
 		})
 	}
+
+	fn proposing_remaining_duration(
+		&self,
+		head: &B::Header,
+		slot_info: &SlotInfo
+	) -> Option<std::time::Duration> {
+		// never give more than 20 times more lenience.
+		const BACKOFF_CAP: u64 = 20;
+
+		let slot_remaining = self.slot_remaining_duration(slot_info);
+		let parent_slot = match find_pre_digest::<B>(head) {
+			Err(_) => return Some(slot_remaining),
+			Ok(d) => d.slot_number(),
+		};
+
+		// we allow a lenience of the number of slots since the head of the
+		// chain was produced, minus 1 (since there is always a difference of at least 1)
+		//
+		// linear back-off.
+		// in normal cases we only attempt to issue blocks up to the end of the slot.
+		// when the chain has been stalled for a few slots, we give more lenience.
+		let slot_lenience = slot_info.number.saturating_sub(parent_slot + 1);
+		let slot_lenience = std::cmp::min(slot_lenience, BACKOFF_CAP);
+		let slot_lenience = Duration::from_secs(slot_lenience * slot_info.duration);
+		Some(slot_lenience + slot_remaining)
+	}
 }
 
 impl<B, C, E, I, Error, SO> SlotWorker<B> for BabeWorker<B, C, E, I, SO> where
-- 
GitLab