Skip to main content

liminal_protocol/algebra/
types.rs

1use core::fmt;
2
3/// One entry/byte resource vector before arithmetic widening.
4#[derive(Clone, Copy, Debug, Default, PartialEq, Eq)]
5pub struct ResourceVector {
6    /// Entry component.
7    pub entries: u64,
8    /// Encoded-byte component.
9    pub bytes: u64,
10}
11
12impl ResourceVector {
13    /// Creates an entry/byte resource vector.
14    #[must_use]
15    pub const fn new(entries: u64, bytes: u64) -> Self {
16        Self { entries, bytes }
17    }
18
19    /// Widens both components before any arithmetic is performed.
20    #[must_use]
21    pub const fn widen(self) -> WideResourceVector {
22        WideResourceVector::new(widen_u64(self.entries), widen_u64(self.bytes))
23    }
24}
25
26/// `From<u64>` is not const at the workspace MSRV. This lossless cast keeps
27/// every public formula const while centralizing that compiler limitation.
28#[allow(clippy::cast_lossless)]
29pub(super) const fn widen_u64(value: u64) -> u128 {
30    value as u128
31}
32
33/// One entry/byte resource vector after widening to the protocol arithmetic domain.
34#[derive(Clone, Copy, Debug, Default, PartialEq, Eq)]
35pub struct WideResourceVector {
36    /// Entry component.
37    pub entries: u128,
38    /// Encoded-byte component.
39    pub bytes: u128,
40}
41
42impl WideResourceVector {
43    /// Creates a widened entry/byte vector.
44    #[must_use]
45    pub const fn new(entries: u128, bytes: u128) -> Self {
46        Self { entries, bytes }
47    }
48
49    /// Returns whether both components are zero.
50    #[must_use]
51    pub const fn is_zero(self) -> bool {
52        self.entries == 0 && self.bytes == 0
53    }
54}
55
56/// Resource dimension, in the contract's entry-before-byte precedence.
57#[derive(Clone, Copy, Debug, PartialEq, Eq)]
58pub enum ResourceDimension {
59    /// Retained entry count.
60    Entries,
61    /// Retained encoded bytes.
62    Bytes,
63}
64
65/// Invalid inputs to the retained-baseline formula.
66#[derive(Clone, Copy, Debug, PartialEq, Eq)]
67pub enum BaselineError {
68    /// More marker credits were supplied than configured identity slots.
69    MarkerCreditsExceedIdentitySlots {
70        /// Configured identity slots.
71        identity_slots: u64,
72        /// Slots currently owning marker credits.
73        marker_credits: u64,
74    },
75}
76
77impl fmt::Display for BaselineError {
78    fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
79        match self {
80            Self::MarkerCreditsExceedIdentitySlots {
81                identity_slots,
82                marker_credits,
83            } => write!(
84                formatter,
85                "marker credits ({marker_credits}) exceed identity slots ({identity_slots})"
86            ),
87        }
88    }
89}
90
91/// Results of the mandatory-class debt and absolute-fit formulas.
92#[derive(Clone, Copy, Debug, PartialEq, Eq)]
93pub struct MandatoryCapacity {
94    /// Exact componentwise post-transaction debt.
95    pub debt: WideResourceVector,
96    /// Whether `B' + K_remaining' <= cap` holds componentwise.
97    pub absolute_fit: bool,
98    /// Whether `d' <= Q` holds componentwise.
99    pub debt_within_mandatory_bound: bool,
100}
101
102impl MandatoryCapacity {
103    /// Returns whether both mandatory-class checks pass.
104    #[must_use]
105    pub const fn is_legal(self) -> bool {
106        self.absolute_fit && self.debt_within_mandatory_bound
107    }
108}
109
110/// Exact post-transfer values for a recovery transaction of charge `r`.
111#[derive(Clone, Copy, Debug, PartialEq, Eq)]
112pub struct RecoveryTransfer {
113    /// `B' = B_removed + r`.
114    pub baseline: WideResourceVector,
115    /// `K_remaining' = K_remaining - r`.
116    pub remaining_recovery_claim: ResourceVector,
117}
118
119/// Invalid or unrepresentable recovery-charge transfer.
120#[derive(Clone, Copy, Debug, PartialEq, Eq)]
121pub struct RecoveryTransferError {
122    /// First component in which the transferred charge exceeded the claim or
123    /// the widened post-transfer baseline overflowed.
124    pub dimension: ResourceDimension,
125}
126
127impl fmt::Display for RecoveryTransferError {
128    fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
129        write!(
130            formatter,
131            "recovery charge exceeds remaining {:?} claim",
132            self.dimension
133        )
134    }
135}
136
137/// Reproducible outputs of the participant physical-floor rule.
138#[derive(Clone, Copy, Debug, PartialEq, Eq)]
139pub struct FloorComputation {
140    /// Minimum member cursor after membership changes, or `H'` when empty.
141    pub member_cursor: u64,
142    /// `min(m, observer_progress) + 1` in the widened boundary domain.
143    pub preferred_floor: u128,
144    /// `max(F, preferred_floor, cap_floor)`.
145    pub resulting_floor: u128,
146}