parent
f4b94c8267
commit
61356f1116
|
@ -124,3 +124,30 @@ pub trait Node {
|
||||||
fn state(&self) -> &Self::State;
|
fn state(&self) -> &Self::State;
|
||||||
fn step(&mut self);
|
fn step(&mut self);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
impl Node for usize {
|
||||||
|
type Settings = ();
|
||||||
|
type State = Self;
|
||||||
|
|
||||||
|
fn new<R: rand::Rng>(_rng: &mut R, id: NodeId, _settings: Self::Settings) -> Self {
|
||||||
|
id.inner()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn id(&self) -> NodeId {
|
||||||
|
(*self).into()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn current_view(&self) -> usize {
|
||||||
|
*self
|
||||||
|
}
|
||||||
|
|
||||||
|
fn state(&self) -> &Self::State {
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
|
fn step(&mut self) {
|
||||||
|
use std::ops::AddAssign;
|
||||||
|
self.add_assign(1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,50 @@
|
||||||
|
use crate::node::Node;
|
||||||
|
use crate::warding::{SimulationState, SimulationWard};
|
||||||
|
use serde::Deserialize;
|
||||||
|
|
||||||
|
/// MinMaxView. It monitors the gap between a min view and max view, triggers when surpassing
|
||||||
|
/// the max view - min view is larger than a gap.
|
||||||
|
#[derive(Debug, Deserialize, Copy, Clone)]
|
||||||
|
pub struct MinMaxViewWard {
|
||||||
|
max_gap: usize,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<N: Node> SimulationWard<N> for MinMaxViewWard {
|
||||||
|
type SimulationState = SimulationState<N>;
|
||||||
|
fn analyze(&mut self, state: &Self::SimulationState) -> bool {
|
||||||
|
let mut min = usize::MAX;
|
||||||
|
let mut max = 0;
|
||||||
|
let nodes = state
|
||||||
|
.nodes
|
||||||
|
.read()
|
||||||
|
.expect("simulations: MinMaxViewWard panic when requiring a read lock");
|
||||||
|
for node in nodes.iter() {
|
||||||
|
let view = node.current_view();
|
||||||
|
min = min.min(view);
|
||||||
|
max = max.max(view);
|
||||||
|
}
|
||||||
|
max - min >= self.max_gap
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod test {
|
||||||
|
use crate::warding::minmax::MinMaxViewWard;
|
||||||
|
use crate::warding::{SimulationState, SimulationWard};
|
||||||
|
use std::sync::{Arc, RwLock};
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn rebase_threshold() {
|
||||||
|
let mut minmax = MinMaxViewWard { max_gap: 5 };
|
||||||
|
let state = SimulationState {
|
||||||
|
nodes: Arc::new(RwLock::new(vec![10])),
|
||||||
|
};
|
||||||
|
// we only have one node, so always false
|
||||||
|
assert!(!minmax.analyze(&state));
|
||||||
|
|
||||||
|
// push a new node with 10
|
||||||
|
state.nodes.write().unwrap().push(20);
|
||||||
|
// we now have two nodes and the max - min is 10 > max_gap 5, so true
|
||||||
|
assert!(minmax.analyze(&state));
|
||||||
|
}
|
||||||
|
}
|
|
@ -5,6 +5,7 @@ use serde::Deserialize;
|
||||||
// internal
|
// internal
|
||||||
use crate::node::Node;
|
use crate::node::Node;
|
||||||
|
|
||||||
|
mod minmax;
|
||||||
mod ttf;
|
mod ttf;
|
||||||
|
|
||||||
pub struct SimulationState<N> {
|
pub struct SimulationState<N> {
|
||||||
|
@ -21,9 +22,10 @@ pub trait SimulationWard<N> {
|
||||||
/// Ward dispatcher
|
/// Ward dispatcher
|
||||||
/// Enum to avoid Boxing (Box<dyn SimulationWard>) wards.
|
/// Enum to avoid Boxing (Box<dyn SimulationWard>) wards.
|
||||||
#[derive(Debug, Deserialize)]
|
#[derive(Debug, Deserialize)]
|
||||||
|
#[serde(rename_all = "snake_case")]
|
||||||
pub enum Ward {
|
pub enum Ward {
|
||||||
#[serde(rename = "time_to_finality")]
|
|
||||||
MaxView(ttf::MaxViewWard),
|
MaxView(ttf::MaxViewWard),
|
||||||
|
MinMaxView(minmax::MinMaxViewWard),
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Ward {
|
impl Ward {
|
||||||
|
@ -32,6 +34,7 @@ impl Ward {
|
||||||
) -> &mut dyn SimulationWard<N, SimulationState = SimulationState<N>> {
|
) -> &mut dyn SimulationWard<N, SimulationState = SimulationState<N>> {
|
||||||
match self {
|
match self {
|
||||||
Ward::MaxView(ward) => ward,
|
Ward::MaxView(ward) => ward,
|
||||||
|
Ward::MinMaxView(ward) => ward,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -23,39 +23,12 @@ impl<N: Node> SimulationWard<N> for MaxViewWard {
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod test {
|
mod test {
|
||||||
use crate::node::{Node, NodeId};
|
|
||||||
use crate::warding::ttf::MaxViewWard;
|
use crate::warding::ttf::MaxViewWard;
|
||||||
use crate::warding::{SimulationState, SimulationWard};
|
use crate::warding::{SimulationState, SimulationWard};
|
||||||
use rand::Rng;
|
|
||||||
use std::ops::AddAssign;
|
|
||||||
use std::sync::{Arc, RwLock};
|
use std::sync::{Arc, RwLock};
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn rebase_threshold() {
|
fn rebase_threshold() {
|
||||||
impl Node for usize {
|
|
||||||
type Settings = ();
|
|
||||||
type State = Self;
|
|
||||||
|
|
||||||
fn new<R: Rng>(_rng: &mut R, id: NodeId, _settings: Self::Settings) -> Self {
|
|
||||||
id.inner()
|
|
||||||
}
|
|
||||||
|
|
||||||
fn id(&self) -> NodeId {
|
|
||||||
(*self).into()
|
|
||||||
}
|
|
||||||
|
|
||||||
fn current_view(&self) -> usize {
|
|
||||||
*self
|
|
||||||
}
|
|
||||||
|
|
||||||
fn state(&self) -> &Self::State {
|
|
||||||
self
|
|
||||||
}
|
|
||||||
|
|
||||||
fn step(&mut self) {
|
|
||||||
self.add_assign(1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
let mut ttf = MaxViewWard { max_view: 10 };
|
let mut ttf = MaxViewWard { max_view: 10 };
|
||||||
|
|
||||||
let node = 11;
|
let node = 11;
|
||||||
|
|
Loading…
Reference in New Issue