1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79
use crate::{NodeCount, NodeIndex, Round, SessionId};
use std::{sync::Arc, time::Duration};
pub type DelaySchedule = Arc<dyn Fn(usize) -> Duration + Sync + Send + 'static>;
/// Configuration of several parameters related to delaying various tasks.
#[derive(Clone)]
pub struct DelayConfig {
/// Tick frequency of the Member. Governs internal task queue of the Member.
pub tick_interval: Duration,
/// After what delay, we repeat a request for a coord or parents.
pub requests_interval: Duration,
/// DelaySchedule(k) represents the delay between the kth and (k+1)th broadcast.
pub unit_broadcast_delay: DelaySchedule,
/// DelaySchedule(k) represents the delay between creating the (k-1)th and kth unit.
pub unit_creation_delay: DelaySchedule,
}
/// Main configuration of the consensus. We refer to [the documentation](https://cardinal-cryptography.github.io/AlephBFT/aleph_bft_api.html#34-alephbft-sessions)
/// Section 3.4 for a discussion of some of these parameters and their significance.
#[derive(Clone)]
pub struct Config {
/// Identification number of the Member=0,..,(n_members-1).
pub node_ix: NodeIndex,
/// Id of the session for which this instance is run.
pub session_id: SessionId,
/// The size of the committee running the consensus.
pub n_members: NodeCount,
/// Configuration of several parameters related to delaying various tasks.
pub delay_config: DelayConfig,
/// Maximum allowable round of a unit.
pub max_round: Round,
}
pub fn exponential_slowdown(
t: usize,
base_delay: f64,
start_exp_delay: usize,
exp_base: f64,
) -> Duration {
// This gives:
// base_delay, for t <= start_exp_delay,
// base_delay * exp_base^(t - start_exp_delay), for t > start_exp_delay.
let delay = if t < start_exp_delay {
base_delay
} else {
let power = t - start_exp_delay;
base_delay * exp_base.powf(power as f64)
};
let delay = delay.round() as u64;
// the above will make it u64::MAX if it exceeds u64
Duration::from_millis(delay)
}
/// A default configuration of what the creators of this package see as optimal parameters.
pub fn default_config(n_members: NodeCount, node_ix: NodeIndex, session_id: SessionId) -> Config {
let unit_creation_delay = Arc::new(|t| {
if t == 0 {
Duration::from_millis(5000)
} else {
exponential_slowdown(t, 500.0, 3000, 1.005)
}
});
let delay_config = DelayConfig {
tick_interval: Duration::from_millis(100),
requests_interval: Duration::from_millis(3000),
unit_broadcast_delay: Arc::new(|t| exponential_slowdown(t, 4000.0, 0, 2.0)),
// 4000, 8000, 16000, 32000, ...
unit_creation_delay,
// 5000, 500, 500, 500, ... (till step 3000), 500, 500*1.005, 500*(1.005)^2, 500*(1.005)^3, ..., 10742207 (last step)
};
Config {
node_ix,
session_id,
n_members,
delay_config,
max_round: 5000,
}
}