diff --git a/ethcore/src/engines/tendermint/params.rs b/ethcore/src/engines/tendermint/params.rs index 904499c04..4e3996c99 100644 --- a/ethcore/src/engines/tendermint/params.rs +++ b/ethcore/src/engines/tendermint/params.rs @@ -17,7 +17,7 @@ //! Tendermint specific parameters. use ethjson; -use super::timeout::DefaultTimeouts; +use super::timeout::TendermintTimeouts; use util::{Address, U256}; /// `Tendermint` params. @@ -30,7 +30,7 @@ pub struct TendermintParams { /// Number of authorities. pub authority_n: usize, /// Timeout durations for different steps. - pub timeouts: DefaultTimeouts, + pub timeouts: TendermintTimeouts, } impl Default for TendermintParams { @@ -54,7 +54,13 @@ impl From for TendermintParams { gas_limit_bound_divisor: p.gas_limit_bound_divisor.into(), authorities: val, authority_n: val_n, - timeouts: DefaultTimeouts::default() + let dt = TendermintTimeouts::default(); + timeouts: TendermintTimeouts { + propose: p.timeout_propose.unwrap_or(dt.propose), + prevote: p.timeout_prevote.unwrap_or(dt.prevote), + precommit: p.timeout_precommit.unwrap_or(dt.precommit), + commit: p.timeout_commit.unwrap_or(dt.commit) + } } } } diff --git a/ethcore/src/engines/tendermint/timeout.rs b/ethcore/src/engines/tendermint/timeout.rs index 52d1bd2d0..f107d06ee 100644 --- a/ethcore/src/engines/tendermint/timeout.rs +++ b/ethcore/src/engines/tendermint/timeout.rs @@ -20,7 +20,8 @@ use std::sync::atomic::{Ordering as AtomicOrdering}; use std::sync::Weak; use io::{IoContext, IoHandler, TimerToken}; use super::{Tendermint, Step}; -use time::get_time; +use time::{get_time, Duration}; +use service::ClientIoMessage; pub struct TimerHandler { engine: Weak, @@ -28,41 +29,50 @@ pub struct TimerHandler { /// Base timeout of each step in ms. #[derive(Debug, Clone)] -pub struct DefaultTimeouts { - pub propose: Ms, - pub prevote: Ms, - pub precommit: Ms, - pub commit: Ms +pub struct TendermintTimeouts { + propose: Duration, + prevote: Duartion, + precommit: Duration, + commit: Duration } -impl Default for DefaultTimeouts { - fn default() -> Self { - DefaultTimeouts { - propose: 1000, - prevote: 1000, - precommit: 1000, - commit: 1000 +impl TendermintTimeouts { + pub fn for_step(step: Step) -> Duration { + match step { + Step::Propose => self.propose, + Step::Prevote => self.prevote, + Step::Precommit => self.precommit, + Step::Commit => self.commit, } } } -pub type Ms = usize; +impl Default for TendermintTimeouts { + fn default() -> Self { + DefaultTimeouts { + propose: Duration::milliseconds(1000), + prevote: Duration::milliseconds(1000), + precommit: Duration::milliseconds(1000), + commit: Duration::milliseconds(1000) + } + } +} #[derive(Clone)] pub struct NextStep; /// Timer token representing the consensus step timeouts. -pub const ENGINE_TIMEOUT_TOKEN: TimerToken = 0; +pub const ENGINE_TIMEOUT_TOKEN: TimerToken = 23; impl IoHandler for TimerHandler { - fn initialize(&self, io: &IoContext) { + fn initialize(&self, io: &IoContext) { if let Some(engine) = self.engine.upgrade() { io.register_timer_once(ENGINE_TIMEOUT_TOKEN, engine.remaining_step_duration().as_millis()) .unwrap_or_else(|e| warn!(target: "poa", "Failed to start consensus step timer: {}.", e)) } } - fn timeout(&self, io: &IoContext, timer: TimerToken) { + fn timeout(&self, io: &IoContext, timer: TimerToken) { if timer == ENGINE_TIMEOUT_TOKEN { if let Some(engine) = self.engine.upgrade() { engine.step.fetch_add(1, AtomicOrdering::SeqCst); @@ -77,14 +87,17 @@ impl IoHandler for TimerHandler { }, }; + + io.register_timer_once(ENGINE_TIMEOUT_TOKEN, engine.next_timeout().as_millis()) + .unwrap_or_else(|e| warn!(target: "poa", "Failed to restart consensus step timer: {}.", e)) + if let Some(ref channel) = *engine.message_channel.lock() { match channel.send(ClientIoMessage::UpdateSealing) { - Ok(_) => trace!(target: "poa", "timeout: UpdateSealing message sent for step {}.", engine.step.load(AtomicOrdering::Relaxed)), + Ok(_) => trace!(target: "poa", "timeout: UpdateSealing message sent for step {}.", engine.step.), Err(err) => trace!(target: "poa", "timeout: Could not send a sealing message {} for step {}.", err, engine.step.load(AtomicOrdering::Relaxed)), } } - io.register_timer_once(ENGINE_TIMEOUT_TOKEN, engine.next_timeout().as_millis()) - .unwrap_or_else(|e| warn!(target: "poa", "Failed to restart consensus step timer: {}.", e)) + } } } diff --git a/json/src/spec/tendermint.rs b/json/src/spec/tendermint.rs index 3d1a5a06d..6858602da 100644 --- a/json/src/spec/tendermint.rs +++ b/json/src/spec/tendermint.rs @@ -27,6 +27,18 @@ pub struct TendermintParams { pub gas_limit_bound_divisor: Uint, /// Valid authorities pub authorities: Vec
, + /// Propose step timeout in milliseconds. + #[serde(rename="timeoutPropose")] + pub timeout_propose: Option, + /// Prevote step timeout in milliseconds. + #[serde(rename="timeoutPrevote")] + pub timeout_prevote: Option, + /// Precommit step timeout in milliseconds. + #[serde(rename="timeoutPrecommit")] + pub timeout_precommit: Option, + /// Commit step timeout in milliseconds. + #[serde(rename="timeoutCommit")] + pub timeout_commit: Option, } /// Tendermint engine deserialization.