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