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