Skip to content

Commit 559fe91

Browse files
committed
Make the acceptable time gaps configurable
1 parent 85eb27a commit 559fe91

File tree

12 files changed

+103
-14
lines changed

12 files changed

+103
-14
lines changed

codechain/codechain.yml

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,16 @@ version_short: "v"
33
author: CodeChain Team <[email protected]>
44
about: CodeChian client
55
args:
6+
- allowed-future-gap:
7+
long: allowed-future-gap
8+
value_name: MS
9+
help: Specify the allowed gap in the future direction from the system time to the block generation time. MS is time measured in milliseconds.
10+
takes_value: true
11+
- allowed-past-gap:
12+
long: allowed-past-gap
13+
value_name: MS
14+
help: Specify the allowed gap in the past direction from the system time to the block generation time. MS is time measured in milliseconds.
15+
takes_value: true
616
- config:
717
long: config
818
help: Specify the certain config file path that you want to use to configure CodeChain to your needs.

codechain/config/mod.rs

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ use std::fs;
2020
use std::str::{self, FromStr};
2121
use std::time::Duration;
2222

23-
use ccore::{MinerOptions, StratumConfig};
23+
use ccore::{MinerOptions, StratumConfig, TimeGapParams};
2424
use cidr::IpCidr;
2525
use ckey::PlatformAddress;
2626
use clap;
@@ -226,6 +226,8 @@ pub struct Mining {
226226
pub reseal_max_period: Option<u64>,
227227
pub no_reseal_timer: Option<bool>,
228228
pub work_queue_size: Option<usize>,
229+
pub allowed_past_gap: Option<u64>,
230+
pub allowed_future_gap: Option<u64>,
229231
}
230232

231233
#[derive(Deserialize)]
@@ -446,8 +448,24 @@ impl Mining {
446448
if let Some(work_queue_size) = matches.value_of("work-queue-size") {
447449
self.work_queue_size = Some(work_queue_size.parse().map_err(|_| "Invalid size")?);
448450
}
451+
if let Some(allowed_past_gap) = matches.value_of("allowed-past-gap") {
452+
self.allowed_past_gap = Some(allowed_past_gap.parse().map_err(|_| "Invalid time gap")?);
453+
}
454+
if let Some(allowed_future_gap) = matches.value_of("allowed-future-gap") {
455+
self.allowed_future_gap = Some(allowed_future_gap.parse().map_err(|_| "Invalid time gap")?);
456+
}
449457
Ok(())
450458
}
459+
460+
pub fn create_time_gaps(&self) -> TimeGapParams {
461+
let allowed_past_gap = Duration::from_millis(self.allowed_past_gap.unwrap_or(30000));
462+
let allowed_future_gap = Duration::from_millis(self.allowed_future_gap.unwrap_or(5000));
463+
464+
TimeGapParams {
465+
allowed_past_gap,
466+
allowed_future_gap,
467+
}
468+
}
451469
}
452470

