Skip to content
This repository was archived by the owner on Nov 15, 2023. It is now read-only.

Commit add8729

Browse files
arkpargavofyork
authored andcommitted
BFT delay adjustments (#593)
* force delay only on votes * set proposal timestamp forward * Adjusted timeout formula
1 parent 054ab79 commit add8729

File tree

3 files changed

+21
-27
lines changed

3 files changed

+21
-27
lines changed

polkadot/consensus/src/lib.rs

Lines changed: 13 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -63,7 +63,7 @@ extern crate substrate_keyring;
6363

6464
use std::collections::{HashMap, HashSet};
6565
use std::sync::Arc;
66-
use std::time::{Duration, Instant};
66+
use std::time::{self, Duration, Instant};
6767

6868
use codec::{Decode, Encode};
6969
use polkadot_api::PolkadotApi;
@@ -267,6 +267,9 @@ impl<C, N, P> bft::Environment<Block> for ProposerFactory<C, N, P>
267267
) -> Result<(Self::Proposer, Self::Input, Self::Output), Error> {
268268
use runtime_primitives::traits::{Hash as HashT, BlakeTwo256};
269269

270+
// force delay in evaluation this long.
271+
const FORCE_DELAY: Timestamp = 5;
272+
270273
let parent_hash = parent_header.hash().into();
271274

272275
let id = BlockId::hash(parent_hash);
@@ -330,6 +333,7 @@ impl<C, N, P> bft::Environment<Block> for ProposerFactory<C, N, P>
330333
transaction_pool: self.transaction_pool.clone(),
331334
offline: self.offline.clone(),
332335
validators,
336+
minimum_timestamp: current_timestamp() + FORCE_DELAY,
333337
_drop_signal: drop_signal,
334338
};
335339

@@ -386,6 +390,7 @@ pub struct Proposer<C: PolkadotApi> {
386390
transaction_pool: Arc<TransactionPool<C>>,
387391
offline: SharedOfflineTracker,
388392
validators: Vec<AccountId>,
393+
minimum_timestamp: u64,
389394
_drop_signal: exit_future::Signal,
390395
}
391396

@@ -437,6 +442,7 @@ impl<C> bft::Proposer<Block> for Proposer<C>
437442
table: self.table.clone(),
438443
offline: self.offline.clone(),
439444
validators: self.validators.clone(),
445+
minimum_timestamp: self.minimum_timestamp,
440446
timing,
441447
})
442448
}
@@ -489,9 +495,11 @@ impl<C> bft::Proposer<Block> for Proposer<C>
489495
);
490496

491497
// the duration until the given timestamp is current
492-
let proposed_timestamp = proposal.timestamp();
498+
let proposed_timestamp = ::std::cmp::max(self.minimum_timestamp, proposal.timestamp());
493499
let timestamp_delay = if proposed_timestamp > current_timestamp {
494-
Some(now + Duration::from_secs(proposed_timestamp - current_timestamp))
500+
let delay_s = proposed_timestamp - current_timestamp;
501+
debug!(target: "bft", "Delaying evaluation of proposal for {} seconds", delay_s);
502+
Some(now + Duration::from_secs(delay_s))
495503
} else {
496504
None
497505
};
@@ -642,8 +650,6 @@ impl<C> bft::Proposer<Block> for Proposer<C>
642650
}
643651

