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}