Skip to main content

solana_vote_interface/state/
vote_instruction_data.rs

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