ibc_client_tendermint_types/
trust_threshold.rs

1//! IBC Domain type definition for [`TrustThreshold`]
2//! represented as a fraction with valid values in the
3//! range `[0, 1)`.
4
5use core::fmt::{Display, Error as FmtError, Formatter};
6
7use ibc_core_client_types::error::ClientError;
8use ibc_core_host_types::error::DecodingError;
9use ibc_proto::ibc::lightclients::tendermint::v1::Fraction;
10use ibc_proto::Protobuf;
11use tendermint::trust_threshold::TrustThresholdFraction;
12
13/// [`TrustThreshold`] defines the level of trust that a client has
14/// towards a set of validators of a chain.
15///
16/// A trust threshold is represented as a fraction, i.e., a numerator
17/// and a denominator.
18/// A typical trust threshold is 1/3 in practice.
19/// This type accepts even a value of 0, (numerator = 0, denominator = 0),
20/// which is used in the client state of an upgrading client.
21#[cfg_attr(
22    feature = "parity-scale-codec",
23    derive(
24        parity_scale_codec::Encode,
25        parity_scale_codec::Decode,
26        scale_info::TypeInfo
27    )
28)]
29#[cfg_attr(
30    feature = "borsh",
31    derive(borsh::BorshSerialize, borsh::BorshDeserialize)
32)]
33#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
34#[derive(Copy, Clone, Debug, PartialEq, Eq)]
35pub struct TrustThreshold {
36    numerator: u64,
37    denominator: u64,
38}
39
40impl TrustThreshold {
41    /// Constant for a trust threshold of 1/3.
42    pub const ONE_THIRD: Self = Self {
43        numerator: 1,
44        denominator: 3,
45    };
46
47    /// Constant for a trust threshold of 2/3.
48    pub const TWO_THIRDS: Self = Self {
49        numerator: 2,
50        denominator: 3,
51    };
52
53    /// Constant for a trust threshold of 0/0.
54    pub const ZERO: Self = Self {
55        numerator: 0,
56        denominator: 0,
57    };
58
59    /// Instantiate a TrustThreshold with the given denominator and
60    /// numerator.
61    ///
62    /// The constructor succeeds if long as the resulting fraction
63    /// is in the range`[0, 1)`.
64    pub fn new(numerator: u64, denominator: u64) -> Result<Self, ClientError> {
65        // The two parameters cannot yield a fraction that is bigger or equal to 1
66        if (numerator > denominator)
67            || (denominator == 0 && numerator != 0)
68            || (numerator == denominator && numerator != 0)
69        {
70            return Err(ClientError::InvalidTrustThreshold {
71                numerator,
72                denominator,
73            });
74        }
75
76        Ok(Self {
77            numerator,
78            denominator,
79        })
80    }
81
82    /// The numerator of the fraction underlying this trust threshold.
83    pub fn numerator(&self) -> u64 {
84        self.numerator
85    }
86
87    /// The denominator of the fraction underlying this trust threshold.
88    pub fn denominator(&self) -> u64 {
89        self.denominator
90    }
91}
92
93/// Conversion from Tendermint domain type into
94/// IBC domain type.
95impl From<TrustThresholdFraction> for TrustThreshold {
96    fn from(t: TrustThresholdFraction) -> Self {
97        Self {
98            numerator: t.numerator(),
99            denominator: t.denominator(),
100        }
101    }
102}
103
104/// Conversion from IBC domain type into
105/// Tendermint domain type.
106impl TryFrom<TrustThreshold> for TrustThresholdFraction {
107    type Error = DecodingError;
108
109    fn try_from(t: TrustThreshold) -> Result<TrustThresholdFraction, Self::Error> {
110        Self::new(t.numerator, t.denominator)
111            .map_err(|_| DecodingError::invalid_raw_data("trust threshold"))
112    }
113}
114
115impl Protobuf<Fraction> for TrustThreshold {}
116
117impl From<TrustThreshold> for Fraction {
118    fn from(t: TrustThreshold) -> Self {
119        Self {
120            numerator: t.numerator,
121            denominator: t.denominator,
122        }
123    }
124}
125
126impl TryFrom<Fraction> for TrustThreshold {
127    type Error = DecodingError;
128
129    fn try_from(value: Fraction) -> Result<Self, Self::Error> {
130        Self::new(value.numerator, value.denominator)
131            .map_err(|_| DecodingError::invalid_raw_data("trust threshold"))
132    }
133}
134
135impl Display for TrustThreshold {
136    fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), FmtError> {
137        write!(f, "{}/{}", self.numerator, self.denominator)
138    }
139}