solana_program/vote/
error.rs

1//! Vote program errors
2
3use {
4    num_derive::{FromPrimitive, ToPrimitive},
5    solana_decode_error::DecodeError,
6    thiserror::Error,
7};
8
9/// Reasons the vote might have had an error
10#[derive(Error, Debug, Clone, PartialEq, Eq, FromPrimitive, ToPrimitive)]
11pub enum VoteError {
12    #[error("vote already recorded or not in slot hashes history")]
13    VoteTooOld,
14
15    #[error("vote slots do not match bank history")]
16    SlotsMismatch,
17
18    #[error("vote hash does not match bank hash")]
19    SlotHashMismatch,
20
21    #[error("vote has no slots, invalid")]
22    EmptySlots,
23
24    #[error("vote timestamp not recent")]
25    TimestampTooOld,
26
27    #[error("authorized voter has already been changed this epoch")]
28    TooSoonToReauthorize,
29
30    // TODO: figure out how to migrate these new errors
31    #[error("Old state had vote which should not have been popped off by vote in new state")]
32    LockoutConflict,
33
34    #[error("Proposed state had earlier slot which should have been popped off by later vote")]
35    NewVoteStateLockoutMismatch,
36
37    #[error("Vote slots are not ordered")]
38    SlotsNotOrdered,
39
40    #[error("Confirmations are not ordered")]
41    ConfirmationsNotOrdered,
42
43    #[error("Zero confirmations")]
44    ZeroConfirmations,
45
46    #[error("Confirmation exceeds limit")]
47    ConfirmationTooLarge,
48
49    #[error("Root rolled back")]
50    RootRollBack,
51
52    #[error("Confirmations for same vote were smaller in new proposed state")]
53    ConfirmationRollBack,
54
55    #[error("New state contained a vote slot smaller than the root")]
56    SlotSmallerThanRoot,
57
58    #[error("New state contained too many votes")]
59    TooManyVotes,
60
61    #[error("every slot in the vote was older than the SlotHashes history")]
62    VotesTooOldAllFiltered,
63
64    #[error("Proposed root is not in slot hashes")]
65    RootOnDifferentFork,
66
67    #[error("Cannot close vote account unless it stopped voting at least one full epoch ago")]
68    ActiveVoteAccountClose,
69
70    #[error("Cannot update commission at this point in the epoch")]
71    CommissionUpdateTooLate,
72
73    #[error("Assertion failed")]
74    AssertionFailed,
75}
76
77impl<E> DecodeError<E> for VoteError {
78    fn type_of() -> &'static str {
79        "VoteError"
80    }
81}
82
83#[cfg(test)]
84mod tests {
85    use {super::*, crate::instruction::InstructionError};
86
87    #[test]
88    fn test_custom_error_decode() {
89        use num_traits::FromPrimitive;
90        fn pretty_err<T>(err: InstructionError) -> String
91        where
92            T: 'static + std::error::Error + DecodeError<T> + FromPrimitive,
93        {
94            if let InstructionError::Custom(code) = err {
95                let specific_error: T = T::decode_custom_error_to_enum(code).unwrap();
96                format!(
97                    "{:?}: {}::{:?} - {}",
98                    err,
99                    T::type_of(),
100                    specific_error,
101                    specific_error,
102                )
103            } else {
104                "".to_string()
105            }
106        }
107        assert_eq!(
108            "Custom(0): VoteError::VoteTooOld - vote already recorded or not in slot hashes history",
109            pretty_err::<VoteError>(VoteError::VoteTooOld.into())
110        )
111    }
112}