644652
fn current_timestamp() -> Timestamp {
645-
use std::time;
646-
647653
time::SystemTime::now().duration_since(time::UNIX_EPOCH)
648654
.expect("now always later than unix epoch; qed")
649655
.as_secs()
@@ -697,6 +703,7 @@ pub struct CreateProposal<C: PolkadotApi> {
697703
timing: ProposalTiming,
698704
validators: Vec<AccountId>,
699705
offline: SharedOfflineTracker,
706+
minimum_timestamp: Timestamp,
700707
}
701708

702709
impl<C> CreateProposal<C> where C: PolkadotApi {
@@ -708,7 +715,7 @@ impl<C> CreateProposal<C> where C: PolkadotApi {
708715
const MAX_VOTE_OFFLINE_SECONDS: Duration = Duration::from_secs(60);
709716

710717
// TODO: handle case when current timestamp behind that in state.
711-
let timestamp = current_timestamp();
718+
let timestamp = ::std::cmp::max(self.minimum_timestamp, current_timestamp());
712719

713720
let elapsed_since_start = self.timing.dynamic_inclusion.started_at().elapsed();
714721
let offline_indices = if elapsed_since_start > MAX_VOTE_OFFLINE_SECONDS {

polkadot/consensus/src/service.rs

Lines changed: 3 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ use transaction_pool::TransactionPool;
3838
use tokio::executor::current_thread::TaskExecutor as LocalThreadHandle;
3939
use tokio::runtime::TaskExecutor as ThreadPoolHandle;
4040
use tokio::runtime::current_thread::Runtime as LocalRuntime;
41-
use tokio::timer::{Delay, Interval};
41+
use tokio::timer::Interval;
4242

4343
use super::{Network, Collators, ProposerFactory};
4444
use error;
@@ -58,25 +58,10 @@ fn start_bft<F, C>(
5858
<F::Proposer as bft::Proposer<Block>>::Error: ::std::fmt::Display + Into<error::Error>,
5959
<F as bft::Environment<Block>>::Error: ::std::fmt::Display
6060
{
61-
const DELAY_UNTIL: Duration = Duration::from_millis(5000);
62-
6361
let mut handle = LocalThreadHandle::current();
6462
match bft_service.build_upon(&header) {
65-
Ok(Some(bft_work)) => {
66-
// do not poll work for some amount of time.
67-
let work = Delay::new(Instant::now() + DELAY_UNTIL).then(move |res| {
68-
if let Err(e) = res {
69-
warn!(target: "bft", "Failed to force delay of consensus: {:?}", e);
70-
}
71-
72-
debug!(target: "bft", "Starting agreement. After forced delay for {:?}",
73-
DELAY_UNTIL);
74-
75-
bft_work
76-
});
77-
if let Err(e) = handle.spawn_local(Box::new(work)) {
78-
warn!(target: "bft", "Couldn't initialize BFT agreement: {:?}", e);
79-
}
63+
Ok(Some(bft_work)) => if let Err(e) = handle.spawn_local(Box::new(bft_work)) {
64+
warn!(target: "bft", "Couldn't initialize BFT agreement: {:?}", e);
8065
}
8166
Ok(None) => trace!(target: "bft", "Could not start agreement on top of {}", header.hash()),
8267
Err(e) => warn!(target: "bft", "BFT agreement error: {}", e),

substrate/bft/src/lib.rs

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -237,10 +237,12 @@ impl<B: Block, P: Proposer<B>> BftInstance<B, P>
237237

238238
{
239239
fn round_timeout_duration(&self, round: usize) -> Duration {
240-
const ROUND_INCREMENT_STEP: usize = 10000;
240+
// 2^(min(6, x/8)) * 10
241+
// Grows exponentially starting from 10 seconds, capped at 640 seconds.
242+
const ROUND_INCREMENT_STEP: usize = 8;
241243

242244
let round = round / ROUND_INCREMENT_STEP;
243-
let round = ::std::cmp::min(63, round) as u32;
245+
let round = ::std::cmp::min(6, round) as u32;
244246

245247
let timeout = 1u64.checked_shl(round)
246248
.unwrap_or_else(u64::max_value)
@@ -867,7 +869,7 @@ mod tests {
867869
hash: None,
868870
start_round: 0,
869871
})),
870-
round_timeout_multiplier: 4,
872+
round_timeout_multiplier: 10,
871873
key: Arc::new(Keyring::One.into()),
872874
factory: DummyFactory
873875
}

0 commit comments

Comments
 (0)