Commit 292ed2cd authored by Arkadiy Paronyan's avatar Arkadiy Paronyan Committed by asynchronous rob
Browse files

BFT delay adjustments (#593)

* force delay only on votes

* set proposal timestamp forward

* Adjusted timeout formula
parent e7d3bf7d
...@@ -64,7 +64,7 @@ extern crate substrate_keyring; ...@@ -64,7 +64,7 @@ extern crate substrate_keyring;
use std::collections::{HashMap, HashSet}; use std::collections::{HashMap, HashSet};
use std::sync::Arc; use std::sync::Arc;
use std::time::{Duration, Instant}; use std::time::{self, Duration, Instant};
use codec::{Decode, Encode}; use codec::{Decode, Encode};
use extrinsic_store::Store as ExtrinsicStore; use extrinsic_store::Store as ExtrinsicStore;
...@@ -274,6 +274,9 @@ impl<C, N, P> bft::Environment<Block> for ProposerFactory<C, N, P> ...@@ -274,6 +274,9 @@ impl<C, N, P> bft::Environment<Block> for ProposerFactory<C, N, P>
) -> Result<(Self::Proposer, Self::Input, Self::Output), Error> { ) -> Result<(Self::Proposer, Self::Input, Self::Output), Error> {
use runtime_primitives::traits::{Hash as HashT, BlakeTwo256}; use runtime_primitives::traits::{Hash as HashT, BlakeTwo256};
// force delay in evaluation this long.
const FORCE_DELAY: Timestamp = 5;
let parent_hash = parent_header.hash().into(); let parent_hash = parent_header.hash().into();
let id = BlockId::hash(parent_hash); let id = BlockId::hash(parent_hash);
...@@ -343,6 +346,7 @@ impl<C, N, P> bft::Environment<Block> for ProposerFactory<C, N, P> ...@@ -343,6 +346,7 @@ impl<C, N, P> bft::Environment<Block> for ProposerFactory<C, N, P>
transaction_pool: self.transaction_pool.clone(), transaction_pool: self.transaction_pool.clone(),
offline: self.offline.clone(), offline: self.offline.clone(),
validators, validators,
minimum_timestamp: current_timestamp() + FORCE_DELAY,
_drop_signal: drop_signal, _drop_signal: drop_signal,
}; };
...@@ -422,6 +426,7 @@ pub struct Proposer<C: PolkadotApi + Send + Sync> { ...@@ -422,6 +426,7 @@ pub struct Proposer<C: PolkadotApi + Send + Sync> {
transaction_pool: Arc<TransactionPool<C>>, transaction_pool: Arc<TransactionPool<C>>,
offline: SharedOfflineTracker, offline: SharedOfflineTracker,
validators: Vec<AccountId>, validators: Vec<AccountId>,
minimum_timestamp: u64,
_drop_signal: exit_future::Signal, _drop_signal: exit_future::Signal,
} }
...@@ -473,6 +478,7 @@ impl<C> bft::Proposer<Block> for Proposer<C> ...@@ -473,6 +478,7 @@ impl<C> bft::Proposer<Block> for Proposer<C>
table: self.table.clone(), table: self.table.clone(),
offline: self.offline.clone(), offline: self.offline.clone(),
validators: self.validators.clone(), validators: self.validators.clone(),
minimum_timestamp: self.minimum_timestamp,
timing, timing,
}) })
} }
...@@ -525,9 +531,11 @@ impl<C> bft::Proposer<Block> for Proposer<C> ...@@ -525,9 +531,11 @@ impl<C> bft::Proposer<Block> for Proposer<C>
); );
// the duration until the given timestamp is current // the duration until the given timestamp is current
let proposed_timestamp = proposal.timestamp(); let proposed_timestamp = ::std::cmp::max(self.minimum_timestamp, proposal.timestamp());
let timestamp_delay = if proposed_timestamp > current_timestamp { let timestamp_delay = if proposed_timestamp > current_timestamp {
Some(now + Duration::from_secs(proposed_timestamp - current_timestamp)) let delay_s = proposed_timestamp - current_timestamp;
debug!(target: "bft", "Delaying evaluation of proposal for {} seconds", delay_s);
Some(now + Duration::from_secs(delay_s))
} else { } else {
None None
}; };
...@@ -677,8 +685,6 @@ impl<C> bft::Proposer<Block> for Proposer<C> ...@@ -677,8 +685,6 @@ impl<C> bft::Proposer<Block> for Proposer<C>
} }
fn current_timestamp() -> Timestamp { fn current_timestamp() -> Timestamp {
use std::time;
time::SystemTime::now().duration_since(time::UNIX_EPOCH) time::SystemTime::now().duration_since(time::UNIX_EPOCH)
.expect("now always later than unix epoch; qed") .expect("now always later than unix epoch; qed")
.as_secs() .as_secs()
...@@ -732,6 +738,7 @@ pub struct CreateProposal<C: PolkadotApi + Send + Sync> { ...@@ -732,6 +738,7 @@ pub struct CreateProposal<C: PolkadotApi + Send + Sync> {
timing: ProposalTiming, timing: ProposalTiming,
validators: Vec<AccountId>, validators: Vec<AccountId>,
offline: SharedOfflineTracker, offline: SharedOfflineTracker,
minimum_timestamp: Timestamp,
} }
impl<C> CreateProposal<C> where C: PolkadotApi + Send + Sync { impl<C> CreateProposal<C> where C: PolkadotApi + Send + Sync {
...@@ -743,7 +750,7 @@ impl<C> CreateProposal<C> where C: PolkadotApi + Send + Sync { ...@@ -743,7 +750,7 @@ impl<C> CreateProposal<C> where C: PolkadotApi + Send + Sync {
const MAX_VOTE_OFFLINE_SECONDS: Duration = Duration::from_secs(60); const MAX_VOTE_OFFLINE_SECONDS: Duration = Duration::from_secs(60);
// TODO: handle case when current timestamp behind that in state. // TODO: handle case when current timestamp behind that in state.
let timestamp = current_timestamp(); let timestamp = ::std::cmp::max(self.minimum_timestamp, current_timestamp());
let elapsed_since_start = self.timing.dynamic_inclusion.started_at().elapsed(); let elapsed_since_start = self.timing.dynamic_inclusion.started_at().elapsed();
let offline_indices = if elapsed_since_start > MAX_VOTE_OFFLINE_SECONDS { let offline_indices = if elapsed_since_start > MAX_VOTE_OFFLINE_SECONDS {
......
...@@ -39,7 +39,7 @@ use extrinsic_store::Store as ExtrinsicStore; ...@@ -39,7 +39,7 @@ use extrinsic_store::Store as ExtrinsicStore;
use tokio::executor::current_thread::TaskExecutor as LocalThreadHandle; use tokio::executor::current_thread::TaskExecutor as LocalThreadHandle;
use tokio::runtime::TaskExecutor as ThreadPoolHandle; use tokio::runtime::TaskExecutor as ThreadPoolHandle;
use tokio::runtime::current_thread::Runtime as LocalRuntime; use tokio::runtime::current_thread::Runtime as LocalRuntime;
use tokio::timer::{Delay, Interval}; use tokio::timer::Interval;
use super::{Network, Collators, ProposerFactory}; use super::{Network, Collators, ProposerFactory};
use error; use error;
...@@ -59,25 +59,10 @@ fn start_bft<F, C>( ...@@ -59,25 +59,10 @@ fn start_bft<F, C>(
<F::Proposer as bft::Proposer<Block>>::Error: ::std::fmt::Display + Into<error::Error>, <F::Proposer as bft::Proposer<Block>>::Error: ::std::fmt::Display + Into<error::Error>,
<F as bft::Environment<Block>>::Error: ::std::fmt::Display <F as bft::Environment<Block>>::Error: ::std::fmt::Display
{ {
const DELAY_UNTIL: Duration = Duration::from_millis(5000);
let mut handle = LocalThreadHandle::current(); let mut handle = LocalThreadHandle::current();
match bft_service.build_upon(&header) { match bft_service.build_upon(&header) {
Ok(Some(bft_work)) => { Ok(Some(bft_work)) => if let Err(e) = handle.spawn_local(Box::new(bft_work)) {
// do not poll work for some amount of time. warn!(target: "bft", "Couldn't initialize BFT agreement: {:?}", e);
let work = Delay::new(Instant::now() + DELAY_UNTIL).then(move |res| {
if let Err(e) = res {
warn!(target: "bft", "Failed to force delay of consensus: {:?}", e);
}
debug!(target: "bft", "Starting agreement. After forced delay for {:?}",
DELAY_UNTIL);
bft_work
});
if let Err(e) = handle.spawn_local(Box::new(work)) {
warn!(target: "bft", "Couldn't initialize BFT agreement: {:?}", e);
}
} }
Ok(None) => trace!(target: "bft", "Could not start agreement on top of {}", header.hash()), Ok(None) => trace!(target: "bft", "Could not start agreement on top of {}", header.hash()),
Err(e) => warn!(target: "bft", "BFT agreement error: {}", e), Err(e) => warn!(target: "bft", "BFT agreement error: {}", e),
......
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