solana_commitment_config/
lib.rs

1//! Definitions of commitment levels.
2
3use core::{fmt, str::FromStr};
4
5#[cfg_attr(
6    feature = "serde",
7    derive(serde_derive::Serialize, serde_derive::Deserialize),
8    serde(rename_all = "camelCase")
9)]
10#[derive(Default, Clone, Copy, Debug, PartialEq, Eq, Hash)]
11pub struct CommitmentConfig {
12    pub commitment: CommitmentLevel,
13}
14
15impl CommitmentConfig {
16    pub const fn finalized() -> Self {
17        Self {
18            commitment: CommitmentLevel::Finalized,
19        }
20    }
21
22    pub const fn confirmed() -> Self {
23        Self {
24            commitment: CommitmentLevel::Confirmed,
25        }
26    }
27
28    pub const fn processed() -> Self {
29        Self {
30            commitment: CommitmentLevel::Processed,
31        }
32    }
33
34    pub fn ok(self) -> Option<Self> {
35        if self == Self::default() {
36            None
37        } else {
38            Some(self)
39        }
40    }
41
42    pub fn is_finalized(&self) -> bool {
43        self.commitment == CommitmentLevel::Finalized
44    }
45
46    pub fn is_confirmed(&self) -> bool {
47        self.commitment == CommitmentLevel::Confirmed
48    }
49
50    pub fn is_processed(&self) -> bool {
51        self.commitment == CommitmentLevel::Processed
52    }
53
54    pub fn is_at_least_confirmed(&self) -> bool {
55        self.is_confirmed() || self.is_finalized()
56    }
57}
58
59impl FromStr for CommitmentConfig {
60    type Err = ParseCommitmentLevelError;
61
62    fn from_str(s: &str) -> Result<Self, Self::Err> {
63        CommitmentLevel::from_str(s).map(|commitment| Self { commitment })
64    }
65}
66
67#[cfg_attr(
68    feature = "serde",
69    derive(serde_derive::Serialize, serde_derive::Deserialize),
70    serde(rename_all = "camelCase")
71)]
72#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
73/// An attribute of a slot. It describes how finalized a block is at some point in time. For example, a slot
74/// is said to be at the max level immediately after the cluster recognizes the block at that slot as
75/// finalized. When querying the ledger state, use lower levels of commitment to report progress and higher
76/// levels to ensure state changes will not be rolled back.
77pub enum CommitmentLevel {
78    /// The highest slot of the heaviest fork processed by the node. Ledger state at this slot is
79    /// not derived from a confirmed or finalized block, but if multiple forks are present, is from
80    /// the fork the validator believes is most likely to finalize.
81    Processed,
82
83    /// The highest slot that has been voted on by supermajority of the cluster, ie. is confirmed.
84    /// Confirmation incorporates votes from gossip and replay. It does not count votes on
85    /// descendants of a block, only direct votes on that block, and upholds "optimistic
86    /// confirmation" guarantees in release 1.3 and onwards.
87    Confirmed,
88
89    /// The highest slot having reached max vote lockout, as recognized by a supermajority of the
90    /// cluster.
91    Finalized,
92}
93
94impl Default for CommitmentLevel {
95    fn default() -> Self {
96        Self::Finalized
97    }
98}
99
100impl FromStr for CommitmentLevel {
101    type Err = ParseCommitmentLevelError;
102
103    fn from_str(s: &str) -> Result<Self, Self::Err> {
104        match s {
105            "processed" => Ok(CommitmentLevel::Processed),
106            "confirmed" => Ok(CommitmentLevel::Confirmed),
107            "finalized" => Ok(CommitmentLevel::Finalized),
108            _ => Err(ParseCommitmentLevelError::Invalid),
109        }
110    }
111}
112
113impl std::fmt::Display for CommitmentLevel {
114    fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
115        let s = match self {
116            CommitmentLevel::Processed => "processed",
117            CommitmentLevel::Confirmed => "confirmed",
118            CommitmentLevel::Finalized => "finalized",
119        };
120        write!(f, "{s}")
121    }
122}
123
124#[derive(Debug)]
125pub enum ParseCommitmentLevelError {
126    Invalid,
127}
128
129impl core::error::Error for ParseCommitmentLevelError {}
130
131impl fmt::Display for ParseCommitmentLevelError {
132    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
133        match self {
134            Self::Invalid => f.write_str("invalid variant"),
135        }
136    }
137}