453471
impl Network {

codechain/config/presets/config.dev.toml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,8 @@ reseal_min_period = 0
1616
reseal_max_period = 120000
1717
no_reseal_timer = false
1818
work_queue_size = 20
19+
allowed_past_gap = 30000
20+
allowed_future_gap = 5000
1921

2022
[network]
2123
disable = false

codechain/config/presets/config.prod.toml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,8 @@ reseal_min_period = 4000
1616
reseal_max_period = 120000
1717
no_reseal_timer = false
1818
work_queue_size = 20
19+
allowed_past_gap = 30000
20+
allowed_future_gap = 5000
1921

2022
[network]
2123
disable = false

codechain/run_node.rs

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -225,10 +225,27 @@ pub fn run_node(matches: &ArgMatches) -> Result<(), String> {
225225

226226
let config = load_config(matches)?;
227227

228+
<<<<<<< HEAD
229+
=======
230+
// FIXME: It is the hotfix for #348.
231+
// Remove the below code if you find the proper way to solve #348.
232+
let _wait = finally(|| {
233+
const DEFAULT: u64 = 1;
234+
let wait_before_shutdown = env::var_os("WAIT_BEFORE_SHUTDOWN")
235+
.and_then(|sec| sec.into_string().ok())
236+
.and_then(|sec| sec.parse().ok())
237+
.unwrap_or(DEFAULT);
238+
::std::thread::sleep(Duration::from_secs(wait_before_shutdown));
239+
});
240+
241+
let time_gap_params = config.mining.create_time_gaps();
242+
243+
>>>>>>> Make the acceptable time gaps configurable
228244
let scheme = match &config.operating.chain {
229245
Some(chain) => chain.scheme()?,
230246
None => return Err("chain is not specified".to_string()),
231247
};
248+
scheme.engine.register_time_gap_config_to_worker(time_gap_params);
232249

233250
let instance_id = config.operating.instance_id.unwrap_or(
234251
SystemTime::now()

core/src/consensus/mod.rs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ pub use self::cuckoo::Cuckoo;
3131
pub use self::null_engine::NullEngine;
3232
pub use self::simple_poa::SimplePoA;
3333
pub use self::solo::Solo;
34-
pub use self::tendermint::{Tendermint, TendermintParams};
34+
pub use self::tendermint::{Tendermint, TendermintParams, TimeGapParams};
3535
pub use self::validator_set::validator_list::ValidatorList;
3636
pub use self::validator_set::ValidatorSet;
3737

@@ -255,6 +255,8 @@ pub trait ConsensusEngine<M: Machine>: Sync + Send {
255255

256256
fn register_network_extension_to_service(&self, _: &NetworkService) {}
257257

258+
fn register_time_gap_config_to_worker(&self, _time_gap_params: TimeGapParams) {}
259+
258260
fn score_to_target(&self, _score: &U256) -> U256 {
259261
U256::zero()
260262
}

core/src/consensus/tendermint/engine.rs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@ use crate::consensus::EngineType;
4040
use crate::error::Error;
4141
use crate::header::Header;
4242
use crate::views::HeaderView;
43+
use consensus::tendermint::params::TimeGapParams;
4344

4445
impl ConsensusEngine<CodeChainMachine> for Tendermint {
4546
fn name(&self) -> &str {
@@ -226,6 +227,10 @@ impl ConsensusEngine<CodeChainMachine> for Tendermint {
226227
receiver.recv().unwrap();
227228
}
228229

230+
fn register_time_gap_config_to_worker(&self, time_gap_params: TimeGapParams) {
231+
self.external_params_initializer.send(time_gap_params).unwrap();
232+
}
233+
229234
fn block_reward(&self, _block_number: u64) -> u64 {
230235
self.block_reward
231236
}

core/src/consensus/tendermint/mod.rs

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ use parking_lot::RwLock;
3434
use primitives::H256;
3535

3636
use self::chain_notify::TendermintChainNotify;
37-
pub use self::params::{TendermintParams, TimeoutParams};
37+
pub use self::params::{TendermintParams, TimeGapParams, TimeoutParams};
3838
use self::types::{Height, Step, View};
3939
use super::stake;
4040
use crate::client::EngineClient;
@@ -56,6 +56,7 @@ pub type BlockHash = H256;
5656
/// ConsensusEngine using `Tendermint` consensus algorithm
5757
pub struct Tendermint {
5858
client: RwLock<Option<Weak<EngineClient>>>,
59+
external_params_initializer: crossbeam::Sender<TimeGapParams>,
5960
extension_initializer: crossbeam::Sender<(crossbeam::Sender<network::Event>, Weak<EngineClient>)>,
6061
timeouts: TimeoutParams,
6162
join: Option<JoinHandle<()>>,
@@ -89,12 +90,14 @@ impl Tendermint {
8990
let timeouts = our_params.timeouts;
9091
let machine = Arc::new(machine);
9192

92-
let (join, extension_initializer, inner, quit_tendermint) = worker::spawn(our_params.validators);
93+
let (join, external_params_initializer, extension_initializer, inner, quit_tendermint) =
94+
worker::spawn(our_params.validators);
9395
let action_handlers: Vec<Arc<ActionHandler>> = vec![Arc::new(stake)];
9496
let chain_notify = Arc::new(TendermintChainNotify::new(inner.clone()));
9597

9698
Arc::new(Tendermint {
9799
client: Default::default(),
100+
external_params_initializer,
98101
extension_initializer,
99102
timeouts,
100103
join: Some(join),
@@ -170,7 +173,13 @@ mod tests {
170173

171174
#[test]
172175
fn has_valid_metadata() {
176+
use std::time::Duration;
173177
let engine = Scheme::new_test_tendermint().engine;
178+
let time_gap_params = TimeGapParams {
179+
allowed_past_gap: Duration::from_millis(30000),
180+
allowed_future_gap: Duration::from_millis(5000),
181+
};
182+
engine.register_time_gap_config_to_worker(time_gap_params);
174183
assert!(!engine.name().is_empty());
175184
}
176185

core/src/consensus/tendermint/params.rs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,11 @@ fn to_duration(ms: cjson::uint::Uint) -> Duration {
6767
Duration::from_millis(ms as u64)
6868
}
6969

70+
pub struct TimeGapParams {
71+
pub allowed_past_gap: Duration,
72+
pub allowed_future_gap: Duration,
73+
}
74+
7075
/// Base timeout of each step in ms.
7176
#[derive(Debug, Copy, Clone)]
7277
pub struct TimeoutParams {

core/src/consensus/tendermint/worker.rs

Lines changed: 24 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ use rlp::{Encodable, UntrustedRlp};
3232
use super::backup::{backup, restore, BackupView};
3333
use super::message::*;
3434
use super::network;
35+
use super::params::TimeGapParams;
3536
use super::types::{BitSet, Height, Proposal, Step, TendermintSealView, TendermintState, TwoThirdsMajority, View};
3637
use super::{
3738
BlockHash, ENGINE_TIMEOUT_BROADCAST_STEP_STATE, ENGINE_TIMEOUT_EMPTY_PROPOSAL, ENGINE_TIMEOUT_TOKEN_NONCE_BASE,
@@ -52,6 +53,7 @@ use crate::BlockId;
5253

5354
type SpawnResult = (
5455
JoinHandle<()>,
56+
crossbeam::Sender<TimeGapParams>,
5557
crossbeam::Sender<(crossbeam::Sender<network::Event>, Weak<EngineClient>)>,
5658
crossbeam::Sender<Event>,
5759
crossbeam::Sender<()>,
@@ -87,7 +89,7 @@ struct Worker {
8789
validators: Arc<ValidatorSet>,
8890
/// Channel to the network extension, must be set later.
8991
extension: EventSender<network::Event>,
90-
92+
time_gap_params: TimeGapParams,
9193
timeout_token_nonce: usize,
9294
}
9395

@@ -167,7 +169,12 @@ pub enum Event {
167169
impl Worker {
168170
#![cfg_attr(feature = "cargo-clippy", allow(clippy::new_ret_no_self))]
169171
/// Create a new instance of Tendermint engine
170-
fn new(validators: Arc<ValidatorSet>, extension: EventSender<network::Event>, client: Weak<EngineClient>) -> Self {
172+
fn new(
173+
validators: Arc<ValidatorSet>,
174+
extension: EventSender<network::Event>,
175+
client: Weak<EngineClient>,
176+
time_gap_params: TimeGapParams,
177+
) -> Self {
171178
Worker {
172179
client,
173180
height: 1,
@@ -182,18 +189,26 @@ impl Worker {
182189
extension,
183190
votes_received: BitSet::new(),
184191
votes_received_changed: false,
185-
192+
time_gap_params,
186193
timeout_token_nonce: ENGINE_TIMEOUT_TOKEN_NONCE_BASE,
187194
}
188195
}
189196

190197
fn spawn(validators: Arc<ValidatorSet>) -> SpawnResult {
191198
let (sender, receiver) = crossbeam::unbounded();
192199
let (quit, quit_receiver) = crossbeam::bounded(1);
200+
let (external_params_initializer, external_params_receiver) = crossbeam::bounded(1);
193201
let (extension_initializer, extension_receiver) = crossbeam::bounded(1);
194202
let join = Builder::new()
195203
.name("tendermint".to_string())
196204
.spawn(move || {
205+
let time_gap_params = match external_params_receiver.recv() {
206+
Ok(time_gap_params) => time_gap_params,
207+
Err(crossbeam::RecvError) => {
208+
cerror!(ENGINE, "The tendermint external parameters are not initialized");
209+
return
210+
}
211+
};
197212
let (extension, client) = crossbeam::select! {
198213
recv(extension_receiver) -> msg => {
199214
match msg {
@@ -215,7 +230,7 @@ impl Worker {
215230
}
216231
};
217232
validators.register_client(Weak::clone(&client));
218-
let mut inner = Self::new(validators, extension, client);
233+
let mut inner = Self::new(validators, extension, client, time_gap_params);
219234
loop {
220235
crossbeam::select! {
221236
recv(receiver) -> msg => {
@@ -342,7 +357,7 @@ impl Worker {
342357
}
343358
})
344359
.unwrap();
345-
(join, extension_initializer, sender, quit)
360+
(join, external_params_initializer, extension_initializer, sender, quit)
346361
}
347362

348363
/// The client is a thread-safe struct. Using it in multi-threads is safe.
@@ -693,11 +708,11 @@ impl Worker {
693708
}
694709

695710
fn is_generation_time_relevant(&self, block_header: &Header) -> bool {
696-
const ACCEPTABLE_FUTURE_GAP: Duration = Duration::from_secs(5);
697-
const ACCEPTABLE_PAST_GAP: Duration = Duration::from_secs(30);
711+
let acceptable_past_gap = self.time_gap_params.allowed_past_gap;
712+
let acceptable_future_gap = self.time_gap_params.allowed_future_gap;
698713
let now = SystemTime::now();
699-
let allowed_min = now - ACCEPTABLE_PAST_GAP;
700-
let allowed_max = now + ACCEPTABLE_FUTURE_GAP;
714+
let allowed_min = now - acceptable_past_gap;
715+
let allowed_max = now + acceptable_future_gap;
701716
let block_generation_time = UNIX_EPOCH.checked_add(Duration::from_secs(block_header.timestamp()));
702717

703718
match block_generation_time {

0 commit comments

Comments
 (0)