Skip to main content

rings_core/
measure.rs

1//! This module provide the `Measure` struct and its implementations.
2//! It is used to assess the reliability of remote peers.
3#![warn(missing_docs)]
4use async_trait::async_trait;
5
6use crate::dht::Did;
7
8/// Type of Measure, see [Measure].
9#[cfg(not(feature = "wasm"))]
10pub type MeasureImpl = Box<dyn BehaviourJudgement + Send + Sync>;
11
12/// Type of Measure, see [crate::measure::Measure].
13#[cfg(feature = "wasm")]
14pub type MeasureImpl = Box<dyn BehaviourJudgement>;
15
16/// The tag of counters in measure.
17#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
18pub enum MeasureCounter {
19    /// The number of sent messages.
20    Sent,
21    /// The number of failed to sent messages.
22    FailedToSend,
23    /// The number of received messages.
24    Received,
25    /// The number of failed to receive messages.
26    FailedToReceive,
27    /// The number of connected.
28    Connect,
29    /// The number of disconnect.
30    Disconnected,
31}
32
33/// `Measure` is used to assess the reliability of peers by counting their behaviour.
34/// It currently count the number of sent and received messages in a given period (1 hour).
35/// The method [Measure::incr] should be called in the proper places.
36#[cfg_attr(feature = "wasm", async_trait(?Send))]
37#[cfg_attr(not(feature = "wasm"), async_trait)]
38pub trait Measure {
39    /// `incr` increments the counter of the given peer.
40    async fn incr(&self, did: Did, counter: MeasureCounter);
41    /// `get_count` returns the counter of the given peer.
42    async fn get_count(&self, did: Did, counter: MeasureCounter) -> u64;
43}
44
45/// `BehaviourJudgement` trait defines a method `good` for assessing whether a node behaves well.
46/// Any structure implementing this trait should provide a way to measure the "goodness" of a node.
47#[cfg_attr(feature = "wasm", async_trait(?Send))]
48#[cfg_attr(not(feature = "wasm"), async_trait)]
49pub trait BehaviourJudgement: Measure {
50    /// This asynchronous method should return a boolean indicating whether the node identified by `did` is behaving well.
51    async fn good(&self, did: Did) -> bool;
52}
53
54/// `ConnectBehaviour` trait offers a default implementation for the `good` method, providing a judgement
55/// based on a node's behavior in establishing connections.
56/// The "goodness" of a node is measured by comparing the connection and disconnection counts against a given threshold.
57#[cfg_attr(feature = "wasm", async_trait(?Send))]
58#[cfg_attr(not(feature = "wasm"), async_trait)]
59pub trait ConnectBehaviour<const THRESHOLD: i64>: Measure {
60    /// This asynchronous method returns a boolean indicating whether the node identified by `did` has a satisfactory connection behavior.
61    async fn good(&self, did: Did) -> bool {
62        let conn = self.get_count(did, MeasureCounter::Connect).await as i64;
63        let disconn = self.get_count(did, MeasureCounter::Disconnected).await as i64;
64        tracing::debug!(
65            "[ConnectBehaviour] in Threadhold: {:}, connect: {:}, disconn: {:}, delta: {:}",
66            THRESHOLD,
67            conn,
68            disconn,
69            conn - disconn
70        );
71        (conn - disconn) < THRESHOLD
72    }
73}
74
75/// `MessageSendBehaviour` trait provides a default implementation for the `good` method, judging a node's
76/// behavior based on its message sending capabilities.
77/// The "goodness" of a node is measured by comparing the sent and failed-to-send counts against a given threshold.
78#[cfg_attr(feature = "wasm", async_trait(?Send))]
79#[cfg_attr(not(feature = "wasm"), async_trait)]
80pub trait MessageSendBehaviour<const THRESHOLD: i64>: Measure {
81    /// This asynchronous method returns a boolean indicating whether the node identified by `did` has a satisfactory message sending behavior.
82    async fn good(&self, did: Did) -> bool {
83        let failed = self.get_count(did, MeasureCounter::FailedToSend).await;
84        (failed as i64) < THRESHOLD
85    }
86}
87
88/// `MessageRecvBehaviour` trait provides a default implementation for the `good` method, assessing a node's
89/// behavior based on its message receiving capabilities.
90/// The "goodness" of a node is measured by comparing the received and failed-to-receive counts against a given threshold.
91#[cfg_attr(feature = "wasm", async_trait(?Send))]
92#[cfg_attr(not(feature = "wasm"), async_trait)]
93pub trait MessageRecvBehaviour<const THRESHOLD: i64>: Measure {
94    /// This asynchronous method returns a boolean indicating whether the node identified by `did` has a satisfactory message receiving behavior.
95    async fn good(&self, did: Did) -> bool {
96        let failed = self.get_count(did, MeasureCounter::FailedToReceive).await;
97        (failed as i64) < THRESHOLD
98    }
99}