solana_vote_interface/state/
vote_instruction_data.rs

1#[cfg(feature = "serde")]
2use serde_derive::{Deserialize, Serialize};
3#[cfg(feature = "frozen-abi")]
4use solana_frozen_abi_macro::{frozen_abi, AbiExample};
5use {
6    crate::state::{Lockout, MAX_LOCKOUT_HISTORY},
7    solana_clock::{Slot, UnixTimestamp},
8    solana_hash::Hash,
9    solana_pubkey::Pubkey,
10    std::{collections::VecDeque, fmt::Debug},
11};
12
13#[cfg_attr(
14    feature = "frozen-abi",
15    frozen_abi(digest = "GvUzgtcxhKVVxPAjSntXGPqjLZK5ovgZzCiUP1tDpB9q"),
16    derive(AbiExample)
17)]
18#[cfg_attr(feature = "serde", derive(Deserialize, Serialize))]
19#[derive(Default, Debug, PartialEq, Eq, Clone)]
20pub struct Vote {
21    /// A stack of votes starting with the oldest vote
22    pub slots: Vec<Slot>,
23    /// signature of the bank's state at the last slot
24    pub hash: Hash,
25    /// processing timestamp of last slot
26    pub timestamp: Option<UnixTimestamp>,
27}
28
29impl Vote {
30    pub fn new(slots: Vec<Slot>, hash: Hash) -> Self {
31        Self {
32            slots,
33            hash,
34            timestamp: None,
35        }
36    }
37
38    pub fn last_voted_slot(&self) -> Option<Slot> {
39        self.slots.last().copied()
40    }
41}
42
43#[cfg_attr(
44    feature = "frozen-abi",
45    frozen_abi(digest = "CxyuwbaEdzP7jDCZyxjgQvLGXadBUZF3LoUvbSpQ6tYN"),
46    derive(AbiExample)
47)]
48#[cfg_attr(feature = "serde", derive(Deserialize, Serialize))]
49#[derive(Default, Debug, PartialEq, Eq, Clone)]
50pub struct VoteStateUpdate {
51    /// The proposed tower
52    pub lockouts: VecDeque<Lockout>,
53    /// The proposed root
54    pub root: Option<Slot>,
55    /// signature of the bank's state at the last slot
56    pub hash: Hash,
57    /// processing timestamp of last slot
58    pub timestamp: Option<UnixTimestamp>,
59}
60
61impl From<Vec<(Slot, u32)>> for VoteStateUpdate {
62    fn from(recent_slots: Vec<(Slot, u32)>) -> Self {
63        let lockouts: VecDeque<Lockout> = recent_slots
64            .into_iter()
65            .map(|(slot, confirmation_count)| {
66                Lockout::new_with_confirmation_count(slot, confirmation_count)
67            })
68            .collect();
69        Self {
70            lockouts,
71            root: None,
72            hash: Hash::default(),
73            timestamp: None,
74        }
75    }
76}
77
78impl VoteStateUpdate {
79    pub fn new(lockouts: VecDeque<Lockout>, root: Option<Slot>, hash: Hash) -> Self {
80        Self {
81            lockouts,
82            root,
83            hash,
84            timestamp: None,
85        }
86    }
87
88    pub fn slots(&self) -> Vec<Slot> {
89        self.lockouts.iter().map(|lockout| lockout.slot()).collect()
90    }
91
92    pub fn last_voted_slot(&self) -> Option<Slot> {
93        self.lockouts.back().map(|l| l.slot())
94    }
95}
96
97#[cfg_attr(
98    feature = "frozen-abi",
99    frozen_abi(digest = "6UDiQMH4wbNwkMHosPMtekMYu2Qa6CHPZ2ymK4mc6FGu"),
100    derive(AbiExample)
101)]
102#[cfg_attr(feature = "serde", derive(Deserialize, Serialize))]
103#[derive(Default, Debug, PartialEq, Eq, Clone)]
104pub struct TowerSync {
105    /// The proposed tower
106    pub lockouts: VecDeque<Lockout>,
107    /// The proposed root
108    pub root: Option<Slot>,
109    /// signature of the bank's state at the last slot
110    pub hash: Hash,
111    /// processing timestamp of last slot
112    pub timestamp: Option<UnixTimestamp>,
113    /// the unique identifier for the chain up to and
114    /// including this block. Does not require replaying
115    /// in order to compute.
116    pub block_id: Hash,
117}
118
119impl From<Vec<(Slot, u32)>> for TowerSync {
120    fn from(recent_slots: Vec<(Slot, u32)>) -> Self {
121        let lockouts: VecDeque<Lockout> = recent_slots
122            .into_iter()
123            .map(|(slot, confirmation_count)| {
124                Lockout::new_with_confirmation_count(slot, confirmation_count)
125            })
126            .collect();
127        Self {
128            lockouts,
129            root: None,
130            hash: Hash::default(),
131            timestamp: None,
132            block_id: Hash::default(),
133        }
134    }
135}
136
137impl TowerSync {
138    pub fn new(
139        lockouts: VecDeque<Lockout>,
140        root: Option<Slot>,
141        hash: Hash,
142        block_id: Hash,
143    ) -> Self {
144        Self {
145            lockouts,
146            root,
147            hash,
148            timestamp: None,
149            block_id,
150        }
151    }
152
153    /// Creates a tower with consecutive votes for `slot - MAX_LOCKOUT_HISTORY + 1` to `slot` inclusive.
154    /// If `slot >= MAX_LOCKOUT_HISTORY`, sets the root to `(slot - MAX_LOCKOUT_HISTORY)`
155    /// Sets the hash to `hash` and leaves `block_id` unset.
156    pub fn new_from_slot(slot: Slot, hash: Hash) -> Self {
157        let lowest_slot = slot
158            .saturating_add(1)
159            .saturating_sub(MAX_LOCKOUT_HISTORY as u64);
160        let slots: Vec<_> = (lowest_slot..slot.saturating_add(1)).collect();
161        Self::new_from_slots(
162            slots,
163            hash,
164            (lowest_slot > 0).then(|| lowest_slot.saturating_sub(1)),
165        )
166    }
167
168    /// Creates a tower with consecutive confirmation for `slots`
169    pub fn new_from_slots(slots: Vec<Slot>, hash: Hash, root: Option<Slot>) -> Self {
170        let lockouts: VecDeque<Lockout> = slots
171            .into_iter()
172            .rev()
173            .enumerate()
174            .map(|(cc, s)| Lockout::new_with_confirmation_count(s, cc.saturating_add(1) as u32))
175            .rev()
176            .collect();
177        Self {
178            lockouts,
179            hash,
180            root,
181            timestamp: None,
182            block_id: Hash::default(),
183        }
184    }
185
186    pub fn slots(&self) -> Vec<Slot> {
187        self.lockouts.iter().map(|lockout| lockout.slot()).collect()
188    }
189
190    pub fn last_voted_slot(&self) -> Option<Slot> {
191        self.lockouts.back().map(|l| l.slot())
192    }
193}
194
195#[cfg_attr(feature = "serde", derive(Deserialize, Serialize))]
196#[derive(Default, Debug, PartialEq, Eq, Clone, Copy)]
197pub struct VoteInit {
198    pub node_pubkey: Pubkey,
199    pub authorized_voter: Pubkey,
200    pub authorized_withdrawer: Pubkey,
201    pub commission: u8,
202}
203
204#[cfg_attr(feature = "serde", derive(Deserialize, Serialize))]
205#[derive(Debug, PartialEq, Eq, Clone, Copy)]
206pub enum VoteAuthorize {
207    Voter,
208    Withdrawer,
209}
210
211#[cfg_attr(feature = "serde", derive(Deserialize, Serialize))]
212#[derive(Debug, PartialEq, Eq, Clone)]
213pub struct VoteAuthorizeWithSeedArgs {
214    pub authorization_type: VoteAuthorize,
215    pub current_authority_derived_key_owner: Pubkey,
216    pub current_authority_derived_key_seed: String,
217    pub new_authority: Pubkey,
218}
219
220#[cfg_attr(feature = "serde", derive(Deserialize, Serialize))]
221#[derive(Debug, PartialEq, Eq, Clone)]
222pub struct VoteAuthorizeCheckedWithSeedArgs {
223    pub authorization_type: VoteAuthorize,
224    pub current_authority_derived_key_owner: Pubkey,
225    pub current_authority_derived_key_seed: String,
226}